diff --git a/.vpython3 b/.vpython3
index de296bc57..e914cf5 100644
--- a/.vpython3
+++ b/.vpython3
@@ -124,4 +124,7 @@
   name: "infra/python/wheels/distro-py2_py3"
   version: "version:1.4.0"
 >
-
+wheel: <
+  name: "infra/python/wheels/pillow/linux-amd64_cp38_cp38"
+  version: "version:8.1.2"
+>
diff --git a/BUILD.gn b/BUILD.gn
index bc3c3e6a..434c215d 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1039,6 +1039,7 @@
         "//chrome:chrome",
         "//chrome/test/chromedriver",
         "//third_party/blink/tools:wpt_tests_isolate",
+        "//tools/imagediff",
       ]
     }
   }
diff --git a/DEPS b/DEPS
index 04e04ca..e1c1016 100644
--- a/DEPS
+++ b/DEPS
@@ -204,11 +204,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '4e94fd11cded4e0b48346eb411b5e953785c3f88',
+  'skia_revision': '2558c468cc71b3cc8b671c6e55aad1d9ae8a8bba',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '07c60e0c75db7c20980bbc2aa51f3468985a60da',
+  'v8_revision': '4f0f4e2a3c5ad9dc7312774da5197e0179c30863',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -216,7 +216,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'b3394db36779b618b824d91f52cfd3dc3136c21f',
+  'angle_revision': '3eace05cb270ea7f44ec1ce9dd002ebb8d4a587f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -283,7 +283,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': '1d23a0a88290fd799c37ced093de9e735009fa9f',
+  'devtools_frontend_revision': 'aa1d0c8587914c402d993da0bbda16e84d513fdf',
   # 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.
@@ -696,7 +696,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'ZvXzCmnbaONNhr6d8cbYTREJiadk9QBhBCm1foVA0nAC',
+          'version': 'xIdmDAvhfStt7ky1enCv_j6NNXqdhajuI8563NJ3QekC',
       },
     ],
     'condition': 'checkout_android',
@@ -909,7 +909,7 @@
   # Tools used when building Chrome for Chrome OS. This affects both the Simple
   # Chrome workflow, as well as the chromeos-chrome ebuild.
   'src/third_party/chromite': {
-      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'd93177cb824290cc917dd4309319995bdd34cf3a',
+      'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '9c61e9c91226d54640c770a90496dc03869d379f',
       'condition': 'checkout_chromeos',
   },
 
@@ -1301,7 +1301,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'a575cd672d138ebcc26f4662cfa0c90a201f3079',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '371d8955a1cbc43fc7b2ec19b30c250d6466291c',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1537,7 +1537,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '66460536ee975a3e98931b7b40a661a63fd9cd57',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'ab6335041130fdc0365a604f49668eac9194f9d6',
+    Var('webrtc_git') + '/src.git' + '@' + '417361423e789b798185d324241f4ac9bfd09066',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1628,7 +1628,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': '9ughCqekZmq8OqJKf4e_YPpRqbU8B2McTqbYID6TN2QC',
+        'version': 'gE5wrFvnrNeqzC53KW7-_NUKMXCrfCv6ijKhNIP8ArIC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -1639,7 +1639,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': '-wDntdsX3lj1JJzGVLv_aRA4r7BlvIVU36NMDZxj5qEC',
+        'version': 'xExuCHB8tqptYTkZGw-QYr6Q_2Y0zcToGTBOLZu1eD0C',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc b/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc
index a110a55..3dca82d 100644
--- a/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc
+++ b/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc
@@ -57,7 +57,6 @@
   InterceptedRequest(
       int frame_tree_node_id,
       uint64_t request_id,
-      int32_t routing_id,
       uint32_t options,
       const network::ResourceRequest& request,
       const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
@@ -132,7 +131,6 @@
 
   const int frame_tree_node_id_;
   const uint64_t request_id_;
-  const int32_t routing_id_;
   const uint32_t options_;
   bool input_stream_previously_failed_ = false;
   bool request_was_redirected_ = false;
@@ -250,7 +248,6 @@
 InterceptedRequest::InterceptedRequest(
     int frame_tree_node_id,
     uint64_t request_id,
-    int32_t routing_id,
     uint32_t options,
     const network::ResourceRequest& request,
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
@@ -262,7 +259,6 @@
         security_options)
     : frame_tree_node_id_(frame_tree_node_id),
       request_id_(request_id),
-      routing_id_(routing_id),
       options_(options),
       intercept_only_(intercept_only),
       security_options_(security_options),
@@ -418,8 +414,8 @@
 
   if (!target_loader_ && target_factory_) {
     target_factory_->CreateLoaderAndStart(
-        target_loader_.BindNewPipeAndPassReceiver(), routing_id_, request_id_,
-        options_, request_, proxied_client_receiver_.BindNewPipeAndPassRemote(),
+        target_loader_.BindNewPipeAndPassReceiver(), request_id_, options_,
+        request_, proxied_client_receiver_.BindNewPipeAndPassRemote(),
         traffic_annotation_);
   }
 }
@@ -751,7 +747,6 @@
 
 void AwProxyingURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> loader,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
@@ -783,9 +778,9 @@
   // manages its own lifecycle
   // TODO(timvolodine): consider keeping track of requests.
   InterceptedRequest* req = new InterceptedRequest(
-      frame_tree_node_id_, request_id, routing_id, options, request,
-      traffic_annotation, std::move(loader), std::move(client),
-      std::move(target_factory_clone), intercept_only_, security_options_);
+      frame_tree_node_id_, request_id, options, request, traffic_annotation,
+      std::move(loader), std::move(client), std::move(target_factory_clone),
+      intercept_only_, security_options_);
   req->Restart();
 }
 
diff --git a/android_webview/browser/network_service/aw_proxying_url_loader_factory.h b/android_webview/browser/network_service/aw_proxying_url_loader_factory.h
index 99a7aba..31c90b2 100644
--- a/android_webview/browser/network_service/aw_proxying_url_loader_factory.h
+++ b/android_webview/browser/network_service/aw_proxying_url_loader_factory.h
@@ -83,7 +83,6 @@
 
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/ash/app_list/views/apps_grid_view_unittest.cc b/ash/app_list/views/apps_grid_view_unittest.cc
index 21ba013..e85ad8e 100644
--- a/ash/app_list/views/apps_grid_view_unittest.cc
+++ b/ash/app_list/views/apps_grid_view_unittest.cc
@@ -1972,56 +1972,60 @@
   EXPECT_TRUE(folder_item->FindChildItem(second_item_id));
 }
 
-// Flaky: crbug.com/1156634
-TEST_P(AppsGridViewTest, DISABLED_MouseDragFlipPage) {
+TEST_P(AppsGridViewTest, MouseDragFlipToNextPage) {
+  // Create 3 full pages of apps.
   model_->PopulateApps(3 * GetTilesPerPage());
   EXPECT_EQ(3, GetPaginationModel()->total_pages());
   EXPECT_EQ(0, GetPaginationModel()->selected_page());
 
-  gfx::Point from = GetItemRectOnCurrentPageAt(0, 0).CenterPoint();
-  gfx::Point to;
+  gfx::Point item_center = GetItemRectOnCurrentPageAt(0, 0).CenterPoint();
   const gfx::Rect apps_grid_bounds = apps_grid_view_->GetLocalBounds();
-  to = gfx::Point(apps_grid_bounds.width() / 2, apps_grid_bounds.bottom() + 1);
+  gfx::Point apps_grid_bottom_center =
+      gfx::Point(apps_grid_bounds.width() / 2, apps_grid_bounds.bottom() + 1);
 
-  // For fullscreen/bubble launcher, drag to the bottom/right of bounds.
+  // Drag an item to the bottom to start flipping pages.
   page_flip_waiter_->Reset();
-  SimulateDrag(AppsGridView::MOUSE, from, to);
-
-  EXPECT_EQ(to, GetDragViewCenter());
-
-  // Page should be flipped after sometime to hit page 1 and 2 then stop.
+  SimulateDrag(AppsGridView::MOUSE, item_center, apps_grid_bottom_center);
   while (test_api_->HasPendingPageFlip()) {
     page_flip_waiter_->Wait();
   }
 
-  // When apps grid gap is enabled, the user can drag an item to an extra page
-  // created at the end.
+  // We flip to an extra page created at the end.
   EXPECT_EQ("1,2,3", page_flip_waiter_->selected_pages());
   EXPECT_EQ(3, GetPaginationModel()->selected_page());
-  EXPECT_EQ(to, GetDragViewCenter());
+  EXPECT_EQ(apps_grid_bottom_center, GetDragViewCenter());
 
-  // Cancel drag and put the dragged view back to its ideal position so that
-  // the next drag would pick it up.
-  EndDrag(apps_grid_view_, true /*cancel*/);
-  test_api_->LayoutToIdealBounds();
+  // End the drag to satisfy checks in AppsGridView destructor.
+  EndDrag(apps_grid_view_, /*cancel=*/true);
+}
 
-  // Now drag to the top edge, and test the other direction.
-  to.set_y(apps_grid_bounds.y());
+TEST_P(AppsGridViewTest, MouseDragFlipToPreviousPage) {
+  // Create 3 full pages of apps.
+  model_->PopulateApps(3 * GetTilesPerPage());
+  EXPECT_EQ(3, GetPaginationModel()->total_pages());
 
+  // Select the last page.
+  GetPaginationModel()->SelectPage(2, /*animate=*/false);
+  EXPECT_EQ(2, GetPaginationModel()->selected_page());
+
+  gfx::Point item_center = GetItemRectOnCurrentPageAt(0, 0).CenterPoint();
+  gfx::Point apps_grid_top_center(apps_grid_view_->GetLocalBounds().width() / 2,
+                                  0);
+
+  // Drag an item to the top to start flipping pages.
   page_flip_waiter_->Reset();
-  SimulateDrag(AppsGridView::MOUSE, from, to);
-
-  EXPECT_EQ(to, GetDragViewCenter());
-
+  SimulateDrag(AppsGridView::MOUSE, item_center, apps_grid_top_center);
   while (test_api_->HasPendingPageFlip()) {
     page_flip_waiter_->Wait();
   }
 
+  // We flipped back to the first page.
   EXPECT_EQ("1,0", page_flip_waiter_->selected_pages());
   EXPECT_EQ(0, GetPaginationModel()->selected_page());
-  EXPECT_EQ(to, GetDragViewCenter());
+  EXPECT_EQ(apps_grid_top_center, GetDragViewCenter());
 
-  EndDrag(apps_grid_view_, true /*cancel*/);
+  // End the drag to satisfy checks in AppsGridView destructor.
+  EndDrag(apps_grid_view_, /*cancel=*/true);
 }
 
 TEST_F(AppsGridViewTest, UpdateFolderBackgroundOnCancelDrag) {
diff --git a/ash/wm/overview/overview_window_drag_controller_unittest.cc b/ash/wm/overview/overview_window_drag_controller_unittest.cc
index 1636ccf..6c0bd360 100644
--- a/ash/wm/overview/overview_window_drag_controller_unittest.cc
+++ b/ash/wm/overview/overview_window_drag_controller_unittest.cc
@@ -191,6 +191,32 @@
   EXPECT_TRUE(overview_session->no_windows_widget_for_testing());
 }
 
+// Test that if window is destroyed during dragging, no crash should happen and
+// drag should be reset.
+TEST_F(OverviewWindowDragControllerTest, WindowDestroyedDuringDragging) {
+  std::unique_ptr<aura::Window> window =
+      CreateAppWindow(gfx::Rect(0, 0, 250, 100));
+  auto* overview_controller = Shell::Get()->overview_controller();
+  overview_controller->StartOverview();
+  EXPECT_TRUE(overview_controller->InOverviewSession());
+  auto* overview_session = overview_controller->overview_session();
+  auto* overview_item =
+      overview_session->GetOverviewItemForWindow(window.get());
+  ASSERT_TRUE(overview_item);
+
+  auto* event_generator = GetEventGenerator();
+  StartDraggingItemBy(overview_item, 30, 200, /*by_touch_gestures=*/false,
+                      event_generator);
+  OverviewWindowDragController* drag_controller =
+      overview_session->window_drag_controller();
+  EXPECT_EQ(OverviewWindowDragController::DragBehavior::kNormalDrag,
+            drag_controller->current_drag_behavior());
+
+  window.reset();
+  EXPECT_EQ(OverviewWindowDragController::DragBehavior::kNoDrag,
+            drag_controller->current_drag_behavior());
+}
+
 // Tests the behavior of dragging a window in portrait tablet mode with virtual
 // desks enabled.
 class OverviewWindowDragControllerDesksPortraitTabletTest : public AshTestBase {
diff --git a/ash/wm/toplevel_window_event_handler.cc b/ash/wm/toplevel_window_event_handler.cc
index 0ff0659..426963e8 100644
--- a/ash/wm/toplevel_window_event_handler.cc
+++ b/ash/wm/toplevel_window_event_handler.cc
@@ -456,6 +456,74 @@
   }
 }
 
+wm::WindowMoveResult ToplevelWindowEventHandler::RunMoveLoop(
+    aura::Window* source,
+    const gfx::Vector2d& drag_offset,
+    ::wm::WindowMoveSource move_source) {
+  DCHECK(!in_move_loop_);  // Can only handle one nested loop at a time.
+  aura::Window* root_window = source->GetRootWindow();
+  DCHECK(root_window);
+  gfx::PointF drag_location;
+  if (move_source == ::wm::WINDOW_MOVE_SOURCE_TOUCH &&
+      aura::Env::GetInstance()->is_touch_down()) {
+    gfx::PointF drag_location_f;
+    bool has_point = aura::Env::GetInstance()
+                         ->gesture_recognizer()
+                         ->GetLastTouchPointForTarget(source, &drag_location_f);
+    drag_location = drag_location_f;
+    DCHECK(has_point);
+  } else {
+    drag_location = gfx::PointF(
+        root_window->GetHost()->dispatcher()->GetLastMouseLocationInRoot());
+    aura::Window::ConvertPointToTarget(root_window, source->parent(),
+                                       &drag_location);
+  }
+  // Set the cursor before calling AttemptToStartDrag(), as that will
+  // eventually call LockCursor() and prevent the cursor from changing.
+  aura::client::CursorClient* cursor_client =
+      aura::client::GetCursorClient(root_window);
+  if (cursor_client)
+    cursor_client->SetCursor(ui::mojom::CursorType::kPointer);
+
+  base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
+
+  DragResult result = DragResult::SUCCESS;
+  if (!AttemptToStartDrag(source, drag_location, HTCAPTION, move_source,
+                          base::BindOnce(OnDragCompleted, &result, &run_loop),
+                          /*update_gesture_target=*/false)) {
+    return ::wm::MOVE_CANCELED;
+  }
+
+  in_move_loop_ = true;
+  base::WeakPtr<ToplevelWindowEventHandler> weak_ptr(
+      weak_factory_.GetWeakPtr());
+
+  // Disable window position auto management while dragging and restore it
+  // aftrewards.
+  WindowState* window_state = WindowState::Get(source);
+  const bool window_position_managed = window_state->GetWindowPositionManaged();
+  window_state->SetWindowPositionManaged(false);
+  aura::WindowTracker tracker({source});
+
+  run_loop.Run();
+
+  if (!weak_ptr)
+    return ::wm::MOVE_CANCELED;
+
+  // Make sure the window hasn't been deleted.
+  if (tracker.Contains(source))
+    window_state->SetWindowPositionManaged(window_position_managed);
+
+  in_move_loop_ = false;
+  return result == DragResult::SUCCESS ? ::wm::MOVE_SUCCESSFUL
+                                       : ::wm::MOVE_CANCELED;
+}
+
+void ToplevelWindowEventHandler::EndMoveLoop() {
+  if (in_move_loop_)
+    RevertDrag();
+}
+
 bool ToplevelWindowEventHandler::AttemptToStartDrag(
     aura::Window* window,
     const gfx::PointF& point_in_parent,
@@ -560,74 +628,6 @@
   return nullptr;
 }
 
-::wm::WindowMoveResult ToplevelWindowEventHandler::RunMoveLoop(
-    aura::Window* source,
-    const gfx::Vector2d& drag_offset,
-    ::wm::WindowMoveSource move_source) {
-  DCHECK(!in_move_loop_);  // Can only handle one nested loop at a time.
-  aura::Window* root_window = source->GetRootWindow();
-  DCHECK(root_window);
-  gfx::PointF drag_location;
-  if (move_source == ::wm::WINDOW_MOVE_SOURCE_TOUCH &&
-      aura::Env::GetInstance()->is_touch_down()) {
-    gfx::PointF drag_location_f;
-    bool has_point = aura::Env::GetInstance()
-                         ->gesture_recognizer()
-                         ->GetLastTouchPointForTarget(source, &drag_location_f);
-    drag_location = drag_location_f;
-    DCHECK(has_point);
-  } else {
-    drag_location = gfx::PointF(
-        root_window->GetHost()->dispatcher()->GetLastMouseLocationInRoot());
-    aura::Window::ConvertPointToTarget(root_window, source->parent(),
-                                       &drag_location);
-  }
-  // Set the cursor before calling AttemptToStartDrag(), as that will
-  // eventually call LockCursor() and prevent the cursor from changing.
-  aura::client::CursorClient* cursor_client =
-      aura::client::GetCursorClient(root_window);
-  if (cursor_client)
-    cursor_client->SetCursor(ui::mojom::CursorType::kPointer);
-
-  base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
-
-  DragResult result = DragResult::SUCCESS;
-  if (!AttemptToStartDrag(source, drag_location, HTCAPTION, move_source,
-                          base::BindOnce(OnDragCompleted, &result, &run_loop),
-                          /*update_gesture_target=*/false)) {
-    return ::wm::MOVE_CANCELED;
-  }
-
-  in_move_loop_ = true;
-  base::WeakPtr<ToplevelWindowEventHandler> weak_ptr(
-      weak_factory_.GetWeakPtr());
-
-  // Disable window position auto management while dragging and restore it
-  // aftrewards.
-  WindowState* window_state = WindowState::Get(source);
-  const bool window_position_managed = window_state->GetWindowPositionManaged();
-  window_state->SetWindowPositionManaged(false);
-  aura::WindowTracker tracker({source});
-
-  run_loop.Run();
-
-  if (!weak_ptr)
-    return ::wm::MOVE_CANCELED;
-
-  // Make sure the window hasn't been deleted.
-  if (tracker.Contains(source))
-    window_state->SetWindowPositionManaged(window_position_managed);
-
-  in_move_loop_ = false;
-  return result == DragResult::SUCCESS ? ::wm::MOVE_SUCCESSFUL
-                                       : ::wm::MOVE_CANCELED;
-}
-
-void ToplevelWindowEventHandler::EndMoveLoop() {
-  if (in_move_loop_)
-    RevertDrag();
-}
-
 bool ToplevelWindowEventHandler::PrepareForDrag(
     aura::Window* window,
     const gfx::PointF& point_in_parent,
diff --git a/ash/wm/toplevel_window_event_handler.h b/ash/wm/toplevel_window_event_handler.h
index f8c26da..8d9bd16 100644
--- a/ash/wm/toplevel_window_event_handler.h
+++ b/ash/wm/toplevel_window_event_handler.h
@@ -68,6 +68,12 @@
   void OnMouseEvent(ui::MouseEvent* event) override;
   void OnGestureEvent(ui::GestureEvent* event) override;
 
+  // wm::WindowMoveClient:
+  wm::WindowMoveResult RunMoveLoop(aura::Window* source,
+                                   const gfx::Vector2d& drag_offset,
+                                   ::wm::WindowMoveSource move_source) override;
+  void EndMoveLoop() override;
+
   // Attempts to start a drag if one is not already in progress. Returns true if
   // successful. |end_closure| is run when the drag completes, including if the
   // drag is not started. If |update_gesture_target| is true, the gesture
@@ -104,12 +110,8 @@
     return event_location_in_gesture_target_;
   }
 
-  // Overridden from wm::WindowMoveClient:
-  ::wm::WindowMoveResult RunMoveLoop(
-      aura::Window* source,
-      const gfx::Vector2d& drag_offset,
-      ::wm::WindowMoveSource move_source) override;
-  void EndMoveLoop() override;
+  // Returns true if there is a drag in progress.
+  bool is_drag_in_progress() const { return window_resizer_.get() != nullptr; }
 
  private:
   class ScopedWindowResizer;
diff --git a/ash/wm/toplevel_window_event_handler_unittest.cc b/ash/wm/toplevel_window_event_handler_unittest.cc
index 9332160..f56181fa 100644
--- a/ash/wm/toplevel_window_event_handler_unittest.cc
+++ b/ash/wm/toplevel_window_event_handler_unittest.cc
@@ -1225,6 +1225,43 @@
   EXPECT_FALSE(overview_controller->InOverviewSession());
 }
 
+// Test that if window destroyed during resize/dragging, no crash should happen.
+TEST_F(ToplevelWindowEventHandlerDragTest, WindowDestroyedDuringDragging) {
+  SendGestureEvent(gfx::Point(0, 0), 0, 5, ui::ET_GESTURE_SCROLL_BEGIN);
+  SendGestureEvent(gfx::Point(700, 500), 700, 500,
+                   ui::ET_GESTURE_SCROLL_UPDATE);
+  EXPECT_TRUE(WindowState::Get(dragged_window_.get())->is_dragged());
+  ToplevelWindowEventHandler* event_handler =
+      Shell::Get()->toplevel_window_event_handler();
+  EXPECT_TRUE(event_handler->is_drag_in_progress());
+
+  dragged_window_.reset();
+  EXPECT_FALSE(event_handler->is_drag_in_progress());
+}
+
+// Test that if window destroyed during resize/dragging in tablet mode, no crash
+// should happen.
+TEST_F(ToplevelWindowEventHandlerDragTest,
+       WindowDestroyedDuringDraggingInTabletMode) {
+  TabletModeControllerTestApi().EnterTabletMode();
+
+  SendGestureEvent(gfx::Point(0, 0), 0, 5, ui::ET_GESTURE_SCROLL_BEGIN);
+  SendGestureEvent(gfx::Point(700, 500), 700, 500,
+                   ui::ET_GESTURE_SCROLL_UPDATE);
+  EXPECT_TRUE(WindowState::Get(dragged_window_.get())->is_dragged());
+  ToplevelWindowEventHandler* event_handler =
+      Shell::Get()->toplevel_window_event_handler();
+  EXPECT_TRUE(event_handler->is_drag_in_progress());
+  OverviewController* overview_controller = Shell::Get()->overview_controller();
+  EXPECT_TRUE(overview_controller->InOverviewSession());
+  EXPECT_FALSE(overview_controller->overview_session()->IsWindowInOverview(
+      dragged_window_.get()));
+
+  dragged_window_.reset();
+  EXPECT_FALSE(event_handler->is_drag_in_progress());
+  EXPECT_TRUE(overview_controller->InOverviewSession());
+}
+
 // Showing the resize shadows when the mouse is over the window edges is
 // tested in resize_shadow_and_cursor_test.cc
 
diff --git a/base/bind_internal.h b/base/bind_internal.h
index 4999a196..a7aba35 100644
--- a/base/bind_internal.h
+++ b/base/bind_internal.h
@@ -1046,6 +1046,17 @@
     struct ToParamWithType {
       static constexpr bool kCanBeForwardedToBoundFunctor =
           std::is_constructible<FunctorParamType, ForwardingType>::value;
+
+      // If the bound type can't be forwarded then test if `FunctorParamType` is
+      // a non-const lvalue reference and a reference to the unwrapped type
+      // *could* have been successfully forwarded.
+      static constexpr bool kNonConstRefParamMustBeWrapped =
+          kCanBeForwardedToBoundFunctor ||
+          !(std::is_lvalue_reference<FunctorParamType>::value &&
+            !std::is_const<std::remove_reference_t<FunctorParamType>>::value &&
+            std::is_convertible<std::decay_t<ForwardingType>&,
+                                FunctorParamType>::value);
+
       // Note that this intentionally drops the const qualifier from
       // `ForwardingType`, to test if it *could* have been successfully
       // forwarded if `Passed()` had been used.
@@ -1117,6 +1128,11 @@
       "bound functor.");
   static_assert(
       BindArgument<i>::template ForwardedAs<Unwrapped>::
+          template ToParamWithType<Param>::kNonConstRefParamMustBeWrapped,
+      "Bound argument for non-const reference parameter must be wrapped in "
+      "std::ref() or base::OwnedRef().");
+  static_assert(
+      BindArgument<i>::template ForwardedAs<Unwrapped>::
           template ToParamWithType<Param>::kCanBeForwardedToBoundFunctor,
       "Type mismatch between bound argument and bound functor's parameter.");
 
diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc
index 72929fb..7154194a 100644
--- a/base/bind_unittest.cc
+++ b/base/bind_unittest.cc
@@ -540,6 +540,94 @@
   EXPECT_EQ(s, "Run2");
 }
 
+void SetFromRef(int& ref) {
+  EXPECT_EQ(ref, 1);
+  ref = 2;
+  EXPECT_EQ(ref, 2);
+}
+
+TEST_F(BindTest, BindOnceWithNonConstRef) {
+  int v = 1;
+
+  // Mutates `v` because it's not bound to callback instead it's forwarded by
+  // Run().
+  auto cb1 = BindOnce(SetFromRef);
+  std::move(cb1).Run(v);
+  EXPECT_EQ(v, 2);
+  v = 1;
+
+  // Mutates `v` through std::reference_wrapper bound to callback.
+  auto cb2 = BindOnce(SetFromRef, std::ref(v));
+  std::move(cb2).Run();
+  EXPECT_EQ(v, 2);
+  v = 1;
+
+  // Everything past here following will make a copy of the argument. The copy
+  // will be mutated and leave `v` unmodified.
+  auto cb3 = BindOnce(SetFromRef, base::OwnedRef(v));
+  std::move(cb3).Run();
+  EXPECT_EQ(v, 1);
+
+  int& ref = v;
+  auto cb4 = BindOnce(SetFromRef, base::OwnedRef(ref));
+  std::move(cb4).Run();
+  EXPECT_EQ(v, 1);
+
+  const int cv = 1;
+  auto cb5 = BindOnce(SetFromRef, base::OwnedRef(cv));
+  std::move(cb5).Run();
+  EXPECT_EQ(cv, 1);
+
+  const int& cref = v;
+  auto cb6 = BindOnce(SetFromRef, base::OwnedRef(cref));
+  std::move(cb6).Run();
+  EXPECT_EQ(cref, 1);
+
+  auto cb7 = BindOnce(SetFromRef, base::OwnedRef(1));
+  std::move(cb7).Run();
+}
+
+TEST_F(BindTest, BindRepeatingWithNonConstRef) {
+  int v = 1;
+
+  // Mutates `v` because it's not bound to callback instead it's forwarded by
+  // Run().
+  auto cb1 = BindRepeating(SetFromRef);
+  std::move(cb1).Run(v);
+  EXPECT_EQ(v, 2);
+  v = 1;
+
+  // Mutates `v` through std::reference_wrapper bound to callback.
+  auto cb2 = BindRepeating(SetFromRef, std::ref(v));
+  std::move(cb2).Run();
+  EXPECT_EQ(v, 2);
+  v = 1;
+
+  // Everything past here following will make a copy of the argument. The copy
+  // will be mutated and leave `v` unmodified.
+  auto cb3 = BindRepeating(SetFromRef, base::OwnedRef(v));
+  std::move(cb3).Run();
+  EXPECT_EQ(v, 1);
+
+  int& ref = v;
+  auto cb4 = BindRepeating(SetFromRef, base::OwnedRef(ref));
+  std::move(cb4).Run();
+  EXPECT_EQ(v, 1);
+
+  const int cv = 1;
+  auto cb5 = BindRepeating(SetFromRef, base::OwnedRef(cv));
+  std::move(cb5).Run();
+  EXPECT_EQ(cv, 1);
+
+  const int& cref = v;
+  auto cb6 = BindRepeating(SetFromRef, base::OwnedRef(cref));
+  std::move(cb6).Run();
+  EXPECT_EQ(cref, 1);
+
+  auto cb7 = BindRepeating(SetFromRef, base::OwnedRef(1));
+  std::move(cb7).Run();
+}
+
 // Functions that take reference parameters.
 //  - Forced reference parameter type still stores a copy.
 //  - Forced const reference parameter type still stores a copy.
diff --git a/base/bind_unittest.nc b/base/bind_unittest.nc
index f20d563d..4068272 100644
--- a/base/bind_unittest.nc
+++ b/base/bind_unittest.nc
@@ -74,6 +74,8 @@
 void TakesMoveOnly(std::unique_ptr<int>) {
 }
 
+void TakesIntRef(int& ref) {}
+
 struct NonEmptyFunctor {
   int x;
   void operator()() const {}
@@ -157,13 +159,41 @@
   ref_arg_cb.Run(p);
 }
 
-#elif defined(NCTEST_DISALLOW_BIND_TO_NON_CONST_REF_PARAM)  // [r"static_assert failed.+?BindArgument<0>::ForwardedAs<.+?>::ToParamWithType<.+?>::kCanBeForwardedToBoundFunctor.+?Type mismatch between bound argument and bound functor's parameter\."]
+#elif defined(NCTEST_BIND_ONCE_WITH_NON_CONST_REF_PARAM)  // [r"static_assert failed due to requirement 'BindArgument<0>::ForwardedAs<.+?>::ToParamWithType<.+?>::kNonConstRefParamMustBeWrapped' \"Bound argument for non-const reference parameter must be wrapped in std::ref\(\) or base::OwnedRef\(\).\""]
 
-// Binding functions with reference parameters requires `std::ref()`.
+// Binding functions with reference parameters requires `std::ref()` or
+// 'base::OwnedRef()`.
 void WontCompile() {
-  Parent p;
-  RepeatingCallback<int()> ref_cb = BindRepeating(&UnwrapParentRef, p);
-  ref_cb.Run();
+  int v = 1;
+  auto cb = BindOnce(&TakesIntRef, v);
+}
+
+#elif defined(NCTEST_BIND_REPEATING_WITH_NON_CONST_REF_PARAM)  // [r"static_assert failed due to requirement 'BindArgument<0>::ForwardedAs<.+?>::ToParamWithType<.+?>::kNonConstRefParamMustBeWrapped' \"Bound argument for non-const reference parameter must be wrapped in std::ref\(\) or base::OwnedRef\(\).\""]
+
+// Binding functions with reference parameters requires `std::ref()` or
+// 'base::OwnedRef()`.
+void WontCompile() {
+  int v = 1;
+  auto cb = BindRepeating(&TakesIntRef, v);
+}
+
+#elif defined(NCTEST_NON_CONST_REF_PARAM_WRONG_TYPE)  // [r"static_assert failed due to requirement 'BindArgument<0>::ForwardedAs<.+?>::ToParamWithType<.+?>::kCanBeForwardedToBoundFunctor' \"Type mismatch between bound argument and bound functor's parameter.\""]
+
+// If the argument and parameter types mismatch then the compile error should be
+// the generic type mismatch error.
+void WontCompile() {
+  float f = 1.0f;
+  auto cb = BindOnce(&TakesIntRef, f);
+}
+
+#elif defined(NCTEST_NON_CONST_REF_PARAM_WRONG_TYPE_AND_WRAPPED)  // [r"static_assert failed due to requirement 'BindArgument<0>::ForwardedAs<.+?>::ToParamWithType<.+?>::kCanBeForwardedToBoundFunctor' \"Type mismatch between bound argument and bound functor's parameter.\""]
+
+// If the argument and parameter types mismatch then the compile error should be
+// the generic type mismatch error even if the argument is wrapped in
+// base::OwnedRef().
+void WontCompile() {
+  float f = 1.0f;
+  auto cb = BindOnce(&TakesIntRef, base::OwnedRef(f));
 }
 
 #elif defined(NCTEST_NO_IMPLICIT_ARRAY_PTR_CONVERSION)  // [r"fatal error: static_assert failed due to requirement '!std::is_array<base::HasRef \[10\]>::value' \"First bound argument to a method cannot be an array.\""]
diff --git a/build/android/gyp/proguard.py b/build/android/gyp/proguard.py
index fb1908c..fd7f6ba 100755
--- a/build/android/gyp/proguard.py
+++ b/build/android/gyp/proguard.py
@@ -554,15 +554,19 @@
     if exclude_generated and config.endswith('.resources.proguard.txt'):
       continue
 
-    ret.append('# File: ' + config)
     with open(config) as config_file:
       contents = config_file.read().rstrip()
 
+    if not contents.strip():
+      # Ignore empty files.
+      continue
+
     # Fix up line endings (third_party configs can have windows endings).
     contents = contents.replace('\r', '')
     # Remove numbers from generated rule comments to make file more
     # diff'able.
     contents = re.sub(r' #generated:\d+', '', contents)
+    ret.append('# File: ' + config)
     ret.append(contents)
     ret.append('')
 
diff --git a/build/config/android/BUILD.gn b/build/config/android/BUILD.gn
index 78c7983a7..8cfe7a0 100644
--- a/build/config/android/BUILD.gn
+++ b/build/config/android/BUILD.gn
@@ -51,6 +51,14 @@
     "-Wl,--exclude-libs=libvpx_assembly_arm.a",
   ]
 
+  # TODO(crbug.com/1184398): Move to compiler-rt when we are ready.
+  ldflags += [ "--rtlib=libgcc" ]
+  if (current_cpu == "arm64") {
+    # For outline atomics on AArch64 (can't pass this unconditionally
+    # due to unused flag warning on other targets).
+    cflags += [ "--rtlib=libgcc" ]
+  }
+
   # $compile_api_level corresponds to the API level used for the sysroot path
   # calculation in //build/config/android/config.gni
   if (current_cpu == "arm") {
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 1b5c564e..cdb34b7 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-3.20210317.0.1
+3.20210317.1.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index 1b5c564e..cdb34b7 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-3.20210317.0.1
+3.20210317.1.1
diff --git a/cc/base/features.cc b/cc/base/features.cc
index 3494bb7f..9b1496f 100644
--- a/cc/base/features.cc
+++ b/cc/base/features.cc
@@ -50,7 +50,7 @@
 }
 
 const base::Feature kRemoveMobileViewportDoubleTap{
-    "RemoveMobileViewportDoubleTap", base::FEATURE_DISABLED_BY_DEFAULT};
+    "RemoveMobileViewportDoubleTap", base::FEATURE_ENABLED_BY_DEFAULT};
 
 const base::Feature kScrollUnification{"ScrollUnification",
                                        base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/cc/input/scroll_snap_data.cc b/cc/input/scroll_snap_data.cc
index f2586f2..17e170d 100644
--- a/cc/input/scroll_snap_data.cc
+++ b/cc/input/scroll_snap_data.cc
@@ -4,14 +4,16 @@
 
 #include "cc/input/scroll_snap_data.h"
 
+#include <algorithm>
+#include <cmath>
+#include <limits>
+#include <memory>
+
 #include "base/check.h"
 #include "base/notreached.h"
 #include "base/numerics/ranges.h"
 #include "cc/input/snap_selection_strategy.h"
 
-#include <algorithm>
-#include <cmath>
-
 namespace cc {
 namespace {
 
@@ -384,6 +386,8 @@
     result.set_visible_range(gfx::RangeF(area.rect.y() - rect_.bottom(),
                                          area.rect.bottom() - rect_.y()));
     // https://www.w3.org/TR/css-scroll-snap-1/#scroll-snap-align
+    // Snap alignment has been normalized for a horizontal left to right and top
+    // to bottom writing mode.
     switch (area.scroll_snap_align.alignment_inline) {
       case SnapAlignment::kStart:
         result.set_snap_offset(area.rect.x() - rect_.x());
diff --git a/cc/metrics/jank_injector.cc b/cc/metrics/jank_injector.cc
index 12c13e41..1ffcbfbe 100644
--- a/cc/metrics/jank_injector.cc
+++ b/cc/metrics/jank_injector.cc
@@ -45,10 +45,12 @@
   bool busy_loop = true;
 };
 
+bool g_jank_enabled_for_test = false;
+
 bool IsJankInjectionEnabled() {
   static bool enabled =
       base::FeatureList::IsEnabled(features::kJankInjectionAblationFeature);
-  return enabled;
+  return enabled || g_jank_enabled_for_test;
 }
 
 using AllowedURLsMap = std::map<std::string, std::vector<std::string>>;
@@ -105,6 +107,16 @@
 
 }  // namespace
 
+ScopedJankInjectionEnabler::ScopedJankInjectionEnabler() {
+  DCHECK(!g_jank_enabled_for_test);
+  g_jank_enabled_for_test = true;
+}
+
+ScopedJankInjectionEnabler::~ScopedJankInjectionEnabler() {
+  DCHECK(g_jank_enabled_for_test);
+  g_jank_enabled_for_test = false;
+}
+
 JankInjector::JankInjector() {
   if (IsJankInjectionEnabled()) {
     config_.target_dropped_frames_percent =
diff --git a/cc/metrics/jank_injector.h b/cc/metrics/jank_injector.h
index b27bf214..5b3f650 100644
--- a/cc/metrics/jank_injector.h
+++ b/cc/metrics/jank_injector.h
@@ -15,6 +15,16 @@
 
 namespace cc {
 
+class CC_EXPORT ScopedJankInjectionEnabler {
+ public:
+  ScopedJankInjectionEnabler();
+  ~ScopedJankInjectionEnabler();
+
+  ScopedJankInjectionEnabler(const ScopedJankInjectionEnabler&) = delete;
+  ScopedJankInjectionEnabler& operator=(const ScopedJankInjectionEnabler&) =
+      delete;
+};
+
 class CC_EXPORT JankInjector {
  public:
   struct CC_EXPORT JankConfig {
diff --git a/cc/metrics/jank_injector_unittest.cc b/cc/metrics/jank_injector_unittest.cc
index cbc50cc..a6587373 100644
--- a/cc/metrics/jank_injector_unittest.cc
+++ b/cc/metrics/jank_injector_unittest.cc
@@ -27,6 +27,7 @@
   scoped_refptr<base::TestSimpleTaskRunner> task_runner(
       new base::TestSimpleTaskRunner());
 
+  ScopedJankInjectionEnabler enable_jank;
   JankInjector injector;
   const auto& config = injector.config();
   EXPECT_EQ(config.target_dropped_frames_percent, 10u);
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 6eaed74..5f0ee88 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -2201,7 +2201,7 @@
     "//content/public/android:content_java",
   ]
   sources =
-      [ "java/src/org/chromium/chrome/browser/MonochromeApplication.java" ]
+      [ "java/src/org/chromium/chrome/browser/MonochromeApplicationImpl.java" ]
 }
 
 # Monochrome equivalent of :base_module_java.
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni
index ddc0be5..4f60c0cd 100644
--- a/chrome/android/chrome_java_resources.gni
+++ b/chrome/android/chrome_java_resources.gni
@@ -894,7 +894,6 @@
   "java/res/values-v28/styles.xml",
   "java/res/values-xhdpi/dimens.xml",
   "java/res/values-xlarge/dimens.xml",
-  "java/res/values-xxhdpi/dimens.xml",
   "java/res/values/attrs.xml",
   "java/res/values/colors.xml",
   "java/res/values/dimens.xml",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 8d9af024..6da5cada 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -14,7 +14,7 @@
   "java/src/org/chromium/chrome/browser/ChromeAccessorActivity.java",
   "java/src/org/chromium/chrome/browser/ChromeActionModeHandler.java",
   "java/src/org/chromium/chrome/browser/ChromeActivitySessionTracker.java",
-  "java/src/org/chromium/chrome/browser/ChromeApplication.java",
+  "java/src/org/chromium/chrome/browser/ChromeApplicationImpl.java",
   "java/src/org/chromium/chrome/browser/ChromeBackgroundServiceImpl.java",
   "java/src/org/chromium/chrome/browser/ChromeBackupAgentImpl.java",
   "java/src/org/chromium/chrome/browser/ChromeBackupWatcher.java",
@@ -321,14 +321,7 @@
   "java/src/org/chromium/chrome/browser/compositor/layouts/eventfilter/GestureHandler.java",
   "java/src/org/chromium/chrome/browser/compositor/layouts/eventfilter/OverlayPanelEventFilter.java",
   "java/src/org/chromium/chrome/browser/compositor/layouts/phone/SimpleAnimationLayout.java",
-  "java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java",
-  "java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java",
-  "java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/OverlappingStack.java",
-  "java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java",
-  "java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java",
   "java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackScroller.java",
-  "java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackTab.java",
-  "java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackViewAnimation.java",
   "java/src/org/chromium/chrome/browser/compositor/overlays/strip/CascadingStripStacker.java",
   "java/src/org/chromium/chrome/browser/compositor/overlays/strip/ScrollingStripStacker.java",
   "java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni
index 91c0edd..7b20a36 100644
--- a/chrome/android/chrome_test_java_sources.gni
+++ b/chrome/android/chrome_test_java_sources.gni
@@ -51,7 +51,6 @@
   "javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java",
   "javatests/src/org/chromium/chrome/browser/accessibility/FontSizePrefsTest.java",
   "javatests/src/org/chromium/chrome/browser/accessibility/settings/AccessibilitySettingsTest.java",
-  "javatests/src/org/chromium/chrome/browser/accessibility_tab_switcher/OverviewListLayoutTest.java",
   "javatests/src/org/chromium/chrome/browser/app/appmenu/DataSaverAppMenuTest.java",
   "javatests/src/org/chromium/chrome/browser/app/appmenu/OverviewAppMenuTest.java",
   "javatests/src/org/chromium/chrome/browser/app/appmenu/TabbedAppMenuTest.java",
diff --git a/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected b/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected
index edbcf98f..6e4bafb 100644
--- a/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected
+++ b/chrome/android/expectations/monochrome_public_bundle.proguard_flags.expected
@@ -745,9 +745,6 @@
 
 -keep class * implements com.google.firebase.components.ComponentRegistrar
 
-# File: obj/third_party/android_deps/google_firebase_firebase_encoders_json_java/proguard.txt
-
-
 # File: obj/third_party/android_deps/google_firebase_firebase_messaging_java/proguard.txt
 # Analytics library is optional.
 # Access to this class is protected by try/catch(NoClassDefFoundError e)
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java
index 1eb91b7..a0a02dd4 100644
--- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java
+++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java
@@ -242,10 +242,11 @@
 
     @Override
     public void startHiding(int nextId, boolean hintAtTabSelection) {
-        super.startHiding(nextId, hintAtTabSelection);
-
         int sourceTabId = nextId;
         if (sourceTabId == Tab.INVALID_TAB_ID) sourceTabId = mTabModelSelector.getCurrentTabId();
+
+        super.startHiding(sourceTabId, hintAtTabSelection);
+
         LayoutTab sourceLayoutTab = createLayoutTab(
                 sourceTabId, mTabModelSelector.isIncognitoSelected(), NO_CLOSE_BUTTON, NO_TITLE);
         sourceLayoutTab.setDecorationAlpha(0);
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTab.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTab.java
index 41bd97f6..489806e 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTab.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/pseudotab/PseudoTab.java
@@ -90,7 +90,7 @@
                 if (cached.getTab() == tab) {
                     return cached;
                 } else {
-                    assert cached.getTab().getWebContents() == null
+                    assert tab.getWebContents() == null || cached.getTab().getWebContents() == null
                             || cached.getTab().getWebContents().getTopLevelNativeWindow() == null;
                     return new PseudoTab(tab);
                 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilities.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilities.java
index b438954..68bd0cb 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilities.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilities.java
@@ -115,7 +115,6 @@
 
         // Having Tab Groups or Start implies Grid Tab Switcher.
         return (!DeviceClassManager.enableAccessibilityLayout()
-                       && CachedFeatureFlags.isEnabled(ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID)
                        && isTabManagementModuleSupported())
                 || isTabGroupsAndroidEnabled() || StartSurfaceConfiguration.isStartSurfaceEnabled();
     }
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/ConditionalTabStripTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/ConditionalTabStripTest.java
deleted file mode 100644
index 36124bf8..0000000
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/ConditionalTabStripTest.java
+++ /dev/null
@@ -1,886 +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.
-
-package org.chromium.chrome.browser.tasks.tab_management;
-
-import static androidx.test.espresso.Espresso.onView;
-import static androidx.test.espresso.action.ViewActions.click;
-import static androidx.test.espresso.action.ViewActions.longClick;
-import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
-import static androidx.test.espresso.assertion.ViewAssertions.matches;
-import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static androidx.test.espresso.matcher.ViewMatchers.withId;
-import static androidx.test.espresso.matcher.ViewMatchers.withParent;
-import static androidx.test.espresso.matcher.ViewMatchers.withText;
-
-import static org.hamcrest.CoreMatchers.allOf;
-import static org.hamcrest.CoreMatchers.containsString;
-import static org.hamcrest.CoreMatchers.not;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import static org.chromium.chrome.browser.flags.ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID;
-import static org.chromium.chrome.browser.flags.ChromeFeatureList.START_SURFACE_ANDROID;
-import static org.chromium.chrome.browser.flags.ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID;
-import static org.chromium.chrome.browser.flags.ChromeFeatureList.TAB_GROUPS_ANDROID;
-import static org.chromium.chrome.browser.tasks.ConditionalTabStripUtils.CONDITIONAL_TAB_STRIP_SESSION_TIME_MS;
-import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.createTabs;
-import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.verifyTabModelTabCount;
-import static org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper.verifyTabStripFaviconCount;
-
-import android.content.Context;
-import android.os.Build;
-import android.os.Build.VERSION_CODES;
-import android.support.test.InstrumentationRegistry;
-import android.view.View;
-import android.widget.ListView;
-
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.test.espresso.contrib.RecyclerViewActions;
-import androidx.test.filters.MediumTest;
-
-import org.hamcrest.Matchers;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.base.test.util.Batch;
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.Criteria;
-import org.chromium.base.test.util.CriteriaHelper;
-import org.chromium.base.test.util.DisableIf;
-import org.chromium.base.test.util.DisabledTest;
-import org.chromium.base.test.util.FlakyTest;
-import org.chromium.base.test.util.Restriction;
-import org.chromium.chrome.browser.ChromeTabbedActivity;
-import org.chromium.chrome.browser.TabsTest.SimulateClickOnMainThread;
-import org.chromium.chrome.browser.TabsTest.SimulateTabSwipeOnMainThread;
-import org.chromium.chrome.browser.accessibility_tab_switcher.AccessibilityTabModelListItem;
-import org.chromium.chrome.browser.accessibility_tab_switcher.AccessibilityTabModelWrapper;
-import org.chromium.chrome.browser.accessibility_tab_switcher.OverviewListLayout;
-import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChrome;
-import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChromePhone;
-import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
-import org.chromium.chrome.browser.compositor.layouts.phone.StackLayout;
-import org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack;
-import org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab;
-import org.chromium.chrome.browser.flags.ChromeSwitches;
-import org.chromium.chrome.browser.infobar.InfoBarContainer;
-import org.chromium.chrome.browser.tab.TabLaunchType;
-import org.chromium.chrome.browser.tabmodel.TabCreator;
-import org.chromium.chrome.browser.tabmodel.TabModel;
-import org.chromium.chrome.browser.tasks.ConditionalTabStripUtils;
-import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
-import org.chromium.chrome.browser.undo_tab_close_snackbar.UndoBarController;
-import org.chromium.chrome.browser.util.ChromeAccessibilityUtil;
-import org.chromium.chrome.tab_ui.R;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
-import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule;
-import org.chromium.chrome.test.util.ChromeTabUtils;
-import org.chromium.chrome.test.util.OverviewModeBehaviorWatcher;
-import org.chromium.chrome.test.util.browser.Features;
-import org.chromium.components.embedder_support.util.UrlConstants;
-import org.chromium.content_public.browser.LoadUrlParams;
-import org.chromium.content_public.browser.test.util.TestThreadUtils;
-import org.chromium.ui.test.util.UiRestriction;
-
-import java.util.concurrent.ExecutionException;
-
-/** End-to-end tests for conditional tab strip component. */
-@RunWith(ChromeJUnit4ClassRunner.class)
-// clang-format off
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
-        ChromeSwitches.DISABLE_STARTUP_PROMOS})
-@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-@Features.EnableFeatures({CONDITIONAL_TAB_STRIP_ANDROID})
-@Features.DisableFeatures({TAB_GRID_LAYOUT_ANDROID, TAB_GROUPS_ANDROID, START_SURFACE_ANDROID})
-@Batch(Batch.PER_CLASS)
-public class ConditionalTabStripTest {
-    // clang-format on
-    private static final int TEST_SESSION_MS = 600000;
-    private static final int SWIPE_TO_RIGHT_DIRECTION = 1;
-    private static final int SWIPE_TO_LEFT_DIRECTION = -1;
-
-    @ClassRule
-    public static final ChromeTabbedActivityTestRule sActivityTestRule =
-            new ChromeTabbedActivityTestRule();
-
-    private SimulateTabSwipeOnMainThread mSwipeToNormal;
-    private SimulateTabSwipeOnMainThread mSwipeToIncognito;
-    private float mPxToDp = 1f;
-    private float mTabsViewHeightDp;
-    private float mTabsViewWidthDp;
-
-    @Rule
-    public final BlankCTATabInitialStateRule mInitialStateRule =
-            new BlankCTATabInitialStateRule(sActivityTestRule, false);
-
-    @Before
-    public void setUp() {
-        // For this test suite, the session time is set to be 0 by default so that we can start a
-        // new session by restarting Chrome. Also, the opt-out indicator and the dismiss counter
-        // are reset to the initial state.
-        CONDITIONAL_TAB_STRIP_SESSION_TIME_MS.setForTesting(0);
-        ConditionalTabStripUtils.setOptOutIndicator(false);
-        ConditionalTabStripUtils.setContinuousDismissCount(0);
-        ConditionalTabStripUtils.setFeatureStatus(ConditionalTabStripUtils.FeatureStatus.DEFAULT);
-
-        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
-        CriteriaHelper.pollUiThread(cta.getTabModelSelector()::isTabStateInitialized);
-
-        float dpToPx = InstrumentationRegistry.getInstrumentation()
-                               .getContext()
-                               .getResources()
-                               .getDisplayMetrics()
-                               .density;
-        mPxToDp = 1.0f / dpToPx;
-        View tabsView = cta.getTabsView();
-        mTabsViewHeightDp = tabsView.getHeight() * mPxToDp;
-        mTabsViewWidthDp = tabsView.getWidth() * mPxToDp;
-        mSwipeToIncognito =
-                new SimulateTabSwipeOnMainThread(cta.getLayoutManager(), mTabsViewWidthDp - 20,
-                        mTabsViewHeightDp / 2, SWIPE_TO_LEFT_DIRECTION * mTabsViewWidthDp, 0);
-        mSwipeToNormal = new SimulateTabSwipeOnMainThread(cta.getLayoutManager(), 20,
-                mTabsViewHeightDp / 2, SWIPE_TO_RIGHT_DIRECTION * mTabsViewWidthDp, 0);
-    }
-
-    @After
-    public void tearDown() {
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            sActivityTestRule.getActivity().getTabModelSelector().getModel(true).closeAllTabs();
-            ChromeAccessibilityUtil.get().setAccessibilityEnabledForTesting(null);
-        });
-    }
-
-    private void enterTabSwitcher(ChromeTabbedActivity cta) {
-        OverviewModeBehaviorWatcher showWatcher = TabUiTestHelper.createOverviewShowWatcher(cta);
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> { cta.findViewById(R.id.tab_switcher_button).performClick(); });
-        showWatcher.waitForBehavior();
-    }
-
-    @Test
-    @MediumTest
-    @DisableIf.Build(sdk_is_less_than = VERSION_CODES.O,
-            message = "Failing or flaky on N & P, see crbug.com/1177383 & crbug.com/1081832")
-    public void
-    testStrip_updateWithAddition() throws Exception {
-        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
-        verifyHidingStrip();
-
-        // Unintentional tab creation will not trigger tab strip.
-        createBlankPageWithLaunchType(cta, false, TabLaunchType.FROM_EXTERNAL_APP);
-        verifyHidingStrip();
-        verifyTabModelTabCount(cta, 2, 0);
-        createBlankPageWithLaunchType(cta, false, TabLaunchType.FROM_LINK);
-        verifyHidingStrip();
-        verifyTabModelTabCount(cta, 3, 0);
-
-        // Intentional tab creation from toolbar menu will trigger tab strip.
-        ChromeTabUtils.newTabFromMenu(
-                InstrumentationRegistry.getInstrumentation(), cta, false, false);
-        verifyShowingStrip(cta, false, 4);
-
-        // Restart chrome to make the current tab strip session expire.
-        cta = restartChrome();
-        verifyHidingStrip();
-        verifyTabModelTabCount(cta, 4, 0);
-
-        // Intentional tab creation from long-press context menu will trigger tab strip.
-        createBlankPageWithLaunchType(cta, false, TabLaunchType.FROM_LONGPRESS_BACKGROUND);
-        verifyShowingStrip(cta, false, 5);
-
-        // Restart chrome to make the current tab strip session expire.
-        cta = restartChrome();
-        verifyHidingStrip();
-        verifyTabModelTabCount(cta, 5, 0);
-
-        // Intentional tab creation from long-press tab switcher action menu will trigger tab strip.
-        onView(withId(R.id.tab_switcher_button)).perform(longClick());
-        onView(withText(R.string.menu_new_tab)).perform(click());
-        verifyShowingStrip(cta, false, 6);
-
-        // When tab strip is already showing, both intentional and unintentional tab creation should
-        // trigger tab strip update.
-        createBlankPageWithLaunchType(cta, false, TabLaunchType.FROM_EXTERNAL_APP);
-        verifyShowingStrip(cta, false, 7);
-        ChromeTabUtils.newTabFromMenu(
-                InstrumentationRegistry.getInstrumentation(), cta, false, false);
-        verifyShowingStrip(cta, false, 8);
-    }
-
-    @Test
-    @MediumTest
-    public void testStrip_updateWithClosure() throws Exception {
-        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
-        verifyHidingStrip();
-
-        createTabs(cta, false, 3);
-        verifyShowingStrip(cta, false, 3);
-
-        // Close one tab in tab switcher, check the update is reflected in tab strip.
-        enterTabSwitcher(cta);
-        closeStackTabAtIndex(cta, 2, false);
-        clickOnStackTabAtIndex(1, false);
-        verifyShowingStrip(cta, false, 2);
-
-        // Close another tab in tab switcher. Since there is only tab left in current tab model,
-        // the strip should be hidden.
-        enterTabSwitcher(cta);
-        closeStackTabAtIndex(cta, 1, false);
-        clickOnStackTabAtIndex(0, false);
-        verifyHidingStrip();
-    }
-
-    @Test
-    @MediumTest
-    public void testStrip_updateWithSelection() throws Exception {
-        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
-        verifyHidingStrip();
-
-        for (int i = 0; i < 3; i++) {
-            createBlankPageWithLaunchType(cta, false, TabLaunchType.FROM_CHROME_UI);
-        }
-        verifyShowingStrip(cta, false, 4);
-
-        // Restart chrome to make the current tab strip session expire.
-        cta = restartChrome();
-        verifyHidingStrip();
-        verifyTabModelTabCount(cta, 4, 0);
-
-        // Tab selection through tab switcher should trigger tab strip, and tab selection will be
-        // reflected in tab strip.
-        for (int i = 0; i < 4; i++) {
-            enterTabSwitcher(cta);
-            verifyHidingStrip();
-            clickOnStackTabAtIndex(i, false);
-            verifyShowingStrip(cta, false, 4);
-            verifyStripSelectedPosition(cta, i);
-        }
-    }
-
-    @Test
-    @MediumTest
-    public void testStrip_updateWithTabModelSwitch() throws Exception {
-        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
-        verifyHidingStrip();
-
-        createTabs(cta, false, 3);
-        verifyShowingStrip(cta, false, 3);
-        createTabs(cta, true, 2);
-        verifyShowingStrip(cta, true, 2);
-        verifyTabModelTabCount(cta, 3, 2);
-        assertTrue(cta.getTabModelSelector().isIncognitoSelected());
-
-        // Switch tab model through tab switcher.
-        enterTabSwitcher(cta);
-        verifyHidingStrip();
-        switchTabModel(cta, false);
-        verifyHidingStrip();
-        clickOnStackTabAtIndex(0, false);
-        verifyShowingStrip(cta, false, 3);
-
-        // Switch tab model through creating new tabs.
-        createTabs(cta, true, 2);
-        verifyTabModelTabCount(cta, 3, 4);
-        verifyShowingStrip(cta, true, 4);
-        createTabs(cta, false, 3);
-        verifyTabModelTabCount(cta, 5, 4);
-        verifyShowingStrip(cta, false, 5);
-    }
-
-    @Test
-    @MediumTest
-    public void testStrip_createTabWithStrip() throws Exception {
-        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
-        verifyHidingStrip();
-
-        // Test creating normal tabs by clicking the plus button in tab strip.
-        createTabs(cta, false, 3);
-        verifyShowingStrip(cta, false, 3);
-        int normalTabCount = 3;
-        for (int i = 0; i < 3; i++) {
-            clickPlusButtonOnStrip();
-            verifyTabModelTabCount(cta, ++normalTabCount, 0);
-            verifyShowingStrip(cta, false, normalTabCount);
-        }
-
-        // Switch to incognito tab model.
-        createTabs(cta, true, 1);
-        // Strip should not be showing when there is only one tab in current model.
-        verifyHidingStrip();
-        createTabs(cta, true, 1);
-        verifyShowingStrip(cta, true, 2);
-
-        // Test creating incognito tabs by clicking the plus button in tab strip.
-        int incognitoTabCount = 2;
-        for (int i = 0; i < 3; i++) {
-            clickPlusButtonOnStrip();
-            verifyTabModelTabCount(cta, normalTabCount, ++incognitoTabCount);
-            verifyShowingStrip(cta, true, incognitoTabCount);
-        }
-    }
-
-    @Test
-    @MediumTest
-    public void testStrip_switchTabWithStrip() throws Exception {
-        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
-        verifyHidingStrip();
-
-        createTabs(cta, false, 4);
-        verifyShowingStrip(cta, false, 4);
-        verifyStripSelectedPosition(cta, 3);
-
-        // Switching between tabs by clicking on favicon.
-        for (int i = 0; i < 4; i++) {
-            clickNthItemInStrip(i);
-            verifyStripSelectedPosition(cta, i);
-        }
-    }
-
-    @Test
-    @MediumTest
-    public void testStrip_closeTabWithStrip() throws Exception {
-        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
-        verifyHidingStrip();
-
-        createTabs(cta, false, 2);
-        verifyShowingStrip(cta, false, 2);
-        verifyStripSelectedPosition(cta, 1);
-
-        // Click the selected item to close the last tab, and the strip should be hidden
-        // after closure.
-        clickNthItemInStrip(1);
-        verifyHidingStrip();
-        verifyTabModelTabCount(cta, 1, 0);
-
-        // Click undo to bring back the last tab, and should bring back the tab strip as
-        // well. Also, the tab whose closure is undone should be selected.
-        CriteriaHelper.pollInstrumentationThread(TabUiTestHelper::verifyUndoBarShowingAndClickUndo);
-        verifyShowingStrip(cta, false, 2);
-        verifyTabModelTabCount(cta, 2, 0);
-        verifyStripSelectedPosition(cta, 1);
-
-        // Disable undo snackbar and test continuous closures.
-        cta.getSnackbarManager().disableForTesting();
-        createTabs(cta, false, 3);
-        verifyShowingStrip(cta, false, 4);
-        int tabCount = 4;
-        for (int i = 3; i > 0; i--) {
-            verifyStripSelectedPosition(cta, i);
-            clickNthItemInStrip(i);
-            verifyTabModelTabCount(cta, --tabCount, 0);
-            if (i == 1) {
-                // Tab strip will be hidden when there is only one tab in current model.
-                verifyHidingStrip();
-            } else {
-                verifyShowingStrip(cta, false, tabCount);
-            }
-        }
-    }
-
-    @Test
-    @MediumTest
-    public void testStrip_dismiss() throws Exception {
-        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
-        verifyHidingStrip();
-
-        triggerStripAndDismiss(cta);
-
-        // Tab strip should keep hidden throughout this session.
-        enterTabSwitcher(cta);
-        clickOnStackTabAtIndex(0, false);
-        verifyHidingStrip();
-        createBlankPageWithLaunchType(cta, false, TabLaunchType.FROM_CHROME_UI);
-        verifyHidingStrip();
-        createTabs(cta, true, 2);
-        verifyHidingStrip();
-    }
-
-    @Test
-    @MediumTest
-    public void testStrip_disabled_expired() throws Exception {
-        triggerStripAndDismiss(sActivityTestRule.getActivity());
-
-        ChromeTabbedActivity cta = restartChrome();
-        verifyHidingStrip();
-
-        createTabs(cta, false, 2);
-        verifyShowingStrip(cta, false, cta.getCurrentTabModel().getCount());
-    }
-
-    @Test
-    @MediumTest
-    public void testStrip_disabled_notExpired() throws Exception {
-        triggerStripAndDismiss(sActivityTestRule.getActivity());
-
-        // Update the session time so that the disabled state is not expired for next restart.
-        CONDITIONAL_TAB_STRIP_SESSION_TIME_MS.setForTesting(TEST_SESSION_MS);
-        ChromeTabbedActivity cta = restartChrome();
-        verifyHidingStrip();
-
-        createTabs(cta, false, 2);
-        verifyHidingStrip();
-    }
-
-    @Test
-    @MediumTest
-    public void testStrip_enabled_expired() throws Exception {
-        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
-        for (int i = 0; i < 3; i++) {
-            createBlankPageWithLaunchType(cta, false, TabLaunchType.FROM_CHROME_UI);
-        }
-        verifyShowingStrip(cta, false, 4);
-
-        restartChrome();
-        verifyHidingStrip();
-    }
-
-    @Test
-    @MediumTest
-    @DisableIf.Build(sdk_is_greater_than = VERSION_CODES.M, sdk_is_less_than = VERSION_CODES.O,
-            message = "Failing on N, see crbug.com/1177383")
-    public void
-    testStrip_enabled_notExpired() throws Exception {
-        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
-        for (int i = 0; i < 3; i++) {
-            createBlankPageWithLaunchType(cta, false, TabLaunchType.FROM_CHROME_UI);
-        }
-        verifyShowingStrip(cta, false, 4);
-
-        // Update the session time so that the disabled state is not expired for next restart.
-        CONDITIONAL_TAB_STRIP_SESSION_TIME_MS.setForTesting(TEST_SESSION_MS);
-        cta = restartChrome();
-        verifyShowingStrip(cta, false, 4);
-    }
-
-    @Test
-    @MediumTest
-    @DisabledTest(message = "crbug.com/1081697")
-    public void testStrip_UndoDismiss() throws Exception {
-        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
-        for (int i = 0; i < 3; i++) {
-            createBlankPageWithLaunchType(cta, false, TabLaunchType.FROM_CHROME_UI);
-        }
-        verifyShowingStrip(cta, false, 4);
-
-        // Dismiss the strip, and then click on the undo snack bar to bring the strip back.
-        clickDismissButtonInStrip();
-        CriteriaHelper.pollInstrumentationThread(TabUiTestHelper::verifyUndoBarShowingAndClickUndo);
-        verifyShowingStrip(cta, false, 4);
-
-        // Update the session time so that the enabled state is not expired for next restart. Verify
-        // that the undo correctly updated the feature status to enabled.
-        CONDITIONAL_TAB_STRIP_SESSION_TIME_MS.setForTesting(TEST_SESSION_MS);
-        cta = restartChrome();
-        verifyShowingStrip(cta, false, 4);
-    }
-
-    @Test
-    @MediumTest
-    @FlakyTest(message = "https://crbug.com/1171567")
-    public void testStrip_InfoBarOptOut() throws Exception {
-        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
-        for (int i = 0; i < 3; i++) {
-            createBlankPageWithLaunchType(cta, false, TabLaunchType.FROM_CHROME_UI);
-        }
-        verifyShowingStrip(cta, false, 4);
-
-        // Initially, the continuous dismiss counter is 0, and dismiss the strip should show undo
-        // snackbar.
-        assertEquals(0, ConditionalTabStripUtils.getContinuousDismissCount());
-        assertTrue(ConditionalTabStripUtils.shouldShowSnackbarForDismissal());
-        clickDismissButtonInStrip();
-        CriteriaHelper.pollUiThread(
-                () -> sActivityTestRule.getActivity().getSnackbarManager().isShowing());
-
-        // Update the dismiss counter so that the next dismissal should be the third continuous
-        // dismissal, and we should show opt-out info bar.
-        ConditionalTabStripUtils.setContinuousDismissCount(1);
-        cta = restartChrome();
-        assertEquals(2, ConditionalTabStripUtils.getContinuousDismissCount());
-        assertFalse(ConditionalTabStripUtils.shouldShowSnackbarForDismissal());
-        createBlankPageWithLaunchType(cta, false, TabLaunchType.FROM_CHROME_UI);
-        verifyShowingStrip(cta, false, 5);
-        clickDismissButtonInStrip();
-        verifyShowingInfoBar(cta);
-
-        // Click the opt-out button should have the feature disabled.
-        assertFalse(ConditionalTabStripUtils.getOptOutIndicator());
-        onView(withId(R.id.button_secondary)).perform(click());
-        assertTrue(ConditionalTabStripUtils.getOptOutIndicator());
-        assertEquals(-1, ConditionalTabStripUtils.getContinuousDismissCount());
-        int oldTabStripPermanentlyHiddenCount = RecordHistogram.getHistogramValueCountForTesting(
-                ConditionalTabStripUtils.UMA_USER_STATUS_RESULT,
-                ConditionalTabStripUtils.UserStatus.TAB_STRIP_PERMANENTLY_HIDDEN);
-        cta = restartChrome();
-        createBlankPageWithLaunchType(cta, false, TabLaunchType.FROM_CHROME_UI);
-        onView(allOf(withParent(withId(R.id.toolbar_container_view)), withId(R.id.tab_list_view)))
-                .check(doesNotExist());
-        int currentTabStripPermanentlyHiddenCount =
-                RecordHistogram.getHistogramValueCountForTesting(
-                        ConditionalTabStripUtils.UMA_USER_STATUS_RESULT,
-                        ConditionalTabStripUtils.UserStatus.TAB_STRIP_PERMANENTLY_HIDDEN);
-        assertEquals(1, currentTabStripPermanentlyHiddenCount - oldTabStripPermanentlyHiddenCount);
-    }
-
-    @Test
-    @MediumTest
-    @FlakyTest(message = "https://crbug.com/1169672")
-    public void testStrip_InfoBarOptIn() throws Exception {
-        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
-        for (int i = 0; i < 3; i++) {
-            createBlankPageWithLaunchType(cta, false, TabLaunchType.FROM_CHROME_UI);
-        }
-        verifyShowingStrip(cta, false, 4);
-
-        // Initially, the continuous dismiss counter is 0, and dismiss the strip should show undo
-        // snackbar.
-        assertEquals(0, ConditionalTabStripUtils.getContinuousDismissCount());
-        assertTrue(ConditionalTabStripUtils.shouldShowSnackbarForDismissal());
-        clickDismissButtonInStrip();
-        CriteriaHelper.pollUiThread(
-                () -> sActivityTestRule.getActivity().getSnackbarManager().isShowing());
-
-        // Update the dismiss counter so that the next dismissal should be the third continuous
-        // dismissal, and we should show opt-out info bar.
-        ConditionalTabStripUtils.setContinuousDismissCount(1);
-        cta = restartChrome();
-        assertEquals(2, ConditionalTabStripUtils.getContinuousDismissCount());
-        assertFalse(ConditionalTabStripUtils.shouldShowSnackbarForDismissal());
-        createBlankPageWithLaunchType(cta, false, TabLaunchType.FROM_CHROME_UI);
-        verifyShowingStrip(cta, false, 5);
-        clickDismissButtonInStrip();
-        verifyShowingInfoBar(cta);
-
-        // Click the opt-in button should set the dismiss counter to -1.
-        onView(withId(R.id.button_primary)).perform(click());
-        assertEquals(-1, ConditionalTabStripUtils.getContinuousDismissCount());
-
-        // Once the counter is set to -1, the counter should no longer be updated by later
-        // dismissals.
-        cta = restartChrome();
-        assertEquals(-1, ConditionalTabStripUtils.getContinuousDismissCount());
-        assertTrue(ConditionalTabStripUtils.shouldShowSnackbarForDismissal());
-        createBlankPageWithLaunchType(cta, false, TabLaunchType.FROM_CHROME_UI);
-        verifyShowingStrip(cta, false, 6);
-        clickDismissButtonInStrip();
-        CriteriaHelper.pollUiThread(
-                () -> sActivityTestRule.getActivity().getSnackbarManager().isShowing());
-    }
-
-    @Test
-    @MediumTest
-    @DisableIf.Build(supported_abis_includes = "x86", message = "https://crbug.com/1094998")
-    public void testStrip_ContinuousDismissCounter() throws Exception {
-        // Mock that the tab strip has been dismissed for two continuous sessions.
-        ConditionalTabStripUtils.setContinuousDismissCount(2);
-
-        // Since strip is not activated in current session, the counter will not be updated.
-        assertEquals(ConditionalTabStripUtils.FeatureStatus.DEFAULT,
-                ConditionalTabStripUtils.getFeatureStatus());
-        ChromeTabbedActivity cta = restartChrome();
-        assertEquals(2, ConditionalTabStripUtils.getContinuousDismissCount());
-
-        // Since the strip was triggered in current session, the counter will be reset to 0 in the
-        // next session.
-        createBlankPageWithLaunchType(cta, false, TabLaunchType.FROM_CHROME_UI);
-        verifyShowingStrip(cta, false, 2);
-        assertEquals(ConditionalTabStripUtils.FeatureStatus.ACTIVATED,
-                ConditionalTabStripUtils.getFeatureStatus());
-        cta = restartChrome();
-        assertEquals(0, ConditionalTabStripUtils.getContinuousDismissCount());
-
-        // Dismiss the strip in current session.
-        createBlankPageWithLaunchType(cta, false, TabLaunchType.FROM_CHROME_UI);
-        verifyShowingStrip(cta, false, 3);
-        clickDismissButtonInStrip();
-        CriteriaHelper.pollUiThread(
-                () -> sActivityTestRule.getActivity().getSnackbarManager().isShowing());
-
-        // Update the dismiss counter so that the next dismissal should be the sixth continuous
-        // dismissal, and we should show opt-out info bar.
-        ConditionalTabStripUtils.setContinuousDismissCount(4);
-        cta = restartChrome();
-        assertEquals(5, ConditionalTabStripUtils.getContinuousDismissCount());
-        createBlankPageWithLaunchType(cta, false, TabLaunchType.FROM_CHROME_UI);
-        verifyShowingStrip(cta, false, 4);
-        clickDismissButtonInStrip();
-        verifyShowingInfoBar(cta);
-
-        // Click the info bar close button to dismiss the info bar.
-        onView(withId(R.id.infobar_close_button)).perform(click());
-        CriteriaHelper.pollUiThread(() -> {
-            InfoBarContainer container = InfoBarContainer.get(
-                    sActivityTestRule.getActivity().getTabModelSelector().getCurrentTab());
-            return container.getInfoBarsForTesting().size() == 0;
-        });
-
-        // We no longer keep the dismiss counter when user has dismissed the strip continuously for
-        // 6 sessions, i.e. dismiss the opt-out info bar twice.
-        restartChrome();
-        assertEquals(-1, ConditionalTabStripUtils.getContinuousDismissCount());
-    }
-
-    @Test
-    @MediumTest
-    public void testUndoClosure_AccessibilityMode() throws Exception {
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> ChromeAccessibilityUtil.get().setAccessibilityEnabledForTesting(true));
-        ChromeTabbedActivity cta = sActivityTestRule.getActivity();
-        SnackbarManager snackbarManager = sActivityTestRule.getActivity().getSnackbarManager();
-        createTabs(cta, false, 3);
-        verifyShowingStrip(cta, false, 3);
-        verifyStripSelectedPosition(cta, 2);
-        assertNull(snackbarManager.getCurrentSnackbarForTesting());
-
-        // Click the selected item in strip to close a tab. The undo snack bar should show, and
-        // clicking on the snack bar button should undo the closure.
-        clickNthItemInStrip(2);
-        verifyShowingStrip(cta, false, 2);
-        assertTrue(snackbarManager.getCurrentSnackbarForTesting().getController()
-                           instanceof UndoBarController);
-        CriteriaHelper.pollInstrumentationThread(TabUiTestHelper::verifyUndoBarShowingAndClickUndo);
-        verifyShowingStrip(cta, false, 3);
-        verifyStripSelectedPosition(cta, 2);
-
-        // The undo snack bar should still work after entering overview mode.
-        clickNthItemInStrip(2);
-        verifyShowingStrip(cta, false, 2);
-        assertTrue(snackbarManager.getCurrentSnackbarForTesting().getController()
-                           instanceof UndoBarController);
-        enterTabSwitcher(cta);
-        verifyHidingStrip();
-        assertNotNull(snackbarManager.getCurrentSnackbarForTesting());
-        assertEquals(3, getAccessibilityOverviewList().getCount());
-        verifyAccessibilityTabClosing(2, true);
-        CriteriaHelper.pollInstrumentationThread(TabUiTestHelper::verifyUndoBarShowingAndClickUndo);
-        verifyAccessibilityTabClosing(2, false);
-
-        // The undo snack bar should not show when closure happens in accessibility tab switcher.
-        AccessibilityTabModelListItem item = getAccessibilityOverviewListItem(0);
-        verifyAccessibilityTabClosing(0, false);
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> item.findViewById(R.id.end_button).performClick());
-        assertNull(snackbarManager.getCurrentSnackbarForTesting());
-        verifyAccessibilityTabClosing(0, true);
-        assertEquals(3, getAccessibilityOverviewList().getCount());
-    }
-
-    private void verifyAccessibilityTabClosing(int index, boolean isClosing) {
-        CriteriaHelper.pollUiThread(() -> {
-            AccessibilityTabModelListItem item = getAccessibilityOverviewListItem(index);
-            Criteria.checkThat(item.findViewById(R.id.undo_contents).getVisibility(),
-                    Matchers.is(isClosing ? View.VISIBLE : View.INVISIBLE));
-        });
-    }
-
-    private ChromeTabbedActivity restartChrome() throws Exception {
-        TabUiTestHelper.finishActivity(sActivityTestRule.getActivity());
-        sActivityTestRule.startMainActivityFromLauncher();
-        // Wait for bottom controls to stabilize.
-        CriteriaHelper.pollUiThread(() -> {
-            Criteria.checkThat(sActivityTestRule.getActivity()
-                                       .getBrowserControlsManager()
-                                       .getBottomControlOffset(),
-                    Matchers.is(0));
-        });
-        return sActivityTestRule.getActivity();
-    }
-
-    private void createBlankPageWithLaunchType(ChromeTabbedActivity cta, boolean isIncognito,
-            @TabLaunchType int type) throws ExecutionException {
-        TabCreator tabCreator =
-                TestThreadUtils.runOnUiThreadBlocking(() -> cta.getTabCreator(isIncognito));
-        LoadUrlParams loadUrlParams = new LoadUrlParams(UrlConstants.CHROME_BLANK_URL);
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> tabCreator.createNewTab(loadUrlParams, type, null));
-    }
-
-    private void verifyHidingStrip() {
-        onView(allOf(withParent(withId(R.id.toolbar_container_view)), withId(R.id.tab_list_view)))
-                .check(matches(not(isDisplayed())));
-    }
-
-    private void verifyShowingStrip(ChromeTabbedActivity cta, boolean isIncognito, int tabCount) {
-        onView(allOf(withParent(withId(R.id.toolbar_container_view)), withId(R.id.tab_list_view)))
-                .check(matches(isDisplayed()));
-        verifyTabStripFaviconCount(cta, tabCount);
-        TabModel tabModel = cta.getTabModelSelector().getModel(isIncognito);
-        assertEquals(isIncognito, cta.getTabModelSelector().isIncognitoSelected());
-        assertEquals(tabCount, tabModel.getCount());
-    }
-
-    private void switchTabModel(ChromeTabbedActivity cta, boolean isIncognito) {
-        assertTrue(cta.getOverviewModeBehavior().overviewVisible());
-        TestThreadUtils.runOnUiThreadBlocking(isIncognito ? mSwipeToIncognito : mSwipeToNormal);
-        // Wait until the target stack is visible.
-        Stack stack = getStack(cta.getLayoutManager(), isIncognito);
-        LayoutTab layoutTab = stack.getTabs()[0].getLayoutTab();
-        CriteriaHelper.pollUiThread(
-                () -> layoutTab.getX() > 0 && layoutTab.getX() < mTabsViewWidthDp);
-    }
-
-    private void clickOnStackTabAtIndex(int index, boolean isIncognito) {
-        LayoutManagerChrome layoutManager = updateTabsViewSize();
-        float[] coordinates = getStackTabClickTarget(index, isIncognito);
-        float clickX = coordinates[0];
-        float clickY = coordinates[1];
-
-        OverviewModeBehaviorWatcher overviewModeWatcher =
-                new OverviewModeBehaviorWatcher(layoutManager, false, true);
-
-        TestThreadUtils.runOnUiThreadBlocking(
-                new SimulateClickOnMainThread(layoutManager, (int) clickX, (int) clickY));
-        overviewModeWatcher.waitForBehavior();
-    }
-
-    private void closeStackTabAtIndex(ChromeTabbedActivity cta, int index, boolean isIncognito) {
-        LayoutManagerChrome layoutManager = updateTabsViewSize();
-        StackLayout layout = (StackLayout) layoutManager.getOverviewLayout();
-        Stack stack = layout.getTabStackAtIndex(
-                isIncognito ? StackLayout.INCOGNITO_STACK_INDEX : StackLayout.NORMAL_STACK_INDEX);
-        assertTrue(
-                "try to close tab at invalid index", index < stack.getTabs().length && index >= 0);
-        LayoutTab layoutTab = stack.getTabs()[index].getLayoutTab();
-        float x = stack.getCloseBoundsOnLayoutTab(layoutTab).centerX();
-        float y = stack.getCloseBoundsOnLayoutTab(layoutTab).centerY();
-        ChromeTabUtils.closeTabWithAction(InstrumentationRegistry.getInstrumentation(), cta,
-                ()
-                        -> TestThreadUtils.runOnUiThreadBlocking(
-                                new SimulateClickOnMainThread(layoutManager, x, y)));
-    }
-
-    private void verifyStripSelectedPosition(ChromeTabbedActivity cta, int index) {
-        assertEquals(cta.getCurrentTabModel().index(), index);
-        // Since View.getForeground() is not supported in 23-, there is not good way for us to
-        // check the selected item from the perspective of Android View. Therefore, skip this check
-        // for API below 23.
-        if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP_MR1) {
-            return;
-        }
-        onView(allOf(withParent(withId(R.id.toolbar_container_view)), withId(R.id.tab_list_view)))
-                .check(matches(isDisplayed()))
-                .check((v, e) -> {
-                    RecyclerView recyclerView = (RecyclerView) v;
-                    RecyclerView.Adapter adapter = recyclerView.getAdapter();
-                    for (int i = 0; i < adapter.getItemCount(); i++) {
-                        View itemView = recyclerView.findViewHolderForAdapterPosition(i).itemView;
-                        if (itemView.getForeground() != null) {
-                            assertEquals(index, i);
-                        }
-                    }
-                });
-    }
-
-    private void clickPlusButtonOnStrip() {
-        onView(allOf(withParent(withId(R.id.main_content)), withId(R.id.toolbar_right_button)))
-                .perform(click());
-    }
-
-    private void clickNthItemInStrip(int index) {
-        onView(allOf(withParent(withId(R.id.toolbar_container_view)), withId(R.id.tab_list_view)))
-                .check(matches(isDisplayed()))
-                .perform(RecyclerViewActions.actionOnItemAtPosition(index, click()));
-    }
-
-    private void clickDismissButtonInStrip() {
-        onView(allOf(withParent(withId(R.id.main_content)), withId(R.id.toolbar_left_button)))
-                .perform(click());
-    }
-
-    private void triggerStripAndDismiss(ChromeTabbedActivity cta) {
-        int normalTabCount = cta.getTabModelSelector().getModel(false).getCount();
-        createTabs(cta, false, 3);
-        verifyShowingStrip(cta, false, normalTabCount + 2);
-
-        // Click the left button should dismiss the tab strip.
-        clickDismissButtonInStrip();
-        verifyHidingStrip();
-    }
-
-    private void verifyShowingInfoBar(ChromeTabbedActivity cta) {
-        CriteriaHelper.pollUiThread(() -> {
-            InfoBarContainer container =
-                    InfoBarContainer.get(cta.getTabModelSelector().getCurrentTab());
-            return container.getVisibility() == View.VISIBLE && !container.isAnimating();
-        });
-        Context context = (Context) cta;
-        onView(withId(R.id.infobar_message))
-                .check(matches(withText(
-                        containsString(context.getString(R.string.tab_strip_info_bar_question)))));
-        onView(withId(R.id.button_primary))
-                .check(matches(withText(
-                        containsString(context.getString(R.string.tab_strip_info_bar_reshow)))));
-        onView(withId(R.id.button_secondary))
-                .check(matches(withText(
-                        containsString(context.getString(R.string.tab_strip_info_bar_no_reshow)))));
-    }
-
-    // Utility methods copied from TabsTest.java.
-    // TODO(yuezhanggg): Pull out these methods into a separate utility class and share them with
-    // TabsTest.
-    private float[] getStackTabClickTarget(final int tabIndexToSelect, final boolean isIncognito) {
-        final LayoutManagerChrome layoutManager = updateTabsViewSize();
-        final float[] target = new float[2];
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Stack stack = getStack(layoutManager, isIncognito);
-            StackTab[] tabs = stack.getTabs();
-            // The position of the click is expressed from the top left corner of the content.
-            // The aim is to find an offset that is inside the content but not on the close
-            // button.  For this, we calculate the center of the visible tab area.
-            LayoutTab layoutTab = tabs[tabIndexToSelect].getLayoutTab();
-            LayoutTab nextLayoutTab = (tabIndexToSelect + 1) < tabs.length
-                    ? tabs[tabIndexToSelect + 1].getLayoutTab()
-                    : null;
-
-            float tabOffsetX = layoutTab.getX();
-            float tabOffsetY = layoutTab.getY();
-            float tabRightX = tabOffsetX + layoutTab.getScaledContentWidth();
-            float tabBottomY = nextLayoutTab != null
-                    ? nextLayoutTab.getY()
-                    : tabOffsetY + layoutTab.getScaledContentHeight();
-            tabRightX = Math.min(tabRightX, mTabsViewWidthDp);
-            tabBottomY = Math.min(tabBottomY, mTabsViewHeightDp);
-
-            target[0] = (tabOffsetX + tabRightX) / 2.0f;
-            target[1] = (tabOffsetY + tabBottomY) / 2.0f;
-        });
-        return target;
-    }
-
-    private Stack getStack(final LayoutManagerChrome layoutManager, boolean isIncognito) {
-        LayoutManagerChromePhone layoutManagerPhone = (LayoutManagerChromePhone) layoutManager;
-        StackLayout layout = (StackLayout) layoutManagerPhone.getOverviewLayout();
-        return (layout).getTabStackAtIndex(
-                isIncognito ? StackLayout.INCOGNITO_STACK_INDEX : StackLayout.NORMAL_STACK_INDEX);
-    }
-
-    private LayoutManagerChrome updateTabsViewSize() {
-        View tabsView = sActivityTestRule.getActivity().getTabsView();
-        mTabsViewHeightDp = tabsView.getHeight() * mPxToDp;
-        mTabsViewWidthDp = tabsView.getWidth() * mPxToDp;
-        return sActivityTestRule.getActivity().getLayoutManager();
-    }
-
-    // Utility methods from OverviewListLayoutTest.java.
-    private ListView getAccessibilityOverviewList() {
-        AccessibilityTabModelWrapper container =
-                ((OverviewListLayout) sActivityTestRule.getActivity().getOverviewListLayout())
-                        .getContainer();
-        return (ListView) container.findViewById(R.id.list_view);
-    }
-
-    private AccessibilityTabModelListItem getAccessibilityOverviewListItem(int index) {
-        return (AccessibilityTabModelListItem) getAccessibilityOverviewList().getChildAt(index);
-    }
-}
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
index 3d611fa1..6e06ea3 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
@@ -68,7 +68,6 @@
 import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter;
 import org.chromium.chrome.browser.theme.ThemeColorProvider;
 import org.chromium.chrome.browser.toolbar.bottom.BottomControlsCoordinator;
-import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.tab_ui.R;
 import org.chromium.chrome.test.util.browser.Features;
@@ -881,405 +880,6 @@
         verifyResetStrip(false, null);
     }
 
-    /*********************** Conditional tab strip related tests *************************/
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void verifyInitialization_CTS() {
-        initAndAssertProperties(mTab1);
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void onClickAdd_CTS() {
-        initAndAssertProperties(mTab1);
-
-        View.OnClickListener listener =
-                mModel.get(TabGroupUiProperties.RIGHT_BUTTON_ON_CLICK_LISTENER);
-        assertThat(listener, instanceOf(View.OnClickListener.class));
-
-        listener.onClick(mView);
-
-        verify(mTabCreator)
-                .createNewTab(isA(LoadUrlParams.class), eq(TabLaunchType.FROM_CHROME_UI), eq(null));
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void onClickDismiss_CTS() {
-        initAndAssertProperties(mTab1);
-
-        View.OnClickListener listener =
-                mModel.get(TabGroupUiProperties.LEFT_BUTTON_ON_CLICK_LISTENER);
-        assertThat(listener, instanceOf(View.OnClickListener.class));
-
-        listener.onClick(mView);
-
-        verifyResetStrip(false, null);
-        assertThat(mTabGroupUiMediator.getConditionalTabStripFeatureStatusForTesting(),
-                equalTo(FeatureStatus.FORBIDDEN));
-        verify(mSnackbarManager).showSnackbar(any(Snackbar.class));
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void tabSelection_FromAddition_CTS() {
-        initAndAssertProperties(mTab1);
-
-        mTabModelObserverArgumentCaptor.getValue().didSelectTab(
-                mTab2, TabSelectionType.FROM_NEW, TAB1_ID);
-
-        // Strip should not be showing since this is a selection due to addition.
-        verifyResetStrip(false, null);
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void tabSelection_SameTab_CTS() {
-        initAndAssertProperties(mTab1);
-
-        mTabModelObserverArgumentCaptor.getValue().didSelectTab(
-                mTab1, TabSelectionType.FROM_USER, TAB1_ID);
-
-        // Strip should not be showing since this is a selection of the same tab.
-        verifyResetStrip(false, null);
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void tabSelection_SameTab_NotDismissSnackbar_CTS() {
-        initAndAssertProperties(mTab1);
-
-        // Mock that undo snackbar is showing.
-        doReturn(true).when(mSnackbarManager).isShowing();
-
-        // Select the same tab.
-        mTabModelObserverArgumentCaptor.getValue().didSelectTab(
-                mTab1, TabSelectionType.FROM_USER, TAB1_ID);
-
-        // Verify that snackbar is not dismissed since there is no different tab selection.
-        verify(mSnackbarManager, never()).dismissSnackbars(eq(mTabGroupUiMediator));
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void tabSelection_DifferentTab_DismissSnackbar_CTS() {
-        initAndAssertProperties(mTab1);
-
-        // Mock that undo snackbar is showing.
-        doReturn(true).when(mSnackbarManager).isShowing();
-
-        // Select a different tab.
-        mTabModelObserverArgumentCaptor.getValue().didSelectTab(
-                mTab1, TabSelectionType.FROM_USER, TAB2_ID);
-
-        // Verify that snackbar is dismissed when a different tab is selected.
-        verify(mSnackbarManager).dismissSnackbars(eq(mTabGroupUiMediator));
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void tabSelection_AfterAddition_CTS() {
-        initAndAssertProperties(mTab1);
-
-        // When a tab is created from clicking the web content, there will be two subsequent
-        // didSelectTab calls, one with type TabSelectionType.FROM_NEW the other with type
-        // TabSelectionType.FROM_USER. We should skip this type of selection signal since it might
-        // be an unintentional tab interaction.
-        mTabModelObserverArgumentCaptor.getValue().didSelectTab(
-                mTab2, TabSelectionType.FROM_NEW, TAB1_ID);
-        verifyResetStrip(false, null);
-
-        mTabModelObserverArgumentCaptor.getValue().didSelectTab(
-                mTab2, TabSelectionType.FROM_USER, TAB1_ID);
-        verifyResetStrip(false, null);
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void tabSelection_FromUser_CTS() {
-        initAndAssertProperties(mTab1);
-
-        mTabModelObserverArgumentCaptor.getValue().didSelectTab(
-                mTab2, TabSelectionType.FROM_USER, TAB1_ID);
-        verifyResetStrip(true, mAllTabsList);
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void tabClosure_NotLastTab_CTS() {
-        initAndAssertProperties(mTab1);
-
-        // Trigger tab strip with a selection.
-        mTabModelObserverArgumentCaptor.getValue().didSelectTab(
-                mTab2, TabSelectionType.FROM_USER, TAB1_ID);
-        verifyResetStrip(true, mAllTabsList);
-
-        // Close tab1 and there are two tabs left.
-        mTabModelObserverArgumentCaptor.getValue().willCloseTab(mTab1, false);
-        verifyNeverReset();
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void tabClosure_LastTab_CTS() {
-        initAndAssertProperties(mTab1);
-
-        // Trigger tab strip with a selection.
-        mTabModelObserverArgumentCaptor.getValue().didSelectTab(
-                mTab2, TabSelectionType.FROM_USER, TAB1_ID);
-        verifyResetStrip(true, mAllTabsList);
-
-        // Close tab2 and tab3 so that there is only one tab left.
-        mTabModelObserverArgumentCaptor.getValue().willCloseTab(mTab3, false);
-        verifyNeverReset();
-        doReturn(2).when(mTabModel).getCount();
-        mTabModelObserverArgumentCaptor.getValue().willCloseTab(mTab2, false);
-        verifyResetStrip(false, null);
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void tabAddition_Unintentional_CTS() {
-        initAndAssertProperties(mTab1);
-
-        TabImpl newTab = prepareTab(TAB4_ID, TAB4_ID);
-        mTabModelObserverArgumentCaptor.getValue().didAddTab(
-                newTab, TabLaunchType.FROM_EXTERNAL_APP, TabCreationState.LIVE_IN_FOREGROUND);
-
-        verifyResetStrip(false, null);
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void tabAddition_FromUI_CTS() {
-        initAndAssertProperties(mTab1);
-
-        TabImpl newTab = prepareTab(TAB4_ID, TAB4_ID);
-        doReturn(4).when(mTabModel).getCount();
-        doReturn(newTab).when(mTabModel).getTabAt(3);
-        mAllTabsList.add(newTab);
-
-        // The reset will be triggered by the subsequent tab selection instead of tab addition.
-        mTabModelObserverArgumentCaptor.getValue().didAddTab(
-                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
-        verifyNeverReset();
-        mTabModelObserverArgumentCaptor.getValue().didSelectTab(
-                newTab, TabLaunchType.FROM_CHROME_UI, TAB1_ID);
-        verifyResetStrip(true, mAllTabsList);
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void tabAddition_FromLongPressBackground_CTS() {
-        initAndAssertProperties(mTab1);
-
-        TabImpl newTab = prepareTab(TAB4_ID, TAB4_ID);
-        doReturn(4).when(mTabModel).getCount();
-        doReturn(newTab).when(mTabModel).getTabAt(3);
-        mAllTabsList.add(newTab);
-
-        // The reset will be triggered by tab addition because there is no subsequent selection.
-        mTabModelObserverArgumentCaptor.getValue().didAddTab(newTab,
-                TabLaunchType.FROM_LONGPRESS_BACKGROUND, TabCreationState.LIVE_IN_FOREGROUND);
-        verifyResetStrip(true, mAllTabsList);
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void restoreCompleted_NotTrigger_CTS() {
-        initAndAssertProperties(mTab1);
-        // Assume that the tab model is being restored. Also, the overview
-        // mode is invisible when restoring is completed.
-        doReturn(POSITION1).when(mTabModel).index();
-        doReturn(mTab1).when(mTabModelSelector).getCurrentTab();
-        doReturn(false).when(mOverviewModeBehavior).overviewVisible();
-
-        // Simulate restore finished.
-        mTabModelObserverArgumentCaptor.getValue().restoreCompleted();
-
-        verifyResetStrip(false, null);
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void tabClosureUndone_UiVisible_NotShowingOverviewMode_CTS() {
-        initAndAssertProperties(mTab1);
-        // OverviewMode is hiding by default.
-        assertThat(mTabGroupUiMediator.getIsShowingOverViewModeForTesting(), equalTo(false));
-
-        // Trigger tab strip with a selection.
-        mTabModelObserverArgumentCaptor.getValue().didSelectTab(
-                mTab2, TabSelectionType.FROM_USER, TAB1_ID);
-        verifyResetStrip(true, mAllTabsList);
-
-        // Simulate that we undo the closure of mTab3.
-        mTabModelObserverArgumentCaptor.getValue().tabClosureUndone(mTab3);
-
-        // Since the strip is already visible, no resetting.
-        verifyNeverReset();
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void tabClosureUndone_UiNotVisible_ShowingOverviewMode_CTS() {
-        // Assume mTab1 is selected.
-        initAndAssertProperties(mTab1);
-        // OverviewMode is hiding by default.
-        assertThat(mTabGroupUiMediator.getIsShowingOverViewModeForTesting(), equalTo(false));
-
-        // Simulate the overview mode is showing, which hides the strip.
-        mOverviewModeObserverArgumentCaptor.getValue().onOverviewModeStartedShowing(true);
-        assertThat(mTabGroupUiMediator.getIsShowingOverViewModeForTesting(), equalTo(true));
-        verifyResetStrip(false, null);
-
-        // Simulate that we undo the closure of mTab3.
-        mTabModelObserverArgumentCaptor.getValue().tabClosureUndone(mTab3);
-
-        // Since overview mode is showing, we should not show strip.
-        verifyResetStrip(false, null);
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void overViewStartedShowing_CTS() {
-        initAndAssertProperties(mTab1);
-
-        mOverviewModeObserverArgumentCaptor.getValue().onOverviewModeStartedShowing(true);
-
-        // Showing overview should activate the feature and hide the strip.
-        assertThat(mTabGroupUiMediator.getConditionalTabStripFeatureStatusForTesting(),
-                equalTo(FeatureStatus.ACTIVATED));
-        verifyResetStrip(false, null);
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void overViewFinishedHiding_CTS() {
-        initAndAssertProperties(mTab1);
-
-        // Show the overview first to activate feature.
-        mOverviewModeObserverArgumentCaptor.getValue().onOverviewModeStartedShowing(true);
-        assertThat(mTabGroupUiMediator.getConditionalTabStripFeatureStatusForTesting(),
-                equalTo(FeatureStatus.ACTIVATED));
-        verifyResetStrip(false, null);
-
-        // Hide the overview should trigger tab strip show.
-        mOverviewModeObserverArgumentCaptor.getValue().onOverviewModeFinishedHiding();
-        verifyResetStrip(true, mAllTabsList);
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void onPauseWithNative_CTS() {
-        initAndAssertProperties(mTab1);
-
-        mPauseResumeWithNativeObserverArgumentCaptor.getValue().onPauseWithNative();
-
-        verifyResetStrip(false, null);
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void onResumeWithNative_featureActivated_CTS() {
-        initAndAssertProperties(mTab1);
-
-        ConditionalTabStripUtils.setFeatureStatus(FeatureStatus.ACTIVATED);
-        mPauseResumeWithNativeObserverArgumentCaptor.getValue().onResumeWithNative();
-
-        verifyResetStrip(true, mAllTabsList);
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void onResumeWithNative_featureForbidden_CTS() {
-        initAndAssertProperties(mTab1);
-
-        ConditionalTabStripUtils.setFeatureStatus(FeatureStatus.FORBIDDEN);
-        mPauseResumeWithNativeObserverArgumentCaptor.getValue().onResumeWithNative();
-
-        verifyResetStrip(false, null);
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void onResumeWithNative_featureDefault_CTS() {
-        initAndAssertProperties(mTab1);
-
-        ConditionalTabStripUtils.setFeatureStatus(FeatureStatus.DEFAULT);
-        mPauseResumeWithNativeObserverArgumentCaptor.getValue().onResumeWithNative();
-
-        verifyResetStrip(false, null);
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void onResumeWithNative_featureActivated_ShowingOverviewMode_CTS() {
-        initAndAssertProperties(mTab1);
-
-        // Mock that the overview mode is showing.
-        mOverviewModeObserverArgumentCaptor.getValue().onOverviewModeStartedShowing(true);
-        verifyResetStrip(false, null);
-        assertThat(mTabGroupUiMediator.getIsShowingOverViewModeForTesting(), equalTo(true));
-
-        // When overview mode is showing before native resume, i,e. ReturnToClank enabled, strip
-        // should not be showing.
-        ConditionalTabStripUtils.setFeatureStatus(FeatureStatus.ACTIVATED);
-        mPauseResumeWithNativeObserverArgumentCaptor.getValue().onResumeWithNative();
-
-        verifyResetStrip(false, null);
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void destroy_CTS() {
-        initAndAssertProperties(mTab1);
-
-        mTabGroupUiMediator.destroy();
-
-        verify(mTabModelFilterProvider)
-                .removeTabModelFilterObserver(mTabModelObserverArgumentCaptor.capture());
-        verify(mOverviewModeBehavior)
-                .removeOverviewModeObserver(mOverviewModeObserverArgumentCaptor.capture());
-        verify(mThemeColorProvider)
-                .removeThemeColorObserver(mThemeColorObserverArgumentCaptor.capture());
-        verify(mThemeColorProvider).removeTintObserver(mTintObserverArgumentCaptor.capture());
-        verify(mTabModelSelector).removeObserver(mTabModelSelectorObserverArgumentCaptor.capture());
-        verify(mTabGroupModelFilter, never())
-                .removeTabGroupObserver(mTabGroupModelFilterObserverArgumentCaptor.capture());
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void switchTabModel_CTS() {
-        initAndAssertProperties(mTab1);
-        assertThat(mTabGroupUiMediator.getIsShowingOverViewModeForTesting(), equalTo(false));
-        TabModel incognitoTabModel = prepareIncognitoTabModel();
-
-        // Trigger tab strip with a selection.
-        mTabModelObserverArgumentCaptor.getValue().didSelectTab(
-                mTab2, TabSelectionType.FROM_USER, TAB1_ID);
-        verifyResetStrip(true, mAllTabsList);
-
-        mTabModelSelectorObserverArgumentCaptor.getValue().onTabModelSelected(
-                mTabModel, incognitoTabModel);
-
-        verify(mSnackbarManager).dismissSnackbars(eq(mTabGroupUiMediator));
-        verifyResetStrip(true, mAllTabsList);
-    }
-
-    @Test
-    @Features.EnableFeatures(ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID)
-    public void testUndoSnackbar_action() {
-        initAndAssertProperties(mTab1);
-        assertThat(ConditionalTabStripUtils.getFeatureStatus(), equalTo(FeatureStatus.DEFAULT));
-
-        mTabGroupUiMediator.onAction(mock(Object.class));
-
-        verifyResetStrip(true, mAllTabsList);
-        assertThat(ConditionalTabStripUtils.getFeatureStatus(), equalTo(FeatureStatus.ACTIVATED));
-    }
-
     /*********************** Class common tests *************************/
 
     @Test
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
index 1c2bf2e..7d7c692 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
@@ -33,8 +33,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import static org.chromium.chrome.browser.flags.ChromeFeatureList.CONDITIONAL_TAB_STRIP_ANDROID;
-import static org.chromium.chrome.browser.flags.ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID;
 import static org.chromium.chrome.browser.flags.ChromeFeatureList.TAB_GROUPS_ANDROID;
 import static org.chromium.chrome.browser.flags.ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID;
 import static org.chromium.chrome.browser.tasks.tab_management.MessageCardViewProperties.MESSAGE_TYPE;
@@ -106,7 +104,6 @@
 import org.chromium.chrome.browser.tab.TabImpl;
 import org.chromium.chrome.browser.tab.TabLaunchType;
 import org.chromium.chrome.browser.tab.TabObserver;
-import org.chromium.chrome.browser.tab.TabSelectionType;
 import org.chromium.chrome.browser.tab.state.CriticalPersistedTabData;
 import org.chromium.chrome.browser.tab.state.PersistedTabDataConfiguration;
 import org.chromium.chrome.browser.tab.state.ShoppingPersistedTabData;
@@ -896,27 +893,6 @@
     }
 
     @Test
-    @Features.EnableFeatures({CONDITIONAL_TAB_STRIP_ANDROID})
-    @Features.DisableFeatures({TAB_GRID_LAYOUT_ANDROID, TAB_GROUPS_ANDROID})
-    public void tabClosureUndone_CTS() {
-        initAndAssertAllProperties();
-
-        TabImpl newTab = prepareTab(TAB3_ID, TAB3_TITLE, TAB3_URL);
-        doReturn(3).when(mTabModel).getCount();
-        doReturn(newTab).when(mTabModel).getTabAt(2);
-        doReturn(Arrays.asList(mTab1, mTab2, newTab))
-                .when(mTabModelFilter)
-                .getRelatedTabList(eq(TAB1_ID));
-
-        mTabModelObserverCaptor.getValue().tabClosureUndone(newTab);
-
-        assertThat(mModel.size(), equalTo(3));
-        assertThat(mModel.get(2).model.get(TabProperties.TAB_ID), equalTo(TAB3_ID));
-        assertThat(mModel.get(2).model.get(TabProperties.TITLE), equalTo(TAB3_TITLE));
-        verify(mTabModel).setIndex(eq(2), eq(TabSelectionType.FROM_USER));
-    }
-
-    @Test
     public void tabMergeIntoGroup() {
         setUpForTabGroupOperation(TabListMediatorType.TAB_SWITCHER);
 
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilitiesUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilitiesUnitTest.java
index e30bc0e..140fb05a 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilitiesUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabUiFeatureUtilitiesUnitTest.java
@@ -67,31 +67,6 @@
         SysUtils.resetForTesting();
     }
 
-    @Test
-    // clang-format off
-    @Features.DisableFeatures({ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID,
-                                ChromeFeatureList.TAB_GROUPS_ANDROID,
-                                ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID})
-    public void testCacheGridTabSwitcher_HighEnd_NoEnabledFlags() {
-        // clang-format on
-        when(mCommandLine.hasSwitch(BaseSwitches.DISABLE_LOW_END_DEVICE_MODE)).thenReturn(true);
-        cacheFeatureFlags();
-
-        CachedFeatureFlags.resetFlagsForTesting();
-        assertFalse(TabUiFeatureUtilities.isGridTabSwitcherEnabled());
-        assertFalse(TabUiFeatureUtilities.isTabGroupsAndroidEnabled());
-        assertFalse(TabUiFeatureUtilities.isTabGroupsAndroidContinuationEnabled());
-
-        setAccessibilityEnabledForTesting(true);
-        DeviceClassManager.resetForTesting();
-        cacheFeatureFlags();
-
-        CachedFeatureFlags.resetFlagsForTesting();
-        assertFalse(TabUiFeatureUtilities.isGridTabSwitcherEnabled());
-        assertFalse(TabUiFeatureUtilities.isTabGroupsAndroidEnabled());
-        assertFalse(TabUiFeatureUtilities.isTabGroupsAndroidContinuationEnabled());
-    }
-
     private void cacheFeatureFlags() {
         List<String> featuresToCache = Arrays.asList(ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID,
                 ChromeFeatureList.TAB_GROUPS_ANDROID,
@@ -274,30 +249,6 @@
     @Features.EnableFeatures({ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID})
     @Features.DisableFeatures({ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID,
                                 ChromeFeatureList.TAB_GROUPS_ANDROID})
-    public void testCacheGridTabSwitcher_HighEnd_Continuation() {
-        // clang-format on
-        when(mCommandLine.hasSwitch(BaseSwitches.DISABLE_LOW_END_DEVICE_MODE)).thenReturn(true);
-        cacheFeatureFlags();
-
-        CachedFeatureFlags.resetFlagsForTesting();
-        assertFalse(TabUiFeatureUtilities.isGridTabSwitcherEnabled());
-        assertFalse(TabUiFeatureUtilities.isTabGroupsAndroidEnabled());
-        assertFalse(TabUiFeatureUtilities.isTabGroupsAndroidContinuationEnabled());
-
-        setAccessibilityEnabledForTesting(true);
-        DeviceClassManager.resetForTesting();
-        cacheFeatureFlags();
-
-        assertFalse(TabUiFeatureUtilities.isGridTabSwitcherEnabled());
-        assertFalse(TabUiFeatureUtilities.isTabGroupsAndroidEnabled());
-        assertFalse(TabUiFeatureUtilities.isTabGroupsAndroidContinuationEnabled());
-    }
-
-    @Test
-    // clang-format off
-    @Features.EnableFeatures({ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID})
-    @Features.DisableFeatures({ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID,
-                                ChromeFeatureList.TAB_GROUPS_ANDROID})
     public void testCacheGridTabSwitcher_LowEnd_Continuation() {
         // clang-format on
         when(mCommandLine.hasSwitch(BaseSwitches.ENABLE_LOW_END_DEVICE_MODE)).thenReturn(true);
diff --git a/chrome/android/features/tab_ui/tab_management_java_sources.gni b/chrome/android/features/tab_ui/tab_management_java_sources.gni
index a674624..dbcd1362 100644
--- a/chrome/android/features/tab_ui/tab_management_java_sources.gni
+++ b/chrome/android/features/tab_ui/tab_management_java_sources.gni
@@ -32,7 +32,6 @@
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/TrendyTermsCoordinatorTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/TrendyTermsViewBinderTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/AssertsTest.java",
-  "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/ConditionalTabStripTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardViewBinderTest.java",
   "//chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/PriceTrackingDialogTest.java",
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/HeaderIphScrollListener.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/HeaderIphScrollListener.java
index 4cd8985..135c2e8 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/HeaderIphScrollListener.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/HeaderIphScrollListener.java
@@ -4,7 +4,6 @@
 
 package org.chromium.chrome.browser.feed;
 
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.ntp.ScrollListener;
 import org.chromium.chrome.browser.ntp.ScrollListener.ScrollState;
 import org.chromium.chrome.browser.ntp.ScrollableContainerDelegate;
@@ -28,14 +27,13 @@
  * that the user wants to interact with the feed are strong.
  */
 public class HeaderIphScrollListener implements ScrollListener {
-    static final String TOOLBAR_TRANSITION_FRACTION_PARAM_NAME = "toolbar-transition-fraction";
-    static final String MIN_SCROLL_FRACTION_PARAM_NAME = "min-scroll-fraction";
-    static final String HEADER_MAX_POSITION_FRACTION_NAME = "header-max-pos-fraction";
+    private static final float MIN_SCROLL_FRACTION = 0.1f;
+    private static final float MAX_HEADER_POS_FRACTION = 0.35f;
 
     /**
      * Delegate to handle actions that are out of the scope of the listener.
      */
-    public static interface Delegate {
+    public interface Delegate {
         /**
          * Gets the feature engagement tracker.
          */
@@ -74,11 +72,8 @@
         mDelegate = delegate;
         mScrollableContainerDelegate = scrollableContainerDelegate;
 
-        mMinScrollFraction = (float) ChromeFeatureList.getFieldTrialParamByFeatureAsDouble(
-                ChromeFeatureList.REPORT_FEED_USER_ACTIONS, MIN_SCROLL_FRACTION_PARAM_NAME, 0.10);
-        mHeaderMaxPosFraction = (float) ChromeFeatureList.getFieldTrialParamByFeatureAsDouble(
-                ChromeFeatureList.REPORT_FEED_USER_ACTIONS, HEADER_MAX_POSITION_FRACTION_NAME,
-                0.35);
+        mMinScrollFraction = MIN_SCROLL_FRACTION;
+        mHeaderMaxPosFraction = MAX_HEADER_POS_FRACTION;
     }
 
     @Override
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/HeaderIphScrollListenerTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/HeaderIphScrollListenerTest.java
index 17cdb19..4c7a2a8 100644
--- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/HeaderIphScrollListenerTest.java
+++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/HeaderIphScrollListenerTest.java
@@ -23,23 +23,16 @@
 import org.chromium.base.test.params.ParameterSet;
 import org.chromium.base.test.params.ParameterizedRunner;
 import org.chromium.base.test.util.Feature;
-import org.chromium.chrome.browser.feed.shared.stream.Stream;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.ntp.ScrollListener;
 import org.chromium.chrome.browser.ntp.ScrollListener.ScrollState;
 import org.chromium.chrome.browser.ntp.ScrollableContainerDelegate;
-import org.chromium.chrome.browser.ntp.snippets.SectionHeaderView;
-import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.user_education.UserEducationHelper;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
 import org.chromium.components.feature_engagement.FeatureConstants;
 import org.chromium.components.feature_engagement.Tracker;
 import org.chromium.components.feature_engagement.TriggerState;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 
 /** Tests for {@link HeaderIphScrollListener}. */
 @RunWith(ParameterizedRunner.class)
@@ -108,19 +101,7 @@
     private static final int FEED_VIEW_HEIGHT = 100;
 
     @Mock
-    private FeedSurfaceCoordinator mFeedSurfaceCoordinator;
-    @Mock
-    private Stream mStream;
-    @Mock
-    private FeedSurfaceMediator mFeedSurfaceMediator;
-    @Mock
-    private SectionHeaderView mSectionHeaderView;
-    @Mock
     private Tracker mTracker;
-    @Mock
-    private Profile mProfile;
-    @Mock
-    private UserEducationHelper mUserEducationHelper;
     private View mFeedRootView;
 
     private boolean mHasShownMenuIph;
@@ -131,10 +112,6 @@
 
         mFeedRootView = new View(InstrumentationRegistry.getContext());
         mFeedRootView.layout(0, 0, 0, FEED_VIEW_HEIGHT);
-
-        Map<String, Boolean> testFeatures =
-                Collections.singletonMap(ChromeFeatureList.REPORT_FEED_USER_ACTIONS, true);
-        ChromeFeatureList.setTestFeatures(testFeatures);
     }
 
     @Test
@@ -142,9 +119,9 @@
     @Feature({"Feed"})
     @ParameterAnnotations.UseMethodParameter(TestParamsForOnScroll.class)
     public void onScrollStateChanged_triggerIph(boolean expectEnabled, int scrollState,
-            int triggerState, boolean wouldTriggerHelpUI, int verticallScrollOffset,
+            int triggerState, boolean wouldTriggerHelpUI, int verticalScrollOffset,
             boolean isFeedHeaderPositionInRecyclerViewSuitableForIPH, boolean isFeedExpanded,
-            boolean isSignedIn) throws Exception {
+            boolean isSignedIn) {
         // Set Tracker mock.
         when(mTracker.getTriggerState(FeatureConstants.FEED_HEADER_MENU_FEATURE))
                 .thenReturn(triggerState);
@@ -183,7 +160,7 @@
                     public void removeScrollListener(ScrollListener listener) {}
                     @Override
                     public int getVerticalScrollOffset() {
-                        return verticallScrollOffset;
+                        return verticalScrollOffset;
                     }
                     @Override
                     public int getRootViewHeight() {
@@ -212,9 +189,9 @@
     @Feature({"Feed"})
     @ParameterAnnotations.UseMethodParameter(TestParamsForOnOffsetChanged.class)
     public void onScrollStateChanged_onHeaderOffsetChanged(boolean expectEnabled, int scrollState,
-            int triggerState, boolean wouldTriggerHelpUI, int verticallScrollOffset,
+            int triggerState, boolean wouldTriggerHelpUI, int verticalScrollOffset,
             boolean isFeedHeaderPositionInRecyclerViewSuitableForIPH, boolean isFeedExpanded,
-            boolean isSignedIn) throws Exception {
+            boolean isSignedIn) {
         // Set Tracker mock.
         when(mTracker.getTriggerState(FeatureConstants.FEED_HEADER_MENU_FEATURE))
                 .thenReturn(triggerState);
@@ -268,7 +245,7 @@
         // Trigger IPH through the scroll listener.
         HeaderIphScrollListener listener =
                 new HeaderIphScrollListener(iphDelegate, scrollableContainerDelegate);
-        listener.onHeaderOffsetChanged(-verticallScrollOffset);
+        listener.onHeaderOffsetChanged(-verticalScrollOffset);
 
         if (expectEnabled) {
             Assert.assertTrue(mHasShownMenuIph);
diff --git a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/v2/FeedV2NewTabPageTest.java b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/v2/FeedV2NewTabPageTest.java
index 5274bfc..54c3bed 100644
--- a/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/v2/FeedV2NewTabPageTest.java
+++ b/chrome/android/feed/core/javatests/src/org/chromium/chrome/browser/feed/v2/FeedV2NewTabPageTest.java
@@ -243,7 +243,7 @@
         // that sign-in promo is not shown.
         TestThreadUtils.runOnUiThreadBlocking(signinObserver::onSignedIn);
         RecyclerViewTestUtils.waitForStableRecyclerView(recyclerView);
-        onView(instanceOf(RecyclerView.class))
+        onView(withId(R.id.feed_stream_recycler_view))
                 .perform(RecyclerViewActions.scrollToPosition(SIGNIN_PROMO_POSITION));
         onView(withId(R.id.signin_promo_view_container)).check(doesNotExist());
 
@@ -251,7 +251,7 @@
         // that sign-in promo is shown.
         TestThreadUtils.runOnUiThreadBlocking(signinObserver::onSignedOut);
         RecyclerViewTestUtils.waitForStableRecyclerView(recyclerView);
-        onView(instanceOf(RecyclerView.class))
+        onView(withId(R.id.feed_stream_recycler_view))
                 .perform(RecyclerViewActions.scrollToPosition(SIGNIN_PROMO_POSITION));
         onView(withId(R.id.signin_promo_view_container)).check(matches(isDisplayed()));
 
@@ -284,12 +284,12 @@
         }
 
         // Verify that sign-in promo is displayed initially.
-        onView(instanceOf(RecyclerView.class))
+        onView(withId(R.id.feed_stream_recycler_view))
                 .perform(RecyclerViewActions.scrollToPosition(SIGNIN_PROMO_POSITION));
         onView(withId(R.id.signin_promo_view_container)).check(matches(isDisplayed()));
 
         // Swipe away the sign-in promo.
-        onView(instanceOf(RecyclerView.class))
+        onView(withId(R.id.feed_stream_recycler_view))
                 .perform(RecyclerViewActions.actionOnItemAtPosition(
                         SIGNIN_PROMO_POSITION, SWIPE_LEFT));
 
@@ -315,7 +315,7 @@
         mIsCachePopulatedInAccountManagerFacade = false;
         openNewTabPage();
         // Check that the sign-in promo is not shown if accounts are not ready.
-        onView(instanceOf(RecyclerView.class))
+        onView(withId(R.id.feed_stream_recycler_view))
                 .perform(RecyclerViewActions.scrollToPosition(SIGNIN_PROMO_POSITION));
         onView(withId(R.id.signin_promo_view_container)).check(doesNotExist());
 
@@ -324,7 +324,7 @@
         ChromeTabUtils.waitForTabPageLoaded(mTab, ChromeTabUtils.getUrlStringOnUiThread(mTab));
 
         // Check that the sign-in promo is displayed this time.
-        onView(instanceOf(RecyclerView.class))
+        onView(withId(R.id.feed_stream_recycler_view))
                 .perform(RecyclerViewActions.scrollToPosition(SIGNIN_PROMO_POSITION));
         onView(withId(R.id.signin_promo_view_container)).check(matches(isDisplayed()));
     }
@@ -336,7 +336,7 @@
     public void testArticleSectionHeaderWithMenu(boolean disableSigninPromoCard) throws Exception {
         openNewTabPage();
         // Scroll to the article section header in case it is not visible.
-        onView(instanceOf(RecyclerView.class))
+        onView(withId(R.id.feed_stream_recycler_view))
                 .perform(RecyclerViewActions.scrollToPosition(ARTICLE_SECTION_HEADER_POSITION));
         waitForView((ViewGroup) mNtp.getView(), allOf(withId(R.id.header_title), isDisplayed()));
 
diff --git a/chrome/android/java/DEPS b/chrome/android/java/DEPS
index 0d8c679..04dc79b 100644
--- a/chrome/android/java/DEPS
+++ b/chrome/android/java/DEPS
@@ -67,7 +67,7 @@
 
 specific_include_rules = {
   # Special-case where monochrome composes chrome+webview
-  "MonochromeApplication\.java": [
+  "MonochromeApplicationImpl\.java": [
     "+android_webview/nonembedded/java/src/org/chromium/android_webview/nonembedded/WebViewApkApplication.java",
   ],
   "SplitMonochromeApplication\.java": [
diff --git a/chrome/android/java/res/values-hdpi/dimens.xml b/chrome/android/java/res/values-hdpi/dimens.xml
index 7c0b014..51d8f55 100644
--- a/chrome/android/java/res/values-hdpi/dimens.xml
+++ b/chrome/android/java/res/values-hdpi/dimens.xml
@@ -10,10 +10,6 @@
     <!-- The size of the bounding box for favicons. -->
     <dimen name="compositor_tab_title_favicon_size">16dp</dimen>
 
-    <!-- TabSwitcher -->
-    <dimen name="tabswitcher_border_frame_padding_left">5.333dp</dimen>
-    <dimen name="tabswitcher_border_frame_padding_top">49.333dp</dimen>
-
     <!-- Location bar -->
     <dimen name="location_bar_status_separator_width">0.5dp</dimen>
 </resources>
diff --git a/chrome/android/java/res/values-xhdpi/dimens.xml b/chrome/android/java/res/values-xhdpi/dimens.xml
index de9197f..7e17cb5 100644
--- a/chrome/android/java/res/values-xhdpi/dimens.xml
+++ b/chrome/android/java/res/values-xhdpi/dimens.xml
@@ -9,8 +9,4 @@
 <resources>
     <!-- The size of the bounding box for favicons. -->
     <dimen name="compositor_tab_title_favicon_size">18dp</dimen>
-
-    <!-- TabSwitcher -->
-    <dimen name="tabswitcher_border_frame_padding_left">5.5dp</dimen>
-    <dimen name="tabswitcher_border_frame_padding_top">49.5dp</dimen>
 </resources>
diff --git a/chrome/android/java/res/values-xxhdpi/dimens.xml b/chrome/android/java/res/values-xxhdpi/dimens.xml
deleted file mode 100644
index ab9be249..0000000
--- a/chrome/android/java/res/values-xxhdpi/dimens.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2015 The Chromium Authors. All rights reserved.
-     Use of this source code is governed by a BSD-style license that can be
-     found in the LICENSE file. -->
-
-<resources>
-    <!-- TabSwitcher -->
-    <dimen name="tabswitcher_border_frame_padding_left">5.333dp</dimen>
-    <dimen name="tabswitcher_border_frame_padding_top">49.333dp</dimen>
-</resources>
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index 26f588f..3238b51 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -12,33 +12,13 @@
 
     <!-- TabSwitcher - The minimum distance from the edge to commit a side swap. -->
     <dimen name="swipe_commit_distance">120dp</dimen>
-    <!-- TabSwitcher - Size of the shift applied to tabs when stacked. -->
-    <dimen name="stacked_tab_visible_size">4dp</dimen>
-    <!-- TabSwitcher - Buffer space above the stack. -->
-    <dimen name="stack_buffer_height">5dp</dimen>
-    <!-- TabSwitcher - Buffer space on the side of the stack. -->
-    <dimen name="stack_buffer_width">5dp</dimen>
-    <!-- TabSwitcher - Minimum spacing between tabs. -->
-    <dimen name="min_spacing">120dp</dimen>
-    <!-- TabSwitcher - Maximum over scroll. -->
-    <dimen name="over_scroll">75dp</dimen>
-    <!-- TabSwitcher - Minimum scrolling distance to even out all the tabs. -->
-    <dimen name="even_out_scrolling">400dp</dimen>
     <!-- TabSwitcher - The space between tabs in the toolbar swiping transition. -->
     <dimen name="toolbar_swipe_space_between_tabs">30dp</dimen>
     <!-- TabSwitcher - The minimum distance from the edge to commit a toolbar side swap. -->
     <dimen name="toolbar_swipe_commit_distance">90dp</dimen>
-    <!-- TabSwitcher - Maximum amount to slide the tabs down or right in over scroll. -->
-    <dimen name="over_scroll_slide">10dp</dimen>
      <!-- TabSwitcher - The size of the close button on each tab. -->
     <dimen name="tab_switcher_close_button_size">20dp</dimen>
 
-    <!-- TabSwitcher -->
-    <dimen name="tabswitcher_border_frame_padding_left">6dp</dimen>
-    <dimen name="tabswitcher_border_frame_padding_top">50dp</dimen>
-    <dimen name="tabswitcher_border_frame_transparent_top">3dp</dimen>
-    <dimen name="tabswitcher_border_frame_transparent_side">2dp</dimen>
-
     <!-- Toolbar Phone - padding of the optional button when menu button is present -->
     <dimen name="toolbar_phone_optional_button_padding">12dp</dimen>
     <!-- Tab title -->
@@ -408,7 +388,6 @@
     <!--  Used as a margin to force the shadow view to overlap other views. -->
     <dimen name="action_bar_shadow_margin_negative">-10dp</dimen>
     <dimen name="sync_promo_view_padding">16dp</dimen>
-    <dimen name="open_new_tab_animation_y_translation">-20dp</dimen>
     <dimen name="sync_passphrase_type_instructions_padding">25dp</dimen>
     <!-- 18dp padding is added to each side of the remove button to limit the image width to 20dp (56dp - 2 * 18dp). -->
     <dimen name="history_item_remove_button_lateral_padding">18dp</dimen>
diff --git a/chrome/android/java/res/values/values.xml b/chrome/android/java/res/values/values.xml
index 5069e0d..8e76009 100644
--- a/chrome/android/java/res/values/values.xml
+++ b/chrome/android/java/res/values/values.xml
@@ -25,9 +25,6 @@
     <!-- Compositor Tab Title Text -->
     <bool name="compositor_tab_title_fake_bold_text">true</bool>
 
-    <!-- TabSwitcher - Maximum amount to tilt tabs in over scroll in degrees. -->
-    <integer name="over_scroll_angle">15</integer>
-
     <!-- Toolbar/AppMenu - Drawable level on reload image button -->
     <integer name="reload_button_level_reload">0</integer>
     <integer name="reload_button_level_stop">1</integer>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java
deleted file mode 100644
index 8ca3bcf..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplication.java
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright 2013 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;
-
-import android.content.Intent;
-import android.content.res.Configuration;
-import android.os.Bundle;
-
-import androidx.annotation.Nullable;
-
-import org.chromium.base.ApplicationStatus;
-import org.chromium.base.annotations.MainDex;
-import org.chromium.base.library_loader.LibraryLoader;
-import org.chromium.chrome.browser.background_task_scheduler.ChromeBackgroundTaskFactory;
-import org.chromium.chrome.browser.base.SplitCompatApplication;
-import org.chromium.chrome.browser.crash.PureJavaExceptionReporter;
-import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
-import org.chromium.chrome.browser.dependency_injection.ChromeAppComponent;
-import org.chromium.chrome.browser.dependency_injection.ChromeAppModule;
-import org.chromium.chrome.browser.dependency_injection.DaggerChromeAppComponent;
-import org.chromium.chrome.browser.dependency_injection.ModuleFactoryOverrides;
-import org.chromium.chrome.browser.flags.CachedFeatureFlags;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
-import org.chromium.chrome.browser.fonts.FontPreloader;
-import org.chromium.chrome.browser.night_mode.SystemNightModeMonitor;
-import org.chromium.chrome.browser.profiles.ProfileResolver;
-import org.chromium.chrome.browser.vr.OnExitVrRequestListener;
-import org.chromium.chrome.browser.vr.VrModuleProvider;
-import org.chromium.components.browser_ui.util.GlobalDiscardableReferencePool;
-import org.chromium.components.embedder_support.browser_context.PartitionResolverSupplier;
-import org.chromium.components.module_installer.util.ModuleUtil;
-import org.chromium.components.version_info.Channel;
-import org.chromium.components.version_info.VersionConstants;
-import org.chromium.url.GURL;
-
-/**
- * Basic application functionality that should be shared among all browser applications that use
- * chrome layer.
- *
- * Note: All application logic should be added to {@link ChromeApplicationImpl}, which will be
- * called from the superclass. See {@link SplitCompatApplication} for more info.
- */
-public class ChromeApplication extends SplitCompatApplication {
-    /** Lock on creation of sComponent. */
-    private static final Object sLock = new Object();
-    @Nullable
-    private static volatile ChromeAppComponent sComponent;
-
-    /** Chrome application logic. */
-    public static class ChromeApplicationImpl extends Impl {
-        public ChromeApplicationImpl() {}
-
-        @Override
-        public void onCreate() {
-            super.onCreate();
-
-            if (isBrowserProcess()) {
-                FontPreloader.getInstance().load(getApplication());
-
-                if (CachedFeatureFlags.isEnabled(ChromeFeatureList.EARLY_LIBRARY_LOAD)) {
-                    // Kick off library loading in a separate thread so it's ready when we need it.
-                    new Thread(() -> LibraryLoader.getInstance().ensureMainDexInitialized())
-                            .start();
-                }
-
-                ApplicationStatus.registerStateListenerForAllActivities(
-                        ChromePowerModeVoter.getInstance());
-
-                // Initializes the support for dynamic feature modules (browser only).
-                ModuleUtil.initApplication();
-
-                if (VersionConstants.CHANNEL == Channel.CANARY) {
-                    GURL.setReportDebugThrowableCallback(
-                            PureJavaExceptionReporter::reportJavaException);
-                }
-
-                // Set Chrome factory for mapping BackgroundTask classes to TaskIds.
-                ChromeBackgroundTaskFactory.setAsDefault();
-                PartitionResolverSupplier.setInstance(new ProfileResolver());
-
-                AppHooks.get().getChimeDelegate().initialize();
-            }
-        }
-
-        @MainDex
-        @Override
-        public void onTrimMemory(int level) {
-            super.onTrimMemory(level);
-            if (isSevereMemorySignal(level)
-                    && GlobalDiscardableReferencePool.getReferencePool() != null) {
-                GlobalDiscardableReferencePool.getReferencePool().drain();
-            }
-            CustomTabsConnection.onTrimMemory(level);
-        }
-
-        @Override
-        public void startActivity(Intent intent, Bundle options) {
-            if (VrModuleProvider.getDelegate().canLaunch2DIntents()
-                    || VrModuleProvider.getIntentDelegate().isVrIntent(intent)) {
-                super.startActivity(intent, options);
-                return;
-            }
-
-            VrModuleProvider.getDelegate().requestToExitVr(new OnExitVrRequestListener() {
-                @Override
-                public void onSucceeded() {
-                    if (!VrModuleProvider.getDelegate().canLaunch2DIntents()) {
-                        throw new IllegalStateException("Still in VR after having exited VR.");
-                    }
-                    startActivity(intent, options);
-                }
-
-                @Override
-                public void onDenied() {}
-            });
-        }
-
-        @Override
-        public void onConfigurationChanged(Configuration newConfig) {
-            super.onConfigurationChanged(newConfig);
-            // TODO(huayinz): Add observer pattern for application configuration changes.
-            if (SplitCompatApplication.isBrowserProcess()) {
-                SystemNightModeMonitor.getInstance().onApplicationConfigurationChanged();
-            }
-        }
-    }
-
-    public ChromeApplication(Impl impl) {
-        setImplSupplier(() -> impl);
-    }
-
-    public ChromeApplication() {
-        this(new ChromeApplicationImpl());
-    }
-
-    /**
-     * Determines whether the given memory signal is considered severe.
-     * @param level The type of signal as defined in {@link android.content.ComponentCallbacks2}.
-     */
-    public static boolean isSevereMemorySignal(int level) {
-        // The conditions are expressed using ranges to capture intermediate levels possibly added
-        // to the API in the future.
-        return (level >= TRIM_MEMORY_RUNNING_LOW && level < TRIM_MEMORY_UI_HIDDEN)
-                || level >= TRIM_MEMORY_MODERATE;
-    }
-
-    /** Returns the application-scoped component. */
-    public static ChromeAppComponent getComponent() {
-        if (sComponent == null) {
-            synchronized (sLock) {
-                if (sComponent == null) {
-                    sComponent = createComponent();
-                }
-            }
-        }
-        return sComponent;
-    }
-
-    private static ChromeAppComponent createComponent() {
-        ChromeAppModule.Factory overriddenFactory =
-                ModuleFactoryOverrides.getOverrideFor(ChromeAppModule.Factory.class);
-        ChromeAppModule module =
-                overriddenFactory == null ? new ChromeAppModule() : overriddenFactory.create();
-
-        AppHooksModule.Factory appHooksFactory =
-                ModuleFactoryOverrides.getOverrideFor(AppHooksModule.Factory.class);
-        AppHooksModule appHooksModule =
-                appHooksFactory == null ? new AppHooksModule() : appHooksFactory.create();
-
-        return DaggerChromeAppComponent.builder().chromeAppModule(module)
-                .appHooksModule(appHooksModule).build();
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplicationImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplicationImpl.java
new file mode 100644
index 0000000..4509475
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplicationImpl.java
@@ -0,0 +1,167 @@
+// Copyright 2013 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;
+
+import android.app.Application;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+
+import org.chromium.base.ApplicationStatus;
+import org.chromium.base.annotations.MainDex;
+import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.chrome.browser.background_task_scheduler.ChromeBackgroundTaskFactory;
+import org.chromium.chrome.browser.base.SplitCompatApplication;
+import org.chromium.chrome.browser.crash.PureJavaExceptionReporter;
+import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
+import org.chromium.chrome.browser.dependency_injection.ChromeAppComponent;
+import org.chromium.chrome.browser.dependency_injection.ChromeAppModule;
+import org.chromium.chrome.browser.dependency_injection.DaggerChromeAppComponent;
+import org.chromium.chrome.browser.dependency_injection.ModuleFactoryOverrides;
+import org.chromium.chrome.browser.flags.CachedFeatureFlags;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.fonts.FontPreloader;
+import org.chromium.chrome.browser.night_mode.SystemNightModeMonitor;
+import org.chromium.chrome.browser.profiles.ProfileResolver;
+import org.chromium.chrome.browser.vr.OnExitVrRequestListener;
+import org.chromium.chrome.browser.vr.VrModuleProvider;
+import org.chromium.components.browser_ui.util.GlobalDiscardableReferencePool;
+import org.chromium.components.embedder_support.browser_context.PartitionResolverSupplier;
+import org.chromium.components.module_installer.util.ModuleUtil;
+import org.chromium.components.version_info.Channel;
+import org.chromium.components.version_info.VersionConstants;
+import org.chromium.url.GURL;
+
+/**
+ * Basic application functionality that should be shared among all browser applications that use
+ * chrome layer.
+ *
+ * Note: All application logic should be added to {@link ChromeApplicationImpl}, which will be
+ * called from the superclass. See {@link SplitCompatApplication} for more info.
+ */
+public class ChromeApplicationImpl extends SplitCompatApplication.Impl {
+    /** Lock on creation of sComponent. */
+    private static final Object sLock = new Object();
+    @Nullable
+    private static volatile ChromeAppComponent sComponent;
+
+    public ChromeApplicationImpl() {}
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+
+        if (SplitCompatApplication.isBrowserProcess()) {
+            FontPreloader.getInstance().load(getApplication());
+
+            if (CachedFeatureFlags.isEnabled(ChromeFeatureList.EARLY_LIBRARY_LOAD)) {
+                // Kick off library loading in a separate thread so it's ready when we need it.
+                new Thread(() -> LibraryLoader.getInstance().ensureMainDexInitialized()).start();
+            }
+
+            ApplicationStatus.registerStateListenerForAllActivities(
+                    ChromePowerModeVoter.getInstance());
+
+            // Initializes the support for dynamic feature modules (browser only).
+            ModuleUtil.initApplication();
+
+            if (VersionConstants.CHANNEL == Channel.CANARY) {
+                GURL.setReportDebugThrowableCallback(
+                        PureJavaExceptionReporter::reportJavaException);
+            }
+
+            // Set Chrome factory for mapping BackgroundTask classes to TaskIds.
+            ChromeBackgroundTaskFactory.setAsDefault();
+            PartitionResolverSupplier.setInstance(new ProfileResolver());
+
+            AppHooks.get().getChimeDelegate().initialize();
+        }
+    }
+
+    @MainDex
+    @Override
+    public void onTrimMemory(int level) {
+        super.onTrimMemory(level);
+        if (isSevereMemorySignal(level)
+                && GlobalDiscardableReferencePool.getReferencePool() != null) {
+            GlobalDiscardableReferencePool.getReferencePool().drain();
+        }
+        CustomTabsConnection.onTrimMemory(level);
+    }
+
+    @Override
+    public void startActivity(Intent intent, Bundle options) {
+        if (VrModuleProvider.getDelegate().canLaunch2DIntents()
+                || VrModuleProvider.getIntentDelegate().isVrIntent(intent)) {
+            super.startActivity(intent, options);
+            return;
+        }
+
+        VrModuleProvider.getDelegate().requestToExitVr(new OnExitVrRequestListener() {
+            @Override
+            public void onSucceeded() {
+                if (!VrModuleProvider.getDelegate().canLaunch2DIntents()) {
+                    throw new IllegalStateException("Still in VR after having exited VR.");
+                }
+                startActivity(intent, options);
+            }
+
+            @Override
+            public void onDenied() {}
+        });
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
+        // TODO(huayinz): Add observer pattern for application configuration changes.
+        if (SplitCompatApplication.isBrowserProcess()) {
+            SystemNightModeMonitor.getInstance().onApplicationConfigurationChanged();
+        }
+    }
+
+    /**
+     * Determines whether the given memory signal is considered severe.
+     * @param level The type of signal as defined in {@link android.content.ComponentCallbacks2}.
+     */
+    public static boolean isSevereMemorySignal(int level) {
+        // The conditions are expressed using ranges to capture intermediate levels possibly added
+        // to the API in the future.
+        return (level >= Application.TRIM_MEMORY_RUNNING_LOW
+                       && level < Application.TRIM_MEMORY_UI_HIDDEN)
+                || level >= Application.TRIM_MEMORY_MODERATE;
+    }
+
+    /** Returns the application-scoped component. */
+    public static ChromeAppComponent getComponent() {
+        if (sComponent == null) {
+            synchronized (sLock) {
+                if (sComponent == null) {
+                    sComponent = createComponent();
+                }
+            }
+        }
+        return sComponent;
+    }
+
+    private static ChromeAppComponent createComponent() {
+        ChromeAppModule.Factory overriddenFactory =
+                ModuleFactoryOverrides.getOverrideFor(ChromeAppModule.Factory.class);
+        ChromeAppModule module =
+                overriddenFactory == null ? new ChromeAppModule() : overriddenFactory.create();
+
+        AppHooksModule.Factory appHooksFactory =
+                ModuleFactoryOverrides.getOverrideFor(AppHooksModule.Factory.class);
+        AppHooksModule appHooksModule =
+                appHooksFactory == null ? new AppHooksModule() : appHooksFactory.create();
+
+        return DaggerChromeAppComponent.builder()
+                .chromeAppModule(module)
+                .appHooksModule(appHooksModule)
+                .build();
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBackupAgentImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBackupAgentImpl.java
index df0b017..29831e03 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBackupAgentImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBackupAgentImpl.java
@@ -20,6 +20,7 @@
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.task.PostTask;
+import org.chromium.chrome.browser.base.SplitCompatApplication;
 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
 import org.chromium.chrome.browser.init.AsyncInitTaskRunner;
 import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
@@ -325,7 +326,7 @@
         PostTask.runSynchronously(UiThreadTaskTraits.DEFAULT, () -> {
             // Chrome library loading depends on PathUtils.
             PathUtils.setPrivateDataDirectorySuffix(
-                    ChromeApplication.PRIVATE_DATA_DIRECTORY_SUFFIX);
+                    SplitCompatApplication.PRIVATE_DATA_DIRECTORY_SUFFIX);
             createAsyncInitTaskRunner(latch).startBackgroundTasks(
                     false /* allocateChildConnection */, true /* initVariationSeed */);
         });
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index 581b085..26d77cc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -74,10 +74,8 @@
 import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChrome;
 import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChromePhone;
 import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChromeTablet;
-import org.chromium.chrome.browser.compositor.layouts.LayoutManagerImpl;
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
 import org.chromium.chrome.browser.compositor.layouts.OverviewModeController;
-import org.chromium.chrome.browser.compositor.layouts.phone.StackLayout;
 import org.chromium.chrome.browser.cookies.CookiesFetcher;
 import org.chromium.chrome.browser.crypto.CipherFactory;
 import org.chromium.chrome.browser.dependency_injection.ChromeActivityComponent;
@@ -612,6 +610,8 @@
         try (TraceEvent e = TraceEvent.scoped(
                      "ChromeTabbedActivity.setupCompositorContentPreNativeForPhone")) {
             CompositorViewHolder compositorViewHolder = getCompositorViewHolder();
+
+            // TODO(1169205): Remove all GTS enabled checks after M5 is default.
             if (TabUiFeatureUtilities.isGridTabSwitcherEnabled()) {
                 TabManagementDelegate tabManagementDelegate =
                         TabManagementModuleProvider.getDelegate();
@@ -622,6 +622,7 @@
                             mStartSurfaceParentTabSupplier, hadWarmStart(), getWindowAndroid());
                 }
             }
+
             // clang-format off
             mLayoutManager = new LayoutManagerChromePhone(compositorViewHolder, mContentContainer,
                     mStartSurfaceSupplier.get(), getTabContentManagerSupplier(),
@@ -695,13 +696,6 @@
                     return;
                 }
 
-                Layout activeLayout = mLayoutManager.getActiveLayout();
-                if (activeLayout instanceof StackLayout && !activeLayout.isStartingToHide()) {
-                    RecordUserAction.record("MobileToolbarStackViewButtonInStackView");
-                } else if (!isInOverviewMode()) {
-                    RecordUserAction.record("MobileToolbarStackViewButtonInBrowsingView");
-                }
-
                 if (isInOverviewMode() && !StartSurfaceConfiguration.isStartSurfaceEnabled()) {
                     hideOverview();
                 } else {
@@ -2197,10 +2191,6 @@
 
     private void hideOverview() {
         assert (mOverviewModeController.overviewVisible());
-        Layout activeLayout = mLayoutManager.getActiveLayout();
-        if (activeLayout instanceof StackLayout) {
-            ((StackLayout) activeLayout).commitOutstandingModelState(LayoutManagerImpl.time());
-        }
         if (getCurrentTabModel().getCount() != 0) {
             // Don't hide overview if current tab stack is empty()
             mOverviewModeController.hideOverview(true);
@@ -2312,7 +2302,7 @@
     @Override
     public void onTrimMemory(int level) {
         super.onTrimMemory(level);
-        if (ChromeApplication.isSevereMemorySignal(level)) {
+        if (ChromeApplicationImpl.isSevereMemorySignal(level)) {
             NativePageAssassin.getInstance().freezeAllHiddenPages();
         }
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/DEPS b/chrome/android/java/src/org/chromium/chrome/browser/DEPS
index 1f3443f..0ab8300 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/DEPS
+++ b/chrome/android/java/src/org/chromium/chrome/browser/DEPS
@@ -130,9 +130,6 @@
   "DownloadInfoBarController\.java": [
     "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
   ],
-  "DownloadPage\.java": [
-    "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
-  ],
   "ExploreSitesIPH\.java": [
     "+chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java",
   ],
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
index a3fc67d..1bc69ae0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
@@ -600,7 +600,7 @@
         if (isValidReferrerHeader(referrerExtra)) {
             return referrerExtra.toString();
         } else if (IntentHandler.notSecureIsIntentChromeOrFirstParty(intent)
-                || ChromeApplication.getComponent()
+                || ChromeApplicationImpl.getComponent()
                            .resolveSessionDataHolder()
                            .canActiveHandlerUseReferrer(customTabsSession, referrerExtra)) {
             return referrerExtra.toString();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
index 005a8719..0b170ab 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
@@ -347,7 +347,7 @@
     }
 
     private static SessionDataHolder getSessionDataHolder() {
-        return ChromeApplication.getComponent().resolveSessionDataHolder();
+        return ChromeApplicationImpl.getComponent().resolveSessionDataHolder();
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/MonochromeApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/MonochromeApplication.java
deleted file mode 100644
index 8aeb1b7..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/MonochromeApplication.java
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2016 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;
-
-import android.content.Context;
-
-import org.chromium.android_webview.nonembedded.WebViewApkApplication;
-import org.chromium.base.ActivityState;
-import org.chromium.base.ApplicationStatus;
-import org.chromium.chrome.browser.base.SplitMonochromeApplication;
-import org.chromium.chrome.browser.version.ChromeVersionInfo;
-
-/**
- * This is Application class for Monochrome.
- *
- * You shouldn't add anything else in this file, this class is split off from
- * normal chrome in order to access Android system API through Android WebView
- * glue layer and have monochrome specific code.
- *
- * This class is NOT used by Trichrome. Do not add anything here which is only
- * related to Monochrome's minimum SDK level or APK packaging decisions, because
- * those are likely to apply to Trichrome as well - this must only be used for
- * things specific to functioning as a WebView implementation.
- */
-public class MonochromeApplication extends ChromeApplication {
-    public MonochromeApplication() {
-        super(new MonochromeApplicationImpl());
-    }
-
-    /** Monochrome application logic. */
-    public static class MonochromeApplicationImpl extends ChromeApplicationImpl {
-        public MonochromeApplicationImpl() {}
-
-        @Override
-        public void onCreate() {
-            super.onCreate();
-            if (!ChromeVersionInfo.isStableBuild()) {
-                // Performing Monochrome WebView DevTools Launcher icon showing/hiding logic in
-                // onCreate rather than in attachBaseContext() because it depends on application
-                // context being initiatied.
-                if (getApplication().isWebViewProcess()) {
-                    // Whenever a monochrome webview process is launched (WebView service or
-                    // developer UI), post a background task to show/hide the DevTools icon.
-                    WebViewApkApplication.postDeveloperUiLauncherIconTask();
-                } else if (isBrowserProcess()) {
-                    // Frequently check current system webview provider and show/hide the icon
-                    // accordingly by listening to Monochrome browser Activities status (whenever a
-                    // browser activity comes to the foreground).
-                    ApplicationStatus.registerStateListenerForAllActivities((activity, state) -> {
-                        if (state == ActivityState.STARTED) {
-                            WebViewApkApplication.postDeveloperUiLauncherIconTask();
-                        }
-                    });
-                }
-            }
-        }
-    }
-
-    @Override
-    public void attachBaseContext(Context context) {
-        super.attachBaseContext(context);
-        SplitMonochromeApplication.initializeMonochromeProcessCommon(getPackageName());
-    }
-
-    @Override
-    public boolean isWebViewProcess() {
-        return WebViewApkApplication.isWebViewProcess();
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/MonochromeApplicationImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/MonochromeApplicationImpl.java
new file mode 100644
index 0000000..39ef59c
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/MonochromeApplicationImpl.java
@@ -0,0 +1,51 @@
+// Copyright 2016 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;
+
+import org.chromium.android_webview.nonembedded.WebViewApkApplication;
+import org.chromium.base.ActivityState;
+import org.chromium.base.ApplicationStatus;
+import org.chromium.chrome.browser.base.SplitCompatApplication;
+import org.chromium.chrome.browser.version.ChromeVersionInfo;
+
+/**
+ * This is Application class for Monochrome.
+ *
+ * You shouldn't add anything else in this file, this class is split off from
+ * normal chrome in order to access Android system API through Android WebView
+ * glue layer and have monochrome specific code.
+ *
+ * This class is NOT used by Trichrome. Do not add anything here which is only
+ * related to Monochrome's minimum SDK level or APK packaging decisions, because
+ * those are likely to apply to Trichrome as well - this must only be used for
+ * things specific to functioning as a WebView implementation.
+ */
+public class MonochromeApplicationImpl extends ChromeApplicationImpl {
+    public MonochromeApplicationImpl() {}
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        if (!ChromeVersionInfo.isStableBuild()) {
+            // Performing Monochrome WebView DevTools Launcher icon showing/hiding logic in
+            // onCreate rather than in attachBaseContext() because it depends on application
+            // context being initiatied.
+            if (getApplication().isWebViewProcess()) {
+                // Whenever a monochrome webview process is launched (WebView service or
+                // developer UI), post a background task to show/hide the DevTools icon.
+                WebViewApkApplication.postDeveloperUiLauncherIconTask();
+            } else if (SplitCompatApplication.isBrowserProcess()) {
+                // Frequently check current system webview provider and show/hide the icon
+                // accordingly by listening to Monochrome browser Activities status (whenever a
+                // browser activity comes to the foreground).
+                ApplicationStatus.registerStateListenerForAllActivities((activity, state) -> {
+                    if (state == ActivityState.STARTED) {
+                        WebViewApkApplication.postDeveloperUiLauncherIconTask();
+                    }
+                });
+            }
+        }
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
index ae46341..e4521ff 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -59,7 +59,7 @@
 import org.chromium.chrome.browser.ActivityTabProvider;
 import org.chromium.chrome.browser.AppHooks;
 import org.chromium.chrome.browser.ChromeActivitySessionTracker;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.ChromeWindow;
 import org.chromium.chrome.browser.DeferredStartupHandler;
 import org.chromium.chrome.browser.IntentHandler;
@@ -494,7 +494,8 @@
      */
     @SuppressWarnings("unchecked")
     protected C createComponent(ChromeActivityCommonsModule commonsModule) {
-        return (C) ChromeApplication.getComponent().createChromeActivityComponent(commonsModule);
+        return (C) ChromeApplicationImpl.getComponent().createChromeActivityComponent(
+                commonsModule);
     }
 
     /**
@@ -2151,7 +2152,7 @@
     @Override
     public void onTrimMemory(int level) {
         super.onTrimMemory(level);
-        if (ChromeApplication.isSevereMemorySignal(level)) {
+        if (ChromeApplicationImpl.isSevereMemorySignal(level)) {
             clearToolbarResourceCache();
         }
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
index 1f81a422..cb7c439 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/flags/ChromeCachedFlags.java
@@ -72,7 +72,6 @@
                 ChromeFeatureList.PAINT_PREVIEW_DEMO,
                 ChromeFeatureList.PAINT_PREVIEW_SHOW_ON_STARTUP,
                 ChromeFeatureList.PRIORITIZE_BOOTSTRAP_TASKS,
-                ChromeFeatureList.REPORT_FEED_USER_ACTIONS,
                 ChromeFeatureList.SHARE_BY_DEFAULT_IN_CCT,
                 ChromeFeatureList.START_SURFACE_ANDROID,
                 ChromeFeatureList.SWAP_PIXEL_FORMAT_TO_FIX_CONVERT_FROM_TRANSLUCENT,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitChromeApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitChromeApplication.java
index ffa906d..cb0b8121 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitChromeApplication.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitChromeApplication.java
@@ -40,7 +40,7 @@
 
     public SplitChromeApplication() {
         this(SplitCompatUtils.getIdentifierName(
-                "org.chromium.chrome.browser.ChromeApplication$ChromeApplicationImpl"));
+                "org.chromium.chrome.browser.ChromeApplicationImpl"));
     }
 
     public SplitChromeApplication(String chromeApplicationClassName) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitMonochromeApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitMonochromeApplication.java
index e2d2960..a34f0e46 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitMonochromeApplication.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitMonochromeApplication.java
@@ -30,7 +30,7 @@
 
     public SplitMonochromeApplication() {
         super(SplitCompatUtils.getIdentifierName(
-                "org.chromium.chrome.browser.MonochromeApplication$MonochromeApplicationImpl"));
+                "org.chromium.chrome.browser.MonochromeApplicationImpl"));
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataDialogActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataDialogActivity.java
index 93435b80..92de6bf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataDialogActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClearDataDialogActivity.java
@@ -15,7 +15,7 @@
 
 import org.chromium.base.IntentUtils;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -88,8 +88,8 @@
 
     private void recordDecision(boolean accepted) {
         boolean appUninstalled = getIsAppUninstalledFromIntent(getIntent());
-        ChromeApplication.getComponent().resolveTwaClearDataDialogRecorder()
-                .handleDialogResult(accepted, appUninstalled);
+        ChromeApplicationImpl.getComponent().resolveTwaClearDataDialogRecorder().handleDialogResult(
+                accepted, appUninstalled);
     }
 
     @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java
index bf498a6..3dbd4f5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ClientAppBroadcastReceiver.java
@@ -9,7 +9,7 @@
 import android.content.Intent;
 
 import org.chromium.base.Log;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.browserservices.permissiondelegation.PermissionUpdater;
 import org.chromium.chrome.browser.metrics.WebApkUma;
 import org.chromium.chrome.browser.version.ChromeVersionInfo;
@@ -77,8 +77,8 @@
     public ClientAppBroadcastReceiver() {
         this(new ClearDataStrategy(), new ClientAppDataRegister(),
                 new BrowserServicesStore(
-                        ChromeApplication.getComponent().resolveSharedPreferencesManager()),
-                ChromeApplication.getComponent().resolveTwaPermissionUpdater());
+                        ChromeApplicationImpl.getComponent().resolveSharedPreferencesManager()),
+                ChromeApplicationImpl.getComponent().resolveTwaPermissionUpdater());
     }
 
     /** Constructor to allow dependency injection in tests. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ManageTrustedWebActivityDataActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ManageTrustedWebActivityDataActivity.java
index b322177..1cbaa95 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ManageTrustedWebActivityDataActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/ManageTrustedWebActivityDataActivity.java
@@ -12,7 +12,7 @@
 import androidx.browser.customtabs.CustomTabsSessionToken;
 
 import org.chromium.base.Log;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
 import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
 import org.chromium.webapk.lib.common.WebApkConstants;
@@ -75,7 +75,7 @@
         }
 
         CustomTabsConnection connection =
-                ChromeApplication.getComponent().resolveCustomTabsConnection();
+                ChromeApplicationImpl.getComponent().resolveCustomTabsConnection();
         return connection.getClientPackageNameForSession(session);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java
index 26005da..c091e3d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClient.java
@@ -36,7 +36,7 @@
 import org.chromium.base.task.AsyncTask;
 import org.chromium.base.task.PostTask;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.browserservices.TrustedWebActivityUmaRecorder.DelegatedNotificationSmallIconFallback;
 import org.chromium.chrome.browser.browserservices.permissiondelegation.TrustedWebActivityPermissionManager;
 import org.chromium.chrome.browser.notifications.NotificationBuilderBase;
@@ -354,7 +354,7 @@
             List<ResolveInfo> resolveInfosForUrl) {
         // This is ugly, but the call site for this is static and called by native.
         TrustedWebActivityClient client =
-                ChromeApplication.getComponent().resolveTrustedWebActivityClient();
+                ChromeApplicationImpl.getComponent().resolveTrustedWebActivityClient();
         return client.createLaunchIntentForTwaInternal(appContext, url, resolveInfosForUrl);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsFactoryImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsFactoryImpl.java
index f5098820..dedd006 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsFactoryImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsFactoryImpl.java
@@ -6,7 +6,7 @@
 
 import androidx.annotation.VisibleForTesting;
 
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.app.ChromeActivity;
 import org.chromium.chrome.browser.customtabs.CustomTabActivity;
 import org.chromium.components.payments.MethodStrings;
@@ -39,7 +39,7 @@
         mRenderFrameHost = renderFrameHost;
         mDigitalGoodsDelegate = mRenderFrameHost::getLastCommittedURL;
         mAdapter = new DigitalGoodsAdapter(
-                ChromeApplication.getComponent().resolveTrustedWebActivityClient());
+                ChromeApplicationImpl.getComponent().resolveTrustedWebActivityClient());
     }
 
     private int getResponseCode(String paymentMethod) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/InstalledWebappGeolocationBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/InstalledWebappGeolocationBridge.java
index 1439fb5..f799c4d8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/InstalledWebappGeolocationBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/InstalledWebappGeolocationBridge.java
@@ -14,7 +14,7 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.base.task.PostTask;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.browserservices.TrustedWebActivityClient;
 import org.chromium.components.embedder_support.util.Origin;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
@@ -69,7 +69,7 @@
         if (origin == null) return null;
 
         return new InstalledWebappGeolocationBridge(nativePtr, origin,
-                ChromeApplication.getComponent().resolveTrustedWebActivityClient());
+                ChromeApplicationImpl.getComponent().resolveTrustedWebActivityClient());
     }
 
     @CalledByNative
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/PermissionUpdater.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/PermissionUpdater.java
index 1c9d696..a5cf34e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/PermissionUpdater.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/PermissionUpdater.java
@@ -9,7 +9,7 @@
 
 import org.chromium.base.Log;
 import org.chromium.base.PackageManagerUtils;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.browserservices.BrowserServicesMetrics;
 import org.chromium.components.embedder_support.util.Origin;
 
@@ -40,7 +40,7 @@
     }
 
     public static PermissionUpdater get() {
-        return ChromeApplication.getComponent().resolveTwaPermissionUpdater();
+        return ChromeApplicationImpl.getComponent().resolveTwaPermissionUpdater();
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionManager.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionManager.java
index 34bc604b..59a2124c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionManager.java
@@ -25,7 +25,7 @@
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.browserservices.TrustedWebActivityUmaRecorder;
 import org.chromium.chrome.browser.customtabs.CustomTabActivity;
 import org.chromium.components.content_settings.ContentSettingValues;
@@ -63,7 +63,7 @@
     private final Lazy<NotificationChannelPreserver> mPermissionPreserver;
 
     public static TrustedWebActivityPermissionManager get() {
-        return ChromeApplication.getComponent().resolveTwaPermissionManager();
+        return ChromeApplicationImpl.getComponent().resolveTwaPermissionManager();
     }
 
     @Inject
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
index 9573df7..d506b43 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChrome.java
@@ -23,7 +23,6 @@
 import org.chromium.chrome.browser.compositor.TitleCache;
 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.phone.StackLayout;
 import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutHelperManager;
 import org.chromium.chrome.browser.device.DeviceClassManager;
 import org.chromium.chrome.browser.fullscreen.FullscreenManager;
@@ -74,9 +73,6 @@
     private boolean mCreatingNtp;
     private final ObserverList<OverviewModeObserver> mOverviewModeObservers;
 
-    /** Whether to create an overview Layout when LayoutManagerChrome is created. */
-    private boolean mCreateOverviewLayout;
-
     protected ObservableSupplier<TabContentManager> mTabContentManagerSupplier;
     private final OneshotSupplierImpl<OverviewModeBehavior> mOverviewModeBehaviorSupplier;
 
@@ -132,8 +128,6 @@
                         browserControlsSupplier = mHost.getBrowserControlsManagerSupplier();
                 mOverviewLayout = tabManagementDelegate.createStartSurfaceLayout(
                         context, this, renderHost, startSurface);
-            } else {
-                mCreateOverviewLayout = true;
             }
         }
 
@@ -179,13 +173,6 @@
                 new OverviewListLayout(context, this, renderHost, browserControlsStateProvider);
         mToolbarSwipeLayout = new ToolbarSwipeLayout(context, this, renderHost);
 
-        if (mCreateOverviewLayout) {
-            final ObservableSupplier<? extends BrowserControlsStateProvider>
-                    browserControlsSupplier = mHost.getBrowserControlsManagerSupplier();
-            mOverviewLayout = new StackLayout(context, this, renderHost,
-                    (ObservableSupplier<BrowserControlsStateProvider>) browserControlsSupplier);
-        }
-
         super.init(selector, creator, controlContainer, dynamicResourceLoader);
 
         // TODO: TitleCache should be a part of the ResourceManager.
@@ -230,34 +217,6 @@
         }
     }
 
-    /**
-     * Simulates a click on the view at the specified pixel offset
-     * from the top left of the view.
-     * This is used by UI tests.
-     * @param x Coordinate of the click in dp.
-     * @param y Coordinate of the click in dp.
-     */
-    @VisibleForTesting
-    public void simulateClick(float x, float y) {
-        if (getActiveLayout() instanceof StackLayout) {
-            ((StackLayout) getActiveLayout()).simulateClick(x, y);
-        }
-    }
-
-    /**
-     * Simulates a drag and issues Up-event to commit the drag.
-     * @param x  Coordinate to start the Drag from in dp.
-     * @param y  Coordinate to start the Drag from in dp.
-     * @param dX Amount of drag in X direction in dp.
-     * @param dY Amount of drag in Y direction in dp.
-     */
-    @VisibleForTesting
-    public void simulateDrag(float x, float y, float dX, float dY) {
-        if (getActiveLayout() instanceof StackLayout) {
-            ((StackLayout) getActiveLayout()).simulateDrag(x, y, dX, dY);
-        }
-    }
-
     private boolean isOverviewLayout(Layout layout) {
         return layout != null && (layout == mOverviewLayout || layout == mOverviewListLayout);
     }
@@ -430,13 +389,10 @@
     @Override
     public void hideOverview(boolean animate) {
         Layout activeLayout = getActiveLayout();
+        if (!isOverviewLayout(activeLayout)) return;
+
         if (activeLayout != null && !activeLayout.isStartingToHide()) {
-            if (animate) {
-                activeLayout.onTabSelecting(time(), Tab.INVALID_TAB_ID);
-            } else {
-                startHiding(Tab.INVALID_TAB_ID, false);
-                doneHiding();
-            }
+            activeLayout.startHiding(Tab.INVALID_TAB_ID, animate);
         }
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/SimpleAnimationLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/SimpleAnimationLayout.java
index 4a364da..6e68fb9e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/SimpleAnimationLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/SimpleAnimationLayout.java
@@ -10,6 +10,7 @@
 import android.content.Context;
 import android.graphics.RectF;
 
+import org.chromium.base.MathUtils;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.compositor.LayerTitleCache;
 import org.chromium.chrome.browser.compositor.layouts.Layout;
@@ -18,7 +19,6 @@
 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.BlackHoleEventFilter;
-import org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack;
 import org.chromium.chrome.browser.compositor.scene_layer.TabListSceneLayer;
 import org.chromium.chrome.browser.layouts.EventFilter;
 import org.chromium.chrome.browser.layouts.LayoutType;
@@ -66,6 +66,15 @@
     /** The time duration of the animation */
     protected static final int TAB_CLOSED_ANIMATION_DURATION = 250;
 
+    /** The percentage of the screen to cover for the discarded tab to be fully transparent. */
+    public static final float DISCARD_RANGE_SCREEN = 0.7f;
+
+    /** The minimum scale the tab can reach when being discarded by a click. */
+    private static final float DISCARD_END_SCALE_CLICK = 0.7f;
+
+    /** The minimum scale the tab can reach when being discarded by a swipe. */
+    private static final float DISCARD_END_SCALE_SWIPE = 0.5f;
+
     /**
      * A cached {@link LayoutTab} representation of the currently closing tab. If it's not
      * null, it means tabClosing() has been called to start animation setup but
@@ -408,7 +417,7 @@
     private void setDiscardAmount(float discard) {
         if (mAnimatedTab != null) {
             final float range = getDiscardRange();
-            final float scale = Stack.computeDiscardScale(discard, range, true);
+            final float scale = computeDiscardScale(discard, range, true);
 
             final float deltaX = mAnimatedTab.getOriginalContentWidth();
             final float deltaY = mAnimatedTab.getOriginalContentHeight() / 2.f;
@@ -416,15 +425,44 @@
             mAnimatedTab.setY(deltaY * (1.f - scale));
             mAnimatedTab.setScale(scale);
             mAnimatedTab.setBorderScale(scale);
-            mAnimatedTab.setAlpha(Stack.computeDiscardAlpha(discard, range));
+            mAnimatedTab.setAlpha(computeDiscardAlpha(discard, range));
         }
     }
 
     /**
+     * Computes the scale of the tab based on its discard status.
+     *
+     * @param amount    The discard amount.
+     * @param range     The range of the absolute value of discard amount.
+     * @param fromClick Whether or not the discard was from a click or a swipe.
+     * @return          The scale of the tab to use to draw the tab.
+     */
+    public static float computeDiscardScale(float amount, float range, boolean fromClick) {
+        if (Math.abs(amount) < 1.0f) return 1.0f;
+        float t = amount / range;
+        float endScale = fromClick ? DISCARD_END_SCALE_CLICK : DISCARD_END_SCALE_SWIPE;
+        return MathUtils.interpolate(1.0f, endScale, Math.abs(t));
+    }
+
+    /**
+     * Computes the alpha value of the tab based on its discard status.
+     *
+     * @param amount The discard amount.
+     * @param range  The range of the absolute value of discard amount.
+     * @return       The alpha value that need to be applied on the tab.
+     */
+    public static float computeDiscardAlpha(float amount, float range) {
+        if (Math.abs(amount) < 1.0f) return 1.0f;
+        float t = amount / range;
+        t = MathUtils.clamp(t, -1.0f, 1.0f);
+        return 1.f - Math.abs(t);
+    }
+
+    /**
      * @return The range of the discard amount.
      */
     private float getDiscardRange() {
-        return Math.min(getWidth(), getHeight()) * Stack.DISCARD_RANGE_SCREEN;
+        return Math.min(getWidth(), getHeight()) * DISCARD_RANGE_SCREEN;
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java
deleted file mode 100644
index ac5307e..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java
+++ /dev/null
@@ -1,194 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.compositor.layouts.phone;
-
-import android.content.Context;
-
-import org.chromium.base.metrics.RecordUserAction;
-import org.chromium.base.supplier.ObservableSupplier;
-import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
-import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost;
-import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost;
-import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tabmodel.TabList;
-import org.chromium.chrome.browser.tabmodel.TabModel;
-import org.chromium.chrome.browser.tabmodel.TabModelSelector;
-import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver;
-import org.chromium.chrome.browser.tabmodel.TabModelUtils;
-
-import java.util.ArrayList;
-
-/**
- * Layout that displays all normal tabs in one stack and all incognito tabs in a second.
- */
-public class StackLayout extends StackLayoutBase {
-    public static final int NORMAL_STACK_INDEX = 0;
-    public static final int INCOGNITO_STACK_INDEX = 1;
-
-    /** Whether the current fling animation is the result of switching stacks. */
-    private boolean mFlingFromModelChange;
-
-    /** Disable the incognito button while selecting a tab. */
-    private boolean mAnimatingStackSwitch;
-
-    /**
-     * @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 browserControlsStateProviderSupplier The {@link ObservableSupplier} for the
-     *                                             {@link BrowserControlsStateProvider}.
-     */
-    public StackLayout(Context context, LayoutUpdateHost updateHost, LayoutRenderHost renderHost,
-            ObservableSupplier<BrowserControlsStateProvider> browserControlsStateProviderSupplier) {
-        super(context, updateHost, renderHost, browserControlsStateProviderSupplier);
-    }
-
-    @Override
-    protected boolean shouldIgnoreTouchInput() {
-        return mAnimatingStackSwitch;
-    }
-
-    @Override
-    public void setTabModelSelector(TabModelSelector modelSelector, TabContentManager manager) {
-        super.setTabModelSelector(modelSelector, manager);
-        if (modelSelector.getTabModelFilterProvider().getCurrentTabModelFilter() == null) {
-            // Registers an observer of the TabModel's creation if it hasn't been created yet. Once
-            // the TabModel is ready, we will call setTablists() immediately.
-            // See https://crbug.com/1142858.
-            TabModelSelectorObserver selectorObserver = new TabModelSelectorObserver() {
-                @Override
-                public void onChange() {
-                    mTabModelSelector.removeObserver(this);
-                    setTablists();
-                }
-            };
-            mTabModelSelector.addObserver(selectorObserver);
-        } else {
-            setTablists();
-        }
-    }
-
-    private void setTablists() {
-        ArrayList<TabList> tabLists = new ArrayList<TabList>();
-        tabLists.add(mTabModelSelector.getTabModelFilterProvider().getTabModelFilter(false));
-        tabLists.add(mTabModelSelector.getTabModelFilterProvider().getTabModelFilter(true));
-        setTabLists(tabLists);
-    }
-
-    @Override
-    protected int getTabStackIndex(int tabId) {
-        if (tabId == Tab.INVALID_TAB_ID) {
-            if (mTemporarySelectedStack != INVALID_STACK_INDEX) return mTemporarySelectedStack;
-
-            return mTabModelSelector.isIncognitoSelected() ? INCOGNITO_STACK_INDEX
-                                                           : NORMAL_STACK_INDEX;
-        } else {
-            return TabModelUtils.getTabById(mTabModelSelector.getModel(true), tabId) != null
-                    ? INCOGNITO_STACK_INDEX
-                    : NORMAL_STACK_INDEX;
-        }
-    }
-
-    @Override
-    public void onTabClosing(long time, int id) {
-        super.onTabClosing(time, id);
-        // Just in case we closed the last tab of a stack we need to trigger the overlap animation.
-        startMarginAnimation(true);
-        // Animate the stack to leave incognito mode.
-        if (!mStacks.get(INCOGNITO_STACK_INDEX).isDisplayable()) onTabModelSwitched(false);
-    }
-
-    @Override
-    public void onTabsAllClosing(long time, boolean incognito) {
-        super.onTabsAllClosing(time, incognito);
-        getTabStackAtIndex(incognito ? INCOGNITO_STACK_INDEX : NORMAL_STACK_INDEX)
-                .tabsAllClosingEffect(time);
-        // trigger the overlap animation.
-        startMarginAnimation(true);
-        // Animate the stack to leave incognito mode.
-        if (!mStacks.get(INCOGNITO_STACK_INDEX).isDisplayable()) onTabModelSwitched(false);
-    }
-
-    @Override
-    public void onTabClosureCancelled(long time, int id, boolean incognito) {
-        super.onTabClosureCancelled(time, id, incognito);
-        getTabStackAtIndex(incognito ? INCOGNITO_STACK_INDEX : NORMAL_STACK_INDEX)
-                .undoClosure(time, id);
-    }
-
-    @Override
-    public void onTabCreated(long time, int id, int tabIndex, int sourceId, boolean newIsIncognito,
-            boolean background, float originX, float originY) {
-        super.onTabCreated(
-                time, id, tabIndex, sourceId, newIsIncognito, background, originX, originY);
-        onTabModelSwitched(newIsIncognito);
-    }
-
-    @Override
-    public void onTabModelSwitched(boolean toIncognitoTabModel) {
-        flingStacks(toIncognitoTabModel ? INCOGNITO_STACK_INDEX : NORMAL_STACK_INDEX);
-        mFlingFromModelChange = true;
-    }
-
-    @Override
-    protected void onAnimationFinished() {
-        super.onAnimationFinished();
-        mFlingFromModelChange = false;
-        if (mTemporarySelectedStack != INVALID_STACK_INDEX) {
-            mTabModelSelector.selectModel(mTemporarySelectedStack == INCOGNITO_STACK_INDEX);
-            mTemporarySelectedStack = INVALID_STACK_INDEX;
-        }
-    }
-
-    @Override
-    protected int getMinRenderedScrollOffset() {
-        // If there's at least one incognito tab open, or we're in the process of switching back
-        // from incognito to normal mode, return -1 so we don't cause any clamping. Otherwise,
-        // return 0 to prevent scrolling.
-        if (mStacks.get(INCOGNITO_STACK_INDEX).isDisplayable() || mFlingFromModelChange) return -1;
-        return 0;
-    }
-
-    @Override
-    public void uiRequestingCloseTab(long time, int id) {
-        super.uiRequestingCloseTab(time, id);
-
-        int incognitoCount = mTabModelSelector.getModel(true).getCount();
-        TabModel model = mTabModelSelector.getModelForTabId(id);
-        if (model != null && model.isIncognito()) incognitoCount--;
-        boolean incognitoVisible = incognitoCount > 0;
-
-        // Make sure we show/hide both stacks depending on which tab we're closing.
-        startMarginAnimation(true, incognitoVisible);
-        if (!incognitoVisible) onTabModelSwitched(false);
-    }
-
-    @Override
-    protected @SwipeMode int computeInputMode(long time, float x, float y, float dx, float dy) {
-        if (mStacks.size() == 2 && !mStacks.get(1).isDisplayable()) return SwipeMode.SEND_TO_STACK;
-        return super.computeInputMode(time, x, y, dx, dy);
-    }
-
-    @Override
-    public void setActiveStackState(int stackIndex) {
-        if (stackIndex != getTabStackIndex(Tab.INVALID_TAB_ID)) {
-            if (stackIndex == NORMAL_STACK_INDEX) {
-                RecordUserAction.record("MobileStackViewNormalMode");
-            } else {
-                RecordUserAction.record("MobileStackViewIncognitoMode");
-            }
-        }
-
-        super.setActiveStackState(stackIndex);
-    }
-
-    @Override
-    public boolean shouldAllowIncognitoSwitching() {
-        return !mAnimatingStackSwitch;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java
deleted file mode 100644
index f330c47..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayoutBase.java
+++ /dev/null
@@ -1,1713 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.compositor.layouts.phone;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.content.Context;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.os.SystemClock;
-import android.util.Pair;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.FrameLayout;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.VisibleForTesting;
-
-import org.chromium.base.Callback;
-import org.chromium.base.MathUtils;
-import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.base.metrics.RecordUserAction;
-import org.chromium.base.supplier.ObservableSupplier;
-import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
-import org.chromium.chrome.browser.browser_controls.BrowserControlsUtils;
-import org.chromium.chrome.browser.compositor.LayerTitleCache;
-import org.chromium.chrome.browser.compositor.layouts.Layout;
-import org.chromium.chrome.browser.compositor.layouts.LayoutManagerImpl;
-import org.chromium.chrome.browser.compositor.layouts.LayoutRenderHost;
-import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost;
-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.GestureEventFilter;
-import org.chromium.chrome.browser.compositor.layouts.eventfilter.GestureHandler;
-import org.chromium.chrome.browser.compositor.layouts.phone.stack.OverlappingStack;
-import org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack;
-import org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab;
-import org.chromium.chrome.browser.compositor.scene_layer.TabListSceneLayer;
-import org.chromium.chrome.browser.homepage.HomepageManager;
-import org.chromium.chrome.browser.layouts.EventFilter;
-import org.chromium.chrome.browser.layouts.LayoutType;
-import org.chromium.chrome.browser.layouts.animation.CompositorAnimator;
-import org.chromium.chrome.browser.layouts.animation.FloatProperty;
-import org.chromium.chrome.browser.layouts.scene_layer.SceneLayer;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tabmodel.TabList;
-import org.chromium.chrome.browser.tabmodel.TabModelSelector;
-import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver;
-import org.chromium.chrome.browser.tabmodel.TabModelUtils;
-import org.chromium.ui.base.LocalizationUtils;
-import org.chromium.ui.resources.ResourceManager;
-
-import java.io.Serializable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
-
-/**
- * Base class for layouts that show one or more stacks of tabs.
- */
-public abstract class StackLayoutBase extends Layout {
-    private static final FloatProperty<StackLayoutBase> INNER_MARGIN_PERCENT =
-            new FloatProperty<StackLayoutBase>("INNER_MARGIN_PERCENT") {
-                @Override
-                public void setValue(StackLayoutBase layoutBase, float v) {
-                    layoutBase.mInnerMarginPercent = v;
-                }
-
-                @Override
-                public Float get(StackLayoutBase layoutBase) {
-                    return layoutBase.mInnerMarginPercent;
-                }
-            };
-
-    private static final FloatProperty<StackLayoutBase> STACK_OFFSET_Y_PERCENT =
-            new FloatProperty<StackLayoutBase>("STACK_OFFSET_Y_PERCENT") {
-                @Override
-                public void setValue(StackLayoutBase layoutBase, float v) {
-                    layoutBase.mStackOffsetYPercent = v;
-                }
-
-                @Override
-                public Float get(StackLayoutBase layoutBase) {
-                    return layoutBase.mStackOffsetYPercent;
-                }
-            };
-
-    private static final FloatProperty<StackLayoutBase> STACK_SNAP =
-            new FloatProperty<StackLayoutBase>("STACK_SNAP") {
-                @Override
-                public void setValue(StackLayoutBase layoutBase, float v) {
-                    layoutBase.setStackSnap(v);
-                }
-
-                @Override
-                public Float get(StackLayoutBase layoutBase) {
-                    return layoutBase.mRenderedScrollOffset == layoutBase.mScrollIndexOffset
-                            ? layoutBase.mRenderedScrollOffset
-                            : null;
-                }
-            };
-
-    @IntDef({DragDirection.NONE, DragDirection.HORIZONTAL, DragDirection.VERTICAL})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface DragDirection {
-        int NONE = 0;
-        int HORIZONTAL = 1;
-        int VERTICAL = 2;
-    }
-
-    @IntDef({SwipeMode.NONE, SwipeMode.SEND_TO_STACK, SwipeMode.SWITCH_STACK})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface SwipeMode {
-        int NONE = 0;
-        int SEND_TO_STACK = 1;
-        int SWITCH_STACK = 2;
-    }
-
-    protected static final int INVALID_STACK_INDEX = -1;
-
-    private static final String TAG = "StackLayoutBase";
-    // Width of the partially shown stack when there are multiple stacks.
-    private static final int MIN_INNER_MARGIN_PERCENT_DP = 55;
-    private static final float INNER_MARGIN_PERCENT_PERCENT = 0.17f;
-
-    // Speed of the automatic fling in dp/ms
-    private static final float FLING_SPEED_DP = 1.5f; // dp / ms
-    private static final int FLING_MIN_DURATION = 100; // ms
-
-    private static final float THRESHOLD_TO_SWITCH_STACK = 0.4f;
-
-    /**
-     * The delta time applied on the velocity from the fling. This is to compute the kick to help
-     * switching the stack.
-     */
-    private static final float SWITCH_STACK_FLING_DT = 1.0f / 30.0f;
-
-    /**
-     * True if this is currently the active layout and startHiding() has not yet been called, false
-     * otherwise.
-     */
-    protected boolean mIsActiveLayout;
-
-    /**
-     * This is true if a new tab was just created and we're in the process of hiding this layout as
-     * a result and false otherwise.
-     */
-    private boolean mIsHidingBecauseOfNewTabCreation;
-
-    /** The list of potentially visible stacks. */
-    protected final ArrayList<Stack> mStacks;
-
-    /** Rectangles that defines the area where each stack need to be laid out. */
-    protected final ArrayList<RectF> mStackRects;
-
-    private final float mDpToPx;
-
-    private int mStackAnimationCount;
-
-    private float mFlingSpeed; // pixel/ms
-
-    private boolean mClicked;
-
-    // If not overscroll, then mRenderedScrollIndex == mScrollIndex;
-    // Otherwise, mRenderedScrollIndex is updated with the actual index passed in
-    // from the event handler; and mRenderedScrollIndex is the value we get
-    // after map mScrollIndex through a decelerate function.
-    // Here we use float as index so we can smoothly animate the transition between stack.
-    protected float mRenderedScrollOffset;
-    private float mScrollIndexOffset;
-
-    private final int mMinMaxInnerMargin;
-    private float mInnerMarginPercent;
-    private float mStackOffsetYPercent;
-
-    @DragDirection
-    private int mDragDirection = DragDirection.NONE;
-
-    @SwipeMode
-    private int mInputMode = SwipeMode.NONE;
-    private float mLastOnDownX;
-    private float mLastOnDownY;
-    private long mLastOnDownTimeStamp;
-
-    private float mWidth;
-    private float mHeight;
-    private @Orientation int mOrientation;
-
-    // Pre-allocated temporary arrays that store id of visible tabs.
-    // They can be used to call populatePriorityVisibilityList.
-    // We use StackTab[] instead of ArrayList<StackTab> because the sorting function does
-    // an allocation to iterate over the elements.
-    // Do not use out of the context of {@link #updateTabPriority}.
-    private StackTab[] mSortedPriorityArray;
-
-    private final ArrayList<Integer> mVisibilityArray = new ArrayList<Integer>();
-    private final VisibilityComparator mVisibilityComparator = new VisibilityComparator();
-    private final OrderComparator mOrderComparator = new OrderComparator();
-    private Comparator<StackTab> mSortingComparator = mVisibilityComparator;
-
-    private static final int LAYOUTTAB_ASYNCHRONOUS_INITIALIZATION_BATCH_SIZE = 4;
-    private boolean mDelayedLayoutTabInitRequired;
-
-    /** Which model (normal or incognito) was active when StackLayout was shown. */
-    private int mModelIndexWhenOpened;
-
-    /** ID of the tab that was active when this layout was shown. */
-    private int mCurrentTabIdWhenOpened;
-
-    /**
-     * Temporarily stores the index of the selected tab stack. This is used to set the currently
-     * selected stack in TabModelSelector once the stack-switching animation finishes.
-     */
-    protected int mTemporarySelectedStack = INVALID_STACK_INDEX;
-
-    // Orientation Variables
-    private PortraitViewport mCachedPortraitViewport;
-    private PortraitViewport mCachedLandscapeViewport;
-
-    private final ViewGroup mViewContainer;
-
-    private final GestureEventFilter mGestureEventFilter;
-
-    private StackLayoutGestureHandler mGestureHandler;
-
-    private final ArrayList<Pair<CompositorAnimator, FloatProperty>> mLayoutAnimations =
-            new ArrayList<>();
-
-    private final ObservableSupplier<BrowserControlsStateProvider> mBrowserControlsSupplier;
-    private final BrowserControlsStateProvider.Observer mBrowserControlsObserver;
-    private Callback<BrowserControlsStateProvider> mBrowserControlsSupplierObserver;
-    private TabListSceneLayer mSceneLayer;
-    private boolean mShowPending;
-
-    private boolean mUiDoneEnteringStack;
-
-    private class StackLayoutGestureHandler implements GestureHandler {
-        @Override
-        public void onDown(float x, float y, boolean fromMouse, int buttons) {
-            long time = time();
-            mDragDirection = DragDirection.NONE;
-            mLastOnDownX = x;
-            mLastOnDownY = y;
-            mLastOnDownTimeStamp = time;
-
-            if (shouldIgnoreTouchInput()) return;
-            mStacks.get(getTabStackIndex()).onDown(time);
-        }
-
-        @Override
-        public void onUpOrCancel() {
-            onUpOrCancel(time());
-        }
-
-        @Override
-        public void drag(float x, float y, float dx, float dy, float tx, float ty) {
-            if (shouldIgnoreTouchInput()) return;
-
-            @SwipeMode
-            int oldInputMode = mInputMode;
-            long time = time();
-            float amountX = dx;
-            float amountY = dy;
-            mInputMode = computeInputMode(time, x, y, amountX, amountY);
-
-            if (mDragDirection == DragDirection.HORIZONTAL) amountY = 0;
-            if (mDragDirection == DragDirection.VERTICAL) amountX = 0;
-
-            if (oldInputMode == SwipeMode.SEND_TO_STACK && mInputMode == SwipeMode.SWITCH_STACK) {
-                mStacks.get(getTabStackIndex()).onUpOrCancel(time);
-            } else if (oldInputMode == SwipeMode.SWITCH_STACK
-                    && mInputMode == SwipeMode.SEND_TO_STACK) {
-                onUpOrCancel(time);
-            }
-
-            if (mInputMode == SwipeMode.SEND_TO_STACK) {
-                mStacks.get(getTabStackIndex()).drag(time, x, y, amountX, amountY);
-            } else if (mInputMode == SwipeMode.SWITCH_STACK) {
-                scrollStacks(isUsingHorizontalLayout() ? amountY : amountX);
-            }
-        }
-
-        @Override
-        public void click(float x, float y, boolean fromMouse, int buttons) {
-            if (shouldIgnoreTouchInput()) return;
-
-            // Click event happens before the up event. mClicked is set to mute the up event.
-            mClicked = true;
-            PortraitViewport viewportParams = getViewportParameters();
-            final int stackIndexDeltaAt = viewportParams.getStackIndexDeltaAt(x, y);
-            if (stackIndexDeltaAt == 0) {
-                mStacks.get(getTabStackIndex()).click(time(), x, y);
-            } else {
-                final int newStackIndex = getTabStackIndex() + stackIndexDeltaAt;
-                if (newStackIndex < 0 || newStackIndex >= mStacks.size()) return;
-                if (!mStacks.get(newStackIndex).isDisplayable()) return;
-                flingStacks(newStackIndex);
-            }
-            requestUpdate();
-        }
-
-        @Override
-        public void fling(float x, float y, float velocityX, float velocityY) {
-            if (shouldIgnoreTouchInput()) return;
-
-            long time = time();
-            float vx = velocityX;
-            float vy = velocityY;
-
-            if (mInputMode == SwipeMode.NONE) {
-                mInputMode = computeInputMode(
-                        time, x, y, vx * SWITCH_STACK_FLING_DT, vy * SWITCH_STACK_FLING_DT);
-            }
-
-            if (mInputMode == SwipeMode.SEND_TO_STACK) {
-                mStacks.get(getTabStackIndex()).fling(time, x, y, vx, vy);
-            } else if (mInputMode == SwipeMode.SWITCH_STACK) {
-                final float velocity = isUsingHorizontalLayout() ? vy : vx;
-                final float origin = isUsingHorizontalLayout() ? y : x;
-                final float max = isUsingHorizontalLayout() ? getHeight() : getWidth();
-                final float predicted = origin + velocity * SWITCH_STACK_FLING_DT;
-                final float delta = MathUtils.clamp(predicted, 0, max) - origin;
-                scrollStacks(delta);
-            }
-            requestUpdate();
-        }
-
-        @Override
-        public void onLongPress(float x, float y) {
-            if (shouldIgnoreTouchInput()) return;
-            mStacks.get(getTabStackIndex()).onLongPress(time(), x, y);
-        }
-
-        @Override
-        public void onPinch(float x0, float y0, float x1, float y1, boolean firstEvent) {
-            if (shouldIgnoreTouchInput()) return;
-            mStacks.get(getTabStackIndex()).onPinch(time(), x0, y0, x1, y1, firstEvent);
-        }
-
-        private void onUpOrCancel(long time) {
-            if (shouldIgnoreTouchInput()) return;
-            cancelDragTabs(time);
-        }
-
-        private void cancelDragTabs(long time) {
-            int currentIndex = getTabStackIndex();
-            if (!mClicked
-                    && Math.abs(currentIndex + mRenderedScrollOffset) > THRESHOLD_TO_SWITCH_STACK) {
-                int nextIndex;
-                if (currentIndex + mRenderedScrollOffset < 0) {
-                    nextIndex = currentIndex + 1;
-                } else {
-                    nextIndex = currentIndex - 1;
-                }
-                if (mStacks.get(nextIndex).isDisplayable()) {
-                    setActiveStackState(nextIndex);
-                }
-            }
-
-            mClicked = false;
-            finishScrollStacks();
-            mStacks.get(getTabStackIndex()).onUpOrCancel(time);
-            mInputMode = SwipeMode.NONE;
-        }
-
-        private long time() {
-            return LayoutManagerImpl.time();
-        }
-    }
-
-    /**
-     * @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 browserControlsStateProviderSupplier An {@link ObservableSupplier} for the
-     *                                             {@link BrowserControlsStateProvider}.
-     */
-    public StackLayoutBase(Context context, LayoutUpdateHost updateHost,
-            LayoutRenderHost renderHost,
-            ObservableSupplier<BrowserControlsStateProvider> browserControlsStateProviderSupplier) {
-        super(context, updateHost, renderHost);
-
-        mGestureHandler = new StackLayoutGestureHandler();
-        mGestureEventFilter = new GestureEventFilter(context, mGestureHandler);
-
-        mMinMaxInnerMargin = (int) (MIN_INNER_MARGIN_PERCENT_DP + 0.5);
-        mFlingSpeed = FLING_SPEED_DP;
-
-        mStacks = new ArrayList<Stack>();
-        mStackRects = new ArrayList<RectF>();
-        mViewContainer = new FrameLayout(getContext());
-
-        mDpToPx = context.getResources().getDisplayMetrics().density;
-        mBrowserControlsSupplier = browserControlsStateProviderSupplier;
-        mBrowserControlsObserver = new BrowserControlsStateProvider.Observer() {
-            @Override
-            public void onControlsOffsetChanged(int topOffset, int topControlsMinHeightOffset,
-                    int bottomOffset, int bottomControlsMinHeightOffset, boolean needsAnimate) {
-                if (!isActive()) return;
-
-                notifySizeChanged(mWidth, mHeight, mOrientation);
-            }
-        };
-
-        // TODO(https://crbug.com/1084528): Replace with OneShotSupplier when it is available.
-        mBrowserControlsSupplierObserver = (browserControlsStateProvider)
-                -> browserControlsStateProvider.addObserver(mBrowserControlsObserver);
-        mBrowserControlsSupplier.addObserver(mBrowserControlsSupplierObserver);
-    }
-
-    public void initWithNative() {
-        ensureSceneLayerCreated();
-        if (mShowPending) {
-            mShowPending = false;
-            show(LayoutManagerImpl.time(), false);
-        }
-    }
-
-    @Override
-    public void destroy() {
-        if (mBrowserControlsSupplier != null) {
-            mBrowserControlsSupplier.removeObserver(mBrowserControlsSupplierObserver);
-
-            if (mBrowserControlsSupplier.get() != null) {
-                mBrowserControlsSupplier.get().removeObserver(mBrowserControlsObserver);
-            }
-        }
-
-        super.destroy();
-    }
-
-    /**
-     * Sets the stack stap value.
-     *
-     * @param v Value to set.
-     */
-    private void setStackSnap(float v) {
-        mRenderedScrollOffset = v;
-        mScrollIndexOffset = v;
-    }
-
-    /**
-     * Whether or not we're currently having the tabs scroll horizontally (as opposed to
-     * vertically).
-     */
-    private boolean isUsingHorizontalLayout() {
-        return getOrientation() == Orientation.LANDSCAPE;
-    }
-
-    /**
-     * Updates this layout to show one tab stack for each of the passed-in TabLists. Takes a
-     * reference to the lists param and expects it not to change.
-     * @param lists The list of TabLists to use.
-     */
-    protected void setTabLists(List<TabList> lists) {
-        if (mStacks.size() > lists.size()) {
-            mStacks.subList(lists.size(), mStacks.size()).clear();
-        }
-        while (mStacks.size() < lists.size()) {
-            Stack stack = new OverlappingStack(getContext(), this);
-            stack.notifySizeChanged(mWidth, mHeight, mOrientation);
-            mStacks.add(stack);
-        }
-
-        for (int i = 0; i < lists.size(); i++) {
-            mStacks.get(i).setTabList(lists.get(i));
-        }
-
-        // mStackRects will get updated in updateLayout()
-    }
-
-    @Override
-    public boolean forceShowBrowserControlsAndroidView() {
-        return true;
-    }
-
-    /**
-     * A subclass can override this to return true to cause touch input to be ignored during certain
-     * operations (e.g. animations).
-     */
-    protected boolean shouldIgnoreTouchInput() {
-        return false;
-    }
-
-    /**
-     * Simulates a click on the view at the specified pixel offset
-     * from the top left of the view.
-     * This is used by UI tests.
-     * @param x Coordinate of the click in dp.
-     * @param y Coordinate of the click in dp.
-     */
-    @VisibleForTesting
-    public void simulateClick(float x, float y) {
-        mGestureHandler.click(x, y, false, -1);
-    }
-
-    /**
-     * Simulates a drag and issues Up-event to commit the drag.
-     * @param x  Coordinate to start the Drag from in dp.
-     * @param y  Coordinate to start the Drag from in dp.
-     * @param dX Amount of drag in X direction in dp.
-     * @param dY Amount of drag in Y direction in dp.
-     */
-    @VisibleForTesting
-    public void simulateDrag(float x, float y, float dX, float dY) {
-        mGestureHandler.onDown(x, y, false, -1);
-        mGestureHandler.drag(x, y, dX, dY, -1, -1);
-        mGestureHandler.onUpOrCancel();
-    }
-
-    @Override
-    public @ViewportMode int getViewportMode() {
-        return ViewportMode.ALWAYS_FULLSCREEN;
-    }
-
-    @Override
-    public void setTabModelSelector(TabModelSelector modelSelector, TabContentManager manager) {
-        super.setTabModelSelector(modelSelector, manager);
-        if (mSceneLayer != null) {
-            mSceneLayer.setTabModelSelector(modelSelector);
-        }
-        resetScrollData();
-
-        new TabModelSelectorTabModelObserver(mTabModelSelector) {
-            @Override
-            public void tabClosureUndone(Tab tab) {
-                if (!isActive()) return;
-                onTabClosureCancelled(LayoutManagerImpl.time(), tab.getId(), tab.isIncognito());
-            }
-        };
-    }
-
-    /**
-     * Called when a tab close has been undone and the tab has been restored.
-     * @param time      The current time of the app in ms.
-     * @param id        The id of the Tab.
-     * @param incognito True if the tab is incognito
-     */
-    public void onTabClosureCancelled(long time, int id, boolean incognito) {}
-
-    /**
-     * Get the tab stack at the specified index.
-     *
-     * @param index Which stack should be returned.
-     * @return The stack at the specified index.
-     * @VisibleForTesting
-     */
-    public Stack getTabStackAtIndex(int index) {
-        return mStacks.get(index);
-    }
-
-    /**
-     * Get the tab stack state.
-     * @return The tab stack index for the given tab id.
-     */
-    private int getTabStackIndex() {
-        return getTabStackIndex(Tab.INVALID_TAB_ID);
-    }
-
-    /**
-     * Get the tab stack state for the specified tab id.
-     *
-     * @param tabId The id of the tab to lookup.
-     * @return The tab stack index for the given tab id.
-     * @VisibleForTesting
-     */
-    protected abstract int getTabStackIndex(int tabId);
-
-    /**
-     * Get the tab stack state for the specified tab id.
-     *
-     * @param tabId The id of the tab to lookup.
-     * @return The tab stack state for the given tab id.
-     * @VisibleForTesting
-     */
-    protected Stack getTabStackForTabId(int tabId) {
-        return mStacks.get(getTabStackIndex(tabId));
-    }
-
-    /**
-     * Commits outstanding model states.
-     * @param time  The current time of the app in ms.
-     */
-    public void commitOutstandingModelState(long time) {
-        for (int i = 0; i < mStacks.size(); i++) {
-            mStacks.get(i).ensureCleaningUpDyingTabs(time);
-        }
-    }
-
-    @Override
-    public void onTabSelecting(long time, int tabId) {
-        // We update TabModelSelector's current model when incognito mode is toggled in the tab
-        // switcher. So the "current model index" is already the one that we're leaving active when
-        // the tab switcher is closed.
-        final int newModelIndex = mTabModelSelector.getCurrentModelIndex();
-        if (newModelIndex != mModelIndexWhenOpened) {
-            final int indexInNewModel = mTabModelSelector.getCurrentModel().index();
-            if (indexInNewModel == mTabModelSelector.getCurrentModel().index()) {
-                // TabModelImpl logs this action when we switch to a different index within a
-                // TabModelImpl. If we switch between TabModelImpls (i.e. switch between normal and
-                // incognito mode), but leave the index the same (i.e. switch back to the most
-                // recently active tab in that stack), TabModelImpl doesn't catch that case, so we
-                // log it here.
-                RecordUserAction.record("MobileTabSwitched");
-            }
-        }
-
-        commitOutstandingModelState(time);
-        if (tabId == Tab.INVALID_TAB_ID) tabId = mTabModelSelector.getCurrentTabId();
-        super.onTabSelecting(time, tabId);
-        mStacks.get(getTabStackIndex()).tabSelectingEffect(time, tabId);
-        startMarginAnimation(false);
-        startYOffsetAnimation(false);
-        finishScrollStacks();
-    }
-
-    @Override
-    public void onTabClosing(long time, int id) {
-        Stack stack = getTabStackForTabId(id);
-        if (stack == null) return;
-        stack.tabClosingEffect(time, id);
-    }
-
-    @Override
-    public boolean handlesCloseAll() {
-        return true;
-    }
-
-    @Override
-    public boolean handlesTabCreating() {
-        return true;
-    }
-
-    @Override
-    public boolean handlesTabClosing() {
-        return true;
-    }
-
-    @Override
-    public void attachViews(ViewGroup container) {
-        // TODO(dtrainor): This is a hack.  We're attaching to the parent of the view container
-        // which is the content container of the Activity.
-        ((ViewGroup) container.getParent())
-                .addView(mViewContainer,
-                        new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
-    }
-
-    @Override
-    public void detachViews() {
-        if (mViewContainer.getParent() != null) {
-            ((ViewGroup) mViewContainer.getParent()).removeView(mViewContainer);
-        }
-        mViewContainer.removeAllViews();
-    }
-
-    /**
-     * @return A {@link ViewGroup} that {@link Stack}s can use to interact with the Android view
-     *         hierarchy.
-     */
-    public ViewGroup getViewContainer() {
-        return mViewContainer;
-    }
-
-    @Override
-    public boolean onBackPressed() {
-        // Force any in progress animations to end. This was introduced because
-        // we end up with 0 tabs if the animation for all tabs closing is still
-        // running when the back button is pressed. We should finish the animation
-        // and close Chrome instead.
-        // See http://crbug.com/522447
-        onUpdateAnimation(SystemClock.currentThreadTimeMillis(), true);
-        return false;
-    }
-
-    @Override
-    public void onTabCreating(int sourceTabId) {
-        // Force any in progress animations to end. This was introduced because
-        // we end up with 0 tabs if the animation for all tabs closing is still
-        // running when a new tab is created.
-        // See http://crbug.com/496557
-        onUpdateAnimation(SystemClock.currentThreadTimeMillis(), true);
-    }
-
-    @Override
-    public void onTabCreated(long time, int id, int tabIndex, int sourceId, boolean newIsIncognito,
-            boolean background, float originX, float originY) {
-        super.onTabCreated(
-                time, id, tabIndex, sourceId, newIsIncognito, background, originX, originY);
-
-        // Suppress startHiding()'s logging to the Tabs.TabOffsetOfSwitch histogram.
-        mIsHidingBecauseOfNewTabCreation = true;
-        startHiding(id, false);
-        mStacks.get(getTabStackIndex(id)).tabCreated(time, id);
-
-        startMarginAnimation(false);
-    }
-
-    // This method is called if the following sequence of operations occurs:
-    // 1. Enter multi-window mode
-    // 2. Create a second Chrome instance by moving a tab to the other window
-    // 3. In the top window, enter the tab switcher
-    // 4. Expand the top window to full screen.
-    @Override
-    public void onTabRestored(long time, int tabId) {
-        super.onTabRestored(time, tabId);
-        // Call show() so that new stack tabs and potentially new stacks get created.
-        // TODO(twellington): add animation for showing the restored tab.
-        if (mSceneLayer == null) {
-            mShowPending = true;
-            return;
-        }
-        show(time, false);
-    }
-
-    @Override
-    public boolean onUpdateAnimation(long time, boolean jumpToEnd) {
-        boolean animationsWasDone = true;
-        if (!mLayoutAnimations.isEmpty()) {
-            if (jumpToEnd) {
-                forceAnimationToFinish();
-            } else {
-                animationsWasDone = !isLayoutAnimating();
-            }
-            if (animationsWasDone || jumpToEnd) {
-                onAnimationFinished();
-            }
-        }
-
-        boolean finishedAllViews = true;
-        for (int i = 0; i < mStacks.size(); i++) {
-            finishedAllViews &= mStacks.get(i).onUpdateViewAnimation(time, jumpToEnd);
-        }
-
-        boolean finishedAllCompositors = true;
-        for (int i = 0; i < mStacks.size(); i++) {
-            finishedAllCompositors &= mStacks.get(i).onUpdateCompositorAnimations(time, jumpToEnd);
-        }
-
-        if (animationsWasDone && finishedAllViews && finishedAllCompositors) {
-            return true;
-        } else {
-            if (!animationsWasDone || !finishedAllCompositors) requestUpdate();
-            return false;
-        }
-    }
-
-    /**
-     * Called when layout-specific actions are needed after the animation finishes.
-     */
-    protected void onAnimationStarted() {
-    }
-
-    /**
-     * Called when layout-specific actions are needed after the animation finishes.
-     */
-    protected void onAnimationFinished() {
-    }
-
-    /**
-     * Called when a UI element is attempting to select a tab.  This will perform the animation
-     * and then actually propagate the action.  This starts hiding this layout which, when complete,
-     * will actually select the tab.
-     * @param time The current time of the app in ms.
-     * @param id   The id of the tab to select.
-     */
-    public void uiSelectingTab(long time, int id) {
-        onTabSelecting(time, id);
-    }
-
-    /**
-     * Called when a UI element is attempting to close a tab.  This will perform the required close
-     * animations.  When the UI is ready to actually close the tab
-     * {@link #uiDoneClosingTab(long, int, boolean, boolean)} should be called to actually propagate
-     * the event to the model.
-     * @param time The current time of the app in ms.
-     * @param id   The id of the tab to close.
-     */
-    public void uiRequestingCloseTab(long time, int id) {
-        // Start the tab closing effect if necessary.
-        getTabStackForTabId(id).tabClosingEffect(time, id);
-    }
-
-    /**
-     * Called when a UI element is done animating the close tab effect started by
-     * {@link #uiRequestingCloseTab(long, int)}.  This actually pushes the close event to the model.
-     * @param time      The current time of the app in ms.
-     * @param id        The id of the tab to close.
-     * @param canUndo   Whether or not this close can be undone.
-     * @param incognito Whether or not this was for the incognito stack or not.
-     */
-    public void uiDoneClosingTab(
-            final long time, final int id, boolean canUndo, final boolean incognito) {
-        // If there are any ongoing layout animations, postpone this until they are done since
-        // closeTabById does a lot of work.
-        for (int i = 0; i < mLayoutAnimations.size(); i++) {
-            if (mLayoutAnimations.get(i).first.isRunning()) {
-                final boolean cachedCanUndo = canUndo;
-                final AnimatorListenerAdapter adapter = new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationEnd(Animator animation) {
-                        uiDoneClosingTab(time, id, cachedCanUndo, incognito);
-                        animation.removeListener(this);
-                    }
-                };
-                mLayoutAnimations.get(i).first.addListener(adapter);
-                return;
-            }
-        }
-
-        assert !isLayoutAnimating();
-
-        // If homepage is enabled and there is a maximum of 1 tab in both models
-        // (this is the last tab), the tab closure cannot be undone.
-        canUndo &= !(HomepageManager.shouldCloseAppWithZeroTabs()
-                && (mTabModelSelector.getModel(true).getCount()
-                                   + mTabModelSelector.getModel(false).getCount()
-                           < 2));
-
-        // Propagate the tab closure to the model.
-        TabModelUtils.closeTabById(mTabModelSelector.getModel(incognito), id, canUndo);
-    }
-
-    public void uiDoneClosingAllTabs(boolean incognito) {
-        // Propagate the tab closure to the model.
-        mTabModelSelector.getModel(incognito).closeAllTabs(false, false);
-    }
-
-    /**
-     * Called when a {@link Stack} instance is done animating the stack enter effect.
-     */
-    public void uiDoneEnteringStack() {
-        mUiDoneEnteringStack = true;
-        // Tabs don't overlap in the horizontal tab switcher experiment, so the order comparator
-        // already does what we want (the visibility comparator's logic actually doesn't compute
-        // visibility properly in this case).
-        mSortingComparator = mVisibilityComparator;
-        doneShowing();
-    }
-
-    /**
-     * Starts the animation for the opposite stack to slide in or out when entering
-     * or leaving stack view.  The animation should be super fast to match more or less
-     * the fling animation.
-     * @param enter True if the stack view is being entered, false if the stack view
-     *              is being left.
-     */
-    protected void startMarginAnimation(boolean enter) {
-        startMarginAnimation(enter, mStacks.size() >= 2 && mStacks.get(1).isDisplayable());
-    }
-
-    protected void startMarginAnimation(boolean enter, boolean showMargin) {
-        // Any outstanding animations must be cancelled to avoid race condition.
-        cancelAnimation(INNER_MARGIN_PERCENT);
-
-        float start = mInnerMarginPercent;
-        float end = enter && showMargin ? 1.0f : 0.0f;
-        if (start != end) {
-            addToAnimation(INNER_MARGIN_PERCENT, start, end, 200, 0);
-        }
-    }
-
-    private void startYOffsetAnimation(boolean enter) {
-        // Any outstanding animations must be cancelled to avoid race condition.
-        cancelAnimation(STACK_OFFSET_Y_PERCENT);
-
-        float start = mStackOffsetYPercent;
-        float end = enter ? 1.f : 0.f;
-        if (start != end) {
-            addToAnimation(STACK_OFFSET_Y_PERCENT, start, end, 300, 0);
-        }
-    }
-
-    @Override
-    public void show(long time, boolean animate) {
-        super.show(time, animate);
-        mUiDoneEnteringStack = false;
-
-        if (!mIsActiveLayout) {
-            // The mIsActiveLayout check is necessary because there are certain edge cases where
-            // show() is called (e.g. to refresh the Stacks) while the tab switcher is already
-            // showing.
-
-            // Note: there are some edge cases (e.g. the last open tab is closed somehow while the
-            // tab switcher is not open) that can also cause this event to be logged without a
-            // toolbar interaction. The event name contains "Toolbar" for historical reasons; the
-            // current intent is to log whenever the tab switcher is entered.
-            RecordUserAction.record("MobileToolbarShowStackView");
-
-            mModelIndexWhenOpened = mTabModelSelector.getCurrentModelIndex();
-            mCurrentTabIdWhenOpened = mTabModelSelector.getCurrentTabId();
-        }
-        mIsActiveLayout = true;
-
-        Tab tab = mTabModelSelector.getCurrentTab();
-        if (tab != null && tab.isNativePage()) mTabContentManager.cacheTabThumbnail(tab);
-
-        // Remove any views in case we're getting another call to show before we hide (quickly
-        // toggling the tab switcher button).
-        mViewContainer.removeAllViews();
-        int currentTabStack = getTabStackIndex();
-
-        for (int i = mStacks.size() - 1; i >= 0; --i) {
-            mStacks.get(i).reset();
-            if (mStacks.get(i).isDisplayable()) {
-                mStacks.get(i).show(i == currentTabStack);
-            } else {
-                mStacks.get(i).cleanupTabs();
-            }
-        }
-        // Initialize the animation and the positioning of all the elements
-        mSortingComparator = mOrderComparator;
-        resetScrollData();
-        for (int i = mStacks.size() - 1; i >= 0; --i) {
-            if (mStacks.get(i).isDisplayable()) {
-                boolean offscreen = (i != getTabStackIndex());
-                mStacks.get(i).stackEntered(time, !offscreen);
-            }
-        }
-        startMarginAnimation(true);
-        startYOffsetAnimation(true);
-        flingStacks(getTabStackIndex());
-
-        if (!animate) onUpdateAnimation(time, true);
-
-        // We will render before we get a call to updateLayout.  Need to make sure all of the tabs
-        // we need to render are up to date.
-        updateLayout(time, 0);
-    }
-
-    @Override
-    public void doneShowing() {
-        if (!mUiDoneEnteringStack) return;
-
-        super.doneShowing();
-
-        if (mBrowserControlsSupplier.get() != null) {
-            mBrowserControlsSupplier.get().addObserver(mBrowserControlsObserver);
-            notifySizeChanged(mWidth, mHeight, mOrientation);
-        }
-    }
-
-    @Override
-    public void notifySizeChanged(float width, float height, @Orientation int orientation) {
-        mWidth = width;
-        mHeight = height;
-        mOrientation = orientation;
-        mCachedLandscapeViewport = null;
-        mCachedPortraitViewport = null;
-        for (Stack stack : mStacks) {
-            stack.notifySizeChanged(width, height, orientation);
-        }
-        resetScrollData();
-        requestUpdate();
-    }
-
-    @Override
-    public void contextChanged(Context context) {
-        super.contextChanged(context);
-        StackTab.resetDimensionConstants(context);
-        for (Stack stack : mStacks) {
-            stack.contextChanged(context);
-        }
-        requestUpdate();
-    }
-
-    protected int getMinRenderedScrollOffset() {
-        return -(mStacks.size() - 1);
-    }
-
-    /**
-     * Computes the input mode for drag and fling based on the first event position.
-     * @param time The current time of the app in ms.
-     * @param x    The x layout position of the mouse (without the displacement).
-     * @param y    The y layout position of the mouse (without the displacement).
-     * @param dx   The x displacement happening this frame.
-     * @param dy   The y displacement happening this frame.
-     * @return     The input mode to select.
-     */
-    protected @SwipeMode int computeInputMode(long time, float x, float y, float dx, float dy) {
-        if (mStacks.size() == 0) return SwipeMode.NONE;
-        if (mStacks.size() == 1) return SwipeMode.SEND_TO_STACK;
-
-        int currentIndex = getTabStackIndex();
-
-        // When a drag starts, lock the drag into being either horizontal or vertical until the
-        // next touch down. The deltas here are already verified by StackLayoutGestureHandler as
-        // being above some threshold so that we know we're handling a drag or fling and not a long
-        // press.
-        if (mDragDirection == DragDirection.NONE) {
-            if (Math.abs(dx) > Math.abs(dy)) {
-                mDragDirection = DragDirection.HORIZONTAL;
-            } else {
-                mDragDirection = DragDirection.VERTICAL;
-            }
-        }
-
-        if ((mDragDirection == DragDirection.VERTICAL) ^ isUsingHorizontalLayout()) {
-            return SwipeMode.SEND_TO_STACK;
-        }
-
-        float relativeX = mLastOnDownX - (x + dx);
-        float relativeY = mLastOnDownY - (y + dy);
-        float switchDelta = isUsingHorizontalLayout() ? relativeY : relativeX;
-
-        // In LTR portrait mode, the first stack can be swiped to the left to switch to the second
-        // stack, and the last stack can be swiped to the right to switch to the first stack. We
-        // reverse the check for RTL portrait mode because increasing the stack index corresponds
-        // to a negative switchDelta. If there are more than two stacks, we do not currently support
-        // swiping to close on any of the stacks in the middle
-        //
-        // Landscape mode is like LTR portrait mode (increasing the stack index corresponds to a
-        // positive switchDelta).
-        final boolean isRtlPortraitMode =
-                (!isUsingHorizontalLayout() && LocalizationUtils.isLayoutRtl());
-        final boolean onLeftmostStack = (currentIndex == 0 && !isRtlPortraitMode)
-                || (currentIndex == mStacks.size() - 1 && isRtlPortraitMode);
-        final boolean onRightmostStack = (currentIndex == 0 && isRtlPortraitMode)
-                || (currentIndex == mStacks.size() - 1 && !isRtlPortraitMode);
-        if ((onLeftmostStack && switchDelta < 0) || (onRightmostStack && switchDelta > 0)) {
-            // Dragging in a direction the stack cannot switch. Pass the drag to the Stack, which
-            // will treat it as intending to discard a tab.
-            return SwipeMode.SEND_TO_STACK;
-        } else {
-            // Interpret the drag as intending to switch between tab stacks.
-            return SwipeMode.SWITCH_STACK;
-        }
-    }
-
-    class PortraitViewport {
-        protected float mWidth;
-        protected float mHeight;
-        PortraitViewport() {
-            mWidth = StackLayoutBase.this.getWidth();
-            mHeight = StackLayoutBase.this.getHeightMinusContentOffsetsDp();
-        }
-
-        float getClampedRenderedScrollOffset() {
-            return MathUtils.clamp(mRenderedScrollOffset, 0, getMinRenderedScrollOffset());
-        }
-
-        float getInnerMargin() {
-            float margin = mInnerMarginPercent
-                    * Math.max(mMinMaxInnerMargin, mWidth * INNER_MARGIN_PERCENT_PERCENT);
-            return margin;
-        }
-
-        /**
-         * Returns an offset that can be added to the index of the current stack to get the index of
-         * the stack at the specified on-screen location.
-         * @param x The x coordinate of the specified on-screen location.
-         * @param y The x coordinate of the specified on-screen location.
-         * @return  The offset to be added to the index of the current stack.
-         */
-        int getStackIndexDeltaAt(float x, float y) {
-            int delta = 0;
-            if (x < getCurrentStackLeft()) {
-                delta = -1;
-            } else if (x > getCurrentStackLeft() + getWidth()) {
-                delta = 1;
-            }
-
-            // Tabs are counted from left to right in LTR mode, but from right to left in RTL mode.
-            if (LocalizationUtils.isLayoutRtl()) delta *= -1;
-
-            return delta;
-        }
-
-        /**
-         * @return The current x coordinate for the left edge of the first stack (right edge if in
-         * RTL mode).
-         */
-        float getStack0Left() {
-            float stack0LeftLtr = getClampedRenderedScrollOffset() * getFullScrollDistance();
-            if (mStacks.size() > 2) {
-                // If we have one or two stacks, we only show a margin on the right side of the left
-                // stack and on the left side of the right stack. But if we have three or more
-                // stacks, we put a margin on both sides
-                stack0LeftLtr += getInnerMargin() / 2;
-            }
-
-            if (LocalizationUtils.isLayoutRtl()) return getInnerMargin() - stack0LeftLtr;
-
-            return stack0LeftLtr;
-        }
-
-        /**
-         * @return The current x coordinate for the left edge of the current stack (actually the
-         * right edge if in RTL mode).
-         */
-        float getCurrentStackLeft() {
-            float offset = getClampedRenderedScrollOffset() + getTabStackIndex();
-            if (mStacks.size() > 2) {
-                return offset * getFullScrollDistance() + getInnerMargin() / 2;
-            }
-
-            // Note: getInnerMargin() is zero if there's only one stack.
-            boolean isRightStack = (getTabStackIndex() == 1) ^ LocalizationUtils.isLayoutRtl();
-            return offset * getFullScrollDistance() + (isRightStack ? getInnerMargin() : 0);
-        }
-
-        float getWidth() {
-            return mWidth - getInnerMargin();
-        }
-
-        float getHeight() {
-            return mHeight;
-        }
-
-        float getStack0Top() {
-            return getTopHeightOffset();
-        }
-
-        float getStack0ToStack1TranslationX() {
-            return Math.round(LocalizationUtils.isLayoutRtl() ? -mWidth + getInnerMargin()
-                                                              : mWidth - getInnerMargin());
-        }
-
-        float getStack0ToStack1TranslationY() {
-            return 0.0f;
-        }
-
-        float getTopHeightOffset() {
-            return getTopContentOffsetDp() * mStackOffsetYPercent;
-        }
-    }
-
-    class LandscapeViewport extends PortraitViewport {
-        LandscapeViewport() {
-            // This is purposefully inverted.
-            mWidth = StackLayoutBase.this.getHeightMinusContentOffsetsDp();
-            mHeight = StackLayoutBase.this.getWidth();
-        }
-
-        @Override
-        float getInnerMargin() {
-            float margin = mInnerMarginPercent
-                    * Math.max(mMinMaxInnerMargin, mWidth * INNER_MARGIN_PERCENT_PERCENT);
-            return margin;
-        }
-
-        @Override
-        int getStackIndexDeltaAt(float x, float y) {
-            if (y < getCurrentStackTop()) return -1;
-            if (y > getCurrentStackTop() + getHeight()) return 1;
-            return 0;
-        }
-
-        @Override
-        float getStack0Left() {
-            return 0.f;
-        }
-
-        @Override
-        float getStack0Top() {
-            return getClampedRenderedScrollOffset() * getFullScrollDistance()
-                    + getTopHeightOffset();
-        }
-
-        /**
-         * @return The current y coordinate for the top edge of the current stack.
-         */
-        float getCurrentStackTop() {
-            float offset = getClampedRenderedScrollOffset() + getTabStackIndex();
-            if (mStacks.size() > 2) {
-                return offset * getFullScrollDistance() + getInnerMargin() / 2
-                        + getTopHeightOffset();
-            }
-
-            return offset * getFullScrollDistance()
-                    + ((getTabStackIndex() == 1) ? getInnerMargin() : 0) + getTopHeightOffset();
-        }
-
-        @Override
-        float getWidth() {
-            return super.getHeight();
-        }
-
-        @Override
-        float getHeight() {
-            return super.getWidth();
-        }
-
-        @Override
-        float getStack0ToStack1TranslationX() {
-            return super.getStack0ToStack1TranslationY();
-        }
-
-        @Override
-        float getStack0ToStack1TranslationY() {
-            // Need getHeight() for this case instead of getHeightMinusBrowserControls() so the
-            // normal stack goes up high enough to clear the status bar when the incognito stack is
-            // active.
-            return Math.round(mWidth - getInnerMargin());
-        }
-    }
-
-    /**
-     * @return The height of the drawing area minus the top and bottom content offsets in dp.
-     */
-    public float getHeightMinusContentOffsetsDp() {
-        return getHeight() - (getTopContentOffsetDp() + getBottomContentOffsetDp());
-    }
-
-    /**
-     * @return The offset of the content from the top of the screen in dp.
-     */
-    public float getTopContentOffsetDp() {
-        final BrowserControlsStateProvider provider = mBrowserControlsSupplier.get();
-        return provider != null ? provider.getContentOffset() / mDpToPx : 0.f;
-    }
-
-    /**
-     * @return The offset of the content from the bottom of the screen in dp.
-     */
-    private float getBottomContentOffsetDp() {
-        final BrowserControlsStateProvider provider = mBrowserControlsSupplier.get();
-        return provider != null ? BrowserControlsUtils.getBottomContentOffset(provider) / mDpToPx
-                                : 0.f;
-    }
-
-    private PortraitViewport getViewportParameters() {
-        if (isUsingHorizontalLayout()) {
-            if (mCachedLandscapeViewport == null) {
-                mCachedLandscapeViewport = new LandscapeViewport();
-            }
-            return mCachedLandscapeViewport;
-        } else {
-            if (mCachedPortraitViewport == null) {
-                mCachedPortraitViewport = new PortraitViewport();
-            }
-            return mCachedPortraitViewport;
-        }
-    }
-
-    /**
-     * Scrolls the tab stacks by amount delta (clamped so that it's not possible to scroll past the
-     * last stack in either direciton). Positive delta corresponds to increasing the x coordinate
-     * in portrait mode (in both LTR and RTL modes), or increasing the y coordinate in landscape
-     * mode.
-     * @param delta The amount to scroll by.
-     */
-    private void scrollStacks(float delta) {
-        cancelAnimation(STACK_SNAP);
-        float fullDistance = getFullScrollDistance();
-        mScrollIndexOffset += MathUtils.flipSignIf(delta / fullDistance,
-                !isUsingHorizontalLayout() && LocalizationUtils.isLayoutRtl());
-        mRenderedScrollOffset =
-                MathUtils.clamp(mScrollIndexOffset, 0, getMinRenderedScrollOffset());
-        requestUpdate();
-    }
-
-    /**
-     * Scrolls over to the tab stack at the specified index, and records that it's now the current
-     * tab stack.
-     * @param index The index of the newly-selected tab stack.
-     */
-    protected void flingStacks(int index) {
-        setActiveStackState(index);
-        finishScrollStacks();
-        requestUpdate();
-    }
-
-    /**
-     * Animate to the final position of the stack.  Unfortunately, both touch-up
-     * and fling can be called and this depends on fling always being called last.
-     * If fling is called first, onUpOrCancel can override the fling position
-     * with the opposite.  For example, if the user does a very small fling from
-     * incognito to non-incognito, which leaves the up event in the incognito side.
-     */
-    private void finishScrollStacks() {
-        cancelAnimation(STACK_SNAP);
-        final int currentModelIndex = getTabStackIndex();
-        float delta = Math.abs(currentModelIndex + mRenderedScrollOffset);
-        float target = -currentModelIndex;
-        if (delta != 0) {
-            long duration = FLING_MIN_DURATION
-                    + (long) Math.abs(delta * getFullScrollDistance() / mFlingSpeed);
-            addToAnimation(STACK_SNAP, mRenderedScrollOffset, target, duration, 0);
-        } else {
-            setStackSnap(target);
-            onAnimationFinished();
-        }
-    }
-
-    /**
-     * Pushes a rectangle to be drawn on the screen on top of everything.
-     *
-     * @param rect  The rectangle to be drawn on screen
-     * @param color The color of the rectangle
-     */
-    public void pushDebugRect(Rect rect, int color) {
-        if (rect.left > rect.right) {
-            int tmp = rect.right;
-            rect.right = rect.left;
-            rect.left = tmp;
-        }
-        if (rect.top > rect.bottom) {
-            int tmp = rect.bottom;
-            rect.bottom = rect.top;
-            rect.top = tmp;
-        }
-        mRenderHost.pushDebugRect(rect, color);
-    }
-
-    @Override
-    protected void updateLayout(long time, long dt) {
-        if (mStacks.size() == 0) return;
-
-        super.updateLayout(time, dt);
-        boolean needUpdate = false;
-
-        if (mStackRects.size() > mStacks.size()) {
-            mStackRects.subList(mStacks.size(), mStackRects.size()).clear();
-        }
-        while (mStackRects.size() < mStacks.size()) mStackRects.add(new RectF());
-
-        final PortraitViewport viewport = getViewportParameters();
-
-        if (!mStackRects.isEmpty()) {
-            mStackRects.get(0).left = viewport.getStack0Left();
-            mStackRects.get(0).right = mStackRects.get(0).left + viewport.getWidth();
-            mStackRects.get(0).top = viewport.getStack0Top();
-            mStackRects.get(0).bottom = mStackRects.get(0).top + viewport.getHeight();
-        }
-
-        for (int i = 1; i < mStackRects.size(); i++) {
-            mStackRects.get(i).left =
-                    mStackRects.get(i - 1).left + viewport.getStack0ToStack1TranslationX();
-            mStackRects.get(i).right = mStackRects.get(i).left + viewport.getWidth();
-            mStackRects.get(i).top =
-                    mStackRects.get(i - 1).top + viewport.getStack0ToStack1TranslationY();
-            mStackRects.get(i).bottom = mStackRects.get(i).top + viewport.getHeight();
-        }
-
-        for (int i = 0; i < mStacks.size(); i++) {
-            final float scrollDistance = Math.abs(i + mRenderedScrollOffset);
-            final float stackFocus = MathUtils.clamp(1 - scrollDistance, 0, 1);
-
-            // The overlapping stack only uses the OrderComparator for visibliity prioritization
-            // during the animation to open the tab switcher. For this case, we pass a fixed index
-            // for the currently-selected tab.
-            //
-            // If the non-overlapping horizontal tab switcher experiment is enabled, we pass -1 so
-            // NonOverlappingStack can use the scroll position to keep the index used for visibility
-            // prioritization up-to-date.
-            final boolean useFixedIndex = mSortingComparator == mOrderComparator;
-            mStacks.get(i).setStackFocusInfo(
-                    stackFocus, useFixedIndex ? mStacks.get(i).getTabList().index() : -1);
-        }
-
-        // Compute position and visibility
-        for (int i = 0; i < mStacks.size(); i++) {
-            mStacks.get(i).computeTabPosition(time, mStackRects.get(i));
-        }
-
-        // Pre-allocate/resize {@link #mLayoutTabs} before it get populated by
-        // computeTabPositionAndAppendLayoutTabs.
-        int tabVisibleCount = 0;
-        for (int i = 0; i < mStacks.size(); i++) {
-            tabVisibleCount += mStacks.get(i).getVisibleCount();
-        }
-
-        if (tabVisibleCount == 0) {
-            mLayoutTabs = null;
-        } else if (mLayoutTabs == null || mLayoutTabs.length != tabVisibleCount) {
-            mLayoutTabs = new LayoutTab[tabVisibleCount];
-        }
-
-        int index = 0;
-        for (int i = 0; i < mStacks.size(); i++) {
-            // Append tabs for the current stack last so they get priority in rendering.
-            if (getTabStackIndex() == i) continue;
-            index = appendVisibleLayoutTabs(time, i, mLayoutTabs, index);
-        }
-        index = appendVisibleLayoutTabs(time, getTabStackIndex(), mLayoutTabs, index);
-        assert index == tabVisibleCount : "index should be incremented up to tabVisibleCount";
-
-        // Update tab snapping
-        for (int i = 0; i < tabVisibleCount; i++) {
-            if (updateSnap(dt, mLayoutTabs[i])) needUpdate = true;
-        }
-
-        if (needUpdate) requestUpdate();
-
-        // Since we've updated the positions of the stacks and tabs, let's go ahead and update
-        // the visible tabs.
-        updateTabPriority();
-    }
-
-    private int appendVisibleLayoutTabs(long time, int stackIndex, LayoutTab[] tabs, int tabIndex) {
-        final StackTab[] stackTabs = mStacks.get(stackIndex).getTabs();
-        if (stackTabs != null) {
-            for (int i = 0; i < stackTabs.length; i++) {
-                LayoutTab t = stackTabs[i].getLayoutTab();
-                if (t.isVisible()) tabs[tabIndex++] = t;
-            }
-        }
-        return tabIndex;
-    }
-
-    /**
-     * Sets the active tab stack.
-     *
-     * @param stackIndex Index of the tab stack to be made active.
-     */
-    public void setActiveStackState(int stackIndex) {
-        mTemporarySelectedStack = stackIndex;
-    }
-
-    private void resetScrollData() {
-        mScrollIndexOffset = -getTabStackIndex();
-        mRenderedScrollOffset = mScrollIndexOffset;
-    }
-
-    /**
-     * @return The distance between two neighboring tab stacks.
-     */
-    private float getFullScrollDistance() {
-        float distance = isUsingHorizontalLayout() ? getHeightMinusContentOffsetsDp() : getWidth();
-        if (mStacks.size() > 2) {
-            return distance - getViewportParameters().getInnerMargin();
-        }
-
-        return distance - 2 * getViewportParameters().getInnerMargin();
-    }
-
-    @Override
-    public void startHiding(int nextTabId, boolean hintAtTabSelection) {
-        if (mBrowserControlsSupplier.get() != null) {
-            mBrowserControlsSupplier.get().removeObserver(mBrowserControlsObserver);
-        }
-
-        super.startHiding(nextTabId, hintAtTabSelection);
-
-        // Reset mIsActiveLayout here instead of in doneHiding() so if a user hits the tab switcher
-        // button on the toolbar to re-open it while we're still in the process of hiding the tab
-        // switcher, we don't skip the logging.
-        mIsActiveLayout = false;
-
-        if (mCurrentTabIdWhenOpened == nextTabId) {
-            RecordUserAction.record("MobileTabReturnedToCurrentTab");
-        }
-    }
-
-    @Override
-    public void doneHiding() {
-        // Log offset between newly-selected and previously-active tabs. A positive offset means the
-        // user switched to a tab earlier in the stack. A negative offset means the user switched to
-        // a tab later in the stack. 0 means they stayed on the same tab. We do not log anything if
-        // the user switched between stacks (normal to incognito or vice-versa). We also do not log
-        // anything if the tab switch was the result of a new tab being created (we do log for
-        // presses of the tab switcher button on the toolbar).
-
-        // Note: we log this in doneHiding() instead of startHiding() because Layout#doneHiding() is
-        // where the new tab actually gets selected. If the user immediately reopens the tab
-        // switcher before the close animation finishes, the new tab doesn't actually get selected.
-        if (!mIsHidingBecauseOfNewTabCreation
-                && mModelIndexWhenOpened == mTabModelSelector.getCurrentModelIndex()) {
-            final int currentIndex = mTabModelSelector.getCurrentModel().index();
-            final Tab newTab = mTabModelSelector.getTabById(mNextTabId);
-            final int newIndex = mTabModelSelector.getCurrentModel().indexOf(newTab);
-            assert newIndex != TabList.INVALID_TAB_INDEX;
-            RecordHistogram.recordSparseHistogram(
-                    "Tabs.TabOffsetOfSwitch", currentIndex - newIndex);
-        }
-        mIsHidingBecauseOfNewTabCreation = false;
-
-        super.doneHiding();
-        RecordUserAction.record("MobileExitStackView");
-
-        mInnerMarginPercent = 0.0f;
-        mStackOffsetYPercent = 0.0f;
-        mTabModelSelector.commitAllTabClosures();
-    }
-
-    /**
-     * Extracts the tabs from a stack and append them into a list.
-     * @param stack     The stack that contains the tabs.
-     * @param outList   The output list where will be the tabs from the stack.
-     * @param index     The current number of item in the outList.
-     * @return The updated index incremented by the number of tabs in the stack.
-     */
-    private static int addAllTabs(Stack stack, StackTab[] outList, int index) {
-        StackTab[] stackTabs = stack.getTabs();
-        if (stackTabs != null) {
-            for (int i = 0; i < stackTabs.length; ++i) {
-                outList[index++] = stackTabs[i];
-            }
-        }
-        return index;
-    }
-
-    /**
-     * Comparator that helps ordering StackTab's visibility sorting value in a decreasing order.
-     */
-    private static class VisibilityComparator implements Comparator<StackTab>, Serializable {
-        @Override
-        public int compare(StackTab tab1, StackTab tab2) {
-            return (int) (tab2.getVisiblitySortingValue() - tab1.getVisiblitySortingValue());
-        }
-    }
-
-    /**
-     * Comparator that helps ordering StackTab's visibility sorting value in a decreasing order.
-     */
-    private static class OrderComparator implements Comparator<StackTab>, Serializable {
-        @Override
-        public int compare(StackTab tab1, StackTab tab2) {
-            return tab1.getOrderSortingValue() - tab2.getOrderSortingValue();
-        }
-    }
-
-    /**
-     * Updates mSortedPriorityArray, which stores the list of StackTabs to render, sorted by
-     * rendering priority.
-     *
-     * @param comparator The comparator used to sort the StackTabs.
-     * @return True if at least one Stack has a tab, false if there are no tabs.
-     */
-    private boolean updateSortedPriorityArray(Comparator<StackTab> comparator) {
-        int allTabsCount = 0;
-        for (int i = 0; i < mStacks.size(); i++) {
-            allTabsCount += mStacks.get(i).getCount();
-        }
-        if (allTabsCount == 0) return false;
-        if (mSortedPriorityArray == null || mSortedPriorityArray.length != allTabsCount) {
-            mSortedPriorityArray = new StackTab[allTabsCount];
-        }
-        int sortedOffset = 0;
-        for (int i = 0; i < mStacks.size(); i++) {
-            sortedOffset = addAllTabs(mStacks.get(i), mSortedPriorityArray, sortedOffset);
-        }
-        assert sortedOffset == mSortedPriorityArray.length;
-        Arrays.sort(mSortedPriorityArray, comparator);
-        return true;
-    }
-
-    /**
-     * Updates the priority list of the {@link LayoutTab} and sends it the systems having processing
-     * to do on a per {@link LayoutTab} basis. Priority meaning may change based on the current
-     * comparator stored in {@link #mSortingComparator}.
-     *
-     * Do not use {@link #mSortedPriorityArray} out side this context. It is only a member to avoid
-     * doing an allocation every frames.
-     */
-    private void updateTabPriority() {
-        if (!updateSortedPriorityArray(mSortingComparator)) return;
-        updateTabsVisibility(mSortedPriorityArray);
-        updateDelayedLayoutTabInit(mSortedPriorityArray);
-    }
-
-    /**
-     * Updates the list of visible tab Id that the tab content manager is suppose to serve. The list
-     * is ordered by priority. The first ones must be in the manager, then the remaining ones should
-     * have at least approximations if possible.
-     *
-     * @param sortedPriorityArray The array of all the {@link StackTab} sorted by priority.
-     */
-    private void updateTabsVisibility(StackTab[] sortedPriorityArray) {
-        mVisibilityArray.clear();
-        for (int i = 0; i < sortedPriorityArray.length; i++) {
-            mVisibilityArray.add(sortedPriorityArray[i].getId());
-        }
-        updateCacheVisibleIds(mVisibilityArray);
-    }
-
-    /**
-     * Initializes the {@link LayoutTab} a few at a time. This function is to be called once a
-     * frame.
-     * The logic of that function is not as trivial as it should be because the input array we want
-     * to initialize the tab from keeps getting reordered from calls to call. This is needed to
-     * get the highest priority tab initialized first.
-     *
-     * @param sortedPriorityArray The array of all the {@link StackTab} sorted by priority.
-     */
-    private void updateDelayedLayoutTabInit(StackTab[] sortedPriorityArray) {
-        if (!mDelayedLayoutTabInitRequired) return;
-
-        int initialized = 0;
-        final int count = sortedPriorityArray.length;
-        for (int i = 0; i < count; i++) {
-            if (initialized >= LAYOUTTAB_ASYNCHRONOUS_INITIALIZATION_BATCH_SIZE) return;
-
-            LayoutTab layoutTab = sortedPriorityArray[i].getLayoutTab();
-            // The actual initialization is done by the parent class.
-            if (super.initLayoutTabFromHost(layoutTab)) {
-                initialized++;
-            }
-        }
-        if (initialized == 0) mDelayedLayoutTabInitRequired = false;
-    }
-
-    @Override
-    protected boolean initLayoutTabFromHost(LayoutTab layoutTab) {
-        if (layoutTab.isInitFromHostNeeded()) mDelayedLayoutTabInitRequired = true;
-        return false;
-    }
-
-    /**
-     * Called by the stacks whenever they start an animation.
-     */
-    public void onStackAnimationStarted() {
-        mStackAnimationCount++;
-    }
-
-    /**
-     * Called by the stacks whenever they finish their animations.
-     */
-    public void onStackAnimationFinished() {
-        mStackAnimationCount--;
-    }
-
-    @Override
-    protected EventFilter getEventFilter() {
-        return mGestureEventFilter;
-    }
-
-    @Override
-    protected SceneLayer getSceneLayer() {
-        return mSceneLayer;
-    }
-
-    private void ensureSceneLayerCreated() {
-        if (mSceneLayer != null) return;
-        mSceneLayer = new TabListSceneLayer();
-    }
-
-    @Override
-    protected void updateSceneLayer(RectF viewport, RectF contentViewport,
-            LayerTitleCache layerTitleCache, TabContentManager tabContentManager,
-            ResourceManager resourceManager, BrowserControlsStateProvider browserControls) {
-        ensureSceneLayerCreated();
-        super.updateSceneLayer(viewport, contentViewport, layerTitleCache, tabContentManager,
-                resourceManager, browserControls);
-        assert mSceneLayer != null;
-
-        mSceneLayer.pushLayers(getContext(), viewport, contentViewport, this, layerTitleCache,
-                tabContentManager, resourceManager, browserControls, SceneLayer.INVALID_RESOURCE_ID,
-                0, 0);
-    }
-
-    @Override
-    public int getLayoutType() {
-        return LayoutType.TAB_SWITCHER;
-    }
-
-    /**
-     * Creates an {@link CompositorAnimator} and adds it to the animation.
-     * Automatically sets the start value at the beginning of the animation.
-     */
-    protected void addToAnimation(FloatProperty<StackLayoutBase> property, float start, float end,
-            long duration, long startTime) {
-        CompositorAnimator compositorAnimator = CompositorAnimator.ofFloatProperty(
-                getAnimationHandler(), this, property, start, end, duration);
-        compositorAnimator.setStartDelay(startTime);
-        compositorAnimator.start();
-
-        for (int i = mLayoutAnimations.size() - 1; i >= 0; i--) {
-            if (mLayoutAnimations.get(i).second == property
-                    && !mLayoutAnimations.get(i).first.isRunning()) {
-                mLayoutAnimations.set(i,
-                        new Pair<CompositorAnimator, FloatProperty>(compositorAnimator, property));
-
-                requestUpdate();
-                return;
-            }
-        }
-
-        mLayoutAnimations.add(
-                new Pair<CompositorAnimator, FloatProperty>(compositorAnimator, property));
-
-        requestUpdate();
-    }
-
-    @Override
-    protected void forceAnimationToFinish() {
-        super.forceAnimationToFinish();
-
-        for (int i = 0; i < mLayoutAnimations.size(); i++) {
-            mLayoutAnimations.get(i).first.end();
-        }
-        mLayoutAnimations.clear();
-    }
-
-    /**
-     * Cancels any animation for the given object and property.
-     * @param object The object being animated.
-     * @param prop   The property to search for.
-     */
-    protected void cancelAnimation(FloatProperty<StackLayoutBase> property) {
-        for (int i = mLayoutAnimations.size() - 1; i >= 0; i--) {
-            if (mLayoutAnimations.get(i).second == property) {
-                mLayoutAnimations.get(i).first.cancel();
-            }
-        }
-    }
-
-    @Override
-    @VisibleForTesting
-    public boolean isLayoutAnimating() {
-        for (int i = 0; i < mLayoutAnimations.size(); i++) {
-            if (mLayoutAnimations.get(i).first.isRunning()) return true;
-        }
-        return false;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/OverlappingStack.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/OverlappingStack.java
deleted file mode 100644
index cccc5ce..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/OverlappingStack.java
+++ /dev/null
@@ -1,679 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.compositor.layouts.phone.stack;
-
-import android.content.Context;
-import android.content.res.Resources;
-
-import org.chromium.base.MathUtils;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.compositor.layouts.Layout.Orientation;
-import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
-import org.chromium.chrome.browser.compositor.layouts.phone.StackLayoutBase;
-import org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation.OverviewAnimationType;
-import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities;
-import org.chromium.ui.base.LocalizationUtils;
-
-/**
- * The overlapping tab stack we use when the HorizontalTabSwitcherAndroid flag is not enabled.
- */
-public class OverlappingStack extends Stack {
-    private static final float SCALE_AMOUNT = 0.90f;
-
-    /**
-     * The percentage of the screen that defines the spacing between tabs by default (no pinch).
-     */
-    private static final float SPACING_SCREEN = 0.26f;
-
-    /**
-     * Percentage of the screen to wrap the scroll space.
-     */
-    private static final float SCROLL_WARP_PCTG = 0.4f;
-
-    /**
-     * How much the stack should adjust the y position of each LayoutTab in portrait mode (as a
-     * fraction of the amount space that would be above and below the tab if it were centered).
-     */
-    private static final float STACK_PORTRAIT_Y_OFFSET_PROPORTION = -0.8f;
-
-    /**
-     * How much the stack should adjust the x position of each LayoutTab in landscape mode (as a
-     * fraction of the amount space that would be to the left and right of the tab if it were
-     * centered).
-     */
-    private static final float STACK_LANDSCAPE_START_OFFSET_PROPORTION = -0.7f;
-
-    /**
-     * How much the stack should adjust the x position of each LayoutTab in portrait mode (as a
-     * fraction of the amount space that would be above and below the tab if it were centered).
-     */
-    private static final float STACK_LANDSCAPE_Y_OFFSET_PROPORTION = -0.5f;
-
-    private float mWarpSize;
-
-    // During pinch, the finger the closest to the bottom of the stack changes the scrolling
-    // and the other finger locally stretches the spacing between the tabs.
-    private int mPinch0TabIndex = -1;
-    private int mPinch1TabIndex = -1;
-    private float mLastPinch0Offset;
-    private float mLastPinch1Offset;
-
-    // Current progress of the 'even out' phase. This progress as the screen get scrolled.
-    private float mEvenOutProgress = 1.0f;
-    // Rate to even out all the tabs.
-    private float mEvenOutRate = 1.0f; // This will be updated from dimens.xlm
-
-    private float mMinSpacing; // This will be updated from dimens.xml
-
-    /**
-     * @param layout The parent layout.
-     */
-    public OverlappingStack(Context context, StackLayoutBase layout) {
-        super(context, layout);
-    }
-
-    @Override
-    public float getScaleAmount() {
-        return SCALE_AMOUNT;
-    }
-
-    @Override
-    protected boolean evenOutTabs(float amount, boolean allowReverseDirection) {
-        if (mStackTabs == null || mOverviewAnimationType != OverviewAnimationType.NONE
-                || mEvenOutProgress >= 1.0f || amount == 0) {
-            return false;
-        }
-        boolean changed = false;
-        boolean reverseScrolling = false;
-
-        // The evening out process last until mEvenOutRate reaches 1.0. Tabs blend linearly
-        // between the current position to a nice evenly scaled pattern. Because we do not store
-        // the starting position for each tab we need more complicated math to do the blend.
-        // The absoluteProgress is how much we need progress this step on the [0, 1] scale.
-        float absoluteProgress = Math.min(Math.abs(amount) * mEvenOutRate, 1.0f - mEvenOutProgress);
-        // The relativeProgress is how much we need to blend the target to the current to get there.
-        float relativeProgress = absoluteProgress / (1.0f - mEvenOutProgress);
-
-        float screenMax = getScrollDimensionSize();
-        for (int i = 0; i < mStackTabs.length; ++i) {
-            float source = mStackTabs[i].getScrollOffset();
-            float target = screenToScroll(i * mSpacing);
-            float sourceScreen = Math.min(screenMax, scrollToScreen(source + mScrollTarget));
-            float targetScreen = Math.min(screenMax, scrollToScreen(target + mScrollTarget));
-            // If the target and the current position matches on the screen then we snap to the
-            // target.
-            if (sourceScreen == targetScreen) {
-                mStackTabs[i].setScrollOffset(target);
-                continue;
-            }
-            float step = source + (target - source) * relativeProgress;
-            float stepScreen = Math.min(screenMax, scrollToScreen(step + mScrollTarget));
-            // If the step can be performed without noticing then we do it.
-            if (sourceScreen == stepScreen) {
-                mStackTabs[i].setScrollOffset(step);
-                continue;
-            }
-            // If the scrolling goes in the same direction as the step then the motion is applied.
-            if ((targetScreen - sourceScreen) * amount > 0 || allowReverseDirection) {
-                mStackTabs[i].setScrollOffset(step);
-                changed = true;
-            } else {
-                reverseScrolling = true;
-            }
-        }
-        // Only account for progress if the scrolling was in the right direction. It assumes here
-        // That if any of the tabs was going in the wrong direction then the progress is not
-        // recorded at all. This is very conservative to avoid poping in the scrolling. It works
-        // for now but might need to be revisited if we see artifacts.
-        if (!reverseScrolling) {
-            mEvenOutProgress += absoluteProgress;
-        }
-        return changed;
-    }
-
-    @Override
-    public void onLongPress(long time, float x, float y) {
-        if (mOverviewAnimationType == OverviewAnimationType.NONE) {
-            int longPressSelected = getTabIndexAtPositon(x, y);
-            if (longPressSelected >= 0) {
-                startAnimation(time, OverviewAnimationType.VIEW_MORE, longPressSelected, false);
-                mEvenOutProgress = 0.0f;
-            }
-        }
-    }
-
-    @Override
-    public void onPinch(long time, float x0, float y0, float x1, float y1, boolean firstEvent) {
-        if ((mOverviewAnimationType != OverviewAnimationType.START_PINCH
-                    && mOverviewAnimationType != OverviewAnimationType.NONE)
-                || mStackTabs == null) {
-            return;
-        }
-        if (mPinch0TabIndex < 0) startAnimation(time, OverviewAnimationType.START_PINCH);
-
-        // Reordering the fingers so pinch0 is always the closest to the top of the stack.
-        // This allows simpler math down the line where we assume that
-        // pinch0TabIndex <= pinch0TabIndex
-        // It also means that crossing the finger will separate the tabs again.
-        boolean inverse = (mCurrentMode == Orientation.PORTRAIT)
-                ? y0 > y1
-                : LocalizationUtils.isLayoutRtl() ? (x0 <= x1) : (x0 > x1);
-        float pinch0X = inverse ? x1 : x0;
-        float pinch0Y = inverse ? y1 : y0;
-        float pinch1X = inverse ? x0 : x1;
-        float pinch1Y = inverse ? y0 : y1;
-        float pinch0Offset = (mCurrentMode == Orientation.PORTRAIT)
-                ? pinch0Y
-                : LocalizationUtils.isLayoutRtl() ? -pinch0X : pinch0X;
-        float pinch1Offset = (mCurrentMode == Orientation.PORTRAIT)
-                ? pinch1Y
-                : LocalizationUtils.isLayoutRtl() ? -pinch1X : pinch1X;
-
-        if (firstEvent) {
-            // Resets pinch and scrolling state.
-            mPinch0TabIndex = -1;
-            mPinch1TabIndex = -1;
-            mScrollingTab = null;
-            commitDiscard(time, false);
-        }
-        int pinch0TabIndex = mPinch0TabIndex;
-        int pinch1TabIndex = mPinch1TabIndex;
-        if (mPinch0TabIndex < 0) {
-            pinch0TabIndex = getTabIndexAtPositon(pinch0X, pinch0Y);
-            pinch1TabIndex = getTabIndexAtPositon(pinch1X, pinch1Y);
-            // If any of them is invalid we invalidate both.
-            if (pinch0TabIndex < 0 || pinch1TabIndex < 0) {
-                pinch0TabIndex = -1;
-                pinch1TabIndex = -1;
-            }
-        }
-
-        if (pinch0TabIndex >= 0 && mPinch0TabIndex == pinch0TabIndex
-                && mPinch1TabIndex == pinch1TabIndex) {
-            final float minScrollTarget = getMinScroll(false);
-            final float maxScrollTarget = getMaxScroll(false);
-            final float oldScrollTarget =
-                    MathUtils.clamp(mScrollTarget, minScrollTarget, maxScrollTarget);
-            // pinch0TabIndex > pinch1TabIndex is unexpected but we do not want to exit
-            // ungracefully so process it as if the tabs were the same.
-            if (pinch0TabIndex >= pinch1TabIndex) {
-                // If one tab is pinched then we only scroll.
-                float screenDelta0 = pinch0Offset - mLastPinch0Offset;
-                if (pinch0TabIndex == 0) {
-                    // Linear scroll on the top tab for the overscroll to kick-in linearly.
-                    setScrollTarget(oldScrollTarget + screenDelta0, false);
-                } else {
-                    float tab0ScrollSpace =
-                            mStackTabs[pinch0TabIndex].getScrollOffset() + oldScrollTarget;
-                    float tab0Screen = scrollToScreen(tab0ScrollSpace);
-                    float tab0ScrollFinal = screenToScroll(tab0Screen + screenDelta0);
-                    setScrollTarget(
-                            tab0ScrollFinal - mStackTabs[pinch0TabIndex].getScrollOffset(), false);
-                }
-                // This is the common case of the pinch, 2 fingers on 2 different tabs.
-            } else {
-                // Find the screen space position before and after the scroll so the tab 0 matches
-                // the finger 0 motion.
-                float screenDelta0 = pinch0Offset - mLastPinch0Offset;
-                float tab0ScreenBefore = approxScreen(mStackTabs[pinch0TabIndex], oldScrollTarget);
-                float tab0ScreenAfter = tab0ScreenBefore + screenDelta0;
-
-                // Find the screen space position before and after the scroll so the tab 1 matches
-                // the finger 1 motion.
-                float screenDelta1 = pinch1Offset - mLastPinch1Offset;
-                float tab1ScreenBefore = approxScreen(mStackTabs[pinch1TabIndex], oldScrollTarget);
-                float tab1ScreenAfter = tab1ScreenBefore + screenDelta1;
-
-                // Heuristic: the scroll is defined by half the change of the first pinched tab.
-                // The rational is that it looks nice this way :)... Scrolling creates a sliding
-                // effect. When a finger does not move then it is expected that none of the tabs
-                // past that steady finger should move. This does the job.
-                float globalScrollBefore = screenToScroll(tab0ScreenBefore);
-                float globalScrollAfter = screenToScroll((tab0ScreenAfter + tab0ScreenBefore) / 2);
-                setScrollTarget(oldScrollTarget + globalScrollAfter - globalScrollBefore, true);
-
-                // Evens out the tabs in between
-                float minScreen = tab0ScreenAfter;
-                float maxScreen = tab0ScreenAfter;
-                for (int i = pinch0TabIndex; i <= pinch1TabIndex; i++) {
-                    float screenBefore = approxScreen(mStackTabs[i], oldScrollTarget);
-                    float t = (tab1ScreenBefore == tab0ScreenBefore)
-                            ? 1
-                            : ((screenBefore - tab0ScreenBefore)
-                                      / (tab1ScreenBefore - tab0ScreenBefore));
-                    float screenAfter = (1 - t) * tab0ScreenAfter + t * tab1ScreenAfter;
-                    screenAfter = Math.max(minScreen, screenAfter);
-                    screenAfter = Math.min(maxScreen, screenAfter);
-                    minScreen = screenAfter + StackTab.sStackedTabVisibleSize;
-                    maxScreen = screenAfter + mStackTabs[i].getSizeInScrollDirection(mCurrentMode);
-                    float newScrollOffset = screenToScroll(screenAfter) - mScrollTarget;
-                    mStackTabs[i].setScrollOffset(newScrollOffset);
-                }
-
-                // Push a bit the tabs bellow pinch1.
-                float delta1 = tab1ScreenAfter - tab1ScreenBefore;
-                for (int i = pinch1TabIndex + 1; i < mStackTabs.length; i++) {
-                    delta1 /= 2;
-                    float screenAfter = approxScreen(mStackTabs[i], oldScrollTarget) + delta1;
-                    screenAfter = Math.max(minScreen, screenAfter);
-                    screenAfter = Math.min(maxScreen, screenAfter);
-                    minScreen = screenAfter + StackTab.sStackedTabVisibleSize;
-                    maxScreen = screenAfter + mStackTabs[i].getSizeInScrollDirection(mCurrentMode);
-                    mStackTabs[i].setScrollOffset(screenToScroll(screenAfter) - mScrollTarget);
-                }
-
-                // Pull a bit the tabs above pinch0.
-                minScreen = tab0ScreenAfter;
-                maxScreen = tab0ScreenAfter;
-                float posScreen = tab0ScreenAfter;
-                float delta0 = tab0ScreenAfter - tab0ScreenBefore;
-                for (int i = pinch0TabIndex - 1; i > 0; i--) {
-                    delta0 /= 2;
-                    minScreen = posScreen - mStackTabs[i].getSizeInScrollDirection(mCurrentMode);
-                    maxScreen = posScreen - StackTab.sStackedTabVisibleSize;
-                    float screenAfter = approxScreen(mStackTabs[i], oldScrollTarget) + delta0;
-                    screenAfter = Math.max(minScreen, screenAfter);
-                    screenAfter = Math.min(maxScreen, screenAfter);
-                    mStackTabs[i].setScrollOffset(screenToScroll(screenAfter) - mScrollTarget);
-                }
-            }
-        }
-        mPinch0TabIndex = pinch0TabIndex;
-        mPinch1TabIndex = pinch1TabIndex;
-        mLastPinch0Offset = pinch0Offset;
-        mLastPinch1Offset = pinch1Offset;
-        mEvenOutProgress = 0.0f;
-        mLayout.requestUpdate();
-    }
-
-    @Override
-    public void onUpOrCancel(long time) {
-        // Make sure the bottom tab always goes back to the top of the screen.
-        if (mPinch0TabIndex >= 0) {
-            startAnimation(time, OverviewAnimationType.REACH_TOP);
-            mLayout.requestUpdate();
-        }
-
-        super.onUpOrCancel(time);
-    }
-
-    @Override
-    protected void springBack(long time) {
-        if (mScroller.isFinished()) {
-            int minScroll = (int) getMinScroll(false);
-            int maxScroll = (int) getMaxScroll(false);
-            if (mScrollTarget < minScroll || mScrollTarget > maxScroll) {
-                mScroller.springBack(0, (int) mScrollTarget, 0, 0, minScroll, maxScroll, time);
-                setScrollTarget(MathUtils.clamp(mScrollTarget, minScroll, maxScroll), false);
-                mLayout.requestUpdate();
-            }
-        }
-    }
-
-    /**
-     * @param context The current Android's context.
-     */
-    @Override
-    public void contextChanged(Context context) {
-        super.contextChanged(context);
-
-        Resources res = context.getResources();
-        final float pxToDp = 1.0f / res.getDisplayMetrics().density;
-
-        mEvenOutRate = 1.0f / (res.getDimension(R.dimen.even_out_scrolling) * pxToDp);
-        mMinSpacing = res.getDimensionPixelOffset(R.dimen.min_spacing) * pxToDp;
-    }
-
-    @Override
-    protected boolean shouldStackTabsAtTop() {
-        return true;
-    }
-
-    @Override
-    protected boolean shouldStackTabsAtBottom() {
-        return true;
-    }
-
-    @Override
-    protected float getStackPortraitYOffsetProportion() {
-        return STACK_PORTRAIT_Y_OFFSET_PROPORTION;
-    }
-
-    @Override
-    protected float getStackLandscapeStartOffsetProportion() {
-        return STACK_LANDSCAPE_START_OFFSET_PROPORTION;
-    }
-
-    @Override
-    protected float getStackLandscapeYOffsetProportion() {
-        return STACK_LANDSCAPE_Y_OFFSET_PROPORTION;
-    }
-
-    @Override
-    protected float getSpacingScreen() {
-        return SPACING_SCREEN;
-    }
-
-    @Override
-    protected boolean shouldCloseGapsBetweenTabs() {
-        return true;
-    }
-
-    @Override
-    protected void computeTabClippingVisibilityHelper() {
-        // alpha override, clipping and culling.
-        final boolean portrait = mCurrentMode == Orientation.PORTRAIT;
-
-        // Iterate through each tab starting at the top of the stack and working
-        // backwards. Set the clip on each tab such that it does not extend past
-        // the beginning of the tab above it. clipOffset is used to keep track
-        // of where the previous tab started.
-        float clipOffset;
-        if (portrait) {
-            // portrait LTR & RTL
-            clipOffset = mLayout.getHeight() + StackTab.sStackedTabVisibleSize;
-        } else if (!LocalizationUtils.isLayoutRtl()) {
-            // landscape LTR
-            clipOffset = mLayout.getWidth() + StackTab.sStackedTabVisibleSize;
-        } else {
-            // landscape RTL
-            clipOffset = -StackTab.sStackedTabVisibleSize;
-        }
-
-        for (int i = mStackTabs.length - 1; i >= 0; i--) {
-            LayoutTab layoutTab = mStackTabs[i].getLayoutTab();
-            layoutTab.setVisible(true);
-
-            // Don't bother with clipping tabs that are dying, rotating, with an X offset, or
-            // non-opaque.
-            if (mStackTabs[i].isDying() || mStackTabs[i].getXInStackOffset() != 0.0f
-                    || layoutTab.getAlpha() < 1.0f) {
-                layoutTab.setClipOffset(0.0f, 0.0f);
-                layoutTab.setClipSize(Float.MAX_VALUE, Float.MAX_VALUE);
-                continue;
-            }
-
-            // The beginning, size, and clipped size of the current tab.
-            float tabOffset;
-            float tabSize;
-            float tabClippedSize;
-            float borderAdjustmentSize;
-            float insetBorderPadding;
-            if (portrait) {
-                // portrait LTR & RTL
-                tabOffset = layoutTab.getY();
-                tabSize = layoutTab.getScaledContentHeight();
-                tabClippedSize = Math.min(tabSize, clipOffset - tabOffset);
-                borderAdjustmentSize = mBorderTransparentTop;
-                insetBorderPadding = mBorderTopPadding;
-            } else if (!LocalizationUtils.isLayoutRtl()) {
-                // landscape LTR
-                tabOffset = layoutTab.getX();
-                tabSize = layoutTab.getScaledContentWidth();
-                tabClippedSize = Math.min(tabSize, clipOffset - tabOffset);
-                borderAdjustmentSize = mBorderTransparentSide;
-                insetBorderPadding = 0;
-            } else {
-                // landscape RTL
-                tabOffset = layoutTab.getX() + layoutTab.getScaledContentWidth();
-                tabSize = layoutTab.getScaledContentWidth();
-                tabClippedSize = Math.min(tabSize, tabOffset - clipOffset);
-                borderAdjustmentSize = -mBorderTransparentSide;
-                insetBorderPadding = 0;
-            }
-
-            float absBorderAdjustmentSize = Math.abs(borderAdjustmentSize);
-
-            if (tabClippedSize <= absBorderAdjustmentSize) {
-                // If the tab is completed covered, don't bother drawing it at all.
-                layoutTab.setVisible(false);
-                layoutTab.setDrawDecoration(true);
-                mLayout.releaseResourcesForTab(layoutTab);
-            } else {
-                // Fade the tab as it gets too close to the next one. This helps
-                // prevent overlapping shadows from becoming too dark.
-                float fade = MathUtils.clamp(((tabClippedSize - absBorderAdjustmentSize)
-                                                     / StackTab.sStackedTabVisibleSize),
-                        0, 1);
-                layoutTab.setDecorationAlpha(fade);
-
-                // When tabs tilt forward, it will expose more of the tab
-                // underneath. To compensate, make the clipping size larger.
-                // Note, this calculation is only an estimate that seems to
-                // work.
-                float clipScale = 1.0f;
-                if (layoutTab.getTiltX() > 0
-                        || ((!portrait && LocalizationUtils.isLayoutRtl())
-                                           ? layoutTab.getTiltY() < 0
-                                           : layoutTab.getTiltY() > 0)) {
-                    final float tilt =
-                            Math.max(layoutTab.getTiltX(), Math.abs(layoutTab.getTiltY()));
-                    clipScale += (tilt / mMaxOverScrollAngle) * 0.60f;
-                }
-
-                float scaledTabClippedSize = Math.min(tabClippedSize * clipScale, tabSize);
-                // Set the clip
-                layoutTab.setClipOffset((!portrait && LocalizationUtils.isLayoutRtl())
-                                ? (tabSize - scaledTabClippedSize)
-                                : 0,
-                        0);
-                layoutTab.setClipSize(portrait ? Float.MAX_VALUE : scaledTabClippedSize,
-                        portrait ? scaledTabClippedSize : Float.MAX_VALUE);
-            }
-
-            // Clip the next tab where this tab begins.
-            if (i > 0) {
-                LayoutTab nextLayoutTab = mStackTabs[i - 1].getLayoutTab();
-                if (nextLayoutTab.getScale() <= layoutTab.getScale()) {
-                    clipOffset = tabOffset;
-                } else {
-                    clipOffset = tabOffset + tabClippedSize * layoutTab.getScale();
-                }
-
-                // Extend the border just a little bit. Otherwise, the
-                // rounded borders will intersect and make it look like the
-                // content is actually smaller.
-                clipOffset += borderAdjustmentSize;
-
-                if (layoutTab.getBorderAlpha() < 1.f && layoutTab.getToolbarAlpha() < 1.f) {
-                    clipOffset += insetBorderPadding;
-                }
-            }
-        }
-    }
-
-    @Override
-    protected int computeReferenceIndex() {
-        int centerIndex =
-                getTabIndexAtPositon(mLayout.getWidth() / 2.0f, mLayout.getHeight() / 2.0f);
-        // Alter the center to take into account the scrolling direction.
-        if (mCurrentScrollDirection > 0) centerIndex++;
-        if (mCurrentScrollDirection < 0) centerIndex--;
-        return MathUtils.clamp(centerIndex, 0, mStackTabs.length - 1);
-    }
-
-    @Override
-    protected float getMinScroll(boolean allowUnderScroll) {
-        float maxOffset = 0;
-        if (mStackTabs != null) {
-            // The tabs are not always ordered so we need to browse them all.
-            for (int i = 0; i < mStackTabs.length; i++) {
-                if (!mStackTabs[i].isDying() && mStackTabs[i].getLayoutTab().isVisible()) {
-                    maxOffset = Math.max(mStackTabs[i].getScrollOffset(), maxOffset);
-                }
-            }
-        }
-        return (allowUnderScroll ? -mMaxUnderScroll : 0) - maxOffset;
-    }
-
-    @Override
-    protected int computeSpacing(int layoutTabCount) {
-        int spacing = 0;
-        if (layoutTabCount > 1) {
-            final float dimension = getScrollDimensionSize();
-            int minSpacing = (int) Math.max(dimension * SPACING_SCREEN, mMinSpacing);
-            if (mStackTabs != null) {
-                for (int i = 0; i < mStackTabs.length; i++) {
-                    assert mStackTabs[i] != null;
-                    if (!mStackTabs[i].isDying()) {
-                        minSpacing = (int) Math.min(
-                                minSpacing, mStackTabs[i].getSizeInScrollDirection(mCurrentMode));
-                    }
-                }
-            }
-            spacing = (int) ((dimension - 20) / (layoutTabCount * .8f));
-            spacing = Math.max(spacing, minSpacing);
-        }
-        return spacing;
-    }
-
-    @Override
-    protected boolean allowOverscroll() {
-        return super.allowOverscroll() && mPinch0TabIndex < 0;
-    }
-
-    @Override
-    protected void resetAllScrollOffset() {
-        if (mTabList == null) return;
-        // Reset the scroll position to put the important {@link StackTab} into focus.
-        // This does not scroll the {@link StackTab}s there but rather moves everything
-        // there immediately.
-        // The selected tab is supposed to show at the center of the screen.
-        float maxTabsPerPage = getScrollDimensionSize() / mSpacing;
-        float centerOffsetIndex = maxTabsPerPage / 2.0f - 0.5f;
-        final int count = mTabList.getCount();
-        final int index = mTabList.index();
-        if (index < centerOffsetIndex || count <= maxTabsPerPage) {
-            mScrollOffset = 0;
-        } else if (index == count - 1 && Math.ceil(maxTabsPerPage) < count) {
-            mScrollOffset = (maxTabsPerPage - count - 1) * mSpacing;
-        } else if ((count - index - 1) < centerOffsetIndex) {
-            mScrollOffset = (maxTabsPerPage - count) * mSpacing;
-        } else {
-            mScrollOffset = (centerOffsetIndex - index) * mSpacing;
-        }
-        // Reset the scroll offset of the tabs too.
-        if (mStackTabs != null) {
-            for (int i = 0; i < mStackTabs.length; i++) {
-                mStackTabs[i].setScrollOffset(screenToScroll(i * mSpacing));
-            }
-        }
-        setScrollTarget(mScrollOffset, false);
-    }
-
-    /**
-     * Unwarps x so it matches the above warp function.
-     * @see #scrollToScreen(float)
-     *
-     * [-oo, 0] -> -warpSize
-     * [0, warpSize] -> 2 * warpSize * sqrt(x / warpSize).
-     * [warpSize, +oo] -> x + warpSize
-     * @param x        The screen space offset.
-     * @param warpSize The size in scroll space of the slow down effect.
-     * @return         The offset in scroll space corresponding to the offset on screen.
-     */
-    private float screenToScroll(float x, float warpSize) {
-        if (x <= 0) return 0;
-        if (x >= warpSize) return x + warpSize;
-        return (float) Math.sqrt(x * warpSize) * 2;
-    }
-
-    /**
-     * Public version of screenToScroll(float, float) that uses the current warp size.
-     * @param scrollSpace The offset in screen space.
-     * @return            The offset in scroll space corresponding to the offset on screen.
-     */
-    @Override
-    public float screenToScroll(float screenSpace) {
-        return screenToScroll(screenSpace, mWarpSize);
-    }
-
-    /**
-     * The scroll space does not map linearly to the screen so it creates a nice slow down
-     * effect at the top of the screen while scrolling.
-     * Warps x so it matches y(x) = x - warpSize on the positive side and 0 on the negative side
-     * with a smooth transition between [0, 2 * warpSize].
-     * @see #screenToScroll(float)
-     *
-     * [-oo, 0] -> 0
-     * [0, 2 * warpSize] -> warpSize * ((x-warpSize) / 2 * warpSize + 0.5) ^ 2.
-     * [2 * warpSize, +oo] -> x
-     * @param x        The offset in scroll space.
-     * @param warpSize The size in scroll space of the slow down effect.
-     * @return         The offset on screen corresponding to the scroll space offset.
-     */
-    private float scrollToScreen(float x, float warpSize) {
-        if (x <= 0) return 0;
-        if (x >= 2 * warpSize) return x - warpSize;
-        x = (x - warpSize) / (2.0f * warpSize) + 0.5f;
-        return x * x * warpSize;
-    }
-
-    /**
-     * Public version of scrollToScreen(float, float) that uses the current warp size.
-     * Maps from scroll coordinates to screen coordinates.
-     * @param scrollSpace The offset in scroll space.
-     * @return            The offset on screen corresponding to the scroll space offset.
-     */
-    @Override
-    public float scrollToScreen(float scrollSpace) {
-        return scrollToScreen(scrollSpace, mWarpSize);
-    }
-
-    @Override
-    public float getMaxTabHeight() {
-        // TODO(crbug.com/1095698): Rework when the stack enter animation is created so that we can
-        // remove this feature specific fix.
-        // When conditional tab strip is enabled, the bottom browser control height should be 0
-        // eventually when overview mode is visible. Hence, we pre-acknowledge the fact and assume
-        // the bottom control height to be 0 here so that the animation is correctly set up.
-        if (TabUiFeatureUtilities.isConditionalTabStripEnabled()) {
-            return mLayout.getHeight() - mLayout.getTopContentOffsetDp();
-        }
-        return mLayout.getHeightMinusContentOffsetsDp();
-    }
-
-    @Override
-    protected void updateCurrentMode(@Orientation int orientation) {
-        setWarpState(true, false);
-        super.updateCurrentMode(orientation);
-    }
-
-    @Override
-    protected void resetInputActionIndices() {
-        super.resetInputActionIndices();
-
-        mPinch0TabIndex = -1;
-        mPinch1TabIndex = -1;
-    }
-
-    /**
-     * Whether or not the tab positions warp from linear to nonlinear as the tabs approach the edge
-     * of the screen.  This allows us to move the tabs to linear space to track finger movements,
-     * but also move them back to non-linear space without any visible change to the user.
-     * @param canWarp           Whether or not the tabs are allowed to warp.
-     * @param adjustCurrentTabs Whether or not to change the tab positions so there's no visible
-     *                          difference after the change.
-     */
-    private void setWarpState(boolean canWarp, boolean adjustCurrentTabs) {
-        float warp = canWarp ? getScrollDimensionSize() * SCROLL_WARP_PCTG : 0.f;
-
-        if (mStackTabs != null && adjustCurrentTabs && Float.compare(warp, mWarpSize) != 0) {
-            float scrollOffset =
-                    MathUtils.clamp(mScrollOffset, getMinScroll(false), getMaxScroll(false));
-            for (int i = 0; i < mStackTabs.length; i++) {
-                StackTab tab = mStackTabs[i];
-                float tabScrollOffset = tab.getScrollOffset();
-                float tabScrollSpace = tabScrollOffset + scrollOffset;
-                float tabScreen = scrollToScreen(tabScrollSpace, mWarpSize);
-                float tabScrollSpaceFinal = screenToScroll(tabScreen, warp);
-                float scrollDelta = tabScrollSpaceFinal - tabScrollSpace;
-                tab.setScrollOffset(tabScrollOffset + scrollDelta);
-            }
-        }
-
-        mWarpSize = warp;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java
deleted file mode 100644
index 4d91d346d..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java
+++ /dev/null
@@ -1,2083 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.compositor.layouts.phone.stack;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.RectF;
-
-import androidx.annotation.IntDef;
-import androidx.annotation.VisibleForTesting;
-
-import org.chromium.base.MathUtils;
-import org.chromium.base.metrics.RecordUserAction;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.compositor.layouts.Layout;
-import org.chromium.chrome.browser.compositor.layouts.Layout.Orientation;
-import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
-import org.chromium.chrome.browser.compositor.layouts.phone.StackLayoutBase;
-import org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation.OverviewAnimationType;
-import org.chromium.chrome.browser.layouts.animation.CompositorAnimationHandler;
-import org.chromium.chrome.browser.layouts.animation.FloatProperty;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tabmodel.TabList;
-import org.chromium.chrome.browser.tabmodel.TabModelUtils;
-import org.chromium.ui.base.LocalizationUtils;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * Handles all the drawing and events of a stack of stackTabs.
- *
- * @VisibleForTesting
- */
-public abstract class Stack {
-    public static final int MAX_NUMBER_OF_STACKED_TABS_TOP = 3;
-    public static final int MAX_NUMBER_OF_STACKED_TABS_BOTTOM = 3;
-
-    private static final float STACK_PORTRAIT_Y_OFFSET_PROPORTION = -0.8f;
-    private static final float STACK_LANDSCAPE_START_OFFSET_PROPORTION = -0.7f;
-    private static final float STACK_LANDSCAPE_Y_OFFSET_PROPORTION = -0.5f;
-
-    @IntDef({DragLock.NONE, DragLock.SCROLL, DragLock.DISCARD})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface DragLock {
-        int NONE = 0;
-        int SCROLL = 1;
-        int DISCARD = 2;
-    }
-
-    /**
-     * The percentage of the screen to cover for the discarded tab to be fully transparent.
-     */
-    public static final float DISCARD_RANGE_SCREEN = 0.7f;
-
-    /**
-     * The percentage the tab need to be dragged to actually discard the card.
-     */
-    private static final float DISCARD_COMMIT_THRESHOLD = 0.4f;
-
-    /**
-     * The percentage of the side of the tab that is inactive to swipe to discard. As this is
-     * a distance computed from both edges, meaningful value ranges in [0 ... 0.5].
-     */
-    private static final float DISCARD_SAFE_SELECTION_PCTG = 0.1f;
-
-    /**
-     * The minimum scale the tab can reach when being discarded by a click.
-     */
-    private static final float DISCARD_END_SCALE_CLICK = 0.7f;
-
-    /**
-     * The minimum scale the tab can reach when being discarded by a swipe.
-     */
-    private static final float DISCARD_END_SCALE_SWIPE = 0.5f;
-
-    /**
-     * The delta time applied on the velocity from the fling. This is to compute the kick to
-     * help discarding a card.
-     */
-    private static final float DISCARD_FLING_DT = 1.0f / 45.0f;
-
-    /**
-     * The maximum contribution of the fling. This is in percentage of the range.
-     */
-    private static final float DISCARD_FLING_MAX_CONTRIBUTION = 0.4f;
-
-    /**
-     * How much to scale the max overscroll angle when tabs are tilting backwards.
-     */
-    private static final float BACKWARDS_TILT_SCALE = 0.5f;
-
-    /**
-     * When overscrolling towards the top or left of the screen, what portion of
-     * the overscroll should be devoted to sliding the tabs together. The rest
-     * of the overscroll is used for tilting.
-     */
-    private static final float OVERSCROLL_TOP_SLIDE_PCTG = 0.25f;
-
-    /**
-     * Scale max under/over scroll by this amount when flinging.
-     */
-    private static final float MAX_OVER_FLING_SCALE = 0.5f;
-
-    /**
-     * mMaxUnderScroll is determined by multing mMaxOverScroll with
-     * MAX_UNDER_SCROLL_SCALE
-     */
-    private static final float MAX_UNDER_SCROLL_SCALE = 2.0f;
-
-    /**
-     * Drags that are mostly horizontal (within 30 degrees) signal that
-     * a user is discarding a tab.
-     */
-    private static final float DRAG_ANGLE_THRESHOLD = (float) Math.tan(Math.toRadians(30.0));
-
-    /**
-     * Reset the scroll mode after this number of milliseconds of inactivity or small motions.
-     */
-    private static final long DRAG_TIME_THRESHOLD = 400;
-
-    /**
-     * Minimum motion threshold to lock the scroll mode.
-     */
-    private static final float DRAG_MOTION_THRESHOLD_DP = 1.25f;
-
-    /**
-     * The number of attempt to get the full roll overscroll animation.
-     */
-    private static final int OVERSCROLL_FULL_ROLL_TRIGGER = 5;
-
-    /**
-     * Percentage of the screen to wrap the scroll space.
-     */
-    private static final float SCROLL_WARP_PCTG = 0.4f;
-
-    /**
-     * Percentage of the screen a swipe gesture must traverse before it is allowed to be
-     * canceled.
-     */
-    private static final float SWIPE_LANDSCAPE_THRESHOLD = 0.19f;
-
-    /**
-     * How far to place the tab to the left of the user's finger when swiping in dp.  This keeps
-     * the tab under the user's finger.
-     */
-    private static final float LANDSCAPE_SWIPE_DRAG_TAB_OFFSET_DP = 40.f;
-
-    // TODO(dtrainor): Investigate removing this.
-    private static final float BORDER_THICKNESS_DP = 4.f;
-
-    // External References
-    protected TabList mTabList;
-
-    // True when the stack is still visible for animation but it is going to be empty.
-    private boolean mIsDying;
-
-    // Screen State Variables
-    protected int mSpacing;
-    protected StackTab[] mStackTabs; // mStackTabs can be null if there are no tabs
-
-    // Overscroll
-    protected StackScroller mScroller;
-    private float mOverScrollOffset;
-    private int mOverScrollDerivative;
-    private int mOverScrollCounter;
-    private float mMaxOverScroll; // This will be updated from dimens.xml
-    protected float mMaxUnderScroll;
-    protected float mMaxOverScrollAngle; // This will be updated from values.xml
-    private float mMaxOverScrollSlide;
-
-    // Drag Lock
-    private @DragLock int mDragLock = DragLock.NONE;
-    private long mLastScrollUpdate;
-    private float mMinScrollMotion;
-
-    // Scrolling Variables
-    protected float mScrollTarget;
-    protected float mScrollOffset;
-    private float mScrollOffsetForDyingTabs;
-    protected float mCurrentScrollDirection;
-    protected StackTab mScrollingTab;
-
-    // Swipe Variables
-    private float mSwipeUnboundScrollOffset;
-    private float mSwipeBoundedScrollOffset;
-    private boolean mSwipeIsCancelable;
-    private boolean mSwipeCanScroll;
-    protected boolean mInSwipe;
-
-    // Discard
-    protected StackTab mDiscardingTab;
-
-    // We can't initialize mDiscardDirection here using LocalizationUtils.isRtl() because it
-    // will involve a jni call. Instead, mDiscardDirection will be initialized in Show().
-    private float mDiscardDirection = Float.NaN;
-
-    private int mReferenceOrderIndex = -1;
-
-    // Orientation Variables
-    protected @Orientation int mCurrentMode = Orientation.PORTRAIT;
-
-    // Animation Variables
-    protected @OverviewAnimationType int mOverviewAnimationType = OverviewAnimationType.NONE;
-    private StackAnimation mAnimationFactory;
-    private StackViewAnimation mViewAnimationFactory;
-
-    // Running set of animations applied to tabs.
-    private StackAnimation.StackAnimatorSet mStackAnimatorSet;
-    private Animator mViewAnimations;
-
-    // The parent Layout
-    protected final StackLayoutBase mLayout;
-
-    // Border values
-    protected float mBorderTransparentTop;
-    protected float mBorderTransparentSide;
-    // TODO(dtrainor): Expose 9-patch padding from resource manager.
-    protected float mBorderTopPadding;
-    private float mBorderLeftPadding;
-
-    // The slop amount in dp to detect a touch on the tab.  Cached values from values/dimens.xml.
-    private float mCompositorButtonSlop; // compositor_button_slop
-
-    private boolean mIsStackForCurrentTabList;
-
-    private final AnimatorListenerAdapter mViewAnimatorListener = new AnimatorListenerAdapter() {
-        @Override
-        public void onAnimationCancel(Animator animation) {
-            mLayout.requestUpdate();
-        }
-
-        @Override
-        public void onAnimationEnd(Animator animation) {
-            mLayout.requestUpdate();
-        }
-    };
-
-    /**
-     * @param layout The parent layout.
-     */
-    public Stack(Context context, StackLayoutBase layout) {
-        mLayout = layout;
-        contextChanged(context);
-    }
-
-    /**
-     * @return Animation handler associated with this stack.
-     */
-    public CompositorAnimationHandler getAnimationHandler() {
-        return mLayout.getAnimationHandler();
-    }
-
-    /**
-     * @param tabList The list to attach to this stack.
-     */
-    public void setTabList(TabList tabList) {
-        mTabList = tabList;
-    }
-
-    /**
-     * @return The TabList associated with this stack.
-     */
-    public TabList getTabList() {
-        return mTabList;
-    }
-
-    /**
-     * @return The {@link StackTab}s currently being rendered by the tab stack.
-     * @VisibleForTesting
-     */
-    public StackTab[] getTabs() {
-        return mStackTabs;
-    }
-
-    /**
-     * @return The number of tabs in the tab stack.
-     * @VisibleForTesting
-     */
-    public int getCount() {
-        return mStackTabs != null ? mStackTabs.length : 0;
-    }
-
-    /**
-     * @return The number of visible tabs in the tab stack.
-     */
-    public int getVisibleCount() {
-        int visibleCount = 0;
-        if (mStackTabs != null) {
-            for (int i = 0; i < mStackTabs.length; ++i) {
-                if (mStackTabs[i].getLayoutTab().isVisible()) visibleCount++;
-            }
-        }
-        return visibleCount;
-    }
-
-    /**
-     * The scale the tabs should be currently shown at (may change based on how many are open).
-     */
-    public abstract float getScaleAmount();
-
-    /*
-     * Main Interaction Methods for the rest of the application
-     *
-     *
-     * These methods are the main entry points for the model to tell the
-     * view that something has changed.  The rest of the application can
-     * alert this class that something in the tab stack has changed or that
-     * the user has decided to enter the tab switcher.
-     *
-     */
-
-    /**
-     * Triggers the closing motions.
-     *
-     * @param time The current time of the app in ms.
-     * @param id The id of the tab that get closed.
-     */
-    public void tabClosingEffect(long time, int id) {
-        if (mStackTabs == null) return;
-
-        // |id| cannot be used to access the particular tab in the model.
-        // The tab is already gone from the model by this point.
-
-        int newIndex = 0;
-        boolean needAnimation = false;
-        for (int i = 0; i < mStackTabs.length; ++i) {
-            if (mStackTabs[i].getId() == id) {
-                // Mark the {@link StackTab} as dying so that when the animation is
-                // finished we can clear it out of the stack. This supports
-                // multiple {@link StackTab} deletions.
-                needAnimation |= !mStackTabs[i].isDying();
-                mStackTabs[i].setDying(true);
-            } else {
-                // Update the {@link StackTab} with a new index here.  This makes sure the
-                // {@link LayoutTab} end up in the proper place.
-                mStackTabs[i].setNewIndex(newIndex++);
-            }
-        }
-
-        if (needAnimation) {
-            mScrollOffsetForDyingTabs = mScrollOffset;
-            mSpacing = computeSpacing(newIndex);
-
-            startAnimation(time, OverviewAnimationType.DISCARD);
-        }
-
-        if (newIndex == 0) mIsDying = true;
-    }
-
-    /**
-     * @return True if we should put the close button on the right side of the tab, or false if
-     *              we should put it on the left. This method already accounts for RTL flipping.
-     */
-    private boolean isCloseButtonOnRight() {
-        return mCurrentMode == Orientation.PORTRAIT ^ LocalizationUtils.isLayoutRtl();
-    }
-
-    /**
-     * Animates all the tabs closing at once.
-     *
-     * @param time The current time of the app in ms.
-     */
-    public void tabsAllClosingEffect(long time) {
-        boolean needAnimation = false;
-
-        if (mStackTabs != null) {
-            for (int i = 0; i < mStackTabs.length; ++i) {
-                needAnimation |= !mStackTabs[i].isDying();
-                mStackTabs[i].setDying(true);
-            }
-        } else {
-            // This needs to be set to true to handle the case where both the normal and
-            // incognito tabs are being closed.
-            needAnimation = true;
-        }
-
-        if (needAnimation) {
-            mScrollOffsetForDyingTabs = mScrollOffset;
-            mSpacing = computeSpacing(0);
-
-            if (mStackTabs != null) {
-                for (int i = 0; i < mStackTabs.length; i++) {
-                    StackTab tab = mStackTabs[i];
-                    tab.setDiscardOriginY(0.f);
-                    tab.setDiscardOriginX(isCloseButtonOnRight()
-                                    ? tab.getLayoutTab().getOriginalContentWidth()
-                                    : 0.f);
-                    tab.setDiscardFromClick(true);
-                }
-            }
-            startAnimation(time, OverviewAnimationType.DISCARD_ALL);
-        }
-
-        mIsDying = true;
-    }
-
-    /**
-     * Animates a new tab opening.
-     *
-     * @param time The current time of the app in ms.
-     * @param id The id of the new tab to animate.
-     */
-    public void tabCreated(long time, int id) {
-        if (!createTabHelper(id)) return;
-        mIsDying = false;
-
-        finishAnimation(time);
-        startAnimation(time, OverviewAnimationType.NEW_TAB_OPENED,
-                TabModelUtils.getTabIndexById(mTabList, id), TabList.INVALID_TAB_INDEX, false);
-    }
-
-    /**
-     * Animates the closing of the stack. Focusing on the selected tab.
-     *
-     * @param time The current time of the app in ms.
-     * @param id   The id of the tab to select.
-     */
-    public void tabSelectingEffect(long time, int id) {
-        int index = TabModelUtils.getTabIndexById(mTabList, id);
-        startAnimation(time, OverviewAnimationType.TAB_FOCUSED, index, -1, false);
-    }
-
-    /**
-     * Called set up the tab stack to the initial state when it is entered.
-     *
-     * @param time The current time of the app in ms.
-     * @param focused Whether or not the stack was focused when entering.
-     */
-    public void stackEntered(long time, boolean focused) {
-        // Don't request new thumbnails until the animation is over. We should
-        // have cached the visible ones already.
-        boolean finishImmediately = !focused;
-        mSpacing = computeSpacing(mStackTabs != null ? mStackTabs.length : 0);
-        resetAllScrollOffset();
-        startAnimation(time, OverviewAnimationType.ENTER_STACK, finishImmediately);
-    }
-
-    /**
-     * @return Whether or not the TabList represented by this TabStackState should be displayed.
-     */
-    public boolean isDisplayable() {
-        if (mTabList == null) return false;
-
-        return !mTabList.isIncognito() || (!mIsDying && mTabList.getCount() > 0);
-    }
-
-    private float getDefaultDiscardDirection() {
-        return (mCurrentMode == Orientation.LANDSCAPE && LocalizationUtils.isLayoutRtl()) ? -1.0f
-                                                                                          : 1.0f;
-    }
-
-    /**
-     * show is called to set up the initial variables, and must always be called before
-     * displaying the stack.
-     * @param isStackForCurrentTabList Whether this {@link Stack} is for the current tab list.
-     */
-    public void show(boolean isStackForCurrentTabList) {
-        mIsStackForCurrentTabList = isStackForCurrentTabList;
-
-        mDiscardDirection = getDefaultDiscardDirection();
-
-        // Reinitialize the roll over counter for each tabswitcher session.
-        mOverScrollCounter = 0;
-
-        // TODO: Recreating the stack {@link StackTab} here might be overkill.  Will these
-        // already exist in the cache?  Check to make sure it makes sense.
-        createStackTabs(false);
-    }
-
-    /*
-     * Animation Start and Finish Methods
-     *
-     * This method kicks off animations by using the
-     * TabSwitcherAnimationFactory to create an AnimatorSet.
-     */
-
-    /**
-     * Starts an animation on the stack.
-     *
-     * @param time The current time of the app in ms.
-     * @param type The type of the animation to start.
-     */
-    protected void startAnimation(long time, @OverviewAnimationType int type) {
-        startAnimation(time, type, TabList.INVALID_TAB_INDEX, false);
-    }
-
-    /**
-     * Starts an animation on the stack.
-     *
-     * @param time The current time of the app in ms.
-     * @param type The type of the animation to start.
-     * @param finishImmediately Whether the animation jumps straight to the end.
-     */
-    private void startAnimation(
-            long time, @OverviewAnimationType int type, boolean finishImmediately) {
-        startAnimation(time, type, TabList.INVALID_TAB_INDEX, finishImmediately);
-    }
-
-    /**
-     * Starts an animation on the stack.
-     *
-     * @param time The current time of the app in ms.
-     * @param type The type of the animation to start.
-     * @param sourceIndex The source index needed by some animation types.
-     * @param finishImmediately Whether the animation jumps straight to the end.
-     */
-    protected void startAnimation(long time, @OverviewAnimationType int type, int sourceIndex,
-            boolean finishImmediately) {
-        startAnimation(time, type, mTabList.index(), sourceIndex, finishImmediately);
-    }
-
-    private void startAnimation(long time, @OverviewAnimationType int type, int focusIndex,
-            int sourceIndex, boolean finishImmediately) {
-        if (!canUpdateAnimation(time, type, sourceIndex, finishImmediately)) {
-            // We need to finish animations started earlier before we start
-            // off a new one.
-            finishAnimation(time);
-            // Stop movement while the animation takes place.
-            stopScrollingMovement(time);
-        }
-
-        if (mAnimationFactory != null && mViewAnimationFactory != null) {
-            mOverviewAnimationType = type;
-
-            // First try to build a View animation.  Then fallback to the compositor animation
-            // if one isn't created.
-            mViewAnimations = mViewAnimationFactory.createAnimatorForType(
-                    type, mStackTabs, mLayout.getViewContainer(), mTabList, focusIndex);
-
-            if (mViewAnimations != null) {
-                mViewAnimations.addListener(mViewAnimatorListener);
-            } else {
-                // Build the AnimatorSet using the TabSwitcherAnimationFactory.
-                // This will give us the appropriate AnimatorSet based on the current
-                // state of the tab switcher and the OverviewAnimationType specified.
-                mStackAnimatorSet = mAnimationFactory.createAnimatorSetForType(type, this,
-                        mStackTabs, focusIndex, sourceIndex, mSpacing, getDiscardRange());
-            }
-
-            if (mStackAnimatorSet != null) mStackAnimatorSet.start();
-            if (mViewAnimations != null) mViewAnimations.start();
-            if (mStackAnimatorSet != null || mViewAnimations != null) {
-                mLayout.onStackAnimationStarted();
-            }
-
-            if ((mStackAnimatorSet == null && mViewAnimations == null) || finishImmediately) {
-                finishAnimation(time);
-            }
-        }
-
-        mLayout.requestUpdate();
-    }
-
-    /**
-     * Performs the necessary actions to finish the current animation.
-     *
-     * @param time The current time of the app in ms.
-     */
-    protected void finishAnimation(long time) {
-        if (mStackAnimatorSet != null) mStackAnimatorSet.end();
-        if (mViewAnimations != null) mViewAnimations.end();
-        if (mStackAnimatorSet != null || mViewAnimations != null) {
-            mLayout.onStackAnimationFinished();
-        }
-
-        switch (mOverviewAnimationType) {
-            case OverviewAnimationType.ENTER_STACK:
-                mLayout.uiDoneEnteringStack();
-                break;
-            case OverviewAnimationType.FULL_ROLL:
-                for (int i = 0; i < mStackTabs.length; i++) {
-                    mStackTabs[i].getLayoutTab().setTiltX(0, 0);
-                    mStackTabs[i].getLayoutTab().setTiltY(0, 0);
-                }
-                springBack(time);
-                break;
-            case OverviewAnimationType.TAB_FOCUSED:
-            // Purposeful fall through
-            case OverviewAnimationType.NEW_TAB_OPENED:
-                // Nothing to do.
-                break;
-            case OverviewAnimationType.DISCARD_ALL:
-                mLayout.uiDoneClosingAllTabs(mTabList.isIncognito());
-                cleanupStackTabState();
-                break;
-            case OverviewAnimationType.UNDISCARD:
-            // Purposeful fall through because if UNDISCARD animation updated DISCARD animation,
-            // DISCARD animation clean up below is not called so UNDISCARD is responsible for
-            // cleaning it up.
-            case OverviewAnimationType.DISCARD:
-                // Remove all dying tabs from mStackTabs.
-                if (mStackTabs != null) {
-                    // Request for the model to be updated.
-                    for (int i = 0; i < mStackTabs.length; ++i) {
-                        StackTab tab = mStackTabs[i];
-                        if (tab.isDying()) {
-                            mLayout.uiDoneClosingTab(
-                                    time, tab.getId(), true, mTabList.isIncognito());
-                        }
-                    }
-                }
-                cleanupStackTabState();
-                break;
-            default:
-                break;
-        }
-
-        // sync the scrollTarget and scrollOffset. For ENTER_STACK animation, don't sync to
-        // ensure the tab can tilt back.
-        if (mOverviewAnimationType != OverviewAnimationType.NONE
-                && mOverviewAnimationType != OverviewAnimationType.ENTER_STACK
-                && mScroller.isFinished()) {
-            setScrollTarget(mScrollOffset, true);
-        }
-        mOverviewAnimationType = OverviewAnimationType.NONE;
-
-        mStackAnimatorSet = null;
-        mViewAnimations = null;
-    }
-
-    private void cleanupStackTabState() {
-        if (mStackTabs != null) {
-            // First count the number of tabs that are still alive.
-            int nNumberOfLiveTabs = 0;
-            for (int i = 0; i < mStackTabs.length; ++i) {
-                if (mStackTabs[i].isDying()) {
-                    mLayout.releaseTabLayout(mStackTabs[i].getLayoutTab());
-                } else {
-                    nNumberOfLiveTabs++;
-                }
-            }
-
-            if (nNumberOfLiveTabs == 0) {
-                // We have no more live {@link StackTab}. Just clean all tab related states.
-                cleanupTabs();
-            } else if (nNumberOfLiveTabs < mStackTabs.length) {
-                // If any tabs have died, we need to remove them from mStackTabs.
-
-                StackTab[] oldTabs = mStackTabs;
-                mStackTabs = new StackTab[nNumberOfLiveTabs];
-
-                int newIndex = 0;
-                for (int i = 0; i < oldTabs.length; ++i) {
-                    if (!oldTabs[i].isDying()) {
-                        mStackTabs[newIndex] = oldTabs[i];
-                        mStackTabs[newIndex].setNewIndex(newIndex);
-                        newIndex++;
-                    }
-                }
-                assert newIndex == nNumberOfLiveTabs;
-            }
-        }
-
-        mDiscardDirection = getDefaultDiscardDirection();
-    }
-
-    /**
-     * Ensure that there are no dying tabs by finishing the current animation.
-     *
-     * @param time The current time of the app in ms.
-     */
-    public void ensureCleaningUpDyingTabs(long time) {
-        finishAnimation(time);
-    }
-
-    /**
-     * Decide if the animation can be started without cleaning up the current animation.
-     * @param time              The current time of the app in ms.
-     * @param type              The type of the animation to start.
-     * @param sourceIndex       The source index needed by some animation types.
-     * @param finishImmediately Whether the animation jumps straight to the end.
-     * @return                  true, if we can start the animation without cleaning up the
-     *                          current animation.
-     */
-    private boolean canUpdateAnimation(long time, @OverviewAnimationType int type, int sourceIndex,
-            boolean finishImmediately) {
-        if (mAnimationFactory != null) {
-            if ((mOverviewAnimationType == OverviewAnimationType.DISCARD
-                        || mOverviewAnimationType == OverviewAnimationType.UNDISCARD
-                        || mOverviewAnimationType == OverviewAnimationType.DISCARD_ALL)
-                    && (type == OverviewAnimationType.DISCARD
-                            || type == OverviewAnimationType.UNDISCARD
-                            || type == OverviewAnimationType.DISCARD_ALL)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Cancel scrolling animation which is a part of discarding animation.
-     * @return true if the animation is canceled, false, if there is nothing to cancel.
-     */
-    private boolean cancelDiscardScrollingAnimation() {
-        if (mOverviewAnimationType == OverviewAnimationType.DISCARD
-                || mOverviewAnimationType == OverviewAnimationType.UNDISCARD
-                || mOverviewAnimationType == OverviewAnimationType.DISCARD_ALL) {
-            if (mStackAnimatorSet != null) {
-                mStackAnimatorSet.cancelCancelableAnimators();
-            }
-            return true;
-        }
-        return false;
-    }
-
-    /**
-     * Checks any Android view animations to see if they have finished yet.
-     * @param time      The current time of the app in ms.
-     * @param jumpToEnd Whether to finish the animation.
-     * @return          Whether the animation was finished.
-     */
-    public boolean onUpdateViewAnimation(long time, boolean jumpToEnd) {
-        boolean finished = true;
-        if (mViewAnimations != null) {
-            finished = !mViewAnimations.isRunning();
-            finishAnimationsIfDone(time, jumpToEnd);
-        }
-        return finished;
-    }
-
-    /**
-     * Steps the animation forward and updates all the animated values.
-     * @param time      The current time of the app in ms.
-     * @param jumpToEnd Whether to finish the animation.
-     * @return          Whether the animation was finished.
-     */
-    public boolean onUpdateCompositorAnimations(long time, boolean jumpToEnd) {
-        if (!jumpToEnd) updateScrollOffset(time);
-
-        boolean animatorSetFinished = true;
-        if (mStackAnimatorSet != null) {
-            animatorSetFinished = jumpToEnd ? true : !mStackAnimatorSet.isRunning();
-        }
-
-        if (mStackAnimatorSet != null) finishAnimationsIfDone(time, jumpToEnd);
-        if (jumpToEnd) forceScrollStop();
-
-        return animatorSetFinished;
-    }
-
-    private void finishAnimationsIfDone(long time, boolean jumpToEnd) {
-        boolean hasViewAnimations = mViewAnimations != null;
-        boolean isViewFinished = hasViewAnimations ? !mViewAnimations.isRunning() : true;
-
-        boolean hasAnimatorSetTabAnimations = mStackAnimatorSet != null;
-        boolean isAnimatorSetTabFinished =
-                hasAnimatorSetTabAnimations ? !mStackAnimatorSet.isRunning() : true;
-
-        boolean hasAnimations = hasViewAnimations || hasAnimatorSetTabAnimations;
-
-        boolean shouldFinish = jumpToEnd && hasAnimations;
-        shouldFinish |= hasAnimations && (!hasViewAnimations || isViewFinished)
-                && (!hasAnimatorSetTabAnimations || isAnimatorSetTabFinished);
-
-        if (shouldFinish) finishAnimation(time);
-    }
-
-    /**
-     * Determines which action was specified by the user's drag.
-     *
-     * @param scrollDrag  The number of pixels moved in the scroll direction.
-     * @param discardDrag The number of pixels moved in the discard direction.
-     * @return            The current lock mode or a hint if the motion was not strong enough
-     *                    to fully lock the mode.
-     */
-    private @DragLock int computeDragLock(float scrollDrag, float discardDrag) {
-        scrollDrag = Math.abs(scrollDrag);
-        discardDrag = Math.abs(discardDrag);
-        @DragLock
-        int hintLock = (discardDrag * DRAG_ANGLE_THRESHOLD) > scrollDrag ? DragLock.DISCARD
-                                                                         : DragLock.SCROLL;
-        // If the user paused the drag for too long, re-determine what the new action is.
-        long timeMillisecond = System.currentTimeMillis();
-        if ((timeMillisecond - mLastScrollUpdate) > DRAG_TIME_THRESHOLD) {
-            mDragLock = DragLock.NONE;
-        }
-        // Select the scroll lock if enough conviction is put into scrolling.
-        if ((mDragLock == DragLock.NONE && Math.abs(scrollDrag - discardDrag) > mMinScrollMotion)
-                || (mDragLock == DragLock.DISCARD && discardDrag > mMinScrollMotion)
-                || (mDragLock == DragLock.SCROLL && scrollDrag > mMinScrollMotion)) {
-            mLastScrollUpdate = timeMillisecond;
-            if (mDragLock == DragLock.NONE) {
-                mDragLock = hintLock;
-            }
-        }
-        // Returns a hint of the lock so we can show feedback even if the lock is not committed
-        // yet.
-        return mDragLock == DragLock.NONE ? hintLock : mDragLock;
-    }
-
-    /*
-     * User Input Routines:
-     *
-     * The input routines that process gestures and click touches.  These
-     * are the main way to interact with the view directly.  Other input
-     * paths happen when model changes impact the view.  This can happen
-     * as a result of some of these actions or from other user input (ie:
-     * from the Toolbar).  These are ignored if an animation is currently
-     * in progress.
-     */
-
-    /**
-     * Called on drag event (from scroll events in the gesture detector).
-     *
-     * @param time    The current time of the app in ms.
-     * @param x       The x coordinate of the end of the drag event.
-     * @param y       The y coordinate of the end of the drag event.
-     * @param amountX The number of pixels dragged in the x direction since the last event.
-     * @param amountY The number of pixels dragged in the y direction since the last event.
-     */
-    public void drag(long time, float x, float y, float amountX, float amountY) {
-        float scrollDrag;
-        float discardDrag;
-        if (mCurrentMode == Orientation.PORTRAIT) {
-            discardDrag = amountX;
-            scrollDrag = amountY;
-        } else {
-            discardDrag = amountY;
-            scrollDrag = LocalizationUtils.isLayoutRtl() ? -amountX : amountX;
-        }
-        @DragLock
-        int hintLock = computeDragLock(scrollDrag, discardDrag);
-        if (hintLock == DragLock.DISCARD) {
-            discard(x, y, amountX, amountY);
-        } else {
-            // Only cancel the current discard attempt if the scroll lock is committed:
-            // by using mDragLock instead of hintLock.
-            if (mDragLock == DragLock.SCROLL && mDiscardingTab != null) {
-                commitDiscard(time, false);
-            }
-            scroll(x, y, LocalizationUtils.isLayoutRtl() ? -amountX : amountX, amountY, false);
-        }
-        mLayout.requestUpdate();
-    }
-
-    /**
-     * Discards and updates the position based on the input event values.
-     *
-     * @param x       The x coordinate of the end of the drag event.
-     * @param y       The y coordinate of the end of the drag event.
-     * @param amountX The number of pixels dragged in the x direction since the last event.
-     * @param amountY The number of pixels dragged in the y direction since the last event.
-     */
-    private void discard(float x, float y, float amountX, float amountY) {
-        if (mStackTabs == null
-                || (mOverviewAnimationType != OverviewAnimationType.NONE
-                        && mOverviewAnimationType != OverviewAnimationType.DISCARD
-                        && mOverviewAnimationType != OverviewAnimationType.DISCARD_ALL
-                        && mOverviewAnimationType != OverviewAnimationType.UNDISCARD)) {
-            return;
-        }
-
-        if (mDiscardingTab == null) {
-            if (!mInSwipe) {
-                mDiscardingTab = getTabAtPositon(x, y);
-            } else {
-                if (mTabList.index() < 0) return;
-                mDiscardingTab = mStackTabs[mTabList.index()];
-            }
-
-            if (mDiscardingTab != null) {
-                cancelDiscardScrollingAnimation();
-
-                // Make sure we are well within the tab in the discard direction.
-                RectF target = getClickTargetBoundsForLayoutTab(mDiscardingTab.getLayoutTab());
-                float distanceToEdge;
-                float edgeToEdge;
-                if (mCurrentMode == Orientation.PORTRAIT) {
-                    mDiscardDirection = 1.0f;
-                    distanceToEdge = Math.max(target.left - x, x - target.right);
-                    edgeToEdge = target.width();
-                } else {
-                    mDiscardDirection = 2.0f - 4.0f * (x / mLayout.getWidth());
-                    mDiscardDirection = MathUtils.clamp(mDiscardDirection, -1.0f, 1.0f);
-                    distanceToEdge = Math.max(target.top - y, y - target.bottom);
-                    edgeToEdge = target.height();
-                }
-
-                float scaledDiscardX = x - mDiscardingTab.getLayoutTab().getX();
-                float scaledDiscardY = y - mDiscardingTab.getLayoutTab().getY();
-                mDiscardingTab.setDiscardOriginX(scaledDiscardX / mDiscardingTab.getScale());
-                mDiscardingTab.setDiscardOriginY(scaledDiscardY / mDiscardingTab.getScale());
-                mDiscardingTab.setDiscardFromClick(false);
-
-                if (Math.abs(distanceToEdge) < DISCARD_SAFE_SELECTION_PCTG * edgeToEdge) {
-                    mDiscardingTab = null;
-                }
-            }
-        }
-        if (mDiscardingTab != null) {
-            float deltaAmount = mCurrentMode == Orientation.PORTRAIT ? amountX : amountY;
-            mDiscardingTab.addToDiscardAmount(deltaAmount);
-        }
-    }
-
-    /**
-     * Called on touch/tilt scroll event.
-     *
-     * @param x       The x coordinate of the end of the scroll event.
-     * @param y       The y coordinate of the end of the scroll event.
-     * @param amountX The number of pixels scrolled in the x direction.
-     * @param amountY The number of pixels scrolled in the y direction.
-     * @param isTilt  True if the call comes from a tilt event.
-     */
-    private void scroll(float x, float y, float amountX, float amountY, boolean isTilt) {
-        if ((!mScroller.isFinished() && isTilt) || mStackTabs == null
-                || (mOverviewAnimationType != OverviewAnimationType.NONE
-                           && mOverviewAnimationType != OverviewAnimationType.DISCARD
-                           && mOverviewAnimationType != OverviewAnimationType.UNDISCARD
-                           && mOverviewAnimationType != OverviewAnimationType.DISCARD_ALL
-                           && mOverviewAnimationType != OverviewAnimationType.ENTER_STACK)) {
-            return;
-        }
-
-        float amountScreen = mCurrentMode == Orientation.PORTRAIT ? amountY : amountX;
-        float amountScroll = amountScreen;
-        float amountEvenOut = amountScreen;
-
-        // Computes the right amount for the scrolling so the finger matches the tab under it.
-        float tabScrollSpaceFinal = 0;
-        if (mScrollingTab == null || isTilt) {
-            mScrollingTab = getTabAtPositon(x, y);
-        }
-
-        if (mScrollingTab == null && mInSwipe && mStackTabs != null) {
-            int index = mTabList.index();
-            if (index >= 0 && index <= mStackTabs.length) mScrollingTab = mStackTabs[index];
-        }
-
-        if (mScrollingTab == null) {
-            if (!isTilt) {
-                amountScroll = 0;
-                amountEvenOut = 0;
-            }
-        } else if (mScrollingTab.getIndex() == 0) {
-            amountEvenOut = 0;
-        } else {
-            // Find the scroll that make the selected tab move the right
-            // amount on the screen.
-            float tabScrollSpace = mScrollingTab.getScrollOffset() + mScrollOffset;
-            float tabScreen = scrollToScreen(tabScrollSpace);
-            tabScrollSpaceFinal = screenToScroll(tabScreen + amountScreen);
-            amountScroll = tabScrollSpaceFinal - tabScrollSpace;
-            // Matching the finger is too strong of a constraints on the edges. So we make
-            // sure the end value is not too far from the linear case.
-            amountScroll = Math.signum(amountScreen)
-                    * MathUtils.clamp(Math.abs(amountScroll), Math.abs(amountScreen) * 0.5f,
-                              Math.abs(amountScreen) * 2.0f);
-        }
-
-        // Evens out the tabs and correct the scroll amount if needed.
-        if (evenOutTabs(amountEvenOut, false) && mScrollingTab.getIndex() > 0) {
-            // Adjust the amount after the even phase
-            float tabScrollSpace = mScrollingTab.getScrollOffset() + mScrollOffset;
-            amountScroll = tabScrollSpaceFinal - tabScrollSpace;
-        }
-
-        // Actually do the scrolling.
-        setScrollTarget(mScrollTarget + amountScroll, false);
-    }
-
-    /**
-     * OverlappingStack implements this to auto-magically the cards as the stack get scrolled.
-     * NonOverlappingStack just ignores this call.
-     *
-     * @param amount                The amount of scroll performed in pixel. The sign indicates
-     *                              the direction.
-     * @param allowReverseDirection Whether or not to allow corrections in the reverse direction
-     *                              of the amount scrolled.
-     * @return                      True if any tab had been 'visibly' moved.
-     */
-    protected abstract boolean evenOutTabs(float amount, boolean allowReverseDirection);
-
-    /**
-     * Called on touch fling event. Scroll the stack or help to discard a tab.
-     *
-     * @param time      The current time of the app in ms.
-     * @param x         The y coordinate of the start of the fling event.
-     * @param y         The y coordinate of the start of the fling event.
-     * @param velocityX The amount of velocity in the x direction.
-     * @param velocityY The amount of velocity in the y direction.
-     */
-    public void fling(long time, float x, float y, float velocityX, float velocityY) {
-        if (mDragLock != DragLock.SCROLL && mDiscardingTab != null) {
-            float velocity = mCurrentMode == Orientation.PORTRAIT ? velocityX : velocityY;
-            float maxDelta = getDiscardRange() * DISCARD_FLING_MAX_CONTRIBUTION;
-            float deltaAmount = MathUtils.clamp(velocity * DISCARD_FLING_DT, -maxDelta, maxDelta);
-            mDiscardingTab.addToDiscardAmount(deltaAmount);
-        } else if (mOverviewAnimationType == OverviewAnimationType.NONE && mScroller.isFinished()
-                && mOverScrollOffset == 0 && getTabIndexAtPositon(x, y) >= 0) {
-            float velocity = mCurrentMode == Orientation.PORTRAIT
-                    ? velocityY
-                    : (LocalizationUtils.isLayoutRtl() ? -velocityX : velocityX);
-            // Fling only overscrolls when the stack is fully unfolded.
-            mScroller.fling(0, (int) mScrollTarget, 0, (int) velocity, 0, 0,
-                    (int) getMinScroll(false), (int) getMaxScroll(false), 0,
-                    (int) ((velocity > 0 ? mMaxOverScroll : mMaxUnderScroll)
-                            * MAX_OVER_FLING_SCALE),
-                    time);
-
-            // Set the target to the final scroll position to make sure
-            // the offset finally gets there regardless of what happens.
-            // We override this when the user interrupts the fling though.
-            setScrollTarget(mScroller.getFinalY(), false);
-        }
-    }
-
-    /**
-     * Get called on down touch event.
-     *
-     * @param time The current time of the app in ms.
-     */
-    public void onDown(long time) {
-        mDragLock = DragLock.NONE;
-        if (mOverviewAnimationType == OverviewAnimationType.NONE) {
-            stopScrollingMovement(time);
-        }
-        // Resets the scrolling state.
-        mScrollingTab = null;
-        commitDiscard(time, false);
-    }
-
-    /**
-     * Get called on long press touch event.
-     *
-     * @param time The current time of the app in ms.
-     * @param x The x coordinate in pixel inside the stack view.
-     * @param y The y coordinate in pixel inside the stack view.
-     */
-    public abstract void onLongPress(long time, float x, float y);
-
-    /**
-     * Called when at least 2 touch events are detected.
-     *
-     * @param time       The current time of the app in ms.
-     * @param x0         The x coordinate of the first touch event.
-     * @param y0         The y coordinate of the first touch event.
-     * @param x1         The x coordinate of the second touch event.
-     * @param y1         The y coordinate of the second touch event.
-     * @param firstEvent The pinch is the first of a sequence of pinch events.
-     */
-    public abstract void onPinch(
-            long time, float x0, float y0, float x1, float y1, boolean firstEvent);
-
-    /**
-     * Commits or release the that currently being considered for discard. This function
-     * also triggers the associated animations.
-     *
-     * @param time         The current time of the app in ms.
-     * @param allowDiscard Whether to allow to discard the tab currently being considered
-     *                     for discard.
-     */
-    protected void commitDiscard(long time, boolean allowDiscard) {
-        if (mDiscardingTab == null) return;
-
-        assert mStackTabs != null;
-        StackTab discarded = mDiscardingTab;
-        if (Math.abs(discarded.getDiscardAmount()) / getDiscardRange() > DISCARD_COMMIT_THRESHOLD
-                && allowDiscard) {
-            mLayout.uiRequestingCloseTab(time, discarded.getId());
-            RecordUserAction.record("MobileStackViewSwipeCloseTab");
-            RecordUserAction.record("MobileTabClosed");
-        } else {
-            startAnimation(time, OverviewAnimationType.UNDISCARD);
-        }
-        mDiscardingTab = null;
-        mLayout.requestUpdate();
-    }
-
-    /**
-     * Called on touch up or cancel event.
-     */
-    public void onUpOrCancel(long time) {
-        // Commit or uncommit discard tab
-        commitDiscard(time, true);
-
-        resetInputActionIndices();
-
-        springBack(time);
-    }
-
-    /**
-     * Bounces the scroll position back to a valid value (e.g. to correct an overscroll or
-     * implement snapping).
-     */
-    protected abstract void springBack(long time);
-
-    /**
-     * Called on touch click event.
-     *
-     * @param time The current time of the app in ms.
-     * @param x    The x coordinate in pixel inside the stack view.
-     * @param y    The y coordinate in pixel inside the stack view.
-     */
-    public void click(long time, float x, float y) {
-        if (mOverviewAnimationType != OverviewAnimationType.NONE
-                && mOverviewAnimationType != OverviewAnimationType.DISCARD
-                && mOverviewAnimationType != OverviewAnimationType.UNDISCARD
-                && mOverviewAnimationType != OverviewAnimationType.DISCARD_ALL) {
-            return;
-        }
-        int clicked = getTabIndexAtPositon(x, y, mCompositorButtonSlop);
-        if (clicked >= 0) {
-            // Check if the click was within the boundaries of the close button defined by its
-            // visible coordinates.
-            if (checkCloseHitTestOnLayoutTab(x, y, mStackTabs[clicked].getLayoutTab())) {
-                // Tell the model to close the tab because the close button was pressed.  The
-                // model will then trigger a notification which will start the actual close
-                // process here if necessary.
-                StackTab tab = mStackTabs[clicked];
-                final float halfCloseBtnWidth = LayoutTab.CLOSE_BUTTON_WIDTH_DP / 2.f;
-                final float halfCloseBtnHeight = mBorderTopPadding / 2.f;
-                final float contentWidth = tab.getLayoutTab().getOriginalContentWidth();
-
-                tab.setDiscardOriginY(halfCloseBtnHeight);
-                tab.setDiscardOriginX(isCloseButtonOnRight() ? contentWidth - halfCloseBtnWidth
-                                                             : halfCloseBtnWidth);
-                tab.setDiscardFromClick(true);
-                mLayout.uiRequestingCloseTab(time, tab.getId());
-                RecordUserAction.record("MobileStackViewCloseTab");
-                RecordUserAction.record("MobileTabClosed");
-            } else {
-                // Let the model know that a new {@link LayoutTab} was selected. The model will
-                // notify us if we need to do anything visual. setIndex() will possibly switch
-                // the models and broadcast the event.
-                mLayout.uiSelectingTab(time, mStackTabs[clicked].getId());
-            }
-        }
-    }
-
-    /**
-     * Tests if a point is inside the closing button of the tab.
-     *
-     * @param x The horizontal coordinate of the hit testing point.
-     * @param y The vertical coordinate of the hit testing point.
-     * @param layoutTab The {@link LayoutTab} to test on.
-     * @return  Whether the hit testing point is inside the tab.
-     */
-    @VisibleForTesting
-    public boolean checkCloseHitTestOnLayoutTab(float x, float y, LayoutTab layoutTab) {
-        RectF closeRectangle = getCloseBoundsOnLayoutTab(layoutTab);
-        return closeRectangle != null ? closeRectangle.contains(x, y) : false;
-    }
-
-    /**
-     * @param layoutTab The {@link LayoutTab} to check.
-     * @return The bounds of the {@link LayoutTab} of the close button. {@code null} if the close
-     *         button is not clickable.
-     */
-    @VisibleForTesting
-    public RectF getCloseBoundsOnLayoutTab(LayoutTab layoutTab) {
-        if (!layoutTab.get(LayoutTab.IS_TITLE_NEEDED) || !layoutTab.get(LayoutTab.IS_VISIBLE)
-                || layoutTab.get(LayoutTab.BORDER_CLOSE_BUTTON_ALPHA) < 0.5f
-                || layoutTab.get(LayoutTab.BORDER_ALPHA) < 0.5f
-                || layoutTab.get(LayoutTab.BORDER_ALPHA) != 1.0f
-                || Math.abs(layoutTab.get(LayoutTab.TILT_X_IN_DEGREES)) > 1.0f
-                || Math.abs(layoutTab.get(LayoutTab.TILT_Y_IN_DEGREES)) > 1.0f) {
-            return null;
-        }
-        RectF closePlacement = layoutTab.get(LayoutTab.CLOSE_PLACEMENT);
-        closePlacement.set(0, 0, LayoutTab.CLOSE_BUTTON_WIDTH_DP, LayoutTab.CLOSE_BUTTON_WIDTH_DP);
-        if (layoutTab.get(LayoutTab.CLOSE_BUTTON_IS_ON_RIGHT)) {
-            closePlacement.offset(layoutTab.getFinalContentWidth() - closePlacement.width(), 0.f);
-        }
-        if (closePlacement.bottom > layoutTab.getFinalContentHeight()
-                || closePlacement.right > layoutTab.getFinalContentWidth()) {
-            return null;
-        }
-        closePlacement.offset(layoutTab.get(LayoutTab.X) + layoutTab.get(LayoutTab.CLIPPED_X),
-                layoutTab.get(LayoutTab.Y) + layoutTab.get(LayoutTab.CLIPPED_Y));
-        closePlacement.inset(-mCompositorButtonSlop, -mCompositorButtonSlop);
-
-        return closePlacement;
-    }
-
-    /*
-     * Initialization and Utility Methods
-     */
-
-    /**
-     * @param context The current Android's context.
-     */
-    public void contextChanged(Context context) {
-        Resources res = context.getResources();
-        final float pxToDp = 1.0f / res.getDisplayMetrics().density;
-
-        mMinScrollMotion = DRAG_MOTION_THRESHOLD_DP;
-        final float maxOverScrollPx = res.getDimensionPixelOffset(R.dimen.over_scroll);
-        final float maxUnderScrollPx = Math.round(maxOverScrollPx * MAX_UNDER_SCROLL_SCALE);
-        mMaxOverScroll = maxOverScrollPx * pxToDp;
-        mMaxUnderScroll = maxUnderScrollPx * pxToDp;
-        mMaxOverScrollAngle = res.getInteger(R.integer.over_scroll_angle);
-        mMaxOverScrollSlide = res.getDimensionPixelOffset(R.dimen.over_scroll_slide) * pxToDp;
-        mBorderTransparentTop =
-                res.getDimension(R.dimen.tabswitcher_border_frame_transparent_top) * pxToDp;
-        mBorderTransparentSide =
-                res.getDimension(R.dimen.tabswitcher_border_frame_transparent_side) * pxToDp;
-        mBorderTopPadding = res.getDimension(R.dimen.tabswitcher_border_frame_padding_top) * pxToDp;
-        mBorderLeftPadding =
-                res.getDimension(R.dimen.tabswitcher_border_frame_padding_left) * pxToDp;
-        mCompositorButtonSlop = res.getDimension(R.dimen.compositor_button_slop) * pxToDp;
-
-        // Just in case the density has changed, rebuild the OverScroller.
-        mScroller = new StackScroller(context);
-    }
-
-    /**
-     * @param width       The new width of the layout.
-     * @param height      The new height of the layout.
-     * @param orientation The new orientation of the layout.
-     */
-    public void notifySizeChanged(float width, float height, @Orientation int orientation) {
-        updateCurrentMode(orientation);
-
-        // Changing the orientation can change which side of the tab we want to show the close
-        // button on (if the horizontal tab switcher experiment is not enabled).
-        if (mStackTabs == null) return;
-        boolean closeButtonIsOnRight = isCloseButtonOnRight();
-        for (int i = 0; i < mStackTabs.length; i++) {
-            mStackTabs[i].getLayoutTab().setCloseButtonIsOnRight(closeButtonIsOnRight);
-        }
-    }
-
-    protected float getScrollDimensionSize() {
-        return mCurrentMode == Orientation.PORTRAIT ? mLayout.getHeightMinusContentOffsetsDp()
-                                                    : mLayout.getWidth();
-    }
-
-    /**
-     * Gets the tab instance at the requested position.
-     *
-     * @param x The x coordinate where to perform the hit test.
-     * @param y The y coordinate where to perform the hit test.
-     * @return  The instance of the tab selected. null if none.
-     */
-    private StackTab getTabAtPositon(float x, float y) {
-        int tabIndexAtPosition = getTabIndexAtPositon(x, y, 0);
-        return tabIndexAtPosition < 0 ? null : mStackTabs[tabIndexAtPosition];
-    }
-
-    /**
-     * Gets the tab index at the requested position.
-     *
-     * @param x The x coordinate where to perform the hit test.
-     * @param y The y coordinate where to perform the hit test.
-     * @return  The index of the tab selected. -1 if none.
-     */
-    protected int getTabIndexAtPositon(float x, float y) {
-        return getTabIndexAtPositon(x, y, 0);
-    }
-
-    /**
-     * Gets the tab index at the requested position.
-     *
-     * @param x    The x coordinate where to perform the hit test.
-     * @param y    The y coordinate where to perform the hit test.
-     * @param slop The acceptable distance to a tab for it to be considered.
-     * @return     The index of the tab selected. -1 if none.
-     */
-    private int getTabIndexAtPositon(float x, float y, float slop) {
-        int closestIndex = -1;
-        float closestDistance = mLayout.getHeight() + mLayout.getWidth();
-        if (mStackTabs != null) {
-            for (int i = mStackTabs.length - 1; i >= 0; --i) {
-                // This is a fail safe.  We should never have a situation where a dying
-                // {@link LayoutTab} can get accessed (the animation check should catch it).
-                if (!mStackTabs[i].isDying() && mStackTabs[i].getLayoutTab().isVisible()) {
-                    float d = computeDistanceToLayoutTab(x, y, mStackTabs[i].getLayoutTab());
-                    // Strict '<' is very important here because we might have several tab at
-                    // the same place and we want the one above.
-                    if (d < closestDistance) {
-                        closestIndex = i;
-                        closestDistance = d;
-                        if (d == 0) break;
-                    }
-                }
-            }
-        }
-        return closestDistance <= slop ? closestIndex : -1;
-    }
-
-    /**
-     * Computes the Manhattan-ish distance to the edge of the tab.
-     * This distance is good enough for click detection.
-     *
-     * @param x          X coordinate of the hit testing point.
-     * @param y          Y coordinate of the hit testing point.
-     * @param layoutTab  The targeting tab.
-     * @return           The Manhattan-ish distance to the tab.
-     */
-    private static float computeDistanceToLayoutTab(float x, float y, LayoutTab layoutTab) {
-        final RectF bounds = getClickTargetBoundsForLayoutTab(layoutTab);
-        float dx = Math.max(bounds.left - x, x - bounds.right);
-        float dy = Math.max(bounds.top - y, y - bounds.bottom);
-        return Math.max(0.0f, Math.max(dx, dy));
-    }
-
-    /**
-     * @return The rectangle that represents the click target of the tab.
-     */
-    private static RectF getClickTargetBoundsForLayoutTab(LayoutTab layoutTab) {
-        final float borderScaled = BORDER_THICKNESS_DP * layoutTab.get(LayoutTab.BORDER_SCALE);
-        RectF bounds = layoutTab.get(LayoutTab.BOUNDS);
-        bounds.top = layoutTab.get(LayoutTab.Y) + layoutTab.get(LayoutTab.CLIPPED_Y) - borderScaled;
-        bounds.bottom = layoutTab.get(LayoutTab.Y) + layoutTab.get(LayoutTab.CLIPPED_Y)
-                + layoutTab.getFinalContentHeight() + borderScaled;
-        bounds.left =
-                layoutTab.get(LayoutTab.X) + layoutTab.get(LayoutTab.CLIPPED_X) - borderScaled;
-        bounds.right = layoutTab.get(LayoutTab.X) + layoutTab.get(LayoutTab.CLIPPED_X)
-                + layoutTab.getFinalContentWidth() + borderScaled;
-        return bounds;
-    }
-
-    /**
-     * ComputeTabPosition pass 1:
-     * Combine the overall stack scale with the animated tab scale.
-     *
-     * @param stackRect The frame of the stack.
-     */
-    private void computeTabScaleAlphaDepthHelper(RectF stackRect) {
-        final float stackScale = getStackScale(stackRect);
-        final float discardRange = getDiscardRange();
-
-        for (int i = 0; i < mStackTabs.length; ++i) {
-            assert mStackTabs[i] != null;
-            StackTab stackTab = mStackTabs[i];
-            LayoutTab layoutTab = stackTab.getLayoutTab();
-            final float discard = stackTab.getDiscardAmount();
-
-            // Scale
-            float discardScale =
-                    computeDiscardScale(discard, discardRange, stackTab.getDiscardFromClick());
-            layoutTab.setScale(stackTab.getScale() * discardScale * stackScale);
-            layoutTab.setBorderScale(discardScale);
-
-            // Alpha
-            float discardAlpha = computeDiscardAlpha(discard, discardRange);
-            layoutTab.setAlpha(stackTab.getAlpha() * discardAlpha);
-        }
-    }
-
-    /**
-     * ComputeTabPosition pass 2:
-     * Adjust the scroll offsets of each tab so no there is no void in between tabs.
-     */
-    private void computeTabScrollOffsetHelper() {
-        float maxScrollOffset = Float.MAX_VALUE;
-        for (int i = 0; i < mStackTabs.length; ++i) {
-            if (mStackTabs[i].isDying()) continue;
-
-            float tabScrollOffset = Math.min(maxScrollOffset, mStackTabs[i].getScrollOffset());
-            mStackTabs[i].setScrollOffset(tabScrollOffset);
-
-            float maxScreenScrollOffset = scrollToScreen(mScrollOffset + tabScrollOffset);
-            maxScrollOffset = -mScrollOffset
-                    + screenToScroll(maxScreenScrollOffset
-                            + mStackTabs[i].getSizeInScrollDirection(mCurrentMode));
-        }
-    }
-
-    /**
-     * @return Whether or not to enable logic that gives the tabs a "stacked" appearance at the
-     *         top (in portrait mode) or left (in landscape mode).
-     */
-    protected abstract boolean shouldStackTabsAtTop();
-
-    /**
-     * @return Whether or not to enable logic that gives the tabs a "stacked" appearance at the
-     *         bottom (in portrait mode) or right (in landscape mode).
-     */
-    protected abstract boolean shouldStackTabsAtBottom();
-
-    /**
-     * @return How much the stack should adjust the y position of each LayoutTab in portrait
-     *         mode (as a fraction of the amount space that would be above and below the tab if
-     *         it were centered).
-     */
-    protected abstract float getStackPortraitYOffsetProportion();
-
-    /**
-     * @return How much the stack should adjust the x position of each LayoutTab in landscape
-     *         mode (as a fraction of the amount space that would be to the left and right of
-     *         the tab if it were centered).
-     */
-    protected abstract float getStackLandscapeStartOffsetProportion();
-
-    /**
-     * @return How much the stack should adjust the x position of each LayoutTab in portrait
-     *         mode (as a fraction of the amount space that would be above and below the tab if
-     *         it were centered).
-     */
-    protected abstract float getStackLandscapeYOffsetProportion();
-
-    /**
-     * ComputeTabPosition pass 3:
-     * Compute the position of the tabs. Adjust for top and bottom stacking.
-     *
-     * @param stackRect The frame of the stack.
-     */
-    private void computeTabOffsetHelper(RectF stackRect) {
-        final boolean portrait = mCurrentMode == Orientation.PORTRAIT;
-
-        // Precompute the position using scroll offset and top stacking.
-        final float parentWidth = stackRect.width();
-        final float parentHeight = stackRect.height();
-        final float overscrollPercent = computeOverscrollPercent();
-        final float scrollOffset =
-                MathUtils.clamp(mScrollOffset, getMinScroll(false), getMaxScroll(false));
-        final float stackScale = getStackScale(stackRect);
-
-        int stackedCount = 0;
-        float minStackedPosition = 0.0f;
-        for (int i = 0; i < mStackTabs.length; ++i) {
-            assert mStackTabs[i] != null;
-            StackTab stackTab = mStackTabs[i];
-            LayoutTab layoutTab = stackTab.getLayoutTab();
-
-            // Position
-            final float stackScrollOffset =
-                    stackTab.isDying() ? mScrollOffsetForDyingTabs : scrollOffset;
-            float screenScrollOffset = approxScreen(stackTab, stackScrollOffset);
-
-            if (shouldStackTabsAtTop()) {
-                // Resolve top stacking
-                screenScrollOffset = Math.max(minStackedPosition, screenScrollOffset);
-                if (stackedCount < MAX_NUMBER_OF_STACKED_TABS_TOP) {
-                    // This make sure all the tab get stacked up as one when all the tabs do a
-                    // full roll animation.
-                    final float tiltXcos = (float) Math.cos(Math.toRadians(layoutTab.getTiltX()));
-                    final float tiltYcos = (float) Math.cos(Math.toRadians(layoutTab.getTiltY()));
-                    float collapse = Math.min(Math.abs(tiltXcos), Math.abs(tiltYcos));
-                    collapse *= layoutTab.getAlpha();
-                    minStackedPosition += StackTab.sStackedTabVisibleSize * collapse;
-                }
-                stackedCount += stackTab.isDying() ? 0 : 1;
-                if (overscrollPercent < 0) {
-                    // Oversroll at the top of the screen. For the first
-                    // OVERSCROLL_TOP_SLIDE_PCTG of the overscroll, slide the tabs
-                    // together so they completely overlap.  After that, stop scrolling the
-                    // tabs.
-                    screenScrollOffset +=
-                            (overscrollPercent / OVERSCROLL_TOP_SLIDE_PCTG) * screenScrollOffset;
-                    screenScrollOffset = Math.max(0, screenScrollOffset);
-                }
-            }
-
-            // Note: All the Offsets except for centering shouldn't depend on the tab's scaling
-            //       because it interferes the scaling center.
-
-            // Centers the tab in its parent.
-            float xIn = (parentWidth - layoutTab.getScaledContentWidth()) / 2.0f;
-            float yIn = (parentHeight - layoutTab.getScaledContentHeight()) / 2.0f;
-
-            // We want slight offset from the center so that multiple tab browsing
-            // have more space to its expanding direction. e.g., On portrait mode,
-            // there will be more space on the bottom than top.
-            final float horizontalPadding =
-                    (parentWidth
-                            - layoutTab.getOriginalContentWidth() * getScaleAmount() * stackScale)
-                    / 2.0f;
-            final float verticalPadding =
-                    (parentHeight
-                            - layoutTab.getOriginalContentHeight() * getScaleAmount() * stackScale)
-                    / 2.0f;
-
-            if (portrait) {
-                yIn += getStackPortraitYOffsetProportion() * verticalPadding;
-                yIn += screenScrollOffset;
-            } else {
-                if (LocalizationUtils.isLayoutRtl()) {
-                    xIn -= getStackLandscapeStartOffsetProportion() * horizontalPadding;
-                    xIn -= screenScrollOffset;
-                } else {
-                    xIn += getStackLandscapeStartOffsetProportion() * horizontalPadding;
-                    xIn += screenScrollOffset;
-                }
-                yIn += getStackLandscapeYOffsetProportion() * verticalPadding;
-            }
-
-            layoutTab.setX(xIn);
-            layoutTab.setY(yIn);
-        }
-
-        if (shouldStackTabsAtBottom()) {
-            // Resolve bottom stacking
-            stackedCount = 0;
-            float maxStackedPosition =
-                    portrait ? mLayout.getHeightMinusContentOffsetsDp() : mLayout.getWidth();
-            for (int i = mStackTabs.length - 1; i >= 0; i--) {
-                assert mStackTabs[i] != null;
-                StackTab stackTab = mStackTabs[i];
-                LayoutTab layoutTab = stackTab.getLayoutTab();
-                if (stackTab.isDying()) continue;
-
-                float pos;
-                if (portrait) {
-                    pos = layoutTab.getY();
-                    layoutTab.setY(Math.min(pos, maxStackedPosition));
-                } else if (LocalizationUtils.isLayoutRtl()) {
-                    // On RTL landscape, pos is a distance between tab's right and mLayout's
-                    // right.
-                    float posOffset = mLayout.getWidth()
-                            - layoutTab.getOriginalContentWidth() * getScaleAmount() * stackScale;
-                    pos = -layoutTab.getX() + posOffset;
-                    layoutTab.setX(-Math.min(pos, maxStackedPosition) + posOffset);
-                } else {
-                    pos = layoutTab.getX();
-                    layoutTab.setX(Math.min(pos, maxStackedPosition));
-                }
-                if (pos >= maxStackedPosition && stackedCount < MAX_NUMBER_OF_STACKED_TABS_BOTTOM) {
-                    maxStackedPosition -= StackTab.sStackedTabVisibleSize;
-                    stackedCount++;
-                }
-            }
-        }
-
-        // final position blend
-        final float discardRange = getDiscardRange();
-        for (int i = 0; i < mStackTabs.length; ++i) {
-            assert mStackTabs[i] != null;
-            StackTab stackTab = mStackTabs[i];
-            LayoutTab layoutTab = stackTab.getLayoutTab();
-
-            final float xIn = layoutTab.getX() + stackTab.getXInStackOffset();
-            final float yIn = layoutTab.getY() + stackTab.getYInStackOffset();
-            final float xOut = stackTab.getXOutOfStack();
-            final float yOut = stackTab.getYOutOfStack();
-            float x = MathUtils.interpolate(xOut, xIn, stackTab.getXInStackInfluence());
-            float y = MathUtils.interpolate(yOut, yIn, stackTab.getYInStackInfluence());
-
-            // Discard offsets
-            if (stackTab.getDiscardAmount() != 0) {
-                float discard = stackTab.getDiscardAmount();
-                boolean fromClick = stackTab.getDiscardFromClick();
-                float scale = computeDiscardScale(discard, discardRange, fromClick);
-                float deltaX = stackTab.getDiscardOriginX()
-                        - stackTab.getLayoutTab().getOriginalContentWidth() / 2.f;
-                float deltaY = stackTab.getDiscardOriginY()
-                        - stackTab.getLayoutTab().getOriginalContentHeight() / 2.f;
-                float discardOffset = fromClick ? 0.f : discard;
-                if (portrait) {
-                    x += discardOffset + deltaX * (1.f - scale);
-                    y += deltaY * (1.f - scale);
-                } else {
-                    x += deltaX * (1.f - scale);
-                    y += discardOffset + deltaY * (1.f - scale);
-                }
-            }
-
-            // Finally apply the stack translation
-            layoutTab.setX(stackRect.left + x);
-            layoutTab.setY(stackRect.top + y);
-        }
-    }
-
-    /**
-     * ComputeTabPosition pass 5:
-     * Computes the clipping, visibility and adjust overall alpha if needed.
-     */
-    protected abstract void computeTabClippingVisibilityHelper();
-
-    /**
-     * Computes the index that should be assumed to be the currently centered tab, for purposes
-     * of prioritizing which thumbnails to render.
-     */
-    protected abstract int computeReferenceIndex();
-
-    /**
-     * ComputeTabPosition pass 6:
-     * Updates the visibility sorting value to use to figure out which thumbnails to load.
-     *
-     * @param stackRect The frame of the stack.
-     */
-    private void computeTabVisibilitySortingHelper(RectF stackRect) {
-        int referenceIndex = mReferenceOrderIndex;
-        if (referenceIndex == -1) referenceIndex = computeReferenceIndex();
-
-        final float width = mLayout.getWidth();
-        final float height = mLayout.getHeight();
-        final float left = MathUtils.clamp(stackRect.left, 0, width);
-        final float right = MathUtils.clamp(stackRect.right, 0, width);
-        final float top = MathUtils.clamp(stackRect.top, 0, height);
-        final float bottom = MathUtils.clamp(stackRect.bottom, 0, height);
-        final float stackArea = (right - left) * (bottom - top);
-        final float layoutArea = Math.max(width * height, 1.0f);
-        final float stackVisibilityMultiplier = stackArea / layoutArea;
-
-        for (int i = 0; i < mStackTabs.length; i++) {
-            mStackTabs[i].updateStackVisiblityValue(stackVisibilityMultiplier);
-            mStackTabs[i].updateVisiblityValue(referenceIndex);
-        }
-    }
-
-    /**
-     * Determine the current amount of overscroll. If the value is 0, there is
-     * no overscroll. If the value is < 0, tabs are overscrolling towards the
-     * top or or left. If the value is > 0, tabs are overscrolling towards the
-     * bottom or right.
-     */
-    private float computeOverscrollPercent() {
-        if (mOverScrollOffset >= 0) {
-            return mOverScrollOffset / mMaxOverScroll;
-        } else {
-            return mOverScrollOffset / mMaxUnderScroll;
-        }
-    }
-
-    /**
-     * Update the tilt of each tab for full roll if necessary.
-     *
-     * @param time      The current time of the app in ms.
-     * @param stackRect The frame of the stack.
-     */
-    private void fullRollHelper(long time, RectF stackRect) {
-        if (mOverviewAnimationType != OverviewAnimationType.FULL_ROLL
-                && computeOverscrollPercent() < 0
-                && mOverScrollCounter >= OVERSCROLL_FULL_ROLL_TRIGGER) {
-            startAnimation(time, OverviewAnimationType.FULL_ROLL);
-            mOverScrollCounter = 0;
-            // Remove overscroll so when the animation finishes the overscroll won't
-            // be bothering.
-            setScrollTarget(
-                    MathUtils.clamp(mScrollOffset, getMinScroll(false), getMaxScroll(false)),
-                    false);
-        }
-    }
-
-    /** Whether or not to apply logic to enforce that there are no gaps between tabs. */
-    protected abstract boolean shouldCloseGapsBetweenTabs();
-
-    /**
-     * Computes the {@link LayoutTab} position from the stack and the stackTab data.
-     *
-     * @param time      The current time of the app in ms.
-     * @param stackRect The rectangle the stack should be drawn into. It may change over frames.
-     */
-    public void computeTabPosition(long time, RectF stackRect) {
-        if (mStackTabs == null || mStackTabs.length == 0) return;
-
-        // Step 1: Updates the {@link LayoutTab} scale, alpha and depth values.
-        computeTabScaleAlphaDepthHelper(stackRect);
-
-        if (shouldCloseGapsBetweenTabs()) {
-            // Step 2: Fix tab scroll offsets to avoid gaps.
-            computeTabScrollOffsetHelper();
-        }
-
-        // Step 3: Compute the actual position.
-        computeTabOffsetHelper(stackRect);
-
-        // Step 4: Test if the full-roll animation needs to be run.
-        fullRollHelper(time, stackRect);
-
-        // Step 5: Clipping, visibility and adjust overall alpha.
-        computeTabClippingVisibilityHelper();
-
-        // Step 6: Update visibility sorting for prioritizing thumbnail texture request.
-        computeTabVisibilitySortingHelper(stackRect);
-    }
-
-    /**
-     * @param stackFocus The current amount of focus of the stack [0 .. 1]
-     * @param orderIndex The index in the stack of the focused tab. -1 to ask the
-     *                   stack to compute it.
-     */
-    public void setStackFocusInfo(float stackFocus, int orderIndex) {
-        if (mStackTabs == null) return;
-        mReferenceOrderIndex = orderIndex;
-        for (int i = 0; i < mStackTabs.length; i++) {
-            mStackTabs[i].getLayoutTab().setBorderCloseButtonAlpha(stackFocus);
-        }
-    }
-
-    /**
-     * Reverts the closure of the tab specified by {@code tabId}.  This will run an undiscard
-     * animation on that tab.
-     * @param time  The current time of the app in ms.
-     * @param tabId The id of the tab to animate.
-     */
-    public void undoClosure(long time, int tabId) {
-        createStackTabs(true);
-        if (mStackTabs == null) return;
-
-        for (int i = 0; i < mStackTabs.length; i++) {
-            StackTab tab = mStackTabs[i];
-
-            if (tab.getId() == tabId) {
-                tab.setDiscardAmount(getDiscardRange());
-                tab.setDying(false);
-                tab.getLayoutTab().setMaxContentHeight(getMaxTabHeight());
-            }
-        }
-
-        mSpacing = computeSpacing(mStackTabs.length);
-        startAnimation(time, OverviewAnimationType.UNDISCARD);
-    }
-
-    /**
-     * Creates the {@link StackTab}s needed for display and populates {@link #mStackTabs}.
-     * It is called from show() at the beginning of every new draw phase. It tries to reuse old
-     * {@link StackTab} instead of creating new ones every time.
-     * @param restoreState Whether or not to restore the {@link LayoutTab} state when we rebuild
-     *                     the {@link StackTab}s.  There are some properties like maximum content
-     *                     size or whether or not to show the toolbar that might have to be
-     *                     restored if we're calling this while the switcher is already visible.
-     */
-    private void createStackTabs(boolean restoreState) {
-        if (mTabList == null) return;
-
-        final int count = mTabList.getCount();
-        if (count == 0) {
-            cleanupTabs();
-        } else {
-            StackTab[] oldTabs = mStackTabs;
-            mStackTabs = new StackTab[count];
-
-            final boolean isIncognito = mTabList.isIncognito();
-            final boolean needTitle = !mLayout.isStartingToHide();
-            for (int i = 0; i < count; ++i) {
-                Tab tab = mTabList.getTabAt(i);
-                int tabId = tab != null ? tab.getId() : Tab.INVALID_TAB_ID;
-                mStackTabs[i] = findTabById(oldTabs, tabId);
-
-                float maxContentWidth = -1.f;
-                float maxContentHeight = -1.f;
-
-                if (mStackTabs[i] != null && mStackTabs[i].getLayoutTab() != null && restoreState) {
-                    maxContentWidth = mStackTabs[i].getLayoutTab().getMaxContentWidth();
-                    maxContentHeight = mStackTabs[i].getLayoutTab().getMaxContentHeight();
-                }
-
-                LayoutTab layoutTab = mLayout.createLayoutTab(tabId, isIncognito,
-                        Layout.SHOW_CLOSE_BUTTON, needTitle, maxContentWidth, maxContentHeight);
-                layoutTab.setInsetBorderVertical(true);
-                layoutTab.setShowToolbar(true);
-                layoutTab.setToolbarAlpha(0.f);
-                layoutTab.setAnonymizeToolbar(!mIsStackForCurrentTabList || mTabList.index() != i);
-                layoutTab.setCloseButtonIsOnRight(isCloseButtonOnRight());
-
-                if (mStackTabs[i] == null) {
-                    mStackTabs[i] = new StackTab(layoutTab);
-                } else {
-                    mStackTabs[i].setLayoutTab(layoutTab);
-                }
-
-                mStackTabs[i].setNewIndex(i);
-                // The initial enterStack animation will take care of
-                // positioning, scaling, etc.
-            }
-        }
-    }
-
-    private StackTab findTabById(StackTab[] layoutTabs, int id) {
-        if (layoutTabs == null) return null;
-        final int count = layoutTabs.length;
-        for (int i = 0; i < count; i++) {
-            if (layoutTabs[i].getId() == id) return layoutTabs[i];
-        }
-        return null;
-    }
-
-    /**
-     * Creates a {@link StackTab}.
-     * This function should ONLY be called from {@link #tabCreated(long, int)} and nowhere else.
-     *
-     * @param id The id of the tab.
-     * @return   Whether the tab has successfully been created and added.
-     */
-    private boolean createTabHelper(int id) {
-        if (TabModelUtils.getTabById(mTabList, id) == null) return false;
-
-        // Check to see if the tab already exists in our model.  This is
-        // just to cover the case where stackEntered and then tabCreated()
-        // called in a row.
-        if (mStackTabs != null) {
-            final int count = mStackTabs.length;
-            for (int i = 0; i < count; ++i) {
-                if (mStackTabs[i].getId() == id) {
-                    return false;
-                }
-            }
-        }
-
-        createStackTabs(true);
-
-        return true;
-    }
-
-    /**
-     * @return The percentage of the screen that defines the spacing between tabs by default (no
-     *         pinch).
-     */
-    protected abstract float getSpacingScreen();
-
-    /**
-     * This redetermines the proper spacing for the {@link StackTab}. It takes in a parameter
-     * for the size instead of using the mStackTabs.length property because we could be setting
-     * the spacing for a delete before the tab has been removed (will help with animations).
-     * @param layoutTabCount The number of layout tabs currently in the Stack.
-     * @return               How far apart the tabs should be spaced (modulo certain
-     *                       adjustments, such as non-linear warping).
-     */
-    protected abstract int computeSpacing(int layoutTabCount);
-
-    private float getStackScale(RectF stackRect) {
-        return mCurrentMode == Orientation.PORTRAIT
-                ? stackRect.width() / mLayout.getWidth()
-                : stackRect.height() / mLayout.getHeightMinusContentOffsetsDp();
-    }
-
-    protected void setScrollTarget(float offset, boolean immediate) {
-        // Ensure that the stack cannot be scrolled too far in either direction.
-        // mScrollOffset is clamped between [-min, 0], where offset 0 has the
-        // farthest back tab (the first tab) at the top, with everything else
-        // pulled down, and -min has the tab at the top of the stack (the last
-        // tab) is pulled up and fully visible.
-        final boolean overscroll = allowOverscroll();
-        mScrollTarget = MathUtils.clamp(offset, getMinScroll(overscroll), getMaxScroll(overscroll));
-        if (immediate) mScrollOffset = mScrollTarget;
-        mCurrentScrollDirection = Math.signum(mScrollTarget - mScrollOffset);
-    }
-
-    /**
-     * Gets the min scroll value.
-     *
-     * @param allowUnderScroll True if underscroll is allowed.
-     */
-    protected abstract float getMinScroll(boolean allowUnderScroll);
-
-    /**
-     * Gets the max scroll value.
-     *
-     * @param allowOverscroll True if overscroll is allowed.
-     */
-    protected float getMaxScroll(boolean allowOverscroll) {
-        if (mStackTabs == null || !allowOverscroll) {
-            return 0;
-        } else {
-            return mMaxOverScroll;
-        }
-    }
-
-    private void stopScrollingMovement(long time) {
-        // We have to cancel the fling if it is in progress.
-        if (mScroller.computeScrollOffset(time)) {
-            // Set the current offset and target to the current scroll
-            // position so the {@link StackTab}s won't scroll anymore.
-            setScrollTarget(mScroller.getCurrY(), true /* immediate */);
-
-            // Tell the scroller to finish scrolling.
-            mScroller.forceFinished(true);
-        } else {
-            // If we aren't scrolling just set the target to the current
-            // offset so we don't move anymore.
-            setScrollTarget(mScrollOffset, false);
-        }
-    }
-
-    protected boolean allowOverscroll() {
-        // All the animations that want to leave the tilt value to be set by the overscroll must
-        // be added here.
-        return mOverviewAnimationType == OverviewAnimationType.NONE
-                || mOverviewAnimationType == OverviewAnimationType.VIEW_MORE
-                || mOverviewAnimationType == OverviewAnimationType.ENTER_STACK;
-    }
-
-    /**
-     * Smoothes input signal. The definition of the input is lower than the
-     * pixel density of the screen so we need to smooth the input to give the illusion of smooth
-     * animation on screen from chunky inputs.
-     * The combination of 20 pixels and 0.9f ensures that the output is not more than 2 pixels
-     * away from the target.
-     * TODO: This has nothing to do with time, just draw rate.
-     *       Is this okay or do we want to have the interpolation based on the time elapsed?
-     * @param current   The current value of the signal.
-     * @param input     The raw input value.
-     * @return          The smoothed signal.
-     */
-    private float smoothInput(float current, float input) {
-        current = MathUtils.clamp(current, input - 20, input + 20);
-        return MathUtils.interpolate(current, input, 0.9f);
-    }
-
-    protected void forceScrollStop() {
-        mScroller.forceFinished(true);
-        updateOverscrollOffset();
-        mScrollTarget = mScrollOffset;
-    }
-
-    private void updateScrollOffset(long time) {
-        // If we are still scrolling, which is determined by a disparity
-        // between our scroll offset and our scroll target, we need
-        // to try to move closer to that position.
-        if (mScrollOffset != mScrollTarget) {
-            if (mScroller.computeScrollOffset(time)) {
-                final float newScrollOffset = mScroller.getCurrY();
-                evenOutTabs(newScrollOffset - mScrollOffset, true);
-                // We are currently in the process of being flinged.  Just
-                // ask the scroller for the new position.
-                mScrollOffset = newScrollOffset;
-            } else {
-                // We are just being dragged or scrolled, not flinged.  This
-                // means we should move closer to our target quickly but not
-                // quickly enough to show the stuttering that could be
-                // exposed by the touch event rate.
-                mScrollOffset = smoothInput(mScrollOffset, mScrollTarget);
-            }
-            mLayout.requestUpdate();
-        } else {
-            // Make sure that the scroller is marked as finished when the destination is
-            // reached.
-            mScroller.forceFinished(true);
-        }
-        updateOverscrollOffset();
-    }
-
-    private void updateOverscrollOffset() {
-        float clamped = MathUtils.clamp(mScrollOffset, getMinScroll(false), getMaxScroll(false));
-        if (!allowOverscroll()) {
-            mScrollOffset = clamped;
-        }
-        float overscroll = mScrollOffset - clamped;
-
-        // Counts the number of overscroll push in the same direction in a row.
-        int derivativeState = (int) Math.signum(Math.abs(mOverScrollOffset) - Math.abs(overscroll));
-        if (derivativeState != mOverScrollDerivative && derivativeState == 1 && overscroll < 0) {
-            mOverScrollCounter++;
-        } else if (overscroll > 0 || mCurrentMode == Orientation.LANDSCAPE) {
-            mOverScrollCounter = 0;
-        }
-        mOverScrollDerivative = derivativeState;
-
-        mOverScrollOffset = overscroll;
-    }
-
-    /**
-     * Called when the stack is opened to reset all the tab and scroll positions.
-     */
-    protected abstract void resetAllScrollOffset();
-
-    protected float approxScreen(StackTab tab, float globalScrollOffset) {
-        return scrollToScreen(tab.getScrollOffset() + globalScrollOffset);
-    }
-
-    /**
-     * Maps from scroll coordinates to screen coordinates.
-     * @param scrollSpace The offset in scroll space.
-     * @return            The offset on screen corresponding to the scroll space offset.
-     */
-    public abstract float scrollToScreen(float scrollSpace);
-
-    /**
-     * Maps from screen coordinates to scroll coordinates. This allows Stack subclasses (e.g.
-     * OverlappingStack) to use non-linear scrolling.
-     * @param scrollSpace The offset in screen space.
-     * @return            The offset in scroll space corresponding to the offset on screen.
-     */
-    public abstract float screenToScroll(float screenSpace);
-
-    /**
-     * @return The range of the discard action. At the end of the +/- range the discarded tab
-     *         will be fully transparent.
-     */
-    private float getDiscardRange() {
-        return getRange(DISCARD_RANGE_SCREEN);
-    }
-
-    private float getRange(float range) {
-        return range
-                * (mCurrentMode == Orientation.PORTRAIT ? mLayout.getWidth()
-                                                        : mLayout.getHeightMinusContentOffsetsDp());
-    }
-
-    /**
-     * @return The maximum height of a layout tab in the tab switcher.
-     */
-    public abstract float getMaxTabHeight();
-
-    /**
-     * @return The current spacing between tabs.
-     */
-    public float getSpacing() {
-        return mSpacing;
-    }
-
-    /**
-     * @return The current overall scroll offset for the Stack.
-     */
-    public float getScrollOffset() {
-        return mScrollOffset;
-    }
-
-    /**
-     * Computes the scale of the tab based on its discard status.
-     *
-     * @param amount    The discard amount.
-     * @param range     The range of the absolute value of discard amount.
-     * @param fromClick Whether or not the discard was from a click or a swipe.
-     * @return          The scale of the tab to use to draw the tab.
-     */
-    public static float computeDiscardScale(float amount, float range, boolean fromClick) {
-        if (Math.abs(amount) < 1.0f) return 1.0f;
-        float t = amount / range;
-        float endScale = fromClick ? DISCARD_END_SCALE_CLICK : DISCARD_END_SCALE_SWIPE;
-        return MathUtils.interpolate(1.0f, endScale, Math.abs(t));
-    }
-
-    /**
-     * Computes the alpha value of the tab based on its discard status.
-     *
-     * @param amount The discard amount.
-     * @param range  The range of the absolute value of discard amount.
-     * @return       The alpha value that need to be applied on the tab.
-     */
-    public static float computeDiscardAlpha(float amount, float range) {
-        if (Math.abs(amount) < 1.0f) return 1.0f;
-        float t = amount / range;
-        t = MathUtils.clamp(t, -1.0f, 1.0f);
-        return 1.f - Math.abs(t);
-    }
-
-    protected void updateCurrentMode(@Orientation int orientation) {
-        mCurrentMode = orientation;
-
-        mDiscardDirection = getDefaultDiscardDirection();
-        final float opaqueTopPadding = mBorderTopPadding - mBorderTransparentTop;
-        mAnimationFactory = new StackAnimation(this, mLayout.getWidth(), mLayout.getHeight(),
-                mLayout.getTopContentOffsetDp(), mBorderTopPadding, opaqueTopPadding,
-                mBorderLeftPadding, mCurrentMode);
-        mViewAnimationFactory = new StackViewAnimation(mLayout.getContext().getResources());
-        if (mStackTabs == null) return;
-        float width = mLayout.getWidth();
-        for (int i = 0; i < mStackTabs.length; i++) {
-            LayoutTab tab = mStackTabs[i].getLayoutTab();
-            if (tab == null) continue;
-            tab.setMaxContentWidth(width);
-            tab.setMaxContentHeight(getMaxTabHeight());
-        }
-    }
-
-    /**
-     * Called to release everything. Called well after the view has been really hidden.
-     */
-    public void cleanupTabs() {
-        mStackTabs = null;
-        resetInputActionIndices();
-    }
-
-    /**
-     * Resets all the indices that are pointing to tabs for various features.
-     */
-    protected void resetInputActionIndices() {
-        mScrollingTab = null;
-        mDiscardingTab = null;
-    }
-
-    /**
-     * Reset session based parameters.
-     * Called before the a session starts. Before the show, regardless if the stack is
-     * displayable.
-     */
-    public void reset() {
-        mIsDying = false;
-    }
-
-    public static final FloatProperty<Stack> SCROLL_OFFSET =
-            new FloatProperty<Stack>("SCROLL_OFFSET") {
-                @Override
-                public void setValue(Stack stack, float v) {
-                    stack.setScrollTarget(v, true);
-                }
-
-                @Override
-                public Float get(Stack stack) {
-                    return stack.getScrollOffset();
-                }
-            };
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java
deleted file mode 100644
index 210e6a3..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackAnimation.java
+++ /dev/null
@@ -1,672 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.compositor.layouts.phone.stack;
-
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.TimeInterpolator;
-
-import androidx.annotation.IntDef;
-
-import org.chromium.base.MathUtils;
-import org.chromium.chrome.browser.compositor.layouts.Layout.Orientation;
-import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
-import org.chromium.chrome.browser.layouts.animation.CompositorAnimationHandler;
-import org.chromium.chrome.browser.layouts.animation.CompositorAnimator;
-import org.chromium.chrome.browser.layouts.animation.FloatProperty;
-import org.chromium.ui.base.LocalizationUtils;
-import org.chromium.ui.interpolators.BakedBezierInterpolator;
-import org.chromium.ui.modelutil.PropertyModel;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.ArrayList;
-
-/**
- * A factory that builds animations for the tab stack.
- */
-public class StackAnimation {
-    @IntDef({OverviewAnimationType.ENTER_STACK, OverviewAnimationType.NEW_TAB_OPENED,
-            OverviewAnimationType.TAB_FOCUSED, OverviewAnimationType.VIEW_MORE,
-            OverviewAnimationType.REACH_TOP, OverviewAnimationType.DISCARD,
-            OverviewAnimationType.DISCARD_ALL, OverviewAnimationType.UNDISCARD,
-            OverviewAnimationType.START_PINCH, OverviewAnimationType.FULL_ROLL,
-            OverviewAnimationType.NONE})
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface OverviewAnimationType {
-        int ENTER_STACK = 0;
-        int NEW_TAB_OPENED = 1;
-        int TAB_FOCUSED = 2;
-        int VIEW_MORE = 3;
-        int REACH_TOP = 4;
-        // Commit/uncommit tab discard animations
-        int DISCARD = 5;
-        int DISCARD_ALL = 6;
-        int UNDISCARD = 7;
-        // Start pinch animation un-tilt all the tabs.
-        int START_PINCH = 8;
-        // Special animation
-        int FULL_ROLL = 9;
-        // Used for when the current state of the system is not animating
-        int NONE = 10;
-    }
-
-    private static final int ENTER_STACK_ANIMATION_DURATION_MS = 300;
-    private static final int ENTER_STACK_BORDER_ALPHA_DURATION_MS = 200;
-    private static final int ENTER_STACK_RESIZE_DELAY_MS = 10;
-    private static final int ENTER_STACK_TOOLBAR_ALPHA_DURATION_MS = 100;
-    private static final int ENTER_STACK_TOOLBAR_ALPHA_DELAY_MS = 100;
-    private static final float ENTER_STACK_SIZE_RATIO = 0.35f;
-
-    private static final int TAB_FOCUSED_ANIMATION_DURATION_MS = 400;
-    private static final int TAB_FOCUSED_BORDER_ALPHA_DURATION_MS = 200;
-    private static final int TAB_FOCUSED_TOOLBAR_ALPHA_DURATION_MS = 250;
-    private static final int TAB_FOCUSED_Y_STACK_DURATION_MS = 200;
-    private static final int TAB_FOCUSED_MAX_DELAY_MS = 100;
-
-    private static final int VIEW_MORE_ANIMATION_DURATION_MS = 400;
-    private static final int VIEW_MORE_MIN_SIZE = 200;
-    private static final float VIEW_MORE_SIZE_RATIO = 0.75f;
-
-    private static final int REACH_TOP_ANIMATION_DURATION_MS = 400;
-
-    private static final int UNDISCARD_ANIMATION_DURATION_MS = 150;
-
-    private static final int TAB_OPENED_ANIMATION_DURATION_MS = 300;
-
-    private static final int DISCARD_ANIMATION_DURATION_MS = 150;
-
-    private static final int TAB_REORDER_DURATION_MS = 500;
-    private static final int TAB_REORDER_START_SPAN = 400;
-
-    private static final int START_PINCH_ANIMATION_DURATION_MS = 75;
-
-    private static final int FULL_ROLL_ANIMATION_DURATION_MS = 1000;
-
-    private final float mWidth;
-    private final float mHeight;
-    private final float mTopBrowserControlsHeight;
-    private final float mBorderTopHeight;
-    private final float mBorderTopOpaqueHeight;
-    private final float mBorderLeftWidth;
-    private final Stack mStack;
-    private final @Orientation int mOrientation;
-
-    /**
-     * Protected constructor.
-     *
-     * @param stack                       The stack using the animations provided by this class.
-     * @param width                       The width of the layout in dp.
-     * @param height                      The height of the layout in dp.
-     * @param heightMinusBrowserControls  The height of the layout minus the browser controls in dp.
-     * @param borderFramePaddingTop       The top padding of the border frame in dp.
-     * @param borderFramePaddingTopOpaque The opaque top padding of the border frame in dp.
-     * @param borderFramePaddingLeft      The left padding of the border frame in dp.
-     */
-    protected StackAnimation(Stack stack, float width, float height, float topBrowserControlsHeight,
-            float borderFramePaddingTop, float borderFramePaddingTopOpaque,
-            float borderFramePaddingLeft, @Orientation int orientation) {
-        mStack = stack;
-        mWidth = width;
-        mHeight = height;
-        mTopBrowserControlsHeight = topBrowserControlsHeight;
-        mOrientation = orientation;
-
-        mBorderTopHeight = borderFramePaddingTop;
-        mBorderTopOpaqueHeight = borderFramePaddingTopOpaque;
-        mBorderLeftWidth = borderFramePaddingLeft;
-    }
-
-    /**
-     * This is a wrapper for a {@link AnimatorSet} that plays a set of {@link CompositorAnimator}s
-     * at the same time, and it has the ability to cancel some {@link CompositorAnimator} animations
-     * as if it is needed.
-     */
-    class StackAnimatorSet {
-        private final ArrayList<Animator> mAnimationList = new ArrayList<>();
-        private final AnimatorSet mAnimatorSet = new AnimatorSet();
-        private final ArrayList<Animator> mCancelableAnimators = new ArrayList<>();
-        private final CompositorAnimationHandler mHandler;
-
-        StackAnimatorSet(CompositorAnimationHandler handler) {
-            mHandler = handler;
-        }
-
-        <T> boolean isPropertyCancelable(FloatProperty<T> property) {
-            return property == StackTab.SCROLL_OFFSET;
-        }
-
-        /**
-         * Helper method to create and add new {@link CompositorAnimator} to the set.
-         * @param target        Target associated with animated property.
-         * @param property      The property being animated.
-         * @param startValue    The starting value of the animation.
-         * @param endValue      The ending value of the animation.
-         * @param durationMs    The duration of the animation.
-         * @param startTimeMs   The start time.
-         * @param interpolator  The time interpolator for the animation. If it is null, will use the
-         *                      Interpolators.DECELERATE_INTERPOLATOR.
-         */
-        <T> void addToAnimationWithDelay(final T target, final FloatProperty<T> property,
-                float startValue, float endValue, long durationMs, long startTimeMs,
-                TimeInterpolator interpolator) {
-            CompositorAnimator compositorAnimator;
-
-            if (interpolator == null) {
-                compositorAnimator = CompositorAnimator.ofFloatProperty(
-                        mHandler, target, property, startValue, endValue, durationMs);
-            } else {
-                compositorAnimator = CompositorAnimator.ofFloatProperty(
-                        mHandler, target, property, startValue, endValue, durationMs, interpolator);
-            }
-            compositorAnimator.setStartDelay(startTimeMs);
-
-            mAnimationList.add(compositorAnimator);
-
-            if (isPropertyCancelable(property)) mCancelableAnimators.add(compositorAnimator);
-        }
-
-        <T> void addToAnimation(final T target, final FloatProperty<T> property, float startValue,
-                float endValue, long durationMs, TimeInterpolator interpolator) {
-            addToAnimationWithDelay(
-                    target, property, startValue, endValue, durationMs, 0, interpolator);
-        }
-
-        void addToAnimationWithDelay(final PropertyModel model,
-                PropertyModel.WritableFloatPropertyKey key, float startValue, float endValue,
-                long durationMs, long startTimeMs) {
-            CompositorAnimator compositorAnimator = CompositorAnimator.ofWritableFloatPropertyKey(
-                    mHandler, model, key, startValue, endValue, durationMs);
-            compositorAnimator.setStartDelay(startTimeMs);
-
-            mAnimationList.add(compositorAnimator);
-        }
-
-        void addToAnimation(final PropertyModel model, PropertyModel.WritableFloatPropertyKey key,
-                float startValue, float endValue, long durationMs) {
-            addToAnimationWithDelay(model, key, startValue, endValue, durationMs, 0);
-        }
-
-        /**
-         * Starts the {@link AnimatorSet} animation.
-         */
-        void start() {
-            mAnimatorSet.playTogether(mAnimationList);
-            mAnimatorSet.start();
-        }
-
-        /**
-         * Cancels the cancelable animations.
-         */
-        void cancelCancelableAnimators() {
-            for (int i = 0; i < mCancelableAnimators.size(); i++) {
-                mCancelableAnimators.get(i).cancel();
-            }
-        }
-
-        /**
-         * {@see AnimatorSet#isRunning}.
-         * @return Whether the {@link AnimatorSet} is running.
-         */
-        boolean isRunning() {
-            return mAnimatorSet.isRunning();
-        }
-
-        /**
-         * Ends the {@link AnimatorSet} animations.
-         * {@see AnimatorSet#end}.
-         */
-        void end() {
-            mAnimatorSet.end();
-        }
-    }
-
-    /**
-     * The wrapper method responsible for delegating the animations request to the appropriate
-     * helper method.  Not all parameters are used for each request.
-     *
-     * @param type          The type of animation to be created.  This is what
-     *                      determines which helper method is called.
-     * @param stack         The current stack.
-     * @param tabs          The tabs that make up the current stack that will
-     *                      be animated.
-     * @param focusIndex    The index of the tab that is the focus of this animation.
-     * @param sourceIndex   The index of the tab that triggered this animation.
-     * @param spacing       The default spacing between the tabs.
-     * @param discardRange  The range of the discard amount value.
-     * @return              The resulting AnimatorSet that will animate the tabs.
-     */
-    public StackAnimatorSet createAnimatorSetForType(@OverviewAnimationType int type, Stack stack,
-            StackTab[] tabs, int focusIndex, int sourceIndex, int spacing, float discardRange) {
-        if (tabs == null) return null;
-
-        StackAnimatorSet stackAnimatorSet = new StackAnimatorSet(stack.getAnimationHandler());
-
-        switch (type) {
-            case OverviewAnimationType.DISCARD: // Purposeful fall through
-            case OverviewAnimationType.DISCARD_ALL: // Purposeful fall through
-            case OverviewAnimationType.UNDISCARD:
-                createLandscapePortraitUpdateDiscardAnimatorSet(
-                        stackAnimatorSet, stack, tabs, spacing, discardRange);
-                break;
-            case OverviewAnimationType.ENTER_STACK:
-                // Responsible for generating the animations that shows the stack being entered.
-                if (mOrientation == Orientation.LANDSCAPE) {
-                    createLandscapeEnterStackAnimatorSet(
-                            stackAnimatorSet, tabs, focusIndex, spacing);
-                } else {
-                    createPortraitEnterStackAnimatorSet(
-                            stackAnimatorSet, tabs, focusIndex, spacing);
-                }
-                break;
-            case OverviewAnimationType.FULL_ROLL:
-                // Responsible for generating the animations that make all the tabs do a full roll.
-                for (int i = 0; i < tabs.length; ++i) {
-                    LayoutTab layoutTab = tabs[i].getLayoutTab();
-                    // Set the pivot
-                    layoutTab.setTiltX(
-                            layoutTab.getTiltX(), layoutTab.getScaledContentHeight() / 2.0f);
-                    layoutTab.setTiltY(
-                            layoutTab.getTiltY(), layoutTab.getScaledContentWidth() / 2.0f);
-                    // Create the angle animation
-                    addLandscapePortraitTiltScrollAnimation(
-                            stackAnimatorSet, layoutTab, -360.0f, FULL_ROLL_ANIMATION_DURATION_MS);
-                }
-                break;
-            case OverviewAnimationType.NEW_TAB_OPENED:
-                // Responsible for generating the animations that shows a new tab being opened.
-                if (mOrientation == Orientation.LANDSCAPE) return null;
-
-                for (int i = 0; i < tabs.length; i++) {
-                    stackAnimatorSet.addToAnimation(tabs[i], StackTab.SCROLL_OFFSET,
-                            tabs[i].getScrollOffset(), 0.0f, TAB_OPENED_ANIMATION_DURATION_MS,
-                            null);
-                }
-                break;
-            case OverviewAnimationType.REACH_TOP:
-                // Responsible for generating the TabSwitcherAnimation that moves the tabs up so
-                // they reach the to top the screen.
-                float screenTarget = 0.0f;
-                for (int i = 0; i < tabs.length; ++i) {
-                    if (screenTarget
-                            >= getLandscapePortraitScreenPositionInScrollDirection(tabs[i])) {
-                        break;
-                    }
-                    stackAnimatorSet.addToAnimation(tabs[i], StackTab.SCROLL_OFFSET,
-                            tabs[i].getScrollOffset(), mStack.screenToScroll(screenTarget),
-                            REACH_TOP_ANIMATION_DURATION_MS, null);
-                    screenTarget += mOrientation == Orientation.LANDSCAPE
-                            ? tabs[i].getLayoutTab().getScaledContentWidth()
-                            : tabs[i].getLayoutTab().getScaledContentHeight();
-                }
-                break;
-            case OverviewAnimationType.START_PINCH:
-                // Responsible for generating the animations that flattens tabs when a pinch begins.
-                for (int i = 0; i < tabs.length; ++i) {
-                    addLandscapePortraitTiltScrollAnimation(stackAnimatorSet,
-                            tabs[i].getLayoutTab(), 0, START_PINCH_ANIMATION_DURATION_MS);
-                }
-                break;
-            case OverviewAnimationType.TAB_FOCUSED:
-                createLandscapePortraitTabFocusedAnimatorSet(
-                        stackAnimatorSet, tabs, focusIndex, spacing);
-                break;
-            case OverviewAnimationType.VIEW_MORE:
-                // Responsible for generating the animations that Shows more of the selected tab.
-                if (sourceIndex + 1 >= tabs.length) return null;
-
-                float offset = mOrientation == Orientation.LANDSCAPE
-                        ? tabs[sourceIndex].getLayoutTab().getScaledContentWidth()
-                        : tabs[sourceIndex].getLayoutTab().getScaledContentHeight();
-                offset = offset * VIEW_MORE_SIZE_RATIO + tabs[sourceIndex].getScrollOffset()
-                        - tabs[sourceIndex + 1].getScrollOffset();
-                offset = Math.max(VIEW_MORE_MIN_SIZE, offset);
-
-                for (int i = sourceIndex + 1; i < tabs.length; ++i) {
-                    stackAnimatorSet.addToAnimation(tabs[i], StackTab.SCROLL_OFFSET,
-                            tabs[i].getScrollOffset(), tabs[i].getScrollOffset() + offset,
-                            VIEW_MORE_ANIMATION_DURATION_MS, null);
-                }
-                break;
-            default:
-                return null;
-        }
-
-        return stackAnimatorSet;
-    }
-
-    private float getLandscapePortraitScreenPositionInScrollDirection(StackTab tab) {
-        return mOrientation == Orientation.LANDSCAPE ? tab.getLayoutTab().getX()
-                                                     : tab.getLayoutTab().getY();
-    }
-
-    private void addLandscapePortraitTiltScrollAnimation(
-            StackAnimatorSet stackAnimatorSet, LayoutTab tab, float end, int durationMs) {
-        if (mOrientation == Orientation.LANDSCAPE) {
-            stackAnimatorSet.addToAnimation(
-                    tab, LayoutTab.TILT_Y_IN_DEGREES, tab.getTiltY(), end, durationMs);
-        } else {
-            stackAnimatorSet.addToAnimation(
-                    tab, LayoutTab.TILT_X_IN_DEGREES, tab.getTiltX(), end, durationMs);
-        }
-    }
-
-    private void createPortraitEnterStackAnimatorSet(
-            StackAnimatorSet stackAnimatorSet, StackTab[] tabs, int focusIndex, int spacing) {
-        final float initialScrollOffset = mStack.screenToScroll(0);
-
-        float trailingScrollOffset = 0.f;
-        if (focusIndex >= 0 && focusIndex < tabs.length - 1) {
-            final float focusOffset = tabs[focusIndex].getScrollOffset();
-            final float nextOffset = tabs[focusIndex + 1].getScrollOffset();
-            final float topSpacing = focusIndex == 0 ? spacing : 0.f;
-            final float extraSpace = tabs[focusIndex].getLayoutTab().getScaledContentHeight()
-                    * ENTER_STACK_SIZE_RATIO;
-            trailingScrollOffset = Math.max(focusOffset - nextOffset + topSpacing + extraSpace, 0);
-        }
-
-        for (int i = 0; i < tabs.length; ++i) {
-            StackTab tab = tabs[i];
-
-            tab.resetOffset();
-            tab.setScale(mStack.getScaleAmount());
-            tab.setAlpha(1.f);
-            tab.getLayoutTab().setToolbarAlpha(i == focusIndex ? 1.f : 0.f);
-            tab.getLayoutTab().setBorderScale(1.f);
-
-            float scrollOffset = mStack.screenToScroll(i * spacing);
-
-            if (i < focusIndex) {
-                tab.getLayoutTab().setMaxContentHeight(mStack.getMaxTabHeight());
-                stackAnimatorSet.addToAnimation(tab, StackTab.SCROLL_OFFSET, initialScrollOffset,
-                        scrollOffset, ENTER_STACK_ANIMATION_DURATION_MS, null);
-            } else if (i > focusIndex) {
-                tab.getLayoutTab().setMaxContentHeight(mStack.getMaxTabHeight());
-                tab.setScrollOffset(scrollOffset + trailingScrollOffset);
-                stackAnimatorSet.addToAnimation(tab, StackTab.Y_IN_STACK_OFFSET, mHeight, 0,
-                        ENTER_STACK_ANIMATION_DURATION_MS, null);
-            } else { // i == focusIndex
-                tab.setScrollOffset(scrollOffset);
-
-                stackAnimatorSet.addToAnimationWithDelay(tab.getLayoutTab(),
-                        LayoutTab.MAX_CONTENT_HEIGHT,
-                        tab.getLayoutTab().getUnclampedOriginalContentHeight(),
-                        mStack.getMaxTabHeight(), ENTER_STACK_ANIMATION_DURATION_MS,
-                        ENTER_STACK_RESIZE_DELAY_MS);
-                stackAnimatorSet.addToAnimation(tab, StackTab.Y_IN_STACK_INFLUENCE, 0.0f, 1.0f,
-                        ENTER_STACK_BORDER_ALPHA_DURATION_MS, null);
-                stackAnimatorSet.addToAnimation(tab, StackTab.SCALE, 1.0f, mStack.getScaleAmount(),
-                        ENTER_STACK_BORDER_ALPHA_DURATION_MS, null);
-                stackAnimatorSet.addToAnimation(tab.getLayoutTab(), LayoutTab.TOOLBAR_Y_OFFSET, 0.f,
-                        getToolbarOffsetToLineUpWithBorder(), ENTER_STACK_BORDER_ALPHA_DURATION_MS);
-                stackAnimatorSet.addToAnimation(tab.getLayoutTab(), LayoutTab.SIDE_BORDER_SCALE,
-                        0.f, 1.f, ENTER_STACK_BORDER_ALPHA_DURATION_MS);
-
-                stackAnimatorSet.addToAnimationWithDelay(tab.getLayoutTab(),
-                        LayoutTab.TOOLBAR_ALPHA, 1.f, 0.f, ENTER_STACK_BORDER_ALPHA_DURATION_MS,
-                        ENTER_STACK_TOOLBAR_ALPHA_DELAY_MS);
-
-                tab.setYOutOfStack(getStaticTabPosition());
-            }
-        }
-    }
-
-    private void createLandscapeEnterStackAnimatorSet(
-            StackAnimatorSet stackAnimatorSet, StackTab[] tabs, int focusIndex, int spacing) {
-        final float initialScrollOffset = mStack.screenToScroll(0);
-
-        for (int i = 0; i < tabs.length; ++i) {
-            StackTab tab = tabs[i];
-
-            tab.resetOffset();
-            tab.setScale(mStack.getScaleAmount());
-            tab.setAlpha(1.f);
-            tab.getLayoutTab().setToolbarAlpha(i == focusIndex ? 1.f : 0.f);
-            tab.getLayoutTab().setBorderScale(1.f);
-
-            final float scrollOffset = mStack.screenToScroll(i * spacing);
-
-            stackAnimatorSet.addToAnimation(tab.getLayoutTab(), LayoutTab.MAX_CONTENT_HEIGHT,
-                    tab.getLayoutTab().getUnclampedOriginalContentHeight(),
-                    mStack.getMaxTabHeight(), ENTER_STACK_ANIMATION_DURATION_MS);
-            if (i < focusIndex) {
-                stackAnimatorSet.addToAnimation(tab, StackTab.SCROLL_OFFSET, initialScrollOffset,
-                        scrollOffset, ENTER_STACK_ANIMATION_DURATION_MS, null);
-            } else if (i > focusIndex) {
-                tab.setScrollOffset(scrollOffset);
-                stackAnimatorSet.addToAnimation(tab, StackTab.X_IN_STACK_OFFSET,
-                        (mWidth > mHeight && LocalizationUtils.isLayoutRtl()) ? -mWidth : mWidth,
-                        0.0f, ENTER_STACK_ANIMATION_DURATION_MS, null);
-            } else { // i == focusIndex
-                tab.setScrollOffset(scrollOffset);
-
-                stackAnimatorSet.addToAnimation(tab, StackTab.X_IN_STACK_INFLUENCE, 0.0f, 1.0f,
-                        ENTER_STACK_BORDER_ALPHA_DURATION_MS, null);
-                stackAnimatorSet.addToAnimation(tab, StackTab.SCALE, 1.0f, mStack.getScaleAmount(),
-                        ENTER_STACK_BORDER_ALPHA_DURATION_MS, null);
-                stackAnimatorSet.addToAnimation(tab.getLayoutTab(), LayoutTab.TOOLBAR_Y_OFFSET, 0.f,
-                        getToolbarOffsetToLineUpWithBorder(), ENTER_STACK_BORDER_ALPHA_DURATION_MS);
-                stackAnimatorSet.addToAnimation(tab.getLayoutTab(), LayoutTab.SIDE_BORDER_SCALE,
-                        0.f, 1.f, ENTER_STACK_BORDER_ALPHA_DURATION_MS);
-
-                stackAnimatorSet.addToAnimationWithDelay(tab.getLayoutTab(),
-                        LayoutTab.TOOLBAR_ALPHA, 1.f, 0.f, ENTER_STACK_TOOLBAR_ALPHA_DURATION_MS,
-                        ENTER_STACK_TOOLBAR_ALPHA_DELAY_MS);
-            }
-        }
-    }
-
-    /**
-     * Responsible for generating the animations that shows a tab being
-     * focused (the stack is being left).
-     * @param stackAnimatorSet {@link StackAnimatorSet} for created animations.
-     * @param tabs          The tabs that make up the stack.  These are the
-     *                      tabs that will be affected by the TabSwitcherAnimation.
-     * @param focusIndex    The focused index.  In this case, this is the index of
-     *                      the tab clicked and is being brought up to view.
-     * @param spacing       The default spacing between tabs.
-     */
-    private void createLandscapePortraitTabFocusedAnimatorSet(
-            StackAnimatorSet stackAnimatorSet, StackTab[] tabs, int focusIndex, int spacing) {
-        for (int i = 0; i < tabs.length; ++i) {
-            StackTab tab = tabs[i];
-            LayoutTab layoutTab = tab.getLayoutTab();
-
-            addLandscapePortraitTiltScrollAnimation(
-                    stackAnimatorSet, layoutTab, 0.0f, TAB_FOCUSED_ANIMATION_DURATION_MS);
-            stackAnimatorSet.addToAnimation(tab, StackTab.DISCARD_AMOUNT, tab.getDiscardAmount(),
-                    0.0f, TAB_FOCUSED_ANIMATION_DURATION_MS, null);
-
-            if (i < focusIndex) {
-                // Landscape: for tabs left of the focused tab move them left to 0.
-                // Portrait: for tabs above the focused tab move them up to 0.
-                stackAnimatorSet.addToAnimation(tab, StackTab.SCROLL_OFFSET, tab.getScrollOffset(),
-                        mOrientation == Orientation.LANDSCAPE
-                                ? Math.max(0.0f, tab.getScrollOffset() - mWidth - spacing)
-                                : tab.getScrollOffset() - mHeight - spacing,
-                        TAB_FOCUSED_ANIMATION_DURATION_MS, null);
-                continue;
-            } else if (i > focusIndex) {
-                if (mOrientation == Orientation.LANDSCAPE) {
-                    // We also need to animate the X Translation to move them right
-                    // off the screen.
-                    float coveringTabPosition = layoutTab.getX();
-                    float distanceToBorder = LocalizationUtils.isLayoutRtl()
-                            ? coveringTabPosition + layoutTab.getScaledContentWidth()
-                            : mWidth - coveringTabPosition;
-                    float clampedDistanceToBorder = MathUtils.clamp(distanceToBorder, 0, mWidth);
-                    float delay = TAB_FOCUSED_MAX_DELAY_MS * clampedDistanceToBorder / mWidth;
-                    stackAnimatorSet.addToAnimationWithDelay(tab, StackTab.X_IN_STACK_OFFSET,
-                            tab.getXInStackOffset(),
-                            tab.getXInStackOffset()
-                                    + (LocalizationUtils.isLayoutRtl() ? -mWidth : mWidth),
-                            (TAB_FOCUSED_ANIMATION_DURATION_MS - (long) delay), (long) delay, null);
-                } else { // mOrientation == Orientation.PORTRAIT
-                    // We also need to animate the Y Translation to move them down
-                    // off the screen.
-                    float coveringTabPosition = layoutTab.getY();
-                    float distanceToBorder =
-                            MathUtils.clamp(mHeight - coveringTabPosition, 0, mHeight);
-                    float delay = TAB_FOCUSED_MAX_DELAY_MS * distanceToBorder / mHeight;
-                    stackAnimatorSet.addToAnimationWithDelay(tab, StackTab.Y_IN_STACK_OFFSET,
-                            tab.getYInStackOffset(), tab.getYInStackOffset() + mHeight,
-                            (TAB_FOCUSED_ANIMATION_DURATION_MS - (long) delay), (long) delay, null);
-                }
-                continue;
-            }
-
-            // This is the focused tab.  We need to scale it back to
-            // 1.0f, move it to the top of the screen, and animate the
-            // X Translation (for Landscape) / Y Translation (for Portrait) so that it looks like it
-            // is zooming into the full screen view.
-            //
-            // In Landscape we additionally move the card to the top left and extend it out so it
-            // becomes a full card.
-            tab.setXOutOfStack(0);
-            tab.setYOutOfStack(0.0f);
-            layoutTab.setBorderScale(1.f);
-
-            if (mOrientation == Orientation.LANDSCAPE) {
-                stackAnimatorSet.addToAnimation(tab, StackTab.X_IN_STACK_INFLUENCE,
-                        tab.getXInStackInfluence(), 0.0f, TAB_FOCUSED_ANIMATION_DURATION_MS, null);
-                stackAnimatorSet.addToAnimation(tab, StackTab.SCROLL_OFFSET, tab.getScrollOffset(),
-                        mStack.screenToScroll(0), TAB_FOCUSED_ANIMATION_DURATION_MS, null);
-            } else { // mOrientation == Orientation.PORTRAIT
-                stackAnimatorSet.addToAnimation(tab, StackTab.SCROLL_OFFSET, tab.getScrollOffset(),
-                        Math.max(0.0f, tab.getScrollOffset() - mWidth - spacing),
-                        TAB_FOCUSED_ANIMATION_DURATION_MS, null);
-            }
-
-            stackAnimatorSet.addToAnimation(tab, StackTab.SCALE, tab.getScale(), 1.0f,
-                    TAB_FOCUSED_ANIMATION_DURATION_MS, null);
-            stackAnimatorSet.addToAnimation(tab, StackTab.Y_IN_STACK_INFLUENCE,
-                    tab.getYInStackInfluence(), 0.0f, TAB_FOCUSED_Y_STACK_DURATION_MS, null);
-            stackAnimatorSet.addToAnimation(tab.getLayoutTab(), LayoutTab.MAX_CONTENT_HEIGHT,
-                    tab.getLayoutTab().getMaxContentHeight(),
-                    tab.getLayoutTab().getUnclampedOriginalContentHeight(),
-                    TAB_FOCUSED_ANIMATION_DURATION_MS);
-
-            tab.setYOutOfStack(getStaticTabPosition());
-
-            if (layoutTab.shouldStall()) {
-                stackAnimatorSet.addToAnimation(layoutTab, LayoutTab.SATURATION, 1.0f, 0.0f,
-                        TAB_FOCUSED_BORDER_ALPHA_DURATION_MS);
-            }
-            stackAnimatorSet.addToAnimation(tab.getLayoutTab(), LayoutTab.TOOLBAR_ALPHA,
-                    layoutTab.getToolbarAlpha(), 1.f, TAB_FOCUSED_TOOLBAR_ALPHA_DURATION_MS);
-            stackAnimatorSet.addToAnimation(tab.getLayoutTab(), LayoutTab.TOOLBAR_Y_OFFSET,
-                    getToolbarOffsetToLineUpWithBorder(), 0.f,
-                    TAB_FOCUSED_TOOLBAR_ALPHA_DURATION_MS);
-            stackAnimatorSet.addToAnimation(tab.getLayoutTab(), LayoutTab.SIDE_BORDER_SCALE, 1.f,
-                    0.f, TAB_FOCUSED_TOOLBAR_ALPHA_DURATION_MS);
-        }
-    }
-
-    /**
-     * Responsible for generating the animations that moves the tabs back in from
-     * discard attempt or commit the current discard (if any). It also re-even the tabs
-     * if one of then is removed.
-     * @param stackAnimatorSet {@link StackAnimatorSet} for created animations.
-     * @param stack         Stack.
-     * @param tabs          The tabs that make up the stack. These are the
-     *                      tabs that will be affected by the TabSwitcherAnimation.
-     * @param spacing       The default spacing between tabs.
-     * @param discardRange  The maximum value the discard amount.
-     */
-    private void createLandscapePortraitUpdateDiscardAnimatorSet(StackAnimatorSet stackAnimatorSet,
-            Stack stack, StackTab[] tabs, int spacing, float discardRange) {
-        int dyingTabsCount = 0;
-        int firstDyingTabIndex = -1;
-        float firstDyingTabOffset = 0;
-        for (int i = 0; i < tabs.length; ++i) {
-            addLandscapePortraitTiltScrollAnimation(stackAnimatorSet, tabs[i].getLayoutTab(), 0.0f,
-                    UNDISCARD_ANIMATION_DURATION_MS);
-
-            if (tabs[i].isDying()) {
-                dyingTabsCount++;
-                if (dyingTabsCount == 1) {
-                    firstDyingTabIndex = i;
-                    firstDyingTabOffset =
-                            getLandscapePortraitScreenPositionInScrollDirection(tabs[i]);
-                }
-            }
-        }
-
-        float screenSizeInScrollDirection =
-                mOrientation == Orientation.LANDSCAPE ? mWidth : mHeight;
-
-        // This is used to determine the discard direction when user just clicks X to close a
-        // tab. On portrait, positive direction (x) is right hand side (on clicking the close
-        // button, discard the tab to the right on LTR, to the left on RTL). On landscape,
-        // positive direction (y) is towards bottom.
-        boolean defaultDiscardDirectionPositive =
-                mOrientation == Orientation.LANDSCAPE ? true : !LocalizationUtils.isLayoutRtl();
-
-        int newIndex = 0;
-        for (int i = 0; i < tabs.length; ++i) {
-            StackTab tab = tabs[i];
-            // If the non-overlapping horizontal tab switcher is enabled, we shift all the
-            // tabs over simultaneously. Otherwise we stagger the animation start times to
-            // create a ripple effect.
-            long startTime = (long) Math.max(0,
-                    TAB_REORDER_START_SPAN / screenSizeInScrollDirection
-                            * (getLandscapePortraitScreenPositionInScrollDirection(tab)
-                                    - firstDyingTabOffset));
-            if (tab.isDying()) {
-                float discard = tab.getDiscardAmount();
-                if (discard == 0.0f) discard = defaultDiscardDirectionPositive ? 0.0f : -0.0f;
-                float s = Math.copySign(1.0f, discard);
-                long duration = (long) (DISCARD_ANIMATION_DURATION_MS
-                        * (1.0f - Math.abs(discard / discardRange)));
-
-                stackAnimatorSet.addToAnimation(tab, StackTab.DISCARD_AMOUNT, discard,
-                        discardRange * s, duration, BakedBezierInterpolator.FADE_OUT_CURVE);
-            } else {
-                if (tab.getDiscardAmount() != 0.f) {
-                    stackAnimatorSet.addToAnimation(tab, StackTab.DISCARD_AMOUNT,
-                            tab.getDiscardAmount(), 0.0f, UNDISCARD_ANIMATION_DURATION_MS, null);
-                }
-                stackAnimatorSet.addToAnimation(tab, StackTab.SCALE, tab.getScale(),
-                        mStack.getScaleAmount(), DISCARD_ANIMATION_DURATION_MS, null);
-
-                stackAnimatorSet.addToAnimation(tab.getLayoutTab(), LayoutTab.MAX_CONTENT_HEIGHT,
-                        tab.getLayoutTab().getMaxContentHeight(), mStack.getMaxTabHeight(),
-                        DISCARD_ANIMATION_DURATION_MS);
-
-                float newScrollOffset = mStack.screenToScroll(spacing * newIndex);
-
-                // If the tab is not dying we want to readjust it's position
-                // based on the new spacing requirements.  For a fully discarded tab, just
-                // put it in the right place.
-                if (tab.getDiscardAmount() >= discardRange) {
-                    tab.setScrollOffset(newScrollOffset);
-                    tab.setScale(mStack.getScaleAmount());
-                } else {
-                    float start = tab.getScrollOffset();
-                    if (start != newScrollOffset) {
-                        stackAnimatorSet.addToAnimation(tab, StackTab.SCROLL_OFFSET, start,
-                                newScrollOffset, TAB_REORDER_DURATION_MS, null);
-                    }
-                }
-                newIndex++;
-            }
-        }
-    }
-
-    /**
-     * @return The offset for the toolbar to line the top up with the opaque component of
-     *         the border.
-     */
-    private float getToolbarOffsetToLineUpWithBorder() {
-        return mTopBrowserControlsHeight - mBorderTopOpaqueHeight;
-    }
-
-    /**
-     * @return The position of the static tab when entering or exiting the tab switcher.
-     */
-    private float getStaticTabPosition() {
-        return mTopBrowserControlsHeight - mBorderTopHeight;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackTab.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackTab.java
deleted file mode 100644
index d85bfae6..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackTab.java
+++ /dev/null
@@ -1,523 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.compositor.layouts.phone.stack;
-
-import android.content.Context;
-import android.content.res.Resources;
-
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.compositor.layouts.Layout.Orientation;
-import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
-import org.chromium.chrome.browser.layouts.animation.FloatProperty;
-
-/**
- * StackTab is used to keep track of a thumbnail's bitmap and position and to
- * draw itself onto the GL canvas at the desired Y Offset.
- * @VisibleForTesting
- */
-public class StackTab {
-    private static final float ALPHA_THRESHOLD = 1.0f / 255.0f;
-    // Cached values from values/dimens.xml
-    public static float sStackedTabVisibleSize; // stacked_tab_visible_size
-    public static float sStackBufferWidth; // stack_buffer_width
-    public static float sStackBufferHeight; // stack_buffer_height
-
-    // Positioner selector
-    private float mXInStackInfluence = 1.0f;
-    private float mYInStackInfluence = 1.0f;
-
-    // In stack positioner
-    private float mScrollOffset;
-    private float mXInStackOffset;
-    private float mYInStackOffset;
-
-    // Out of stack positioner
-    private float mXOutOfStack;
-    private float mYOutOfStack;
-
-    // Values that get animated
-    private float mAlpha = 1.0f;
-    private float mScale = 1.0f;
-    private float mDiscardAmount; // This might alter position, rotation and alpha
-
-    // Discard states
-    private float mDiscardOriginX;
-    private float mDiscardOriginY;
-    private boolean mDiscardFromClick;
-
-    // The index of the tab in the stack
-    private int mIndex;
-
-    // True if the tab is currently being removed (while animating).
-    protected boolean mDying;
-
-    // The visibility sorting value is used to determine the importance of the tab for
-    // texture allocation. It is computed from the area and its position in the stack.
-    // Larger values will have more priority for acquiring texture. Negative values "often"
-    // means that the tab is not visible at all (but there are no guaranty and it's fine).
-    private float mCachedVisibleArea; // Intermediate value
-    private float mCachedIndexDistance; // Intermediate value
-    private float mCacheStackVisibility = 1.0f; // Intermediate value
-    private long mVisiblitySortingValue; // Sorting value based on visible area.
-    private int mOrderSortingValue; // Sorting value based on distance to selection.
-
-    private LayoutTab mLayoutTab;
-
-    public static final FloatProperty<StackTab> DISCARD_AMOUNT =
-            new FloatProperty<StackTab>("DISCARD_AMOUNT") {
-                @Override
-                public void setValue(StackTab layoutTab, float v) {
-                    layoutTab.setDiscardAmount(v);
-                }
-
-                @Override
-                public Float get(StackTab layoutTab) {
-                    return layoutTab.getDiscardAmount();
-                }
-            };
-
-    public static final FloatProperty<StackTab> SCALE = new FloatProperty<StackTab>("SCALE") {
-        @Override
-        public void setValue(StackTab layoutTab, float v) {
-            layoutTab.setScale(v);
-        }
-
-        @Override
-        public Float get(StackTab layoutTab) {
-            return layoutTab.getScale();
-        }
-    };
-
-    public static final FloatProperty<StackTab> SCROLL_OFFSET =
-            new FloatProperty<StackTab>("SCROLL_OFFSET") {
-                @Override
-                public void setValue(StackTab layoutTab, float v) {
-                    layoutTab.setScrollOffset(v);
-                }
-
-                @Override
-                public Float get(StackTab layoutTab) {
-                    return layoutTab.getScrollOffset();
-                }
-            };
-
-    public static final FloatProperty<StackTab> X_IN_STACK_INFLUENCE =
-            new FloatProperty<StackTab>("X_IN_STACK_INFLUENCE") {
-                @Override
-                public void setValue(StackTab layoutTab, float v) {
-                    layoutTab.setXInStackInfluence(v);
-                }
-
-                @Override
-                public Float get(StackTab layoutTab) {
-                    return layoutTab.getXInStackInfluence();
-                }
-            };
-
-    public static final FloatProperty<StackTab> X_IN_STACK_OFFSET =
-            new FloatProperty<StackTab>("X_IN_STACK_OFFSET") {
-                @Override
-                public void setValue(StackTab layoutTab, float v) {
-                    layoutTab.setXInStackOffset(v);
-                }
-
-                @Override
-                public Float get(StackTab layoutTab) {
-                    return layoutTab.getXInStackOffset();
-                }
-            };
-
-    public static final FloatProperty<StackTab> Y_IN_STACK_INFLUENCE =
-            new FloatProperty<StackTab>("Y_IN_STACK_INFLUENCE") {
-                @Override
-                public void setValue(StackTab layoutTab, float v) {
-                    layoutTab.setYInStackInfluence(v);
-                }
-
-                @Override
-                public Float get(StackTab layoutTab) {
-                    return layoutTab.getYInStackInfluence();
-                }
-            };
-
-    public static final FloatProperty<StackTab> Y_IN_STACK_OFFSET =
-            new FloatProperty<StackTab>("Y_IN_STACK_OFFSET") {
-                @Override
-                public void setValue(StackTab layoutTab, float v) {
-                    layoutTab.setYInStackOffset(v);
-                }
-
-                @Override
-                public Float get(StackTab layoutTab) {
-                    return layoutTab.getYInStackOffset();
-                }
-            };
-
-    /**
-     * @param tab The tab this instance is supposed to draw.
-     */
-    public StackTab(LayoutTab tab) {
-        mLayoutTab = tab;
-    }
-
-    /**
-     * @param index The new index in the stack layout.
-     */
-    public void setNewIndex(int index) {
-        mIndex = index;
-    }
-
-    /**
-     * @return The index in the stack layout.
-     */
-    public int getIndex() {
-        return mIndex;
-    }
-
-    /**
-     * @return The {@link LayoutTab} this instance is supposed to draw.
-     */
-    public LayoutTab getLayoutTab() {
-        return mLayoutTab;
-    }
-
-    /**
-     * Set the {@link LayoutTab} this instance is supposed to draw.
-     */
-    public void setLayoutTab(LayoutTab tab) {
-        mLayoutTab = tab;
-    }
-
-    /**
-     * @return The id of the tab, same as the id from the Tab in TabModel.
-     */
-    public int getId() {
-        return mLayoutTab.getId();
-    }
-
-    /**
-     * @param y The vertical translation to be applied after the placement in the stack.
-     */
-    public void setYInStackOffset(float y) {
-        mYInStackOffset = y;
-    }
-
-    /**
-     * @return The vertical translation applied after the placement in the stack.
-     */
-    public float getYInStackOffset() {
-        return mYInStackOffset;
-    }
-
-    /**
-     * @param x The horizontal translation to be applied after the placement in the stack.
-     */
-    public void setXInStackOffset(float x) {
-        mXInStackOffset = x;
-    }
-
-    /**
-     * @return The horizontal translation applied after the placement in the stack.
-     */
-    public float getXInStackOffset() {
-        return mXInStackOffset;
-    }
-
-    /**
-     * @param y The vertical absolute position when out of stack.
-     */
-    public void setYOutOfStack(float y) {
-        mYOutOfStack = y;
-    }
-
-    /**
-     * @return The vertical absolute position when out of stack.
-     */
-    public float getYOutOfStack() {
-        return mYOutOfStack;
-    }
-
-    /**
-     * @param x The horizontal absolute position when out of stack.
-     */
-    public void setXOutOfStack(float x) {
-        mXOutOfStack = x;
-    }
-
-    /**
-     * @return The horizontal absolute position when out of stack.
-     */
-    public float getXOutOfStack() {
-        return mXOutOfStack;
-    }
-
-    /**
-     * Set the transparency value for all of the tab (the contents,
-     * border, etc...).  For components that allow specifying
-     * their own alpha values, it will use the min of these two fields.
-     *
-     * @param f The transparency value for the tab.
-     */
-    public void setAlpha(float f) {
-        mAlpha = f;
-    }
-
-    /**
-     * @return The transparency value for all of the tab components.
-     */
-    public float getAlpha() {
-        return mAlpha;
-    }
-
-    /**
-     * @param xInStackInfluence The horizontal blend value between instack
-     *                          and out of stack pacement [0 .. 1].
-     */
-    public void setXInStackInfluence(float xInStackInfluence) {
-        mXInStackInfluence = xInStackInfluence;
-    }
-
-    /**
-     * @return The horizontal blend value between instack and out of stack pacement [0 .. 1].
-     */
-    public float getXInStackInfluence() {
-        return mXInStackInfluence;
-    }
-
-    /**
-     * @param yInStackInfluence The vertical blend value between instack
-     *                          and out of stack pacement [0 .. 1].
-     */
-    public void setYInStackInfluence(float yInStackInfluence) {
-        mYInStackInfluence = yInStackInfluence;
-    }
-
-    /**
-     * @return The verical blend value between instack and out of stack pacement [0 .. 1].
-     */
-    public float getYInStackInfluence() {
-        return mYInStackInfluence;
-    }
-
-    /**
-     * @param scale The scale to apply to the tab, compared to the parent.
-     */
-    public void setScale(float scale) {
-        mScale = scale;
-    }
-
-    /**
-     * @return The scale to apply to the tab, compared to the parent.
-     */
-    public float getScale() {
-        return mScale;
-    }
-
-    /**
-     * @param offset The offset of the tab along the scrolling direction in scroll space.
-     */
-    public void setScrollOffset(float offset) {
-        mScrollOffset = offset;
-    }
-
-    /**
-     * @return The offset of the tab along the scrolling direction in scroll space.
-     */
-    public float getScrollOffset() {
-        return mScrollOffset;
-    }
-
-    /**
-     * @param amount The amount of discard displacement. 0 is no discard. Negative is discard
-     *               on the left. Positive is discard on the right.
-     */
-    public void setDiscardAmount(float amount) {
-        mDiscardAmount = amount;
-    }
-
-    /**
-     * @param deltaAmount The amount of delta discard to be added to the current discard amount.
-     */
-    public void addToDiscardAmount(float deltaAmount) {
-        mDiscardAmount += deltaAmount;
-    }
-
-    /**
-     * @return The amount of discard displacement. 0 is no discard. Negative is discard
-     *         on the left. Positive is discard on the right.
-     */
-    public float getDiscardAmount() {
-        return mDiscardAmount;
-    }
-
-    /**
-     * @param x The x coordinate in tab space of where the discard transforms should originate.
-     */
-    public void setDiscardOriginX(float x) {
-        mDiscardOriginX = x;
-    }
-
-    /**
-     * @param y The y coordinate in tab space of where the discard transforms should originate.
-     */
-    public void setDiscardOriginY(float y) {
-        mDiscardOriginY = y;
-    }
-
-    /**
-     * @return The x coordinate in tab space of where the discard transforms should originate.
-     */
-    public float getDiscardOriginX() {
-        return mDiscardOriginX;
-    }
-
-    /**
-     * @return The y coordinate in tab space of where the discard transforms should originate.
-     */
-    public float getDiscardOriginY() {
-        return mDiscardOriginY;
-    }
-
-    /**
-     * @param fromClick Whether or not this discard was from a click event.
-     */
-    public void setDiscardFromClick(boolean fromClick) {
-        mDiscardFromClick = fromClick;
-    }
-
-    /**
-     * @return Whether or not this discard was from a click event.
-     */
-    public boolean getDiscardFromClick() {
-        return mDiscardFromClick;
-    }
-
-    /**
-     * @param dying True if the Tab/ContentView will be destroyed, and we are still animating its
-     *              visible representation.
-     */
-    public void setDying(boolean dying) {
-        mDying = dying;
-    }
-
-    /**
-     * @return True if the Tab/ContentView is destroyed, but we are still animating its
-     *         visible representation.
-     */
-    public boolean isDying() {
-        return mDying;
-    }
-
-    /**
-     * @param orientation The orientation to choose to get the size.
-     * @return            The size of the content along the provided orientation.
-     */
-    public float getSizeInScrollDirection(@Orientation int orientation) {
-        if (orientation == Orientation.PORTRAIT) {
-            return mLayoutTab.getScaledContentHeight();
-        } else {
-            return mLayoutTab.getScaledContentWidth();
-        }
-    }
-
-    /**
-     * Helper function that gather the static constants from values/dimens.xml.
-     * @param context The Android Context.
-     */
-    public static void resetDimensionConstants(Context context) {
-        Resources res = context.getResources();
-        final float pxToDp = 1.0f / res.getDisplayMetrics().density;
-        sStackedTabVisibleSize =
-                res.getDimensionPixelOffset(R.dimen.stacked_tab_visible_size) * pxToDp;
-        sStackBufferWidth = res.getDimensionPixelOffset(R.dimen.stack_buffer_width) * pxToDp;
-        sStackBufferHeight = res.getDimensionPixelOffset(R.dimen.stack_buffer_height) * pxToDp;
-    }
-
-    /**
-     * Reset the offset to factory default.
-     */
-    public void resetOffset() {
-        mXInStackInfluence = 1.0f;
-        mYInStackInfluence = 1.0f;
-        mScrollOffset = 0.0f;
-        mXInStackOffset = 0.0f;
-        mYInStackOffset = 0.0f;
-        mXOutOfStack = 0.0f;
-        mYOutOfStack = 0.0f;
-        mDiscardOriginX = 0.f;
-        mDiscardOriginY = 0.f;
-        mDiscardFromClick = false;
-    }
-
-    /**
-     * Updates the cached visible area value to be used to sort tabs by visibility.
-     * @param referenceIndex The index that has the highest priority.
-     */
-    public void updateVisiblityValue(int referenceIndex) {
-        mCachedVisibleArea = computeVisibleArea();
-        mCachedIndexDistance = Math.abs(mIndex - referenceIndex);
-        mOrderSortingValue = computeOrderSortingValue(mCachedIndexDistance, mCacheStackVisibility);
-        mVisiblitySortingValue = computeVisibilitySortingValue(
-                mCachedVisibleArea, mOrderSortingValue, mCacheStackVisibility);
-    }
-
-    /**
-     * @return The theoretical number of visible pixels. 0 if invisible.
-     */
-    private float computeVisibleArea() {
-        return (mLayoutTab.get(LayoutTab.IS_VISIBLE)
-                                       && mLayoutTab.get(LayoutTab.ALPHA) > ALPHA_THRESHOLD
-                               ? 1.0f
-                               : 0.0f)
-                * mLayoutTab.getFinalContentWidth() * mLayoutTab.getFinalContentHeight();
-    }
-
-    /**
-     * Updates the cached visible area value to be used to sort tabs by visibility.
-     * @param stackVisibility   Multiplier that represents how much the stack fills the screen.
-     */
-    public void updateStackVisiblityValue(float stackVisibility) {
-        mCacheStackVisibility = stackVisibility;
-        mOrderSortingValue = computeOrderSortingValue(mCachedIndexDistance, mCacheStackVisibility);
-        mVisiblitySortingValue = computeVisibilitySortingValue(
-                mCachedVisibleArea, mOrderSortingValue, mCacheStackVisibility);
-    }
-
-    /**
-     * Computes the visibility sorting value based on the tab visible area, its distance to the
-     * central index and the overall visibility of the stack.
-     * The '-index' index factor need to be smaller for stack that have small visibility.
-     * Multiplying by a small stackVisibility makes it bigger (because it is negative), hence the
-     * division. To avoid dividing by 0 it need to be offset a bit. 0.1f is the 'a bit' part of
-     * the explanation.
-     */
-    private static long computeVisibilitySortingValue(
-            float area, float orderSortingValue, float stackVisibility) {
-        return (long) (area * stackVisibility - orderSortingValue);
-    }
-
-    /**
-     * @return The cached visible sorting value. Call updateCachedVisibleArea to update it.
-     */
-    public long getVisiblitySortingValue() {
-        return mVisiblitySortingValue;
-    }
-
-    /**
-     * Computes the ordering value only based on the distance of the tab to the center one.
-     * Low values have higher priority.
-     */
-    private static int computeOrderSortingValue(float indexDistance, float stackVisibility) {
-        return (int) ((indexDistance + 1) / (0.1f + 0.9f * stackVisibility));
-    }
-
-    /**
-     * @return The cached order sorting value. Used to sort based on the tab ordering rather than
-     *         visible area.
-     */
-    public int getOrderSortingValue() {
-        return mOrderSortingValue;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackViewAnimation.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackViewAnimation.java
deleted file mode 100644
index ebfc23838..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/StackViewAnimation.java
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.compositor.layouts.phone.stack;
-
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
-import android.animation.PropertyValuesHolder;
-import android.content.res.Resources;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.FrameLayout;
-
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation.OverviewAnimationType;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tabmodel.TabList;
-import org.chromium.chrome.browser.theme.ThemeUtils;
-import org.chromium.components.browser_ui.widget.animation.Interpolators;
-
-/**
- * A factory that builds Android view animations for the tab stack.
- */
-public class StackViewAnimation {
-    private static final int TAB_OPENED_BG_ANIMATION_DURATION = 150;
-    private static final int TAB_OPENED_VIEW_ANIMATION_DURATION = 350;
-
-    private final int mTranslationYStart;
-
-    /**
-     * Constructor.
-     *
-     * @param resources Android {@link Resources} used to retrieve dimensions.
-     */
-    public StackViewAnimation(Resources resources) {
-        mTranslationYStart =
-                resources.getDimensionPixelSize(R.dimen.open_new_tab_animation_y_translation);
-    }
-
-    /**
-     * The wrapper method responsible for delegating animation requests to the appropriate helper
-     * method.
-     * @param type       The type of animation to be created.  This is what determines which helper
-     *                   method is called.
-     * @param tabs       The tabs that make up the current stack.
-     * @param container  The {@link ViewGroup} that {@link View}s can be added to/removed from.
-     * @param list       The {@link TabList} that this animation will influence.
-     * @param focusIndex The index of the tab that is the focus of this animation.
-     * @return           The resulting {@link Animator} that will animate the Android views.
-     */
-    public Animator createAnimatorForType(@OverviewAnimationType int type, StackTab[] tabs,
-            ViewGroup container, TabList list, int focusIndex) {
-        Animator animator = null;
-
-        if (list != null && type == OverviewAnimationType.NEW_TAB_OPENED) {
-            animator = createNewTabOpenedAnimator(tabs, container, list, focusIndex);
-        }
-
-        return animator;
-    }
-
-    private Animator createNewTabOpenedAnimator(
-            StackTab[] tabs, ViewGroup container, TabList list, int focusIndex) {
-        Tab tab = list.getTabAt(focusIndex);
-        if (tab == null || !tab.isNativePage()) return null;
-
-        View view = tab.getView();
-        if (view == null) return null;
-
-        // Set up the view hierarchy
-        if (view.getParent() != null) ((ViewGroup) view.getParent()).removeView(view);
-        ViewGroup bgView = new FrameLayout(view.getContext());
-        bgView.setBackgroundColor(ThemeUtils.getBackgroundColor(tab));
-        bgView.addView(view);
-        container.addView(
-                bgView, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
-
-        // Update any compositor state that needs to change
-        if (tabs != null && focusIndex >= 0 && focusIndex < tabs.length) {
-            tabs[focusIndex].setAlpha(0.f);
-        }
-
-        // Build the view animations
-        PropertyValuesHolder viewAlpha = PropertyValuesHolder.ofFloat(View.ALPHA, 0.f, 1.f);
-        ObjectAnimator viewAlphaAnimator = ObjectAnimator.ofPropertyValuesHolder(view, viewAlpha);
-        viewAlphaAnimator.setDuration(TAB_OPENED_VIEW_ANIMATION_DURATION);
-        viewAlphaAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR);
-
-        PropertyValuesHolder yTranslation =
-                PropertyValuesHolder.ofFloat(View.TRANSLATION_Y, mTranslationYStart, 0.f);
-        ObjectAnimator viewYTranslationAnimator =
-                ObjectAnimator.ofPropertyValuesHolder(view, yTranslation);
-        viewYTranslationAnimator.setDuration(TAB_OPENED_VIEW_ANIMATION_DURATION);
-        viewYTranslationAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR);
-
-        PropertyValuesHolder bgAlpha = PropertyValuesHolder.ofFloat(View.ALPHA, 0.f, 1.f);
-        ObjectAnimator bgAlphaAnimator = ObjectAnimator.ofPropertyValuesHolder(bgView, bgAlpha);
-        bgAlphaAnimator.setDuration(TAB_OPENED_BG_ANIMATION_DURATION);
-        bgAlphaAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN_INTERPOLATOR);
-
-        AnimatorSet set = new AnimatorSet();
-        set.playTogether(viewAlphaAnimator, viewYTranslationAnimator, bgAlphaAnimator);
-
-        return set;
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java
index ea2b59b..1e2fff8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java
@@ -21,7 +21,7 @@
 import org.chromium.base.ApiCompatibilityUtils;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.KeyboardShortcuts;
 import org.chromium.chrome.browser.app.ChromeActivity;
 import org.chromium.chrome.browser.app.tabmodel.TabModelOrchestrator;
@@ -166,7 +166,7 @@
                 mIntentDataProvider, getStartupTabPreloader(), mNightModeStateController,
                 intentIgnoringCriterion, getTopUiThemeColorProvider());
         BaseCustomTabActivityComponent component =
-                ChromeApplication.getComponent().createBaseCustomTabActivityComponent(
+                ChromeApplicationImpl.getComponent().createBaseCustomTabActivityComponent(
                         commonsModule, baseCustomTabsModule);
 
         mDelegateFactory = component.resolveTabDelegateFactory();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
index 9e6b0ee..699508a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java
@@ -52,7 +52,7 @@
 import org.chromium.base.task.TaskTraits;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.AppHooks;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.WarmupManager;
 import org.chromium.chrome.browser.browserservices.PostMessageHandler;
@@ -96,7 +96,7 @@
  * Implementation of the ICustomTabsService interface.
  *
  * Note: This class is meant to be package private, and is public to be
- * accessible from {@link ChromeApplication}.
+ * accessible from {@link ChromeApplicationImpl}.
  */
 @JNINamespace("customtabs")
 public class CustomTabsConnection {
@@ -216,14 +216,14 @@
 
     /**
      * <strong>DO NOT CALL</strong>
-     * Public to be instanciable from {@link ChromeApplication}. This is however
+     * Public to be instanciable from {@link ChromeApplicationImpl}. This is however
      * intended to be private.
      */
     public CustomTabsConnection() {
         super();
         mClientManager = new ClientManager();
         mLogRequests = CommandLine.getInstance().hasSwitch(LOG_SERVICE_REQUESTS);
-        mSessionDataHolder = ChromeApplication.getComponent().resolveSessionDataHolder();
+        mSessionDataHolder = ChromeApplicationImpl.getComponent().resolveSessionDataHolder();
     }
 
     /**
@@ -334,7 +334,7 @@
 
                 // TODO(pshmakov): invert this dependency by moving event dispatching to a separate
                 // class.
-                ChromeApplication.getComponent()
+                ChromeApplicationImpl.getComponent()
                         .resolveCustomTabsFileProcessor()
                         .onSessionDisconnected(session);
             }
@@ -1452,7 +1452,7 @@
     public static void onTrimMemory(int level) {
         if (!hasInstance()) return;
 
-        if (ChromeApplication.isSevereMemorySignal(level)) {
+        if (ChromeApplicationImpl.isSevereMemorySignal(level)) {
             getInstance().mClientManager.cleanupUnusedSessions();
         }
     }
@@ -1607,7 +1607,7 @@
 
     public boolean receiveFile(
             CustomTabsSessionToken sessionToken, Uri uri, int purpose, Bundle extras) {
-        return ChromeApplication.getComponent().resolveCustomTabsFileProcessor().processFile(
+        return ChromeApplicationImpl.getComponent().resolveCustomTabsFileProcessor().processFile(
                 sessionToken, uri, purpose, extras);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/IncognitoCustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/IncognitoCustomTabIntentDataProvider.java
index fcb1d03..8f4d0e61 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/IncognitoCustomTabIntentDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/IncognitoCustomTabIntentDataProvider.java
@@ -25,7 +25,7 @@
 
 import org.chromium.base.IntentUtils;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider;
 import org.chromium.chrome.browser.flags.ActivityType;
@@ -138,7 +138,7 @@
         String sendersPackageName =
                 CustomTabsConnection.getInstance().getClientPackageNameForSession(sessionToken);
         return !TextUtils.isEmpty(sendersPackageName)
-                && ChromeApplication.getComponent().resolveExternalAuthUtils().isGoogleSigned(
+                && ChromeApplicationImpl.getComponent().resolveExternalAuthUtils().isGoogleSigned(
                         sendersPackageName);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dagger.md b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dagger.md
index cd7013be..1db2f573 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dagger.md
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/dagger.md
@@ -95,7 +95,7 @@
 
 ### access a Dagger class from a non-Dagger class
 
-If the class is a singleton, add a suitable *resolve* method to [ChromeAppComponent][4], you can then call `ChromeApplication.getComponent().resolveMyClass()` to get access.
+If the class is a singleton, add a suitable *resolve* method to [ChromeAppComponent][4], you can then call `ChromeApplicationImpl.getComponent().resolveMyClass()` to get access.
 
 If the class is `@ActivityScope`, add a suitable resolve method to [BaseCustomTabActivityComponent][5], and then get the object out of Dagger in `BaseCustomTabActivity#createComponent`.
 You can then fetch the instance off `BaseCustomTabActivity`.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/LegacyDownloadProviderImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/LegacyDownloadProviderImpl.java
index f4a4bbe..d4fd7e9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/LegacyDownloadProviderImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/LegacyDownloadProviderImpl.java
@@ -90,7 +90,7 @@
 
     @Override
     public void onAllDownloadsRetrieved(List<DownloadItem> items, ProfileKey profileKey) {
-        List<Callback<ArrayList<OfflineItem>>> list = mRequestsMap.get(profileKey);
+        List<Callback<ArrayList<OfflineItem>>> list = getRequestList(profileKey);
         if (list.isEmpty()) return;
 
         ArrayList<OfflineItem> offlineItems = new ArrayList<>();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoTabLauncher.java b/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoTabLauncher.java
index 9c5c01f5..502b72f2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoTabLauncher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoTabLauncher.java
@@ -23,7 +23,7 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.task.PostTask;
 import org.chromium.base.task.TaskTraits;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
@@ -120,7 +120,7 @@
         String sendersPackageName =
                 intent.getStringExtra(IncognitoTabLauncher.EXTRA_SENDERS_PACKAGE_NAME);
         return !TextUtils.isEmpty(sendersPackageName)
-                && ChromeApplication.getComponent().resolveExternalAuthUtils().isGoogleSigned(
+                && ChromeApplicationImpl.getComponent().resolveExternalAuthUtils().isGoogleSigned(
                         sendersPackageName);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
index 5de900d..2c979ce 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
@@ -30,7 +30,7 @@
 import org.chromium.chrome.browser.AfterStartupTaskUtils;
 import org.chromium.chrome.browser.AppHooks;
 import org.chromium.chrome.browser.ChromeActivitySessionTracker;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.ChromeBackupAgentImpl;
 import org.chromium.chrome.browser.DefaultBrowserInfo;
 import org.chromium.chrome.browser.DeferredStartupHandler;
@@ -411,8 +411,8 @@
                 () -> MediaViewerUtils.updateMediaLauncherActivityEnabled());
 
         deferredStartupHandler.addDeferredTask(
-                ChromeApplication.getComponent().resolveTwaClearDataDialogRecorder()
-                        ::makeDeferredRecordings);
+                ChromeApplicationImpl.getComponent()
+                        .resolveTwaClearDataDialogRecorder()::makeDeferredRecordings);
         deferredStartupHandler.addDeferredTask(WebApkUma::recordDeferredUma);
 
         deferredStartupHandler.addDeferredTask(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
index 1394338..912ba1d1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
@@ -34,7 +34,7 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.browserservices.TrustedWebActivityClient;
 import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
 import org.chromium.chrome.browser.notifications.channels.SiteChannelsManager;
@@ -845,7 +845,7 @@
 
     private TrustedWebActivityClient getTwaClient() {
         if (mTwaClient == null) {
-            mTwaClient = ChromeApplication.getComponent().resolveTrustedWebActivityClient();
+            mTwaClient = ChromeApplicationImpl.getComponent().resolveTrustedWebActivityClient();
         }
         return mTwaClient;
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderServiceImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderServiceImpl.java
index 336f60a8..e3dfc39 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderServiceImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/DecoderServiceImpl.java
@@ -13,7 +13,7 @@
 import org.chromium.base.annotations.MainDex;
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.task.PostTask;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.base.SplitCompatApplication;
 import org.chromium.components.browser_ui.photo_picker.ImageDecoder;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 
@@ -39,7 +39,7 @@
         // The decoder service relies on PathUtils.
         PostTask.runSynchronously(UiThreadTaskTraits.DEFAULT, () -> {
             PathUtils.setPrivateDataDirectorySuffix(
-                    ChromeApplication.PRIVATE_DATA_DIRECTORY_SUFFIX);
+                    SplitCompatApplication.PRIVATE_DATA_DIRECTORY_SUFFIX);
         });
 
         LibraryLoader.getInstance().ensureInitialized();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/policy/PolicyAuditor.java b/chrome/android/java/src/org/chromium/chrome/browser/policy/PolicyAuditor.java
index 02c9c88a..f08cc2f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/policy/PolicyAuditor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/policy/PolicyAuditor.java
@@ -33,7 +33,7 @@
     }
 
     /**
-     * Make it non-obvious to accidentally instantiate this outside of ChromeApplication.
+     * Make it non-obvious to accidentally instantiate this outside of ChromeApplicationImpl.
      */
     protected PolicyAuditor() {}
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java
index 3c135123..e60e1e8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/TabsTest.java
@@ -13,12 +13,9 @@
 
 import android.content.pm.ActivityInfo;
 import android.graphics.Point;
-import android.os.Build.VERSION_CODES;
-import android.os.Debug;
 import android.os.SystemClock;
 import android.support.test.InstrumentationRegistry;
 import android.util.DisplayMetrics;
-import android.util.Log;
 import android.view.View;
 
 import androidx.test.filters.LargeTest;
@@ -40,7 +37,6 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Criteria;
 import org.chromium.base.test.util.CriteriaHelper;
-import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.FlakyTest;
@@ -49,14 +45,9 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.compositor.layouts.Layout;
 import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChrome;
-import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChromePhone;
 import org.chromium.chrome.browser.compositor.layouts.LayoutManagerImpl;
 import org.chromium.chrome.browser.compositor.layouts.SceneChangeObserver;
 import org.chromium.chrome.browser.compositor.layouts.StaticLayout;
-import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
-import org.chromium.chrome.browser.compositor.layouts.phone.StackLayout;
-import org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack;
-import org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.layouts.animation.CompositorAnimationHandler;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
@@ -71,7 +62,6 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
 import org.chromium.chrome.browser.tabpersistence.TabStateDirectory;
-import org.chromium.chrome.browser.toolbar.top.ToggleTabStackButton;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.ChromeTabUtils;
@@ -80,7 +70,6 @@
 import org.chromium.chrome.test.util.OverviewModeBehaviorWatcher;
 import org.chromium.components.browser_ui.widget.gesture.SwipeGestureListener.ScrollDirection;
 import org.chromium.components.browser_ui.widget.gesture.SwipeGestureListener.SwipeHandler;
-import org.chromium.components.embedder_support.util.UrlConstants;
 import org.chromium.components.javascript_dialogs.JavascriptTabModalDialog;
 import org.chromium.content_public.browser.SelectionPopupController;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
@@ -101,7 +90,6 @@
 import java.io.File;
 import java.util.Locale;
 import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -458,125 +446,6 @@
     }
 
     /**
-     * A Runnable to simulate a click on given coordinates.
-     */
-    public static class SimulateClickOnMainThread implements Runnable {
-        private final LayoutManagerChrome mLayoutManager;
-        private final float mX;
-        private final float mY;
-
-        public SimulateClickOnMainThread(LayoutManagerChrome layoutManager, float x, float y) {
-            mLayoutManager = layoutManager;
-            mX = x;
-            mY = y;
-        }
-
-        @Override
-        public void run() {
-            mLayoutManager.simulateClick(mX, mY);
-        }
-    }
-
-    /**
-     * A Runnable to simulate a swipe with specific coordinates and distance.
-     */
-    public static class SimulateTabSwipeOnMainThread implements Runnable {
-        private final LayoutManagerChrome mLayoutManager;
-        private final float mX;
-        private final float mY;
-        private final float mDeltaX;
-        private final float mDeltaY;
-
-        public SimulateTabSwipeOnMainThread(LayoutManagerChrome layoutManager, float x, float y,
-                float dX, float dY) {
-            mLayoutManager = layoutManager;
-            mX = x;
-            mY = y;
-            mDeltaX = dX;
-            mDeltaY = dY;
-        }
-
-        @Override
-        public void run() {
-            mLayoutManager.simulateDrag(mX, mY, mDeltaX, mDeltaY);
-        }
-    }
-
-    /**
-     * Verify that the provided click position closes a tab.
-     * TODO(yuezhanggg@): The hard-coded coordinates are not a good way to verify the position of
-     * the closing button. Should be replaced by render tests.
-     */
-    private void checkCloseTabAtPosition(final float x, final float y) {
-        ChromeTabbedActivity cta = mActivityTestRule.getActivity();
-
-        int initialTabCount = cta.getCurrentTabModel().getCount();
-        ChromeTabUtils.fullyLoadUrlInNewTab(InstrumentationRegistry.getInstrumentation(), cta,
-                UrlConstants.CHROME_BLANK_URL, false);
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> { cta.getLayoutManager().showOverview(false); });
-
-        Assert.assertTrue("Expected: " + (initialTabCount + 1)
-                        + " tab Got: " + cta.getCurrentTabModel().getCount(),
-                (initialTabCount + 1) == cta.getCurrentTabModel().getCount());
-        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
-        final LayoutManagerChrome layoutManager = updateTabsViewSize();
-        StackLayout layout = (StackLayout) layoutManager.getOverviewLayout();
-        Stack stack = layout.getTabStackAtIndex(0);
-        Assert.assertTrue("Position is not in the active area of the close button",
-                stack.checkCloseHitTestOnLayoutTab(x, y, stack.getTabs()[0].getLayoutTab()));
-        ChromeTabUtils.closeTabWithAction(InstrumentationRegistry.getInstrumentation(), cta,
-                ()
-                        -> InstrumentationRegistry.getInstrumentation().runOnMainSync(
-                                new SimulateClickOnMainThread(layoutManager, x, y)));
-        Assert.assertTrue(
-                "Expected: " + initialTabCount + " tab Got: " + cta.getCurrentTabModel().getCount(),
-                initialTabCount == cta.getCurrentTabModel().getCount());
-    }
-
-    /**
-     * Verify close button works in the TabSwitcher in portrait mode.
-     * This code does not handle properly different screen densities.
-     */
-    @Test
-    @LargeTest
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
-    @Feature({"Android-TabSwitcher"})
-    @DisableIf.Build(sdk_is_greater_than = VERSION_CODES.O_MR1,
-            message = "Very flaky on android-pie-x86-rel https://crbug.com/1135837")
-    public void
-    testTabSwitcherPortraitCloseButton() {
-        mActivityTestRule.getActivity().setRequestedOrientation(
-                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
-        int portraitWidth = Math.min(
-                mActivityTestRule.getActivity().getResources().getDisplayMetrics().widthPixels,
-                mActivityTestRule.getActivity().getResources().getDisplayMetrics().heightPixels);
-        // Hard-coded coordinates of the close button on the top right of the screen.
-        // If the coordinates need to be updated, the easiest is to take a screenshot and measure.
-        // Note that starting from the right of the screen should cover any screen size.
-        checkCloseTabAtPosition(portraitWidth * mPxToDp - 32, 70);
-    }
-
-    /**
-     * Verify close button works in the TabSwitcher in landscape mode.
-     * This code does not handle properly different screen densities.
-     */
-    @Test
-    @LargeTest
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
-    @DisableIf.Build(message = "Flaky on Android P, see https://crbug.com/1164443",
-            sdk_is_greater_than = VERSION_CODES.O_MR1, sdk_is_less_than = VERSION_CODES.Q)
-    @Feature({"Android-TabSwitcher"})
-    public void
-    testTabSwitcherLandscapeCloseButton() {
-        mActivityTestRule.getActivity().setRequestedOrientation(
-                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
-        // Hard-coded coordinates of the close button on the bottom left of the screen.
-        // If the coordinates need to be updated, the easiest is to take a screenshot and measure.
-        checkCloseTabAtPosition(74 * mPxToDp, 216 * mPxToDp);
-    }
-
-    /**
      * Verify that we can open a large number of tabs without running out of
      * memory. This test waits for the NTP to load before opening the next one.
      * This is a LargeTest but because we're doing it "slowly", we need to further scale
@@ -671,18 +540,6 @@
                 startCount + num, mActivityTestRule.getActivity().getCurrentTabModel().getCount());
     }
 
-    class ClickOptionButtonOnMainThread implements Runnable {
-        @Override
-        public void run() {
-            // This is equivalent to clickById(R.id.tab_switcher_button) but does not rely on the
-            // event pipeline.
-            ToggleTabStackButton button =
-                    mActivityTestRule.getActivity().findViewById(R.id.tab_switcher_button);
-            Assert.assertNotNull("Could not find view R.id.tab_switcher_button", button);
-            button.onClick(button);
-        }
-    }
-
     /** Enters the tab switcher without animation.*/
     private void showOverviewWithNoAnimation() {
         ThreadUtils.runOnUiThreadBlocking(
@@ -721,235 +578,6 @@
         return tabCount;
     }
 
-    /**
-     * Verifies that when more than 9 tabs are open only at most 8 are drawn. Basically it verifies
-     * that the tab culling mechanism works properly.
-     */
-    /*
-       @LargeTest
-       @Feature({"Android-TabSwitcher"})
-    */
-    @Test
-    @DisabledTest(message = "crbug.com/156746")
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
-    public void testTabsCulling() {
-        // Open one more tabs than maxTabsDrawn.
-        final int maxTabsDrawn = 8;
-        int tabCount = openTabs(maxTabsDrawn + 1, false);
-        showOverviewWithNoAnimation();
-
-        // Check counts.
-        LayoutManagerChromePhone layoutManager =
-                (LayoutManagerChromePhone) mActivityTestRule.getActivity().getLayoutManager();
-        int drawnCount = layoutManager.getOverviewLayout().getLayoutTabsToRender().length;
-        int drawnExpected = Math.min(tabCount, maxTabsDrawn);
-        Assert.assertEquals("The number of drawn tab is wrong", drawnExpected, drawnCount);
-    }
-
-    /**
-     * Checks the stacked tabs in the stack are visible.
-     */
-    private void checkTabsStacking() {
-        final int count = mActivityTestRule.getActivity().getCurrentTabModel().getCount();
-        Assert.assertEquals(
-                "The number of tab in the stack should match the number of tabs in the model",
-                count, getLayoutTabInStackCount(false));
-
-        Assert.assertTrue("The selected tab should always be visible",
-                stackTabIsVisible(
-                        false, mActivityTestRule.getActivity().getCurrentTabModel().index()));
-        for (int i = 0; i < Stack.MAX_NUMBER_OF_STACKED_TABS_TOP && i < count; i++) {
-            Assert.assertTrue("The stacked tab " + i + " from the top should always be visible",
-                    stackTabIsVisible(false, i));
-        }
-        for (int i = 0; i < Stack.MAX_NUMBER_OF_STACKED_TABS_BOTTOM && i < count; i++) {
-            Assert.assertTrue("The stacked tab " + i + " from the bottom should always be visible",
-                    stackTabIsVisible(false, count - 1 - i));
-        }
-    }
-
-    /**
-     * Verifies that the tab are actually stacking at the bottom and top of the screen.
-     */
-    /**
-     * @LargeTest
-     * @Feature({"Android-TabSwitcher"})
-     */
-    @Test
-    @FlakyTest(message = "crbug.com/170179")
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
-    public void testTabsStacking() {
-        final int count = openTabs(12, false);
-
-        // Selecting the first tab to scroll all the way to the top.
-        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> TabModelUtils.setIndex(
-                                mActivityTestRule.getActivity().getCurrentTabModel(), 0));
-        showOverviewWithNoAnimation();
-        checkTabsStacking();
-
-        // Selecting the last tab to scroll all the way to the bottom.
-        hideOverviewWithNoAnimation();
-        InstrumentationRegistry.getInstrumentation().runOnMainSync(
-                () -> TabModelUtils.setIndex(
-                                mActivityTestRule.getActivity().getCurrentTabModel(), count - 1));
-        showOverviewWithNoAnimation();
-        checkTabsStacking();
-    }
-
-    /**
-     * @return A stable read of allocated size (native + dalvik) after gc.
-     */
-    private long getStableAllocatedSize() {
-        // Measure the equivalent of allocated size native + dalvik in:
-        // adb shell dumpsys meminfo | grep chrome -A 20
-        int maxTries = 8;
-        int tries = 0;
-        long threshold = 512; // bytes
-        long lastAllocatedSize = Long.MAX_VALUE;
-        long currentAllocatedSize = 0;
-        while (tries < maxTries && Math.abs(currentAllocatedSize - lastAllocatedSize) > threshold) {
-            System.gc();
-            try {
-                Thread.sleep(1000 + tries * 500); // Memory measurement is not an exact science...
-                lastAllocatedSize = currentAllocatedSize;
-                currentAllocatedSize = Debug.getNativeHeapAllocatedSize()
-                        + Runtime.getRuntime().totalMemory();
-                //Log.w("MEMORY_MEASURE", "[" + tries + "/" + maxTries + "]" +
-                //        "currentAllocatedSize " + currentAllocatedSize);
-            } catch (InterruptedException e) {
-                e.printStackTrace();
-            }
-            tries++;
-        }
-        Assert.assertTrue("Could not have a stable read on native allocated size even after "
-                        + tries + " gc.",
-                tries < maxTries);
-        return currentAllocatedSize;
-    }
-
-    /**
-     * Verify that switching back and forth to the tabswitcher does not leak memory.
-     */
-    /**
-     * @LargeTest
-     * @Feature({"Android-TabSwitcher"})
-     */
-    @Test
-    @FlakyTest(message = "crbug.com/303319")
-    @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    public void testTabSwitcherMemoryLeak() {
-        openTabs(4, true);
-
-        int maxTries = 10;
-        int tries = 0;
-        long threshold = 1024; // bytes
-        long lastAllocatedSize = 0;
-        long currentAllocatedSize = 2 * threshold;
-        while (tries < maxTries && (lastAllocatedSize + threshold) < currentAllocatedSize) {
-            showOverviewWithNoAnimation();
-
-            lastAllocatedSize = currentAllocatedSize;
-            currentAllocatedSize = getStableAllocatedSize();
-            //Log.w("MEMORY_TEST", "[" + tries + "/" + maxTries + "]" +
-            //        "currentAllocatedSize " + currentAllocatedSize);
-
-            hideOverviewWithNoAnimation();
-            tries++;
-        }
-
-        Assert.assertTrue(
-                "Native heap allocated size keeps increasing even after " + tries + " iterations",
-                tries < maxTries);
-    }
-
-    /**
-     * Verify that switching back and forth stay stable. This test last for at least 8 seconds.
-     */
-    @Test
-    @LargeTest
-    @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    @Feature({"Android-TabSwitcher"})
-    public void testTabSwitcherStability() throws InterruptedException {
-        openTabs(8, true);
-
-        // This is about as fast as you can ever click.
-        final long fastestUserInput = 20; // ms
-        for (int i = 0; i < 50; i++) {
-            // Show overview
-            InstrumentationRegistry.getInstrumentation().runOnMainSync(
-                    new ClickOptionButtonOnMainThread());
-            Thread.sleep(fastestUserInput);
-
-            // hide overview
-            InstrumentationRegistry.getInstrumentation().runOnMainSync(
-                    new ClickOptionButtonOnMainThread());
-            Thread.sleep(fastestUserInput);
-        }
-    }
-
-    @Test
-    @LargeTest
-    @Feature({"Android-TabSwitcher"})
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
-    public void testTabSelectionPortrait() {
-        mActivityTestRule.getActivity().setRequestedOrientation(
-                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
-        checkTabSelection(2, 0, false);
-
-        // Ensure all tabs following the selected tab are off the screen when the animation is
-        // complete.
-        final int count = getLayoutTabInStackCount(false);
-        for (int i = 1; i < count; i++) {
-            float y = getLayoutTabInStackXY(false, i)[1];
-            Assert.assertTrue(
-                    String.format(Locale.US,
-                            "Tab %d's final draw Y, %f, should exceed the view height, %f.", i, y,
-                            mTabsViewHeightDp),
-                    y >= mTabsViewHeightDp);
-        }
-    }
-
-    /**
-     * @LargeTest
-     * @Feature({"Android-TabSwitcher"})
-     */
-    @Test
-    @FlakyTest(message = "crbug.com/170179")
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
-    public void testTabSelectionLandscape() {
-        mActivityTestRule.getActivity().setRequestedOrientation(
-                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
-        checkTabSelection(2, 0, true);
-
-        // Ensure all tabs following the selected tab are off the screen when the animation is
-        // complete.
-        final int count = getLayoutTabInStackCount(false);
-        for (int i = 1; i < count; i++) {
-            float x = getLayoutTabInStackXY(false, i)[0];
-            Assert.assertTrue(
-                    String.format(Locale.US,
-                            "Tab %d's final draw X, %f, should exceed the view width, %f.", i, x,
-                            mTabsViewWidthDp),
-                    x >= mTabsViewWidthDp);
-        }
-    }
-
-    /**
-     * Verify that we don't crash and show the overview mode after closing the last tab.
-     */
-    @Test
-    @SmallTest
-    @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    @Feature({"Android-TabSwitcher"})
-    public void testCloseLastTabFromMain() {
-        OverviewModeBehaviorWatcher overviewModeWatcher = new OverviewModeBehaviorWatcher(
-                mActivityTestRule.getActivity().getLayoutManager(), true, false);
-        ChromeTabUtils.closeCurrentTab(
-                InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity());
-        InstrumentationRegistry.getInstrumentation().waitForIdleSync();
-        overviewModeWatcher.waitForBehavior();
-    }
-
     private LayoutManagerChrome updateTabsViewSize() {
         View tabsView = mActivityTestRule.getActivity().getTabsView();
         mTabsViewHeightDp = tabsView.getHeight() * mPxToDp;
@@ -957,349 +585,6 @@
         return mActivityTestRule.getActivity().getLayoutManager();
     }
 
-    private Stack getStack(final LayoutManagerChrome layoutManager, boolean isIncognito) {
-        Assert.assertTrue(
-                "getStack must be executed on the ui thread", ThreadUtils.runningOnUiThread());
-        LayoutManagerChromePhone layoutManagerPhone = (LayoutManagerChromePhone) layoutManager;
-        StackLayout layout = (StackLayout) layoutManagerPhone.getOverviewLayout();
-        return (layout).getTabStackAtIndex(
-                isIncognito ? StackLayout.INCOGNITO_STACK_INDEX : StackLayout.NORMAL_STACK_INDEX);
-    }
-
-    private int getLayoutTabInStackCount(final boolean isIncognito) {
-        final LayoutManagerChrome layoutManager = updateTabsViewSize();
-        final int[] count = new int[1];
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Stack stack = getStack(layoutManager, isIncognito);
-            count[0] = stack.getTabs().length;
-        });
-        return count[0];
-    }
-
-    private boolean stackTabIsVisible(final boolean isIncognito, final int index) {
-        final LayoutManagerChrome layoutManager = updateTabsViewSize();
-        final boolean[] isVisible = new boolean[1];
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Stack stack = getStack(layoutManager, isIncognito);
-            isVisible[0] = (stack.getTabs())[index].getLayoutTab().isVisible();
-        });
-        return isVisible[0];
-    }
-
-    private float[] getLayoutTabInStackXY(final boolean isIncognito, final int index) {
-        final LayoutManagerChrome layoutManager = updateTabsViewSize();
-        final float[] xy = new float[2];
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Stack stack = getStack(layoutManager, isIncognito);
-            xy[0] = (stack.getTabs())[index].getLayoutTab().getX();
-            xy[1] = (stack.getTabs())[index].getLayoutTab().getY();
-        });
-        return xy;
-    }
-
-    private float[] getStackTabClickTarget(final int tabIndexToSelect, final boolean isIncognito,
-            final boolean isLandscape) {
-        final LayoutManagerChrome layoutManager = updateTabsViewSize();
-        final float[] target = new float[2];
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Stack stack = getStack(layoutManager, isIncognito);
-            StackTab[] tabs = stack.getTabs();
-            // The position of the click is expressed from the top left corner of the content.
-            // The aim is to find an offset that is inside the content but not on the close
-            // button.  For this, we calculate the center of the visible tab area.
-            LayoutTab layoutTab = tabs[tabIndexToSelect].getLayoutTab();
-            LayoutTab nextLayoutTab = (tabIndexToSelect + 1) < tabs.length
-                    ? tabs[tabIndexToSelect + 1].getLayoutTab() : null;
-
-            float tabOffsetX = layoutTab.getX();
-            float tabOffsetY = layoutTab.getY();
-            float tabRightX;
-            float tabBottomY;
-            if (isLandscape) {
-                tabRightX = nextLayoutTab != null
-                        ? nextLayoutTab.getX()
-                        : tabOffsetX + layoutTab.getScaledContentWidth();
-                tabBottomY = tabOffsetY + layoutTab.getScaledContentHeight();
-            } else {
-                tabRightX = tabOffsetX + layoutTab.getScaledContentWidth();
-                tabBottomY = nextLayoutTab != null
-                        ? nextLayoutTab.getY()
-                        : tabOffsetY + layoutTab.getScaledContentHeight();
-            }
-            tabRightX = Math.min(tabRightX, mTabsViewWidthDp);
-            tabBottomY = Math.min(tabBottomY, mTabsViewHeightDp);
-
-            target[0] = (tabOffsetX + tabRightX) / 2.0f;
-            target[1] = (tabOffsetY + tabBottomY) / 2.0f;
-        });
-        return target;
-    }
-
-    private void checkTabSelection(
-            int additionalTabsToOpen, int tabIndexToSelect, boolean isLandscape) {
-        for (int i = 0; i < additionalTabsToOpen; i++) {
-            ChromeTabUtils.newTabFromMenu(
-                    InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity());
-        }
-        Assert.assertEquals("Number of open tabs does not match", additionalTabsToOpen + 1,
-                mActivityTestRule.getActivity().getCurrentTabModel().getCount());
-        showOverviewWithNoAnimation();
-
-        float[] coordinates = getStackTabClickTarget(tabIndexToSelect, false, isLandscape);
-        float clickX = coordinates[0];
-        float clickY = coordinates[1];
-
-        OverviewModeBehaviorWatcher overviewModeWatcher = new OverviewModeBehaviorWatcher(
-                mActivityTestRule.getActivity().getLayoutManager(), false, true);
-
-        final LayoutManagerChrome layoutManager = updateTabsViewSize();
-        InstrumentationRegistry.getInstrumentation().runOnMainSync(
-                new SimulateClickOnMainThread(layoutManager, (int) clickX, (int) clickY));
-        overviewModeWatcher.waitForBehavior();
-
-        // Make sure we did not accidentally close a tab.
-        Assert.assertEquals("Number of open tabs does not match", additionalTabsToOpen + 1,
-                mActivityTestRule.getActivity().getCurrentTabModel().getCount());
-    }
-
-    public void swipeToCloseTab(final int tabIndexToClose, final boolean isLandscape,
-            final boolean isIncognito, final int swipeDirection) {
-        final LayoutManagerChrome layoutManager = updateTabsViewSize();
-        float[] coordinates = getStackTabClickTarget(tabIndexToClose, isIncognito, isLandscape);
-        final float clickX = coordinates[0];
-        final float clickY = coordinates[1];
-        Log.v("ChromeTest", String.format("clickX %f clickY %f", clickX, clickY));
-
-        ChromeTabUtils.closeTabWithAction(InstrumentationRegistry.getInstrumentation(),
-                mActivityTestRule.getActivity(), () -> {
-                    if (isLandscape) {
-                        InstrumentationRegistry.getInstrumentation().runOnMainSync(
-                                new SimulateTabSwipeOnMainThread(layoutManager, clickX, clickY, 0,
-                                        swipeDirection * mTabsViewWidthDp));
-                    } else {
-                        InstrumentationRegistry.getInstrumentation().runOnMainSync(
-                                new SimulateTabSwipeOnMainThread(layoutManager, clickX, clickY,
-                                        swipeDirection * mTabsViewHeightDp, 0));
-                    }
-                });
-
-        CriteriaHelper.pollUiThread(() -> {
-            return !mActivityTestRule.getActivity()
-                            .getLayoutManager()
-                            .getActiveLayout()
-                            .isLayoutAnimating();
-        }, "Did not finish animation");
-    }
-
-    private void swipeToCloseNTabs(
-            int number, boolean isLandscape, boolean isIncognito, int swipeDirection) {
-        for (int i = number - 1; i >= 0; i--) {
-            swipeToCloseTab(i, isLandscape, isIncognito, swipeDirection);
-        }
-    }
-
-    /**
-     * Test closing few tabs by swiping them in Overview portrait mode.
-     */
-    @Test
-    @MediumTest
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
-    @Feature({"Android-TabSwitcher", "Main"})
-    public void testCloseTabPortrait() {
-        mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
-        mActivityTestRule.startMainActivityWithURL(
-                mTestServer.getURL("/chrome/test/data/android/test.html"));
-
-        mActivityTestRule.getActivity().setRequestedOrientation(
-                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
-
-        int tabCount = mActivityTestRule.getActivity().getCurrentTabModel().getCount();
-        ChromeTabUtils.newTabsFromMenu(
-                InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity(), 3);
-        Assert.assertEquals("wrong count after new tabs", tabCount + 3,
-                mActivityTestRule.getActivity().getCurrentTabModel().getCount());
-
-        showOverviewWithNoAnimation();
-        swipeToCloseNTabs(3, false, false, SWIPE_TO_LEFT_DIRECTION);
-
-        Assert.assertEquals("Wrong tab counts after closing a few of them", tabCount,
-                mActivityTestRule.getActivity().getCurrentTabModel().getCount());
-    }
-
-    /**
-     * Test closing few tabs by swiping them in Overview landscape mode.
-     */
-    @Test
-    @MediumTest
-    @Feature({"Android-TabSwitcher", "Main"})
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
-    public void testCloseTabLandscape() {
-        mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext());
-        mActivityTestRule.startMainActivityWithURL(
-                mTestServer.getURL("/chrome/test/data/android/test.html"));
-
-        mActivityTestRule.getActivity().setRequestedOrientation(
-                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
-
-        int tabCount = mActivityTestRule.getActivity().getCurrentTabModel().getCount();
-        ChromeTabUtils.newTabsFromMenu(
-                InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity(), 3);
-        Assert.assertEquals("wrong count after new tabs", tabCount + 3,
-                mActivityTestRule.getActivity().getCurrentTabModel().getCount());
-
-        showOverviewWithNoAnimation();
-        swipeToCloseTab(0, true, false, SWIPE_TO_LEFT_DIRECTION);
-        swipeToCloseTab(0, true, false, SWIPE_TO_LEFT_DIRECTION);
-        swipeToCloseTab(0, true, false, SWIPE_TO_LEFT_DIRECTION);
-
-        Assert.assertEquals("Wrong tab counts after closing a few of them", tabCount,
-                mActivityTestRule.getActivity().getCurrentTabModel().getCount());
-    }
-
-    /**
-     * Test close Incognito tab by swiping in Overview Portrait mode.
-     */
-    @Test
-    @MediumTest
-    @Feature({"Android-TabSwitcher"})
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
-    public void testCloseIncognitoTabPortrait() throws InterruptedException {
-        mActivityTestRule.getActivity().setRequestedOrientation(
-                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
-        mActivityTestRule.newIncognitoTabsFromMenu(2);
-
-        showOverviewWithNoAnimation();
-        UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
-        swipeToCloseNTabs(2, false, true, SWIPE_TO_LEFT_DIRECTION);
-    }
-
-    /**
-     * Test close 5 Incognito tabs by swiping in Overview Portrait mode.
-     */
-    @Test
-    @Feature({"Android-TabSwitcher"})
-    @MediumTest
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
-    public void testCloseFiveIncognitoTabPortrait() throws InterruptedException {
-        mActivityTestRule.getActivity().setRequestedOrientation(
-                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
-        mActivityTestRule.newIncognitoTabsFromMenu(5);
-
-        showOverviewWithNoAnimation();
-        UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
-        swipeToCloseNTabs(5, false, true, SWIPE_TO_LEFT_DIRECTION);
-    }
-
-    /**
-     * Simple swipe gesture should not close tabs when two Tabstacks are open in Overview mode.
-     * Test in Portrait Mode.
-     */
-    @Test
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
-    @MediumTest
-    @Feature({"Android-TabSwitcher"})
-    public void testSwitchTabStackWithoutClosingTabsInPortrait() {
-        mActivityTestRule.getActivity().setRequestedOrientation(
-                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
-        LayoutManagerChrome layoutManager = updateTabsViewSize();
-        SimulateTabSwipeOnMainThread swipeToIncognito =
-                new SimulateTabSwipeOnMainThread(layoutManager, mTabsViewWidthDp - 20,
-                        mTabsViewHeightDp / 2, SWIPE_TO_LEFT_DIRECTION * mTabsViewWidthDp, 0);
-        SimulateTabSwipeOnMainThread swipeToNormal = new SimulateTabSwipeOnMainThread(layoutManager,
-                20, mTabsViewHeightDp / 2, SWIPE_TO_RIGHT_DIRECTION * mTabsViewWidthDp, 0);
-        testSwitchTabStackWithoutClosingTabs(swipeToIncognito, swipeToNormal);
-    }
-
-    /**
-     * Simple swipe gesture should not close tabs when two Tabstacks are open in Overview mode.
-     * Test in Landscape Mode.
-     */
-    @Test
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
-    @MediumTest
-    @Feature({"Android-TabSwitcher"})
-    public void testSwitchTabStackWithoutClosingTabsInLandscape() {
-        mActivityTestRule.getActivity().setRequestedOrientation(
-                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
-        LayoutManagerChrome layoutManager = updateTabsViewSize();
-        SimulateTabSwipeOnMainThread swipeToIncognito =
-                new SimulateTabSwipeOnMainThread(layoutManager, mTabsViewWidthDp / 2,
-                        mTabsViewHeightDp - 20, 0, SWIPE_TO_LEFT_DIRECTION * mTabsViewWidthDp);
-        SimulateTabSwipeOnMainThread swipeToNormal = new SimulateTabSwipeOnMainThread(layoutManager,
-                mTabsViewWidthDp / 2, 20, 0, SWIPE_TO_RIGHT_DIRECTION * mTabsViewWidthDp);
-        testSwitchTabStackWithoutClosingTabs(swipeToIncognito, swipeToNormal);
-    }
-
-    private void testSwitchTabStackWithoutClosingTabs(SimulateTabSwipeOnMainThread swipeToIncognito,
-            SimulateTabSwipeOnMainThread swipeToNormal) {
-        ChromeTabbedActivity cta = mActivityTestRule.getActivity();
-        final TabModelSelector tabModelSelector = cta.getTabModelSelector();
-        final StackLayout layout = (StackLayout) cta.getLayoutManager().getOverviewLayout();
-
-        mActivityTestRule.newIncognitoTabFromMenu();
-        ChromeTabUtils.newTabFromMenu(InstrumentationRegistry.getInstrumentation(), cta);
-        showOverviewWithNoAnimation();
-        final int normalTabCount = getLayoutTabInStackCount(false);
-        final int incognitoTabCount = getLayoutTabInStackCount(true);
-        Assert.assertEquals(2, normalTabCount);
-        Assert.assertEquals(1, incognitoTabCount);
-
-        // Swipe to switch between normal and incognito tab model for 20 times.
-        boolean shouldSwipeToIncognito = true;
-        for (int i = 0; i < 20; i++) {
-            SimulateTabSwipeOnMainThread swipe =
-                    shouldSwipeToIncognito ? swipeToIncognito : swipeToNormal;
-            int tabCount = shouldSwipeToIncognito ? incognitoTabCount : normalTabCount;
-            Assert.assertNotEquals("Tab model has not been changed before swipe",
-                    shouldSwipeToIncognito, tabModelSelector.isIncognitoSelected());
-            Assert.assertNotEquals("Tab count has not been changed before swipe", tabCount,
-                    tabModelSelector.getCurrentModel().getCount());
-            // Swipe to switch tab model.
-            TestThreadUtils.runOnUiThreadBlocking(swipe);
-            CriteriaHelper.pollUiThread(() -> !layout.isLayoutAnimating());
-            Assert.assertEquals("Tab model should be changed by swipe.", shouldSwipeToIncognito,
-                    tabModelSelector.isIncognitoSelected());
-            Assert.assertEquals("Tab count should be changed by swipe.", tabCount,
-                    tabModelSelector.getCurrentModel().getCount());
-            // Flip the swipe direction.
-            shouldSwipeToIncognito = !shouldSwipeToIncognito;
-        }
-    }
-
-    /**
-     * Test close Incognito tab by swiping in Overview Landscape mode.
-     */
-    @Test
-    @MediumTest
-    @Feature({"Android-TabSwitcher"})
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
-    public void testCloseIncognitoTabLandscape() throws InterruptedException {
-        mActivityTestRule.getActivity().setRequestedOrientation(
-                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
-        mActivityTestRule.newIncognitoTabFromMenu();
-
-        showOverviewWithNoAnimation();
-        UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
-        swipeToCloseTab(0, true, true, SWIPE_TO_LEFT_DIRECTION);
-    }
-
-    /**
-     * Test close 5 Incognito tabs by swiping in Overview Landscape mode.
-     */
-    @Test
-    @MediumTest
-    @Feature({"Android-TabSwitcher"})
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
-    public void testCloseFiveIncognitoTabLandscape() throws InterruptedException {
-        mActivityTestRule.getActivity().setRequestedOrientation(
-                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
-        mActivityTestRule.newIncognitoTabsFromMenu(5);
-
-        showOverviewWithNoAnimation();
-        UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
-        swipeToCloseNTabs(5, true, true, SWIPE_TO_LEFT_DIRECTION);
-    }
-
     /**
      * Test that we can safely close a tab during a fling (http://b/issue?id=5364043)
      */
@@ -1367,31 +652,6 @@
                 mActivityTestRule.getActivity().getActivityTab().isIncognito());
     }
 
-    /**
-     * Test NewTab button on the browser toolbar.
-     * Restricted to phones due crbug.com/429671.
-     */
-    @Test
-    @MediumTest
-    @Feature({"Android-TabSwitcher"})
-    @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    public void testNewTabButton() throws ExecutionException, InterruptedException {
-        int initialTabCount = mActivityTestRule.getActivity().getCurrentTabModel().getCount();
-        showOverviewWithNoAnimation();
-
-        ThreadUtils.runOnUiThreadBlocking(
-                () -> mActivityTestRule.getActivity()
-                        .findViewById(R.id.new_tab_button)
-                        .performClick());
-
-        int newTabCount = mActivityTestRule.getActivity().getCurrentTabModel().getCount();
-        Assert.assertEquals("Tab count is expected to increment by 1 after clicking new tab button",
-                initialTabCount + 1, newTabCount);
-        UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
-        CriteriaHelper.pollInstrumentationThread(
-                () -> !mActivityTestRule.getActivity().isInOverviewMode());
-    }
-
     @Test
     @MediumTest
     @Feature({"Android-TabSwitcher"})
@@ -1651,43 +911,6 @@
                         WAIT_RESIZE_TIMEOUT_MS, TimeUnit.MILLISECONDS));
     }
 
-    /**
-     * Test that orientation changes cause the live tab reflow.
-     */
-    @Test
-    @MediumTest
-    @Feature({"Android-TabSwitcher"})
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
-    public void testOrientationChangeCausesLiveTabReflowInTabSwitcher()
-            throws InterruptedException, TimeoutException {
-        mActivityTestRule.getActivity().setRequestedOrientation(
-                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
-        ChromeTabUtils.newTabFromMenu(
-                InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity());
-        mActivityTestRule.loadUrl(RESIZE_TEST_URL);
-
-        showOverviewWithNoAnimation();
-        final WebContents webContents = mActivityTestRule.getWebContents();
-        JavaScriptUtils.executeJavaScriptAndWaitForResult(webContents, "resizeHappened = false;");
-        mActivityTestRule.getActivity().setRequestedOrientation(
-                ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
-        UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
-        Assert.assertEquals(
-                "onresize event wasn't received by the live tab (tabswitcher, to Landscape)",
-                "true",
-                JavaScriptUtils.executeJavaScriptAndWaitForResult(webContents, "resizeHappened",
-                        WAIT_RESIZE_TIMEOUT_MS, TimeUnit.MILLISECONDS));
-
-        JavaScriptUtils.executeJavaScriptAndWaitForResult(webContents, "resizeHappened = false;");
-        mActivityTestRule.getActivity().setRequestedOrientation(
-                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
-        UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
-        Assert.assertEquals(
-                "onresize event wasn't received by the live tab (tabswitcher, to Portrait)", "true",
-                JavaScriptUtils.executeJavaScriptAndWaitForResult(webContents, "resizeHappened",
-                        WAIT_RESIZE_TIMEOUT_MS, TimeUnit.MILLISECONDS));
-    }
-
     @Test
     @MediumTest
     @Feature({"Android-TabSwitcher"})
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/accessibility_tab_switcher/OverviewListLayoutTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/accessibility_tab_switcher/OverviewListLayoutTest.java
deleted file mode 100644
index 789766f7f..0000000
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/accessibility_tab_switcher/OverviewListLayoutTest.java
+++ /dev/null
@@ -1,440 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.accessibility_tab_switcher;
-
-import android.os.SystemClock;
-import android.support.test.InstrumentationRegistry;
-import android.view.View;
-import android.widget.ListView;
-import android.widget.TextView;
-
-import androidx.test.filters.MediumTest;
-
-import com.google.android.material.tabs.TabLayout;
-
-import org.hamcrest.Matchers;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import org.chromium.base.CommandLine;
-import org.chromium.base.test.util.CallbackHelper;
-import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.Criteria;
-import org.chromium.base.test.util.CriteriaHelper;
-import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.Restriction;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutTab;
-import org.chromium.chrome.browser.flags.ChromeSwitches;
-import org.chromium.chrome.browser.tab.Tab;
-import org.chromium.chrome.browser.tabmodel.TabModel;
-import org.chromium.chrome.browser.tabmodel.TabModelObserver;
-import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
-import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
-import org.chromium.chrome.test.util.ChromeTabUtils;
-import org.chromium.chrome.test.util.MenuUtils;
-import org.chromium.chrome.test.util.TabStripUtils;
-import org.chromium.chrome.test.util.browser.TabLoadObserver;
-import org.chromium.content_public.browser.test.util.TestThreadUtils;
-import org.chromium.content_public.browser.test.util.TestTouchUtils;
-import org.chromium.content_public.browser.test.util.TouchCommon;
-import org.chromium.ui.test.util.UiRestriction;
-
-import java.util.concurrent.TimeoutException;
-
-/**
- * Tests accessibility UI.
- */
-@RunWith(ChromeJUnit4ClassRunner.class)
-@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-public class OverviewListLayoutTest {
-    @Rule
-    public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
-
-    private static final String PAGE_1_HTML = "data:text/html;charset=utf-8,"
-            + "<html><head><title>Page%201<%2Ftitle><%2Fhead><body><%2Fbody><%2Fhtml>";
-    private static final String PAGE_2_HTML = "data:text/html;charset=utf-8,"
-            + "<html><head><title>Page%202<%2Ftitle><%2Fhead><body><%2Fbody><%2Fhtml>";
-
-    private static final int SWIPE_START_X_OFFSET = 10;
-    private static final int SWIPE_START_Y_OFFSET = 10;
-    private static final int SWIPE_END_X = 20;
-
-    private void verifyChildCount(int count) {
-        CriteriaHelper.pollUiThread(
-                () -> Criteria.checkThat(getList().getChildCount(), Matchers.is(count)));
-    }
-
-    private void verifyTabModelCount(boolean incognito, int count) {
-        CriteriaHelper.pollUiThread(() -> {
-            int actualCount = mActivityTestRule.getActivity()
-                                      .getTabModelSelector()
-                                      .getModel(incognito)
-                                      .getCount();
-            Criteria.checkThat(actualCount, Matchers.is(count));
-        });
-    }
-
-    @Before
-    public void setUp() {
-        CommandLine.getInstance().appendSwitch(ChromeSwitches.ENABLE_ACCESSIBILITY_TAB_SWITCHER);
-        mActivityTestRule.startMainActivityFromLauncher();
-    }
-
-    private AccessibilityTabModelWrapper getContainer() {
-        return ((OverviewListLayout) mActivityTestRule.getActivity().getOverviewListLayout())
-                .getContainer();
-    }
-
-    private ListView getList() {
-        return (ListView) getContainer().findViewById(R.id.list_view);
-    }
-
-    private void setupTabs() {
-        ChromeTabUtils.newTabsFromMenu(
-                InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity(), 3);
-
-        TestTouchUtils.performClickOnMainSync(InstrumentationRegistry.getInstrumentation(),
-                mActivityTestRule.getActivity().findViewById(R.id.tab_switcher_button));
-
-        verifyChildCount(4);
-    }
-
-    private AccessibilityTabModelListItem getListItemAndDisableAnimations(int index) {
-        AccessibilityTabModelListItem item = getListItem(index);
-        item.disableAnimations();
-        return item;
-    }
-
-    private AccessibilityTabModelListItem getListItem(int index) {
-        AccessibilityTabModelListItem item =
-                (AccessibilityTabModelListItem) getList().getChildAt(index);
-        return item;
-    }
-
-    private CharSequence getTabTitleOfListItem(int index) {
-        View childView = getListItem(index);
-        TextView childTextView;
-        childTextView = (TextView) childView.findViewById(org.chromium.chrome.R.id.title);
-        return childTextView.getText();
-    }
-
-    private void toggleTabSwitcher(final boolean expectVisible) {
-        TestTouchUtils.performClickOnMainSync(InstrumentationRegistry.getInstrumentation(),
-                mActivityTestRule.getActivity().findViewById(R.id.tab_switcher_button));
-        CriteriaHelper.pollUiThread(() -> {
-            if (expectVisible) {
-                Criteria.checkThat(getContainer(), Matchers.notNullValue());
-                Criteria.checkThat(getContainer().getParent(), Matchers.notNullValue());
-            } else {
-                if (getContainer() == null) return;
-                Criteria.checkThat(getContainer().getParent(), Matchers.nullValue());
-            }
-        });
-    }
-
-    @Test
-    @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    @MediumTest
-    @Feature({"Accessibility"})
-    public void testCanEnterSwitcher() {
-        TestTouchUtils.performClickOnMainSync(InstrumentationRegistry.getInstrumentation(),
-                mActivityTestRule.getActivity().findViewById(R.id.tab_switcher_button));
-
-        Assert.assertNotNull("Accessibility container was not initialized", getContainer());
-        Assert.assertNotNull("Accessibility container was not visible", getContainer().getParent());
-    }
-
-    @Test
-    @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    @MediumTest
-    @Feature({"Accessibility"})
-    public void testCanLeaveSwitcher() {
-        TestTouchUtils.performClickOnMainSync(InstrumentationRegistry.getInstrumentation(),
-                mActivityTestRule.getActivity().findViewById(R.id.tab_switcher_button));
-
-        Assert.assertNotNull("Accessibility container was not initialized", getContainer());
-        Assert.assertNotNull("Accessibility container was not visible", getContainer().getParent());
-
-        TestTouchUtils.performClickOnMainSync(InstrumentationRegistry.getInstrumentation(),
-                mActivityTestRule.getActivity().findViewById(R.id.tab_switcher_button));
-        Assert.assertNull("Accessibility container was not visible", getContainer().getParent());
-    }
-
-    @Test
-    @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    @MediumTest
-    @Feature({"Accessibility"})
-    public void testCanCloseWithCloseButton() throws TimeoutException {
-        setupTabs();
-
-        AccessibilityTabModelListItem item = getListItemAndDisableAnimations(0);
-
-        final CallbackHelper didReceiveClosureCommittedHelper = new CallbackHelper();
-        final TabModel model = mActivityTestRule.getActivity().getCurrentTabModel();
-        model.addObserver(new TabModelObserver() {
-            @Override
-            public void tabClosureCommitted(Tab tab) {
-                didReceiveClosureCommittedHelper.notifyCalled();
-            }
-        });
-
-        TestTouchUtils.performClickOnMainSync(
-                InstrumentationRegistry.getInstrumentation(), item.getCloseButtonForTests());
-
-        didReceiveClosureCommittedHelper.waitForCallback(0);
-
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> { Assert.assertEquals("Tab not closed", 3, getList().getChildCount()); });
-    }
-
-    @Test
-    @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    @MediumTest
-    @Feature({"Accessibility"})
-    public void testCanSwipeClosed() throws TimeoutException {
-        setupTabs();
-
-        AccessibilityTabModelListItem item = getListItemAndDisableAnimations(1);
-
-        int[] location = TestTouchUtils.getAbsoluteLocationFromRelative(
-                item, SWIPE_START_X_OFFSET, SWIPE_START_Y_OFFSET);
-
-        final CallbackHelper didReceiveClosureCommittedHelper = new CallbackHelper();
-        final TabModel model = mActivityTestRule.getActivity().getCurrentTabModel();
-        model.addObserver(new TabModelObserver() {
-            @Override
-            public void tabClosureCommitted(Tab tab) {
-                didReceiveClosureCommittedHelper.notifyCalled();
-            }
-        });
-
-        long downTime = SystemClock.uptimeMillis();
-        TouchCommon.dragStart(mActivityTestRule.getActivity(), location[0], location[1], downTime);
-        TouchCommon.dragTo(mActivityTestRule.getActivity(), location[0],
-                (int) (item.getWidth() / 1.5), location[1], location[1], 20, downTime);
-        TouchCommon.dragEnd(mActivityTestRule.getActivity(), 400, location[1], downTime);
-
-        didReceiveClosureCommittedHelper.waitForCallback(0);
-
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> { Assert.assertEquals("Tab not closed", 3, getList().getChildCount()); });
-    }
-
-    @Test
-    @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    @MediumTest
-    @Feature({"Accessibility"})
-    public void testResetSwipe() {
-        setupTabs();
-
-        AccessibilityTabModelListItem item = getListItemAndDisableAnimations(0);
-
-        int[] location = TestTouchUtils.getAbsoluteLocationFromRelative(
-                item, SWIPE_START_X_OFFSET, SWIPE_START_Y_OFFSET);
-
-        TouchCommon.dragTo(mActivityTestRule.getActivity(), location[0], SWIPE_END_X, location[1],
-                location[1], 20, SystemClock.uptimeMillis());
-
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Assert.assertEquals("Tab not reset as expected", 4, getList().getChildCount());
-        });
-    }
-
-    @Test
-    @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    @MediumTest
-    @Feature({"Accessibility"})
-    public void testCloseAndUndo() throws TimeoutException {
-        setupTabs();
-
-        final AccessibilityTabModelListItem item = getListItem(0);
-
-        final CallbackHelper didReceivePendingClosureHelper = new CallbackHelper();
-        final TabModel model = mActivityTestRule.getActivity().getCurrentTabModel();
-        model.addObserver(new TabModelObserver() {
-            @Override
-            public void tabPendingClosure(Tab tab) {
-                didReceivePendingClosureHelper.notifyCalled();
-            }
-        });
-
-        TestTouchUtils.performClickOnMainSync(
-                InstrumentationRegistry.getInstrumentation(), item.getCloseButtonForTests());
-
-        didReceivePendingClosureHelper.waitForCallback(0);
-
-        TestTouchUtils.performClickOnMainSync(
-                InstrumentationRegistry.getInstrumentation(), item.findViewById(R.id.undo_button));
-
-        Assert.assertFalse("Close not undone", item.hasPendingClosure());
-
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Assert.assertEquals("Tab closure not undone", 4, getList().getChildCount());
-        });
-    }
-
-    @Test
-    @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    @MediumTest
-    @Feature({"Accessibility"})
-    public void testCloseAll() {
-        setupTabs();
-
-        MenuUtils.invokeCustomMenuActionSync(InstrumentationRegistry.getInstrumentation(),
-                mActivityTestRule.getActivity(), R.id.close_all_tabs_menu_id);
-
-        verifyChildCount(0);
-        verifyTabModelCount(false, 0);
-        Assert.assertFalse(mActivityTestRule.getActivity()
-                                   .findViewById(R.id.tab_switcher_mode_tab_switcher_button)
-                                   .isEnabled());
-        Assert.assertTrue(
-                mActivityTestRule.getActivity().findViewById(R.id.new_tab_button).isEnabled());
-    }
-
-    @Test
-    @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    @MediumTest
-    @Feature({"Accessibility"})
-    public void testCloseAllIncognito() {
-        setupTabs();
-        mActivityTestRule.newIncognitoTabsFromMenu(2);
-        TestTouchUtils.performClickOnMainSync(InstrumentationRegistry.getInstrumentation(),
-                mActivityTestRule.getActivity().findViewById(R.id.tab_switcher_button));
-        verifyChildCount(2);
-
-        MenuUtils.invokeCustomMenuActionSync(InstrumentationRegistry.getInstrumentation(),
-                mActivityTestRule.getActivity(), R.id.close_all_incognito_tabs_menu_id);
-        verifyTabModelCount(true, 0);
-
-        verifyChildCount(4);
-        Assert.assertTrue(mActivityTestRule.getActivity()
-                                  .findViewById(R.id.tab_switcher_mode_tab_switcher_button)
-                                  .isEnabled());
-
-        MenuUtils.invokeCustomMenuActionSync(InstrumentationRegistry.getInstrumentation(),
-                mActivityTestRule.getActivity(), R.id.close_all_tabs_menu_id);
-
-        verifyChildCount(0);
-        verifyTabModelCount(false, 0);
-        Assert.assertFalse(mActivityTestRule.getActivity()
-                                   .findViewById(R.id.tab_switcher_mode_tab_switcher_button)
-                                   .isEnabled());
-        Assert.assertTrue(
-                mActivityTestRule.getActivity().findViewById(R.id.new_tab_button).isEnabled());
-    }
-
-    @Test
-    @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    @MediumTest
-    @Feature({"Accessibility"})
-    public void testModelSwitcherVisibility() {
-        setupTabs();
-
-        View switcherButtons = getContainer().findViewById(R.id.tab_wrapper);
-
-        Assert.assertEquals(
-                "Tab Model Switcher buttons visible", View.GONE, switcherButtons.getVisibility());
-
-        mActivityTestRule.newIncognitoTabsFromMenu(2);
-
-        TestTouchUtils.performClickOnMainSync(InstrumentationRegistry.getInstrumentation(),
-                mActivityTestRule.getActivity().findViewById(R.id.tab_switcher_button));
-
-        Assert.assertEquals("Tab Model switcher buttons not visible", View.VISIBLE,
-                switcherButtons.getVisibility());
-    }
-
-    @Test
-    @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    @MediumTest
-    @Feature({"Accessibility"})
-    public void testModelSwitcherFunctionality() {
-        mActivityTestRule.newIncognitoTabsFromMenu(2);
-
-        ChromeTabUtils.newTabsFromMenu(
-                InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity(), 3);
-
-        TestTouchUtils.performClickOnMainSync(InstrumentationRegistry.getInstrumentation(),
-                mActivityTestRule.getActivity().findViewById(R.id.tab_switcher_button));
-
-        View switcherButtons = getContainer().findViewById(R.id.tab_wrapper);
-
-        Assert.assertEquals("Tab Model Switcher buttons visible", View.VISIBLE,
-                switcherButtons.getVisibility());
-
-        TabLayout.Tab incognitoButton = getContainer().getIncognitoTabsButton();
-
-        Assert.assertNotNull("IncognitoButton is null", incognitoButton);
-
-        TestThreadUtils.runOnUiThreadBlocking(() -> incognitoButton.select());
-
-        verifyChildCount(2);
-
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> getContainer().getStandardTabsButton().select());
-
-        verifyChildCount(4);
-    }
-
-    /**
-     * Tests that the TabObserver of the {@link AccessibilityTabModelListItem} is added back
-     * to the Tab after the View is hidden.  This requires bringing the tab switcher back twice
-     * because the TabObserver is removed/added when the tab switcher's View is detached from/
-     * attached to the window.
-     */
-    @Test
-    @MediumTest
-    @Feature({"Accessibility"})
-    public void testObservesTitleChanges() throws Exception {
-        mActivityTestRule.loadUrl(PAGE_1_HTML);
-
-        // Bring the tab switcher forward and send it away twice.
-        toggleTabSwitcher(true);
-        Assert.assertEquals("Page 1", getTabTitleOfListItem(0));
-        toggleTabSwitcher(false);
-        toggleTabSwitcher(true);
-        toggleTabSwitcher(false);
-
-        // Load another URL.
-        new TabLoadObserver(mActivityTestRule.getActivity().getActivityTab())
-                .fullyLoadUrl(PAGE_2_HTML);
-
-        // Bring the tab switcher forward and check the title.
-        toggleTabSwitcher(true);
-        Assert.assertEquals("Page 2", getTabTitleOfListItem(0));
-    }
-
-    @Test
-    @Restriction(UiRestriction.RESTRICTION_TYPE_TABLET)
-    @MediumTest
-    @Feature({"Accessibility"})
-    public void testCloseTabThroughTabStrip() throws TimeoutException {
-        setupTabs();
-
-        getListItemAndDisableAnimations(0);
-        final CallbackHelper didReceiveClosureCommittedHelper = new CallbackHelper();
-        final TabModel model = mActivityTestRule.getActivity().getCurrentTabModel();
-        model.addObserver(new TabModelObserver() {
-            @Override
-            public void tabClosureCommitted(Tab tab) {
-                didReceiveClosureCommittedHelper.notifyCalled();
-            }
-        });
-
-        StripLayoutTab tab = TabStripUtils.findStripLayoutTab(
-                mActivityTestRule.getActivity(), false, model.getTabAt(0).getId());
-        TabStripUtils.clickCompositorButton(tab.getCloseButton(),
-                InstrumentationRegistry.getInstrumentation(), mActivityTestRule.getActivity());
-        didReceiveClosureCommittedHelper.waitForCallback(0);
-
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> { Assert.assertEquals("Tab not closed", 3, getList().getChildCount()); });
-    }
-}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/RunningInChromeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/RunningInChromeTest.java
index b8bd10b..6f71d27c 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/RunningInChromeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/RunningInChromeTest.java
@@ -36,7 +36,7 @@
 import org.chromium.base.test.util.CriteriaHelper;
 import org.chromium.base.test.util.FlakyTest;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
 import org.chromium.chrome.browser.dependency_injection.ChromeActivityCommonsModule;
 import org.chromium.chrome.browser.dependency_injection.ModuleOverridesRule;
@@ -126,7 +126,7 @@
         mMockNotificationManager.setNotificationsEnabled(false);
 
         mStore = new BrowserServicesStore(
-                ChromeApplication.getComponent().resolveSharedPreferencesManager());
+                ChromeApplicationImpl.getComponent().resolveSharedPreferencesManager());
         mStore.removeTwaDisclosureAcceptanceForPackage(PACKAGE_NAME);
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientLocationDelegationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientLocationDelegationTest.java
index 3e9f2055..60c980d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientLocationDelegationTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientLocationDelegationTest.java
@@ -23,7 +23,7 @@
 import org.chromium.base.test.BaseJUnit4ClassRunner;
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CallbackHelper;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.dependency_injection.ChromeAppComponent;
 import org.chromium.components.embedder_support.util.Origin;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
@@ -58,7 +58,7 @@
 
     @Before
     public void setUp() throws TimeoutException, RemoteException {
-        ChromeAppComponent component = ChromeApplication.getComponent();
+        ChromeAppComponent component = ChromeApplicationImpl.getComponent();
         mClient = component.resolveTrustedWebActivityClient();
 
         // TestTrustedWebActivityService is in the test support apk.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java
index 2b1f9dd..34d35b6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityClientTest.java
@@ -32,7 +32,7 @@
 import org.chromium.base.test.BaseJUnit4ClassRunner;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.dependency_injection.ChromeAppComponent;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.notifications.NotificationUmaTracker;
@@ -137,7 +137,7 @@
         mTargetContext = InstrumentationRegistry.getTargetContext();
         mBuilder = new StandardNotificationBuilder(mTargetContext);
 
-        ChromeAppComponent component = ChromeApplication.getComponent();
+        ChromeAppComponent component = ChromeApplicationImpl.getComponent();
         mClient = component.resolveTrustedWebActivityClient();
 
         // TestTrustedWebActivityService is in the test support apk.
@@ -266,8 +266,8 @@
         Assert.assertNull(TrustedWebActivityClient.createLaunchIntentForTwa(
                 context, SCOPE.toString(), Collections.singletonList(resolveInfo)));
 
-        ChromeApplication.getComponent().resolveTwaPermissionManager()
-                .addDelegateApp(Origin.create(SCOPE), targetPackageName);
+        ChromeApplicationImpl.getComponent().resolveTwaPermissionManager().addDelegateApp(
+                Origin.create(SCOPE), targetPackageName);
 
         Assert.assertNotNull(TrustedWebActivityClient.createLaunchIntentForTwa(
                 context, SCOPE.toString(), Collections.singletonList(resolveInfo)));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsTest.java
index b3af5cb3..87d014e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/digitalgoods/DigitalGoodsTest.java
@@ -32,7 +32,7 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.CriteriaHelper;
 import org.chromium.base.test.util.DisableIf;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.browserservices.TrustedWebActivityClient;
 import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
 import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils;
@@ -73,7 +73,7 @@
         // Native needs to be initialized to start the test server.
         LibraryLoader.getInstance().ensureInitialized();
 
-        ChromeAppComponent component = ChromeApplication.getComponent();
+        ChromeAppComponent component = ChromeApplicationImpl.getComponent();
         component.resolveTwaPermissionManager().addDelegateApp(
                 Origin.createOrThrow(TWA_SERVICE_SCOPE), "org.chromium.chrome.tests.support");
         mClient = component.resolveTrustedWebActivityClient();
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionsTest.java
index 10855f3..23175c4 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPermissionsTest.java
@@ -25,7 +25,7 @@
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.DisableIf;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.ShortcutHelper;
 import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
 import org.chromium.chrome.browser.customtabs.CustomTabsTestUtils;
@@ -82,7 +82,7 @@
                 CustomTabsTestUtils.createMinimalCustomTabIntent(
                         InstrumentationRegistry.getTargetContext(), mTestPage));
 
-        mPermissionManager = ChromeApplication.getComponent().resolveTwaPermissionManager();
+        mPermissionManager = ChromeApplicationImpl.getComponent().resolveTwaPermissionManager();
         mPermissionManager.clearForTesting();
         assertEquals("\"default\"", getNotificationPermission());
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPreferencesUiTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPreferencesUiTest.java
index f486444..b302e100 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPreferencesUiTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityPreferencesUiTest.java
@@ -17,7 +17,7 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.CriteriaHelper;
 import org.chromium.base.test.util.Feature;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.settings.SettingsActivity;
 import org.chromium.chrome.browser.site_settings.SiteSettingsTestUtils;
@@ -53,7 +53,7 @@
         mActivityTestRule.startMainActivityOnBlankPage();
 
         mPackage = InstrumentationRegistry.getTargetContext().getPackageName();
-        mPermissionMananger = ChromeApplication.getComponent().resolveTwaPermissionManager();
+        mPermissionMananger = ChromeApplicationImpl.getComponent().resolveTwaPermissionManager();
     }
 
     /**
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 ac4b0dc9..9c98baf 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
@@ -7,6 +7,10 @@
 import static android.os.Build.VERSION_CODES.N_MR1;
 
 import static org.hamcrest.Matchers.is;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_LOW_END_DEVICE;
 import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE;
@@ -14,7 +18,6 @@
 import static org.chromium.chrome.test.util.ViewUtils.createMotionEvent;
 
 import android.content.Context;
-import android.graphics.PointF;
 import android.support.test.InstrumentationRegistry;
 import android.view.MotionEvent;
 import android.view.MotionEvent.PointerCoords;
@@ -30,32 +33,26 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
 
 import org.chromium.base.Log;
 import org.chromium.base.MathUtils;
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.supplier.OneshotSupplierImpl;
 import org.chromium.base.test.UiThreadTest;
-import org.chromium.base.test.params.ParameterAnnotations;
-import org.chromium.base.test.params.ParameterProvider;
-import org.chromium.base.test.params.ParameterSet;
-import org.chromium.base.test.params.ParameterizedRunner;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.CriteriaHelper;
 import org.chromium.base.test.util.DisableIf;
-import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.browser.ActivityTabProvider;
 import org.chromium.chrome.browser.accessibility_tab_switcher.OverviewListLayout;
-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.phone.StackLayout;
-import org.chromium.chrome.browser.compositor.layouts.phone.stack.Stack;
-import org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTab;
 import org.chromium.chrome.browser.flags.CachedFeatureFlags;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
@@ -70,11 +67,13 @@
 import org.chromium.chrome.browser.tabmodel.TabModelSelector;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
 import org.chromium.chrome.browser.tasks.tab_management.TabListCoordinator;
+import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
 import org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper;
 import org.chromium.chrome.browser.theme.TopUiThemeColorProvider;
 import org.chromium.chrome.browser.util.ChromeAccessibilityUtil;
+import org.chromium.chrome.features.start_surface.StartSurface;
 import org.chromium.chrome.features.start_surface.StartSurfaceLayout;
-import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.chrome.test.util.browser.tabmodel.MockTabModel.MockTabModelDelegate;
@@ -84,15 +83,12 @@
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.ui.test.util.UiRestriction;
 
-import java.util.Arrays;
-import java.util.List;
 import java.util.concurrent.TimeoutException;
 
 /**
  * Unit tests for {@link org.chromium.chrome.browser.compositor.layouts.LayoutManagerChrome}
  */
-@RunWith(ParameterizedRunner.class)
-@ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class)
+@RunWith(ChromeJUnit4ClassRunner.class)
 public class LayoutManagerTest implements MockTabModelDelegate {
     private static final String TAG = "LayoutManagerTest";
 
@@ -105,6 +101,18 @@
     @Mock
     private TopUiThemeColorProvider mTopUiThemeColorProvider;
 
+    @Mock
+    private StartSurface mStartSurface;
+
+    @Mock
+    private StartSurface.Controller mStartSurfaceController;
+
+    @Mock
+    private TabSwitcher.TabListDelegate mTabListDelegate;
+
+    @Captor
+    private ArgumentCaptor<StartSurface.OverviewModeObserver> mStartSurfaceOverviewModeCaptor;
+
     private long mLastDownTime;
 
     private TabModelSelector mTabModelSelector;
@@ -118,17 +126,6 @@
 
     private OneshotSupplierImpl<LayoutStateProvider> mLayoutStateProviderSupplier;
 
-    public static class GridTabSwitcherParams implements ParameterProvider {
-        private static List<ParameterSet> sGridTabSwitcherParams =
-                Arrays.asList(new ParameterSet().value(false).name("GridTabSwicherDisabled"),
-                        new ParameterSet().value(true).name("GridTabSwicherEnabled"));
-
-        @Override
-        public List<ParameterSet> getParameters() {
-            return sGridTabSwitcherParams;
-        }
-    }
-
     class LayoutObserverCallbackHelper extends CallbackHelper {
         @LayoutType
         public int layoutType;
@@ -190,6 +187,10 @@
 
         mDpToPx = context.getResources().getDisplayMetrics().density;
 
+        when(mStartSurface.getController()).thenReturn(mStartSurfaceController);
+        when(mStartSurface.getTabListDelegate()).thenReturn(mTabListDelegate);
+        when(mStartSurface.getTabGridDialogVisibilitySupplier()).thenReturn(() -> false);
+
         mTabModelSelector = new MockTabModelSelector(standardTabCount, incognitoTabCount, this);
         if (standardIndexSelected != TabModel.INVALID_TAB_INDEX) {
             TabModelUtils.setIndex(mTabModelSelector.getModel(false), standardIndexSelected);
@@ -219,9 +220,27 @@
             mLayoutStateProviderSupplier = new OneshotSupplierImpl<>();
         }
 
-        mManagerPhone = new LayoutManagerChromePhone(layoutManagerHost, container, null,
+        mManagerPhone = new LayoutManagerChromePhone(layoutManagerHost, container, mStartSurface,
                 tabContentManagerSupplier, null, overviewModeBehaviorSupplier,
                 mLayoutStateProviderSupplier, () -> mTopUiThemeColorProvider);
+        verify(mStartSurfaceController)
+                .addOverviewModeObserver(mStartSurfaceOverviewModeCaptor.capture());
+
+        doAnswer((Answer<Void>) invocation -> {
+            mStartSurfaceOverviewModeCaptor.getValue().finishedShowing();
+            simulateTime(mManager, 1000);
+            return null;
+        })
+                .when(mStartSurfaceController)
+                .showOverview(anyBoolean());
+
+        doAnswer((Answer<Void>) invocation -> {
+            mStartSurfaceOverviewModeCaptor.getValue().finishedHiding();
+            return null;
+        })
+                .when(mStartSurfaceController)
+                .hideOverview(anyBoolean());
+
         tabContentManagerSupplier.set(tabContentManager);
         mManager = mManagerPhone;
         CompositorAnimationHandler.setTestingMode(true);
@@ -229,72 +248,6 @@
         initializeMotionEvent();
     }
 
-    private void eventDown(long time, PointF p) {
-        mLastDownTime = time;
-
-        mPointerCoords[0].x = p.x * mDpToPx;
-        mPointerCoords[0].y = p.y * mDpToPx;
-
-        MotionEvent event = MotionEvent.obtain(mLastDownTime, time, MotionEvent.ACTION_DOWN,
-                1, mProperties, mPointerCoords, 0, 0, 1, 1, 0, 0, 0, 0);
-        Assert.assertTrue(
-                "Down event not intercepted", mManager.onInterceptTouchEvent(event, false));
-        Assert.assertTrue("Down event not handled", mManager.onTouchEvent(event));
-    }
-
-    private void eventDown1(long time, PointF p) {
-        mPointerCoords[1].x = p.x * mDpToPx;
-        mPointerCoords[1].y = p.y * mDpToPx;
-
-        Assert.assertTrue("Down_1 event not handled",
-                mManager.onTouchEvent(MotionEvent.obtain(mLastDownTime, time,
-                        MotionEvent.ACTION_POINTER_DOWN
-                                | (0x1 << MotionEvent.ACTION_POINTER_INDEX_SHIFT),
-                        2, mProperties, mPointerCoords, 0, 0, 1, 1, 0, 0, 0, 0)));
-    }
-
-    private void eventMove(long time, PointF p) {
-        mPointerCoords[0].x = p.x * mDpToPx;
-        mPointerCoords[0].y = p.y * mDpToPx;
-
-        Assert.assertTrue("Move event not handled",
-                mManager.onTouchEvent(
-                        MotionEvent.obtain(mLastDownTime, time, MotionEvent.ACTION_MOVE, 1,
-                                mProperties, mPointerCoords, 0, 0, 1, 1, 0, 0, 0, 0)));
-    }
-
-    private void eventUp(long time, PointF p) {
-        mPointerCoords[0].x = p.x * mDpToPx;
-        mPointerCoords[0].y = p.y * mDpToPx;
-
-        Assert.assertTrue("Up event not handled",
-                mManager.onTouchEvent(MotionEvent.obtain(mLastDownTime, time, MotionEvent.ACTION_UP,
-                        1, mProperties, mPointerCoords, 0, 0, 1, 1, 0, 0, 0, 0)));
-    }
-
-    private void eventUp1(long time, PointF p) {
-        mPointerCoords[1].x = p.x * mDpToPx;
-        mPointerCoords[1].y = p.y * mDpToPx;
-
-        Assert.assertTrue("Up_1 event not handled",
-                mManager.onTouchEvent(MotionEvent.obtain(mLastDownTime, time,
-                        MotionEvent.ACTION_POINTER_UP
-                                | (0x1 << MotionEvent.ACTION_POINTER_INDEX_SHIFT),
-                        2, mProperties, mPointerCoords, 0, 0, 1, 1, 0, 0, 0, 0)));
-    }
-
-    private void eventMoveBoth(long time, PointF p0, PointF p1) {
-        mPointerCoords[0].x = p0.x * mDpToPx;
-        mPointerCoords[0].y = p0.y * mDpToPx;
-        mPointerCoords[1].x = p1.x * mDpToPx;
-        mPointerCoords[1].y = p1.y * mDpToPx;
-
-        Assert.assertTrue("Move event not handled",
-                mManager.onTouchEvent(
-                        MotionEvent.obtain(mLastDownTime, time, MotionEvent.ACTION_MOVE, 2,
-                                mProperties, mPointerCoords, 0, 0, 1, 1, 0, 0, 0, 0)));
-    }
-
     @Test
     @SmallTest
     @Feature({"Android-TabSwitcher"})
@@ -306,181 +259,6 @@
 
     @Test
     @SmallTest
-    @Feature({"Android-TabSwitcher"})
-    @UiThreadTest
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
-    @DisabledTest(message = "https://crbug.com/965250")
-    public void testStack() {
-        initializeLayoutManagerPhone(3, 0);
-        mManagerPhone.showOverview(true);
-        Assert.assertTrue(
-                "layoutManager is way too long to end motion", simulateTime(mManager, 1000));
-        Assert.assertTrue("The activate layout type is expected to be StackLayout",
-                mManager.getActiveLayout() instanceof StackLayout);
-        mManagerPhone.hideOverview(true);
-        Assert.assertTrue(
-                "layoutManager is way too long to end motion", simulateTime(mManager, 1000));
-    }
-
-    @Test
-    @SmallTest
-    @Feature({"Android-TabSwitcher"})
-    @UiThreadTest
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
-    public void testStackNoAnimation() {
-        initializeLayoutManagerPhone(1, 0);
-        mManagerPhone.showOverview(false);
-        Assert.assertTrue("The activate layout type is expected to be StackLayout",
-                mManager.getActiveLayout() instanceof StackLayout);
-        mManagerPhone.hideOverview(false);
-    }
-
-    /**
-     * Tests the tab pinching behavior with two finger.
-     * This test is still under development.
-     */
-    @Test
-    @SmallTest
-    @Feature({"Android-TabSwitcher"})
-    @UiThreadTest
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
-    public void testStackPinch() {
-        initializeLayoutManagerPhone(5, 0);
-        // Setting the index to the second to last element ensure the stack can be scrolled in both
-        // directions.
-        mManager.tabSelected(mTabModelSelector.getCurrentModel().getTabAt(3).getId(),
-                Tab.INVALID_TAB_ID, false);
-
-        mManagerPhone.showOverview(false);
-        // Basic verifications
-        Assert.assertTrue("The activate layout type is expected to be StackLayout",
-                mManager.getActiveLayout() instanceof StackLayout);
-
-        StackLayout layout = (StackLayout) mManager.getActiveLayout();
-        Stack stack = layout.getTabStackAtIndex(StackLayout.NORMAL_STACK_INDEX);
-        StackTab[] tabs = stack.getTabs();
-
-        long time = 0;
-        // At least one update is necessary to get updated positioning of LayoutTabs.
-        mManager.onUpdate(time, 16);
-        time++;
-
-        LayoutTab tab1 = tabs[1].getLayoutTab();
-        LayoutTab tab3 = tabs[3].getLayoutTab();
-
-        float fingerOffset = Math.min(tab1.getClippedHeight() / 2, tab3.getClippedHeight() / 2);
-
-        PointF finger0 = new PointF(tab1.getX() + tab1.getFinalContentWidth() / 2,
-                tab1.getY() + fingerOffset);
-
-        // Initiate finger 0
-        eventDown(time, finger0);
-        mManager.onUpdate(time, 16);
-        time++;
-
-        // Move finger 0: Y to simulate a scroll
-        final float scrollOffset1 = (tab3.getY() - tab1.getY()) / 8.0f;
-        finger0.y += scrollOffset1;
-
-        eventMove(time, finger0);
-        mManager.onUpdate(time, 16);
-        time++;
-
-        finger0.y -= scrollOffset1;
-
-        eventMove(time, finger0);
-        mManager.onUpdate(time, 16);
-        time++;
-
-        float expectedTab1X = tab1.getX();
-        float expectedTab1Y = tab1.getY();
-
-        // Initiate the pinch with finger 1
-        PointF finger1 = new PointF(tab3.getX() + tab3.getFinalContentWidth() / 2,
-                tab3.getY() + fingerOffset);
-        eventDown1(time, finger1);
-        mManager.onUpdate(time, 16);
-        time++;
-
-        final float delta = 0.001f;
-        Assert.assertEquals("Wrong x offset for tab 1", expectedTab1X, tab1.getX(), delta);
-        Assert.assertEquals("Wrong y offset for tab 1", expectedTab1Y, tab1.getY(), delta);
-        float expectedTab3X = tab3.getX();
-        float expectedTab3Y = tab3.getY();
-
-        // Move Finger 0: Y only
-        finger0.y += scrollOffset1;
-        expectedTab1Y += scrollOffset1;
-
-        eventMoveBoth(time, finger0, finger1);
-        mManager.onUpdate(time, 16);
-        time++;
-
-        Assert.assertEquals("Wrong x offset for tab 1", expectedTab1X, tab1.getX(), delta);
-        Assert.assertEquals("Wrong y offset for tab 1", expectedTab1Y, tab1.getY(), delta);
-        Assert.assertEquals("Wrong x offset for tab 3", expectedTab3X, tab3.getX(), delta);
-        Assert.assertEquals("Wrong y offset for tab 3", expectedTab3Y, tab3.getY(), delta);
-
-        // Move finger 0: Y and X
-        finger0.y += scrollOffset1;
-        finger0.x += tab1.getFinalContentWidth() / 8.0f;
-        expectedTab1Y += scrollOffset1;
-
-        eventMoveBoth(time, finger0, finger1);
-        mManager.onUpdate(time, 16);
-        time++;
-
-        Assert.assertEquals("Wrong x offset for tab 1", expectedTab1X, tab1.getX(), delta);
-        Assert.assertEquals("Wrong y offset for tab 1", expectedTab1Y, tab1.getY(), delta);
-        Assert.assertEquals("Wrong x offset for tab 3", expectedTab3X, tab3.getX(), delta);
-        Assert.assertEquals("Wrong y offset for tab 3", expectedTab3Y, tab3.getY(), delta);
-
-        // Move finger 1: Y and X
-        final float scrollOffset3 = (tab3.getY() - layout.getHeight()) / 8.0f;
-        finger1.y += scrollOffset3;
-        finger1.x += tab3.getFinalContentWidth() / 8.0f;
-        expectedTab3Y += scrollOffset3;
-
-        eventMoveBoth(time, finger0, finger1);
-        mManager.onUpdate(time, 16);
-        time++;
-
-        Assert.assertEquals("Wrong x offset for tab 1", expectedTab1X, tab1.getX(), delta);
-        Assert.assertEquals("Wrong y offset for tab 1", expectedTab1Y, tab1.getY(), delta);
-        Assert.assertEquals("Wrong x offset for tab 3", expectedTab3X, tab3.getX(), delta);
-        Assert.assertEquals("Wrong y offset for tab 3", expectedTab3Y, tab3.getY(), delta);
-
-        // Move finger 0 and 1: Y and X
-        finger0.y += scrollOffset1;
-        finger0.x += tab1.getFinalContentWidth() / 8.0f;
-        expectedTab1Y += scrollOffset1;
-        finger1.y += scrollOffset3;
-        finger1.x += tab3.getFinalContentWidth() / 8.0f;
-        expectedTab3Y += scrollOffset3;
-
-        eventMoveBoth(time, finger0, finger1);
-        mManager.onUpdate(time, 16);
-        time++;
-
-        Assert.assertEquals("Wrong x offset for tab 1", expectedTab1X, tab1.getX(), delta);
-        Assert.assertEquals("Wrong y offset for tab 1", expectedTab1Y, tab1.getY(), delta);
-        Assert.assertEquals("Wrong x offset for tab 3", expectedTab3X, tab3.getX(), delta);
-        Assert.assertEquals("Wrong y offset for tab 3", expectedTab3Y, tab3.getY(), delta);
-
-        // Done
-        eventUp1(time, finger1);
-        eventUp(time, finger0);
-
-        Assert.assertEquals("Wrong x offset for tab 1", expectedTab1X, tab1.getX(), delta);
-        Assert.assertEquals("Wrong y offset for tab 1", expectedTab1Y, tab1.getY(), delta);
-        Assert.assertEquals("Wrong x offset for tab 3", expectedTab3X, tab3.getX(), delta);
-        Assert.assertEquals("Wrong y offset for tab 3", expectedTab3Y, tab3.getY(), delta);
-
-        mManagerPhone.hideOverview(false);
-    }
-
-    @Test
-    @SmallTest
     @Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
     @Feature({"Android-TabSwitcher"})
     @UiThreadTest
@@ -616,25 +394,6 @@
 
     @Test
     @MediumTest
-    @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE, RESTRICTION_TYPE_NON_LOW_END_DEVICE})
-    @Feature({"Android-TabSwitcher"})
-    // clang-format off
-    @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
-    @Features.EnableFeatures({ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID})
-    @Features.DisableFeatures({ChromeFeatureList.TAB_GROUPS_ANDROID,
-            ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID})
-    public void testStartSurfaceLayout_Disabled_HighEndPhone() throws Exception {
-        // clang-format on
-        verifyStackLayoutEnabled();
-
-        // Verify accessibility
-        TabUiTestHelper.finishActivity(mActivityTestRule.getActivity());
-        setAccessibilityEnabledForTesting(true);
-        verifyOverviewListLayoutEnabled();
-    }
-
-    @Test
-    @MediumTest
     @Restriction({UiRestriction.RESTRICTION_TYPE_PHONE})
     @Feature({"Android-TabSwitcher"})
     // clang-format off
@@ -744,11 +503,8 @@
     @Test
     @MediumTest
     @DisableIf.Build(sdk_is_greater_than = N_MR1, message = "crbug.com/1139943")
-    @ParameterAnnotations.UseMethodParameter(GridTabSwitcherParams.class)
-    public void testLayoutObserverNotification_ShowAndHide_TabSwitcher(boolean isGridTabSwitcher)
-            throws TimeoutException {
-        CachedFeatureFlags.setForTesting(
-                ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID, isGridTabSwitcher);
+    @Features.EnableFeatures({ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID})
+    public void testLayoutObserverNotification_ShowAndHide_TabSwitcher() throws TimeoutException {
         LayoutObserverCallbackHelper startedShowingCallback = new LayoutObserverCallbackHelper();
         LayoutObserverCallbackHelper finishedShowingCallback = new LayoutObserverCallbackHelper();
         LayoutObserverCallbackHelper startedHidingCallback = new LayoutObserverCallbackHelper();
@@ -798,7 +554,6 @@
         startedShowingCallback.waitForCallback(2);
         Assert.assertEquals(LayoutType.BROWSING, startedShowingCallback.layoutType);
 
-        finishedShowingCallback.waitForCallback(1);
         Assert.assertEquals(LayoutType.BROWSING, finishedShowingCallback.layoutType);
     }
 
@@ -972,20 +727,6 @@
     }
 
     /**
-     * Verify {@link StackLayout} is in used. The {@link StackLayout} is used when
-     * ChromeFeatureList.TAB_GROUPS_ANDROID or ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID is disabled
-     * in high end phone.
-     */
-    private void verifyStackLayoutEnabled() {
-        launchedChromeAndEnterTabSwitcher();
-
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Layout activeLayout = getActiveLayout();
-            Assert.assertTrue(activeLayout instanceof StackLayout);
-        });
-    }
-
-    /**
      * Verify the {@link OverviewListLayout} is in used. The {@link OverviewListLayout} is used when
      * accessibility is turned on. It is also used for low end device.
      */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/MockResourcesForLayout.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/MockResourcesForLayout.java
index ae50eb4..6d5049dc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/MockResourcesForLayout.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/layouts/MockResourcesForLayout.java
@@ -33,15 +33,8 @@
 
     public MockResourcesForLayout(Resources resources) {
         mValidResources = resources;
-        mFloats.put(R.dimen.over_scroll_slide, 10.0f);
-        mFloats.put(R.dimen.tabswitcher_border_frame_padding_left, 6.f);
-        mFloats.put(R.dimen.tabswitcher_border_frame_padding_top, 50.f);
         mFloats.put(org.chromium.chrome.R.dimen.compositor_tab_title_text_size, 13.0f);
         mIntegers.put(R.color.tab_switcher_background, 0xFF111111);
-        mFloats.put(R.dimen.over_scroll, 75.0f);
-        mIntegers.put(R.integer.over_scroll_angle, 15);
-        mFloats.put(R.dimen.even_out_scrolling, 400.0f);
-        mFloats.put(R.dimen.min_spacing, 120.0f);
         mFloats.put(R.dimen.swipe_commit_distance, 120.0f);
         mFloats.put(R.dimen.toolbar_swipe_space_between_tabs, 30.0f);
         mFloats.put(R.dimen.toolbar_swipe_commit_distance, 90.0f);
@@ -51,16 +44,8 @@
         mFloats.put(R.dimen.tab_title_favicon_start_padding, 16.0f);
         mFloats.put(R.dimen.tab_title_favicon_end_padding, 7.0f);
         mFloats.put(org.chromium.chrome.R.dimen.compositor_tab_title_favicon_size, 16.0f);
-        mFloats.put(R.dimen.stacked_tab_visible_size, 4.0f);
-        mFloats.put(R.dimen.stack_buffer_width, 5.0f);
-        mFloats.put(R.dimen.stack_buffer_height, 5.0f);
         mFloats.put(org.chromium.chrome.R.dimen.compositor_button_slop, 20.0f);
         mFloats.put(R.dimen.accessibility_tab_height, 65.f);
-        mFloats.put(R.dimen.tabswitcher_border_frame_padding_left, 6.f);
-        mFloats.put(R.dimen.tabswitcher_border_frame_padding_top, 50.f);
-        mFloats.put(R.dimen.tabswitcher_border_frame_transparent_top, 3.f);
-        mFloats.put(R.dimen.tabswitcher_border_frame_transparent_side, 2.f);
-        mFloats.put(R.dimen.open_new_tab_animation_y_translation, -20.f);
         mBooleans.put(org.chromium.chrome.R.bool.compositor_tab_title_fake_bold_text, true);
         mStrings.put(R.string.tab_loading_default_title, "Loading...");
         mFloats.put(org.chromium.chrome.R.dimen.overlay_panel_bar_height, 56.f);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
index 98b9235..0c5d442 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -84,7 +84,7 @@
 import org.chromium.base.test.util.Feature;
 import org.chromium.base.test.util.Restriction;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeApplicationImpl;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.TabsOpenedFromExternalAppTest;
@@ -3113,7 +3113,7 @@
     }
 
     private SessionDataHolder getSessionDataHolder() {
-        return ChromeApplication.getComponent().resolveSessionDataHolder();
+        return ChromeApplicationImpl.getComponent().resolveSessionDataHolder();
     }
 
     private CustomTabIntentDataProvider getCustomTabIntentDataProvider() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java
index 7bb59ad..302a506 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/explore_sites/ExploreSitesPageTest.java
@@ -5,8 +5,7 @@
 package org.chromium.chrome.browser.explore_sites;
 
 import static androidx.test.espresso.Espresso.onView;
-
-import static org.hamcrest.Matchers.instanceOf;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
 
 import android.os.SystemClock;
 
@@ -136,7 +135,7 @@
     @Features.EnableFeatures(ChromeFeatureList.EXPLORE_SITES)
     public void testScrolledLayout_withBack() throws Exception {
         final int scrollPosition = 2;
-        onView(instanceOf(RecyclerView.class))
+        onView(withId(R.id.feed_stream_recycler_view))
                 .perform(RecyclerViewActions.scrollToPosition(scrollPosition));
         mRenderTestRule.render(mRecyclerView, "recycler_layout");
         Assert.assertEquals(scrollPosition, getFirstVisiblePosition());
@@ -156,7 +155,8 @@
     @Features.EnableFeatures(ChromeFeatureList.EXPLORE_SITES)
     @ParameterAnnotations.UseMethodParameter(NightModeTestUtils.NightModeParams.class)
     public void testInitialLayout(boolean nightModeEnabled) throws Exception {
-        onView(instanceOf(RecyclerView.class)).perform(RecyclerViewActions.scrollToPosition(0));
+        onView(withId(R.id.explore_sites_category_recycler))
+                .perform(RecyclerViewActions.scrollToPosition(0));
         mRenderTestRule.render(mRecyclerView, "initial_layout");
     }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java
index ba1be3b..1082083 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/gesturenav/NavigationHandlerTest.java
@@ -21,12 +21,15 @@
 
 import org.chromium.base.ActivityState;
 import org.chromium.base.ApplicationStatus;
+import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Criteria;
 import org.chromium.base.test.util.CriteriaHelper;
 import org.chromium.base.test.util.Restriction;
-import org.chromium.chrome.browser.compositor.layouts.OverviewModeController;
+import org.chromium.chrome.browser.compositor.layouts.LayoutManagerChrome;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.layouts.LayoutStateProvider;
+import org.chromium.chrome.browser.layouts.LayoutType;
 import org.chromium.chrome.browser.layouts.animation.CompositorAnimationHandler;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabLaunchType;
@@ -43,6 +46,8 @@
 import org.chromium.ui.base.PageTransition;
 import org.chromium.ui.test.util.UiRestriction;
 
+import java.util.concurrent.TimeoutException;
+
 /**
  * Tests {@link NavigationHandler} navigating back/forward using overscroll history navigation.
  */
@@ -273,7 +278,7 @@
     @Test
     @SmallTest
     @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
-    public void testEdgeSwipeIsNoopInTabSwitcher() {
+    public void testEdgeSwipeIsNoopInTabSwitcher() throws TimeoutException {
         mActivityTestRule.loadUrl(UrlConstants.NTP_URL);
         mActivityTestRule.loadUrl(UrlConstants.RECENT_TABS_URL);
         setTabSwitcherModeAndWait(true);
@@ -289,12 +294,27 @@
      * Enter or exit the tab switcher with animations and wait for the scene to change.
      * @param inSwitcher Whether to enter or exit the tab switcher.
      */
-    private void setTabSwitcherModeAndWait(boolean inSwitcher) {
-        OverviewModeController controller = mActivityTestRule.getActivity().getLayoutManager();
+    private void setTabSwitcherModeAndWait(boolean inSwitcher) throws TimeoutException {
+        CallbackHelper switchHelper = new CallbackHelper();
+        LayoutStateProvider.LayoutStateObserver layoutObserver =
+                new LayoutStateProvider.LayoutStateObserver() {
+                    @Override
+                    public void onFinishedShowing(int layoutType) {
+                        if ((inSwitcher && layoutType == LayoutType.TAB_SWITCHER)
+                                || (!inSwitcher && layoutType == LayoutType.BROWSING)) {
+                            switchHelper.notifyCalled();
+                        }
+                    }
+                };
+
+        LayoutManagerChrome controller = mActivityTestRule.getActivity().getLayoutManager();
+        controller.addObserver(layoutObserver);
         if (inSwitcher) {
             TestThreadUtils.runOnUiThreadBlocking(() -> controller.showOverview(false));
         } else {
             TestThreadUtils.runOnUiThreadBlocking(() -> controller.hideOverview(false));
         }
+        switchHelper.waitForCallback(0);
+        controller.removeObserver(layoutObserver);
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ChromeTabModalPresenterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ChromeTabModalPresenterTest.java
index 6a03c35..ac4937ad 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ChromeTabModalPresenterTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/modaldialog/ChromeTabModalPresenterTest.java
@@ -5,6 +5,7 @@
 package org.chromium.chrome.browser.modaldialog;
 
 import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.Espresso.pressBack;
 import static androidx.test.espresso.action.ViewActions.click;
 import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
 import static androidx.test.espresso.assertion.ViewAssertions.matches;
@@ -225,7 +226,7 @@
 
         // Exit overview mode. The first dialog should be showing again.
         int callCount = mTestObserver.onTabInteractabilityChangedCallback.getCallCount();
-        onView(withId(R.id.tab_switcher_mode_tab_switcher_button)).perform(click());
+        pressBack();
         mTestObserver.onTabInteractabilityChangedCallback.waitForCallback(callCount);
 
         checkPendingSize(mManager, ModalDialogType.TAB, 1);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
index e392b3a..30faa66 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/NewTabPageTest.java
@@ -10,7 +10,6 @@
 import static androidx.test.espresso.matcher.ViewMatchers.withId;
 
 import static org.hamcrest.Matchers.allOf;
-import static org.hamcrest.Matchers.instanceOf;
 import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.eq;
@@ -26,7 +25,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 
-import androidx.recyclerview.widget.RecyclerView;
 import androidx.test.espresso.contrib.RecyclerViewActions;
 import androidx.test.filters.LargeTest;
 import androidx.test.filters.MediumTest;
@@ -192,7 +190,7 @@
     @Features.DisableFeatures(ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY)
     public void testRender_SignInPromoLegacy() throws Exception {
         // Scroll to the sign in promo in case it is not visible.
-        onView(instanceOf(RecyclerView.class))
+        onView(withId(R.id.feed_stream_recycler_view))
                 .perform(RecyclerViewActions.scrollToPosition(SIGNIN_PROMO_POSITION));
         mRenderTestRule.render(mNtp.getCoordinatorForTesting().getSignInPromoViewForTesting(),
                 "sign_in_promo_legacy");
@@ -204,7 +202,7 @@
     @Features.EnableFeatures(ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY)
     public void testRender_SignInPromoNoAccounts() throws Exception {
         // Scroll to the sign in promo in case it is not visible.
-        onView(instanceOf(RecyclerView.class))
+        onView(withId(R.id.feed_stream_recycler_view))
                 .perform(RecyclerViewActions.scrollToPosition(SIGNIN_PROMO_POSITION));
         mRenderTestRule.render(
                 mNtp.getCoordinatorForTesting().getSignInPromoViewForTesting(), "sign_in_promo");
@@ -218,7 +216,7 @@
         mAccountManagerTestRule.addAccount(mAccountManagerTestRule.createProfileDataFromName(
                 AccountManagerTestRule.TEST_ACCOUNT_EMAIL));
         // Scroll to the sign in promo in case it is not visible.
-        onView(instanceOf(RecyclerView.class))
+        onView(withId(R.id.feed_stream_recycler_view))
                 .perform(RecyclerViewActions.scrollToPosition(SIGNIN_PROMO_POSITION));
         mRenderTestRule.render(mNtp.getCoordinatorForTesting().getSignInPromoViewForTesting(),
                 "sign_in_promo_with_account");
@@ -231,7 +229,7 @@
     public void testRender_SyncPromo() throws Exception {
         mAccountManagerTestRule.addTestAccountThenSignin();
         // Scroll to the sign in promo in case it is not visible.
-        onView(instanceOf(RecyclerView.class))
+        onView(withId(R.id.feed_stream_recycler_view))
                 .perform(RecyclerViewActions.scrollToPosition(SIGNIN_PROMO_POSITION));
         mRenderTestRule.render(
                 mNtp.getCoordinatorForTesting().getSignInPromoViewForTesting(), "sync_promo");
@@ -242,7 +240,7 @@
     @Feature({"NewTabPage", "FeedNewTabPage", "RenderTest"})
     public void testRender_ArticleSectionHeader() throws Exception {
         // Scroll to the article section header in case it is not visible.
-        onView(instanceOf(RecyclerView.class))
+        onView(withId(R.id.feed_stream_recycler_view))
                 .perform(RecyclerViewActions.scrollToPosition(ARTICLE_SECTION_HEADER_POSITION));
         waitForView((ViewGroup) mNtp.getView(), allOf(withId(R.id.header_title), isDisplayed()));
         View view = mNtp.getCoordinatorForTesting().getSectionHeaderViewForTesting();
@@ -250,7 +248,7 @@
         mRenderTestRule.render(view, "expandable_header_expanded");
 
         // Toggle header on the current tab.
-        onView(instanceOf(RecyclerView.class))
+        onView(withId(R.id.feed_stream_recycler_view))
                 .perform(RecyclerViewActions.scrollToPosition(ARTICLE_SECTION_HEADER_POSITION));
         waitForView((ViewGroup) mNtp.getView(), allOf(withId(R.id.header_title), isDisplayed()));
         onView(withId(R.id.header_title)).perform(click());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoTest.java
index 464fb86..d56dbee 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoTest.java
@@ -13,7 +13,6 @@
 import static androidx.test.espresso.matcher.ViewMatchers.withId;
 
 import static org.hamcrest.Matchers.allOf;
-import static org.hamcrest.Matchers.instanceOf;
 
 import static org.chromium.chrome.test.util.ViewUtils.waitForView;
 
@@ -21,7 +20,6 @@
 import android.view.View;
 import android.view.ViewGroup;
 
-import androidx.recyclerview.widget.RecyclerView;
 import androidx.test.espresso.contrib.RecyclerViewActions;
 import androidx.test.espresso.intent.Intents;
 import androidx.test.filters.MediumTest;
@@ -69,8 +67,7 @@
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @EnableFeatures({ChromeFeatureList.ENHANCED_PROTECTION_PROMO_CARD,
         ChromeFeatureList.SAFE_BROWSING_ENHANCED_PROTECTION_ENABLED})
-@Features.
-DisableFeatures({ChromeFeatureList.QUERY_TILES, ChromeFeatureList.REPORT_FEED_USER_ACTIONS})
+@Features.DisableFeatures({ChromeFeatureList.QUERY_TILES})
 public class EnhancedProtectionPromoTest {
     private static final String METRICS_ENHANCED_PROTECTION_PROMO =
             "NewTabPage.Promo.EnhancedProtectionPromo";
@@ -200,7 +197,7 @@
     }
 
     private void scrollToEnhancedProtectionPromo() {
-        onView(instanceOf(RecyclerView.class))
+        onView(withId(R.id.feed_stream_recycler_view))
                 .perform(RecyclerViewActions.scrollToPosition(NTP_HEADER_POSITION + 1));
         waitForView((ViewGroup) mActivityTestRule.getActivity().findViewById(
                             R.id.enhanced_protection_promo),
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelMergingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelMergingTest.java
index 74a2d78..484b28d 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelMergingTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabModelMergingTest.java
@@ -26,6 +26,7 @@
 import org.chromium.base.ActivityState;
 import org.chromium.base.ApplicationStatus;
 import org.chromium.base.ApplicationStatus.ActivityStateListener;
+import org.chromium.base.ThreadUtils;
 import org.chromium.base.test.util.CallbackHelper;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Criteria;
@@ -462,6 +463,10 @@
     @LargeTest
     @Feature({"TabPersistentStore", "MultiWindow"})
     public void testMergeWithNoTabs() {
+        // Enter the tab switcher before closing all tabs with grid tab switcher enabled, otherwise
+        // the activity is killed and the test fails.
+        ThreadUtils.runOnUiThreadBlocking(() -> mActivity1.getLayoutManager().showOverview(false));
+
         // Close all tabs and wait for the callback.
         ChromeTabUtils.closeAllTabs(InstrumentationRegistry.getInstrumentation(), mActivity1);
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetControllerTest.java
index 5613cf1..fc15cdc 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetControllerTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/widget/bottomsheet/BottomSheetControllerTest.java
@@ -218,7 +218,17 @@
     @Feature({"BottomSheetController"})
     public void testSheetPeekAfterTabSwitcher() throws TimeoutException {
         requestContentInSheet(mLowPriorityContent, true);
+        CallbackHelper peekCallbackHelper = new CallbackHelper();
+        mSheetController.addObserver(new EmptyBottomSheetObserver() {
+            @Override
+            public void onSheetStateChanged(int newState) {
+                if (newState == BottomSheetController.SheetState.PEEK) {
+                    peekCallbackHelper.notifyCalled();
+                }
+            }
+        });
         enterAndExitTabSwitcher();
+        peekCallbackHelper.waitForCallback(0);
         assertEquals("The bottom sheet should be peeking.", BottomSheetController.SheetState.PEEK,
                 mSheetController.getSheetState());
         assertEquals("The bottom sheet is showing incorrect content.", mLowPriorityContent,
@@ -236,6 +246,14 @@
 
         requestContentInSheet(mLowPriorityContent, true);
 
+        CallbackHelper contentChangeHelper = new CallbackHelper();
+        mSheetController.addObserver(new EmptyBottomSheetObserver() {
+            @Override
+            public void onSheetContentChanged(BottomSheetContent newContent) {
+                contentChangeHelper.notifyCalled();
+            }
+        });
+
         // Enter the tab switcher and select a different tab.
         ThreadUtils.runOnUiThreadBlocking(() -> {
             mActivity.getLayoutManager().showOverview(false);
@@ -248,6 +266,7 @@
             mTestSupport.endAllAnimations();
         });
 
+        contentChangeHelper.waitForCallback(0);
         assertEquals("The bottom sheet still should be hidden.",
                 BottomSheetController.SheetState.HIDDEN, mSheetController.getSheetState());
         assertEquals("The bottom sheet is showing incorrect content.", null,
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index d9dd9642..10d0ca4 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -360,6 +360,9 @@
   <message name="IDS_CELLULAR_SETUP_ESIM_PAGE_SCAN_QR_CODE_LOADING" desc="Label informing the user that the activation code is currently being verified.">
     Verifying activation code...
   </message>
+  <message name="IDS_CELLULAR_SETUP_ESIM_PAGE_SCAN_QR_CODE_INVALID" desc="Label informing the user that the code used to install an eSIM profile is invalid.">
+    Invalid code. Please try again.
+  </message>
   <message name="IDS_CELLULAR_SETUP_ESTABLISH_NETWORK_CONNECTION" desc="Message, informing user that a network connection is being established during cellular setup">
     Establishing network connection ...
   </message>
diff --git a/chrome/app/chromeos_strings_grdp/IDS_CELLULAR_SETUP_ESIM_PAGE_SCAN_QR_CODE_INVALID.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_CELLULAR_SETUP_ESIM_PAGE_SCAN_QR_CODE_INVALID.png.sha1
new file mode 100644
index 0000000..9425aab0
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_CELLULAR_SETUP_ESIM_PAGE_SCAN_QR_CODE_INVALID.png.sha1
@@ -0,0 +1 @@
+6cbe893ed14f8502c1f29966a600cb52e0f4df41
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 41dc90f..8685553 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -574,6 +574,8 @@
     "history/web_history_service_factory.h",
     "history_clusters/history_clusters_tab_helper.cc",
     "history_clusters/history_clusters_tab_helper.h",
+    "history_clusters/memories_service_factory.cc",
+    "history_clusters/memories_service_factory.h",
     "icon_loader.cc",
     "icon_loader.h",
     "icon_manager.cc",
@@ -2072,7 +2074,6 @@
     "//components/leveldb_proto",
     "//components/lookalikes/core",
     "//components/lookalikes/core:features",
-    "//components/memories/content",
     "//components/memories/core",
     "//components/metrics:call_stack_profile_collector",
     "//components/metrics:call_stack_profile_params",
@@ -6920,6 +6921,8 @@
       "extensions/test_blocklist.h",
       "extensions/test_blocklist_state_fetcher.cc",
       "extensions/test_blocklist_state_fetcher.h",
+      "extensions/test_extension_message_bubble_delegate.cc",
+      "extensions/test_extension_message_bubble_delegate.h",
       "extensions/test_extension_service.cc",
       "extensions/test_extension_service.h",
       "extensions/test_extension_system.cc",
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index c36b307..bde803a 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -171,7 +171,6 @@
   "+components/login",
   "+components/media_message_center",
   "+components/media_router/browser",
-  "+components/memories/content",
   "+components/memories/core",
   "+components/messages/android",
   "+components/metal_util",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 78e04b0b..a65db7c 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1915,6 +1915,19 @@
 #endif  // OS_ANDROID
 
 #if defined(OS_ANDROID)
+const FeatureEntry::FeatureParam kAddToHomescreen_UseTextBubble[] = {
+    {"use_text_bubble", "true"}};
+const FeatureEntry::FeatureParam kAddToHomescreen_UseMessage[] = {
+    {"use_message", "true"}};
+
+const FeatureEntry::FeatureVariation kAddToHomescreenIPHVariations[] = {
+    {"Use Text Bubble", kAddToHomescreen_UseTextBubble,
+     base::size(kAddToHomescreen_UseTextBubble), nullptr},
+    {"Use Message", kAddToHomescreen_UseMessage,
+     base::size(kAddToHomescreen_UseMessage), nullptr}};
+#endif
+
+#if defined(OS_ANDROID)
 const FeatureEntry::FeatureParam
     kAutofillUseMobileLabelDisambiguationShowAll[] = {
         {autofill::features::kAutofillUseMobileLabelDisambiguationParameterName,
@@ -3651,6 +3664,11 @@
      flag_descriptions::kSystemKeyboardLockDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(features::kSystemKeyboardLock)},
 #if defined(OS_ANDROID)
+    {"add-to-homescreen-iph", flag_descriptions::kAddToHomescreenIPHName,
+     flag_descriptions::kAddToHomescreenIPHDescription, kOsAndroid,
+     FEATURE_WITH_PARAMS_VALUE_TYPE(chrome::android::kAddToHomescreenIPH,
+                                    kAddToHomescreenIPHVariations,
+                                    "AddToHomescreen")},
     {"offline-pages-live-page-sharing",
      flag_descriptions::kOfflinePagesLivePageSharingName,
      flag_descriptions::kOfflinePagesLivePageSharingDescription, kOsAndroid,
@@ -3844,9 +3862,6 @@
      flag_descriptions::kXsurfaceMetricsReportingName,
      flag_descriptions::kXsurfaceMetricsReportingDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(feed::kWebFeed)},
-    {"report-feed-user-actions", flag_descriptions::kReportFeedUserActionsName,
-     flag_descriptions::kReportFeedUserActionsDescription, kOsAndroid,
-     FEATURE_VALUE_TYPE(feed::kReportFeedUserActions)},
     {"interest-feed-v1-clicks-and-views-cond-upload",
      flag_descriptions::kInterestFeedV1ClickAndViewActionsConditionalUploadName,
      flag_descriptions::
@@ -5715,11 +5730,6 @@
      flag_descriptions::kStorageAccessAPIDescription, kOsAll,
      FEATURE_VALUE_TYPE(blink::features::kStorageAccessAPI)},
 
-    {"same-site-by-default-cookies",
-     flag_descriptions::kSameSiteByDefaultCookiesName,
-     flag_descriptions::kSameSiteByDefaultCookiesDescription, kOsAll,
-     FEATURE_VALUE_TYPE(net::features::kSameSiteByDefaultCookies)},
-
     {"enable-removing-all-third-party-cookies",
      flag_descriptions::kEnableRemovingAllThirdPartyCookiesName,
      flag_descriptions::kEnableRemovingAllThirdPartyCookiesDescription,
@@ -5727,11 +5737,6 @@
      FEATURE_VALUE_TYPE(
          browsing_data::features::kEnableRemovingAllThirdPartyCookies)},
 
-    {"cookies-without-same-site-must-be-secure",
-     flag_descriptions::kCookiesWithoutSameSiteMustBeSecureName,
-     flag_descriptions::kCookiesWithoutSameSiteMustBeSecureDescription, kOsAll,
-     FEATURE_VALUE_TYPE(net::features::kCookiesWithoutSameSiteMustBeSecure)},
-
 #if defined(OS_MAC)
     {"enterprise-reporting-api-keychain-recreation",
      flag_descriptions::kEnterpriseReportingApiKeychainRecreationName,
diff --git a/chrome/browser/ash/login/chrome_restart_request.cc b/chrome/browser/ash/login/chrome_restart_request.cc
index a1ddbb1..1e362537 100644
--- a/chrome/browser/ash/login/chrome_restart_request.cc
+++ b/chrome/browser/ash/login/chrome_restart_request.cc
@@ -271,7 +271,8 @@
 class ChromeRestartRequest
     : public base::SupportsWeakPtr<ChromeRestartRequest> {
  public:
-  explicit ChromeRestartRequest(const std::vector<std::string>& argv);
+  explicit ChromeRestartRequest(const std::vector<std::string>& argv,
+                                RestartChromeReason reson);
   ~ChromeRestartRequest();
 
   // Starts the request.
@@ -285,13 +286,16 @@
   void OnRestartJob(base::ScopedFD local_auth_fd, bool result);
 
   const std::vector<std::string> argv_;
+  const RestartChromeReason reason_;
+
   base::OneShotTimer timer_;
 
   DISALLOW_COPY_AND_ASSIGN(ChromeRestartRequest);
 };
 
-ChromeRestartRequest::ChromeRestartRequest(const std::vector<std::string>& argv)
-    : argv_(argv) {}
+ChromeRestartRequest::ChromeRestartRequest(const std::vector<std::string>& argv,
+                                           RestartChromeReason reason)
+    : argv_(argv), reason_(reason) {}
 
 ChromeRestartRequest::~ChromeRestartRequest() {}
 
@@ -334,6 +338,7 @@
   // of the socket-pair alive for the duration of the RPC.
   SessionManagerClient::Get()->RestartJob(
       remote_auth_fd.get(), argv_,
+      static_cast<SessionManagerClient::RestartJobReason>(reason_),
       base::BindOnce(&ChromeRestartRequest::OnRestartJob, AsWeakPtr(),
                      std::move(local_auth_fd)));
 }
@@ -377,7 +382,8 @@
   DeriveEnabledFeatures(command_line);
 }
 
-void RestartChrome(const base::CommandLine& command_line) {
+void RestartChrome(const base::CommandLine& command_line,
+                   RestartChromeReason reason) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   BootTimesRecorder::Get()->set_restart_requested();
 
@@ -405,7 +411,7 @@
   }
 
   // ChromeRestartRequest deletes itself after request sent to session manager.
-  (new ChromeRestartRequest(command_line.argv()))->Start();
+  (new ChromeRestartRequest(command_line.argv(), reason))->Start();
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/ash/login/chrome_restart_request.h b/chrome/browser/ash/login/chrome_restart_request.h
index 3e4f11b..4d0353a 100644
--- a/chrome/browser/ash/login/chrome_restart_request.h
+++ b/chrome/browser/ash/login/chrome_restart_request.h
@@ -15,6 +15,15 @@
 
 namespace chromeos {
 
+// Keep in sync with RestartJobReason in
+// chromeos/dbus/session_manager/session_manager_client.h
+enum class RestartChromeReason : uint32_t {
+  // Restart browser for Guest session.
+  kGuest = 0,
+  // Restart browser without user session for headless Chromium.
+  kUserless = 1,
+};
+
 // Determines the `command_line` to be used for the OTR process.
 void GetOffTheRecordCommandLine(const GURL& start_url,
                                 bool is_oobe_completed,
@@ -22,7 +31,10 @@
                                 base::CommandLine* command_line);
 
 // Request session manager to restart chrome with a new command line.
-void RestartChrome(const base::CommandLine& command_line);
+// |reason| - reason to restart chrome with user session (for guest sessions
+// only) or without user session (for headless chrome).
+void RestartChrome(const base::CommandLine& command_line,
+                   RestartChromeReason reason);
 
 }  // namespace chromeos
 
diff --git a/chrome/browser/ash/login/screens/error_screen.cc b/chrome/browser/ash/login/screens/error_screen.cc
index b4e69172..f50fd9f 100644
--- a/chrome/browser/ash/login/screens/error_screen.cc
+++ b/chrome/browser/ash/login/screens/error_screen.cc
@@ -315,7 +315,7 @@
   base::CommandLine command_line(browser_command_line.GetProgram());
   GetOffTheRecordCommandLine(GURL(), StartupUtils::IsOobeCompleted(),
                              browser_command_line, &command_line);
-  RestartChrome(command_line);
+  RestartChrome(command_line, RestartChromeReason::kGuest);
 }
 
 void ErrorScreen::OnPasswordChangeDetected(const UserContext& user_context) {
diff --git a/chrome/browser/ash/login/session/user_session_manager.cc b/chrome/browser/ash/login/session/user_session_manager.cc
index 5038a21..73943c8 100644
--- a/chrome/browser/ash/login/session/user_session_manager.cc
+++ b/chrome/browser/ash/login/session/user_session_manager.cc
@@ -597,7 +597,7 @@
         base::CommandLine::StringVector());
   }
 
-  RestartChrome(command_line);
+  RestartChrome(command_line, RestartChromeReason::kGuest);
 }
 
 scoped_refptr<Authenticator> UserSessionManager::CreateAuthenticator(
diff --git a/chrome/browser/ash/login/ui/oobe_ui_dialog_delegate.cc b/chrome/browser/ash/login/ui/oobe_ui_dialog_delegate.cc
index 993c6420..51e3d70 100644
--- a/chrome/browser/ash/login/ui/oobe_ui_dialog_delegate.cc
+++ b/chrome/browser/ash/login/ui/oobe_ui_dialog_delegate.cc
@@ -21,7 +21,6 @@
 #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
 #include "chrome/browser/ui/ash/ash_util.h"
-#include "chrome/browser/ui/ash/login_screen_client.h"
 #include "chrome/browser/ui/webui/chrome_web_contents_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h"
 #include "chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h"
@@ -106,6 +105,27 @@
         event, GetFocusManager());
   }
 
+  OobeUI* GetOobeUI() {
+    content::WebUI* webui = web_contents()->GetWebUI();
+    if (webui)
+      return static_cast<OobeUI*>(webui->GetController());
+    return nullptr;
+  }
+
+  // Overridden from views::View:
+  void AboutToRequestFocusFromTabTraversal(bool reverse) override {
+    // Return the focus to the web contents.
+    web_contents()->FocusThroughTabTraversal(reverse);
+    GetWidget()->Activate();
+    web_contents()->Focus();
+
+    if (!GetOobeUI())
+      return;
+    CoreOobeView* view = GetOobeUI()->GetCoreOobeView();
+    if (view)
+      view->FocusReturned(reverse);
+  }
+
  private:
   views::UnhandledKeyboardEventHandler unhandled_keyboard_event_handler_;
 };
@@ -214,7 +234,7 @@
     base::WeakPtr<LoginDisplayHostMojo> controller)
     : controller_(controller) {
   set_can_resize(false);
-  keyboard_observer_.Add(ChromeKeyboardControllerClient::Get());
+  keyboard_observer_.Observe(ChromeKeyboardControllerClient::Get());
 
   for (size_t i = 0; i < ash::kLoginAcceleratorDataLength; ++i) {
     if (ash::kLoginAcceleratorData[i].global)
@@ -263,7 +283,7 @@
 
   GetOobeUI()->GetErrorScreen()->MaybeInitCaptivePortalWindowProxy(
       dialog_view_->web_contents());
-  captive_portal_observer_.Add(
+  captive_portal_observer_.Observe(
       GetOobeUI()->GetErrorScreen()->captive_portal_window_proxy());
 }
 
@@ -288,6 +308,14 @@
 }
 
 void OobeUIDialogDelegate::Show() {
+  if (LoginScreenClient::Get()) {
+    scoped_system_tray_focus_observer_ =
+        std::make_unique<base::ScopedObservation<
+            LoginScreenClient, ash::SystemTrayFocusObserver,
+            &LoginScreenClient::AddSystemTrayFocusObserver,
+            &LoginScreenClient::RemoveSystemTrayFocusObserver>>(this);
+    scoped_system_tray_focus_observer_->Observe(LoginScreenClient::Get());
+  }
   widget_->Show();
   if (state_ == ash::OobeDialogState::HIDDEN) {
     SetState(ash::OobeDialogState::GAIA_SIGNIN);
@@ -305,6 +333,7 @@
 }
 
 void OobeUIDialogDelegate::Hide() {
+  scoped_system_tray_focus_observer_.reset();
   if (!widget_)
     return;
   widget_->Hide();
@@ -335,11 +364,8 @@
 }
 
 OobeUI* OobeUIDialogDelegate::GetOobeUI() const {
-  if (dialog_view_) {
-    content::WebUI* webui = dialog_view_->web_contents()->GetWebUI();
-    if (webui)
-      return static_cast<OobeUI*>(webui->GetController());
-  }
+  if (dialog_view_)
+    return dialog_view_->GetOobeUI();
   return nullptr;
 }
 
@@ -443,4 +469,9 @@
   captive_portal_delegate_->Hide();
 }
 
+void OobeUIDialogDelegate::OnFocusLeavingSystemTray(bool reverse) {
+  if (dialog_view_)
+    dialog_view_->AboutToRequestFocusFromTabTraversal(reverse);
+}
+
 }  // namespace chromeos
diff --git a/chrome/browser/ash/login/ui/oobe_ui_dialog_delegate.h b/chrome/browser/ash/login/ui/oobe_ui_dialog_delegate.h
index 39ed4b9..18c3242 100644
--- a/chrome/browser/ash/login/ui/oobe_ui_dialog_delegate.h
+++ b/chrome/browser/ash/login/ui/oobe_ui_dialog_delegate.h
@@ -9,11 +9,13 @@
 
 #include "ash/public/cpp/login_accelerators.h"
 #include "ash/public/cpp/login_types.h"
+#include "ash/public/cpp/system_tray_focus_observer.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
-#include "base/scoped_observer.h"
+#include "base/scoped_observation.h"
 #include "chrome/browser/ash/login/screens/error_screen.h"
 #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h"
+#include "chrome/browser/ui/ash/login_screen_client.h"
 #include "chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.h"
 #include "components/web_modal/web_contents_modal_dialog_host.h"
 #include "ui/views/view_observer.h"
@@ -51,7 +53,8 @@
 class OobeUIDialogDelegate : public ui::WebDialogDelegate,
                              public ChromeKeyboardControllerClient::Observer,
                              public CaptivePortalWindowProxy::Observer,
-                             public views::ViewObserver {
+                             public views::ViewObserver,
+                             public ash::SystemTrayFocusObserver {
  public:
   explicit OobeUIDialogDelegate(base::WeakPtr<LoginDisplayHostMojo> controller);
   ~OobeUIDialogDelegate() override;
@@ -118,6 +121,9 @@
   void OnBeforeCaptivePortalShown() override;
   void OnAfterCaptivePortalHidden() override;
 
+  // ash::SystemTrayFocusObserver:
+  void OnFocusLeavingSystemTray(bool reverse) override;
+
   base::WeakPtr<LoginDisplayHostMojo> controller_;
 
   base::WeakPtr<CaptivePortalDialogDelegate> captive_portal_delegate_;
@@ -130,12 +136,20 @@
   // Reference to dialog view stored in widget_.
   OobeWebDialogView* dialog_view_ = nullptr;
 
-  ScopedObserver<ChromeKeyboardControllerClient,
-                 ChromeKeyboardControllerClient::Observer>
+  base::ScopedObservation<ChromeKeyboardControllerClient,
+                          ChromeKeyboardControllerClient::Observer>
       keyboard_observer_{this};
-  ScopedObserver<CaptivePortalWindowProxy, CaptivePortalWindowProxy::Observer>
+  base::ScopedObservation<CaptivePortalWindowProxy,
+                          CaptivePortalWindowProxy::Observer>
       captive_portal_observer_{this};
 
+  std::unique_ptr<base::ScopedObservation<
+      LoginScreenClient,
+      ash::SystemTrayFocusObserver,
+      &LoginScreenClient::AddSystemTrayFocusObserver,
+      &LoginScreenClient::RemoveSystemTrayFocusObserver>>
+      scoped_system_tray_focus_observer_;
+
   std::map<ui::Accelerator, ash::LoginAcceleratorAction> accel_map_;
   ash::OobeDialogState state_ = ash::OobeDialogState::HIDDEN;
 
diff --git a/chrome/browser/autofill/credit_card_accessory_controller_impl_unittest.cc b/chrome/browser/autofill/credit_card_accessory_controller_impl_unittest.cc
index 7b4a564..56f850e 100644
--- a/chrome/browser/autofill/credit_card_accessory_controller_impl_unittest.cc
+++ b/chrome/browser/autofill/credit_card_accessory_controller_impl_unittest.cc
@@ -16,7 +16,7 @@
 #include "components/autofill/core/browser/test_autofill_driver.h"
 #include "components/autofill/core/browser/test_personal_data_manager.h"
 #include "components/autofill/core/common/form_data.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/strings/grit/components_strings.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/autofill/form_structure_browsertest.cc b/chrome/browser/autofill/form_structure_browsertest.cc
index 15a8f41..dd4172d3 100644
--- a/chrome/browser/autofill/form_structure_browsertest.cc
+++ b/chrome/browser/autofill/form_structure_browsertest.cc
@@ -31,7 +31,7 @@
 #include "components/autofill/core/browser/form_structure.h"
 #include "components/autofill/core/browser/pattern_provider/pattern_configuration_parser.h"
 #include "components/autofill/core/common/autofill_features.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test.h"
 #include "net/http/http_status_code.h"
diff --git a/chrome/browser/captive_portal/captive_portal_browsertest.cc b/chrome/browser/captive_portal/captive_portal_browsertest.cc
index 961375b2..c62b173 100644
--- a/chrome/browser/captive_portal/captive_portal_browsertest.cc
+++ b/chrome/browser/captive_portal/captive_portal_browsertest.cc
@@ -879,10 +879,9 @@
     CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     content::BrowserContext::GetDefaultStoragePartition(browser()->profile())
         ->GetURLLoaderFactoryForBrowserProcess()
-        ->CreateLoaderAndStart(std::move(job.receiver), job.routing_id,
-                               job.request_id, job.options,
-                               std::move(job.url_request), job.client.Unbind(),
-                               job.traffic_annotation);
+        ->CreateLoaderAndStart(std::move(job.receiver), job.request_id,
+                               job.options, std::move(job.url_request),
+                               job.client.Unbind(), job.traffic_annotation);
   }
 
   // Abandon all active kMockHttps* requests.  |expected_num_jobs|
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index c526332..7aaf5cf 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -4657,7 +4657,6 @@
   // network::mojom::URLLoaderFactory:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/chrome/browser/chromeos/fileapi/external_file_url_loader_factory.cc b/chrome/browser/chromeos/fileapi/external_file_url_loader_factory.cc
index dc2a9f9..c1e9f1b 100644
--- a/chrome/browser/chromeos/fileapi/external_file_url_loader_factory.cc
+++ b/chrome/browser/chromeos/fileapi/external_file_url_loader_factory.cc
@@ -353,7 +353,6 @@
 
 void ExternalFileURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> loader,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
diff --git a/chrome/browser/chromeos/fileapi/external_file_url_loader_factory.h b/chrome/browser/chromeos/fileapi/external_file_url_loader_factory.h
index 29fbf04..93dc250 100644
--- a/chrome/browser/chromeos/fileapi/external_file_url_loader_factory.h
+++ b/chrome/browser/chromeos/fileapi/external_file_url_loader_factory.h
@@ -45,7 +45,6 @@
   // network::mojom::URLLoaderFactory:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/chrome/browser/chromeos/fileapi/external_file_url_loader_factory_unittest.cc b/chrome/browser/chromeos/fileapi/external_file_url_loader_factory_unittest.cc
index 520ee9f4..1a0af3e 100644
--- a/chrome/browser/chromeos/fileapi/external_file_url_loader_factory_unittest.cc
+++ b/chrome/browser/chromeos/fileapi/external_file_url_loader_factory_unittest.cc
@@ -96,9 +96,9 @@
       const network::ResourceRequest& resource_request) {
     mojo::PendingRemote<network::mojom::URLLoader> loader;
     url_loader_factory_->CreateLoaderAndStart(
-        loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-        0 /* request_id */, network::mojom::kURLLoadOptionNone,
-        resource_request, client->CreateRemote(),
+        loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+        network::mojom::kURLLoadOptionNone, resource_request,
+        client->CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
     return loader;
   }
diff --git a/chrome/browser/component_updater/crl_set_component_installer_unittest.cc b/chrome/browser/component_updater/crl_set_component_installer_unittest.cc
index 69046a6..31fce5f 100644
--- a/chrome/browser/component_updater/crl_set_component_installer_unittest.cc
+++ b/chrome/browser/component_updater/crl_set_component_installer_unittest.cc
@@ -67,7 +67,7 @@
         loader_factory.BindNewPipeAndPassReceiver(), std::move(params));
     loader_.reset();
     loader_factory->CreateLoaderAndStart(
-        loader_.BindNewPipeAndPassReceiver(), 1, 1,
+        loader_.BindNewPipeAndPassReceiver(), 1,
         network::mojom::kURLLoadOptionSendSSLInfoWithResponse |
             network::mojom::kURLLoadOptionSendSSLInfoForCertificateError,
         request, client_->CreateRemote(),
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
index 86160ab..886988047 100644
--- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -1828,7 +1828,7 @@
   network::ResourceRequest resource_request;
   resource_request.url = embedded_test_server()->GetURL("/hung");
   factory->CreateLoaderAndStart(
-      loader.InitWithNewPipeAndPassReceiver(), 0, 0,
+      loader.InitWithNewPipeAndPassReceiver(), 0,
       network::mojom::kURLLoadOptionNone, resource_request,
       client.CreateRemote(),
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
diff --git a/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc b/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc
index 670e8b0..fd7ecf3 100644
--- a/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc
+++ b/chrome/browser/extensions/extension_message_bubble_controller_unittest.cc
@@ -28,6 +28,7 @@
 #include "chrome/browser/extensions/proxy_overridden_bubble_delegate.h"
 #include "chrome/browser/extensions/settings_api_bubble_delegate.h"
 #include "chrome/browser/extensions/suspicious_extension_bubble_delegate.h"
+#include "chrome/browser/extensions/test_extension_message_bubble_delegate.h"
 #include "chrome/browser/extensions/test_extension_system.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_model.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_model_factory.h"
@@ -371,7 +372,6 @@
     // global variables, they can be shared between tests and cause
     // unpredicatable behavior.
     DevModeBubbleDelegate(profile()).ClearProfileSetForTesting();
-    NtpOverriddenBubbleDelegate(profile()).ClearProfileSetForTesting();
     ProxyOverriddenBubbleDelegate(profile()).ClearProfileSetForTesting();
     for (auto type : {BUBBLE_TYPE_HOME_PAGE, BUBBLE_TYPE_SEARCH_ENGINE,
                       BUBBLE_TYPE_STARTUP_PAGES}) {
@@ -430,24 +430,27 @@
 // TODO(https://crbug.com/1177315): This test is flaky. When the flake is fixed,
 // re-enable this test.
 TEST_F(ExtensionMessageBubbleTest,
-       DISABLED_BubbleCorrectlyReshowsOnDeactivationDismissal) {
+       DISABLED_BubbleDoesNotAcknowledgeExtensionOnDeactivationDismissal) {
   Init();
 
-  ASSERT_TRUE(
-      LoadExtensionOverridingNtp("1", kId1, ManifestLocation::kInternal));
-  ASSERT_TRUE(
-      LoadExtensionOverridingNtp("2", kId2, ManifestLocation::kInternal));
-  std::unique_ptr<TestExtensionMessageBubbleController> controller(
-      new TestExtensionMessageBubbleController(
-          new NtpOverriddenBubbleDelegate(browser()->profile()), browser()));
+  scoped_refptr<const Extension> extension = ExtensionBuilder("Alpha").Build();
+  service_->AddExtension(extension.get());
+  auto test_delegate = std::make_unique<TestExtensionMessageBubbleDelegate>(
+      browser()->profile());
+  test_delegate->IncludeExtensionId(extension->id());
+
+  auto* test_delegate_raw = test_delegate.get();
+  auto controller = std::make_unique<TestExtensionMessageBubbleController>(
+      test_delegate.release(), browser());
+
   controller->SetIsActiveBubble();
 
-  // The list will contain one enabled unpacked extension (ext 2).
+  // The list will contain the single extension.
   EXPECT_TRUE(controller->ShouldShow());
-  std::vector<std::u16string> override_extensions =
+  std::vector<std::u16string> listed_extensions =
       controller->GetExtensionList();
-  ASSERT_EQ(1U, override_extensions.size());
-  EXPECT_EQ(base::ASCIIToUTF16("Extension 2"), override_extensions[0]);
+  ASSERT_EQ(1U, listed_extensions.size());
+  EXPECT_EQ(u"Alpha", listed_extensions[0]);
   EXPECT_EQ(0U, controller->link_click_count());
   EXPECT_EQ(0U, controller->dismiss_click_count());
   EXPECT_EQ(0U, controller->action_click_count());
@@ -462,41 +465,9 @@
   EXPECT_EQ(0U, controller->action_click_count());
   EXPECT_EQ(1U, controller->dismiss_click_count());
 
-  // No extension should have become disabled.
-  ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
-  EXPECT_TRUE(registry->enabled_extensions().GetByID(kId2));
-
   // Since the bubble was dismissed due to deactivation, the extension should
   // not have been acknowledged.
-  EXPECT_FALSE(controller->delegate()->HasBubbleInfoBeenAcknowledged(kId2));
-
-  bubble.set_action_on_show(
-      FakeExtensionMessageBubble::BUBBLE_ACTION_DISMISS_DEACTIVATION);
-  controller.reset(new TestExtensionMessageBubbleController(
-      new NtpOverriddenBubbleDelegate(browser()->profile()), browser()));
-  controller->SetIsActiveBubble();
-  // The bubble shouldn't show again for the same profile (we don't want to
-  // be annoying).
-  EXPECT_FALSE(controller->ShouldShow());
-  controller->delegate()->ClearProfileSetForTesting();
-  EXPECT_TRUE(controller->ShouldShow());
-  // Explicitly click the dismiss button. The extension should be
-  // acknowledged.
-  bubble.set_controller(controller.get());
-  bubble.set_action_on_show(
-      FakeExtensionMessageBubble::BUBBLE_ACTION_CLICK_DISMISS_BUTTON);
-  bubble.Show();
-  EXPECT_TRUE(controller->delegate()->HasBubbleInfoBeenAcknowledged(kId2));
-
-  // Uninstall the current ntp-controlling extension, allowing the other to
-  // take control.
-  service_->UninstallExtension(kId2, UNINSTALL_REASON_FOR_TESTING, nullptr);
-
-  // Even though we already showed for the given profile, we should show
-  // again, because it's a different extension.
-  controller.reset(new TestExtensionMessageBubbleController(
-      new NtpOverriddenBubbleDelegate(browser()->profile()), browser()));
-  EXPECT_TRUE(controller->ShouldShow());
+  EXPECT_FALSE(test_delegate_raw->WasExtensionAcknowledged(extension->id()));
 }
 
 // The feature this is meant to test is only enacted on Windows, but it should
@@ -891,11 +862,15 @@
 // enabled extension is uninstalled.
 TEST_F(ExtensionMessageBubbleTest, BubbleClosedAfterEnabledExtensionUninstall) {
   Init();
-  ASSERT_TRUE(
-      LoadExtensionOverridingNtp("1", kId1, ManifestLocation::kUnpacked));
+
+  scoped_refptr<const Extension> extension = ExtensionBuilder("Alpha").Build();
+  service_->AddExtension(extension.get());
+  auto test_delegate = std::make_unique<TestExtensionMessageBubbleDelegate>(
+      browser()->profile());
+  test_delegate->IncludeExtensionId(extension->id());
 
   auto controller = std::make_unique<TestExtensionMessageBubbleController>(
-      new NtpOverriddenBubbleDelegate(browser()->profile()), browser());
+      test_delegate.release(), browser());
   controller->SetIsActiveBubble();
 
   EXPECT_TRUE(controller->ShouldShow());
@@ -910,7 +885,8 @@
   EXPECT_FALSE(bubble.is_closed());
 
   // Uninstall the extension.
-  service_->UninstallExtension(kId1, UNINSTALL_REASON_FOR_TESTING, nullptr);
+  service_->UninstallExtension(extension->id(), UNINSTALL_REASON_FOR_TESTING,
+                               nullptr);
   ASSERT_EQ(0U, controller->GetExtensionList().size());
 
   // The bubble should be closed after the extension is uninstalled.
@@ -1398,26 +1374,27 @@
 
 // Tests if that ShouldShow() returns false if the bubble's associated extension
 // has been removed.
-TEST_F(ExtensionMessageBubbleTest, TestShouldShowMethod) {
+TEST_F(ExtensionMessageBubbleTest,
+       ShouldShowReturnsFalseIfExtensionIsDisabled) {
   Init();
-  ExtensionRegistry* registry = ExtensionRegistry::Get(profile());
-  ASSERT_TRUE(
-      LoadExtensionOverridingNtp("1", kId1, ManifestLocation::kUnpacked));
-  ASSERT_TRUE(registry->enabled_extensions().GetByID(kId1));
 
-  std::unique_ptr<TestExtensionMessageBubbleController> ntp_bubble_controller(
-      new TestExtensionMessageBubbleController(
-          new NtpOverriddenBubbleDelegate(browser()->profile()), browser()));
+  scoped_refptr<const Extension> extension = ExtensionBuilder("Alpha").Build();
+  service_->AddExtension(extension.get());
+  auto test_delegate = std::make_unique<TestExtensionMessageBubbleDelegate>(
+      browser()->profile());
+  test_delegate->IncludeExtensionId(extension->id());
 
-  ASSERT_EQ(1u, ntp_bubble_controller->GetExtensionIdList().size());
-  EXPECT_EQ(kId1, ntp_bubble_controller->GetExtensionIdList()[0]);
-  EXPECT_TRUE(ntp_bubble_controller->ShouldShow());
+  auto controller = std::make_unique<TestExtensionMessageBubbleController>(
+      test_delegate.release(), browser());
 
-  // Disable the extension for being from outside the webstore.
-  service_->DisableExtension(kId1,
-                             extensions::disable_reason::DISABLE_NOT_VERIFIED);
-  EXPECT_TRUE(registry->disabled_extensions().GetByID(kId1));
-  EXPECT_FALSE(ntp_bubble_controller->ShouldShow());
+  ASSERT_EQ(1u, controller->GetExtensionIdList().size());
+  EXPECT_EQ(extension->id(), controller->GetExtensionIdList()[0]);
+  EXPECT_TRUE(controller->ShouldShow());
+
+  // Disable the extension.
+  service_->DisableExtension(extension->id(),
+                             extensions::disable_reason::DISABLE_USER_ACTION);
+  EXPECT_FALSE(controller->ShouldShow());
 }
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/extension_protocols_unittest.cc b/chrome/browser/extensions/extension_protocols_unittest.cc
index da7103b..fcc4c97 100644
--- a/chrome/browser/extensions/extension_protocols_unittest.cc
+++ b/chrome/browser/extensions/extension_protocols_unittest.cc
@@ -338,13 +338,12 @@
  private:
   GetResult LoadURL(const GURL& url,
                     network::mojom::RequestDestination destination) {
-    constexpr int32_t kRoutingId = 81;
     constexpr int32_t kRequestId = 28;
 
     mojo::PendingRemote<network::mojom::URLLoader> loader;
     network::TestURLLoaderClient client;
     loader_factory_->CreateLoaderAndStart(
-        loader.InitWithNewPipeAndPassReceiver(), kRoutingId, kRequestId,
+        loader.InitWithNewPipeAndPassReceiver(), kRequestId,
         network::mojom::kURLLoadOptionNone,
         CreateResourceRequest("GET", destination, url), client.CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index 801ecb7..eb778ff5 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -5196,7 +5196,7 @@
   std::u16string db_name = base::UTF8ToUTF16("db");
   std::u16string description = base::UTF8ToUTF16("db_description");
   int64_t size;
-  db_tracker->DatabaseOpened(origin_id, db_name, description, 1, &size);
+  db_tracker->DatabaseOpened(origin_id, db_name, description, &size);
   db_tracker->DatabaseClosed(origin_id, db_name);
   std::vector<storage::OriginInfo> origins;
   db_tracker->GetAllOriginsInfo(&origins);
diff --git a/chrome/browser/extensions/test_blocklist_state_fetcher.cc b/chrome/browser/extensions/test_blocklist_state_fetcher.cc
index 1e383ac..b134010 100644
--- a/chrome/browser/extensions/test_blocklist_state_fetcher.cc
+++ b/chrome/browser/extensions/test_blocklist_state_fetcher.cc
@@ -22,7 +22,6 @@
   // network::URLLoaderFactory implementation:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/chrome/browser/extensions/test_extension_message_bubble_delegate.cc b/chrome/browser/extensions/test_extension_message_bubble_delegate.cc
new file mode 100644
index 0000000..9eb72bb
--- /dev/null
+++ b/chrome/browser/extensions/test_extension_message_bubble_delegate.cc
@@ -0,0 +1,110 @@
+// Copyright 2021 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/extensions/test_extension_message_bubble_delegate.h"
+
+#include "base/containers/contains.h"
+
+namespace extensions {
+
+TestExtensionMessageBubbleDelegate::TestExtensionMessageBubbleDelegate(
+    Profile* profile)
+    : ExtensionMessageBubbleController::Delegate(profile) {}
+TestExtensionMessageBubbleDelegate::~TestExtensionMessageBubbleDelegate() =
+    default;
+
+bool TestExtensionMessageBubbleDelegate::ShouldIncludeExtension(
+    const Extension* extension) {
+  return base::Contains(extension_ids_, extension->id());
+}
+
+void TestExtensionMessageBubbleDelegate::AcknowledgeExtension(
+    const ExtensionId& extension_id,
+    ExtensionMessageBubbleController::BubbleAction action) {
+  acknowledged_extensions_.emplace(extension_id, action);
+}
+
+void TestExtensionMessageBubbleDelegate::PerformAction(
+    const ExtensionIdList& list) {}
+
+std::u16string TestExtensionMessageBubbleDelegate::GetTitle() const {
+  return u"Title";
+}
+
+std::u16string TestExtensionMessageBubbleDelegate::GetMessageBody(
+    bool anchored_to_browser_action,
+    int extension_count) const {
+  return u"Body";
+}
+
+std::u16string TestExtensionMessageBubbleDelegate::GetOverflowText(
+    const std::u16string& overflow_count) const {
+  return std::u16string();
+}
+
+std::u16string TestExtensionMessageBubbleDelegate::GetLearnMoreLabel() const {
+  return u"Learn more";
+}
+
+GURL TestExtensionMessageBubbleDelegate::GetLearnMoreUrl() const {
+  return GURL();
+}
+
+std::u16string TestExtensionMessageBubbleDelegate::GetActionButtonLabel()
+    const {
+  return u"OK";
+}
+
+std::u16string TestExtensionMessageBubbleDelegate::GetDismissButtonLabel()
+    const {
+  return u"Cancel";
+}
+
+bool TestExtensionMessageBubbleDelegate::ShouldCloseOnDeactivate() const {
+  return true;
+}
+
+bool TestExtensionMessageBubbleDelegate::ShouldShow(
+    const ExtensionIdList& extensions) const {
+  return true;
+}
+
+void TestExtensionMessageBubbleDelegate::OnShown(
+    const ExtensionIdList& extensions) {}
+
+void TestExtensionMessageBubbleDelegate::ClearProfileSetForTesting() {}
+
+bool TestExtensionMessageBubbleDelegate::ShouldShowExtensionList() const {
+  return true;
+}
+
+bool TestExtensionMessageBubbleDelegate::ShouldHighlightExtensions() const {
+  return true;
+}
+
+bool TestExtensionMessageBubbleDelegate::ShouldLimitToEnabledExtensions()
+    const {
+  return true;
+}
+
+void TestExtensionMessageBubbleDelegate::LogExtensionCount(size_t count) {}
+
+void TestExtensionMessageBubbleDelegate::LogAction(
+    ExtensionMessageBubbleController::BubbleAction action) {}
+
+bool TestExtensionMessageBubbleDelegate::SupportsPolicyIndicator() {
+  return true;
+}
+
+void TestExtensionMessageBubbleDelegate::IncludeExtensionId(
+    const ExtensionId& extension_id) {
+  extension_ids_.insert(extension_id);
+}
+
+bool TestExtensionMessageBubbleDelegate::WasExtensionAcknowledged(
+    const ExtensionId& extension_id) const {
+  return base::Contains(acknowledged_extensions_, extension_id);
+}
+
+}  // namespace extensions
diff --git a/chrome/browser/extensions/test_extension_message_bubble_delegate.h b/chrome/browser/extensions/test_extension_message_bubble_delegate.h
new file mode 100644
index 0000000..3a64dc9
--- /dev/null
+++ b/chrome/browser/extensions/test_extension_message_bubble_delegate.h
@@ -0,0 +1,72 @@
+// Copyright 2021 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_EXTENSIONS_TEST_EXTENSION_MESSAGE_BUBBLE_DELEGATE_H_
+#define CHROME_BROWSER_EXTENSIONS_TEST_EXTENSION_MESSAGE_BUBBLE_DELEGATE_H_
+
+#include <map>
+#include <set>
+#include <string>
+
+#include "chrome/browser/extensions/extension_message_bubble_controller.h"
+#include "extensions/common/extension_id.h"
+
+namespace extensions {
+
+// A programmable test delegate to exercise the ExtensionMessageBubbleController
+// framework.
+class TestExtensionMessageBubbleDelegate
+    : public ExtensionMessageBubbleController::Delegate {
+ public:
+  explicit TestExtensionMessageBubbleDelegate(Profile* profile);
+  TestExtensionMessageBubbleDelegate(
+      const TestExtensionMessageBubbleDelegate&) = delete;
+  TestExtensionMessageBubbleDelegate& operator=(
+      const TestExtensionMessageBubbleDelegate&) = delete;
+  ~TestExtensionMessageBubbleDelegate() override;
+
+  // ExtensionMessageBubbleController::Delegate:
+  bool ShouldIncludeExtension(const Extension* extension) override;
+  void AcknowledgeExtension(
+      const ExtensionId& extension_id,
+      ExtensionMessageBubbleController::BubbleAction action) override;
+  void PerformAction(const ExtensionIdList& list) override;
+  std::u16string GetTitle() const override;
+  std::u16string GetMessageBody(bool anchored_to_browser_action,
+                                int extension_count) const override;
+  std::u16string GetOverflowText(
+      const std::u16string& overflow_count) const override;
+  std::u16string GetLearnMoreLabel() const override;
+  GURL GetLearnMoreUrl() const override;
+  std::u16string GetActionButtonLabel() const override;
+  std::u16string GetDismissButtonLabel() const override;
+  bool ShouldCloseOnDeactivate() const override;
+  bool ShouldShow(const ExtensionIdList& extensions) const override;
+  void OnShown(const ExtensionIdList& extensions) override;
+  void ClearProfileSetForTesting() override;
+  bool ShouldShowExtensionList() const override;
+  bool ShouldHighlightExtensions() const override;
+  bool ShouldLimitToEnabledExtensions() const override;
+  void LogExtensionCount(size_t count) override;
+  void LogAction(
+      ExtensionMessageBubbleController::BubbleAction action) override;
+  bool SupportsPolicyIndicator() override;
+
+  // Indicate that `ShouldIncludeExtension()` should always return true for
+  // the given `extension_id`.
+  void IncludeExtensionId(const ExtensionId& extension_id);
+
+  // Returns true if the given `extension_id` was acknowledged.
+  bool WasExtensionAcknowledged(const ExtensionId& extension_id) const;
+
+ private:
+  std::set<ExtensionId> extension_ids_;
+
+  std::map<ExtensionId, ExtensionMessageBubbleController::BubbleAction>
+      acknowledged_extensions_;
+};
+
+}  // namespace extensions
+
+#endif  // CHROME_BROWSER_EXTENSIONS_TEST_EXTENSION_MESSAGE_BUBBLE_DELEGATE_H_
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 27b9c14..acc80217 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -59,6 +59,11 @@
     "expiry_milestone": 93
   },
   {
+    "name": "add-to-homescreen-iph",
+    "owners": [ "shaktisahu" ],
+    "expiry_milestone": 94
+  },
+  {
     "name": "aggregated-ml-app-ranking",
     "owners": [ "pdyson", "jiameng" ],
     "expiry_milestone": 81
@@ -363,11 +368,6 @@
     "expiry_milestone": 95
   },
   {
-    "name": "autofill-off-no-server-data",
-    "owners": [ "seblalancette" ],
-    "expiry_milestone": 79
-  },
-  {
     "name": "autofill-profile-client-validation",
     "owners": [ "parastoog" ],
     "expiry_milestone": 79
@@ -781,11 +781,6 @@
     "expiry_milestone": 90
   },
   {
-    "name": "cookies-without-same-site-must-be-secure",
-    "owners": [ "chlily", "morlovich" ],
-    "expiry_milestone": 90
-  },
-  {
     "name": "copy-link-to-text",
     "owners": [ "johntlee" ],
     "expiry_milestone": 92
@@ -1751,11 +1746,6 @@
     "expiry_milestone": 95
   },
   {
-    "name": "enable-experimental-productivity-features",
-    "owners": [ "feature-control@chromium.org" ],
-    "expiry_milestone": 86
-  },
-  {
     "name": "enable-experimental-web-platform-features",
     "owners": [ "//third_party/blink/renderer/core/OWNERS" ],
     // Used by developers to activate experimental features in blink.
@@ -1796,8 +1786,8 @@
   },
   {
     "name": "enable-fullpage-screenshot",
-    "owners": [ "jmentasti", "seblalancette" ],
-    "expiry_milestone": 90
+    "owners": [ "seblalancette" ],
+    "expiry_milestone": 94
   },
   {
     "name": "enable-future-v8-vm-features",
@@ -3303,7 +3293,7 @@
     // This is useful for isolating additional origins beyond the normal site
     // isolation policy, as well as for diagnosing problems when site isolation
     // only applies to some sites.
-    "expiry_milestone": 90
+    "expiry_milestone": 100
   },
   {
     "name": "isolation-by-default",
@@ -4245,7 +4235,7 @@
       "sauski",
       "msramek",
       "chrome-friendly-settings@google.com"],
-    "expiry_milestone": 90
+    "expiry_milestone": 94
   },
   {
     "name": "privacy-reordered-android",
@@ -4541,16 +4531,6 @@
     "expiry_milestone": 92
   },
   {
-    "name": "safety-check-ios",
-    "owners": [
-      "andzaytsev",
-      "harrisonsean",
-      "msramek",
-      "chrome-friendly-settings@google.com"
-    ],
-    "expiry_milestone": 90
-  },
-  {
     "name": "safety-check-weak-passwords",
     "owners": [
       "rainhard",
@@ -4565,11 +4545,6 @@
     "expiry_milestone": 89
   },
   {
-    "name": "same-site-by-default-cookies",
-    "owners": [ "chlily", "morlovich" ],
-    "expiry_milestone": 90
-  },
-  {
     "name": "scan-app-media-link",
     "owners": [ "gavinwill", "jschettler" ],
     "expiry_milestone": 95
@@ -4808,7 +4783,7 @@
     "_comment2": "in https://crbug.com/849815.",
     "name": "site-isolation-trial-opt-out",
     "owners": [ "site-isolation-dev", "alexmos", "creis", "lukasza" ],
-    "expiry_milestone": 95
+    "expiry_milestone": 100
   },
   {
     "name": "smart-dim-model-v3",
@@ -4880,7 +4855,7 @@
     // therefore unlikely to ship anytime soon, but this allows experimenting
     // with a stronger isolation policy for users who may not care about
     // breaking compatibility with document.domain.
-    "expiry_milestone": 90
+    "expiry_milestone": 100
   },
   {
     "name": "stylus-battery-status",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index ad3b6de..417e19b 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -500,14 +500,6 @@
     "Show messages in DevTools about upcoming deprecations that would affect "
     "sent/received cookies.";
 
-const char kCookiesWithoutSameSiteMustBeSecureName[] =
-    "Cookies without SameSite must be secure";
-const char kCookiesWithoutSameSiteMustBeSecureDescription[] =
-    "If enabled, cookies without SameSite restrictions must also be Secure. If "
-    "a cookie without SameSite restrictions is set without the Secure "
-    "attribute, it will be rejected. This flag only has an effect if "
-    "\"SameSite by default cookies\" is also enabled.";
-
 const char kCooperativeSchedulingName[] = "Cooperative Scheduling";
 const char kCooperativeSchedulingDescription[] =
     "Enables cooperative scheduling in Blink.";
@@ -2083,12 +2075,6 @@
     "If enabled, a Safety Tip UI may be displayed when visiting or interacting "
     "with a site Chrome believes may be suspicious.";
 
-const char kSameSiteByDefaultCookiesName[] = "SameSite by default cookies";
-const char kSameSiteByDefaultCookiesDescription[] =
-    "Treat cookies that don't specify a SameSite attribute as if they were "
-    "SameSite=Lax. Sites must specify SameSite=None in order to enable "
-    "third-party usage.";
-
 const char kSchemefulSameSiteName[] = "Schemeful Same-Site";
 const char kSchemefulSameSiteDescription[] =
     "Modify the same-site computation such that origins with the same "
@@ -2674,6 +2660,11 @@
 
 #if defined(OS_ANDROID)
 
+const char kAddToHomescreenIPHName[] = "Add to homescreen IPH";
+const char kAddToHomescreenIPHDescription[] =
+    " Shows in-product-help messages educating users about add to homescreen "
+    "option in chrome.";
+
 const char kAImageReaderName[] = "Android ImageReader";
 const char kAImageReaderDescription[] =
     " Enables MediaPlayer and MediaCodec to use AImageReader on Android. "
@@ -3246,12 +3237,6 @@
     "regardless of whether they are safe or useful. This requires the Related "
     "Searches feature flag to also be enabled.";
 
-const char kReportFeedUserActionsName[] =
-    "Enable the report of click actions on cards in Chrome's Feed on Android.";
-const char kReportFeedUserActionsDescription[] =
-    "Enable the report of click actions on cards in Chrome's Feed on Android."
-    " Also enable the feed header menu to manage the feed.";
-
 const char kRequestDesktopSiteForTabletsName[] =
     "Request desktop site for tablets on Android";
 const char kRequestDesktopSiteForTabletsDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 323fc67..7957510 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -321,9 +321,6 @@
 extern const char kCookieDeprecationMessagesName[];
 extern const char kCookieDeprecationMessagesDescription[];
 
-extern const char kCookiesWithoutSameSiteMustBeSecureName[];
-extern const char kCookiesWithoutSameSiteMustBeSecureDescription[];
-
 extern const char kCooperativeSchedulingName[];
 extern const char kCooperativeSchedulingDescription[];
 
@@ -1223,9 +1220,6 @@
 extern const char kSafetyTipName[];
 extern const char kSafetyTipDescription[];
 
-extern const char kSameSiteByDefaultCookiesName[];
-extern const char kSameSiteByDefaultCookiesDescription[];
-
 extern const char kSchemefulSameSiteName[];
 extern const char kSchemefulSameSiteDescription[];
 
@@ -1568,6 +1562,9 @@
 
 #if defined(OS_ANDROID)
 
+extern const char kAddToHomescreenIPHName[];
+extern const char kAddToHomescreenIPHDescription[];
+
 extern const char kAImageReaderName[];
 extern const char kAImageReaderDescription[];
 
@@ -1887,9 +1884,6 @@
 extern const char kRelatedSearchesUiName[];
 extern const char kRelatedSearchesUiDescription[];
 
-extern const char kReportFeedUserActionsName[];
-extern const char kReportFeedUserActionsDescription[];
-
 extern const char kRequestDesktopSiteForTabletsName[];
 extern const char kRequestDesktopSiteForTabletsDescription[];
 
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index 0ef7047..58aff9f 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -124,10 +124,10 @@
     &feed::kInterestFeedV1ClicksAndViewsConditionalUpload,
     &feed::kInterestFeedV2,
     &feed::kInterestFeedV2Hearts,
-    &feed::kReportFeedUserActions,
     &feed::kWebFeed,
     &feed::kXsurfaceMetricsReporting,
     &history::kHideFromApi3Transitions,
+    &kAddToHomescreenIPH,
     &kAllowNewIncognitoTabIntents,
     &kAllowRemoteContextForNotifications,
     &kAndroidDefaultBrowserPromo,
@@ -325,6 +325,10 @@
 }  // namespace
 
 // Alphabetical:
+
+const base::Feature kAddToHomescreenIPH{"AddToHomescreenIPH",
+                                        base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kAndroidDefaultBrowserPromo{
     "AndroidDefaultBrowserPromo", base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h
index c98b5edd..2db7380 100644
--- a/chrome/browser/flags/android/chrome_feature_list.h
+++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -12,6 +12,7 @@
 namespace android {
 
 // Alphabetical:
+extern const base::Feature kAddToHomescreenIPH;
 extern const base::Feature kAllowNewIncognitoTabIntents;
 extern const base::Feature kAllowRemoteContextForNotifications;
 extern const base::Feature kAndroidDefaultBrowserPromo;
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java
index 54dfa94..4c6752b 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/CachedFeatureFlags.java
@@ -76,7 +76,6 @@
             put(ChromeFeatureList.TAB_TO_GTS_ANIMATION, false);
             put(ChromeFeatureList.TEST_DEFAULT_DISABLED, false);
             put(ChromeFeatureList.TEST_DEFAULT_ENABLED, true);
-            put(ChromeFeatureList.REPORT_FEED_USER_ACTIONS, false);
             put(ChromeFeatureList.INTEREST_FEED_V2, true);
             put(ChromeFeatureList.THEME_REFACTOR_ANDROID, false);
             put(ChromeFeatureList.USE_CHIME_ANDROID_SDK, false);
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
index c505abc..f114d9d4 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -189,6 +189,7 @@
 
     /* Alphabetical: */
     public static final String ADAPTIVE_BUTTON_IN_TOP_TOOLBAR = "AdaptiveButtonInTopToolbar";
+    public static final String ADD_TO_HOMESCREEN_IPH = "AddToHomescreenIPH";
     public static final String ALLOW_NEW_INCOGNITO_TAB_INTENTS = "AllowNewIncognitoTabIntents";
     public static final String ALLOW_REMOTE_CONTEXT_FOR_NOTIFICATIONS =
             "AllowRemoteContextForNotifications";
@@ -413,7 +414,6 @@
     public static final String RELATED_SEARCHES = "RelatedSearches";
     public static final String RELATED_SEARCHES_UI = "RelatedSearchesUi";
     public static final String REQUEST_DESKTOP_SITE_FOR_TABLETS = "RequestDesktopSiteForTablets";
-    public static final String REPORT_FEED_USER_ACTIONS = "ReportFeedUserActions";
     public static final String SAFE_BROWSING_DELAYED_WARNINGS = "SafeBrowsingDelayedWarnings";
     public static final String SAFE_BROWSING_ENHANCED_PROTECTION_ENABLED =
             "SafeBrowsingEnhancedProtection";
diff --git a/chrome/browser/history_clusters/memories_service_factory.cc b/chrome/browser/history_clusters/memories_service_factory.cc
new file mode 100644
index 0000000..a216819
--- /dev/null
+++ b/chrome/browser/history_clusters/memories_service_factory.cc
@@ -0,0 +1,51 @@
+// Copyright 2021 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/history_clusters/memories_service_factory.h"
+
+#include "chrome/browser/history/history_service_factory.h"
+#include "chrome/browser/profiles/profile.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "components/keyed_service/core/service_access_type.h"
+#include "components/memories/core/memories_service.h"
+#include "content/public/browser/storage_partition.h"
+
+// static
+memories::MemoriesService* MemoriesServiceFactory::GetForBrowserContext(
+    content::BrowserContext* browser_context) {
+  return static_cast<memories::MemoriesService*>(
+      GetInstance().GetServiceForBrowserContext(browser_context, true));
+}
+
+// static
+MemoriesServiceFactory& MemoriesServiceFactory::GetInstance() {
+  static base::NoDestructor<MemoriesServiceFactory> instance;
+  return *instance;
+}
+
+MemoriesServiceFactory::MemoriesServiceFactory()
+    : BrowserContextKeyedServiceFactory(
+          "MemoriesService",
+          BrowserContextDependencyManager::GetInstance()) {
+  DependsOn(HistoryServiceFactory::GetInstance());
+}
+
+MemoriesServiceFactory::~MemoriesServiceFactory() = default;
+
+KeyedService* MemoriesServiceFactory::BuildServiceInstanceFor(
+    content::BrowserContext* context) const {
+  auto* profile = Profile::FromBrowserContext(context);
+  auto* history_service = HistoryServiceFactory::GetForProfile(
+      profile, ServiceAccessType::EXPLICIT_ACCESS);
+  auto url_loader_factory =
+      content::BrowserContext::GetDefaultStoragePartition(context)
+          ->GetURLLoaderFactoryForBrowserProcess();
+  return new memories::MemoriesService(history_service, url_loader_factory);
+}
+
+content::BrowserContext* MemoriesServiceFactory::GetBrowserContextToUse(
+    content::BrowserContext* context) const {
+  // Give incognito its own isolated service.
+  return context;
+}
diff --git a/components/memories/content/memories_service_factory.h b/chrome/browser/history_clusters/memories_service_factory.h
similarity index 80%
rename from components/memories/content/memories_service_factory.h
rename to chrome/browser/history_clusters/memories_service_factory.h
index c164b0d..0b6c56630 100644
--- a/components/memories/content/memories_service_factory.h
+++ b/chrome/browser/history_clusters/memories_service_factory.h
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_MEMORIES_CONTENT_MEMORIES_SERVICE_FACTORY_H_
-#define COMPONENTS_MEMORIES_CONTENT_MEMORIES_SERVICE_FACTORY_H_
+#ifndef CHROME_BROWSER_HISTORY_CLUSTERS_MEMORIES_SERVICE_FACTORY_H_
+#define CHROME_BROWSER_HISTORY_CLUSTERS_MEMORIES_SERVICE_FACTORY_H_
 
 #include "base/no_destructor.h"
 #include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+#include "content/public/browser/browser_context.h"
 
 namespace memories {
 class MemoriesService;
@@ -33,4 +34,4 @@
       content::BrowserContext* context) const override;
 };
 
-#endif  // COMPONENTS_MEMORIES_CONTENT_MEMORIES_SERVICE_FACTORY_H_
+#endif  // CHROME_BROWSER_HISTORY_CLUSTERS_MEMORIES_SERVICE_FACTORY_H_
diff --git a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc
index ba65d79..dd49483 100644
--- a/chrome/browser/media/webrtc/desktop_capture_access_handler.cc
+++ b/chrome/browser/media/webrtc/desktop_capture_access_handler.cc
@@ -256,6 +256,14 @@
       const bool display_notification =
           display_notification_ && ShouldDisplayNotification(extension);
 
+      if (!content::WebContents::FromRenderFrameHost(
+              content::RenderFrameHost::FromID(request.render_process_id,
+                                               request.render_frame_id))) {
+        std::move(callback).Run(
+            devices, blink::mojom::MediaStreamRequestResult::INVALID_STATE,
+            std::move(ui));
+        return;
+      }
       ui = GetDevicesForDesktopCapture(
           web_contents, &devices, screen_id,
           blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE,
diff --git a/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc b/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc
index 164b4e53..cad31457 100644
--- a/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc
+++ b/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc
@@ -296,7 +296,7 @@
     return;
   }
 
-  // If the kill switch is, or the request was blocked because of feature
+  // If the kill switch is, or the request was blocked because of permissions
   // policy we don't update the tab context.
   if (result != blink::mojom::MediaStreamRequestResult::KILL_SWITCH_ON &&
       !blocked_by_permissions_policy) {
diff --git a/chrome/browser/net/chrome_report_sender_unittest.cc b/chrome/browser/net/chrome_report_sender_unittest.cc
index a558284..942ef6d3 100644
--- a/chrome/browser/net/chrome_report_sender_unittest.cc
+++ b/chrome/browser/net/chrome_report_sender_unittest.cc
@@ -34,7 +34,6 @@
   // network::SharedURLLoaderFactory
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& url_request,
diff --git a/chrome/browser/net/system_network_context_manager.cc b/chrome/browser/net/system_network_context_manager.cc
index 0110dc7..849ffe94 100644
--- a/chrome/browser/net/system_network_context_manager.cc
+++ b/chrome/browser/net/system_network_context_manager.cc
@@ -212,7 +212,6 @@
 
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& url_request,
@@ -223,7 +222,7 @@
     if (!manager_)
       return;
     manager_->GetURLLoaderFactory()->CreateLoaderAndStart(
-        std::move(receiver), routing_id, request_id, options, url_request,
+        std::move(receiver), request_id, options, url_request,
         std::move(client), traffic_annotation);
   }
 
diff --git a/chrome/browser/optimization_guide/prediction/prediction_model_download_manager_unittest.cc b/chrome/browser/optimization_guide/prediction/prediction_model_download_manager_unittest.cc
index eb25470..b4fd629f 100644
--- a/chrome/browser/optimization_guide/prediction/prediction_model_download_manager_unittest.cc
+++ b/chrome/browser/optimization_guide/prediction/prediction_model_download_manager_unittest.cc
@@ -424,8 +424,16 @@
       PredictionModelDownloadStatus::kFailedCrxVerification, 1);
 }
 
+// TODO(crbug.com/1156112): Flaky on Windows.
+#if defined(OS_WIN)
+#define MAYBE_VerifiedCrxWithInvalidPublisherShouldDeleteTempFile \
+  DISABLED_VerifiedCrxWithInvalidPublisherShouldDeleteTempFile
+#else
+#define MAYBE_VerifiedCrxWithInvalidPublisherShouldDeleteTempFile \
+  VerifiedCrxWithInvalidPublisherShouldDeleteTempFile
+#endif
 TEST_F(PredictionModelDownloadManagerTest,
-       VerifiedCrxWithInvalidPublisherShouldDeleteTempFile) {
+       MAYBE_VerifiedCrxWithInvalidPublisherShouldDeleteTempFile) {
   base::HistogramTester histogram_tester;
 
   TestPredictionModelDownloadObserver observer;
@@ -536,9 +544,17 @@
       PredictionModelDownloadStatus::kFailedModelFileNotFound, 1);
 }
 
+// TODO(crbug.com/1156112): Flaky on Windows.
+#if defined(OS_WIN)
+#define MAYBE_VerifiedCrxWithGoodModelFilesShouldDeleteDownloadFileButHaveContentExtracted \
+  DISABLED_VerifiedCrxWithGoodModelFilesShouldDeleteDownloadFileButHaveContentExtracted
+#else
+#define MAYBE_VerifiedCrxWithGoodModelFilesShouldDeleteDownloadFileButHaveContentExtracted \
+  VerifiedCrxWithGoodModelFilesShouldDeleteDownloadFileButHaveContentExtracted
+#endif
 TEST_F(
     PredictionModelDownloadManagerTest,
-    VerifiedCrxWithGoodModelFilesShouldDeleteDownloadFileButHaveContentExtracted) {
+    MAYBE_VerifiedCrxWithGoodModelFilesShouldDeleteDownloadFileButHaveContentExtracted) {
   base::HistogramTester histogram_tester;
 
   TestPredictionModelDownloadObserver observer;
diff --git a/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc
index c67ef69..f0f3067 100644
--- a/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/core/ukm_page_load_metrics_observer.cc
@@ -20,6 +20,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/content_settings/cookie_settings_factory.h"
 #include "chrome/browser/history/history_service_factory.h"
+#include "chrome/browser/history_clusters/memories_service_factory.h"
 #include "chrome/browser/prefetch/no_state_prefetch/no_state_prefetch_manager_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
@@ -30,7 +31,6 @@
 #include "components/content_settings/core/common/pref_names.h"
 #include "components/history/core/browser/history_service.h"
 #include "components/keyed_service/core/service_access_type.h"
-#include "components/memories/content/memories_service_factory.h"
 #include "components/memories/core/memories_service.h"
 #include "components/metrics/net/network_metrics_provider.h"
 #include "components/no_state_prefetch/browser/no_state_prefetch_manager.h"
diff --git a/chrome/browser/password_manager/android/password_generation_controller_impl.cc b/chrome/browser/password_manager/android/password_generation_controller_impl.cc
index 5da062a..36e78c2 100644
--- a/chrome/browser/password_manager/android/password_generation_controller_impl.cc
+++ b/chrome/browser/password_manager/android/password_generation_controller_impl.cc
@@ -16,8 +16,8 @@
 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/password_generation_util.h"
-#include "components/autofill/core/common/renderer_id.h"
 #include "components/autofill/core/common/signatures.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_generation_frame_helper.h"
 #include "components/password_manager/core/browser/password_manager.h"
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.h b/chrome/browser/password_manager/chrome_password_manager_client.h
index 1d73456..f56c1719 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client.h
+++ b/chrome/browser/password_manager/chrome_password_manager_client.h
@@ -17,7 +17,7 @@
 #include "build/chromeos_buildflags.h"
 #include "components/autofill/content/common/mojom/autofill_driver.mojom-forward.h"
 #include "components/autofill/core/common/password_generation_util.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/autofill_assistant/browser/public/runtime_observer.h"
 #include "components/password_manager/content/browser/content_credential_manager.h"
 #include "components/password_manager/content/browser/content_password_manager_driver_factory.h"
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc
index bc5587a0..c8cb937 100644
--- a/chrome/browser/password_manager/password_manager_browsertest.cc
+++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -46,7 +46,7 @@
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/autofill_switches.h"
 #include "components/autofill/core/common/form_field_data.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/content/browser/content_password_manager_driver.h"
 #include "components/password_manager/content/browser/content_password_manager_driver_factory.h"
 #include "components/password_manager/core/browser/form_parsing/password_field_prediction.h"
diff --git a/chrome/browser/performance_monitor/process_metrics_recorder.cc b/chrome/browser/performance_monitor/process_metrics_recorder.cc
index fe2c1436..e5c8f360 100644
--- a/chrome/browser/performance_monitor/process_metrics_recorder.cc
+++ b/chrome/browser/performance_monitor/process_metrics_recorder.cc
@@ -27,16 +27,24 @@
 void ProcessMetricsRecorder::OnMetricsSampled(
     const ProcessMetadata& process_metadata,
     const ProcessMonitor::Metrics& metrics) {
-  // We scale up to the equivalent of 64 CPU cores fully loaded. More than this
-  // doesn't really matter, as we're already in a terrible place.
-  const int kHistogramMin = 1;
-  const int kHistogramMax = 6400;
-  const int kHistogramBucketCount = 50;
+  // CPU usage metrics are reported as a double in the
+  // [0.0, number of core * 100.0] range. The CPU usage is usually below 1% and
+  // so the histogram are reported with a 1/10000 granularity to make analyzing
+  // the data easier (otherwise almost all the samples end up in the same [0, 1[
+  // bucket).
+  constexpr int kCPUUsageFactor = 100;
+  // We scale up to the equivalent of 2 CPU cores fully loaded. More than this
+  // doesn't really matter, as we're already in a terrible place. This used to
+  // be capped at 64 cores but the data showed that this was way too much, the
+  // per process CPU usage really rarely exceeds 100% of one core.
+  constexpr int kHistogramMin = 1;
+  constexpr int kHistogramMax = 200 * kCPUUsageFactor;
+  constexpr int kHistogramBucketCount = 50;
 
 #if defined(OS_WIN)
-  const int kDiskUsageHistogramMin = 1;
-  const int kDiskUsageHistogramMax = 200 * 1024 * 1024;  // 200 M/sec.
-  const int kDiskUsageHistogramBucketCount = 50;
+  constexpr int kDiskUsageHistogramMin = 1;
+  constexpr int kDiskUsageHistogramMax = 200 * 1024 * 1024;  // 200 M/sec.
+  constexpr int kDiskUsageHistogramBucketCount = 50;
 #endif
 
   // The histogram macros don't support variables as histogram names,
@@ -44,8 +52,9 @@
   switch (process_metadata.process_type) {
     case content::PROCESS_TYPE_BROWSER:
       UMA_HISTOGRAM_CUSTOM_COUNTS(
-          "PerformanceMonitor.AverageCPU.BrowserProcess", metrics.cpu_usage,
-          kHistogramMin, kHistogramMax, kHistogramBucketCount);
+          "PerformanceMonitor.AverageCPU2.BrowserProcess",
+          metrics.cpu_usage * kCPUUsageFactor, kHistogramMin, kHistogramMax,
+          kHistogramBucketCount);
       // If CPU usage has consistently been above our threshold,
       // we *may* have an issue.
       if (metrics.cpu_usage > kHighCPUUtilizationThreshold) {
@@ -76,8 +85,9 @@
       break;
     case content::PROCESS_TYPE_RENDERER:
       UMA_HISTOGRAM_CUSTOM_COUNTS(
-          "PerformanceMonitor.AverageCPU.RendererProcess", metrics.cpu_usage,
-          kHistogramMin, kHistogramMax, kHistogramBucketCount);
+          "PerformanceMonitor.AverageCPU2.RendererProcess2",
+          metrics.cpu_usage * kCPUUsageFactor, kHistogramMin, kHistogramMax,
+          kHistogramBucketCount);
       if (metrics.cpu_usage > kHighCPUUtilizationThreshold) {
         UMA_HISTOGRAM_BOOLEAN("PerformanceMonitor.HighCPU.RendererProcess",
                               true);
@@ -100,9 +110,10 @@
 
       break;
     case content::PROCESS_TYPE_GPU:
-      UMA_HISTOGRAM_CUSTOM_COUNTS("PerformanceMonitor.AverageCPU.GPUProcess",
-                                  metrics.cpu_usage, kHistogramMin,
-                                  kHistogramMax, kHistogramBucketCount);
+      UMA_HISTOGRAM_CUSTOM_COUNTS("PerformanceMonitor.AverageCPU2.GPUProcess",
+                                  metrics.cpu_usage * kCPUUsageFactor,
+                                  kHistogramMin, kHistogramMax,
+                                  kHistogramBucketCount);
       if (metrics.cpu_usage > kHighCPUUtilizationThreshold)
         UMA_HISTOGRAM_BOOLEAN("PerformanceMonitor.HighCPU.GPUProcess", true);
 #if defined(OS_MAC) || defined(OS_LINUX) || defined(OS_CHROMEOS) || \
@@ -121,9 +132,10 @@
 
       break;
     case content::PROCESS_TYPE_PPAPI_PLUGIN:
-      UMA_HISTOGRAM_CUSTOM_COUNTS("PerformanceMonitor.AverageCPU.PPAPIProcess",
-                                  metrics.cpu_usage, kHistogramMin,
-                                  kHistogramMax, kHistogramBucketCount);
+      UMA_HISTOGRAM_CUSTOM_COUNTS("PerformanceMonitor.AverageCPU2.PPAPIProcess",
+                                  metrics.cpu_usage * kCPUUsageFactor,
+                                  kHistogramMin, kHistogramMax,
+                                  kHistogramBucketCount);
       if (metrics.cpu_usage > kHighCPUUtilizationThreshold)
         UMA_HISTOGRAM_BOOLEAN("PerformanceMonitor.HighCPU.PPAPIProcess", true);
       break;
@@ -135,18 +147,12 @@
     case kProcessSubtypeUnknown:
       break;
     case kProcessSubtypePPAPIFlash:
-      UMA_HISTOGRAM_CUSTOM_COUNTS(
-          "PerformanceMonitor.AverageCPU.PPAPIFlashProcess", metrics.cpu_usage,
-          kHistogramMin, kHistogramMax, kHistogramBucketCount);
-      if (metrics.cpu_usage > kHighCPUUtilizationThreshold) {
-        UMA_HISTOGRAM_BOOLEAN("PerformanceMonitor.HighCPU.PPAPIFlashProcess",
-                              true);
-      }
+      NOTREACHED() << "Flash isn't supported anymore.";
       break;
     case kProcessSubtypeExtensionPersistent:
       UMA_HISTOGRAM_CUSTOM_COUNTS(
-          "PerformanceMonitor.AverageCPU.RendererExtensionPersistentProcess",
-          metrics.cpu_usage, kHistogramMin, kHistogramMax,
+          "PerformanceMonitor.AverageCPU2.RendererExtensionPersistentProcess",
+          metrics.cpu_usage * kCPUUsageFactor, kHistogramMin, kHistogramMax,
           kHistogramBucketCount);
       if (metrics.cpu_usage > kHighCPUUtilizationThreshold) {
         UMA_HISTOGRAM_BOOLEAN(
@@ -156,8 +162,8 @@
       break;
     case kProcessSubtypeExtensionEvent:
       UMA_HISTOGRAM_CUSTOM_COUNTS(
-          "PerformanceMonitor.AverageCPU.RendererExtensionEventProcess",
-          metrics.cpu_usage, kHistogramMin, kHistogramMax,
+          "PerformanceMonitor.AverageCPU2.RendererExtensionEventProcess",
+          metrics.cpu_usage * kCPUUsageFactor, kHistogramMin, kHistogramMax,
           kHistogramBucketCount);
       if (metrics.cpu_usage > kHighCPUUtilizationThreshold) {
         UMA_HISTOGRAM_BOOLEAN(
diff --git a/chrome/browser/predictors/prefetch_manager.cc b/chrome/browser/predictors/prefetch_manager.cc
index b32d16e7..2384d544 100644
--- a/chrome/browser/predictors/prefetch_manager.cc
+++ b/chrome/browser/predictors/prefetch_manager.cc
@@ -269,7 +269,6 @@
   std::unique_ptr<blink::ThrottlingURLLoader> loader =
       blink::ThrottlingURLLoader::CreateLoaderAndStart(
           std::move(factory), std::move(throttles),
-          /*routing_id is not needed*/ -1,
           content::GlobalRequestID::MakeBrowserInitiated().request_id, options,
           &request, client.get(), kPrefetchTrafficAnnotation,
           base::ThreadTaskRunnerHandle::Get(),
diff --git a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_proxying_url_loader_factory.cc b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_proxying_url_loader_factory.cc
index b0e4947..53e3895 100644
--- a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_proxying_url_loader_factory.cc
+++ b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_proxying_url_loader_factory.cc
@@ -106,7 +106,6 @@
     network::mojom::URLLoaderFactory* target_factory,
     ResourceLoadSuccessfulCallback on_resource_load_successful,
     mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
@@ -123,8 +122,8 @@
       client_receiver_.BindNewPipeAndPassRemote();
 
   target_factory->CreateLoaderAndStart(
-      target_loader_.BindNewPipeAndPassReceiver(), routing_id, request_id,
-      options, request, std::move(proxy_client), traffic_annotation);
+      target_loader_.BindNewPipeAndPassReceiver(), request_id, options, request,
+      std::move(proxy_client), traffic_annotation);
 
   // Calls |OnBindingsClosed| only after both disconnect handlers have been run.
   base::RepeatingClosure closure = base::BarrierClosure(
@@ -355,7 +354,6 @@
 
 void PrefetchProxyProxyingURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
@@ -414,7 +412,7 @@
         base::BindOnce(
             &PrefetchProxyProxyingURLLoaderFactory::OnEligibilityResult,
             weak_factory_.GetWeakPtr(), profile, std::move(loader_receiver),
-            routing_id, request_id, options, request, std::move(client),
+            request_id, options, request, std::move(client),
             traffic_annotation));
     return;
   }
@@ -426,7 +424,7 @@
     // Load this resource from |isolated_factory_|'s cache.
     auto in_progress_request = std::make_unique<InProgressRequest>(
         profile, this, isolated_factory_.get(), base::NullCallback(),
-        std::move(loader_receiver), routing_id, request_id, options, request,
+        std::move(loader_receiver), request_id, options, request,
         std::move(client), traffic_annotation);
     in_progress_request->SetOnCompleteRecordMetricsCallback(
         base::BindOnce(&PrefetchProxyProxyingURLLoaderFactory::
@@ -438,7 +436,7 @@
     // No metrics callback here, since there's nothing important to record.
     requests_.insert(std::make_unique<InProgressRequest>(
         profile, this, network_process_factory_.get(), base::NullCallback(),
-        std::move(loader_receiver), routing_id, request_id, options, request,
+        std::move(loader_receiver), request_id, options, request,
         std::move(client), traffic_annotation));
   }
 }
@@ -446,7 +444,6 @@
 void PrefetchProxyProxyingURLLoaderFactory::OnEligibilityResult(
     Profile* profile,
     mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
@@ -504,8 +501,8 @@
 
   auto in_progress_request = std::make_unique<InProgressRequest>(
       profile, this, isolated_factory_.get(), resource_load_successful_callback,
-      std::move(loader_receiver), routing_id, request_id, options,
-      isolated_request, std::move(client), traffic_annotation);
+      std::move(loader_receiver), request_id, options, isolated_request,
+      std::move(client), traffic_annotation);
   in_progress_request->SetOnCompleteRecordMetricsCallback(
       base::BindOnce(&PrefetchProxyProxyingURLLoaderFactory::
                          RecordSubresourceMetricsDuringPrerender,
diff --git a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_proxying_url_loader_factory.h b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_proxying_url_loader_factory.h
index 7d7b91d..7aa6d67 100644
--- a/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_proxying_url_loader_factory.h
+++ b/chrome/browser/prefetch/prefetch_proxy/prefetch_proxy_proxying_url_loader_factory.h
@@ -86,7 +86,6 @@
   // network::mojom::URLLoaderFactory:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
@@ -106,7 +105,6 @@
         network::mojom::URLLoaderFactory* target_factory,
         ResourceLoadSuccessfulCallback on_resource_load_successful,
         mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
-        int32_t routing_id,
         int32_t request_id,
         uint32_t options,
         const network::ResourceRequest& request,
@@ -230,7 +228,6 @@
   void OnEligibilityResult(
       Profile* profile,
       mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/chrome/browser/prefetch/search_prefetch/back_forward_search_prefetch_url_loader.cc b/chrome/browser/prefetch/search_prefetch/back_forward_search_prefetch_url_loader.cc
index 4df22795..e5baf22 100644
--- a/chrome/browser/prefetch/search_prefetch/back_forward_search_prefetch_url_loader.cc
+++ b/chrome/browser/prefetch/search_prefetch/back_forward_search_prefetch_url_loader.cc
@@ -65,7 +65,7 @@
 
   // Create a network service URL loader with passed in params.
   url_loader_factory->CreateLoaderAndStart(
-      network_url_loader_.BindNewPipeAndPassReceiver(), 0, 0,
+      network_url_loader_.BindNewPipeAndPassReceiver(), 0,
       network::mojom::kURLLoadOptionNone, prefetch_request,
       url_loader_receiver_.BindNewPipeAndPassRemote(
           base::ThreadTaskRunnerHandle::Get()),
@@ -103,7 +103,7 @@
 
   // Create a network service URL loader with passed in params.
   url_loader_factory->CreateLoaderAndStart(
-      network_url_loader_.BindNewPipeAndPassReceiver(), 0, 0,
+      network_url_loader_.BindNewPipeAndPassReceiver(), 0,
       network::mojom::kURLLoadOptionNone, *resource_request_,
       url_loader_receiver_.BindNewPipeAndPassRemote(
           base::ThreadTaskRunnerHandle::Get()),
diff --git a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
index 1e14c8b5..3ec3f036 100644
--- a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
+++ b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
@@ -39,7 +39,7 @@
 
   // Create a network service URL loader with passed in params.
   url_loader_factory->CreateLoaderAndStart(
-      network_url_loader_.BindNewPipeAndPassReceiver(), 0, 0,
+      network_url_loader_.BindNewPipeAndPassReceiver(), 0,
       network::mojom::kURLLoadOptionNone, *resource_request_,
       url_loader_receiver_.BindNewPipeAndPassRemote(
           base::ThreadTaskRunnerHandle::Get()),
diff --git a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
index 1417383f..16b69d5 100644
--- a/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
+++ b/chrome/browser/resources/chromeos/login/screen_gaia_signin.js
@@ -223,7 +223,7 @@
     isShown_: {
       type: Boolean,
       value: false,
-    }
+    },
   },
 
   observers: [
@@ -514,7 +514,8 @@
 
   /** @private */
   focusActiveFrame_() {
-    this.getActiveFrame_().focus();
+    let activeFrame = this.getActiveFrame_();
+    Polymer.RenderStatus.afterNextRender(this, () => activeFrame.focus());
   },
 
   /** Event handler that is invoked after the screen is shown. */
@@ -1205,6 +1206,14 @@
   },
 
   /**
+   * Whether new OOBE layout is enabled.
+   */
+  newLayoutEnabled_() {
+    return loadTimeData.valueExists('newLayoutEnabled') &&
+        loadTimeData.getBoolean('newLayoutEnabled');
+  },
+
+  /**
    * Called when focus is returned.
    * @param {boolean} reverse Is focus returned in reverse order?
    */
@@ -1213,7 +1222,7 @@
     // returned from the system tray in regular order. Because the webview is
     // the first focusable element of the screen and we want to eliminate extra
     // tab. Reverse tab doesn't need any adjustments here.
-    if (!reverse)
+    if (!this.newLayoutEnabled_() && !reverse)
       this.focusActiveFrame_();
   },
 });
diff --git a/chrome/browser/resources/chromeos/login/screens/oobe/oobe_eula.html b/chrome/browser/resources/chromeos/login/screens/oobe/oobe_eula.html
index aa4c8240..81fa554 100644
--- a/chrome/browser/resources/chromeos/login/screens/oobe/oobe_eula.html
+++ b/chrome/browser/resources/chromeos/login/screens/oobe/oobe_eula.html
@@ -18,6 +18,12 @@
 <dom-module id="oobe-eula-element">
   <template>
     <style include="oobe-dialog-host">
+      a {
+        color: var(--google-blue-500);
+        text-decoration: none;
+        width: fit-content;
+      }
+
       #crosEulaFrame {
         /* minimal height which allows popup dialogs looks fine. */
         min-height: 300px;
diff --git a/chrome/browser/resources/chromeos/login/screens/oobe/oobe_eula.js b/chrome/browser/resources/chromeos/login/screens/oobe/oobe_eula.js
index f108532..907e9e46 100644
--- a/chrome/browser/resources/chromeos/login/screens/oobe/oobe_eula.js
+++ b/chrome/browser/resources/chromeos/login/screens/oobe/oobe_eula.js
@@ -489,6 +489,14 @@
   },
 
   /**
+   * Whether new OOBE layout is enabled.
+   */
+  newLayoutEnabled_() {
+    return loadTimeData.valueExists('newLayoutEnabled') &&
+        loadTimeData.getBoolean('newLayoutEnabled');
+  },
+
+  /**
    * Called when focus is returned.
    * @param {boolean} reverse Is focus returned in reverse order?
    */
@@ -497,7 +505,7 @@
     // returned from the system tray in regular order. Because the webview is
     // the first focusable element of the screen and we want to eliminate extra
     // tab. Reverse tab doesn't need any adjustments here.
-    if (!reverse && this.uiStep == UIState.EULA)
+    if (!this.newLayoutEnabled_() && !reverse && this.uiStep == UIState.EULA)
       Polymer.RenderStatus.afterNextRender(
           this, () => this.$.crosEulaFrame.focus());
   },
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.cc b/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.cc
index 5d329ec6..cd945a1 100644
--- a/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.cc
+++ b/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.cc
@@ -317,7 +317,6 @@
 
 void CertificateReportingServiceTestHelper::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& url_request,
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.h b/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.h
index 09cef82..e3b64233 100644
--- a/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.h
+++ b/chrome/browser/safe_browsing/certificate_reporting_service_test_utils.h
@@ -161,7 +161,6 @@
   // network::SharedURLLoaderFactory
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& url_request,
diff --git a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc
index b6d9b6a..1cdc56a 100644
--- a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc
+++ b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.cc
@@ -85,7 +85,6 @@
   InProgressRequest(
       ProxyingURLLoaderFactory* factory,
       mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
@@ -284,7 +283,6 @@
 ProxyingURLLoaderFactory::InProgressRequest::InProgressRequest(
     ProxyingURLLoaderFactory* factory,
     mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
@@ -310,8 +308,8 @@
 
   if (modified_headers.IsEmpty() && removed_headers.empty()) {
     factory_->target_factory_->CreateLoaderAndStart(
-        target_loader_.BindNewPipeAndPassReceiver(), routing_id, request_id,
-        options, request, std::move(proxy_client), traffic_annotation);
+        target_loader_.BindNewPipeAndPassReceiver(), request_id, options,
+        request, std::move(proxy_client), traffic_annotation);
 
     // We need to keep a full copy of the request headers in case there is a
     // redirect and the request headers need to be modified again.
@@ -326,8 +324,8 @@
     }
 
     factory_->target_factory_->CreateLoaderAndStart(
-        target_loader_.BindNewPipeAndPassReceiver(), routing_id, request_id,
-        options, request_copy, std::move(proxy_client), traffic_annotation);
+        target_loader_.BindNewPipeAndPassReceiver(), request_id, options,
+        request_copy, std::move(proxy_client), traffic_annotation);
 
     headers_.Swap(&request_copy.headers);
     cors_exempt_headers_.Swap(&request_copy.cors_exempt_headers);
@@ -470,15 +468,14 @@
 
 void ProxyingURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
     mojo::PendingRemote<network::mojom::URLLoaderClient> client,
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
   requests_.insert(std::make_unique<InProgressRequest>(
-      this, std::move(loader_receiver), routing_id, request_id, options,
-      request, std::move(client), traffic_annotation));
+      this, std::move(loader_receiver), request_id, options, request,
+      std::move(client), traffic_annotation));
 }
 
 void ProxyingURLLoaderFactory::Clone(
diff --git a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.h b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.h
index c9b6e97..2410564 100644
--- a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.h
+++ b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory.h
@@ -60,7 +60,6 @@
   // network::mojom::URLLoaderFactory:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/chrome/browser/subresource_filter/ad_tagging_browsertest.cc b/chrome/browser/subresource_filter/ad_tagging_browsertest.cc
index 7e1f5ff..2248447 100644
--- a/chrome/browser/subresource_filter/ad_tagging_browsertest.cc
+++ b/chrome/browser/subresource_filter/ad_tagging_browsertest.cc
@@ -38,6 +38,7 @@
 namespace {
 
 using content::RenderFrameHost;
+using testing::CreateAllowlistSuffixRule;
 using testing::CreateSuffixRule;
 
 // Creates a link element with rel="stylesheet" and href equal to the specified
@@ -117,8 +118,11 @@
 
   void SetUpOnMainThread() override {
     SubresourceFilterBrowserTest::SetUpOnMainThread();
-    SetRulesetWithRules(
-        {CreateSuffixRule("ad_script.js"), CreateSuffixRule("ad=true")});
+    // Allowlist rules are only checked if there is a matching blocklist rule.
+    SetRulesetWithRules({CreateSuffixRule("ad_script.js"),
+                         CreateSuffixRule("ad=true"),
+                         CreateSuffixRule("allowed=true"),
+                         CreateAllowlistSuffixRule("allowed=true")});
   }
 
   content::WebContents* GetWebContents() {
@@ -357,26 +361,25 @@
   RenderFrameHost* ad_child =
       CreateSrcFrame(GetWebContents(), GetURL("frame_factory.html?2&ad=true"));
   EXPECT_TRUE(observer.GetIsAdSubframe(ad_child->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
-      ad_child, /*parent_is_ad=*/false,
-      FilterListEvidence::kMatchedBlockingRule,
-      ScriptHeuristicEvidence::kNotCreatedByAdScript);
+  ExpectFrameAdEvidence(ad_child, /*parent_is_ad=*/false,
+                        FilterListEvidence::kMatchedBlockingRule,
+                        ScriptHeuristicEvidence::kNotCreatedByAdScript);
 
   // (3) Ad child of 2.
   RenderFrameHost* ad_child_2 =
       CreateSrcFrame(ad_child, GetURL("frame_factory.html?sub=1&3&ad=true"));
   EXPECT_TRUE(observer.GetIsAdSubframe(ad_child_2->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
-      ad_child_2, /*parent_is_ad=*/true, FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(ad_child_2, /*parent_is_ad=*/true,
+                        FilterListEvidence::kMatchedBlockingRule,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
 
   // (4) Vanilla child of 2.
   RenderFrameHost* vanilla_child_2 =
       CreateSrcFrame(ad_child, GetURL("frame_factory.html?4"));
   EXPECT_TRUE(observer.GetIsAdSubframe(vanilla_child_2->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
-      vanilla_child_2, /*parent_is_ad=*/true, FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(vanilla_child_2, /*parent_is_ad=*/true,
+                        FilterListEvidence::kMatchedNoRules,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
 
   // (5) Vanilla child of 1. This tests something subtle.
   // frame_factory.html?ad=true loads the same script that frame_factory.html
@@ -484,9 +487,9 @@
   RenderFrameHost* ad_child = CreateSrcFrameFromAdScript(
       GetWebContents(), GetURL("frame_factory.html?1"));
   EXPECT_TRUE(observer.GetIsAdSubframe(ad_child->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
-      ad_child, /*parent_is_ad=*/false, FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(ad_child, /*parent_is_ad=*/false,
+                        FilterListEvidence::kMatchedNoRules,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
 }
 
 // Test that same-origin doc.write created iframes are tagged as ads.
@@ -504,9 +507,9 @@
   // (2) Ad child.
   content::RenderFrameHost* ad_frame =
       CreateDocWrittenFrameFromAdScript(GetWebContents());
-  observer.VerifyEvidenceForAdSubframe(
-      ad_frame, /*parent_is_ad=*/false, FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(ad_frame, /*parent_is_ad=*/false,
+                        FilterListEvidence::kNotChecked,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
 }
 
 // Test that the children same-origin doc.write created iframes are tagged as
@@ -537,33 +540,31 @@
       CreateSrcFrameFromAdScript(vanilla_frame, GetURL("frame_factory.html?2"));
   EXPECT_TRUE(
       observer.GetIsAdSubframe(ad_child_of_vanilla->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
-      ad_child_of_vanilla, /*parent_is_ad=*/false,
-      FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(ad_child_of_vanilla, /*parent_is_ad=*/false,
+                        FilterListEvidence::kMatchedNoRules,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
 
   // Ad frame and descendants
   content::RenderFrameHost* ad_frame =
       CreateDocWrittenFrameFromAdScript(GetWebContents());
-  observer.VerifyEvidenceForAdSubframe(
-      ad_frame, /*parent_is_ad=*/false, FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(ad_frame, /*parent_is_ad=*/false,
+                        FilterListEvidence::kNotChecked,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
 
   content::RenderFrameHost* vanilla_child_of_ad =
       CreateSrcFrame(ad_frame, GetURL("frame_factory.html?3"));
   EXPECT_TRUE(
       observer.GetIsAdSubframe(vanilla_child_of_ad->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
-      vanilla_child_of_ad, /*parent_is_ad=*/true,
-      FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(vanilla_child_of_ad, /*parent_is_ad=*/true,
+                        FilterListEvidence::kMatchedNoRules,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
 
   content::RenderFrameHost* ad_child_of_ad =
       CreateSrcFrameFromAdScript(ad_frame, GetURL("frame_factory.html?4"));
   EXPECT_TRUE(observer.GetIsAdSubframe(ad_child_of_ad->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
-      ad_child_of_ad, /*parent_is_ad=*/true, FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(ad_child_of_ad, /*parent_is_ad=*/true,
+                        FilterListEvidence::kMatchedNoRules,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
 }
 
 // Test that frames with an aborted initial load due to a doc.write are still
@@ -586,10 +587,9 @@
       CreateFrameWithDocWriteAbortedLoadFromAdScript(GetWebContents());
   EXPECT_TRUE(observer.GetIsAdSubframe(
       ad_frame_with_aborted_load->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
-      ad_frame_with_aborted_load, /*parent_is_ad=*/false,
-      FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(ad_frame_with_aborted_load,
+                        /*parent_is_ad=*/false, FilterListEvidence::kNotChecked,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
 
   // Child with ad parent.
   content::RenderFrameHost* ad_frame = CreateSrcFrameFromAdScript(
@@ -599,10 +599,9 @@
   EXPECT_TRUE(observer.GetIsAdSubframe(ad_frame->GetFrameTreeNodeId()));
   EXPECT_TRUE(observer.GetIsAdSubframe(
       child_frame_of_ad_with_aborted_load->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
-      child_frame_of_ad_with_aborted_load, /*parent_is_ad=*/true,
-      FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(child_frame_of_ad_with_aborted_load,
+                        /*parent_is_ad=*/true, FilterListEvidence::kNotChecked,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
 }
 
 // Test that frames with an aborted initial load due to a window.stop are still
@@ -625,10 +624,9 @@
       CreateFrameWithWindowStopAbortedLoadFromAdScript(GetWebContents());
   EXPECT_TRUE(observer.GetIsAdSubframe(
       ad_frame_with_aborted_load->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
-      ad_frame_with_aborted_load, /*parent_is_ad=*/false,
-      FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(ad_frame_with_aborted_load,
+                        /*parent_is_ad=*/false, FilterListEvidence::kNotChecked,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
 
   // Child with ad parent.
   content::RenderFrameHost* ad_frame = CreateSrcFrameFromAdScript(
@@ -638,10 +636,9 @@
   EXPECT_TRUE(observer.GetIsAdSubframe(ad_frame->GetFrameTreeNodeId()));
   EXPECT_TRUE(observer.GetIsAdSubframe(
       child_frame_of_ad_with_aborted_load->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
-      child_frame_of_ad_with_aborted_load, /*parent_is_ad=*/true,
-      FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(child_frame_of_ad_with_aborted_load,
+                        /*parent_is_ad=*/true, FilterListEvidence::kNotChecked,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
 }
 
 // Test that the children of a frame with its initial load aborted due to a
@@ -674,10 +671,9 @@
       vanilla_frame_with_aborted_load, GetURL("frame_factory.html?2"));
   EXPECT_TRUE(
       observer.GetIsAdSubframe(ad_child_of_vanilla->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
-      ad_child_of_vanilla, /*parent_is_ad=*/false,
-      FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(ad_child_of_vanilla, /*parent_is_ad=*/false,
+                        FilterListEvidence::kMatchedNoRules,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
 
   // Create a frame and abort its initial load in ad script. The children of
   // this ad frame should be tagged as ads.
@@ -685,26 +681,24 @@
       CreateFrameWithDocWriteAbortedLoadFromAdScript(GetWebContents());
   EXPECT_TRUE(observer.GetIsAdSubframe(
       ad_frame_with_aborted_load->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
-      ad_frame_with_aborted_load, /*parent_is_ad=*/false,
-      FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(ad_frame_with_aborted_load,
+                        /*parent_is_ad=*/false, FilterListEvidence::kNotChecked,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
 
   content::RenderFrameHost* vanilla_child_of_ad = CreateSrcFrame(
       ad_frame_with_aborted_load, GetURL("frame_factory.html?3"));
   EXPECT_TRUE(
       observer.GetIsAdSubframe(vanilla_child_of_ad->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
-      vanilla_child_of_ad, /*parent_is_ad=*/true,
-      FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(vanilla_child_of_ad, /*parent_is_ad=*/true,
+                        FilterListEvidence::kMatchedNoRules,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
 
   content::RenderFrameHost* ad_child_of_ad = CreateSrcFrameFromAdScript(
       ad_frame_with_aborted_load, GetURL("frame_factory.html?4"));
   EXPECT_TRUE(observer.GetIsAdSubframe(ad_child_of_ad->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
-      ad_child_of_ad, /*parent_is_ad=*/true, FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(ad_child_of_ad, /*parent_is_ad=*/true,
+                        FilterListEvidence::kMatchedNoRules,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
 }
 
 // Test that the children of a frame with its initial load aborted due to a
@@ -732,10 +726,9 @@
       vanilla_frame_with_aborted_load, GetURL("frame_factory.html"));
   EXPECT_TRUE(
       observer.GetIsAdSubframe(ad_child_of_vanilla->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
-      ad_child_of_vanilla, /*parent_is_ad=*/false,
-      FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(ad_child_of_vanilla, /*parent_is_ad=*/false,
+                        FilterListEvidence::kMatchedNoRules,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
 
   // Create a frame and abort its initial load in ad script. The children of
   // this ad frame should be tagged as ads.
@@ -743,27 +736,81 @@
       CreateFrameWithWindowStopAbortedLoadFromAdScript(GetWebContents());
   EXPECT_TRUE(observer.GetIsAdSubframe(
       ad_frame_with_aborted_load->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
-      ad_frame_with_aborted_load, /*parent_is_ad=*/false,
-      FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(ad_frame_with_aborted_load,
+                        /*parent_is_ad=*/false, FilterListEvidence::kNotChecked,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
 
   content::RenderFrameHost* vanilla_child_of_ad =
       CreateSrcFrame(ad_frame_with_aborted_load, GetURL("frame_factory.html"));
   EXPECT_TRUE(
       observer.GetIsAdSubframe(vanilla_child_of_ad->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
-      vanilla_child_of_ad, /*parent_is_ad=*/true,
-      FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(vanilla_child_of_ad, /*parent_is_ad=*/true,
+                        FilterListEvidence::kMatchedNoRules,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
 
   content::RenderFrameHost* ad_child_of_ad = CreateSrcFrameFromAdScript(
       ad_frame_with_aborted_load, GetURL("frame_factory.html"));
   EXPECT_TRUE(observer.GetIsAdSubframe(ad_child_of_ad->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
-      vanilla_child_of_ad, /*parent_is_ad=*/true,
-      FilterListEvidence::kNotChecked,
-      ScriptHeuristicEvidence::kCreatedByAdScript);
+  ExpectFrameAdEvidence(vanilla_child_of_ad, /*parent_is_ad=*/true,
+                        FilterListEvidence::kMatchedNoRules,
+                        ScriptHeuristicEvidence::kCreatedByAdScript);
+}
+
+// Test that navigating a frame to a URL with a less restrictive load policy
+// updates the latest filter list result, but not the most-restrictive one.
+IN_PROC_BROWSER_TEST_F(
+    AdTaggingBrowserTest,
+    NavigationToLessRestrictiveUrl_MostRestrictiveLoadPolicyUnchanged) {
+  TestSubresourceFilterObserver observer(web_contents());
+
+  // Main frame.
+  ui_test_utils::NavigateToURL(browser(), GetURL("frame_factory.html"));
+
+  content::RenderFrameHost* test_frame = CreateSrcFrame(
+      GetWebContents(), GetURL("frame_factory.html?allowed=true"));
+  EXPECT_FALSE(observer.GetIsAdSubframe(test_frame->GetFrameTreeNodeId()));
+  ExpectFrameAdEvidence(
+      test_frame, /*parent_is_ad=*/false,
+      /*latest_filter_list_result=*/FilterListEvidence::kMatchedAllowingRule,
+      /*most_restrictive_filter_list_result=*/
+      FilterListEvidence::kMatchedAllowingRule,
+      ScriptHeuristicEvidence::kNotCreatedByAdScript);
+
+  NavigateFrame(test_frame, GetURL("frame_factory.html"));
+  EXPECT_FALSE(observer.GetIsAdSubframe(test_frame->GetFrameTreeNodeId()));
+  ExpectFrameAdEvidence(
+      test_frame, /*parent_is_ad=*/false,
+      /*latest_filter_list_result=*/FilterListEvidence::kMatchedNoRules,
+      /*most_restrictive_filter_list_result=*/
+      FilterListEvidence::kMatchedNoRules,
+      ScriptHeuristicEvidence::kNotCreatedByAdScript);
+
+  NavigateFrame(test_frame, GetURL("frame_factory.html?allowed=true"));
+  EXPECT_FALSE(observer.GetIsAdSubframe(test_frame->GetFrameTreeNodeId()));
+  ExpectFrameAdEvidence(
+      test_frame, /*parent_is_ad=*/false,
+      /*latest_filter_list_result=*/FilterListEvidence::kMatchedAllowingRule,
+      /*most_restrictive_filter_list_result=*/
+      FilterListEvidence::kMatchedNoRules,
+      ScriptHeuristicEvidence::kNotCreatedByAdScript);
+
+  NavigateFrame(test_frame, GetURL("frame_factory.html?ad=true"));
+  EXPECT_TRUE(observer.GetIsAdSubframe(test_frame->GetFrameTreeNodeId()));
+  ExpectFrameAdEvidence(
+      test_frame, /*parent_is_ad=*/false,
+      /*latest_filter_list_result=*/FilterListEvidence::kMatchedBlockingRule,
+      /*most_restrictive_filter_list_result=*/
+      FilterListEvidence::kMatchedBlockingRule,
+      ScriptHeuristicEvidence::kNotCreatedByAdScript);
+
+  NavigateFrame(test_frame, GetURL("frame_factory.html"));
+  EXPECT_TRUE(observer.GetIsAdSubframe(test_frame->GetFrameTreeNodeId()));
+  ExpectFrameAdEvidence(
+      test_frame, /*parent_is_ad=*/false,
+      /*latest_filter_list_result=*/FilterListEvidence::kMatchedNoRules,
+      /*most_restrictive_filter_list_result=*/
+      FilterListEvidence::kMatchedBlockingRule,
+      ScriptHeuristicEvidence::kNotCreatedByAdScript);
 }
 
 // Basic vanilla stylesheet with vanilla font and image.
diff --git a/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc b/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc
index a4571e77..0a2a085 100644
--- a/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_browser_test_harness.cc
@@ -26,6 +26,7 @@
 #include "components/safe_browsing/core/db/v4_protocol_manager_util.h"
 #include "components/safe_browsing/core/db/v4_test_util.h"
 #include "components/safe_browsing/core/features.h"
+#include "components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h"
 #include "components/subresource_filter/content/browser/ruleset_service.h"
 #include "components/subresource_filter/content/browser/subresource_filter_profile_context.h"
 #include "components/subresource_filter/content/browser/test_ruleset_publisher.h"
diff --git a/chrome/browser/task_manager/task_manager_interface.cc b/chrome/browser/task_manager/task_manager_interface.cc
index 044443c..9e5b0123 100644
--- a/chrome/browser/task_manager/task_manager_interface.cc
+++ b/chrome/browser/task_manager/task_manager_interface.cc
@@ -40,6 +40,7 @@
   return TaskManagerImpl::GetInstance();
 }
 
+// static
 void TaskManagerInterface::UpdateAccumulatedStatsNetworkForRoute(
     int process_id,
     int route_id,
diff --git a/chrome/browser/themes/theme_helper.cc b/chrome/browser/themes/theme_helper.cc
index e17ad78..4f48c44 100644
--- a/chrome/browser/themes/theme_helper.cc
+++ b/chrome/browser/themes/theme_helper.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/themes/theme_service.h"
 
+#include "base/feature_list.h"
 #include "base/no_destructor.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
@@ -11,6 +12,7 @@
 #include "chrome/browser/themes/custom_theme_supplier.h"
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/ui/ui_features.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/grit/theme_resources.h"
 #include "components/grit/components_scaled_resources.h"
 #include "components/omnibox/browser/omnibox_field_trial.h"
@@ -480,6 +482,10 @@
     int id,
     bool incognito,
     const CustomThemeSupplier* theme_supplier) {
+  if (incognito && base::FeatureList::IsEnabled(
+                       features::kIncognitoBrandConsistencyForDesktop)) {
+    return true;
+  }
   // The incognito NTP uses the default background color instead of any theme
   // background color, unless the theme also sets a custom background image.
   return incognito && (id == TP::COLOR_NTP_BACKGROUND) &&
diff --git a/chrome/browser/themes/theme_service_unittest.cc b/chrome/browser/themes/theme_service_unittest.cc
index f1655e2..24ad914 100644
--- a/chrome/browser/themes/theme_service_unittest.cc
+++ b/chrome/browser/themes/theme_service_unittest.cc
@@ -21,6 +21,7 @@
 #include "chrome/browser/themes/theme_properties.h"
 #include "chrome/browser/themes/theme_service_factory.h"
 #include "chrome/common/buildflags.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_paths.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/testing_browser_process.h"
@@ -183,6 +184,26 @@
   ThemeService* theme_service_ = nullptr;
 };
 
+class IncognitoThemeServiceTest : public ThemeServiceTest,
+                                  public testing::WithParamInterface<bool> {
+ public:
+  IncognitoThemeServiceTest() {
+    bool flag_enabled = GetParam();
+    if (flag_enabled) {
+      feature_list_.InitAndEnableFeature(
+          features::kIncognitoBrandConsistencyForDesktop);
+    }
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+INSTANTIATE_TEST_SUITE_P(
+    IncognitoThemeServiceTestWithIncognitoBrandConsistencyFlag,
+    IncognitoThemeServiceTest,
+    testing::Values(false, true));
+
 // Installs then uninstalls a theme and makes sure that the ThemeService
 // reverts to the default theme after the uninstall.
 TEST_F(ThemeServiceTest, ThemeInstallUninstall) {
@@ -304,6 +325,33 @@
 #endif
 }
 
+TEST_P(IncognitoThemeServiceTest, IncognitoCustomColor_WithAutoGeneratedTheme) {
+  theme_service_->BuildAutogeneratedThemeFromColor(
+      SkColorSetRGB(100, 100, 100));
+
+  // Should get the same ThemeService for incognito and original profiles.
+  ThemeService* otr_theme_service =
+      ThemeServiceFactory::GetForProfile(profile_->GetPrimaryOTRProfile());
+  EXPECT_EQ(theme_service_, otr_theme_service);
+
+  const ui::ThemeProvider& otr_provider =
+      ThemeService::GetThemeProviderForProfile(
+          profile_->GetPrimaryOTRProfile());
+
+  SkColor default_incognito_color = ThemeProperties::GetDefaultColor(
+      ThemeProperties::COLOR_FRAME_ACTIVE, /*incognito= */ true,
+      /*dark_mode= */ false);
+  bool is_brand_consistency_flag_enabled = GetParam();
+
+  if (is_brand_consistency_flag_enabled) {
+    EXPECT_EQ(default_incognito_color,
+              otr_provider.GetColor(ThemeProperties::COLOR_FRAME_ACTIVE));
+  } else {
+    EXPECT_NE(default_incognito_color,
+              otr_provider.GetColor(ThemeProperties::COLOR_FRAME_ACTIVE));
+  }
+}
+
 TEST_F(ThemeServiceTest, GetColorForToolbarButton) {
   // This test relies on toolbar buttons having no tint, which is not currently
   // true in dark mode.
diff --git a/chrome/browser/ui/commander/bookmark_command_source.cc b/chrome/browser/ui/commander/bookmark_command_source.cc
index 0b859f6..4936399 100644
--- a/chrome/browser/ui/commander/bookmark_command_source.cc
+++ b/chrome/browser/ui/commander/bookmark_command_source.cc
@@ -6,7 +6,6 @@
 
 #include "base/i18n/case_conversion.h"
 #include "base/logging.h"
-#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
@@ -87,7 +86,7 @@
   std::vector<gfx::Range> ranges;
   // TODO(lgrey): Temporarily using an untranslated string since it's not
   // yet clear which commands will ship.
-  std::u16string open_title = base::ASCIIToUTF16("Open bookmark...");
+  std::u16string open_title = u"Open bookmark...";
   double score = finder.Find(open_title, &ranges);
   if (score > 0) {
     auto verb = std::make_unique<CommandItem>(open_title, score, ranges);
diff --git a/chrome/browser/ui/commander/commander_controller_unittest.cc b/chrome/browser/ui/commander/commander_controller_unittest.cc
index 0a9cb32..a7aadf4 100644
--- a/chrome/browser/ui/commander/commander_controller_unittest.cc
+++ b/chrome/browser/ui/commander/commander_controller_unittest.cc
@@ -125,7 +125,7 @@
   EXPECT_EQ(first->invocations().size(), 0u);
   EXPECT_EQ(second->invocations().size(), 0u);
 
-  std::u16string input = base::ASCIIToUTF16("foobar");
+  std::u16string input = u"foobar";
   controller->OnTextChanged(input, browser());
 
   EXPECT_EQ(first->invocations().size(), 1u);
@@ -145,7 +145,7 @@
       &CommanderControllerTest::OnViewModelUpdated, base::Unretained(this)));
   {
     ViewModelCallbackWaiter waiter(this);
-    controller->OnTextChanged(base::ASCIIToUTF16("foobar"), browser());
+    controller->OnTextChanged(u"foobar", browser());
   }
   // Assert since we're accessing an element.
   ASSERT_EQ(received_view_models_.size(), 1u);
@@ -153,7 +153,7 @@
 
   {
     ViewModelCallbackWaiter waiter(this);
-    controller->OnTextChanged(base::ASCIIToUTF16("barfoo"), browser());
+    controller->OnTextChanged(u"barfoo", browser());
   }
   EXPECT_EQ(received_view_models_.size(), 2u);
   EXPECT_NE(received_view_models_.back().result_set_id, first_id);
@@ -164,15 +164,14 @@
   auto first = std::make_unique<TestCommandSource>(
       base::BindRepeating([](const std::u16string&, Browser* browser) {
         CommandSource::CommandResults result;
-        result.push_back(
-            CreateNoOpCommandItem(base::ASCIIToUTF16("first"), 100));
+        result.push_back(CreateNoOpCommandItem(u"first", 100));
         return result;
       }));
   auto second = std::make_unique<TestCommandSource>(
       base::BindRepeating([](const std::u16string&, Browser* browser) {
         CommandSource::CommandResults result;
-        auto item = CreateNoOpCommandItem(base::ASCIIToUTF16("second"), 99);
-        item->annotation = base::ASCIIToUTF16("2nd");
+        auto item = CreateNoOpCommandItem(u"second", 99);
+        item->annotation = u"2nd";
         item->entity_type = CommandItem::Entity::kBookmark;
         result.push_back(std::move(item));
         return result;
@@ -187,18 +186,18 @@
 
   {
     ViewModelCallbackWaiter waiter(this);
-    controller->OnTextChanged(base::ASCIIToUTF16("foobar"), browser());
+    controller->OnTextChanged(u"foobar", browser());
   }
   ASSERT_EQ(received_view_models_.size(), 1u);
   CommanderViewModel model = received_view_models_.back();
   ASSERT_EQ(model.items.size(), 2u);
 
-  EXPECT_EQ(model.items[0].title, base::ASCIIToUTF16("first"));
+  EXPECT_EQ(model.items[0].title, u"first");
   EXPECT_EQ(model.items[0].annotation, std::u16string());
   EXPECT_EQ(model.items[0].entity_type, CommandItem::Entity::kCommand);
 
-  EXPECT_EQ(model.items[1].title, base::ASCIIToUTF16("second"));
-  EXPECT_EQ(model.items[1].annotation, base::ASCIIToUTF16("2nd"));
+  EXPECT_EQ(model.items[1].title, u"second");
+  EXPECT_EQ(model.items[1].annotation, u"2nd");
   EXPECT_EQ(model.items[1].entity_type, CommandItem::Entity::kBookmark);
 }
 
@@ -209,21 +208,17 @@
   auto first = std::make_unique<TestCommandSource>(
       base::BindRepeating([](const std::u16string&, Browser* browser) {
         CommandSource::CommandResults result;
-        result.push_back(
-            CreateNoOpCommandItem(base::ASCIIToUTF16("third"), 98));
-        result.push_back(
-            CreateNoOpCommandItem(base::ASCIIToUTF16("first"), 100));
-        result.push_back(
-            CreateNoOpCommandItem(base::ASCIIToUTF16("fourth"), 90));
+        result.push_back(CreateNoOpCommandItem(u"third", 98));
+        result.push_back(CreateNoOpCommandItem(u"first", 100));
+        result.push_back(CreateNoOpCommandItem(u"fourth", 90));
 
         return result;
       }));
   auto second = std::make_unique<TestCommandSource>(
       base::BindRepeating([](const std::u16string&, Browser* browser) {
         CommandSource::CommandResults result;
-        result.push_back(
-            CreateNoOpCommandItem(base::ASCIIToUTF16("second"), 99));
-        result.push_back(CreateNoOpCommandItem(base::ASCIIToUTF16("fifth"), 1));
+        result.push_back(CreateNoOpCommandItem(u"second", 99));
+        result.push_back(CreateNoOpCommandItem(u"fifth", 1));
         return result;
       }));
   sources.push_back(std::move(first));
@@ -236,16 +231,16 @@
 
   {
     ViewModelCallbackWaiter waiter(this);
-    controller->OnTextChanged(base::ASCIIToUTF16("foobar"), browser());
+    controller->OnTextChanged(u"foobar", browser());
   }
   ASSERT_EQ(received_view_models_.size(), 1u);
   CommanderViewModel model = received_view_models_.back();
   ASSERT_EQ(model.items.size(), 5u);
-  EXPECT_EQ(model.items[0].title, base::ASCIIToUTF16("first"));
-  EXPECT_EQ(model.items[1].title, base::ASCIIToUTF16("second"));
-  EXPECT_EQ(model.items[2].title, base::ASCIIToUTF16("third"));
-  EXPECT_EQ(model.items[3].title, base::ASCIIToUTF16("fourth"));
-  EXPECT_EQ(model.items[4].title, base::ASCIIToUTF16("fifth"));
+  EXPECT_EQ(model.items[0].title, u"first");
+  EXPECT_EQ(model.items[1].title, u"second");
+  EXPECT_EQ(model.items[2].title, u"third");
+  EXPECT_EQ(model.items[3].title, u"fourth");
+  EXPECT_EQ(model.items[4].title, u"fifth");
 }
 
 TEST_F(CommanderControllerTest, ViewModelSortsCommandsAboveNouns) {
@@ -253,11 +248,11 @@
   auto source = std::make_unique<TestCommandSource>(
       base::BindRepeating([](const std::u16string&, Browser* browser) {
         CommandSource::CommandResults result;
-        auto window = CreateNoOpCommandItem(base::ASCIIToUTF16("window"), 99);
+        auto window = CreateNoOpCommandItem(u"window", 99);
         window->entity_type = CommandItem::Entity::kWindow;
-        auto command = CreateNoOpCommandItem(base::ASCIIToUTF16("command"), 90);
+        auto command = CreateNoOpCommandItem(u"command", 90);
         command->entity_type = CommandItem::Entity::kCommand;
-        auto tab = CreateNoOpCommandItem(base::ASCIIToUTF16("tab"), 100);
+        auto tab = CreateNoOpCommandItem(u"tab", 100);
         tab->entity_type = CommandItem::Entity::kTab;
         result.push_back(std::move(window));
         result.push_back(std::move(command));
@@ -272,20 +267,20 @@
 
   {
     ViewModelCallbackWaiter waiter(this);
-    controller->OnTextChanged(base::ASCIIToUTF16("foobar"), browser());
+    controller->OnTextChanged(u"foobar", browser());
   }
   ASSERT_EQ(received_view_models_.size(), 1u);
   CommanderViewModel model = received_view_models_.back();
   ASSERT_EQ(model.items.size(), 3u);
-  EXPECT_EQ(model.items[0].title, base::ASCIIToUTF16("command"));
+  EXPECT_EQ(model.items[0].title, u"command");
 }
 
 TEST_F(CommanderControllerTest, ViewModelRetainsBoldRanges) {
   std::vector<std::unique_ptr<CommandSource>> sources;
   auto source = std::make_unique<TestCommandSource>(
       base::BindRepeating([=](const std::u16string&, Browser* browser) {
-        auto first = CreateNoOpCommandItem(base::ASCIIToUTF16("first"), 100);
-        auto second = CreateNoOpCommandItem(base::ASCIIToUTF16("second"), 99);
+        auto first = CreateNoOpCommandItem(u"first", 100);
+        auto second = CreateNoOpCommandItem(u"second", 99);
         first->matched_ranges.clear();
         first->matched_ranges.emplace_back(0, 2);
         first->matched_ranges.emplace_back(4, 1);
@@ -304,12 +299,12 @@
 
   {
     ViewModelCallbackWaiter waiter(this);
-    controller->OnTextChanged(base::ASCIIToUTF16("foobar"), browser());
+    controller->OnTextChanged(u"foobar", browser());
   }
   ASSERT_EQ(received_view_models_.size(), 1u);
   CommanderViewModel model = received_view_models_.back();
   // Ensure |first| is at index 0;
-  EXPECT_EQ(model.items[0].title, base::ASCIIToUTF16("first"));
+  EXPECT_EQ(model.items[0].title, u"first");
   std::vector<gfx::Range> first_ranges = {gfx::Range(0, 2), gfx::Range(4, 1)};
   std::vector<gfx::Range> second_ranges = {gfx::Range(1, 4)};
   EXPECT_EQ(model.items[0].matched_ranges, first_ranges);
@@ -323,8 +318,8 @@
   auto source = std::make_unique<TestCommandSource>(base::BindRepeating(
       [](bool* first_called_ptr, bool* second_called_ptr, const std::u16string&,
          Browser* browser) {
-        auto first = CreateNoOpCommandItem(base::ASCIIToUTF16("first"), 100);
-        auto second = CreateNoOpCommandItem(base::ASCIIToUTF16("second"), 99);
+        auto first = CreateNoOpCommandItem(u"first", 100);
+        auto second = CreateNoOpCommandItem(u"second", 99);
         first->command = base::BindOnce([](bool* called) { *called = true; },
                                         first_called_ptr);
         second->command = base::BindOnce([](bool* called) { *called = true; },
@@ -343,12 +338,12 @@
 
   {
     ViewModelCallbackWaiter waiter(this);
-    controller->OnTextChanged(base::ASCIIToUTF16("foobar"), browser());
+    controller->OnTextChanged(u"foobar", browser());
   }
   ASSERT_EQ(received_view_models_.size(), 1u);
   CommanderViewModel model = received_view_models_.back();
   // Ensure |first| is at index 0;
-  EXPECT_EQ(model.items[0].title, base::ASCIIToUTF16("first"));
+  EXPECT_EQ(model.items[0].title, u"first");
 
   {
     ViewModelCallbackWaiter waiter(this);
@@ -366,7 +361,7 @@
   bool item_called = false;
   auto source = std::make_unique<TestCommandSource>(base::BindRepeating(
       [](bool* called_ptr, const std::u16string&, Browser* browser) {
-        auto item = CreateNoOpCommandItem(base::ASCIIToUTF16("first"), 100);
+        auto item = CreateNoOpCommandItem(u"first", 100);
         item->command =
             base::BindOnce([](bool* called) { *called = true; }, called_ptr);
         CommandSource::CommandResults result;
@@ -382,7 +377,7 @@
 
   {
     ViewModelCallbackWaiter waiter(this);
-    controller->OnTextChanged(base::ASCIIToUTF16("foobar"), browser());
+    controller->OnTextChanged(u"foobar", browser());
   }
   ASSERT_EQ(received_view_models_.size(), 1u);
   CommanderViewModel model = received_view_models_.back();
@@ -397,7 +392,7 @@
   bool item_called = false;
   auto source = std::make_unique<TestCommandSource>(base::BindRepeating(
       [](bool* called_ptr, const std::u16string&, Browser* browser) {
-        auto item = CreateNoOpCommandItem(base::ASCIIToUTF16("first"), 100);
+        auto item = CreateNoOpCommandItem(u"first", 100);
         item->command =
             base::BindOnce([](bool* called) { *called = true; }, called_ptr);
         CommandSource::CommandResults result;
@@ -413,7 +408,7 @@
 
   {
     ViewModelCallbackWaiter waiter(this);
-    controller->OnTextChanged(base::ASCIIToUTF16("foobar"), browser());
+    controller->OnTextChanged(u"foobar", browser());
   }
   ASSERT_EQ(received_view_models_.size(), 1u);
   CommanderViewModel model = received_view_models_.back();
@@ -426,12 +421,12 @@
   std::vector<std::unique_ptr<CommandSource>> sources;
   auto source = std::make_unique<TestCommandSource>(
       base::BindRepeating([](const std::u16string&, Browser* browser) {
-        auto item = CreateNoOpCommandItem(base::ASCIIToUTF16("first"), 100);
+        auto item = CreateNoOpCommandItem(u"first", 100);
         CommandItem::CompositeCommandProvider noop =
             base::BindRepeating([](const std::u16string&) {
               return CommandSource::CommandResults();
             });
-        item->command = std::make_pair(base::ASCIIToUTF16("Do stuff"), noop);
+        item->command = std::make_pair(u"Do stuff", noop);
         CommandSource::CommandResults result;
         result.push_back(std::move(item));
         return result;
@@ -444,7 +439,7 @@
 
   {
     ViewModelCallbackWaiter waiter(this);
-    controller->OnTextChanged(base::ASCIIToUTF16("abracadabra"), browser());
+    controller->OnTextChanged(u"abracadabra", browser());
   }
   ASSERT_EQ(received_view_models_.size(), 1u);
   {
@@ -454,8 +449,7 @@
   }
   EXPECT_EQ(received_view_models_.back().action,
             CommanderViewModel::Action::kPrompt);
-  EXPECT_EQ(received_view_models_.back().prompt_text,
-            base::ASCIIToUTF16("Do stuff"));
+  EXPECT_EQ(received_view_models_.back().prompt_text, u"Do stuff");
 }
 
 TEST_F(CommanderControllerTest, OnTextChangedPassedToCompositeCommandProvider) {
@@ -464,15 +458,14 @@
   auto source = std::make_unique<TestCommandSource>(base::BindRepeating(
       [](std::u16string* passthrough_string, const std::u16string& string,
          Browser* browser) {
-        auto item = CreateNoOpCommandItem(base::ASCIIToUTF16("first"), 100);
+        auto item = CreateNoOpCommandItem(u"first", 100);
         CommandItem::CompositeCommandProvider provider = base::BindRepeating(
             [](std::u16string* out_string, const std::u16string& string) {
               *out_string = string;
               return CommandSource::CommandResults();
             },
             passthrough_string);
-        item->command =
-            std::make_pair(base::ASCIIToUTF16("Do stuff"), provider);
+        item->command = std::make_pair(u"Do stuff", provider);
         CommandSource::CommandResults result;
         result.push_back(std::move(item));
         return result;
@@ -486,7 +479,7 @@
 
   {
     ViewModelCallbackWaiter waiter(this);
-    controller->OnTextChanged(base::ASCIIToUTF16("abracadabra"), browser());
+    controller->OnTextChanged(u"abracadabra", browser());
   }
   ASSERT_EQ(received_view_models_.size(), 1u);
   {
@@ -496,8 +489,8 @@
                                   received_view_models_.back().result_set_id);
   }
 
-  controller->OnTextChanged(base::ASCIIToUTF16("hocus pocus"), browser());
-  EXPECT_EQ(received_string, base::ASCIIToUTF16("hocus pocus"));
+  controller->OnTextChanged(u"hocus pocus", browser());
+  EXPECT_EQ(received_string, u"hocus pocus");
 }
 
 TEST_F(CommanderControllerTest,
@@ -505,18 +498,16 @@
   std::vector<std::unique_ptr<CommandSource>> sources;
   auto source = std::make_unique<TestCommandSource>(
       base::BindRepeating([](const std::u16string&, Browser* browser) {
-        auto outer = CreateNoOpCommandItem(base::ASCIIToUTF16("outer"), 100);
+        auto outer = CreateNoOpCommandItem(u"outer", 100);
         CommandItem::CompositeCommandProvider provider =
             base::BindRepeating([](const std::u16string&) {
               CommandSource::CommandResults results;
-              auto inner =
-                  CreateNoOpCommandItem(base::ASCIIToUTF16("inner"), 100);
+              auto inner = CreateNoOpCommandItem(u"inner", 100);
               inner->command = base::MakeExpectedRunClosure(FROM_HERE);
               results.push_back(std::move(inner));
               return results;
             });
-        outer->command =
-            std::make_pair(base::ASCIIToUTF16("Do stuff"), provider);
+        outer->command = std::make_pair(u"Do stuff", provider);
         CommandSource::CommandResults result;
         result.push_back(std::move(outer));
         return result;
@@ -528,7 +519,7 @@
       &CommanderControllerTest::OnViewModelUpdated, base::Unretained(this)));
   {
     ViewModelCallbackWaiter waiter(this);
-    controller->OnTextChanged(base::ASCIIToUTF16("abracadabra"), browser());
+    controller->OnTextChanged(u"abracadabra", browser());
   }
 
   ASSERT_EQ(received_view_models_.size(), 1u);
@@ -542,11 +533,10 @@
   // this time.
   {
     ViewModelCallbackWaiter waiter(this);
-    controller->OnTextChanged(base::ASCIIToUTF16("hocus pocus"), browser());
+    controller->OnTextChanged(u"hocus pocus", browser());
   }
   ASSERT_EQ(received_view_models_.size(), 3u);
-  EXPECT_EQ(received_view_models_.back().items[0].title,
-            base::ASCIIToUTF16("inner"));
+  EXPECT_EQ(received_view_models_.back().items[0].title, u"inner");
 
   controller->OnCommandSelected(0, received_view_models_.back().result_set_id);
   // Inner command is an ExpectedRunClosure, so we will fail here if it wasn't
@@ -559,13 +549,12 @@
       &sources,
       std::make_unique<TestCommandSource>(
           base::BindRepeating([](const std::u16string&, Browser* browser) {
-            auto item = CreateNoOpCommandItem(base::ASCIIToUTF16("first"), 100);
+            auto item = CreateNoOpCommandItem(u"first", 100);
             CommandItem::CompositeCommandProvider noop =
                 base::BindRepeating([](const std::u16string&) {
                   return CommandSource::CommandResults();
                 });
-            item->command =
-                std::make_pair(base::ASCIIToUTF16("Do stuff"), noop);
+            item->command = std::make_pair(u"Do stuff", noop);
             CommandSource::CommandResults result;
             result.push_back(std::move(item));
             return result;
@@ -578,7 +567,7 @@
   // Prime the sources so we can select an item.
   {
     ViewModelCallbackWaiter waiter(this);
-    controller->OnTextChanged(base::ASCIIToUTF16("abracadabra"), browser());
+    controller->OnTextChanged(u"abracadabra", browser());
   }
   EXPECT_EQ(source->invocations().size(), 1u);
 
@@ -594,7 +583,7 @@
   // This should go to the provider and not be seen by the source.
   {
     ViewModelCallbackWaiter waiter(this);
-    controller->OnTextChanged(base::ASCIIToUTF16("alakazam"), browser());
+    controller->OnTextChanged(u"alakazam", browser());
   }
   EXPECT_EQ(source->invocations().size(), 1u);
 
@@ -602,10 +591,10 @@
   // Composite command was cancelled, so the source should see this one.
   {
     ViewModelCallbackWaiter waiter(this);
-    controller->OnTextChanged(base::ASCIIToUTF16("hocus pocus"), browser());
+    controller->OnTextChanged(u"hocus pocus", browser());
   }
   EXPECT_EQ(source->invocations().size(), 2u);
-  EXPECT_EQ(source->invocations().back(), base::ASCIIToUTF16("hocus pocus"));
+  EXPECT_EQ(source->invocations().back(), u"hocus pocus");
 }
 
 }  // namespace commander
diff --git a/chrome/browser/ui/commander/entity_match_unittest.cc b/chrome/browser/ui/commander/entity_match_unittest.cc
index 657e7fb3..9bdcb97 100644
--- a/chrome/browser/ui/commander/entity_match_unittest.cc
+++ b/chrome/browser/ui/commander/entity_match_unittest.cc
@@ -107,8 +107,7 @@
   auto browser_with_match = CreateAndActivateBrowser("Orange juice");
   auto browser_without_match = CreateAndActivateBrowser("Aqua regia");
 
-  auto matches =
-      WindowsMatchingInput(browser(), base::ASCIIToUTF16("orange"), true);
+  auto matches = WindowsMatchingInput(browser(), u"orange", true);
   ASSERT_EQ(matches.size(), 1u);
   EXPECT_EQ(matches.at(0).browser, browser_with_match.get());
 }
@@ -118,8 +117,7 @@
   auto browser_good_match =
       CreateAndActivateBrowser("Oracular Nouns Gesture Electrically");
 
-  auto matches =
-      WindowsMatchingInput(browser(), base::ASCIIToUTF16("orange"), true);
+  auto matches = WindowsMatchingInput(browser(), u"orange", true);
   ASSERT_EQ(matches.size(), 2u);
   base::ranges::sort(matches, std::greater<>(), &WindowMatch::score);
   EXPECT_EQ(matches.at(0).browser, browser_best_match.get());
@@ -130,14 +128,14 @@
   auto browser2 = CreateAndActivateBrowser("Boop");
 
   // Browser 2 was activated last, so we expect it to be the top match.
-  auto matches = WindowsMatchingInput(browser(), base::ASCIIToUTF16(""), true);
+  auto matches = WindowsMatchingInput(browser(), u"", true);
   ASSERT_EQ(matches.size(), 2u);
   base::ranges::sort(matches, std::greater<>(), &WindowMatch::score);
   EXPECT_EQ(matches.at(0).browser, browser2.get());
 
   BrowserList::GetInstance()->SetLastActive(browser1.get());
   // Activating browser 1 should have brought it to the top.
-  matches = WindowsMatchingInput(browser(), base::ASCIIToUTF16(""), true);
+  matches = WindowsMatchingInput(browser(), u"", true);
   ASSERT_EQ(matches.size(), 2u);
   base::ranges::sort(matches, std::greater<>(), &WindowMatch::score);
   EXPECT_EQ(matches.at(0).browser, browser1.get());
diff --git a/chrome/browser/ui/commander/fuzzy_finder_unittest.cc b/chrome/browser/ui/commander/fuzzy_finder_unittest.cc
index d81549024..b7366a2 100644
--- a/chrome/browser/ui/commander/fuzzy_finder_unittest.cc
+++ b/chrome/browser/ui/commander/fuzzy_finder_unittest.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/ui/commander/fuzzy_finder.h"
 
 #include "base/i18n/case_conversion.h"
-#include "base/strings/utf_string_conversions.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace commander {
@@ -22,18 +21,15 @@
 
 TEST(CommanderFuzzyFinder, NonmatchIsZero) {
   std::vector<gfx::Range> ranges;
-  EXPECT_EQ(0, FuzzyFind(base::ASCIIToUTF16("orange"),
-                         base::ASCIIToUTF16("orangutan"), &ranges));
+  EXPECT_EQ(0, FuzzyFind(u"orange", u"orangutan", &ranges));
   EXPECT_TRUE(ranges.empty());
-  EXPECT_EQ(0, FuzzyFind(base::ASCIIToUTF16("elephant"),
-                         base::ASCIIToUTF16("orangutan"), &ranges));
+  EXPECT_EQ(0, FuzzyFind(u"elephant", u"orangutan", &ranges));
   EXPECT_TRUE(ranges.empty());
 }
 
 TEST(CommanderFuzzyFinder, ExactMatchIsOne) {
   std::vector<gfx::Range> ranges;
-  EXPECT_EQ(1, FuzzyFind(base::ASCIIToUTF16("orange"),
-                         base::ASCIIToUTF16("orange"), &ranges));
+  EXPECT_EQ(1, FuzzyFind(u"orange", u"orange", &ranges));
   EXPECT_EQ(ranges, std::vector<gfx::Range>({{0, 6}}));
 }
 
@@ -41,8 +37,7 @@
 // tested in ExactMatchIsOne() above.
 TEST(CommanderFuzzyFinder, NeedleHaystackSameLength) {
   std::vector<gfx::Range> ranges;
-  EXPECT_EQ(0, FuzzyFind(base::ASCIIToUTF16("ranges"),
-                         base::ASCIIToUTF16("orange"), &ranges));
+  EXPECT_EQ(0, FuzzyFind(u"ranges", u"orange", &ranges));
   EXPECT_TRUE(ranges.empty());
 }
 
@@ -50,14 +45,13 @@
 // coverage rather than ensuring the path is taken).
 TEST(CommanderFuzzyFinder, SingleCharNeedle) {
   std::vector<gfx::Range> ranges;
-  FuzzyFinder finder(base::ASCIIToUTF16("o"));
+  FuzzyFinder finder(u"o");
 
-  double prefix_score = finder.Find(base::ASCIIToUTF16("orange"), &ranges);
+  double prefix_score = finder.Find(u"orange", &ranges);
   EXPECT_EQ(ranges, std::vector<gfx::Range>({{0, 1}}));
-  double internal_score = finder.Find(base::ASCIIToUTF16("phone"), &ranges);
+  double internal_score = finder.Find(u"phone", &ranges);
   EXPECT_EQ(ranges, std::vector<gfx::Range>({{2, 3}}));
-  double boundary_score =
-      finder.Find(base::ASCIIToUTF16("phone operator"), &ranges);
+  double boundary_score = finder.Find(u"phone operator", &ranges);
   EXPECT_EQ(ranges, std::vector<gfx::Range>({{6, 7}}));
 
   // Expected ordering:
@@ -69,23 +63,21 @@
   EXPECT_GT(boundary_score, internal_score);
 
   // ...and non-matches should have score = 0.
-  EXPECT_EQ(0, finder.Find(base::ASCIIToUTF16("aquarium"), &ranges));
+  EXPECT_EQ(0, finder.Find(u"aquarium", &ranges));
   EXPECT_TRUE(ranges.empty());
 }
 
 TEST(CommanderFuzzyFinder, CaseInsensitive) {
   std::vector<gfx::Range> ranges;
-  EXPECT_EQ(1, FuzzyFind(base::ASCIIToUTF16("orange"),
-                         base::ASCIIToUTF16("Orange"), &ranges));
+  EXPECT_EQ(1, FuzzyFind(u"orange", u"Orange", &ranges));
   EXPECT_EQ(ranges, std::vector<gfx::Range>({{0, 6}}));
 }
 
 TEST(CommanderFuzzyFinder, PrefixRanksHigherThanInternal) {
   std::vector<gfx::Range> ranges;
-  FuzzyFinder finder(base::ASCIIToUTF16("orange"));
-  double prefix_rank = finder.Find(base::ASCIIToUTF16("Orange juice"), &ranges);
-  double non_prefix_rank =
-      finder.Find(base::ASCIIToUTF16("William of Orange"), &ranges);
+  FuzzyFinder finder(u"orange");
+  double prefix_rank = finder.Find(u"Orange juice", &ranges);
+  double non_prefix_rank = finder.Find(u"William of Orange", &ranges);
 
   EXPECT_GT(prefix_rank, 0);
   EXPECT_GT(non_prefix_rank, 0);
@@ -96,24 +88,20 @@
 
 TEST(CommanderFuzzyFinder, NeedleLongerThanHaystack) {
   std::vector<gfx::Range> ranges;
-  EXPECT_EQ(0, FuzzyFind(base::ASCIIToUTF16("orange juice"),
-                         base::ASCIIToUTF16("orange"), &ranges));
+  EXPECT_EQ(0, FuzzyFind(u"orange juice", u"orange", &ranges));
   EXPECT_TRUE(ranges.empty());
 }
 
 TEST(CommanderFuzzyFinder, Noncontiguous) {
   std::vector<gfx::Range> ranges;
-  EXPECT_GT(FuzzyFind(base::ASCIIToUTF16("tuot"),
-                      base::UTF8ToUTF16("Tlön, Uqbar, Orbis Tertius"), &ranges),
-            0);
+  EXPECT_GT(FuzzyFind(u"tuot", u"Tlön, Uqbar, Orbis Tertius", &ranges), 0);
   EXPECT_EQ(ranges,
             std::vector<gfx::Range>({{0, 1}, {6, 7}, {13, 14}, {19, 20}}));
 }
 
 TEST(CommanderFuzzyFinder, EmptyStringDoesNotMatch) {
   std::vector<gfx::Range> ranges;
-  EXPECT_EQ(0, FuzzyFind(base::ASCIIToUTF16(""), base::ASCIIToUTF16("orange"),
-                         &ranges));
+  EXPECT_EQ(0, FuzzyFind(u"", u"orange", &ranges));
   EXPECT_TRUE(ranges.empty());
 }
 
diff --git a/chrome/browser/ui/commander/simple_command_source.cc b/chrome/browser/ui/commander/simple_command_source.cc
index 36309ab..3020218 100644
--- a/chrome/browser/ui/commander/simple_command_source.cc
+++ b/chrome/browser/ui/commander/simple_command_source.cc
@@ -6,7 +6,6 @@
 
 #include "base/bind.h"
 #include "base/i18n/case_conversion.h"
-#include "base/strings/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/ui/accelerator_utils.h"
 #include "chrome/browser/ui/browser_commands.h"
@@ -37,33 +36,32 @@
       {IDC_FIND, l10n_util::GetStringUTF16(IDS_FIND)},
       {IDC_SAVE_PAGE, l10n_util::GetStringUTF16(IDS_SAVE_PAGE)},
       {IDC_PRINT, l10n_util::GetStringUTF16(IDS_PRINT)},
-      {IDC_SHOW_HISTORY, base::ASCIIToUTF16("Show history")},
-      {IDC_RELOAD, base::ASCIIToUTF16("Reload")},
-      {IDC_NEW_TAB, base::ASCIIToUTF16("Create new tab")},
-      {IDC_RESTORE_TAB, base::ASCIIToUTF16("Open recently closed tab")},
-      {IDC_NEW_WINDOW, base::ASCIIToUTF16("Create new window")},
-      {IDC_NEW_INCOGNITO_WINDOW,
-       base::ASCIIToUTF16("Create new incognito window")},
-      {IDC_BOOKMARK_THIS_TAB, base::ASCIIToUTF16("Bookmark this tab")},
-      {IDC_BOOKMARK_ALL_TABS, base::ASCIIToUTF16("Bookmark all tabs")},
-      {IDC_BACK, base::ASCIIToUTF16("Back")},
-      {IDC_FORWARD, base::ASCIIToUTF16("Forward")},
-      {IDC_ZOOM_PLUS, base::ASCIIToUTF16("Zoom in")},
-      {IDC_ZOOM_MINUS, base::ASCIIToUTF16("Zoom out")},
-      {IDC_ZOOM_NORMAL, base::ASCIIToUTF16("Reset zoom")},
-      {IDC_VIEW_SOURCE, base::ASCIIToUTF16("View page source")},
-      {IDC_EXIT, base::ASCIIToUTF16("Quit")},
-      {IDC_EMAIL_PAGE_LOCATION, base::ASCIIToUTF16("Email page location")},
-      {IDC_FOCUS_LOCATION, base::ASCIIToUTF16("Focus location bar")},
-      {IDC_FOCUS_TOOLBAR, base::ASCIIToUTF16("Focus toolbar")},
-      {IDC_OPEN_FILE, base::ASCIIToUTF16("Open file")},
-      {IDC_TASK_MANAGER, base::ASCIIToUTF16("Show task manager")},
-      {IDC_SHOW_BOOKMARK_MANAGER, base::ASCIIToUTF16("Show bookmark manager")},
-      {IDC_SHOW_DOWNLOADS, base::ASCIIToUTF16("Show downloads")},
-      {IDC_CLEAR_BROWSING_DATA, base::ASCIIToUTF16("Clear browsing data")},
-      {IDC_OPTIONS, base::ASCIIToUTF16("Show settings")},
-      {IDC_SHOW_AVATAR_MENU, base::ASCIIToUTF16("Switch profile")},
-      {IDC_DEV_TOOLS_TOGGLE, base::ASCIIToUTF16("Toggle developer tools")},
+      {IDC_SHOW_HISTORY, u"Show history"},
+      {IDC_RELOAD, u"Reload"},
+      {IDC_NEW_TAB, u"Create new tab"},
+      {IDC_RESTORE_TAB, u"Open recently closed tab"},
+      {IDC_NEW_WINDOW, u"Create new window"},
+      {IDC_NEW_INCOGNITO_WINDOW, u"Create new incognito window"},
+      {IDC_BOOKMARK_THIS_TAB, u"Bookmark this tab"},
+      {IDC_BOOKMARK_ALL_TABS, u"Bookmark all tabs"},
+      {IDC_BACK, u"Back"},
+      {IDC_FORWARD, u"Forward"},
+      {IDC_ZOOM_PLUS, u"Zoom in"},
+      {IDC_ZOOM_MINUS, u"Zoom out"},
+      {IDC_ZOOM_NORMAL, u"Reset zoom"},
+      {IDC_VIEW_SOURCE, u"View page source"},
+      {IDC_EXIT, u"Quit"},
+      {IDC_EMAIL_PAGE_LOCATION, u"Email page location"},
+      {IDC_FOCUS_LOCATION, u"Focus location bar"},
+      {IDC_FOCUS_TOOLBAR, u"Focus toolbar"},
+      {IDC_OPEN_FILE, u"Open file"},
+      {IDC_TASK_MANAGER, u"Show task manager"},
+      {IDC_SHOW_BOOKMARK_MANAGER, u"Show bookmark manager"},
+      {IDC_SHOW_DOWNLOADS, u"Show downloads"},
+      {IDC_CLEAR_BROWSING_DATA, u"Clear browsing data"},
+      {IDC_OPTIONS, u"Show settings"},
+      {IDC_SHOW_AVATAR_MENU, u"Switch profile"},
+      {IDC_DEV_TOOLS_TOGGLE, u"Toggle developer tools"},
   };
   CommandSource::CommandResults results;
   FuzzyFinder finder(input);
diff --git a/chrome/browser/ui/commander/tab_command_source.cc b/chrome/browser/ui/commander/tab_command_source.cc
index b881c85..c2f8cb7 100644
--- a/chrome/browser/ui/commander/tab_command_source.cc
+++ b/chrome/browser/ui/commander/tab_command_source.cc
@@ -8,7 +8,6 @@
 #include <string>
 
 #include "base/bind.h"
-#include "base/strings/utf_string_conversions.h"
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/ui/accelerator_utils.h"
 #include "chrome/browser/ui/browser.h"
@@ -339,8 +338,7 @@
   TabStripModel* tab_strip_model = browser->tab_strip_model();
   // TODO(lgrey): Temporarily using hardcoded English titles instead of
   // translated strings so we can experiment without adding translation load.
-  if (auto item = ItemForTitle(base::ASCIIToUTF16("Close current tab"), finder,
-                               &ranges)) {
+  if (auto item = ItemForTitle(u"Close current tab", finder, &ranges)) {
     item->command =
         base::BindOnce(&chrome::CloseTab, base::Unretained(browser));
     ui::Accelerator accelerator;
@@ -349,16 +347,14 @@
     results.push_back(std::move(item));
   }
   if (chrome::CanCloseOtherTabs(browser)) {
-    if (auto item = ItemForTitle(base::ASCIIToUTF16("Close other tabs"), finder,
-                                 &ranges)) {
+    if (auto item = ItemForTitle(u"Close other tabs", finder, &ranges)) {
       item->command =
           base::BindOnce(&chrome::CloseOtherTabs, base::Unretained(browser));
       results.push_back(std::move(item));
     }
   }
   if (chrome::CanCloseTabsToRight(browser)) {
-    if (auto item = ItemForTitle(base::ASCIIToUTF16("Close tabs to the right"),
-                                 finder, &ranges)) {
+    if (auto item = ItemForTitle(u"Close tabs to the right", finder, &ranges)) {
       item->command =
           base::BindOnce(&chrome::CloseTabsToRight, base::Unretained(browser));
       results.push_back(std::move(item));
@@ -366,8 +362,7 @@
   }
 
   if (CanCloseTabsToLeft(tab_strip_model)) {
-    if (auto item = ItemForTitle(base::ASCIIToUTF16("Close tabs to the left"),
-                                 finder, &ranges)) {
+    if (auto item = ItemForTitle(u"Close tabs to the left", finder, &ranges)) {
       item->command =
           base::BindOnce(&CloseTabsToLeft, base::Unretained(browser));
       results.push_back(std::move(item));
@@ -375,8 +370,7 @@
   }
 
   if (HasUnpinnedTabs(tab_strip_model)) {
-    if (auto item = ItemForTitle(base::ASCIIToUTF16("Close unpinned tabs"),
-                                 finder, &ranges)) {
+    if (auto item = ItemForTitle(u"Close unpinned tabs", finder, &ranges)) {
       item->command =
           base::BindOnce(&CloseUnpinnedTabs, base::Unretained(browser));
       results.push_back(std::move(item));
@@ -395,10 +389,9 @@
   }
 
   if (CanMoveTabsToExistingWindow(browser)) {
-    if (auto item = ItemForTitle(base::ASCIIToUTF16("Move tabs to window..."),
-                                 finder, &ranges)) {
+    if (auto item = ItemForTitle(u"Move tabs to window...", finder, &ranges)) {
       item->command = std::make_pair(
-          base::ASCIIToUTF16("Move tabs to..."),
+          u"Move tabs to...",
           base::BindRepeating(&MoveTabsToWindowCommandsForWindowsMatching,
                               base::Unretained(browser)));
       results.push_back(std::move(item));
diff --git a/chrome/browser/ui/commander/window_command_source.cc b/chrome/browser/ui/commander/window_command_source.cc
index 6fa50a25..35a4a70 100644
--- a/chrome/browser/ui/commander/window_command_source.cc
+++ b/chrome/browser/ui/commander/window_command_source.cc
@@ -6,7 +6,6 @@
 
 #include <numeric>
 
-#include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_list.h"
@@ -97,9 +96,8 @@
   std::vector<gfx::Range> ranges;
   // TODO(lgrey): Temporarily using untranslated strings since it's not
   // yet clear which commands will ship.
-  std::u16string open_title = base::ASCIIToUTF16("Switch to window...");
-  std::u16string merge_title =
-      base::ASCIIToUTF16("Merge current window into...");
+  std::u16string open_title = u"Switch to window...";
+  std::u16string merge_title = u"Merge current window into...";
 
   double score = finder.Find(open_title, &ranges);
   if (score > 0) {
diff --git a/chrome/browser/ui/extensions/extension_message_bubble_bridge_unittest.cc b/chrome/browser/ui/extensions/extension_message_bubble_bridge_unittest.cc
index aac47809..22fbb815 100644
--- a/chrome/browser/ui/extensions/extension_message_bubble_bridge_unittest.cc
+++ b/chrome/browser/ui/extensions/extension_message_bubble_bridge_unittest.cc
@@ -10,9 +10,8 @@
 #include "base/values.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/extensions/extension_service_test_with_install.h"
-#include "chrome/browser/extensions/extension_web_ui_override_registrar.h"
-#include "chrome/browser/extensions/ntp_overridden_bubble_delegate.h"
 #include "chrome/browser/extensions/suspicious_extension_bubble_delegate.h"
+#include "chrome/browser/extensions/test_extension_message_bubble_delegate.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/toolbar/test_toolbar_actions_bar_bubble_delegate.h"
 #include "chrome/browser/ui/toolbar/toolbar_actions_bar_bubble_delegate.h"
@@ -40,11 +39,6 @@
 
 namespace {
 
-std::unique_ptr<KeyedService> BuildOverrideRegistrar(
-    content::BrowserContext* context) {
-  return std::make_unique<extensions::ExtensionWebUIOverrideRegistrar>(context);
-}
-
 std::unique_ptr<KeyedService> BuildToolbarModel(
     content::BrowserContext* context) {
   return std::make_unique<ToolbarActionsModel>(
@@ -72,11 +66,6 @@
     params.window = browser_window_.get();
     browser_ = std::unique_ptr<Browser>(Browser::Create(params));
 
-    extensions::ExtensionWebUIOverrideRegistrar::GetFactoryInstance()
-        ->SetTestingFactory(browser()->profile(),
-                            base::BindRepeating(&BuildOverrideRegistrar));
-    extensions::ExtensionWebUIOverrideRegistrar::GetFactoryInstance()->Get(
-        browser()->profile());
     ToolbarActionsModelFactory::GetInstance()->SetTestingFactory(
         browser()->profile(), base::BindRepeating(&BuildToolbarModel));
   }
@@ -95,53 +84,59 @@
 
 TEST_F(ExtensionMessageBubbleBridgeUnitTest,
        TestGetExtraViewInfoMethodWithNormalSettingsOverrideExtension) {
-  base::FilePath path(data_dir().AppendASCII("api_test/override/newtab/"));
-  EXPECT_NE(nullptr, PackAndInstallCRX(path, INSTALL_NEW));
+  scoped_refptr<const extensions::Extension> extension =
+      extensions::ExtensionBuilder("extension").Build();
+  ASSERT_TRUE(extension);
+  service()->AddExtension(extension.get());
 
-  std::unique_ptr<extensions::ExtensionMessageBubbleController>
-      ntp_bubble_controller(new extensions::ExtensionMessageBubbleController(
-          new extensions::NtpOverriddenBubbleDelegate(browser()->profile()),
-          browser()));
+  auto delegate =
+      std::make_unique<extensions::TestExtensionMessageBubbleDelegate>(
+          profile());
+  delegate->IncludeExtensionId(extension->id());
+  auto controller =
+      std::make_unique<extensions::ExtensionMessageBubbleController>(
+          delegate.release(), browser());
 
-  ASSERT_EQ(1U, ntp_bubble_controller->GetExtensionList().size());
+  ASSERT_EQ(1U, controller->GetExtensionList().size());
 
-  std::unique_ptr<ToolbarActionsBarBubbleDelegate> bridge(
-      new ExtensionMessageBubbleBridge(std::move(ntp_bubble_controller)));
+  std::unique_ptr<ToolbarActionsBarBubbleDelegate> bridge =
+      std::make_unique<ExtensionMessageBubbleBridge>(std::move(controller));
 
   std::unique_ptr<ToolbarActionsBarBubbleDelegate::ExtraViewInfo>
       extra_view_info = bridge->GetExtraViewInfo();
 
   EXPECT_FALSE(extra_view_info->resource);
-  EXPECT_EQ(l10n_util::GetStringUTF16(IDS_LEARN_MORE), extra_view_info->text);
+  EXPECT_EQ(u"Learn more", extra_view_info->text);
   EXPECT_TRUE(extra_view_info->is_learn_more);
 
-  EXPECT_EQ(
-      l10n_util::GetStringUTF16(IDS_EXTENSION_CONTROLLED_RESTORE_SETTINGS),
-      bridge->GetActionButtonText());
+  EXPECT_EQ(u"OK", bridge->GetActionButtonText());
 }
 
 TEST_F(ExtensionMessageBubbleBridgeUnitTest,
        TestGetExtraViewInfoMethodWithPolicyInstalledSettingsOverrideExtension) {
-  base::FilePath path(data_dir().AppendASCII("api_test/override/newtab/"));
-  EXPECT_NE(nullptr,
-            PackAndInstallCRX(path, extensions::Manifest::EXTERNAL_POLICY,
-                              INSTALL_NEW));
+  scoped_refptr<const extensions::Extension> extension =
+      extensions::ExtensionBuilder("extension")
+          .SetLocation(extensions::mojom::ManifestLocation::kExternalPolicy)
+          .Build();
+  ASSERT_TRUE(extension);
+  service()->AddExtension(extension.get());
 
-  std::unique_ptr<extensions::ExtensionMessageBubbleController>
-      ntp_bubble_controller(new extensions::ExtensionMessageBubbleController(
-          new extensions::NtpOverriddenBubbleDelegate(browser()->profile()),
-          browser()));
+  auto delegate =
+      std::make_unique<extensions::TestExtensionMessageBubbleDelegate>(
+          profile());
+  delegate->IncludeExtensionId(extension->id());
+  auto controller =
+      std::make_unique<extensions::ExtensionMessageBubbleController>(
+          delegate.release(), browser());
 
-  ASSERT_EQ(1U, ntp_bubble_controller->GetExtensionList().size());
+  ASSERT_EQ(1U, controller->GetExtensionList().size());
 
-  std::unique_ptr<ToolbarActionsBarBubbleDelegate> bridge(
-      new ExtensionMessageBubbleBridge(std::move(ntp_bubble_controller)));
+  std::unique_ptr<ToolbarActionsBarBubbleDelegate> bridge =
+      std::make_unique<ExtensionMessageBubbleBridge>(std::move(controller));
 
   std::unique_ptr<ToolbarActionsBarBubbleDelegate::ExtraViewInfo>
       extra_view_info = bridge->GetExtraViewInfo();
 
-  extra_view_info = bridge->GetExtraViewInfo();
-
   EXPECT_EQ(&vector_icons::kBusinessIcon, extra_view_info->resource);
   EXPECT_EQ(l10n_util::GetStringUTF16(IDS_EXTENSIONS_INSTALLED_BY_ADMIN),
             extra_view_info->text);
diff --git a/chrome/browser/ui/global_media_controls/media_notification_service.cc b/chrome/browser/ui/global_media_controls/media_notification_service.cc
index 97650a12..d04eab4 100644
--- a/chrome/browser/ui/global_media_controls/media_notification_service.cc
+++ b/chrome/browser/ui/global_media_controls/media_notification_service.cc
@@ -535,6 +535,10 @@
   if (presentation_request_notification_producer_) {
     presentation_request_notification_producer_
         ->OnStartPresentationContextCreated(std::move(context));
+  } else {
+    context->InvokeErrorCallback(blink::mojom::PresentationError(
+        blink::mojom::PresentationErrorType::PRESENTATION_REQUEST_CANCELLED,
+        "Unable to start presentation."));
   }
 }
 
diff --git a/chrome/browser/ui/global_media_controls/presentation_request_notification_producer.cc b/chrome/browser/ui/global_media_controls/presentation_request_notification_producer.cc
index df3f39d..37fc643 100644
--- a/chrome/browser/ui/global_media_controls/presentation_request_notification_producer.cc
+++ b/chrome/browser/ui/global_media_controls/presentation_request_notification_producer.cc
@@ -118,7 +118,7 @@
 }
 
 void PresentationRequestNotificationProducer::AfterMediaDialogClosed() {
-  item_.reset();
+  DeleteItemForPresentationRequest("Dialog closed.");
   if (presentation_manager_)
     presentation_manager_->RemoveObserver(this);
   presentation_manager_ = nullptr;
@@ -133,10 +133,9 @@
   // notification for a non-default request, we ignored changes in the
   // default request.
   if (!HasItemForNonDefaultRequest()) {
+    DeleteItemForPresentationRequest("Default presentation changed.");
     if (presentation_request) {
       CreateItemForPresentationRequest(*presentation_request, nullptr);
-    } else {
-      item_.reset();
     }
   }
 }
@@ -154,3 +153,13 @@
   DCHECK(web_contents);
   notification_service_->AddSupplementalNotification(item_->id(), web_contents);
 }
+
+void PresentationRequestNotificationProducer::DeleteItemForPresentationRequest(
+    const std::string& message) {
+  if (item_) {
+    item_->context()->InvokeErrorCallback(blink::mojom::PresentationError(
+        blink::mojom::PresentationErrorType::PRESENTATION_REQUEST_CANCELLED,
+        message));
+    item_.reset();
+  }
+}
diff --git a/chrome/browser/ui/global_media_controls/presentation_request_notification_producer.h b/chrome/browser/ui/global_media_controls/presentation_request_notification_producer.h
index 76fd8e6..ebc587d 100644
--- a/chrome/browser/ui/global_media_controls/presentation_request_notification_producer.h
+++ b/chrome/browser/ui/global_media_controls/presentation_request_notification_producer.h
@@ -78,6 +78,7 @@
   void CreateItemForPresentationRequest(
       const content::PresentationRequest& request,
       std::unique_ptr<media_router::StartPresentationContext> context);
+  void DeleteItemForPresentationRequest(const std::string& message);
 
   // Returns true if there is an item, and the item is for a non-default
   // presentation request.
diff --git a/chrome/browser/ui/passwords/password_generation_popup_controller_impl.h b/chrome/browser/ui/passwords/password_generation_popup_controller_impl.h
index 42037e22..f291dafb 100644
--- a/chrome/browser/ui/passwords/password_generation_popup_controller_impl.h
+++ b/chrome/browser/ui/passwords/password_generation_popup_controller_impl.h
@@ -16,8 +16,8 @@
 #include "chrome/browser/ui/autofill/popup_controller_common.h"
 #include "chrome/browser/ui/passwords/password_generation_popup_controller.h"
 #include "components/autofill/content/browser/key_press_handler_manager.h"
-#include "components/autofill/core/common/renderer_id.h"
 #include "components/autofill/core/common/signatures.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "ui/gfx/geometry/rect.h"
diff --git a/chrome/browser/ui/passwords/password_generation_popup_controller_impl_unittest.cc b/chrome/browser/ui/passwords/password_generation_popup_controller_impl_unittest.cc
index a473a49..6042814 100644
--- a/chrome/browser/ui/passwords/password_generation_popup_controller_impl_unittest.cc
+++ b/chrome/browser/ui/passwords/password_generation_popup_controller_impl_unittest.cc
@@ -9,7 +9,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "components/autofill/core/common/password_generation_util.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/stub_password_manager_driver.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/ui/passwords/password_generation_popup_view_browsertest.cc b/chrome/browser/ui/passwords/password_generation_popup_view_browsertest.cc
index 9347afe..8c3d795 100644
--- a/chrome/browser/ui/passwords/password_generation_popup_view_browsertest.cc
+++ b/chrome/browser/ui/passwords/password_generation_popup_view_browsertest.cc
@@ -12,7 +12,7 @@
 #include "chrome/browser/ui/passwords/password_generation_popup_view_tester.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/test/base/in_process_browser_test.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/content/browser/content_password_manager_driver.h"
 #include "components/password_manager/content/browser/content_password_manager_driver_factory.h"
 #include "content/public/test/browser_test.h"
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc
index 94336ec..ac6f0e0 100644
--- a/chrome/browser/ui/tabs/tab_strip_model.cc
+++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -1284,9 +1284,13 @@
     case CommandMoveToExistingWindow:
       return true;
 
-    case CommandMoveTabsToNewWindow:
-      return delegate()->CanMoveTabsToWindow(
-          GetIndicesForCommand(context_index));
+    case CommandMoveTabsToNewWindow: {
+      std::vector<int> indices = GetIndicesForCommand(context_index);
+      const bool would_leave_strip_empty =
+          static_cast<int>(indices.size()) == count();
+      return !would_leave_strip_empty &&
+             delegate()->CanMoveTabsToWindow(indices);
+    }
 
     default:
       NOTREACHED();
diff --git a/chrome/browser/ui/views/extensions/extension_dialog.cc b/chrome/browser/ui/views/extensions/extension_dialog.cc
index 3329ac7..f2e89cc 100644
--- a/chrome/browser/ui/views/extensions/extension_dialog.cc
+++ b/chrome/browser/ui/views/extensions/extension_dialog.cc
@@ -81,39 +81,11 @@
   extension_view_->SetPreferredSize(gfx::Size(width, height));
 }
 
-void ExtensionDialog::WindowClosing() {
+void ExtensionDialog::OnWindowClosing() {
   if (observer_)
     observer_->ExtensionDialogClosing(this);
 }
 
-void ExtensionDialog::DeleteDelegate() {
-  // The window has finished closing.  Allow ourself to be deleted.
-  Release();
-}
-
-// TODO(ellyjones): Are either of these overrides necessary? It seems like
-// extension_view_ is always this dialog's contents view, in which case
-// GetWidget will already behave this way.
-views::Widget* ExtensionDialog::GetWidget() {
-  return extension_view_ ? extension_view_->GetWidget() : nullptr;
-}
-
-const views::Widget* ExtensionDialog::GetWidget() const {
-  return extension_view_ ? extension_view_->GetWidget() : nullptr;
-}
-
-views::View* ExtensionDialog::GetContentsView() {
-  if (!extension_view_) {
-    extension_view_ = new ExtensionViewViews(host_.get());  // Owned by caller.
-
-    // Show a white background while the extension loads.  This is prettier than
-    // flashing a black unfilled window frame.
-    extension_view_->SetBackground(views::CreateSolidBackground(SK_ColorWHITE));
-  }
-
-  return extension_view_;
-}
-
 void ExtensionDialog::OnExtensionHostDidStopFirstLoad(
     const extensions::ExtensionHost* host) {
   DCHECK_EQ(host, host_.get());
@@ -154,7 +126,11 @@
   SetButtons(ui::DIALOG_BUTTON_NONE);
   set_use_custom_frame(false);
 
-  AddRef();  // Balanced in DeleteDelegate();
+  AddRef();
+  RegisterDeleteDelegateCallback(
+      base::BindOnce(&ExtensionDialog::Release, base::Unretained(this)));
+  RegisterWindowClosingCallback(base::BindOnce(
+      &ExtensionDialog::OnWindowClosing, base::Unretained(this)));
 
   extension_host_observation_.Observe(host_.get());
   process_manager_observation_.Observe(
@@ -166,6 +142,16 @@
   SetShowTitle(!init_params.title.empty());
   SetTitle(init_params.title);
 
+  extension_view_ =
+      SetContentsView(std::make_unique<ExtensionViewViews>(host_.get()));
+
+  // Show a white background while the extension loads.  This is prettier than
+  // flashing a black unfilled window frame.
+  extension_view_->SetBackground(views::CreateSolidBackground(SK_ColorWHITE));
+  extension_view_->SetPreferredSize(init_params.size);
+  extension_view_->SetMinimumSize(init_params.min_size);
+  extension_view_->SetVisible(true);
+
   bool can_resize = true;
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   // Prevent dialog resize mouse cursor in tablet mode, crbug.com/453634.
@@ -227,13 +213,6 @@
   // TODO(jamescook): Remove redundant call to Activate()?
   window->Activate();
 
-  // Creating the Widget should have called GetContentsView() and created
-  // |extension_view_|.
-  DCHECK(extension_view_);
-  extension_view_->SetPreferredSize(init_params.size);
-  extension_view_->SetMinimumSize(init_params.min_size);
-  extension_view_->SetVisible(true);
-
   // Ensure the DOM JavaScript can respond immediately to keyboard shortcuts.
   host_->host_contents()->Focus();
 }
diff --git a/chrome/browser/ui/views/extensions/extension_dialog.h b/chrome/browser/ui/views/extensions/extension_dialog.h
index df46fc3..707c8c9 100644
--- a/chrome/browser/ui/views/extensions/extension_dialog.h
+++ b/chrome/browser/ui/views/extensions/extension_dialog.h
@@ -92,13 +92,6 @@
 
   extensions::ExtensionViewHost* host() const { return host_.get(); }
 
-  // views::DialogDelegate:
-  void WindowClosing() override;
-  void DeleteDelegate() override;
-  views::Widget* GetWidget() override;
-  const views::Widget* GetWidget() const override;
-  views::View* GetContentsView() override;
-
   // extensions::ExtensionHostObserver:
   void OnExtensionHostDidStopFirstLoad(
       const extensions::ExtensionHost* host) override;
@@ -121,6 +114,8 @@
                   gfx::NativeWindow parent_window,
                   const InitParams& init_params);
 
+  void OnWindowClosing();
+
   // Window Title
   std::u16string window_title_;
 
diff --git a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc
index dbd410d..46833a28 100644
--- a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc
+++ b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc
@@ -115,8 +115,8 @@
   SetButtons(ui::DIALOG_BUTTON_NONE);
   SetModalType(ui::MODAL_TYPE_NONE);
 
-  const std::u16string title = browser_->tab_strip_model()
-                                   ->group_model()
+  TabStripModel* const tab_strip_model = browser_->tab_strip_model();
+  const std::u16string title = tab_strip_model->group_model()
                                    ->GetTabGroup(group_)
                                    ->visual_data()
                                    ->title();
@@ -229,6 +229,11 @@
               base::Unretained(this)));
   move_to_new_window_menu_item->SetBorder(
       views::CreateEmptyBorder(control_insets));
+  // Disable the option if we'd leave the window empty.
+  if (tab_strip_model->count() ==
+      tab_strip_model->group_model()->GetTabGroup(group_)->tab_count()) {
+    move_to_new_window_menu_item->SetEnabled(false);
+  }
   menu_items_container->AddChildView(std::move(move_to_new_window_menu_item));
 
   if (base::FeatureList::IsEnabled(features::kTabGroupsFeedback)) {
diff --git a/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc b/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc
index c0e27981..f882621 100644
--- a/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/chromeos/cellular_setup/cellular_setup_localized_strings_provider.cc
@@ -76,6 +76,7 @@
     {"scanQrCodeError", IDS_CELLULAR_SETUP_ESIM_PAGE_SCAN_QR_CODE_ERROR},
     {"qrCodeRetry", IDS_CELLULAR_SETUP_ESIM_PAGE_SCAN_QR_CODE_RETRY},
     {"scanQrCodeLoading", IDS_CELLULAR_SETUP_ESIM_PAGE_SCAN_QR_CODE_LOADING},
+    {"scanQrCodeInvalid", IDS_CELLULAR_SETUP_ESIM_PAGE_SCAN_QR_CODE_INVALID},
     {"profileListPageMessage", IDS_CELLULAR_SETUP_PROFILE_LIST_PAGE_MESSAGE},
     {"eidPopupTitle", IDS_CELLULAR_SETUP_EID_POPUP_TITLE},
     {"eidPopupDescription", IDS_CELLULAR_SETUP_EID_POPUP_DESCRIPTION},
diff --git a/chrome/browser/ui/webui/memories/memories.mojom b/chrome/browser/ui/webui/memories/memories.mojom
index e644c7a99..1fa7470 100644
--- a/chrome/browser/ui/webui/memories/memories.mojom
+++ b/chrome/browser/ui/webui/memories/memories.mojom
@@ -30,6 +30,9 @@
   // Returns sample Memories related to |query| for experimentation with a POC.
   // TODO(crbug.com/1179069): Remove this when real Memories are available.
   GetSampleMemories(string query) => (MemoriesResult result);
+
+  // Return memories related to visit history.
+  GetMemories() => (MemoriesResult memories);
 };
 
 // WebUI-side handler for requests from the browser.
diff --git a/chrome/browser/ui/webui/memories/memories_handler.cc b/chrome/browser/ui/webui/memories/memories_handler.cc
index 2b62afe..7bb04aa6 100644
--- a/chrome/browser/ui/webui/memories/memories_handler.cc
+++ b/chrome/browser/ui/webui/memories/memories_handler.cc
@@ -4,8 +4,15 @@
 
 #include "chrome/browser/ui/webui/memories/memories_handler.h"
 
+#include <algorithm>
+#include <utility>
+#include <vector>
+
+#include "chrome/browser/history_clusters/memories_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
+#include "components/memories/core/memories_service.h"
 #include "content/public/browser/web_contents.h"
+#include "url/gurl.h"
 
 #if !defined(OFFICIAL_BUILD)
 #include "base/bind.h"
@@ -244,3 +251,13 @@
   std::move(callback).Run(std::move(memories_result_mojom));
 #endif
 }
+
+void MemoriesHandler::GetMemories(MemoriesResultCallback callback) {
+  auto* memory_service = MemoriesServiceFactory::GetForBrowserContext(profile_);
+  memory_service->GetMemories(base::BindOnce([](memories::Memories memories) {
+                                auto result =
+                                    memories::mojom::MemoriesResult::New();
+                                result->memories = std::move(memories);
+                                return result;
+                              }).Then(std::move(callback)));
+}
diff --git a/chrome/browser/ui/webui/memories/memories_handler.h b/chrome/browser/ui/webui/memories/memories_handler.h
index f8079b3..727d495a 100644
--- a/chrome/browser/ui/webui/memories/memories_handler.h
+++ b/chrome/browser/ui/webui/memories/memories_handler.h
@@ -5,8 +5,12 @@
 #ifndef CHROME_BROWSER_UI_WEBUI_MEMORIES_MEMORIES_HANDLER_H_
 #define CHROME_BROWSER_UI_WEBUI_MEMORIES_MEMORIES_HANDLER_H_
 
+#include <string>
+
+#include "base/callback.h"
 #include "chrome/browser/ui/webui/memories/memories.mojom.h"
 #include "components/memories/core/memories.mojom.h"
+#include "components/memories/core/memories_remote_model_helper.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
@@ -50,6 +54,8 @@
   void GetSampleMemories(const std::string& query,
                          MemoriesResultCallback callback) override;
 
+  void GetMemories(MemoriesResultCallback callback) override;
+
  private:
 #if !defined(OFFICIAL_BUILD)
   void OnHistoryQueryResults(const std::string& query,
diff --git a/chrome/browser/vr/speech_recognizer_unittest.cc b/chrome/browser/vr/speech_recognizer_unittest.cc
index c77685d1..842930f5 100644
--- a/chrome/browser/vr/speech_recognizer_unittest.cc
+++ b/chrome/browser/vr/speech_recognizer_unittest.cc
@@ -63,7 +63,6 @@
 
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
@@ -71,8 +70,8 @@
       const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
       override {
     test_url_loader_factory_.CreateLoaderAndStart(
-        std::move(loader), routing_id, request_id, options, request,
-        std::move(client), traffic_annotation);
+        std::move(loader), request_id, options, request, std::move(client),
+        traffic_annotation);
   }
 
   // network::SharedURLLoaderFactory:
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 59140e4e..35453a8 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-master-1615442232-362501ddc2ce39442e4e87db225c0e7a04e774f5.profdata
+chrome-linux-master-1615982238-6d28cc0efb64698424ab4787b59036e1ccdfa770.profdata
diff --git a/chrome/renderer/autofill/fake_mojo_password_manager_driver.h b/chrome/renderer/autofill/fake_mojo_password_manager_driver.h
index adc34fd8..e9cc5ae 100644
--- a/chrome/renderer/autofill/fake_mojo_password_manager_driver.h
+++ b/chrome/renderer/autofill/fake_mojo_password_manager_driver.h
@@ -10,7 +10,7 @@
 
 #include "base/optional.h"
 #include "components/autofill/content/common/mojom/autofill_driver.mojom.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "mojo/public/cpp/bindings/associated_receiver.h"
 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/renderer/autofill/fake_password_generation_driver.h b/chrome/renderer/autofill/fake_password_generation_driver.h
index 68c6107..de5431b 100644
--- a/chrome/renderer/autofill/fake_password_generation_driver.h
+++ b/chrome/renderer/autofill/fake_password_generation_driver.h
@@ -11,7 +11,7 @@
 #include "base/optional.h"
 #include "components/autofill/content/common/mojom/autofill_driver.mojom.h"
 #include "components/autofill/core/common/password_generation_util.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "mojo/public/cpp/bindings/associated_receiver.h"
 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/chrome/renderer/autofill/form_autofill_browsertest.cc b/chrome/renderer/autofill/form_autofill_browsertest.cc
index 284a766..6f2aa5b6 100644
--- a/chrome/renderer/autofill/form_autofill_browsertest.cc
+++ b/chrome/renderer/autofill/form_autofill_browsertest.cc
@@ -21,7 +21,7 @@
 #include "components/autofill/core/common/autofill_data_validation.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/form_data.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_vector.h"
diff --git a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
index ab2ee49..5f37283 100644
--- a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
+++ b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
@@ -30,7 +30,7 @@
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/autofill/core/common/mojom/autofill_types.mojom.h"
 #include "components/autofill/core/common/password_form_fill_data.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "components/safe_browsing/buildflags.h"
 #include "content/public/renderer/render_frame.h"
diff --git a/chrome/renderer/autofill/password_generation_agent_browsertest.cc b/chrome/renderer/autofill/password_generation_agent_browsertest.cc
index bf8b533..3d77668 100644
--- a/chrome/renderer/autofill/password_generation_agent_browsertest.cc
+++ b/chrome/renderer/autofill/password_generation_agent_browsertest.cc
@@ -29,7 +29,7 @@
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/autofill/core/common/password_generation_util.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "content/public/renderer/render_frame.h"
 #include "content/public/renderer/render_view.h"
diff --git a/chrome/renderer/autofill/password_generation_test_utils.cc b/chrome/renderer/autofill/password_generation_test_utils.cc
index 9b1bf96c..251989d 100644
--- a/chrome/renderer/autofill/password_generation_test_utils.cc
+++ b/chrome/renderer/autofill/password_generation_test_utils.cc
@@ -9,8 +9,8 @@
 #include "components/autofill/content/renderer/form_autofill_util.h"
 #include "components/autofill/content/renderer/password_generation_agent.h"
 #include "components/autofill/core/common/password_form_generation_data.h"
-#include "components/autofill/core/common/renderer_id.h"
 #include "components/autofill/core/common/signatures.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "net/base/escape.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/web_string.h"
diff --git a/chrome/services/sharing/nearby/platform/DEPS b/chrome/services/sharing/nearby/platform/DEPS
index fee0951..82811c0 100644
--- a/chrome/services/sharing/nearby/platform/DEPS
+++ b/chrome/services/sharing/nearby/platform/DEPS
@@ -6,4 +6,5 @@
   '+device/bluetooth/public',
   '+third_party/abseil-cpp/absl/strings/string_view.h',
   '+third_party/abseil-cpp/absl/time/time.h',
+  "+unicode/locid.h"
 ]
diff --git a/chrome/services/sharing/nearby/platform/webrtc.cc b/chrome/services/sharing/nearby/platform/webrtc.cc
index 3eb7117..24452c8d7 100644
--- a/chrome/services/sharing/nearby/platform/webrtc.cc
+++ b/chrome/services/sharing/nearby/platform/webrtc.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/services/sharing/nearby/platform/webrtc.h"
 
-#include "base/i18n/timezone.h"
 #include "chrome/services/sharing/webrtc/ipc_network_manager.h"
 #include "chrome/services/sharing/webrtc/ipc_packet_socket_factory.h"
 #include "chrome/services/sharing/webrtc/mdns_responder_adapter.h"
@@ -18,6 +17,7 @@
 #include "third_party/webrtc/api/jsep.h"
 #include "third_party/webrtc/api/peer_connection_interface.h"
 #include "third_party/webrtc_overrides/task_queue_factory.h"
+#include "unicode/locid.h"
 
 namespace location {
 namespace nearby {
@@ -62,6 +62,12 @@
         }
     )");
 
+// Returns the ISO country code for the locale currently set as the
+// user's device language.
+const std::string GetCurrentCountryCode() {
+  return std::string(icu::Locale::getDefault().getCountry());
+}
+
 class ProxyAsyncResolverFactory final : public webrtc::AsyncResolverFactory {
  public:
   explicit ProxyAsyncResolverFactory(
@@ -156,7 +162,7 @@
       case location::nearby::connections::LocationStandard_Format::
           LocationStandard_Format_UNKNOWN:
         // Here we default to the current default country code before sending.
-        location_hint_ptr->location = base::CountryCodeForCurrentTimezone();
+        location_hint_ptr->location = GetCurrentCountryCode();
         location_hint_ptr->format =
             sharing::mojom::LocationStandardFormat::ISO_3166_1_ALPHA_2;
         break;
@@ -283,7 +289,7 @@
 WebRtcMedium::~WebRtcMedium() = default;
 
 const std::string WebRtcMedium::GetDefaultCountryCode() {
-  return base::CountryCodeForCurrentTimezone();
+  return GetCurrentCountryCode();
 }
 
 void WebRtcMedium::CreatePeerConnection(
diff --git a/chrome/services/sharing/nearby/platform/webrtc_test.cc b/chrome/services/sharing/nearby/platform/webrtc_test.cc
index 3803afb..fdb14f1 100644
--- a/chrome/services/sharing/nearby/platform/webrtc_test.cc
+++ b/chrome/services/sharing/nearby/platform/webrtc_test.cc
@@ -4,13 +4,13 @@
 
 #include "chrome/services/sharing/nearby/platform/webrtc.h"
 
-#include "base/i18n/timezone.h"
 #include "base/test/task_environment.h"
 #include "chrome/services/sharing/nearby/test_support/mock_webrtc_dependencies.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/shared_remote.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "unicode/locid.h"
 
 namespace location {
 namespace nearby {
@@ -186,7 +186,7 @@
               sharing::MockWebRtcDependencies::SendMessageCallback callback) {
             // Validate we get the default country code if we pass an UNKNOWN
             // location hint.
-            EXPECT_EQ(base::CountryCodeForCurrentTimezone(),
+            EXPECT_EQ(icu::Locale::getDefault().getCountry(),
                       location_hint->location);
             EXPECT_EQ(
                 sharing::mojom::LocationStandardFormat::ISO_3166_1_ALPHA_2,
@@ -261,7 +261,7 @@
                   callback) {
             // Expect the unknown location hint to get defaulted by the time we
             // get here.
-            EXPECT_EQ(base::CountryCodeForCurrentTimezone(),
+            EXPECT_EQ(icu::Locale::getDefault().getCountry(),
                       location_hint->location);
             EXPECT_EQ(
                 sharing::mojom::LocationStandardFormat::ISO_3166_1_ALPHA_2,
diff --git a/chrome/test/chromedriver/server/http_handler.cc b/chrome/test/chromedriver/server/http_handler.cc
index 3ea0e0c..00d8f37d 100644
--- a/chrome/test/chromedriver/server/http_handler.cc
+++ b/chrome/test/chromedriver/server/http_handler.cc
@@ -87,7 +87,6 @@
 
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
@@ -96,14 +95,14 @@
       override {
     if (network_task_runner_->RunsTasksInCurrentSequence()) {
       url_loader_factory_->CreateLoaderAndStart(
-          std::move(loader), routing_id, request_id, options, request,
-          std::move(client), traffic_annotation);
+          std::move(loader), request_id, options, request, std::move(client),
+          traffic_annotation);
     } else {
       network_task_runner_->PostTask(
           FROM_HERE,
           base::BindOnce(&WrapperURLLoaderFactory::CreateLoaderAndStart,
-                         base::Unretained(this), std::move(loader), routing_id,
-                         request_id, options, request, std::move(client),
+                         base::Unretained(this), std::move(loader), request_id,
+                         options, request, std::move(client),
                          traffic_annotation));
     }
   }
diff --git a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/activation_code_page_test.js b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/activation_code_page_test.js
index f9df619..3fe9f6c4 100644
--- a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/activation_code_page_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/activation_code_page_test.js
@@ -55,6 +55,7 @@
 
   teardown(function() {
     activationCodePage.remove();
+    FakeBarcodeDetector.setShouldFail(false);
   });
 
   test('UI states', async function() {
@@ -115,17 +116,6 @@
     assertFalse(scanSuccessContainer.hidden);
     assertTrue(scanFailureContainer.hidden);
 
-    // Mock an invalid activation code.
-    activationCodePage.showError = true;
-
-    // The scanFinishContainer and scanFailureContainer should now be visible,
-    // video, start scanning UI and scanSuccessContainer hidden.
-    assertFalse(scanFinishContainer.hidden);
-    assertTrue(startScanningContainer.hidden);
-    assertTrue(video.hidden);
-    assertTrue(scanSuccessContainer.hidden);
-    assertFalse(scanFailureContainer.hidden);
-
     // Click the 'Try Again' button.
     tryAgainButton.click();
     await flushAsync();
@@ -149,17 +139,6 @@
     assertTrue(scanFailureContainer.hidden);
     assertFalse(activationCodePage.showError);
 
-    // Mock another invalid activation code.
-    activationCodePage.showError = true;
-
-    // The scanFinishContainer and scanFailureContainer should now be visible,
-    // video, start scanning UI and scanSuccessContainer hidden.
-    assertFalse(scanFinishContainer.hidden);
-    assertTrue(startScanningContainer.hidden);
-    assertTrue(video.hidden);
-    assertTrue(scanSuccessContainer.hidden);
-    assertFalse(scanFailureContainer.hidden);
-
     // Click the 'Try Again' button.
     tryAgainButton.click();
     await flushAsync();
@@ -326,4 +305,27 @@
     await flushAsync();
     assertTrue(eventFired);
   });
+
+  test(
+      'Install error after manual entry should show error on input',
+      async function() {
+        await flushAsync();
+        const input = activationCodePage.$$('#activationCode');
+        const startScanningContainer =
+            activationCodePage.$$('#startScanningContainer');
+        const scanFinishContainer =
+            activationCodePage.$$('#scanFinishContainer');
+        assertTrue(!!input);
+        assertTrue(!!startScanningContainer);
+        assertTrue(!!scanFinishContainer);
+        assertFalse(input.invalid);
+
+        input.value = 'ACTIVATION_CODE';
+        activationCodePage.showError = true;
+        assertTrue(input.invalid);
+
+        // Should be showing the start scanning UI.
+        assertFalse(startScanningContainer.hidden);
+        assertTrue(scanFinishContainer.hidden);
+      });
 });
diff --git a/chrome/updater/BUILD.gn b/chrome/updater/BUILD.gn
index cc5dc279..64219c8 100644
--- a/chrome/updater/BUILD.gn
+++ b/chrome/updater/BUILD.gn
@@ -346,8 +346,14 @@
       "policy_service_unittest.cc",
       "prefs_unittest.cc",
       "tag_unittest.cc",
+      "test/integration_test_commands.h",
+      "test/integration_test_commands_system.cc",
+      "test/integration_test_commands_system.h",
+      "test/integration_test_commands_user.cc",
+      "test/integration_test_commands_user.h",
       "test/integration_tests.cc",
-      "test/integration_tests.h",
+      "test/integration_tests_impl.cc",
+      "test/integration_tests_impl.h",
       "test/server.cc",
       "test/server.h",
       "unittest_util_unittest.cc",
diff --git a/chrome/updater/test/integration_test_commands.h b/chrome/updater/test/integration_test_commands.h
new file mode 100644
index 0000000..3fd7072a4
--- /dev/null
+++ b/chrome/updater/test/integration_test_commands.h
@@ -0,0 +1,57 @@
+// Copyright 2021 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_UPDATER_TEST_INTEGRATION_TEST_COMMANDS_H_
+#define CHROME_UPDATER_TEST_INTEGRATION_TEST_COMMANDS_H_
+
+#include <string>
+
+#include "base/memory/ref_counted.h"
+#include "chrome/updater/updater_scope.h"
+
+class GURL;
+
+namespace updater {
+namespace test {
+
+class IntegrationTestCommands
+    : public base::RefCountedThreadSafe<IntegrationTestCommands> {
+ public:
+  // TODO(crbug.com/1096654): Remove GetUpdaterScope method when all tests are
+  // enabled for system context.
+  virtual UpdaterScope GetUpdaterScope() const = 0;
+  virtual void EnterTestMode(const GURL& url) const = 0;
+  virtual void Clean() const = 0;
+  virtual void ExpectClean() const = 0;
+  virtual void ExpectInstalled() const = 0;
+  virtual void ExpectCandidateUninstalled() const = 0;
+  virtual void Install() const = 0;
+  virtual void SetActive(const std::string& app_id) const = 0;
+  virtual void ExpectActiveUpdater() const = 0;
+  virtual void ExpectActive(const std::string& app_id) const = 0;
+  virtual void ExpectNotActive(const std::string& app_id) const = 0;
+  virtual void ExpectVersionActive(const std::string& version) const = 0;
+  virtual void ExpectVersionNotActive(const std::string& version) const = 0;
+  virtual void Uninstall() const = 0;
+  virtual void RegisterApp(const std::string& app_id) const = 0;
+  virtual void RegisterTestApp() const = 0;
+  virtual void CopyLog() const = 0;
+  virtual void SetupFakeUpdaterHigherVersion() const = 0;
+  virtual void SetupFakeUpdaterLowerVersion() const = 0;
+  virtual void SetFakeExistenceCheckerPath(const std::string& app_id) const = 0;
+  virtual void ExpectAppUnregisteredExistenceCheckerPath(
+      const std::string& app_id) const = 0;
+  virtual void RunWake(int exit_code) const = 0;
+  virtual void PrintLog() const = 0;
+
+ protected:
+  friend class base::RefCountedThreadSafe<IntegrationTestCommands>;
+
+  virtual ~IntegrationTestCommands() = default;
+};
+
+}  // namespace test
+}  // namespace updater
+
+#endif  // CHROME_UPDATER_TEST_INTEGRATION_TEST_COMMANDS_H_
diff --git a/chrome/updater/test/integration_test_commands_system.cc b/chrome/updater/test/integration_test_commands_system.cc
new file mode 100644
index 0000000..5f1b1eb
--- /dev/null
+++ b/chrome/updater/test/integration_test_commands_system.cc
@@ -0,0 +1,172 @@
+// Copyright 2021 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/updater/test/integration_test_commands_system.h"
+
+#include <cstdlib>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/strings/string_number_conversions.h"
+#include "build/build_config.h"
+#include "chrome/updater/constants.h"
+#include "chrome/updater/persisted_data.h"
+#include "chrome/updater/prefs.h"
+#include "chrome/updater/test/integration_tests_impl.h"
+#include "chrome/updater/util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+#if defined(OS_WIN)
+#include "base/strings/utf_string_conversions.h"
+#endif  // OS_WIN
+
+namespace updater {
+namespace test {
+
+class IntegrationTestCommandsSystem : public IntegrationTestCommands {
+ public:
+  IntegrationTestCommandsSystem() = default;
+
+  UpdaterScope GetUpdaterScope() const override {
+    return UpdaterScope::kSystem;
+  }
+
+  void PrintLog() const override { RunCommand("print_log"); }
+
+  void CopyLog() const override {
+    base::Optional<base::FilePath> path = GetDataDirPath(GetUpdaterScope());
+    ASSERT_TRUE(path);
+
+#if defined(OS_WIN)
+    RunCommand("copy_log", {Param("path", base::WideToUTF8(path->value()))});
+#else
+    RunCommand("copy_log", {Param("path", path->value())});
+#endif  // OS_WIN
+  }
+
+  void Clean() const override { RunCommand("clean"); }
+
+  void ExpectClean() const override { RunCommand("expect_clean"); }
+
+  void Install() const override { RunCommand("install"); }
+
+  void ExpectInstalled() const override { RunCommand("expect_installed"); }
+
+  void Uninstall() const override { RunCommand("uninstall"); }
+
+  void ExpectCandidateUninstalled() const override {
+    RunCommand("expect_candidate_uninstalled");
+  }
+
+  void EnterTestMode(const GURL& url) const override {
+    RunCommand("enter_test_mode", {Param("url", url.spec())});
+  }
+
+  void ExpectVersionActive(const std::string& version) const override {
+    RunCommand("expect_version_active", {Param("version", version)});
+  }
+
+  void ExpectVersionNotActive(const std::string& version) const override {
+    RunCommand("expect_version_not_active", {Param("version", version)});
+  }
+
+  void ExpectActiveUpdater() const override {
+    RunCommand("expect_active_updater");
+  }
+
+  void ExpectActive(const std::string& app_id) const override {
+    RunCommand("expect_active", {Param("app_id", app_id)});
+  }
+
+  void ExpectNotActive(const std::string& app_id) const override {
+    RunCommand("expect_not_active", {Param("app_id", app_id)});
+  }
+
+  void SetupFakeUpdaterHigherVersion() const override {
+    RunCommand("setup_fake_updater_higher_version");
+  }
+
+  void SetupFakeUpdaterLowerVersion() const override {
+    RunCommand("setup_fake_updater_lower_version");
+  }
+
+  void SetFakeExistenceCheckerPath(const std::string& app_id) const override {
+    RunCommand("set_fake_existence_checker_path", {Param("app_id", app_id)});
+  }
+
+  void ExpectAppUnregisteredExistenceCheckerPath(
+      const std::string& app_id) const override {
+    RunCommand("expect_app_unregistered_existence_checker_path",
+               {Param("app_id", app_id)});
+  }
+
+  void SetActive(const std::string& app_id) const override {
+    RunCommand("set_active", {Param("app_id", app_id)});
+  }
+
+  void RunWake(int expected_exit_code) const override {
+    RunCommand("run_wake",
+               {Param("exit_code", base::NumberToString(expected_exit_code))});
+  }
+
+  void RegisterApp(const std::string& app_id) const override {
+    RunCommand("register_app", {Param("app_id", app_id)});
+  }
+
+  void RegisterTestApp() const override { RunCommand("register_test_app"); }
+
+ private:
+  ~IntegrationTestCommandsSystem() override = default;
+
+  struct Param {
+    Param(const std::string& name, const std::string& value)
+        : name(name), value(value) {}
+    std::string name;
+    std::string value;
+  };
+
+  void RunCommand(const std::string& command_switch,
+                  const std::vector<Param>& params) const {
+    const base::CommandLine command_line =
+        *base::CommandLine::ForCurrentProcess();
+    base::FilePath path(command_line.GetProgram());
+    EXPECT_TRUE(base::PathExists(path));
+    path = path.DirName();
+    EXPECT_TRUE(base::PathExists(path));
+    path = MakeAbsoluteFilePath(path);
+    path = path.Append(FILE_PATH_LITERAL("updater_integration_tests_helper"));
+    EXPECT_TRUE(base::PathExists(path));
+
+    base::CommandLine helper_command(path);
+    helper_command.AppendSwitch(command_switch);
+
+    for (const Param& param : params) {
+      helper_command.AppendSwitchASCII(param.name, param.value);
+    }
+
+    helper_command.AppendSwitch(kEnableLoggingSwitch);
+    helper_command.AppendSwitchASCII(kLoggingModuleSwitch, "*/updater/*=2");
+
+    int exit_code = -1;
+    ASSERT_TRUE(Run(GetUpdaterScope(), helper_command, &exit_code));
+    EXPECT_EQ(exit_code, 0);
+  }
+
+  void RunCommand(const std::string& command_switch) const {
+    RunCommand(command_switch, {});
+  }
+};
+
+scoped_refptr<IntegrationTestCommands> CreateIntegrationTestCommandsSystem() {
+  return base::MakeRefCounted<IntegrationTestCommandsSystem>();
+}
+
+}  // namespace test
+}  // namespace updater
diff --git a/chrome/updater/test/integration_test_commands_system.h b/chrome/updater/test/integration_test_commands_system.h
new file mode 100644
index 0000000..097e454
--- /dev/null
+++ b/chrome/updater/test/integration_test_commands_system.h
@@ -0,0 +1,19 @@
+// Copyright 2021 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_UPDATER_TEST_INTEGRATION_TEST_COMMANDS_SYSTEM_H_
+#define CHROME_UPDATER_TEST_INTEGRATION_TEST_COMMANDS_SYSTEM_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "chrome/updater/test/integration_test_commands.h"
+
+namespace updater {
+namespace test {
+
+scoped_refptr<IntegrationTestCommands> CreateIntegrationTestCommandsSystem();
+
+}  // namespace test
+}  // namespace updater
+
+#endif  // CHROME_UPDATER_TEST_INTEGRATION_TEST_COMMANDS_SYSTEM_H_
diff --git a/chrome/updater/test/integration_test_commands_user.cc b/chrome/updater/test/integration_test_commands_user.cc
new file mode 100644
index 0000000..91a03d8
--- /dev/null
+++ b/chrome/updater/test/integration_test_commands_user.cc
@@ -0,0 +1,125 @@
+// Copyright 2021 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/updater/test/integration_test_commands_user.h"
+
+#include <cstdlib>
+#include <memory>
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/optional.h"
+#include "chrome/updater/test/integration_tests_impl.h"
+#include "chrome/updater/updater_scope.h"
+#include "chrome/updater/util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace updater {
+namespace test {
+
+class IntegrationTestCommandsUser : public IntegrationTestCommands {
+ public:
+  IntegrationTestCommandsUser() = default;
+
+  UpdaterScope GetUpdaterScope() const override { return UpdaterScope::kUser; }
+
+  void PrintLog() const override { updater::test::PrintLog(GetUpdaterScope()); }
+
+  void CopyLog() const override {
+    base::Optional<base::FilePath> path = GetDataDirPath(GetUpdaterScope());
+    EXPECT_TRUE(path);
+    if (path)
+      updater::test::CopyLog(*path);
+  }
+
+  void Clean() const override { updater::test::Clean(GetUpdaterScope()); }
+
+  void ExpectClean() const override {
+    updater::test::ExpectClean(GetUpdaterScope());
+  }
+
+  void Install() const override { updater::test::Install(GetUpdaterScope()); }
+
+  void ExpectInstalled() const override {
+    updater::test::ExpectInstalled(GetUpdaterScope());
+  }
+
+  void Uninstall() const override {
+    updater::test::Uninstall(GetUpdaterScope());
+  }
+
+  void ExpectCandidateUninstalled() const override {
+    updater::test::ExpectCandidateUninstalled(GetUpdaterScope());
+  }
+
+  void EnterTestMode(const GURL& url) const override {
+    updater::test::EnterTestMode(url);
+  }
+
+  void ExpectVersionActive(const std::string& version) const override {
+    updater::test::ExpectVersionActive(version);
+  }
+
+  void ExpectVersionNotActive(const std::string& version) const override {
+    updater::test::ExpectVersionNotActive(version);
+  }
+
+  void ExpectActiveUpdater() const override {
+    updater::test::ExpectActiveUpdater(GetUpdaterScope());
+  }
+
+  void SetupFakeUpdaterHigherVersion() const override {
+    updater::test::SetupFakeUpdaterHigherVersion(GetUpdaterScope());
+  }
+
+  void SetupFakeUpdaterLowerVersion() const override {
+    updater::test::SetupFakeUpdaterLowerVersion(GetUpdaterScope());
+  }
+
+  void SetFakeExistenceCheckerPath(const std::string& app_id) const override {
+    updater::test::SetFakeExistenceCheckerPath(app_id);
+  }
+
+  void ExpectAppUnregisteredExistenceCheckerPath(
+      const std::string& app_id) const override {
+    updater::test::ExpectAppUnregisteredExistenceCheckerPath(app_id);
+  }
+
+  void SetActive(const std::string& app_id) const override {
+    updater::test::SetActive(GetUpdaterScope(), app_id);
+  }
+
+  void ExpectActive(const std::string& app_id) const override {
+    updater::test::ExpectActive(GetUpdaterScope(), app_id);
+  }
+
+  void ExpectNotActive(const std::string& app_id) const override {
+    updater::test::ExpectNotActive(GetUpdaterScope(), app_id);
+  }
+
+  void RunWake(int exit_code) const override {
+    updater::test::RunWake(GetUpdaterScope(), exit_code);
+  }
+
+  void RegisterApp(const std::string& app_id) const override {
+    updater::test::RegisterApp(app_id);
+  }
+
+  void RegisterTestApp() const override {
+    updater::test::RegisterTestApp(GetUpdaterScope());
+  }
+
+ private:
+  ~IntegrationTestCommandsUser() override = default;
+};
+
+scoped_refptr<IntegrationTestCommands> CreateIntegrationTestCommandsUser() {
+  return base::MakeRefCounted<IntegrationTestCommandsUser>();
+}
+
+}  // namespace test
+}  // namespace updater
diff --git a/chrome/updater/test/integration_test_commands_user.h b/chrome/updater/test/integration_test_commands_user.h
new file mode 100644
index 0000000..9b2116d
--- /dev/null
+++ b/chrome/updater/test/integration_test_commands_user.h
@@ -0,0 +1,19 @@
+// Copyright 2021 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_UPDATER_TEST_INTEGRATION_TEST_COMMANDS_USER_H_
+#define CHROME_UPDATER_TEST_INTEGRATION_TEST_COMMANDS_USER_H_
+
+#include "base/memory/scoped_refptr.h"
+#include "chrome/updater/test/integration_test_commands.h"
+
+namespace updater {
+namespace test {
+
+scoped_refptr<IntegrationTestCommands> CreateIntegrationTestCommandsUser();
+
+}  // namespace test
+}  // namespace updater
+
+#endif  // CHROME_UPDATER_TEST_INTEGRATION_TEST_COMMANDS_USER_H_
diff --git a/chrome/updater/test/integration_tests.cc b/chrome/updater/test/integration_tests.cc
index fbbe731c..5a9e91a 100644
--- a/chrome/updater/test/integration_tests.cc
+++ b/chrome/updater/test/integration_tests.cc
@@ -2,7 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/updater/test/integration_tests.h"
 
 #include <cstdlib>
 #include <memory>
@@ -27,6 +26,10 @@
 #include "chrome/updater/persisted_data.h"
 #include "chrome/updater/prefs.h"
 #include "chrome/updater/registration_data.h"
+#include "chrome/updater/test/integration_test_commands.h"
+#include "chrome/updater/test/integration_test_commands_system.h"
+#include "chrome/updater/test/integration_test_commands_user.h"
+#include "chrome/updater/test/integration_tests_impl.h"
 #include "chrome/updater/test/server.h"
 #include "chrome/updater/test/test_app/constants.h"
 #include "chrome/updater/test/test_app/test_app_version.h"
@@ -42,424 +45,8 @@
 #endif  // OS_WIN
 
 namespace updater {
-
 namespace test {
 
-// TODO(crbug.com/1096654): Move the IntegrationTestCommands* classes, along
-// with all the updater::test::Foo(UpdaterScope) implementations to their
-// own file.
-class IntegrationTestCommandsUser : public IntegrationTestCommands {
- public:
-  IntegrationTestCommandsUser() = default;
-
-  static scoped_refptr<IntegrationTestCommands>
-  CreateIntegrationTestCommands() {
-    return base::MakeRefCounted<IntegrationTestCommandsUser>();
-  }
-
-  UpdaterScope scope() const override { return UpdaterScope::kUser; }
-
-  void PrintLog() const override { updater::test::PrintLog(scope()); }
-
-  void CopyLog() const override {
-    base::Optional<base::FilePath> path = GetDataDirPath(scope());
-    EXPECT_TRUE(path);
-    if (path)
-      updater::test::CopyLog(*path);
-  }
-
-  void Clean() const override { updater::test::Clean(scope()); }
-
-  void ExpectClean() const override { updater::test::ExpectClean(scope()); }
-
-  void Install() const override { updater::test::Install(scope()); }
-
-  void ExpectInstalled() const override {
-    updater::test::ExpectInstalled(scope());
-  }
-
-  void Uninstall() const override { updater::test::Uninstall(scope()); }
-
-  void ExpectCandidateUninstalled() const override {
-    updater::test::ExpectCandidateUninstalled(scope());
-  }
-
-  void EnterTestMode(const GURL& url) const override {
-    updater::test::EnterTestMode(url);
-  }
-
-  void ExpectVersionActive(const std::string& version) const override {
-    updater::test::ExpectVersionActive(version);
-  }
-
-  void ExpectVersionNotActive(const std::string& version) const override {
-    updater::test::ExpectVersionNotActive(version);
-  }
-
-  void ExpectActiveUpdater() const override {
-    updater::test::ExpectActiveUpdater(scope());
-  }
-
-  void SetupFakeUpdaterHigherVersion() const override {
-    updater::test::SetupFakeUpdaterHigherVersion(scope());
-  }
-
-  void SetupFakeUpdaterLowerVersion() const override {
-    updater::test::SetupFakeUpdaterLowerVersion(scope());
-  }
-
-  void SetFakeExistenceCheckerPath(const std::string& app_id) const override {
-    updater::test::SetFakeExistenceCheckerPath(app_id);
-  }
-
-  void ExpectAppUnregisteredExistenceCheckerPath(
-      const std::string& app_id) const override {
-    updater::test::ExpectAppUnregisteredExistenceCheckerPath(app_id);
-  }
-
-  void SetActive(const std::string& app_id) const override {
-    updater::test::SetActive(scope(), app_id);
-  }
-
-  void ExpectActive(const std::string& app_id) const override {
-    updater::test::ExpectActive(scope(), app_id);
-  }
-
-  void ExpectNotActive(const std::string& app_id) const override {
-    updater::test::ExpectNotActive(scope(), app_id);
-  }
-
-  void RunWake(int exit_code) const override {
-    updater::test::RunWake(scope(), exit_code);
-  }
-
-  void RegisterApp(const std::string& app_id) const override {
-    updater::test::RegisterApp(app_id);
-  }
-
-  void RegisterTestApp() const override {
-    updater::test::RegisterTestApp(scope());
-  }
-
- private:
-  ~IntegrationTestCommandsUser() override = default;
-};
-
-class IntegrationTestCommandsSystem : public IntegrationTestCommands {
- public:
-  IntegrationTestCommandsSystem() = default;
-
-  static scoped_refptr<IntegrationTestCommands>
-  CreateIntegrationTestCommands() {
-    return base::MakeRefCounted<IntegrationTestCommandsSystem>();
-  }
-
-  UpdaterScope scope() const override { return UpdaterScope::kSystem; }
-
-  void PrintLog() const override { RunHelperCommand("print_log"); }
-
-  void CopyLog() const override {
-    base::Optional<base::FilePath> path = GetDataDirPath(scope());
-    ASSERT_TRUE(path);
-
-#if defined(OS_WIN)
-    RunHelperCommand("copy_log",
-                     {HelperParam("path", base::WideToUTF8(path->value()))});
-#else
-    RunHelperCommand("copy_log", {HelperParam("path", path->value())});
-#endif  // OS_WIN
-  }
-
-  void Clean() const override { RunHelperCommand("clean"); }
-
-  void ExpectClean() const override { RunHelperCommand("expect_clean"); }
-
-  void Install() const override { RunHelperCommand("install"); }
-
-  void ExpectInstalled() const override {
-    RunHelperCommand("expect_installed");
-  }
-
-  void Uninstall() const override { RunHelperCommand("uninstall"); }
-
-  void ExpectCandidateUninstalled() const override {
-    RunHelperCommand("expect_candidate_uninstalled");
-  }
-
-  void EnterTestMode(const GURL& url) const override {
-    RunHelperCommand("enter_test_mode", {HelperParam("url", url.spec())});
-  }
-
-  void ExpectVersionActive(const std::string& version) const override {
-    RunHelperCommand("expect_version_active",
-                     {HelperParam("version", version)});
-  }
-
-  void ExpectVersionNotActive(const std::string& version) const override {
-    RunHelperCommand("expect_version_not_active",
-                     {HelperParam("version", version)});
-  }
-
-  void ExpectActiveUpdater() const override {
-    RunHelperCommand("expect_active_updater");
-  }
-
-  void ExpectActive(const std::string& app_id) const override {
-    RunHelperCommand("expect_active", {HelperParam("app_id", app_id)});
-  }
-
-  void ExpectNotActive(const std::string& app_id) const override {
-    RunHelperCommand("expect_not_active", {HelperParam("app_id", app_id)});
-  }
-
-  void SetupFakeUpdaterHigherVersion() const override {
-    RunHelperCommand("setup_fake_updater_higher_version");
-  }
-
-  void SetupFakeUpdaterLowerVersion() const override {
-    RunHelperCommand("setup_fake_updater_lower_version");
-  }
-
-  void SetFakeExistenceCheckerPath(const std::string& app_id) const override {
-    RunHelperCommand("set_fake_existence_checker_path",
-                     {HelperParam("app_id", app_id)});
-  }
-
-  void ExpectAppUnregisteredExistenceCheckerPath(
-      const std::string& app_id) const override {
-    RunHelperCommand("expect_app_unregistered_existence_checker_path",
-                     {HelperParam("app_id", app_id)});
-  }
-
-  void SetActive(const std::string& app_id) const override {
-    RunHelperCommand("set_active", {HelperParam("app_id", app_id)});
-  }
-
-  void RunWake(int expected_exit_code) const override {
-    RunHelperCommand(
-        "run_wake",
-        {HelperParam("exit_code", base::NumberToString(expected_exit_code))});
-  }
-
-  void RegisterApp(const std::string& app_id) const override {
-    RunHelperCommand("register_app", {HelperParam("app_id", app_id)});
-  }
-
-  void RegisterTestApp() const override {
-    RunHelperCommand("register_test_app");
-  }
-
- private:
-  ~IntegrationTestCommandsSystem() override = default;
-
-  struct HelperParam {
-    HelperParam(const std::string& param_name, const std::string& param_value)
-        : param_name(param_name), param_value(param_value) {}
-    std::string param_name;
-    std::string param_value;
-  };
-
-  void RunHelperCommand(const std::string& command_switch,
-                        const std::vector<HelperParam>& params) const {
-    const base::CommandLine command_line =
-        *base::CommandLine::ForCurrentProcess();
-    base::FilePath path(command_line.GetProgram());
-    EXPECT_TRUE(base::PathExists(path));
-    path = path.DirName();
-    EXPECT_TRUE(base::PathExists(path));
-    path = MakeAbsoluteFilePath(path);
-    path = path.Append(FILE_PATH_LITERAL("updater_integration_tests_helper"));
-    EXPECT_TRUE(base::PathExists(path));
-
-    base::CommandLine helper_command(path);
-    helper_command.AppendSwitch(command_switch);
-
-    for (const HelperParam& param : params) {
-      helper_command.AppendSwitchASCII(param.param_name, param.param_value);
-    }
-
-    helper_command.AppendSwitch(kEnableLoggingSwitch);
-    helper_command.AppendSwitchASCII(kLoggingModuleSwitch, "*/updater/*=2");
-
-    int exit_code = -1;
-    ASSERT_TRUE(Run(scope(), helper_command, &exit_code));
-    EXPECT_EQ(exit_code, 0);
-  }
-
-  void RunHelperCommand(const std::string& command_switch) const {
-    RunHelperCommand(command_switch, {});
-  }
-};
-
-void RegisterApp(const std::string& app_id) {
-  scoped_refptr<UpdateService> update_service = CreateUpdateService();
-  RegistrationRequest registration;
-  registration.app_id = app_id;
-  registration.version = base::Version("0.1");
-  base::RunLoop loop;
-  update_service->RegisterApp(
-      registration, base::BindOnce(base::BindLambdaForTesting(
-                        [&loop](const RegistrationResponse& response) {
-                          EXPECT_EQ(response.status_code, 0);
-                          loop.Quit();
-                        })));
-  loop.Run();
-}
-
-void ExpectVersionActive(const std::string& version) {
-  EXPECT_EQ(CreateGlobalPrefs()->GetActiveVersion(), version);
-}
-
-void ExpectVersionNotActive(const std::string& version) {
-  EXPECT_NE(CreateGlobalPrefs()->GetActiveVersion(), version);
-}
-
-void PrintLog(UpdaterScope scope) {
-  std::string contents;
-  base::Optional<base::FilePath> path = GetDataDirPath(scope);
-  EXPECT_TRUE(path);
-  if (path &&
-      base::ReadFileToString(path->AppendASCII("updater.log"), &contents)) {
-    VLOG(0) << "Contents of updater.log:";
-    VLOG(0) << contents;
-  } else {
-    VLOG(0) << "Failed to read updater.log file.";
-  }
-}
-
-const testing::TestInfo* GetTestInfo() {
-  return testing::UnitTest::GetInstance()->current_test_info();
-}
-
-base::FilePath GetLogDestinationDir() {
-  // Fetch path to ${ISOLATED_OUTDIR} env var.
-  // ResultDB reads logs and test artifacts info from there.
-  return base::FilePath::FromUTF8Unsafe(std::getenv("ISOLATED_OUTDIR"));
-}
-
-void CopyLog(const base::FilePath& src_dir) {
-  // TODO(crbug.com/1159189): copy other test artifacts.
-  base::FilePath dest_dir = GetLogDestinationDir();
-  if (base::PathExists(dest_dir) && base::PathExists(src_dir)) {
-    base::FilePath test_name_path = dest_dir.AppendASCII(base::StrCat(
-        {GetTestInfo()->test_suite_name(), ".", GetTestInfo()->name()}));
-    EXPECT_TRUE(base::CreateDirectory(test_name_path));
-
-    base::FilePath dest_file_path = test_name_path.AppendASCII("updater.log");
-    base::FilePath log_path = src_dir.AppendASCII("updater.log");
-    VLOG(0) << "Copying updater.log file. From: " << log_path
-            << ". To: " << dest_file_path;
-    EXPECT_TRUE(base::CopyFile(log_path, dest_file_path));
-  }
-}
-
-void RunWake(UpdaterScope scope, int expected_exit_code) {
-  const base::Optional<base::FilePath> installed_executable_path =
-      GetInstalledExecutablePath(scope);
-  ASSERT_TRUE(installed_executable_path);
-  EXPECT_TRUE(base::PathExists(*installed_executable_path));
-  base::CommandLine command_line(*installed_executable_path);
-  command_line.AppendSwitch(kWakeSwitch);
-  command_line.AppendSwitch(kEnableLoggingSwitch);
-  command_line.AppendSwitchASCII(kLoggingModuleSwitch, "*/updater/*=2");
-  int exit_code = -1;
-  ASSERT_TRUE(Run(scope, command_line, &exit_code));
-  EXPECT_EQ(exit_code, expected_exit_code);
-}
-
-void SetupFakeUpdaterPrefs(const base::Version& version) {
-  std::unique_ptr<GlobalPrefs> global_prefs = CreateGlobalPrefs();
-  global_prefs->SetActiveVersion(version.GetString());
-  global_prefs->SetSwapping(false);
-  PrefsCommitPendingWrites(global_prefs->GetPrefService());
-
-  ASSERT_EQ(version.GetString(), global_prefs->GetActiveVersion());
-}
-
-void SetupFakeUpdaterInstallFolder(UpdaterScope scope,
-                                   const base::Version& version) {
-  const base::Optional<base::FilePath> folder_path =
-      GetFakeUpdaterInstallFolderPath(scope, version);
-  ASSERT_TRUE(folder_path);
-  ASSERT_TRUE(base::CreateDirectory(*folder_path));
-}
-
-void SetupFakeUpdater(UpdaterScope scope, const base::Version& version) {
-  SetupFakeUpdaterPrefs(version);
-  SetupFakeUpdaterInstallFolder(scope, version);
-}
-
-void SetupFakeUpdaterVersion(UpdaterScope scope, int offset) {
-  ASSERT_NE(offset, 0);
-  std::vector<uint32_t> components =
-      base::Version(UPDATER_VERSION_STRING).components();
-  base::CheckedNumeric<uint32_t> new_version = components[0];
-  new_version += offset;
-  ASSERT_TRUE(new_version.AssignIfValid(&components[0]));
-  SetupFakeUpdater(scope, base::Version(std::move(components)));
-}
-
-void SetupFakeUpdaterLowerVersion(UpdaterScope scope) {
-  SetupFakeUpdaterVersion(scope, -1);
-}
-
-void SetupFakeUpdaterHigherVersion(UpdaterScope scope) {
-  SetupFakeUpdaterVersion(scope, 1);
-}
-
-void SetFakeExistenceCheckerPath(const std::string& app_id) {
-  std::unique_ptr<GlobalPrefs> global_prefs = CreateGlobalPrefs();
-  auto persisted_data =
-      base::MakeRefCounted<PersistedData>(global_prefs->GetPrefService());
-  base::FilePath fake_ecp =
-      persisted_data->GetExistenceCheckerPath(app_id).Append(
-          FILE_PATH_LITERAL("NOT_THERE"));
-  persisted_data->SetExistenceCheckerPath(app_id, fake_ecp);
-
-  PrefsCommitPendingWrites(global_prefs->GetPrefService());
-
-  EXPECT_EQ(fake_ecp.value(),
-            persisted_data->GetExistenceCheckerPath(app_id).value());
-}
-
-void ExpectAppUnregisteredExistenceCheckerPath(const std::string& app_id) {
-  std::unique_ptr<GlobalPrefs> global_prefs = CreateGlobalPrefs();
-  auto persisted_data =
-      base::MakeRefCounted<PersistedData>(global_prefs->GetPrefService());
-  EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("")).value(),
-            persisted_data->GetExistenceCheckerPath(app_id).value());
-}
-
-bool Run(UpdaterScope scope, base::CommandLine command_line, int* exit_code) {
-  base::ScopedAllowBaseSyncPrimitivesForTesting allow_wait_process;
-  command_line.AppendSwitch("enable-logging");
-  command_line.AppendSwitchASCII("vmodule", "*/updater/*=2");
-  if (scope == UpdaterScope::kSystem) {
-    command_line.AppendSwitch(kSystemSwitch);
-    command_line = MakeElevated(command_line);
-  }
-  VLOG(0) << " Run command: " << command_line.GetCommandLineString();
-  base::Process process = base::LaunchProcess(command_line, {});
-  if (!process.IsValid())
-    return false;
-
-  // TODO(crbug.com/1096654): Get the timeout from TestTimeouts.
-  return process.WaitForExitWithTimeout(base::TimeDelta::FromSeconds(45),
-                                        exit_code);
-}
-
-void SleepFor(int seconds) {
-  VLOG(2) << "Sleeping " << seconds << " seconds...";
-  base::WaitableEvent sleep(base::WaitableEvent::ResetPolicy::MANUAL,
-                            base::WaitableEvent::InitialState::NOT_SIGNALED);
-  base::ThreadPool::PostDelayedTask(
-      FROM_HERE, {base::MayBlock()},
-      base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&sleep)),
-      base::TimeDelta::FromSeconds(seconds));
-  sleep.Wait();
-  VLOG(2) << "Sleep complete.";
-}
-
 class IntegrationTest
     : public ::testing::TestWithParam<scoped_refptr<IntegrationTestCommands>> {
  protected:
@@ -522,7 +109,7 @@
   }
   void RegisterTestApp() { test_commands_->RegisterTestApp(); }
   void RunWake(int exit_code) { test_commands_->RunWake(exit_code); }
-  UpdaterScope GetUpdaterScope() { return test_commands_->scope(); }
+  UpdaterScope GetUpdaterScope() { return test_commands_->GetUpdaterScope(); }
 
  private:
   base::test::TaskEnvironment environment_;
@@ -549,23 +136,18 @@
 }
 
 TEST_P(IntegrationTest, SelfUninstallOutdatedUpdater) {
-  // TODO(crbug.com/1096654): Enable for system.
-  if (GetUpdaterScope() == UpdaterScope::kSystem) {
-    Uninstall();
-    return;
-  }
-
   Install();
   ExpectInstalled();
   SetupFakeUpdaterHigherVersion();
   ExpectVersionNotActive(UPDATER_VERSION_STRING);
+  SleepFor(2);
 
   RunWake(0);
 
   // The mac server will remain active for 10 seconds after it replies to the
   // wake client, then shut down and uninstall itself. Sleep to wait for this
   // to happen.
-  SleepFor(13);
+  SleepFor(11);
 
   ExpectCandidateUninstalled();
   // The candidate uninstall should not have altered global prefs.
@@ -725,24 +307,19 @@
 #if defined(OS_MAC)
 // TODO(crbug.com/1096654): Enable tests for IntegrationTestCommandsSystem on
 // bots that support passwordless sudo.
-INSTANTIATE_TEST_SUITE_P(
-    IntegrationTestVariations,
-    IntegrationTest,
-    testing::Values(
-        IntegrationTestCommandsUser::CreateIntegrationTestCommands()));
+INSTANTIATE_TEST_SUITE_P(IntegrationTestVariations,
+                         IntegrationTest,
+                         testing::Values(CreateIntegrationTestCommandsUser()));
 #endif
 
 #if defined(OS_WIN)
 // TODO(crbug.com/1096654): Enable for system.
-INSTANTIATE_TEST_SUITE_P(
-    IntegrationTestVariations,
-    IntegrationTest,
-    testing::Values(
-        IntegrationTestCommandsUser::CreateIntegrationTestCommands()));
+INSTANTIATE_TEST_SUITE_P(IntegrationTestVariations,
+                         IntegrationTest,
+                         testing::Values(CreateIntegrationTestCommandsUser()));
 #endif
 
 #endif  // defined(OS_WIN) || !defined(COMPONENT_BUILD)
 
 }  // namespace test
-
 }  // namespace updater
diff --git a/chrome/updater/test/integration_tests_helper.cc b/chrome/updater/test/integration_tests_helper.cc
index ced6444e..9305c35 100644
--- a/chrome/updater/test/integration_tests_helper.cc
+++ b/chrome/updater/test/integration_tests_helper.cc
@@ -16,7 +16,7 @@
 #include "build/build_config.h"
 #include "chrome/updater/app/app.h"
 #include "chrome/updater/constants.h"
-#include "chrome/updater/test/integration_tests.h"
+#include "chrome/updater/test/integration_tests_impl.h"
 #include "chrome/updater/updater_scope.h"
 #include "url/gurl.h"
 
@@ -109,8 +109,10 @@
       int exit_code = -1;
       if (base::StringToInt(command_line->GetSwitchValueASCII("exit_code"),
                             &exit_code)) {
-        RunWake(UpdaterScope::kSystem, exit_code);
-        Shutdown(kSuccess);
+        task_runner->PostTaskAndReply(
+            FROM_HERE,
+            base::BindOnce(&RunWake, UpdaterScope::kSystem, exit_code),
+            base::BindOnce(&AppTestHelper::Shutdown, this, kSuccess));
       } else {
         Shutdown(kBadExitCodeSwitch);
       }
@@ -223,6 +225,12 @@
   base::SingleThreadTaskExecutor main_task_executor(base::MessagePumpType::UI);
 
   base::CommandLine::Init(argc, argv);
+
+  logging::SetLogItems(/*enable_process_id=*/true,
+                       /*enable_thread_id=*/true,
+                       /*enable_timestamp=*/true,
+                       /*enable_tickcount=*/false);
+
   return MakeAppTestHelper()->Run();
 }
 
diff --git a/chrome/updater/test/integration_tests_impl.cc b/chrome/updater/test/integration_tests_impl.cc
new file mode 100644
index 0000000..071f5b3
--- /dev/null
+++ b/chrome/updater/test/integration_tests_impl.cc
@@ -0,0 +1,213 @@
+// Copyright 2021 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/updater/test/integration_tests_impl.h"
+
+#include <cstdlib>
+#include <memory>
+#include <string>
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/numerics/checked_math.h"
+#include "base/optional.h"
+#include "base/process/launch.h"
+#include "base/process/process.h"
+#include "base/run_loop.h"
+#include "base/strings/strcat.h"
+#include "base/task/post_task.h"
+#include "base/task/task_traits.h"
+#include "base/test/bind.h"
+#include "base/time/time.h"
+#include "base/version.h"
+#include "chrome/updater/constants.h"
+#include "chrome/updater/persisted_data.h"
+#include "chrome/updater/prefs.h"
+#include "chrome/updater/registration_data.h"
+#include "chrome/updater/update_service.h"
+#include "chrome/updater/updater_scope.h"
+#include "chrome/updater/updater_version.h"
+#include "chrome/updater/util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace updater {
+namespace test {
+
+void RegisterApp(const std::string& app_id) {
+  scoped_refptr<UpdateService> update_service = CreateUpdateService();
+  RegistrationRequest registration;
+  registration.app_id = app_id;
+  registration.version = base::Version("0.1");
+  base::RunLoop loop;
+  update_service->RegisterApp(
+      registration, base::BindOnce(base::BindLambdaForTesting(
+                        [&loop](const RegistrationResponse& response) {
+                          EXPECT_EQ(response.status_code, 0);
+                          loop.Quit();
+                        })));
+  loop.Run();
+}
+
+void ExpectVersionActive(const std::string& version) {
+  EXPECT_EQ(CreateGlobalPrefs()->GetActiveVersion(), version);
+}
+
+void ExpectVersionNotActive(const std::string& version) {
+  EXPECT_NE(CreateGlobalPrefs()->GetActiveVersion(), version);
+}
+
+void PrintLog(UpdaterScope scope) {
+  std::string contents;
+  base::Optional<base::FilePath> path = GetDataDirPath(scope);
+  EXPECT_TRUE(path);
+  if (path &&
+      base::ReadFileToString(path->AppendASCII("updater.log"), &contents)) {
+    VLOG(0) << "Contents of updater.log:";
+    VLOG(0) << contents;
+    VLOG(0) << "End contents of updater.log.";
+  } else {
+    VLOG(0) << "Failed to read updater.log file.";
+  }
+}
+
+const testing::TestInfo* GetTestInfo() {
+  return testing::UnitTest::GetInstance()->current_test_info();
+}
+
+base::FilePath GetLogDestinationDir() {
+  // Fetch path to ${ISOLATED_OUTDIR} env var.
+  // ResultDB reads logs and test artifacts info from there.
+  return base::FilePath::FromUTF8Unsafe(std::getenv("ISOLATED_OUTDIR"));
+}
+
+void CopyLog(const base::FilePath& src_dir) {
+  // TODO(crbug.com/1159189): copy other test artifacts.
+  base::FilePath dest_dir = GetLogDestinationDir();
+  if (base::PathExists(dest_dir) && base::PathExists(src_dir)) {
+    base::FilePath test_name_path = dest_dir.AppendASCII(base::StrCat(
+        {GetTestInfo()->test_suite_name(), ".", GetTestInfo()->name()}));
+    EXPECT_TRUE(base::CreateDirectory(test_name_path));
+
+    base::FilePath dest_file_path = test_name_path.AppendASCII("updater.log");
+    base::FilePath log_path = src_dir.AppendASCII("updater.log");
+    VLOG(0) << "Copying updater.log file. From: " << log_path
+            << ". To: " << dest_file_path;
+    EXPECT_TRUE(base::CopyFile(log_path, dest_file_path));
+  }
+}
+
+void RunWake(UpdaterScope scope, int expected_exit_code) {
+  const base::Optional<base::FilePath> installed_executable_path =
+      GetInstalledExecutablePath(scope);
+  ASSERT_TRUE(installed_executable_path);
+  EXPECT_TRUE(base::PathExists(*installed_executable_path));
+  base::CommandLine command_line(*installed_executable_path);
+  command_line.AppendSwitch(kWakeSwitch);
+  command_line.AppendSwitch(kEnableLoggingSwitch);
+  command_line.AppendSwitchASCII(kLoggingModuleSwitch, "*/updater/*=2");
+  int exit_code = -1;
+  ASSERT_TRUE(Run(scope, command_line, &exit_code));
+  EXPECT_EQ(exit_code, expected_exit_code);
+}
+
+void SetupFakeUpdaterPrefs(const base::Version& version) {
+  std::unique_ptr<GlobalPrefs> global_prefs = CreateGlobalPrefs();
+  ASSERT_TRUE(global_prefs) << "No global prefs.";
+  global_prefs->SetActiveVersion(version.GetString());
+  global_prefs->SetSwapping(false);
+  PrefsCommitPendingWrites(global_prefs->GetPrefService());
+
+  ASSERT_EQ(version.GetString(), global_prefs->GetActiveVersion());
+}
+
+void SetupFakeUpdaterInstallFolder(UpdaterScope scope,
+                                   const base::Version& version) {
+  const base::Optional<base::FilePath> folder_path =
+      GetFakeUpdaterInstallFolderPath(scope, version);
+  ASSERT_TRUE(folder_path);
+  ASSERT_TRUE(base::CreateDirectory(*folder_path));
+}
+
+void SetupFakeUpdater(UpdaterScope scope, const base::Version& version) {
+  SetupFakeUpdaterPrefs(version);
+  SetupFakeUpdaterInstallFolder(scope, version);
+}
+
+void SetupFakeUpdaterVersion(UpdaterScope scope, int offset) {
+  ASSERT_NE(offset, 0);
+  std::vector<uint32_t> components =
+      base::Version(UPDATER_VERSION_STRING).components();
+  base::CheckedNumeric<uint32_t> new_version = components[0];
+  new_version += offset;
+  ASSERT_TRUE(new_version.AssignIfValid(&components[0]));
+  SetupFakeUpdater(scope, base::Version(std::move(components)));
+}
+
+void SetupFakeUpdaterLowerVersion(UpdaterScope scope) {
+  SetupFakeUpdaterVersion(scope, -1);
+}
+
+void SetupFakeUpdaterHigherVersion(UpdaterScope scope) {
+  SetupFakeUpdaterVersion(scope, 1);
+}
+
+void SetFakeExistenceCheckerPath(const std::string& app_id) {
+  std::unique_ptr<GlobalPrefs> global_prefs = CreateGlobalPrefs();
+  auto persisted_data =
+      base::MakeRefCounted<PersistedData>(global_prefs->GetPrefService());
+  base::FilePath fake_ecp =
+      persisted_data->GetExistenceCheckerPath(app_id).Append(
+          FILE_PATH_LITERAL("NOT_THERE"));
+  persisted_data->SetExistenceCheckerPath(app_id, fake_ecp);
+
+  PrefsCommitPendingWrites(global_prefs->GetPrefService());
+
+  EXPECT_EQ(fake_ecp.value(),
+            persisted_data->GetExistenceCheckerPath(app_id).value());
+}
+
+void ExpectAppUnregisteredExistenceCheckerPath(const std::string& app_id) {
+  std::unique_ptr<GlobalPrefs> global_prefs = CreateGlobalPrefs();
+  auto persisted_data =
+      base::MakeRefCounted<PersistedData>(global_prefs->GetPrefService());
+  EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("")).value(),
+            persisted_data->GetExistenceCheckerPath(app_id).value());
+}
+
+bool Run(UpdaterScope scope, base::CommandLine command_line, int* exit_code) {
+  base::ScopedAllowBaseSyncPrimitivesForTesting allow_wait_process;
+  command_line.AppendSwitch("enable-logging");
+  command_line.AppendSwitchASCII("vmodule", "*/updater/*=2");
+  if (scope == UpdaterScope::kSystem) {
+    command_line.AppendSwitch(kSystemSwitch);
+    command_line = MakeElevated(command_line);
+  }
+  VLOG(0) << " Run command: " << command_line.GetCommandLineString();
+  base::Process process = base::LaunchProcess(command_line, {});
+  if (!process.IsValid())
+    return false;
+
+  // TODO(crbug.com/1096654): Get the timeout from TestTimeouts.
+  return process.WaitForExitWithTimeout(base::TimeDelta::FromSeconds(45),
+                                        exit_code);
+}
+
+void SleepFor(int seconds) {
+  VLOG(2) << "Sleeping " << seconds << " seconds...";
+  base::WaitableEvent sleep(base::WaitableEvent::ResetPolicy::MANUAL,
+                            base::WaitableEvent::InitialState::NOT_SIGNALED);
+  base::ThreadPool::PostDelayedTask(
+      FROM_HERE, {base::MayBlock()},
+      base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&sleep)),
+      base::TimeDelta::FromSeconds(seconds));
+  sleep.Wait();
+  VLOG(2) << "Sleep complete.";
+}
+
+}  // namespace test
+}  // namespace updater
diff --git a/chrome/updater/test/integration_tests.h b/chrome/updater/test/integration_tests_impl.h
similarity index 71%
rename from chrome/updater/test/integration_tests.h
rename to chrome/updater/test/integration_tests_impl.h
index 0aa497a..f49fc65 100644
--- a/chrome/updater/test/integration_tests.h
+++ b/chrome/updater/test/integration_tests_impl.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_UPDATER_TEST_INTEGRATION_TESTS_H_
-#define CHROME_UPDATER_TEST_INTEGRATION_TESTS_H_
+#ifndef CHROME_UPDATER_TEST_INTEGRATION_TESTS_IMPL_H_
+#define CHROME_UPDATER_TEST_INTEGRATION_TESTS_IMPL_H_
 
 #include <string>
 
@@ -21,7 +21,6 @@
 class GURL;
 
 namespace updater {
-
 namespace test {
 
 // Prints the updater.log file to stdout.
@@ -124,44 +123,7 @@
 void ExpectInterfacesRegistered();
 #endif
 
-class IntegrationTestCommands
-    : public base::RefCountedThreadSafe<IntegrationTestCommands> {
- public:
-  static scoped_refptr<IntegrationTestCommands> CreateIntegrationTestCommands();
-
-  virtual UpdaterScope scope() const = 0;
-
-  virtual void EnterTestMode(const GURL& url) const = 0;
-  virtual void Clean() const = 0;
-  virtual void ExpectClean() const = 0;
-  virtual void ExpectInstalled() const = 0;
-  virtual void ExpectCandidateUninstalled() const = 0;
-  virtual void Install() const = 0;
-  virtual void SetActive(const std::string& app_id) const = 0;
-  virtual void ExpectActiveUpdater() const = 0;
-  virtual void ExpectActive(const std::string& app_id) const = 0;
-  virtual void ExpectNotActive(const std::string& app_id) const = 0;
-  virtual void ExpectVersionActive(const std::string& version) const = 0;
-  virtual void ExpectVersionNotActive(const std::string& version) const = 0;
-  virtual void Uninstall() const = 0;
-  virtual void RegisterApp(const std::string& app_id) const = 0;
-  virtual void RegisterTestApp() const = 0;
-  virtual void CopyLog() const = 0;
-  virtual void SetupFakeUpdaterHigherVersion() const = 0;
-  virtual void SetupFakeUpdaterLowerVersion() const = 0;
-  virtual void SetFakeExistenceCheckerPath(const std::string& app_id) const = 0;
-  virtual void ExpectAppUnregisteredExistenceCheckerPath(
-      const std::string& app_id) const = 0;
-  virtual void RunWake(int exit_code) const = 0;
-  virtual void PrintLog() const = 0;
-
- protected:
-  friend class base::RefCountedThreadSafe<IntegrationTestCommands>;
-
-  virtual ~IntegrationTestCommands() = default;
-};
-
 }  // namespace test
 }  // namespace updater
 
-#endif  // CHROME_UPDATER_TEST_INTEGRATION_TESTS_H_
+#endif  // CHROME_UPDATER_TEST_INTEGRATION_TESTS_IMPL_H_
diff --git a/chrome/updater/test/integration_tests_mac.mm b/chrome/updater/test/integration_tests_mac.mm
index d3aeb9e..46ef1881 100644
--- a/chrome/updater/test/integration_tests_mac.mm
+++ b/chrome/updater/test/integration_tests_mac.mm
@@ -24,7 +24,7 @@
 #import "chrome/updater/mac/mac_util.h"
 #include "chrome/updater/mac/xpc_service_names.h"
 #include "chrome/updater/prefs.h"
-#include "chrome/updater/test/integration_tests.h"
+#include "chrome/updater/test/integration_tests_impl.h"
 #include "chrome/updater/test/test_app/constants.h"
 #include "chrome/updater/test/test_app/test_app_version.h"
 #include "chrome/updater/updater_branding.h"
@@ -159,6 +159,8 @@
 
   @autoreleasepool {
     RemoveJobFromLaunchd(scope, launchd_domain, launchd_type,
+                         CopyWakeLaunchdName());
+    RemoveJobFromLaunchd(scope, launchd_domain, launchd_type,
                          CopyUpdateServiceLaunchdName());
     RemoveJobFromLaunchd(scope, launchd_domain, launchd_type,
                          CopyUpdateServiceInternalLaunchdName());
@@ -195,8 +197,6 @@
   Launchd::Domain launchd_domain = LaunchdDomain(scope);
   Launchd::Type launchd_type = LaunchdType(scope);
 
-  VLOG(0) << "Scope :" << scope
-          << "; GetProductPath(scope): " << GetProductPath(scope);
   // Files must exist on the file system.
   base::Optional<base::FilePath> path = GetProductPath(scope);
   EXPECT_TRUE(path);
diff --git a/chrome/updater/test/integration_tests_win.cc b/chrome/updater/test/integration_tests_win.cc
index ef5711e..7712adc 100644
--- a/chrome/updater/test/integration_tests_win.cc
+++ b/chrome/updater/test/integration_tests_win.cc
@@ -23,7 +23,7 @@
 #include "chrome/updater/app/server/win/updater_legacy_idl.h"
 #include "chrome/updater/constants.h"
 #include "chrome/updater/external_constants_builder.h"
-#include "chrome/updater/test/integration_tests.h"
+#include "chrome/updater/test/integration_tests_impl.h"
 #include "chrome/updater/test/test_app/constants.h"
 #include "chrome/updater/test/test_app/test_app_version.h"
 #include "chrome/updater/updater_branding.h"
diff --git a/chrome/updater/test/server.cc b/chrome/updater/test/server.cc
index 021ad309..e6b8d8db 100644
--- a/chrome/updater/test/server.cc
+++ b/chrome/updater/test/server.cc
@@ -8,7 +8,7 @@
 #include <memory>
 #include <string>
 
-#include "chrome/updater/test/integration_tests.h"
+#include "chrome/updater/test/integration_tests_impl.h"
 #include "net/http/http_status_code.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "net/test/embedded_test_server/http_request.h"
diff --git a/chromecast/browser/cast_extension_url_loader_factory.cc b/chromecast/browser/cast_extension_url_loader_factory.cc
index 7da2f9e..fdec863a 100644
--- a/chromecast/browser/cast_extension_url_loader_factory.cc
+++ b/chromecast/browser/cast_extension_url_loader_factory.cc
@@ -31,7 +31,6 @@
  public:
   static void CreateAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
@@ -43,9 +42,8 @@
     // data has been sent to it.
     auto* cast_extension_url_loader = new CastExtensionURLLoader(
         std::move(loader_receiver), std::move(client));
-    cast_extension_url_loader->Start(routing_id, request_id, options,
-                                     std::move(request), traffic_annotation,
-                                     network_factory);
+    cast_extension_url_loader->Start(request_id, options, std::move(request),
+                                     traffic_annotation, network_factory);
   }
 
  private:
@@ -62,8 +60,7 @@
 
   ~CastExtensionURLLoader() override = default;
 
-  void Start(int32_t routing_id,
-             int32_t request_id,
+  void Start(int32_t request_id,
              uint32_t options,
              const network::ResourceRequest& request,
              const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
@@ -71,8 +68,8 @@
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
     network_factory->CreateLoaderAndStart(
-        network_loader_.BindNewPipeAndPassReceiver(), routing_id, request_id,
-        options, request, network_client_receiver_.BindNewPipeAndPassRemote(),
+        network_loader_.BindNewPipeAndPassReceiver(), request_id, options,
+        request, network_client_receiver_.BindNewPipeAndPassRemote(),
         traffic_annotation);
 
     network_client_receiver_.set_disconnect_handler(base::BindOnce(
@@ -203,7 +200,6 @@
 
 void CastExtensionURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
@@ -223,7 +219,7 @@
   if (!CastRedirectHandler::ParseUrl(&cast_url, extension, url)) {
     // Defer to the default handler to load from disk.
     extension_factory_->CreateLoaderAndStart(
-        std::move(loader_receiver), routing_id, request_id, options, request,
+        std::move(loader_receiver), request_id, options, request,
         std::move(client), traffic_annotation);
     return;
   }
@@ -245,9 +241,8 @@
   // Force a redirect to the new URL but without changing where the webpage
   // thinks it is.
   CastExtensionURLLoader::CreateAndStart(
-      std::move(loader_receiver), routing_id, request_id, options,
-      std::move(new_request), std::move(client), traffic_annotation,
-      network_factory_);
+      std::move(loader_receiver), request_id, options, std::move(new_request),
+      std::move(client), traffic_annotation, network_factory_);
 }
 
 void CastExtensionURLLoaderFactory::OnBrowserContextDestroyed() {
diff --git a/chromecast/browser/cast_extension_url_loader_factory.h b/chromecast/browser/cast_extension_url_loader_factory.h
index 45b7d15..51de190 100644
--- a/chromecast/browser/cast_extension_url_loader_factory.h
+++ b/chromecast/browser/cast_extension_url_loader_factory.h
@@ -64,7 +64,6 @@
   // network::mojom::URLLoaderFactory:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/chromecast/browser/cast_network_contexts.cc b/chromecast/browser/cast_network_contexts.cc
index 1040d13..888488dc 100644
--- a/chromecast/browser/cast_network_contexts.cc
+++ b/chromecast/browser/cast_network_contexts.cc
@@ -48,7 +48,6 @@
   // mojom::URLLoaderFactory implementation:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& url_request,
@@ -59,7 +58,7 @@
     if (!network_context_)
       return;
     network_context_->GetSystemURLLoaderFactory()->CreateLoaderAndStart(
-        std::move(receiver), routing_id, request_id, options, url_request,
+        std::move(receiver), request_id, options, url_request,
         std::move(client), traffic_annotation);
   }
 
diff --git a/chromeos/components/diagnostics_ui/backend/routine_log.cc b/chromeos/components/diagnostics_ui/backend/routine_log.cc
index 2f235e8..8c645c6 100644
--- a/chromeos/components/diagnostics_ui/backend/routine_log.cc
+++ b/chromeos/components/diagnostics_ui/backend/routine_log.cc
@@ -26,6 +26,30 @@
       base::TimeFormatTimeOfDayWithMilliseconds(base::Time::Now()));
 }
 
+std::string getRoutineResultString(mojom::StandardRoutineResult result) {
+  switch (result) {
+    case mojom::StandardRoutineResult::kTestPassed:
+      return "Passed";
+    case mojom::StandardRoutineResult::kTestFailed:
+      return "Failed";
+    case mojom::StandardRoutineResult::kExecutionError:
+      return "Execution error";
+    case mojom::StandardRoutineResult::kUnableToRun:
+      return "Unable to run";
+  }
+}
+
+std::string getRoutineTypeString(mojom::RoutineType type) {
+  std::stringstream s;
+  s << type;
+  const std::string routineName = s.str();
+
+  // Remove leading "k" ex: "kCpuStress" -> "CpuStress".
+  DCHECK_GE(routineName.size(), 1U);
+  DCHECK_EQ(routineName[0], 'k');
+  return routineName.substr(1, routineName.size() - 1);
+}
+
 }  // namespace
 
 RoutineLog::RoutineLog(const base::FilePath& routine_log_file_path)
@@ -39,8 +63,9 @@
   }
 
   std::stringstream log_line;
-  log_line << GetCurrentTimeAsString() << kSeparator << type << kSeparator
-           << kStartedDescription << kNewline;
+  log_line << GetCurrentTimeAsString() << kSeparator
+           << getRoutineTypeString(type) << kSeparator << kStartedDescription
+           << kNewline;
   AppendToLog(log_line.str());
 }
 
@@ -49,8 +74,9 @@
   DCHECK(base::PathExists(routine_log_file_path_));
 
   std::stringstream log_line;
-  log_line << GetCurrentTimeAsString() << kSeparator << type << kSeparator
-           << result << kNewline;
+  log_line << GetCurrentTimeAsString() << kSeparator
+           << getRoutineTypeString(type) << kSeparator
+           << getRoutineResultString(result) << kNewline;
   AppendToLog(log_line.str());
 }
 
diff --git a/chromeos/components/diagnostics_ui/backend/routine_log_unittest.cc b/chromeos/components/diagnostics_ui/backend/routine_log_unittest.cc
index 6a0be5f..584f7c58 100644
--- a/chromeos/components/diagnostics_ui/backend/routine_log_unittest.cc
+++ b/chromeos/components/diagnostics_ui/backend/routine_log_unittest.cc
@@ -61,7 +61,7 @@
       GetLogLineContents(first_line);
 
   ASSERT_EQ(3u, first_line_contents.size());
-  EXPECT_EQ("kCpuStress", first_line_contents[1]);
+  EXPECT_EQ("CpuStress", first_line_contents[1]);
   EXPECT_EQ("Started", first_line_contents[2]);
 }
 
@@ -80,7 +80,7 @@
       GetLogLineContents(first_line);
 
   ASSERT_EQ(3u, first_line_contents.size());
-  EXPECT_EQ("kMemory", first_line_contents[1]);
+  EXPECT_EQ("Memory", first_line_contents[1]);
   EXPECT_EQ("Started", first_line_contents[2]);
 
   const std::string second_line = log_lines[1];
@@ -88,8 +88,8 @@
       GetLogLineContents(second_line);
 
   ASSERT_EQ(3u, second_line_contents.size());
-  EXPECT_EQ("kMemory", second_line_contents[1]);
-  EXPECT_EQ("kTestPassed", second_line_contents[2]);
+  EXPECT_EQ("Memory", second_line_contents[1]);
+  EXPECT_EQ("Passed", second_line_contents[2]);
 }
 
 TEST_F(RoutineLogTest, Cancelled) {
diff --git a/chromeos/components/diagnostics_ui/backend/session_log_handler_unittest.cc b/chromeos/components/diagnostics_ui/backend/session_log_handler_unittest.cc
index 5fd8a38..3021931c 100644
--- a/chromeos/components/diagnostics_ui/backend/session_log_handler_unittest.cc
+++ b/chromeos/components/diagnostics_ui/backend/session_log_handler_unittest.cc
@@ -237,7 +237,7 @@
       GetLogLineContents(log_lines[11]);
   ASSERT_EQ(3u, first_routine_log_line_contents.size());
   // first_routine_log_line_contents[0] is ignored because it's a timestamp.
-  EXPECT_EQ("kCpuStress", first_routine_log_line_contents[1]);
+  EXPECT_EQ("CpuStress", first_routine_log_line_contents[1]);
   EXPECT_EQ("Started", first_routine_log_line_contents[2]);
 }
 
diff --git a/chromeos/components/diagnostics_ui/backend/system_routine_controller_unittest.cc b/chromeos/components/diagnostics_ui/backend/system_routine_controller_unittest.cc
index f25fd4b..7274ab0 100644
--- a/chromeos/components/diagnostics_ui/backend/system_routine_controller_unittest.cc
+++ b/chromeos/components/diagnostics_ui/backend/system_routine_controller_unittest.cc
@@ -697,7 +697,7 @@
 
   std::vector<std::string> log_line_contents = GetLogLineContents(log_lines[0]);
   ASSERT_EQ(3u, log_line_contents.size());
-  EXPECT_EQ("kCpuStress", log_line_contents[1]);
+  EXPECT_EQ("CpuStress", log_line_contents[1]);
   EXPECT_EQ("Started", log_line_contents[2]);
 
   // Update the status on cros_healthd.
@@ -717,8 +717,8 @@
 
   log_line_contents = GetLogLineContents(log_lines[1]);
   ASSERT_EQ(3u, log_line_contents.size());
-  EXPECT_EQ("kCpuStress", log_line_contents[1]);
-  EXPECT_EQ("kTestPassed", log_line_contents[2]);
+  EXPECT_EQ("CpuStress", log_line_contents[1]);
+  EXPECT_EQ("Passed", log_line_contents[2]);
 
   // Start another routine and cancel it and verify the cancellation appears in
   // logs. Use a unique_ptr for the RoutineRunner so we can easily destroy it.
diff --git a/chromeos/components/diagnostics_ui/resources/diagnostics_app.js b/chromeos/components/diagnostics_ui/resources/diagnostics_app.js
index 264f9cd..a953c7d 100644
--- a/chromeos/components/diagnostics_ui/resources/diagnostics_app.js
+++ b/chromeos/components/diagnostics_ui/resources/diagnostics_app.js
@@ -119,6 +119,6 @@
           this.toastText_ =
               loadTimeData.getString(`sessionLogToastText${result}`);
           this.$.toast.show();
-        })
+        }).catch(() => {/* File selection cancelled */});
   },
 });
\ No newline at end of file
diff --git a/chromeos/dbus/session_manager/fake_session_manager_client.cc b/chromeos/dbus/session_manager/fake_session_manager_client.cc
index 2ed358d..d57aba5 100644
--- a/chromeos/dbus/session_manager/fake_session_manager_client.cc
+++ b/chromeos/dbus/session_manager/fake_session_manager_client.cc
@@ -286,10 +286,12 @@
 
 void FakeSessionManagerClient::RestartJob(int socket_fd,
                                           const std::vector<std::string>& argv,
+                                          RestartJobReason reason,
                                           VoidDBusMethodCallback callback) {
   DCHECK(supports_browser_restart_);
 
   restart_job_argv_ = argv;
+  restart_job_reason_ = reason;
   if (restart_job_callback_)
     std::move(restart_job_callback_).Run();
 
diff --git a/chromeos/dbus/session_manager/fake_session_manager_client.h b/chromeos/dbus/session_manager/fake_session_manager_client.h
index 6382d3f..8e2d26a 100644
--- a/chromeos/dbus/session_manager/fake_session_manager_client.h
+++ b/chromeos/dbus/session_manager/fake_session_manager_client.h
@@ -57,6 +57,7 @@
   void EmitAshInitialized() override;
   void RestartJob(int socket_fd,
                   const std::vector<std::string>& argv,
+                  RestartJobReason reason,
                   VoidDBusMethodCallback callback) override;
   void SaveLoginPassword(const std::string& password) override;
 
@@ -165,6 +166,11 @@
   const base::Optional<std::vector<std::string>>& restart_job_argv() const {
     return restart_job_argv_;
   }
+
+  base::Optional<RestartJobReason> restart_job_reason() const {
+    return restart_job_reason_;
+  }
+
   // If |force_failure| is true, forces StorePolicy() to fail.
   void ForceStorePolicyFailure(bool force_failure) {
     force_store_policy_failure_ = force_failure;
@@ -289,6 +295,10 @@
   // requested restarted arguments.
   base::Optional<std::vector<std::string>> restart_job_argv_;
 
+  // If restart job was requested, and the client supports restart job, the
+  // requested restart reason.
+  base::Optional<RestartJobReason> restart_job_reason_;
+
   base::ObserverList<Observer>::Unchecked observers_{
       SessionManagerClient::kObserverListPolicy};
   SessionManagerClient::ActiveSessionsMap user_sessions_;
diff --git a/chromeos/dbus/session_manager/session_manager_client.cc b/chromeos/dbus/session_manager/session_manager_client.cc
index bbe8225..4aeb3a8 100644
--- a/chromeos/dbus/session_manager/session_manager_client.cc
+++ b/chromeos/dbus/session_manager/session_manager_client.cc
@@ -208,12 +208,14 @@
 
   void RestartJob(int socket_fd,
                   const std::vector<std::string>& argv,
+                  RestartJobReason reason,
                   VoidDBusMethodCallback callback) override {
     dbus::MethodCall method_call(login_manager::kSessionManagerInterface,
                                  login_manager::kSessionManagerRestartJob);
     dbus::MessageWriter writer(&method_call);
     writer.AppendFileDescriptor(socket_fd);
     writer.AppendArrayOfStrings(argv);
+    writer.AppendUint32(static_cast<uint32_t>(reason));
     session_manager_proxy_->CallMethod(
         &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
         base::BindOnce(&SessionManagerClientImpl::OnVoidMethod,
diff --git a/chromeos/dbus/session_manager/session_manager_client.h b/chromeos/dbus/session_manager/session_manager_client.h
index 246d310..97a99e0 100644
--- a/chromeos/dbus/session_manager/session_manager_client.h
+++ b/chromeos/dbus/session_manager/session_manager_client.h
@@ -75,6 +75,13 @@
     NEED_POWERWASH = 3,
   };
 
+  enum class RestartJobReason : uint32_t {
+    // Restart browser for Guest session.
+    kGuest = 0,
+    // Restart browser without user session for headless Chromium.
+    kUserless = 1,
+  };
+
   // Interface for observing changes from the session manager.
   class Observer {
    public:
@@ -154,8 +161,11 @@
   // request originates from belongs to the browser itself.
   // This method duplicates |socket_fd| so it's OK to close the FD without
   // waiting for the result.
+  // |reason| - restart job without user session (for headless chromium)
+  // or with user session (for guest sessions only).
   virtual void RestartJob(int socket_fd,
                           const std::vector<std::string>& argv,
+                          RestartJobReason reason,
                           VoidDBusMethodCallback callback) = 0;
 
   // Sends the user's password to the session manager.
diff --git a/chromeos/services/cellular_setup/esim_profile.cc b/chromeos/services/cellular_setup/esim_profile.cc
index 8a6ab40..4ba2f1f9 100644
--- a/chromeos/services/cellular_setup/esim_profile.cc
+++ b/chromeos/services/cellular_setup/esim_profile.cc
@@ -371,7 +371,7 @@
                      weak_ptr_factory_.GetWeakPtr()),
       base::BindOnce(&ESimProfile::OnNewProfileConnectFailure,
                      weak_ptr_factory_.GetWeakPtr()),
-      /*check_error_state=*/false, ConnectCallbackMode::ON_COMPLETED);
+      /*check_error_state=*/false, ConnectCallbackMode::ON_STARTED);
 }
 
 void ESimProfile::OnNewProfileConnectSuccess() {
diff --git a/chromeos/services/cellular_setup/euicc.cc b/chromeos/services/cellular_setup/euicc.cc
index af9a33a0..2758d65 100644
--- a/chromeos/services/cellular_setup/euicc.cc
+++ b/chromeos/services/cellular_setup/euicc.cc
@@ -258,7 +258,7 @@
                      weak_ptr_factory_.GetWeakPtr(), profile_path),
       base::BindOnce(&Euicc::OnNewProfileConnectFailure,
                      weak_ptr_factory_.GetWeakPtr(), profile_path),
-      /*check_error_state=*/false, ConnectCallbackMode::ON_COMPLETED);
+      /*check_error_state=*/false, ConnectCallbackMode::ON_STARTED);
 }
 
 void Euicc::OnNewProfileConnectSuccess(const dbus::ObjectPath& profile_path) {
diff --git a/components/BUILD.gn b/components/BUILD.gn
index b8636f82..0d385ac 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -107,6 +107,7 @@
     "//components/language/core/common:unit_tests",
     "//components/leveldb_proto:unit_tests",
     "//components/lookalikes/core:unit_tests",
+    "//components/memories/core:unit_tests",
     "//components/metrics:unit_tests",
     "//components/metrics/demographics:unit_tests",
     "//components/navigation_metrics:unit_tests",
diff --git a/components/autofill/content/renderer/form_autofill_util.h b/components/autofill/content/renderer/form_autofill_util.h
index 1168dfee..9a984644 100644
--- a/components/autofill/content/renderer/form_autofill_util.h
+++ b/components/autofill/content/renderer/form_autofill_util.h
@@ -18,7 +18,7 @@
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "third_party/blink/public/platform/web_vector.h"
 #include "third_party/blink/public/web/web_element_collection.h"
 #include "ui/gfx/geometry/rect_f.h"
diff --git a/components/autofill/content/renderer/form_autofill_util_browsertest.cc b/components/autofill/content/renderer/form_autofill_util_browsertest.cc
index 42b65ab..a76524f 100644
--- a/components/autofill/content/renderer/form_autofill_util_browsertest.cc
+++ b/components/autofill/content/renderer/form_autofill_util_browsertest.cc
@@ -10,7 +10,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
 #include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "content/public/test/render_view_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/autofill/content/renderer/form_cache.h b/components/autofill/content/renderer/form_cache.h
index 1d05e42..c2458830 100644
--- a/components/autofill/content/renderer/form_cache.h
+++ b/components/autofill/content/renderer/form_cache.h
@@ -16,7 +16,7 @@
 #include "base/macros.h"
 #include "components/autofill/core/common/field_data_manager.h"
 #include "components/autofill/core/common/form_data.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 
 namespace blink {
 class WebFormControlElement;
diff --git a/components/autofill/content/renderer/html_based_username_detector.h b/components/autofill/content/renderer/html_based_username_detector.h
index ef1c22a..a61c2c5 100644
--- a/components/autofill/content/renderer/html_based_username_detector.h
+++ b/components/autofill/content/renderer/html_based_username_detector.h
@@ -9,7 +9,7 @@
 #include <vector>
 
 #include "components/autofill/core/common/form_data.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "third_party/blink/public/web/web_form_control_element.h"
 #include "third_party/blink/public/web/web_input_element.h"
 
diff --git a/components/autofill/content/renderer/password_autofill_agent.h b/components/autofill/content/renderer/password_autofill_agent.h
index a9c1694..56ccdc63 100644
--- a/components/autofill/content/renderer/password_autofill_agent.h
+++ b/components/autofill/content/renderer/password_autofill_agent.h
@@ -25,7 +25,7 @@
 #include "components/autofill/core/common/field_data_manager.h"
 #include "components/autofill/core/common/mojom/autofill_types.mojom.h"
 #include "components/autofill/core/common/password_form_fill_data.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "content/public/renderer/render_frame_observer.h"
 #include "mojo/public/cpp/bindings/associated_receiver.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
diff --git a/components/autofill/content/renderer/password_form_conversion_utils.cc b/components/autofill/content/renderer/password_form_conversion_utils.cc
index bb1bb71..b4fd8f4 100644
--- a/components/autofill/content/renderer/password_form_conversion_utils.cc
+++ b/components/autofill/content/renderer/password_form_conversion_utils.cc
@@ -10,7 +10,7 @@
 #include "base/strings/string_piece.h"
 #include "base/strings/string_split.h"
 #include "components/autofill/content/renderer/html_based_username_detector.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/base/url_util.h"
 #include "third_party/blink/public/platform/web_string.h"
diff --git a/components/autofill/content/renderer/password_generation_agent.h b/components/autofill/content/renderer/password_generation_agent.h
index 1b1cc36..edfe319 100644
--- a/components/autofill/content/renderer/password_generation_agent.h
+++ b/components/autofill/content/renderer/password_generation_agent.h
@@ -16,7 +16,7 @@
 #include "components/autofill/content/common/mojom/autofill_agent.mojom.h"
 #include "components/autofill/content/common/mojom/autofill_driver.mojom.h"
 #include "components/autofill/content/renderer/renderer_save_password_progress_logger.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "content/public/renderer/render_frame_observer.h"
 #include "mojo/public/cpp/bindings/associated_receiver.h"
 #include "mojo/public/cpp/bindings/associated_remote.h"
diff --git a/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc b/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc
index 106d5e35..9137540 100644
--- a/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc
+++ b/components/autofill/content/renderer/renderer_save_password_progress_logger_unittest.cc
@@ -8,7 +8,7 @@
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
 #include "components/autofill/content/common/mojom/autofill_driver.mojom.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
diff --git a/components/autofill/core/browser/autofill_handler.h b/components/autofill/core/browser/autofill_handler.h
index 3f1dc3c..8eb8fd5 100644
--- a/components/autofill/core/browser/autofill_handler.h
+++ b/components/autofill/core/browser/autofill_handler.h
@@ -22,8 +22,8 @@
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/language_code.h"
 #include "components/autofill/core/common/mojom/autofill_types.mojom.h"
-#include "components/autofill/core/common/renderer_id.h"
 #include "components/autofill/core/common/signatures.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/translate/core/browser/translate_driver.h"
 #include "components/version_info/channel.h"
 
diff --git a/components/autofill/core/browser/autofill_metrics_unittest.cc b/components/autofill/core/browser/autofill_metrics_unittest.cc
index 8a5ba99..a0b4f52 100644
--- a/components/autofill/core/browser/autofill_metrics_unittest.cc
+++ b/components/autofill/core/browser/autofill_metrics_unittest.cc
@@ -54,8 +54,8 @@
 #include "components/autofill/core/common/dense_set.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_field_data.h"
-#include "components/autofill/core/common/renderer_id.h"
 #include "components/autofill/core/common/signatures.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/prefs/pref_service.h"
 #include "components/sync/driver/test_sync_service.h"
 #include "components/translate/core/common/language_detection_details.h"
diff --git a/components/autofill/core/browser/autofill_test_utils.cc b/components/autofill/core/browser/autofill_test_utils.cc
index b93be9d..a0c07ef 100644
--- a/components/autofill/core/browser/autofill_test_utils.cc
+++ b/components/autofill/core/browser/autofill_test_utils.cc
@@ -28,7 +28,7 @@
 #include "components/autofill/core/common/form_data_predictions.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/autofill/core/common/form_field_data_predictions.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/os_crypt/os_crypt_mocker.h"
 #include "components/pref_registry/pref_registry_syncable.h"
 #include "components/prefs/pref_service.h"
diff --git a/components/autofill/core/browser/form_parsing/field_candidates.h b/components/autofill/core/browser/form_parsing/field_candidates.h
index 7c1a0db..6907bb9 100644
--- a/components/autofill/core/browser/form_parsing/field_candidates.h
+++ b/components/autofill/core/browser/form_parsing/field_candidates.h
@@ -9,7 +9,7 @@
 
 #include "base/containers/flat_map.h"
 #include "components/autofill/core/browser/field_types.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 
 namespace autofill {
 
diff --git a/components/autofill/core/browser/form_structure.h b/components/autofill/core/browser/form_structure.h
index e87103e..1dd3023 100644
--- a/components/autofill/core/browser/form_structure.h
+++ b/components/autofill/core/browser/form_structure.h
@@ -27,7 +27,7 @@
 #include "components/autofill/core/common/dense_set.h"
 #include "components/autofill/core/common/language_code.h"
 #include "components/autofill/core/common/mojom/autofill_types.mojom.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
diff --git a/components/autofill/core/common/BUILD.gn b/components/autofill/core/common/BUILD.gn
index 31a58e9..5f5ebd95 100644
--- a/components/autofill/core/common/BUILD.gn
+++ b/components/autofill/core/common/BUILD.gn
@@ -49,12 +49,12 @@
     "password_form_generation_data.h",
     "password_generation_util.cc",
     "password_generation_util.h",
-    "renderer_id.cc",
-    "renderer_id.h",
     "save_password_progress_logger.cc",
     "save_password_progress_logger.h",
     "signatures.cc",
     "signatures.h",
+    "unique_ids.cc",
+    "unique_ids.h",
   ]
 
   deps = [
diff --git a/components/autofill/core/common/field_data_manager.h b/components/autofill/core/common/field_data_manager.h
index b6f3183..4eb5c24 100644
--- a/components/autofill/core/common/field_data_manager.h
+++ b/components/autofill/core/common/field_data_manager.h
@@ -10,7 +10,7 @@
 
 #include "base/optional.h"
 #include "components/autofill/core/common/form_field_data.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 
 namespace autofill {
 
diff --git a/components/autofill/core/common/field_data_manager_unittest.cc b/components/autofill/core/common/field_data_manager_unittest.cc
index ce5515a..aafb6d5 100644
--- a/components/autofill/core/common/field_data_manager_unittest.cc
+++ b/components/autofill/core/common/field_data_manager_unittest.cc
@@ -5,7 +5,7 @@
 #include "components/autofill/core/common/field_data_manager.h"
 
 #include "base/strings/utf_string_conversions.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using autofill::FormFieldData;
diff --git a/components/autofill/core/common/form_data.h b/components/autofill/core/common/form_data.h
index f6b53809..d4cfd25 100644
--- a/components/autofill/core/common/form_data.h
+++ b/components/autofill/core/common/form_data.h
@@ -13,7 +13,7 @@
 #include "build/build_config.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
diff --git a/components/autofill/core/common/form_field_data.h b/components/autofill/core/common/form_field_data.h
index e976c6e9..cda1f1f 100644
--- a/components/autofill/core/common/form_field_data.h
+++ b/components/autofill/core/common/form_field_data.h
@@ -15,7 +15,7 @@
 #include "base/i18n/rtl.h"
 #include "build/build_config.h"
 #include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "ui/gfx/geometry/rect_f.h"
 
 namespace base {
diff --git a/components/autofill/core/common/mojom/autofill_types_mojom_traits.h b/components/autofill/core/common/mojom/autofill_types_mojom_traits.h
index a0812b0..3cba8529 100644
--- a/components/autofill/core/common/mojom/autofill_types_mojom_traits.h
+++ b/components/autofill/core/common/mojom/autofill_types_mojom_traits.h
@@ -19,7 +19,7 @@
 #include "components/autofill/core/common/password_form_fill_data.h"
 #include "components/autofill/core/common/password_form_generation_data.h"
 #include "components/autofill/core/common/password_generation_util.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "mojo/public/cpp/base/text_direction_mojom_traits.h"
 #include "mojo/public/cpp/bindings/struct_traits.h"
 #include "mojo/public/mojom/base/unguessable_token.mojom-shared.h"
diff --git a/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc b/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc
index e671123..e8ca918 100644
--- a/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc
+++ b/components/autofill/core/common/mojom/autofill_types_mojom_traits_unittest.cc
@@ -14,8 +14,8 @@
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/autofill/core/common/mojom/test_autofill_types.mojom.h"
 #include "components/autofill/core/common/password_generation_util.h"
-#include "components/autofill/core/common/renderer_id.h"
 #include "components/autofill/core/common/signatures.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/receiver_set.h"
 #include "mojo/public/cpp/bindings/remote.h"
diff --git a/components/autofill/core/common/password_form_fill_data.h b/components/autofill/core/common/password_form_fill_data.h
index 375b127..3e89a66 100644
--- a/components/autofill/core/common/password_form_fill_data.h
+++ b/components/autofill/core/common/password_form_fill_data.h
@@ -9,7 +9,7 @@
 #include <vector>
 
 #include "components/autofill/core/common/form_data.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 
 namespace autofill {
 
diff --git a/components/autofill/core/common/password_form_generation_data.h b/components/autofill/core/common/password_form_generation_data.h
index 7c22909..e919bb8e 100644
--- a/components/autofill/core/common/password_form_generation_data.h
+++ b/components/autofill/core/common/password_form_generation_data.h
@@ -6,7 +6,7 @@
 #define COMPONENTS_AUTOFILL_CORE_COMMON_PASSWORD_FORM_GENERATION_DATA_H_
 
 #include "build/build_config.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 
 namespace autofill {
 
diff --git a/components/autofill/core/common/password_generation_util.h b/components/autofill/core/common/password_generation_util.h
index 9f799574..a2a5960 100644
--- a/components/autofill/core/common/password_generation_util.h
+++ b/components/autofill/core/common/password_generation_util.h
@@ -9,7 +9,7 @@
 
 #include "base/i18n/rtl.h"
 #include "components/autofill/core/common/form_data.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "ui/gfx/geometry/rect_f.h"
 
 namespace autofill {
diff --git a/components/autofill/core/common/renderer_id.cc b/components/autofill/core/common/unique_ids.cc
similarity index 95%
rename from components/autofill/core/common/renderer_id.cc
rename to components/autofill/core/common/unique_ids.cc
index 1d9fd2c..d4e96f4 100644
--- a/components/autofill/core/common/renderer_id.cc
+++ b/components/autofill/core/common/unique_ids.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 
 #include "components/autofill/core/common/logging/log_buffer.h"
 
diff --git a/components/autofill/core/common/renderer_id.h b/components/autofill/core/common/unique_ids.h
similarity index 95%
rename from components/autofill/core/common/renderer_id.h
rename to components/autofill/core/common/unique_ids.h
index eabcdfc..ab25f87 100644
--- a/components/autofill/core/common/renderer_id.h
+++ b/components/autofill/core/common/unique_ids.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef COMPONENTS_AUTOFILL_CORE_COMMON_RENDERER_ID_H_
-#define COMPONENTS_AUTOFILL_CORE_COMMON_RENDERER_ID_H_
+#ifndef COMPONENTS_AUTOFILL_CORE_COMMON_UNIQUE_IDS_H_
+#define COMPONENTS_AUTOFILL_CORE_COMMON_UNIQUE_IDS_H_
 
 #include <stdint.h>
 #include <limits>
@@ -95,4 +95,4 @@
 
 }  // namespace autofill
 
-#endif  // COMPONENTS_AUTOFILL_CORE_COMMON_RENDERER_ID_H_
+#endif  // COMPONENTS_AUTOFILL_CORE_COMMON_UNIQUE_IDS_H_
diff --git a/components/autofill/ios/browser/form_suggestion_provider_query.h b/components/autofill/ios/browser/form_suggestion_provider_query.h
index ad9db58..734b50e 100644
--- a/components/autofill/ios/browser/form_suggestion_provider_query.h
+++ b/components/autofill/ios/browser/form_suggestion_provider_query.h
@@ -7,7 +7,7 @@
 
 #import <Foundation/Foundation.h>
 
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 
 namespace {
 NSString* const kPasswordFieldType = @"password";
diff --git a/components/autofill/ios/browser/js_autofill_manager.h b/components/autofill/ios/browser/js_autofill_manager.h
index 0b5a29e..4a670f6 100644
--- a/components/autofill/ios/browser/js_autofill_manager.h
+++ b/components/autofill/ios/browser/js_autofill_manager.h
@@ -8,7 +8,7 @@
 #include "base/ios/block_types.h"
 #include "base/values.h"
 #include "components/autofill/core/common/autofill_constants.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 
 namespace web {
 class WebFrame;
diff --git a/components/autofill/ios/form_util/form_activity_params.h b/components/autofill/ios/form_util/form_activity_params.h
index 6639ecc..b3210b6 100644
--- a/components/autofill/ios/form_util/form_activity_params.h
+++ b/components/autofill/ios/form_util/form_activity_params.h
@@ -6,7 +6,7 @@
 
 #include <string>
 
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 
 namespace autofill {
 
diff --git a/components/autofill_assistant/browser/actions/action_delegate.h b/components/autofill_assistant/browser/actions/action_delegate.h
index 7f0ecc4..2827ebc3 100644
--- a/components/autofill_assistant/browser/actions/action_delegate.h
+++ b/components/autofill_assistant/browser/actions/action_delegate.h
@@ -118,15 +118,6 @@
       const ElementFinder::Result& element,
       base::OnceCallback<void(const ClientStatus&)> callback) = 0;
 
-  // Wait for the |element| to stop moving on the page. Fails with
-  // ELEMENT_UNSTABLE.
-  virtual void WaitUntilElementIsStable(
-      int max_rounds,
-      base::TimeDelta check_interval,
-      const ElementFinder::Result& element,
-      base::OnceCallback<void(const ClientStatus&, base::TimeDelta)>
-          callback) = 0;
-
   // Have the UI enter the prompt mode and make the given actions available.
   //
   // While a prompt is in progress, the UI looks the same as it does between
@@ -204,14 +195,6 @@
                               const autofill::FormData&,
                               const autofill::FormFieldData&)> callback) = 0;
 
-  // Select the option to be picked given by the |re2| in the |element|.
-  virtual void SelectOption(
-      const std::string& re2,
-      bool case_sensitive,
-      SelectOptionProto::OptionComparisonAttribute option_comparison_attribute,
-      const ElementFinder::Result& element,
-      base::OnceCallback<void(const ClientStatus&)> callback) = 0;
-
   // Scroll to an |element|'s position. |top_padding| specifies the padding
   // between the focused element and the top.
   // If |container| is specified, that container will be scrolled, if
@@ -234,45 +217,6 @@
   virtual void SetTouchableElementArea(
       const ElementAreaProto& touchable_element_area) = 0;
 
-  // Get the value attribute of an |element| and return the result through
-  // |callback|. If the lookup fails, the value will be empty. An empty result
-  // does not mean an error.
-  virtual void GetFieldValue(
-      const ElementFinder::Result& element,
-      base::OnceCallback<void(const ClientStatus&, const std::string&)>
-          callback) = 0;
-
-  // Get the value of a nested |attribute| from an |element| and return the
-  // result through |callback|. If the lookup fails, the value will be empty.
-  // An empty result does not mean an error.
-  virtual void GetStringAttribute(
-      const std::vector<std::string>& attributes,
-      const ElementFinder::Result& element,
-      base::OnceCallback<void(const ClientStatus&, const std::string&)>
-          callback) = 0;
-
-  // Set the value attribute of an |element| to the specified |value| and
-  // trigger an onchange event.
-  virtual void SetValueAttribute(
-      const std::string& value,
-      const ElementFinder::Result& element,
-      base::OnceCallback<void(const ClientStatus&)> callback) = 0;
-
-  // Set the nested |attributes| of an |element| to the specified |value|.
-  virtual void SetAttribute(
-      const std::vector<std::string>& attributes,
-      const std::string& value,
-      const ElementFinder::Result& element,
-      base::OnceCallback<void(const ClientStatus&)> callback) = 0;
-
-  // Inputs the specified codepoints into |element|. Expects the |element| to
-  // have focus. Returns the result through |callback|.
-  virtual void SendKeyboardInput(
-      const std::vector<UChar32>& codepoints,
-      int key_press_delay_in_millisecond,
-      const ElementFinder::Result& element,
-      base::OnceCallback<void(const ClientStatus&)> callback) = 0;
-
   // Make the next call to WaitForNavigation to expect a navigation event that
   // started after this call.
   virtual void ExpectNavigation() = 0;
diff --git a/components/autofill_assistant/browser/actions/action_delegate_util.cc b/components/autofill_assistant/browser/actions/action_delegate_util.cc
index dfd4c52..3fcf21f3 100644
--- a/components/autofill_assistant/browser/actions/action_delegate_util.cc
+++ b/components/autofill_assistant/browser/actions/action_delegate_util.cc
@@ -139,8 +139,8 @@
                      delegate->GetWebController()->GetWeakPtr(), true));
   if (click_type != ClickType::JAVASCRIPT) {
     AddStepIgnoreTiming(
-        base::BindOnce(&ActionDelegate::WaitUntilElementIsStable,
-                       delegate->GetWeakPtr(),
+        base::BindOnce(&WebController::WaitUntilElementIsStable,
+                       delegate->GetWebController()->GetWeakPtr(),
                        delegate->GetSettings().box_model_check_count,
                        delegate->GetSettings().box_model_check_interval),
         actions);
@@ -295,9 +295,9 @@
     AddClickOrTapSequence(delegate, ClickType::CLICK, /* on_top=*/SKIP_STEP,
                           actions.get());
   }
-  actions->emplace_back(base::BindOnce(&ActionDelegate::SendKeyboardInput,
-                                       delegate->GetWeakPtr(), codepoints,
-                                       delay_in_millis));
+  actions->emplace_back(base::BindOnce(
+      &WebController::SendKeyboardInput,
+      delegate->GetWebController()->GetWeakPtr(), codepoints, delay_in_millis));
 
   PerformAll(std::move(actions), element, std::move(done));
 }
@@ -329,25 +329,27 @@
 
   auto actions = std::make_unique<ElementActionVector>();
   if (value.empty()) {
-    actions->emplace_back(base::BindOnce(&ActionDelegate::SetValueAttribute,
-                                         delegate->GetWeakPtr(),
-                                         std::string()));
+    actions->emplace_back(base::BindOnce(
+        &WebController::SetValueAttribute,
+        delegate->GetWebController()->GetWeakPtr(), std::string()));
   } else {
     switch (fill_strategy) {
       case UNSPECIFIED_KEYBAORD_STRATEGY:
       case SET_VALUE:
-        actions->emplace_back(base::BindOnce(&ActionDelegate::SetValueAttribute,
-                                             delegate->GetWeakPtr(), value));
+        actions->emplace_back(
+            base::BindOnce(&WebController::SetValueAttribute,
+                           delegate->GetWebController()->GetWeakPtr(), value));
         break;
       case SIMULATE_KEY_PRESSES:
-        actions->emplace_back(base::BindOnce(&ActionDelegate::SetValueAttribute,
-                                             delegate->GetWeakPtr(),
-                                             std::string()));
+        actions->emplace_back(base::BindOnce(
+            &WebController::SetValueAttribute,
+            delegate->GetWebController()->GetWeakPtr(), std::string()));
         AddClickOrTapSequence(delegate, ClickType::CLICK,
                               /* on_top= */ SKIP_STEP, actions.get());
         actions->emplace_back(base::BindOnce(
-            &ActionDelegate::SendKeyboardInput, delegate->GetWeakPtr(),
-            UTF8ToUnicode(value), key_press_delay_in_millisecond));
+            &WebController::SendKeyboardInput,
+            delegate->GetWebController()->GetWeakPtr(), UTF8ToUnicode(value),
+            key_press_delay_in_millisecond));
         break;
       case SIMULATE_KEY_PRESSES_SELECT_VALUE:
         // TODO(b/149004036): In case of empty, send a backspace (i.e. code 8),
@@ -358,19 +360,21 @@
             base::BindOnce(&WebController::SelectFieldValue,
                            delegate->GetWebController()->GetWeakPtr()));
         actions->emplace_back(base::BindOnce(
-            &ActionDelegate::SendKeyboardInput, delegate->GetWeakPtr(),
-            UTF8ToUnicode(value), key_press_delay_in_millisecond));
+            &WebController::SendKeyboardInput,
+            delegate->GetWebController()->GetWeakPtr(), UTF8ToUnicode(value),
+            key_press_delay_in_millisecond));
         break;
       case SIMULATE_KEY_PRESSES_FOCUS:
-        actions->emplace_back(base::BindOnce(&ActionDelegate::SetValueAttribute,
-                                             delegate->GetWeakPtr(),
-                                             std::string()));
+        actions->emplace_back(base::BindOnce(
+            &WebController::SetValueAttribute,
+            delegate->GetWebController()->GetWeakPtr(), std::string()));
         actions->emplace_back(
             base::BindOnce(&WebController::FocusField,
                            delegate->GetWebController()->GetWeakPtr()));
         actions->emplace_back(base::BindOnce(
-            &ActionDelegate::SendKeyboardInput, delegate->GetWeakPtr(),
-            UTF8ToUnicode(value), key_press_delay_in_millisecond));
+            &WebController::SendKeyboardInput,
+            delegate->GetWebController()->GetWeakPtr(), UTF8ToUnicode(value),
+            key_press_delay_in_millisecond));
         break;
     }
   }
diff --git a/components/autofill_assistant/browser/actions/action_delegate_util_unittest.cc b/components/autofill_assistant/browser/actions/action_delegate_util_unittest.cc
index 7a760c9..476a95e 100644
--- a/components/autofill_assistant/browser/actions/action_delegate_util_unittest.cc
+++ b/components/autofill_assistant/browser/actions/action_delegate_util_unittest.cc
@@ -152,8 +152,8 @@
   EXPECT_CALL(*mock_delegate, WaitUntilDocumentIsInReadyState(_, _, _, _))
       .WillOnce(RunOnceCallback<3>(OkClientStatus(),
                                    base::TimeDelta::FromSeconds(0)));
-  EXPECT_CALL(*mock_delegate, WaitUntilElementIsStable(
-                                  _, _, EqualsElement(expected_element), _))
+  EXPECT_CALL(*mock_delegate, ScrollToElementPosition(
+                                  _, _, _, EqualsElement(expected_element), _))
       .Times(0);
   EXPECT_CALL(*this, MockDone(_)).Times(0);
 
@@ -172,10 +172,9 @@
         std::move(done).Run(OkClientStatus());
       },
       base::BindLambdaForTesting([&]() { mock_delegate.reset(); })));
-  AddStepIgnoreTiming(base::BindOnce(&ActionDelegate::WaitUntilElementIsStable,
-                                     mock_delegate->GetWeakPtr(), 1,
-                                     base::TimeDelta::FromMilliseconds(0)),
-                      actions.get());
+  actions->emplace_back(base::BindOnce(
+      &ActionDelegate::ScrollToElementPosition, mock_delegate->GetWeakPtr(),
+      Selector({"#element"}), TopPadding(), nullptr));
 
   FindElementAndPerform(mock_delegate.get(), expected_selector,
                         base::BindOnce(&PerformAll, std::move(actions)),
diff --git a/components/autofill_assistant/browser/actions/click_action_unittest.cc b/components/autofill_assistant/browser/actions/click_action_unittest.cc
index 1b8a2ee..07d9e13 100644
--- a/components/autofill_assistant/browser/actions/click_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/click_action_unittest.cc
@@ -38,7 +38,7 @@
                                           base::TimeDelta::FromSeconds(0)));
     ON_CALL(mock_web_controller_, ScrollIntoView(_, _, _))
         .WillByDefault(RunOnceCallback<2>(OkClientStatus()));
-    ON_CALL(mock_action_delegate_, WaitUntilElementIsStable(_, _, _, _))
+    ON_CALL(mock_web_controller_, WaitUntilElementIsStable(_, _, _, _))
         .WillByDefault(RunOnceCallback<3>(OkClientStatus(),
                                           base::TimeDelta::FromSeconds(0)));
     ON_CALL(mock_web_controller_, CheckOnTop(_, _))
@@ -100,7 +100,7 @@
               ScrollIntoView(true, EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       WaitUntilElementIsStable(_, _, EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<3>(OkClientStatus(),
                                    base::TimeDelta::FromSeconds(0)));
@@ -123,7 +123,7 @@
   ElementFinder::Result expected_element =
       test_util::MockFindElement(mock_action_delegate_, expected_selector);
 
-  EXPECT_CALL(mock_action_delegate_, WaitUntilElementIsStable(_, _, _, _))
+  EXPECT_CALL(mock_web_controller_, WaitUntilElementIsStable(_, _, _, _))
       .Times(0);
   EXPECT_CALL(mock_web_controller_, CheckOnTop(_, _)).Times(0);
   EXPECT_CALL(mock_action_delegate_,
@@ -165,7 +165,7 @@
 
   InSequence seq;
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       WaitUntilElementIsStable(_, _, EqualsElement(expected_element), _));
   EXPECT_CALL(mock_web_controller_,
               CheckOnTop(EqualsElement(expected_element), _));
@@ -191,7 +191,7 @@
 
   InSequence seq;
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       WaitUntilElementIsStable(_, _, EqualsElement(expected_element), _));
   EXPECT_CALL(mock_web_controller_,
               CheckOnTop(EqualsElement(expected_element), _));
diff --git a/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler.cc b/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler.cc
index 0abd22d5..088f92f 100644
--- a/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler.cc
+++ b/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler.cc
@@ -325,7 +325,7 @@
     }
 
     const ElementFinder::Result* element_ptr = element.get();
-    action_delegate_->SelectOption(
+    action_delegate_->GetWebController()->SelectOption(
         re2, /* case_sensitive= */ false, option_comparison_attribute,
         *element_ptr,
         base::BindOnce(&RequiredFieldsFallbackHandler::OnSetFallbackFieldValue,
diff --git a/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler_unittest.cc b/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler_unittest.cc
index b7e048dc..eca5e09 100644
--- a/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler_unittest.cc
+++ b/components/autofill_assistant/browser/actions/fallback_handler/required_fields_fallback_handler_unittest.cc
@@ -52,14 +52,14 @@
         .WillByDefault(Return(&mock_web_controller_));
     ON_CALL(mock_web_controller_, GetElementTag(_, _))
         .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "INPUT"));
-    ON_CALL(mock_action_delegate_, SetValueAttribute(_, _, _))
+    ON_CALL(mock_web_controller_, SetValueAttribute(_, _, _))
         .WillByDefault(RunOnceCallback<2>(OkClientStatus()));
     ON_CALL(mock_action_delegate_, WaitUntilDocumentIsInReadyState(_, _, _, _))
         .WillByDefault(RunOnceCallback<3>(OkClientStatus(),
                                           base::TimeDelta::FromSeconds(0)));
     ON_CALL(mock_web_controller_, ScrollIntoView(_, _, _))
         .WillByDefault(RunOnceCallback<2>(OkClientStatus()));
-    ON_CALL(mock_action_delegate_, WaitUntilElementIsStable(_, _, _, _))
+    ON_CALL(mock_web_controller_, WaitUntilElementIsStable(_, _, _, _))
         .WillByDefault(RunOnceCallback<3>(OkClientStatus(),
                                           base::TimeDelta::FromSeconds(0)));
   }
@@ -96,19 +96,19 @@
   Selector card_number_selector({"#card_number"});
   Selector card_network_selector({"#card_network"});
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, card_name_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, card_name_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), std::string()));
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, card_number_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, card_number_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), std::string()));
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, card_network_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, card_network_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), std::string()));
 
   std::vector<RequiredField> required_fields = {
@@ -170,9 +170,9 @@
 }
 
 TEST_F(RequiredFieldsFallbackHandlerTest, AddsFirstFieldFillingError) {
-  ON_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  ON_CALL(mock_web_controller_, GetFieldValue(_, _))
       .WillByDefault(RunOnceCallback<1>(OkClientStatus(), ""));
-  ON_CALL(mock_action_delegate_, SetValueAttribute(_, _, _))
+  ON_CALL(mock_web_controller_, SetValueAttribute(_, _, _))
       .WillByDefault(RunOnceCallback<2>(ClientStatus(OTHER_ACTION_STATUS)));
 
   std::vector<RequiredField> required_fields = {
@@ -224,7 +224,7 @@
 
 TEST_F(RequiredFieldsFallbackHandlerTest,
        AddsFirstEmptyFieldAfterFillingToError) {
-  ON_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  ON_CALL(mock_web_controller_, GetFieldValue(_, _))
       .WillByDefault(RunOnceCallback<1>(OkClientStatus(), ""));
 
   std::vector<RequiredField> required_fields = {
@@ -274,9 +274,9 @@
 }
 
 TEST_F(RequiredFieldsFallbackHandlerTest, DoesNotFallbackIfFieldsAreFilled) {
-  ON_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  ON_CALL(mock_web_controller_, GetFieldValue(_, _))
       .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "value"));
-  EXPECT_CALL(mock_action_delegate_, SetValueAttribute(_, _, _)).Times(0);
+  EXPECT_CALL(mock_web_controller_, SetValueAttribute(_, _, _)).Times(0);
 
   std::vector<RequiredField> required_fields = {
       CreateRequiredField("${51}", {"#card_name"})};
@@ -292,18 +292,18 @@
 }
 
 TEST_F(RequiredFieldsFallbackHandlerTest, FillsEmptyRequiredField) {
-  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  EXPECT_CALL(mock_web_controller_, GetFieldValue(_, _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), ""));
   Selector expected_selector({"#card_name"});
   Expectation set_value =
       EXPECT_CALL(
-          mock_action_delegate_,
+          mock_web_controller_,
           SetValueAttribute("John Doe",
                             EqualsElement(test_util::MockFindElement(
                                 mock_action_delegate_, expected_selector)),
                             _))
           .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  EXPECT_CALL(mock_web_controller_, GetFieldValue(_, _))
       .After(set_value)
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "John Doe"));
 
@@ -326,10 +326,10 @@
 }
 
 TEST_F(RequiredFieldsFallbackHandlerTest, FallsBackForForcedFilledField) {
-  ON_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  ON_CALL(mock_web_controller_, GetFieldValue(_, _))
       .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "value"));
   Selector expected_selector({"#card_name"});
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute("John Doe",
                                 EqualsElement(test_util::MockFindElement(
                                     mock_action_delegate_, expected_selector)),
@@ -356,9 +356,9 @@
 }
 
 TEST_F(RequiredFieldsFallbackHandlerTest, FailsIfForcedFieldDidNotGetFilled) {
-  ON_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  ON_CALL(mock_web_controller_, GetFieldValue(_, _))
       .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "value"));
-  EXPECT_CALL(mock_action_delegate_, SetValueAttribute(_, _, _)).Times(0);
+  EXPECT_CALL(mock_web_controller_, SetValueAttribute(_, _, _)).Times(0);
 
   std::vector<RequiredField> required_fields = {
       CreateRequiredField("${51}", {"#card_name"})};
@@ -399,18 +399,18 @@
 }
 
 TEST_F(RequiredFieldsFallbackHandlerTest, FillsFieldWithPattern) {
-  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  EXPECT_CALL(mock_web_controller_, GetFieldValue(_, _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), ""));
   Selector expected_selector({"#card_expiry"});
   Expectation set_value =
       EXPECT_CALL(
-          mock_action_delegate_,
+          mock_web_controller_,
           SetValueAttribute("08/2050",
                             EqualsElement(test_util::MockFindElement(
                                 mock_action_delegate_, expected_selector)),
                             _))
           .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  EXPECT_CALL(mock_web_controller_, GetFieldValue(_, _))
       .After(set_value)
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
@@ -437,10 +437,10 @@
 
 TEST_F(RequiredFieldsFallbackHandlerTest,
        FailsToFillFieldWithUnknownOrEmptyKey) {
-  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  EXPECT_CALL(mock_web_controller_, GetFieldValue(_, _))
       .Times(2)
       .WillRepeatedly(RunOnceCallback<1>(OkClientStatus(), ""));
-  EXPECT_CALL(mock_action_delegate_, SetValueAttribute(_, _, _)).Times(0);
+  EXPECT_CALL(mock_web_controller_, SetValueAttribute(_, _, _)).Times(0);
 
   std::vector<RequiredField> required_fields = {
       CreateRequiredField("${53}", {"#card_expiry"}),
@@ -503,9 +503,9 @@
 
   // First validation fails.
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, expected_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, expected_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), std::string()));
 
   // Fill field.
@@ -514,16 +514,16 @@
   EXPECT_CALL(mock_web_controller_,
               GetElementTag(EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "SELECT"));
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SelectOption("^2050", false, SelectOptionProto::LABEL,
                            EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<4>(OkClientStatus()));
 
   // Second validation succeeds.
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, expected_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, expected_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "2050"));
 
   std::vector<RequiredField> required_fields = {
@@ -545,8 +545,8 @@
 }
 
 TEST_F(RequiredFieldsFallbackHandlerTest, ClicksOnCustomDropdown) {
-  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _)).Times(0);
-  EXPECT_CALL(mock_action_delegate_, SetValueAttribute(_, _, _)).Times(0);
+  EXPECT_CALL(mock_web_controller_, GetFieldValue(_, _)).Times(0);
+  EXPECT_CALL(mock_web_controller_, SetValueAttribute(_, _, _)).Times(0);
   Selector expected_main_selector({"#card_expiry"});
   EXPECT_CALL(
       mock_action_delegate_,
@@ -589,8 +589,8 @@
 }
 
 TEST_F(RequiredFieldsFallbackHandlerTest, CustomDropdownClicksStopOnError) {
-  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _)).Times(0);
-  EXPECT_CALL(mock_action_delegate_, SetValueAttribute(_, _, _)).Times(0);
+  EXPECT_CALL(mock_web_controller_, GetFieldValue(_, _)).Times(0);
+  EXPECT_CALL(mock_web_controller_, SetValueAttribute(_, _, _)).Times(0);
   Selector expected_main_selector({"#card_expiry"});
   Expectation main_click =
       EXPECT_CALL(
@@ -639,13 +639,13 @@
 
   // First validation fails
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, expected_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, expected_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "value"));
 
   // Clears field.
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute(std::string(),
                                 EqualsElement(test_util::MockFindElement(
                                     mock_action_delegate_, expected_selector)),
@@ -654,9 +654,9 @@
 
   // Second validation succeeds.
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, expected_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, expected_selector)),
+                            _))
       .WillRepeatedly(RunOnceCallback<1>(OkClientStatus(), std::string()));
 
   std::vector<RequiredField> required_fields = {
@@ -679,11 +679,11 @@
   Selector forced_field_selector({"#forced_field"});
 
   // First validation skips forced fields.
-  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _)).Times(0);
+  EXPECT_CALL(mock_web_controller_, GetFieldValue(_, _)).Times(0);
 
   // Fills field.
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       SetValueAttribute("value",
                         EqualsElement(test_util::MockFindElement(
                             mock_action_delegate_, forced_field_selector)),
@@ -692,9 +692,9 @@
 
   // Second validation checks the field.
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, forced_field_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, forced_field_selector)),
+                            _))
       .WillRepeatedly(RunOnceCallback<1>(OkClientStatus(), "value"));
 
   auto forced_field = CreateRequiredField("value", {"#forced_field"});
@@ -720,16 +720,16 @@
   auto card_name_element =
       test_util::MockFindElement(mock_web_controller_, card_name_selector, 2);
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(card_name_element), _))
+              GetFieldValue(EqualsElement(card_name_element), _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), std::string()))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "value"));
   auto card_number_element =
       test_util::MockFindElement(mock_web_controller_, card_number_selector, 2);
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(card_number_element), _))
+              GetFieldValue(EqualsElement(card_number_element), _))
       .Times(2)
       .WillRepeatedly(RunOnceCallback<1>(OkClientStatus(), "value"));
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute(_,
                                 EqualsElement(test_util::MockFindElement(
                                     mock_action_delegate_, card_name_selector)),
diff --git a/components/autofill_assistant/browser/actions/get_element_status_action.cc b/components/autofill_assistant/browser/actions/get_element_status_action.cc
index eded04ba..0131717 100644
--- a/components/autofill_assistant/browser/actions/get_element_status_action.cc
+++ b/components/autofill_assistant/browser/actions/get_element_status_action.cc
@@ -13,6 +13,7 @@
 #include "components/autofill_assistant/browser/client_status.h"
 #include "components/autofill_assistant/browser/service.pb.h"
 #include "components/autofill_assistant/browser/user_data_util.h"
+#include "components/autofill_assistant/browser/web/web_controller.h"
 #include "third_party/re2/src/re2/re2.h"
 
 namespace autofill_assistant {
@@ -132,8 +133,9 @@
       selector_,
       base::BindOnce(
           &action_delegate_util::TakeElementAndGetProperty<std::string>,
-          base::BindOnce(&ActionDelegate::GetStringAttribute,
-                         delegate_->GetWeakPtr(), attribute_list),
+          base::BindOnce(&WebController::GetStringAttribute,
+                         delegate_->GetWebController()->GetWeakPtr(),
+                         attribute_list),
           base::BindOnce(&GetElementStatusAction::OnGetStringAttribute,
                          weak_ptr_factory_.GetWeakPtr())));
 }
diff --git a/components/autofill_assistant/browser/actions/get_element_status_action_unittest.cc b/components/autofill_assistant/browser/actions/get_element_status_action_unittest.cc
index 5a98281c..1297e2ca 100644
--- a/components/autofill_assistant/browser/actions/get_element_status_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/get_element_status_action_unittest.cc
@@ -16,6 +16,7 @@
 #include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
 #include "components/autofill_assistant/browser/selector.h"
 #include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/web/mock_web_controller.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace autofill_assistant {
@@ -39,11 +40,13 @@
   void SetUp() override {
     ON_CALL(mock_action_delegate_, GetUserData)
         .WillByDefault(Return(&user_data_));
+    ON_CALL(mock_action_delegate_, GetWebController)
+        .WillByDefault(Return(&mock_web_controller_));
     ON_CALL(mock_action_delegate_, OnShortWaitForElement(_, _))
         .WillByDefault(RunOnceCallback<1>(OkClientStatus(),
                                           base::TimeDelta::FromSeconds(0)));
     test_util::MockFindAnyElement(mock_action_delegate_);
-    ON_CALL(mock_action_delegate_, GetStringAttribute(_, _, _))
+    ON_CALL(mock_web_controller_, GetStringAttribute(_, _, _))
         .WillByDefault(RunOnceCallback<2>(OkClientStatus(), kValue));
 
     proto_.set_value_source(GetElementStatusProto::VALUE);
@@ -58,6 +61,7 @@
   }
 
   MockActionDelegate mock_action_delegate_;
+  MockWebController mock_web_controller_;
   base::MockCallback<Action::ProcessActionCallback> callback_;
   GetElementStatusProto proto_;
   UserData user_data_;
@@ -183,7 +187,7 @@
 
   auto expected_element =
       test_util::MockFindElement(mock_action_delegate_, selector);
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               GetStringAttribute(ElementsAre("value"),
                                  EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus(), kValue));
@@ -346,7 +350,7 @@
 }
 
 TEST_F(GetElementStatusActionTest, EmptyTextForEmptyValueIsSuccess) {
-  ON_CALL(mock_action_delegate_, GetStringAttribute(_, _, _))
+  ON_CALL(mock_web_controller_, GetStringAttribute(_, _, _))
       .WillByDefault(RunOnceCallback<2>(OkClientStatus(), std::string()));
 
   Selector selector({"#element"});
@@ -387,7 +391,7 @@
 
   auto expected_element =
       test_util::MockFindElement(mock_action_delegate_, selector);
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               GetStringAttribute(ElementsAre("innerText"),
                                  EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus(), kValue));
@@ -481,7 +485,7 @@
 }
 
 TEST_F(GetElementStatusActionTest, EmptyRegexpForEmptyValueIsSuccess) {
-  ON_CALL(mock_action_delegate_, GetStringAttribute(_, _, _))
+  ON_CALL(mock_web_controller_, GetStringAttribute(_, _, _))
       .WillByDefault(RunOnceCallback<2>(OkClientStatus(), std::string()));
 
   Selector selector({"#element"});
@@ -508,7 +512,7 @@
 }
 
 TEST_F(GetElementStatusActionTest, BlankTextWithRemovingSpacesIsExpectedEmpty) {
-  ON_CALL(mock_action_delegate_, GetStringAttribute(_, _, _))
+  ON_CALL(mock_web_controller_, GetStringAttribute(_, _, _))
       .WillByDefault(RunOnceCallback<2>(OkClientStatus(), "   "));
 
   Selector selector({"#element"});
diff --git a/components/autofill_assistant/browser/actions/mock_action_delegate.h b/components/autofill_assistant/browser/actions/mock_action_delegate.h
index eeee04f1..8f03f45 100644
--- a/components/autofill_assistant/browser/actions/mock_action_delegate.h
+++ b/components/autofill_assistant/browser/actions/mock_action_delegate.h
@@ -87,13 +87,6 @@
                     const ElementFinder::Result& element,
                     base::OnceCallback<void(const ClientStatus&)> callback));
 
-  MOCK_METHOD4(WaitUntilElementIsStable,
-               void(int,
-                    base::TimeDelta,
-                    const ElementFinder::Result& element,
-                    base::OnceCallback<void(const ClientStatus&,
-                                            base::TimeDelta)> callback));
-
   MOCK_METHOD5(Prompt,
                void(std::unique_ptr<std::vector<UserAction>> user_actions,
                     bool disable_force_expand_sheet,
@@ -147,81 +140,27 @@
                     const Selector& selector,
                     base::OnceCallback<void(const ClientStatus&)>& callback));
 
-  MOCK_METHOD5(SelectOption,
-               void(const std::string& re2,
-                    bool case_sensitive,
-                    SelectOptionProto::OptionComparisonAttribute
-                        option_comparison_attribute,
-                    const ElementFinder::Result& element,
-                    base::OnceCallback<void(const ClientStatus&)> callback));
-
   MOCK_METHOD5(ScrollToElementPosition,
                void(const Selector& selector,
                     const TopPadding& top_padding,
                     std::unique_ptr<ElementFinder::Result> scrollable_element,
                     const ElementFinder::Result& element,
                     base::OnceCallback<void(const ClientStatus&)> callback));
-
   MOCK_METHOD1(SetTouchableElementArea,
                void(const ElementAreaProto& touchable_element_area));
-
-  MOCK_METHOD2(HighlightElement,
-               void(const ElementFinder::Result& element,
-                    base::OnceCallback<void(const ClientStatus&)> callback));
-
   MOCK_METHOD1(CollectUserData,
                void(CollectUserDataOptions* collect_user_data_options));
-
   MOCK_METHOD1(
       SetLastSuccessfulUserDataOptions,
       void(std::unique_ptr<CollectUserDataOptions> collect_user_data_options));
-
   MOCK_CONST_METHOD0(GetLastSuccessfulUserDataOptions,
                      CollectUserDataOptions*());
-
   MOCK_METHOD1(
       WriteUserData,
       void(base::OnceCallback<void(UserData*, UserData::FieldChange*)>));
-
   MOCK_METHOD2(GetFullCard,
                void(const autofill::CreditCard* credit_card,
                     ActionDelegate::GetFullCardCallback callback));
-
-  MOCK_METHOD2(GetFieldValue,
-               void(const ElementFinder::Result& element,
-                    base::OnceCallback<void(const ClientStatus&,
-                                            const std::string&)> callback));
-
-  MOCK_METHOD3(GetStringAttribute,
-               void(const std::vector<std::string>& attributes,
-                    const ElementFinder::Result& element,
-                    base::OnceCallback<void(const ClientStatus&,
-                                            const std::string&)> callback));
-
-  MOCK_METHOD3(SetValueAttribute,
-               void(const std::string& value,
-                    const ElementFinder::Result& element,
-                    base::OnceCallback<void(const ClientStatus&)> callback));
-
-  MOCK_METHOD4(SetAttribute,
-               void(const std::vector<std::string>& attribute,
-                    const std::string& value,
-                    const ElementFinder::Result& element,
-                    base::OnceCallback<void(const ClientStatus&)> callback));
-
-  void SendKeyboardInput(
-      const std::vector<UChar32>& codepoints,
-      int delay_in_millisecond,
-      const ElementFinder::Result& element,
-      base::OnceCallback<void(const ClientStatus&)> callback) {
-    OnSendKeyboardInput(codepoints, delay_in_millisecond, element, callback);
-  }
-  MOCK_METHOD4(OnSendKeyboardInput,
-               void(const std::vector<UChar32>& codepoints,
-                    int delay_in_millisecond,
-                    const ElementFinder::Result& element,
-                    base::OnceCallback<void(const ClientStatus&)>& callback));
-
   MOCK_METHOD0(ExpectNavigation, void());
   MOCK_METHOD0(ExpectedNavigationHasStarted, bool());
   MOCK_METHOD1(WaitForNavigation,
diff --git a/components/autofill_assistant/browser/actions/select_option_action.cc b/components/autofill_assistant/browser/actions/select_option_action.cc
index c088199..83586d1a 100644
--- a/components/autofill_assistant/browser/actions/select_option_action.cc
+++ b/components/autofill_assistant/browser/actions/select_option_action.cc
@@ -13,6 +13,7 @@
 #include "components/autofill_assistant/browser/actions/action_delegate_util.h"
 #include "components/autofill_assistant/browser/client_status.h"
 #include "components/autofill_assistant/browser/user_data_util.h"
+#include "components/autofill_assistant/browser/web/web_controller.h"
 
 namespace autofill_assistant {
 
@@ -88,8 +89,9 @@
          SelectOptionProto::NOT_SET);
   action_delegate_util::FindElementAndPerform(
       delegate_, selector,
-      base::BindOnce(&ActionDelegate::SelectOption, delegate_->GetWeakPtr(),
-                     value_, case_sensitive_,
+      base::BindOnce(&WebController::SelectOption,
+                     delegate_->GetWebController()->GetWeakPtr(), value_,
+                     case_sensitive_,
                      proto_.select_option().option_comparison_attribute()),
       base::BindOnce(&SelectOptionAction::EndAction,
                      weak_ptr_factory_.GetWeakPtr()));
diff --git a/components/autofill_assistant/browser/actions/select_option_action_unittest.cc b/components/autofill_assistant/browser/actions/select_option_action_unittest.cc
index a1c6c6d..81100d4 100644
--- a/components/autofill_assistant/browser/actions/select_option_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/select_option_action_unittest.cc
@@ -16,6 +16,7 @@
 #include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
 #include "components/autofill_assistant/browser/selector.h"
 #include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/web/mock_web_controller.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace autofill_assistant {
@@ -33,6 +34,9 @@
   SelectOptionActionTest() {}
 
   void SetUp() override {
+    ON_CALL(mock_action_delegate_, GetWebController)
+        .WillByDefault(Return(&mock_web_controller_));
+
     proto_.set_option_comparison_attribute(SelectOptionProto::VALUE);
   }
 
@@ -48,6 +52,7 @@
   }
 
   MockActionDelegate mock_action_delegate_;
+  MockWebController mock_web_controller_;
   base::MockCallback<Action::ProcessActionCallback> callback_;
   SelectOptionProto proto_;
   UserData user_data_;
@@ -114,7 +119,7 @@
                                    base::TimeDelta::FromSeconds(0)));
   auto expected_element =
       test_util::MockFindElement(mock_action_delegate_, expected_selector);
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SelectOption("option", false, SelectOptionProto::VALUE,
                            EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<4>(OkClientStatus()));
@@ -185,7 +190,7 @@
               OnShortWaitForElement(expected_selector, _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(),
                                    base::TimeDelta::FromSeconds(0)));
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SelectOption("John", false, SelectOptionProto::VALUE,
                            EqualsElement(test_util::MockFindElement(
                                mock_action_delegate_, expected_selector)),
@@ -213,7 +218,7 @@
                                    base::TimeDelta::FromSeconds(0)));
   auto expected_element =
       test_util::MockFindElement(mock_action_delegate_, expected_selector);
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SelectOption("^option$", true, SelectOptionProto::VALUE,
                            EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<4>(OkClientStatus()));
@@ -250,7 +255,7 @@
               OnShortWaitForElement(expected_selector, _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(),
                                    base::TimeDelta::FromSeconds(0)));
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SelectOption("^\\+41791234567$", true, SelectOptionProto::VALUE,
                            EqualsElement(test_util::MockFindElement(
                                mock_action_delegate_, expected_selector)),
diff --git a/components/autofill_assistant/browser/actions/set_attribute_action.cc b/components/autofill_assistant/browser/actions/set_attribute_action.cc
index aeb6d49a..9f2c3a2 100644
--- a/components/autofill_assistant/browser/actions/set_attribute_action.cc
+++ b/components/autofill_assistant/browser/actions/set_attribute_action.cc
@@ -12,6 +12,7 @@
 #include "components/autofill_assistant/browser/actions/action_delegate_util.h"
 #include "components/autofill_assistant/browser/client_status.h"
 #include "components/autofill_assistant/browser/web/element_finder.h"
+#include "components/autofill_assistant/browser/web/web_controller.h"
 
 namespace autofill_assistant {
 
@@ -51,7 +52,8 @@
 
   action_delegate_util::FindElementAndPerform(
       delegate_, selector,
-      base::BindOnce(&ActionDelegate::SetAttribute, delegate_->GetWeakPtr(),
+      base::BindOnce(&WebController::SetAttribute,
+                     delegate_->GetWebController()->GetWeakPtr(),
                      ExtractVector(proto_.set_attribute().attribute()),
                      proto_.set_attribute().value()),
       base::BindOnce(&SetAttributeAction::OnSetAttribute,
diff --git a/components/autofill_assistant/browser/actions/set_attribute_action_unittest.cc b/components/autofill_assistant/browser/actions/set_attribute_action_unittest.cc
index aa75800..256987a 100644
--- a/components/autofill_assistant/browser/actions/set_attribute_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/set_attribute_action_unittest.cc
@@ -10,6 +10,7 @@
 #include "components/autofill_assistant/browser/actions/mock_action_delegate.h"
 #include "components/autofill_assistant/browser/selector.h"
 #include "components/autofill_assistant/browser/service.pb.h"
+#include "components/autofill_assistant/browser/web/mock_web_controller.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace autofill_assistant {
@@ -20,12 +21,16 @@
 using ::testing::InSequence;
 using ::testing::Pointee;
 using ::testing::Property;
+using ::testing::Return;
 
 class SetAttributeActionTest : public testing::Test {
  public:
   SetAttributeActionTest() {}
 
-  void SetUp() override {}
+  void SetUp() override {
+    ON_CALL(mock_action_delegate_, GetWebController)
+        .WillByDefault(Return(&mock_web_controller_));
+  }
 
  protected:
   void Run() {
@@ -36,6 +41,7 @@
   }
 
   MockActionDelegate mock_action_delegate_;
+  MockWebController mock_web_controller_;
   base::MockCallback<Action::ProcessActionCallback> callback_;
   SetAttributeProto proto_;
 };
@@ -64,7 +70,7 @@
   auto expected_element =
       test_util::MockFindElement(mock_action_delegate_, expected_selector);
   std::vector<std::string> expected_attributes = {"value"};
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetAttribute(expected_attributes, "Hello World",
                            EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<3>(OkClientStatus()));
diff --git a/components/autofill_assistant/browser/actions/set_form_field_value_action.cc b/components/autofill_assistant/browser/actions/set_form_field_value_action.cc
index 6719bdd..ab0c102 100644
--- a/components/autofill_assistant/browser/actions/set_form_field_value_action.cc
+++ b/components/autofill_assistant/browser/actions/set_form_field_value_action.cc
@@ -14,6 +14,7 @@
 #include "components/autofill_assistant/browser/client_status.h"
 #include "components/autofill_assistant/browser/user_data_util.h"
 #include "components/autofill_assistant/browser/web/element_finder.h"
+#include "components/autofill_assistant/browser/web/web_controller.h"
 
 namespace autofill_assistant {
 namespace {
@@ -266,7 +267,7 @@
     EndAction(status);
     return;
   }
-  delegate_->GetFieldValue(
+  delegate_->GetWebController()->GetFieldValue(
       *element_,
       base::BindOnce(&SetFormFieldValueAction::OnGetFieldValue,
                      weak_ptr_factory_.GetWeakPtr(),
diff --git a/components/autofill_assistant/browser/actions/set_form_field_value_action_unittest.cc b/components/autofill_assistant/browser/actions/set_form_field_value_action_unittest.cc
index 221e87c..c3ff7ce 100644
--- a/components/autofill_assistant/browser/actions/set_form_field_value_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/set_form_field_value_action_unittest.cc
@@ -65,10 +65,10 @@
     ON_CALL(mock_action_delegate_, OnShortWaitForElement(_, _))
         .WillByDefault(RunOnceCallback<1>(OkClientStatus(),
                                           base::TimeDelta::FromSeconds(0)));
-    ON_CALL(mock_action_delegate_, GetFieldValue(_, _))
+    ON_CALL(mock_web_controller_, GetFieldValue(_, _))
         .WillByDefault(RunOnceCallback<1>(OkClientStatus(), ""));
     test_util::MockFindAnyElement(mock_action_delegate_);
-    ON_CALL(mock_action_delegate_, SetValueAttribute(_, _, _))
+    ON_CALL(mock_web_controller_, SetValueAttribute(_, _, _))
         .WillByDefault(RunOnceCallback<2>(OkClientStatus()));
     ON_CALL(mock_web_controller_, SelectFieldValue(_, _))
         .WillByDefault(RunOnceCallback<1>(OkClientStatus()));
@@ -77,12 +77,12 @@
                                           base::TimeDelta::FromSeconds(0)));
     ON_CALL(mock_web_controller_, ScrollIntoView(_, _, _))
         .WillByDefault(RunOnceCallback<2>(OkClientStatus()));
-    ON_CALL(mock_action_delegate_, WaitUntilElementIsStable(_, _, _, _))
+    ON_CALL(mock_web_controller_, WaitUntilElementIsStable(_, _, _, _))
         .WillByDefault(RunOnceCallback<3>(OkClientStatus(),
                                           base::TimeDelta::FromSeconds(0)));
     ON_CALL(mock_action_delegate_, ClickOrTapElement(_, _, _))
         .WillByDefault(RunOnceCallback<2>(OkClientStatus()));
-    ON_CALL(mock_action_delegate_, OnSendKeyboardInput(_, _, _, _))
+    ON_CALL(mock_web_controller_, SendKeyboardInput(_, _, _, _))
         .WillByDefault(RunOnceCallback<3>(OkClientStatus()));
 
     user_data_.selected_login_ =
@@ -155,10 +155,10 @@
   const ElementFinder::Result& expected_element =
       test_util::MockFindElement(mock_action_delegate_, fake_selector_);
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       SetValueAttribute(kFakeUsername, EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               GetFieldValue(EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), kFakeUsername));
 
@@ -176,10 +176,10 @@
   const ElementFinder::Result& expected_element =
       test_util::MockFindElement(mock_action_delegate_, fake_selector_);
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       SetValueAttribute(kFakePassword, EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               GetFieldValue(EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), kFakePassword));
 
@@ -193,7 +193,7 @@
   auto* value = set_form_field_proto_->add_value();
   value->set_use_password(true);
   SetFormFieldValueAction action(&mock_action_delegate_, proto_);
-  ON_CALL(mock_action_delegate_, GetFieldValue(_, _))
+  ON_CALL(mock_web_controller_, GetFieldValue(_, _))
       .WillByDefault(RunOnceCallback<1>(OkClientStatus(), kFakePassword));
   action.ProcessAction(callback_.Get());
   EXPECT_TRUE(action.field_inputs_.empty());
@@ -203,11 +203,11 @@
   auto* value = set_form_field_proto_->add_value();
   value->set_keycode(13);  // carriage return
   SetFormFieldValueAction action(&mock_action_delegate_, proto_);
-  EXPECT_CALL(mock_action_delegate_,
-              OnSendKeyboardInput(std::vector<int>{13}, _,
-                                  EqualsElement(test_util::MockFindElement(
-                                      mock_action_delegate_, fake_selector_)),
-                                  _))
+  EXPECT_CALL(mock_web_controller_,
+              SendKeyboardInput(std::vector<int>{13}, _,
+                                EqualsElement(test_util::MockFindElement(
+                                    mock_action_delegate_, fake_selector_)),
+                                _))
       .WillOnce(RunOnceCallback<3>(OkClientStatus()));
 
   EXPECT_CALL(
@@ -221,11 +221,11 @@
   std::string keyboard_input = "SomeQuery𠜎\r";
   value->set_keyboard_input(keyboard_input);
   SetFormFieldValueAction action(&mock_action_delegate_, proto_);
-  EXPECT_CALL(mock_action_delegate_,
-              OnSendKeyboardInput(UTF8ToUnicode(keyboard_input), _,
-                                  EqualsElement(test_util::MockFindElement(
-                                      mock_action_delegate_, fake_selector_)),
-                                  _))
+  EXPECT_CALL(mock_web_controller_,
+              SendKeyboardInput(UTF8ToUnicode(keyboard_input), _,
+                                EqualsElement(test_util::MockFindElement(
+                                    mock_action_delegate_, fake_selector_)),
+                                _))
       .WillOnce(RunOnceCallback<3>(OkClientStatus()));
 
   EXPECT_CALL(
@@ -259,9 +259,9 @@
       mock_action_delegate_,
       ClickOrTapElement(ClickType::CLICK, EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
-              OnSendKeyboardInput(UTF8ToUnicode(keyboard_input), _,
-                                  EqualsElement(expected_element), _))
+  EXPECT_CALL(mock_web_controller_,
+              SendKeyboardInput(UTF8ToUnicode(keyboard_input), _,
+                                EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<3>(OkClientStatus()));
 
   EXPECT_CALL(
@@ -278,10 +278,10 @@
   const ElementFinder::Result& expected_element =
       test_util::MockFindElement(mock_action_delegate_, fake_selector_);
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       SetValueAttribute("SomeText𠜎", EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               GetFieldValue(EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "SomeText𠜎"));
 
@@ -305,7 +305,7 @@
                                    base::TimeDelta::FromSeconds(0)));
   auto expected_element =
       test_util::MockFindElement(mock_action_delegate_, fake_selector_);
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute("", EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
   EXPECT_CALL(mock_action_delegate_,
@@ -320,9 +320,9 @@
       mock_action_delegate_,
       ClickOrTapElement(ClickType::CLICK, EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
-              OnSendKeyboardInput(UTF8ToUnicode(keyboard_input), _,
-                                  EqualsElement(expected_element), _))
+  EXPECT_CALL(mock_web_controller_,
+              SendKeyboardInput(UTF8ToUnicode(keyboard_input), _,
+                                EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<3>(OkClientStatus()));
 
   EXPECT_CALL(
@@ -349,9 +349,9 @@
   EXPECT_CALL(mock_web_controller_,
               SelectFieldValue(EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
-              OnSendKeyboardInput(UTF8ToUnicode(keyboard_input), _,
-                                  EqualsElement(expected_element), _))
+  EXPECT_CALL(mock_web_controller_,
+              SendKeyboardInput(UTF8ToUnicode(keyboard_input), _,
+                                EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<3>(OkClientStatus()));
 
   EXPECT_CALL(
@@ -370,15 +370,15 @@
   SetFormFieldValueAction action(&mock_action_delegate_, proto_);
   const ElementFinder::Result& expected_element =
       test_util::MockFindElement(mock_action_delegate_, fake_selector_);
-  EXPECT_CALL(mock_action_delegate_,
-              OnSendKeyboardInput(UTF8ToUnicode("SomeText"), _,
-                                  EqualsElement(expected_element), _))
+  EXPECT_CALL(mock_web_controller_,
+              SendKeyboardInput(UTF8ToUnicode("SomeText"), _,
+                                EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<3>(OkClientStatus()));
   // The second entry, a deprecated keycode is transformed into a
   // field_input.keyboard_input.
-  EXPECT_CALL(mock_action_delegate_,
-              OnSendKeyboardInput(std::vector<int>{13}, _,
-                                  EqualsElement(expected_element), _))
+  EXPECT_CALL(mock_web_controller_,
+              SendKeyboardInput(std::vector<int>{13}, _,
+                                EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<3>(OkClientStatus()));
 
   EXPECT_CALL(
@@ -398,10 +398,10 @@
   const ElementFinder::Result& expected_element =
       test_util::MockFindElement(mock_action_delegate_, fake_selector_);
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       SetValueAttribute("SomeText𠜎", EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               GetFieldValue(EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "SomeText𠜎"));
 
@@ -430,19 +430,19 @@
 
   const ElementFinder::Result& expected_element =
       test_util::MockFindElement(mock_action_delegate_, fake_selector_);
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute("123", EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               GetFieldValue(EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), std::string()));
 
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute("", EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
-              OnSendKeyboardInput(UTF8ToUnicode("123"), _,
-                                  EqualsElement(expected_element), _))
+  EXPECT_CALL(mock_web_controller_,
+              SendKeyboardInput(UTF8ToUnicode("123"), _,
+                                EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<3>(OkClientStatus()));
 
   EXPECT_CALL(callback_,
@@ -465,19 +465,19 @@
   const ElementFinder::Result& expected_element =
       test_util::MockFindElement(mock_action_delegate_, fake_selector_);
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       SetValueAttribute(kFakePassword, EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               GetFieldValue(EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), std::string()));
 
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute("", EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
-              OnSendKeyboardInput(UTF8ToUnicode(kFakePassword), _,
-                                  EqualsElement(expected_element), _))
+  EXPECT_CALL(mock_web_controller_,
+              SendKeyboardInput(UTF8ToUnicode(kFakePassword), _,
+                                EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<3>(OkClientStatus()));
 
   EXPECT_CALL(callback_,
@@ -503,36 +503,36 @@
       test_util::MockFindElement(mock_action_delegate_, fake_selector_);
 
   // First value.
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute("SomeText", EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               GetFieldValue(EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), std::string()));
 
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute("", EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
-              OnSendKeyboardInput(UTF8ToUnicode("SomeText"), _,
-                                  EqualsElement(expected_element), _))
+  EXPECT_CALL(mock_web_controller_,
+              SendKeyboardInput(UTF8ToUnicode("SomeText"), _,
+                                EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<3>(OkClientStatus()));
 
   // Second value.
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       SetValueAttribute("SomeOtherText", EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               GetFieldValue(EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), std::string()));
 
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute("", EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
-              OnSendKeyboardInput(UTF8ToUnicode("SomeOtherText"), _,
-                                  EqualsElement(expected_element), _))
+  EXPECT_CALL(mock_web_controller_,
+              SendKeyboardInput(UTF8ToUnicode("SomeOtherText"), _,
+                                EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<3>(OkClientStatus()));
 
   EXPECT_CALL(callback_,
@@ -608,10 +608,10 @@
 
   const ElementFinder::Result& expected_element =
       test_util::MockFindElement(mock_action_delegate_, fake_selector_);
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute("John", EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               GetFieldValue(EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
diff --git a/components/autofill_assistant/browser/actions/show_cast_action.cc b/components/autofill_assistant/browser/actions/show_cast_action.cc
index 3dcc821..27361f70 100644
--- a/components/autofill_assistant/browser/actions/show_cast_action.cc
+++ b/components/autofill_assistant/browser/actions/show_cast_action.cc
@@ -129,8 +129,8 @@
       base::BindOnce(
           &ShowCastAction::RunAndIncreaseWaitTimer,
           weak_ptr_factory_.GetWeakPtr(),
-          base::BindOnce(&ActionDelegate::WaitUntilElementIsStable,
-                         delegate_->GetWeakPtr(),
+          base::BindOnce(&WebController::WaitUntilElementIsStable,
+                         delegate_->GetWebController()->GetWeakPtr(),
                          proto_.show_cast().stable_check_max_rounds(),
                          base::TimeDelta::FromMilliseconds(
                              proto_.show_cast().stable_check_interval_ms()))),
diff --git a/components/autofill_assistant/browser/actions/show_cast_action_unittest.cc b/components/autofill_assistant/browser/actions/show_cast_action_unittest.cc
index 3a4065f..30b653ed 100644
--- a/components/autofill_assistant/browser/actions/show_cast_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/show_cast_action_unittest.cc
@@ -164,7 +164,7 @@
               ScrollIntoView(false, EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       WaitUntilElementIsStable(_, _, EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<3>(OkClientStatus(),
                                    base::TimeDelta::FromSeconds(1)));
diff --git a/components/autofill_assistant/browser/actions/use_address_action_unittest.cc b/components/autofill_assistant/browser/actions/use_address_action_unittest.cc
index 2e99679..e294c811 100644
--- a/components/autofill_assistant/browser/actions/use_address_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/use_address_action_unittest.cc
@@ -166,7 +166,7 @@
           OnShortWaitForElement(Selector({kFakeSelector}), _))
       .WillByDefault(RunOnceCallback<1>(OkClientStatus(),
                                         base::TimeDelta::FromSeconds(0)));
-  ON_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  ON_CALL(mock_web_controller_, GetFieldValue(_, _))
       .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
   ActionProto action;
@@ -201,7 +201,7 @@
           OnShortWaitForElement(Selector({kFakeSelector}), _))
       .WillByDefault(RunOnceCallback<1>(OkClientStatus(),
                                         base::TimeDelta::FromSeconds(0)));
-  ON_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  ON_CALL(mock_web_controller_, GetFieldValue(_, _))
       .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
   ActionProto action;
@@ -249,7 +249,7 @@
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
 
   // Validation succeeds.
-  ON_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  ON_CALL(mock_web_controller_, GetFieldValue(_, _))
       .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
   EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED,
@@ -285,7 +285,7 @@
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
 
   // Validation succeeds.
-  ON_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  ON_CALL(mock_web_controller_, GetFieldValue(_, _))
       .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
   EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED,
@@ -327,24 +327,24 @@
 
   // Validation fails when getting FIRST_NAME.
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, email_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, email_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, first_name_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, first_name_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), ""));
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, last_name_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, last_name_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
   // Fallback fails.
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       SetValueAttribute(kFirstName,
                         EqualsElement(test_util::MockFindElement(
                             mock_action_delegate_, first_name_selector)),
@@ -406,25 +406,25 @@
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
 
   // First validation fails with an empty value, called once for each field.
-  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  EXPECT_CALL(mock_web_controller_, GetFieldValue(_, _))
       .Times(3)
       .WillRepeatedly(RunOnceCallback<1>(OkClientStatus(), std::string()));
 
   // Expect fields to be filled
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       SetValueAttribute(kFirstName,
                         EqualsElement(test_util::MockFindElement(
                             mock_action_delegate_, first_name_selector)),
                         _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute(kLastName,
                                 EqualsElement(test_util::MockFindElement(
                                     mock_action_delegate_, last_name_selector)),
                                 _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute(kEmail,
                                 EqualsElement(test_util::MockFindElement(
                                     mock_action_delegate_, email_selector)),
@@ -432,7 +432,7 @@
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
 
   // Second validation succeeds.
-  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  EXPECT_CALL(mock_web_controller_, GetFieldValue(_, _))
       .Times(3)
       .WillRepeatedly(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
@@ -482,13 +482,13 @@
 
   // First validation fails.
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, first_name_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, first_name_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), ""));
   // Fill first name.
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       SetValueAttribute(kFirstName,
                         EqualsElement(test_util::MockFindElement(
                             mock_action_delegate_, first_name_selector)),
@@ -496,9 +496,9 @@
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
   // Second validation succeeds.
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, first_name_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, first_name_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
   ProcessedActionProto processed_action;
@@ -533,14 +533,14 @@
 
   // Validation fails when getting phone number.
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, phone_number_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, phone_number_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), ""));
 
   // Fallback succeeds.
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       SetValueAttribute("(+41) (79) 1234567",
                         EqualsElement(test_util::MockFindElement(
                             mock_action_delegate_, phone_number_selector)),
@@ -549,9 +549,9 @@
 
   // Second validation succeeds.
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, phone_number_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, phone_number_selector)),
+                            _))
       .WillRepeatedly(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
   EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED,
@@ -584,12 +584,12 @@
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
 
   // Do not check required field.
-  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _)).Times(0);
+  EXPECT_CALL(mock_web_controller_, GetFieldValue(_, _)).Times(0);
 
   // But we still want the first name filled, with simulated keypresses.
   auto expected_element =
       test_util::MockFindElement(mock_action_delegate_, first_name_selector);
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute("", EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
   EXPECT_CALL(mock_action_delegate_,
@@ -600,23 +600,23 @@
   EXPECT_CALL(mock_web_controller_,
               ScrollIntoView(true, EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_, WaitUntilElementIsStable(_, _, _, _))
+  EXPECT_CALL(mock_web_controller_, WaitUntilElementIsStable(_, _, _, _))
       .WillOnce(RunOnceCallback<3>(OkClientStatus(),
                                    base::TimeDelta::FromSeconds(0)));
   EXPECT_CALL(
       mock_action_delegate_,
       ClickOrTapElement(ClickType::CLICK, EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
-              OnSendKeyboardInput(UTF8ToUnicode(kFirstName), 1000,
-                                  EqualsElement(expected_element), _))
+  EXPECT_CALL(mock_web_controller_,
+              SendKeyboardInput(UTF8ToUnicode(kFirstName), 1000,
+                                EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<3>(OkClientStatus()));
 
   // The field is only checked afterwards and is not empty.
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, first_name_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, first_name_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
   EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED,
@@ -646,13 +646,13 @@
 
   // First validation fails.
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, first_name_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, first_name_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), ""));
   // Fill first name.
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       SetValueAttribute(kFirstName,
                         EqualsElement(test_util::MockFindElement(
                             mock_action_delegate_, first_name_selector)),
@@ -660,9 +660,9 @@
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
   // Second validation succeeds.
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, first_name_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, first_name_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
   ProcessedActionProto processed_action;
diff --git a/components/autofill_assistant/browser/actions/use_credit_card_action_unittest.cc b/components/autofill_assistant/browser/actions/use_credit_card_action_unittest.cc
index 1b9206b0..3f4998e 100644
--- a/components/autofill_assistant/browser/actions/use_credit_card_action_unittest.cc
+++ b/components/autofill_assistant/browser/actions/use_credit_card_action_unittest.cc
@@ -164,7 +164,7 @@
           OnShortWaitForElement(Selector({kFakeSelector}), _))
       .WillByDefault(RunOnceCallback<1>(OkClientStatus(),
                                         base::TimeDelta::FromSeconds(0)));
-  ON_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  ON_CALL(mock_web_controller_, GetFieldValue(_, _))
       .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "not empty"));
   ActionProto action;
   auto* use_card = action.mutable_use_card();
@@ -200,7 +200,7 @@
           OnShortWaitForElement(Selector({kFakeSelector}), _))
       .WillByDefault(RunOnceCallback<1>(OkClientStatus(),
                                         base::TimeDelta::FromSeconds(0)));
-  ON_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  ON_CALL(mock_web_controller_, GetFieldValue(_, _))
       .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "not empty"));
   ActionProto action;
   auto* use_card = action.mutable_use_card();
@@ -228,7 +228,7 @@
 
 TEST_F(UseCreditCardActionTest, FillCreditCardRequiredFieldsFilled) {
   // Validation succeeds.
-  ON_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  ON_CALL(mock_web_controller_, GetFieldValue(_, _))
       .WillByDefault(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
   ActionProto action = CreateUseCreditCardAction();
@@ -322,52 +322,52 @@
   Selector network_selector({"#network"});
 
   // First validation fails with an empty value, called once for each field.
-  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  EXPECT_CALL(mock_web_controller_, GetFieldValue(_, _))
       .Times(7)
       .WillRepeatedly(RunOnceCallback<1>(OkClientStatus(), std::string()));
 
   // Expect fields to be filled
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute(kFakeCvc,
                                 EqualsElement(test_util::MockFindElement(
                                     mock_action_delegate_, cvc_selector)),
                                 _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       SetValueAttribute("09",
                         EqualsElement(test_util::MockFindElement(
                             mock_action_delegate_, expiry_month_selector)),
                         _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       SetValueAttribute("50",
                         EqualsElement(test_util::MockFindElement(
                             mock_action_delegate_, expiry_year2_selector)),
                         _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       SetValueAttribute("2050",
                         EqualsElement(test_util::MockFindElement(
                             mock_action_delegate_, expiry_year4_selector)),
                         _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute("Adam West",
                                 EqualsElement(test_util::MockFindElement(
                                     mock_action_delegate_, card_name_selector)),
                                 _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       SetValueAttribute("4111111111111111",
                         EqualsElement(test_util::MockFindElement(
                             mock_action_delegate_, card_number_selector)),
                         _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute("visa",
                                 EqualsElement(test_util::MockFindElement(
                                     mock_action_delegate_, network_selector)),
@@ -375,7 +375,7 @@
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
 
   // After fallback, second validation succeeds.
-  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _))
+  EXPECT_CALL(mock_web_controller_, GetFieldValue(_, _))
       .Times(7)
       .WillRepeatedly(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
@@ -407,13 +407,13 @@
       .WillOnce(RunOnceCallback<3>(OkClientStatus()));
 
   // Do not check required field.
-  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _)).Times(0);
+  EXPECT_CALL(mock_web_controller_, GetFieldValue(_, _)).Times(0);
 
   // But we still want the CVC filled, with simulated keypresses.
   Selector cvc_selector({"#cvc"});
   auto expected_element =
       test_util::MockFindElement(mock_action_delegate_, cvc_selector);
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute("", EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
   EXPECT_CALL(mock_action_delegate_,
@@ -424,23 +424,23 @@
   EXPECT_CALL(mock_web_controller_,
               ScrollIntoView(true, EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_, WaitUntilElementIsStable(_, _, _, _))
+  EXPECT_CALL(mock_web_controller_, WaitUntilElementIsStable(_, _, _, _))
       .WillOnce(RunOnceCallback<3>(OkClientStatus(),
                                    base::TimeDelta::FromSeconds(0)));
   EXPECT_CALL(
       mock_action_delegate_,
       ClickOrTapElement(ClickType::CLICK, EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
-  EXPECT_CALL(mock_action_delegate_,
-              OnSendKeyboardInput(UTF8ToUnicode(kFakeCvc), 1000,
-                                  EqualsElement(expected_element), _))
+  EXPECT_CALL(mock_web_controller_,
+              SendKeyboardInput(UTF8ToUnicode(kFakeCvc), 1000,
+                                EqualsElement(expected_element), _))
       .WillOnce(RunOnceCallback<3>(OkClientStatus()));
 
   // The field is only checked afterwards and is not empty.
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, cvc_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, cvc_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
   EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED, ProcessAction(action));
@@ -469,12 +469,12 @@
 
   // First validation fails.
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, cvc_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, cvc_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), ""));
   // Fill cvc.
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute(kFakeCvc,
                                 EqualsElement(test_util::MockFindElement(
                                     mock_action_delegate_, cvc_selector)),
@@ -482,9 +482,9 @@
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
   // Second validation succeeds.
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, cvc_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, cvc_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
   EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED, ProcessAction(action));
@@ -537,12 +537,12 @@
 
   // First validation fails.
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, cvc_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, cvc_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), ""));
   // Fill CVC.
-  EXPECT_CALL(mock_action_delegate_,
+  EXPECT_CALL(mock_web_controller_,
               SetValueAttribute(kFakeCvc,
                                 EqualsElement(test_util::MockFindElement(
                                     mock_action_delegate_, cvc_selector)),
@@ -550,9 +550,9 @@
       .WillOnce(RunOnceCallback<2>(OkClientStatus()));
   // Second validation succeeds.
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, cvc_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, cvc_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
   ProcessedActionProto processed_action;
@@ -589,14 +589,14 @@
   // Validation fails when getting expiration date.
   EXPECT_CALL(
       mock_web_controller_,
-      OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                          mock_web_controller_, expiration_date_selector)),
-                      _))
+      GetFieldValue(EqualsElement(test_util::MockFindElement(
+                        mock_web_controller_, expiration_date_selector)),
+                    _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), ""));
 
   // Fallback succeeds.
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       SetValueAttribute("09 - 2050",
                         EqualsElement(test_util::MockFindElement(
                             mock_action_delegate_, expiration_date_selector)),
@@ -606,9 +606,9 @@
   // Second validation succeeds.
   EXPECT_CALL(
       mock_web_controller_,
-      OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                          mock_web_controller_, expiration_date_selector)),
-                      _))
+      GetFieldValue(EqualsElement(test_util::MockFindElement(
+                        mock_web_controller_, expiration_date_selector)),
+                    _))
       .WillRepeatedly(RunOnceCallback<1>(OkClientStatus(), "not empty"));
 
   EXPECT_EQ(ProcessedActionStatusProto::ACTION_APPLIED,
@@ -633,14 +633,14 @@
   // Validation fails when getting expiration date.
   EXPECT_CALL(
       mock_web_controller_,
-      OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                          mock_web_controller_, expiration_date_selector)),
-                      _))
+      GetFieldValue(EqualsElement(test_util::MockFindElement(
+                        mock_web_controller_, expiration_date_selector)),
+                    _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), ""));
 
   // Fallback fails.
   EXPECT_CALL(
-      mock_action_delegate_,
+      mock_web_controller_,
       SetValueAttribute("09/2050",
                         EqualsElement(test_util::MockFindElement(
                             mock_action_delegate_, expiration_date_selector)),
diff --git a/components/autofill_assistant/browser/batch_element_checker_unittest.cc b/components/autofill_assistant/browser/batch_element_checker_unittest.cc
index ee1f6d9a..0be4906 100644
--- a/components/autofill_assistant/browser/batch_element_checker_unittest.cc
+++ b/components/autofill_assistant/browser/batch_element_checker_unittest.cc
@@ -132,9 +132,9 @@
 TEST_F(BatchElementCheckerTest, OneFieldValueFound) {
   Selector expected_selector({"field"});
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, expected_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, expected_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "some value"));
   checks_.AddFieldValueCheck(expected_selector, FieldValueCallback("field"));
   Run("was_run");
@@ -148,7 +148,7 @@
   EXPECT_CALL(mock_web_controller_, OnFindElement(expected_selector, _))
       .WillOnce(
           RunOnceCallback<1>(ClientStatus(ELEMENT_RESOLUTION_FAILED), nullptr));
-  EXPECT_CALL(mock_web_controller_, OnGetFieldValue(_, _)).Times(0);
+  EXPECT_CALL(mock_web_controller_, GetFieldValue(_, _)).Times(0);
   checks_.AddFieldValueCheck(expected_selector, FieldValueCallback("field"));
   Run("was_run");
 
@@ -159,9 +159,9 @@
 TEST_F(BatchElementCheckerTest, OneFieldValueEmpty) {
   Selector expected_selector({"field"});
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, expected_selector)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, expected_selector)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), std::string()));
   checks_.AddFieldValueCheck(expected_selector, FieldValueCallback("field"));
   Run("was_run");
@@ -181,15 +181,15 @@
           RunOnceCallback<1>(ClientStatus(ELEMENT_RESOLUTION_FAILED), nullptr));
   Selector expected_selector_4({"4"});
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, expected_selector_4)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, expected_selector_4)),
+                            _))
       .WillOnce(RunOnceCallback<1>(OkClientStatus(), "value"));
   Selector expected_selector_5({"5"});
   EXPECT_CALL(mock_web_controller_,
-              OnGetFieldValue(EqualsElement(test_util::MockFindElement(
-                                  mock_web_controller_, expected_selector_5)),
-                              _))
+              GetFieldValue(EqualsElement(test_util::MockFindElement(
+                                mock_web_controller_, expected_selector_5)),
+                            _))
       .WillOnce(RunOnceCallback<1>(ClientStatus(ELEMENT_RESOLUTION_FAILED),
                                    std::string()));
 
diff --git a/components/autofill_assistant/browser/protocol_utils.cc b/components/autofill_assistant/browser/protocol_utils.cc
index f0a6c77..4bc2e25 100644
--- a/components/autofill_assistant/browser/protocol_utils.cc
+++ b/components/autofill_assistant/browser/protocol_utils.cc
@@ -291,10 +291,12 @@
       }
       return PerformOnSingleElementAction::WithClientId(
           delegate, action, action.set_element_attribute().client_id(),
-          base::BindOnce(&action_delegate_util::PerformWithTextValue, delegate,
-                         action.set_element_attribute().value(),
-                         base::BindOnce(&ActionDelegate::SetAttribute,
-                                        delegate->GetWeakPtr(), attributes)));
+          base::BindOnce(
+              &action_delegate_util::PerformWithTextValue, delegate,
+              action.set_element_attribute().value(),
+              base::BindOnce(&WebController::SetAttribute,
+                             delegate->GetWebController()->GetWeakPtr(),
+                             attributes)));
     }
     case ActionProto::ActionInfoCase::kSelectFieldValue:
       return PerformOnSingleElementAction::WithClientId(
@@ -310,8 +312,8 @@
       return PerformOnSingleElementAction::WithClientIdTimed(
           delegate, action,
           action.wait_for_element_to_become_stable().client_id(),
-          base::BindOnce(&ActionDelegate::WaitUntilElementIsStable,
-                         delegate->GetWeakPtr(),
+          base::BindOnce(&WebController::WaitUntilElementIsStable,
+                         delegate->GetWebController()->GetWeakPtr(),
                          action.wait_for_element_to_become_stable()
                              .stable_check_max_rounds(),
                          base::TimeDelta::FromMilliseconds(
diff --git a/components/autofill_assistant/browser/script_executor.cc b/components/autofill_assistant/browser/script_executor.cc
index 0094d74e..f6d5752f 100644
--- a/components/autofill_assistant/browser/script_executor.cc
+++ b/components/autofill_assistant/browser/script_executor.cc
@@ -350,15 +350,6 @@
   delegate_->GetWebController()->FindAllElements(selector, std::move(callback));
 }
 
-void ScriptExecutor::WaitUntilElementIsStable(
-    int max_rounds,
-    base::TimeDelta check_interval,
-    const ElementFinder::Result& element,
-    base::OnceCallback<void(const ClientStatus&, base::TimeDelta)> callback) {
-  delegate_->GetWebController()->WaitUntilElementIsStable(
-      element, max_rounds, check_interval, std::move(callback));
-}
-
 void ScriptExecutor::ClickOrTapElement(
     ClickType click_type,
     const ElementFinder::Result& element,
@@ -545,17 +536,6 @@
       selector, std::move(callback));
 }
 
-void ScriptExecutor::SelectOption(
-    const std::string& re2,
-    bool case_sensitive,
-    SelectOptionProto::OptionComparisonAttribute option_comparison_attribute,
-    const ElementFinder::Result& element,
-    base::OnceCallback<void(const ClientStatus&)> callback) {
-  delegate_->GetWebController()->SelectOption(element, re2, case_sensitive,
-                                              option_comparison_attribute,
-                                              std::move(callback));
-}
-
 void ScriptExecutor::ScrollToElementPosition(
     const Selector& selector,
     const TopPadding& top_padding,
@@ -600,48 +580,6 @@
   delegate_->SetStepProgressBarConfiguration(configuration);
 }
 
-void ScriptExecutor::GetFieldValue(
-    const ElementFinder::Result& element,
-    base::OnceCallback<void(const ClientStatus&, const std::string&)>
-        callback) {
-  delegate_->GetWebController()->GetFieldValue(element, std::move(callback));
-}
-
-void ScriptExecutor::GetStringAttribute(
-    const std::vector<std::string>& attributes,
-    const ElementFinder::Result& element,
-    base::OnceCallback<void(const ClientStatus&, const std::string&)>
-        callback) {
-  delegate_->GetWebController()->GetStringAttribute(element, attributes,
-                                                    std::move(callback));
-}
-
-void ScriptExecutor::SetValueAttribute(
-    const std::string& value,
-    const ElementFinder::Result& element,
-    base::OnceCallback<void(const ClientStatus&)> callback) {
-  delegate_->GetWebController()->SetValueAttribute(element, value,
-                                                   std::move(callback));
-}
-
-void ScriptExecutor::SetAttribute(
-    const std::vector<std::string>& attributes,
-    const std::string& value,
-    const ElementFinder::Result& element,
-    base::OnceCallback<void(const ClientStatus&)> callback) {
-  delegate_->GetWebController()->SetAttribute(element, attributes, value,
-                                              std::move(callback));
-}
-
-void ScriptExecutor::SendKeyboardInput(
-    const std::vector<UChar32>& codepoints,
-    int key_press_delay_in_millisecond,
-    const ElementFinder::Result& element,
-    base::OnceCallback<void(const ClientStatus&)> callback) {
-  delegate_->GetWebController()->SendKeyboardInput(
-      element, codepoints, key_press_delay_in_millisecond, std::move(callback));
-}
-
 void ScriptExecutor::ExpectNavigation() {
   // TODO(b/160948417): Clean this up such that the logic is not required in
   //  both |ScriptExecutor| and |Controller|.
diff --git a/components/autofill_assistant/browser/script_executor.h b/components/autofill_assistant/browser/script_executor.h
index 6ab1434..e66241c3 100644
--- a/components/autofill_assistant/browser/script_executor.h
+++ b/components/autofill_assistant/browser/script_executor.h
@@ -133,12 +133,6 @@
                    ElementFinder::Callback callback) const override;
   void FindAllElements(const Selector& selector,
                        ElementFinder::Callback callback) const override;
-  void WaitUntilElementIsStable(
-      int max_rounds,
-      base::TimeDelta check_interval,
-      const ElementFinder::Result& element,
-      base::OnceCallback<void(const ClientStatus&, base::TimeDelta)> callback)
-      override;
   void ClickOrTapElement(
       ClickType click_type,
       const ElementFinder::Result& element,
@@ -175,12 +169,6 @@
                               const autofill::FormData& form_data,
                               const autofill::FormFieldData& field_data)>
           callback) override;
-  void SelectOption(
-      const std::string& re2,
-      bool case_sensitive,
-      SelectOptionProto::OptionComparisonAttribute option_comparison_attribute,
-      const ElementFinder::Result& element,
-      base::OnceCallback<void(const ClientStatus&)> callback) override;
   void ScrollToElementPosition(
       const Selector& selector,
       const TopPadding& top_padding,
@@ -189,29 +177,6 @@
       base::OnceCallback<void(const ClientStatus&)> callback) override;
   void SetTouchableElementArea(
       const ElementAreaProto& touchable_element_area) override;
-  void GetFieldValue(
-      const ElementFinder::Result& element,
-      base::OnceCallback<void(const ClientStatus&, const std::string&)>
-          callback) override;
-  void GetStringAttribute(
-      const std::vector<std::string>& attributes,
-      const ElementFinder::Result& element,
-      base::OnceCallback<void(const ClientStatus&, const std::string&)>
-          callback) override;
-  void SetValueAttribute(
-      const std::string& value,
-      const ElementFinder::Result& element,
-      base::OnceCallback<void(const ClientStatus&)> callback) override;
-  void SetAttribute(
-      const std::vector<std::string>& attributes,
-      const std::string& value,
-      const ElementFinder::Result& element,
-      base::OnceCallback<void(const ClientStatus&)> callback) override;
-  void SendKeyboardInput(
-      const std::vector<UChar32>& codepoints,
-      int key_press_delay_in_millisecond,
-      const ElementFinder::Result& element,
-      base::OnceCallback<void(const ClientStatus&)> callback) override;
   void ExpectNavigation() override;
   bool ExpectedNavigationHasStarted() override;
   bool WaitForNavigation(base::OnceCallback<void(bool)> callback) override;
diff --git a/components/autofill_assistant/browser/web/mock_web_controller.h b/components/autofill_assistant/browser/web/mock_web_controller.h
index 868afb5..b0e45b6 100644
--- a/components/autofill_assistant/browser/web/mock_web_controller.h
+++ b/components/autofill_assistant/browser/web/mock_web_controller.h
@@ -42,6 +42,13 @@
   MOCK_METHOD2(CheckOnTop,
                void(const ElementFinder::Result&,
                     base::OnceCallback<void(const ClientStatus&)>));
+  MOCK_METHOD5(SelectOption,
+               void(const std::string& re2,
+                    bool case_sensitive,
+                    SelectOptionProto::OptionComparisonAttribute
+                        option_comparison_attribute,
+                    const ElementFinder::Result& element,
+                    base::OnceCallback<void(const ClientStatus&)> callback));
   MOCK_METHOD2(HighlightElement,
                void(const ElementFinder::Result&,
                     base::OnceCallback<void(const ClientStatus&)>));
@@ -51,6 +58,11 @@
   MOCK_METHOD2(FocusField,
                void(const ElementFinder::Result& element,
                     base::OnceCallback<void(const ClientStatus&)> callback));
+  MOCK_METHOD4(SendKeyboardInput,
+               void(const std::vector<UChar32>& codepoints,
+                    int delay_in_millisecond,
+                    const ElementFinder::Result& element,
+                    base::OnceCallback<void(const ClientStatus&)> callback));
   MOCK_METHOD2(GetOuterHtml,
                void(const ElementFinder::Result& element,
                     base::OnceCallback<void(const ClientStatus&,
@@ -68,11 +80,10 @@
       void(const ElementFinder::Result& elements,
            base::OnceCallback<void(const ClientStatus&,
                                    const std::vector<std::string>&)> callback));
-
   MOCK_METHOD4(WaitUntilElementIsStable,
-               void(const ElementFinder::Result& element,
-                    int,
+               void(int,
                     base::TimeDelta,
+                    const ElementFinder::Result& element,
                     base::OnceCallback<void(const ClientStatus&,
                                             base::TimeDelta)> callback));
 
@@ -102,29 +113,25 @@
                     const TopPadding& top_padding,
                     base::OnceCallback<void(const ClientStatus&)>& callback));
 
-  void GetFieldValue(
-      const ElementFinder::Result& element,
-      base::OnceCallback<void(const ClientStatus&, const std::string&)>
-          callback) override {
-    OnGetFieldValue(element, callback);
-  }
-  MOCK_METHOD2(OnGetFieldValue,
+  MOCK_METHOD2(GetFieldValue,
                void(const ElementFinder::Result& element,
                     base::OnceCallback<void(const ClientStatus&,
-                                            const std::string&)>& callback));
+                                            const std::string&)> callback));
 
-  void GetStringAttribute(
-      const ElementFinder::Result& element,
-      const std::vector<std::string>& attributes,
-      base::OnceCallback<void(const ClientStatus&, const std::string&)>
-          callback) override {
-    OnGetStringAttribute(element, attributes, callback);
-  }
-  MOCK_METHOD3(OnGetStringAttribute,
-               void(const ElementFinder::Result& element,
-                    const std::vector<std::string>& attributes,
-                    base::OnceCallback<void(const ClientStatus&,
-                                            const std::string&)>& callback));
+  MOCK_METHOD3(
+      GetStringAttribute,
+      void(const std::vector<std::string>&,
+           const ElementFinder::Result&,
+           base::OnceCallback<void(const ClientStatus&, const std::string&)>));
+  MOCK_METHOD3(SetValueAttribute,
+               void(const std::string& value,
+                    const ElementFinder::Result& element,
+                    base::OnceCallback<void(const ClientStatus&)> callback));
+  MOCK_METHOD4(SetAttribute,
+               void(const std::vector<std::string>&,
+                    const std::string&,
+                    const ElementFinder::Result&,
+                    base::OnceCallback<void(const ClientStatus&)>));
 
   void GetVisualViewport(
       base::OnceCallback<void(const ClientStatus&, const RectF&)> callback)
diff --git a/components/autofill_assistant/browser/web/web_controller.cc b/components/autofill_assistant/browser/web/web_controller.cc
index dbb65b6..2c336e37f 100644
--- a/components/autofill_assistant/browser/web/web_controller.cc
+++ b/components/autofill_assistant/browser/web/web_controller.cc
@@ -445,9 +445,9 @@
 }
 
 void WebController::WaitUntilElementIsStable(
-    const ElementFinder::Result& element,
     int max_rounds,
     base::TimeDelta check_interval,
+    const ElementFinder::Result& element,
     base::OnceCallback<void(const ClientStatus&, base::TimeDelta)> callback) {
   std::unique_ptr<ElementPositionGetter> getter =
       std::make_unique<ElementPositionGetter>(devtools_client_.get(),
@@ -929,10 +929,10 @@
 }
 
 void WebController::SelectOption(
-    const ElementFinder::Result& element,
     const std::string& re2,
     bool case_sensitive,
     SelectOptionProto::OptionComparisonAttribute option_comparison_attribute,
+    const ElementFinder::Result& element,
     base::OnceCallback<void(const ClientStatus&)> callback) {
 #ifdef NDEBUG
   VLOG(3) << __func__ << " re2=(redacted)"
@@ -1068,8 +1068,8 @@
 }
 
 void WebController::GetStringAttribute(
-    const ElementFinder::Result& element,
     const std::vector<std::string>& attributes,
+    const ElementFinder::Result& element,
     base::OnceCallback<void(const ClientStatus&, const std::string&)>
         callback) {
   VLOG(3) << __func__ << " attributes=[" << base::JoinString(attributes, ",")
@@ -1122,8 +1122,8 @@
 }
 
 void WebController::SetValueAttribute(
-    const ElementFinder::Result& element,
     const std::string& value,
+    const ElementFinder::Result& element,
     base::OnceCallback<void(const ClientStatus&)> callback) {
   std::vector<std::unique_ptr<runtime::CallArgument>> argument;
   AddRuntimeCallArgument(value, &argument);
@@ -1142,9 +1142,9 @@
 }
 
 void WebController::SetAttribute(
-    const ElementFinder::Result& element,
     const std::vector<std::string>& attributes,
     const std::string& value,
+    const ElementFinder::Result& element,
     base::OnceCallback<void(const ClientStatus&)> callback) {
   DVLOG(3) << __func__ << " attributes=[" << base::JoinString(attributes, ",")
            << "], value=" << value;
@@ -1183,14 +1183,14 @@
     const std::string& value,
     const ElementFinder::Result& element,
     base::OnceCallback<void(const ClientStatus&)> callback) {
-  SendKeyboardInput(element, UTF8ToUnicode(value),
-                    key_press_delay_in_millisecond, std::move(callback));
+  SendKeyboardInput(UTF8ToUnicode(value), key_press_delay_in_millisecond,
+                    element, std::move(callback));
 }
 
 void WebController::SendKeyboardInput(
-    const ElementFinder::Result& element,
     const std::vector<UChar32>& codepoints,
     const int key_press_delay_in_millisecond,
+    const ElementFinder::Result& element,
     base::OnceCallback<void(const ClientStatus&)> callback) {
   auto worker =
       std::make_unique<SendKeyboardInputWorker>(devtools_client_.get());
diff --git a/components/autofill_assistant/browser/web/web_controller.h b/components/autofill_assistant/browser/web/web_controller.h
index c336b0c6..218ef38 100644
--- a/components/autofill_assistant/browser/web/web_controller.h
+++ b/components/autofill_assistant/browser/web/web_controller.h
@@ -103,9 +103,9 @@
   // Get a stable position of the given element. Fail with ELEMENT_UNSTABLE if
   // the element position doesn't stabilize quickly enough.
   virtual void WaitUntilElementIsStable(
-      const ElementFinder::Result& element,
       int max_rounds,
       base::TimeDelta check_interval,
+      const ElementFinder::Result& element,
       base::OnceCallback<void(const ClientStatus&, base::TimeDelta)> callback);
 
   // Check whether the center given element is on top. Fail with
@@ -140,10 +140,10 @@
 
   // Select the option to be picked given by the |re2| in the |element|.
   virtual void SelectOption(
-      const ElementFinder::Result& element,
       const std::string& re2,
       bool case_sensitive,
       SelectOptionProto::OptionComparisonAttribute option_comparison_attribute,
+      const ElementFinder::Result& element,
       base::OnceCallback<void(const ClientStatus&)> callback);
 
   // Highlight an |element|.
@@ -175,23 +175,23 @@
   // result through |callback|. If the lookup fails, the value will be empty.
   // An empty result does not mean an error.
   virtual void GetStringAttribute(
-      const ElementFinder::Result& element,
       const std::vector<std::string>& attributes,
+      const ElementFinder::Result& element,
       base::OnceCallback<void(const ClientStatus&, const std::string&)>
           callback);
 
   // Set the value attribute of an |element| to the specified |value| and
   // trigger an onchange event.
   virtual void SetValueAttribute(
-      const ElementFinder::Result& element,
       const std::string& value,
+      const ElementFinder::Result& element,
       base::OnceCallback<void(const ClientStatus&)> callback);
 
   // Set the nested |attributes| of an |element| to the specified |value|.
   virtual void SetAttribute(
-      const ElementFinder::Result& element,
       const std::vector<std::string>& attributes,
       const std::string& value,
+      const ElementFinder::Result& element,
       base::OnceCallback<void(const ClientStatus&)> callback);
 
   // Select the current value in a text |element|.
@@ -209,9 +209,9 @@
   // |key_press_delay_in_millisecond| between them. Returns the result through
   // |callback|.
   virtual void SendKeyboardInput(
-      const ElementFinder::Result& element,
       const std::vector<UChar32>& codepoints,
       int key_press_delay_in_millisecond,
+      const ElementFinder::Result& element,
       base::OnceCallback<void(const ClientStatus&)> callback);
 
   // Inputs the specified |value| into |element| with keystrokes per character.
diff --git a/components/autofill_assistant/browser/web/web_controller_browsertest.cc b/components/autofill_assistant/browser/web/web_controller_browsertest.cc
index cb91a4c..abb349d 100644
--- a/components/autofill_assistant/browser/web/web_controller_browsertest.cc
+++ b/components/autofill_assistant/browser/web/web_controller_browsertest.cc
@@ -347,7 +347,7 @@
     ASSERT_TRUE(element_result != nullptr);
     const ElementFinder::Result* element_result_ptr = element_result.get();
     web_controller_->SelectOption(
-        *element_result_ptr, re2, case_sensitive, option_comparison_attribute,
+        re2, case_sensitive, option_comparison_attribute, *element_result_ptr,
         base::BindOnce(&WebControllerBrowserTest::ElementRetainingCallback,
                        base::Unretained(this), std::move(element_result),
                        std::move(done_callback), result_output));
@@ -564,7 +564,7 @@
     ClientStatus captured_status;
     base::RunLoop run_loop;
     web_controller_->WaitUntilElementIsStable(
-        element, max_rounds, check_interval,
+        max_rounds, check_interval, element,
         base::BindLambdaForTesting(
             [&captured_status, &run_loop](const ClientStatus& status,
                                           base::TimeDelta) {
@@ -662,7 +662,7 @@
     ASSERT_TRUE(element_result != nullptr);
     const ElementFinder::Result* element_result_ptr = element_result.get();
     web_controller_->GetStringAttribute(
-        *element_result_ptr, attributes,
+        attributes, *element_result_ptr,
         base::BindOnce(
             &WebControllerBrowserTest::ElementRetainingStringCallback,
             base::Unretained(this), std::move(element_result),
@@ -765,17 +765,17 @@
       const ElementFinder::Result& element,
       base::OnceCallback<void(const ClientStatus&)> callback) {
     if (value.empty()) {
-      web_controller_->SetValueAttribute(element, value, std::move(callback));
+      web_controller_->SetValueAttribute(value, element, std::move(callback));
       return;
     }
 
     switch (fill_strategy) {
       case SET_VALUE:
-        web_controller_->SetValueAttribute(element, value, std::move(callback));
+        web_controller_->SetValueAttribute(value, element, std::move(callback));
         return;
       case SIMULATE_KEY_PRESSES:
         web_controller_->SetValueAttribute(
-            element, /* value= */ std::string(),
+            /* value= */ std::string(), element,
             base::BindOnce(
                 &WebControllerBrowserTest::OnSetValueAttributeForSetFieldValue,
                 base::Unretained(this), value, false, element,
@@ -790,7 +790,7 @@
         return;
       case SIMULATE_KEY_PRESSES_FOCUS:
         web_controller_->SetValueAttribute(
-            element, /* value= */ std::string(),
+            /* value= */ std::string(), element,
             base::BindOnce(
                 &WebControllerBrowserTest::OnSetValueAttributeForSetFieldValue,
                 base::Unretained(this), value, true, element,
@@ -824,8 +824,8 @@
       std::move(callback).Run(status);
       return;
     }
-    web_controller_->SendKeyboardInput(element, UTF8ToUnicode(value),
-                                       /* delay_in_milli= */ 0,
+    web_controller_->SendKeyboardInput(UTF8ToUnicode(value),
+                                       /* delay_in_milli= */ 0, element,
                                        std::move(callback));
   }
 
@@ -905,7 +905,7 @@
       return;
     }
 
-    web_controller_->SendKeyboardInput(element, codepoints, delay_in_milli,
+    web_controller_->SendKeyboardInput(codepoints, delay_in_milli, element,
                                        std::move(callback));
   }
 
@@ -942,7 +942,7 @@
     ASSERT_TRUE(element_result != nullptr);
     const ElementFinder::Result* element_result_ptr = element_result.get();
     web_controller_->SetAttribute(
-        *element_result_ptr, attributes, value,
+        attributes, value, *element_result_ptr,
         base::BindOnce(&WebControllerBrowserTest::ElementRetainingCallback,
                        base::Unretained(this), std::move(element_result),
                        std::move(done_callback), result_output));
@@ -2175,8 +2175,8 @@
   ClientStatus status;
   base::RunLoop run_loop;
   web_controller_->SendKeyboardInput(
-      bad_element, UTF8ToUnicode("never sent"),
-      /* key_press_delay_in_millisecond= */ 0,
+      UTF8ToUnicode("never sent"),
+      /* key_press_delay_in_millisecond= */ 0, bad_element,
       base::BindOnce(&WebControllerBrowserTest::OnClientStatus,
                      base::Unretained(this), run_loop.QuitClosure(), &status));
   run_loop.Run();
diff --git a/components/browsing_data/content/database_helper_browsertest.cc b/components/browsing_data/content/database_helper_browsertest.cc
index ae570d3..9a07641 100644
--- a/components/browsing_data/content/database_helper_browsertest.cc
+++ b/components/browsing_data/content/database_helper_browsertest.cc
@@ -4,9 +4,15 @@
 
 #include <stdint.h>
 
+#include <list>
+#include <string>
+#include <vector>
+
 #include "base/bind.h"
 #include "base/callback_helpers.h"
+#include "base/files/file_path.h"
 #include "base/files/file_util.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind.h"
@@ -19,6 +25,10 @@
 #include "content/public/test/content_browser_test.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
+#include "storage/browser/database/database_tracker.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "url/origin.h"
 
 using content::BrowserContext;
 using content::BrowserThread;
@@ -52,7 +62,7 @@
           std::u16string db_name = base::ASCIIToUTF16("db");
           std::u16string description = base::ASCIIToUTF16("db_description");
           int64_t size;
-          db_tracker->DatabaseOpened(kTestIdentifier1, db_name, description, 1,
+          db_tracker->DatabaseOpened(kTestIdentifier1, db_name, description,
                                      &size);
           db_tracker->DatabaseClosed(kTestIdentifier1, db_name);
           base::FilePath db_path1 =
@@ -60,7 +70,7 @@
           base::CreateDirectory(db_path1.DirName());
           ASSERT_EQ(0, base::WriteFile(db_path1, nullptr, 0));
           db_tracker->DatabaseOpened(kTestIdentifierExtension, db_name,
-                                     description, 1, &size);
+                                     description, &size);
           db_tracker->DatabaseClosed(kTestIdentifierExtension, db_name);
           base::FilePath db_path2 =
               db_tracker->GetFullDBFilePath(kTestIdentifierExtension, db_name);
diff --git a/components/download/internal/common/resource_downloader.cc b/components/download/internal/common/resource_downloader.cc
index 64b8adb7..20ebc60 100644
--- a/components/download/internal/common/resource_downloader.cc
+++ b/components/download/internal/common/resource_downloader.cc
@@ -179,7 +179,6 @@
   // Set up the URLLoader
   url_loader_factory_->CreateLoaderAndStart(
       url_loader_.BindNewPipeAndPassReceiver(),
-      0,  // routing_id
       0,  // request_id
       network::mojom::kURLLoadOptionSendSSLInfoWithResponse,
       *(resource_request_.get()), std::move(url_loader_client_remote),
diff --git a/components/feed/feed_feature_list.cc b/components/feed/feed_feature_list.cc
index d3c1ae7..1d6fdc5 100644
--- a/components/feed/feed_feature_list.cc
+++ b/components/feed/feed_feature_list.cc
@@ -33,9 +33,6 @@
     &kInterestFeedContentSuggestions,
     "only_set_last_refresh_attempt_on_success", true};
 
-const base::Feature kReportFeedUserActions{"ReportFeedUserActions",
-                                           base::FEATURE_DISABLED_BY_DEFAULT};
-
 const base::Feature kInterestFeedV1ClicksAndViewsConditionalUpload{
     "InterestFeedV1ClickAndViewActionsConditionalUpload",
     base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/feed/feed_feature_list.h b/components/feed/feed_feature_list.h
index f1b38fd..8eeb9618 100644
--- a/components/feed/feed_feature_list.h
+++ b/components/feed/feed_feature_list.h
@@ -24,10 +24,6 @@
 extern const base::FeatureParam<bool> kThrottleBackgroundFetches;
 extern const base::FeatureParam<bool> kOnlySetLastRefreshAttemptOnSuccess;
 
-// Indicates if user card clicks and views in Chrome's feed should be reported
-// for personalization. Also enables the feed header menu to manage the feed.
-extern const base::Feature kReportFeedUserActions;
-
 // Determines whether conditions should be reached before enabling the upload of
 // click and view actions in the feed (e.g., the user needs to view X cards).
 // For example, this is needed when the notice card is at the second position in
diff --git a/components/installedapp/android/java/src/org/chromium/components/installedapp/InstalledAppProviderImpl.java b/components/installedapp/android/java/src/org/chromium/components/installedapp/InstalledAppProviderImpl.java
index 62ee47be..306459e 100644
--- a/components/installedapp/android/java/src/org/chromium/components/installedapp/InstalledAppProviderImpl.java
+++ b/components/installedapp/android/java/src/org/chromium/components/installedapp/InstalledAppProviderImpl.java
@@ -9,7 +9,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.res.Resources;
-import android.util.Pair;
 
 import androidx.annotation.Nullable;
 import androidx.annotation.UiThread;
@@ -119,37 +118,36 @@
 
     /** Utility class for waiting for all the installation/verification results. */
     @UiThread
-    private static class ResultHolder {
+    private class ResultHolder {
         private int mNumTasks;
-        Callback mCallback;
+        private FilterInstalledAppsResponse mCallback;
         private ArrayList<RelatedApplication> mInstalledApps;
         private int mDelayMs;
 
         /**
          * @param numTasks How many results to wait for.
-         * @param callback Gets called with the results once all the tasks are complete.
+         * @param callback Will be passed on to {@link onFilteredInstalledApps()} to be invoked with
+         *         the results once all the tasks are complete.
          */
-        public ResultHolder(
-                int numTasks, Callback<Pair<ArrayList<RelatedApplication>, Integer>> callback) {
+        public ResultHolder(int numTasks, FilterInstalledAppsResponse callback) {
             mNumTasks = numTasks;
             mCallback = callback;
             mInstalledApps =
                     new ArrayList<RelatedApplication>(Collections.nCopies(mNumTasks, null));
-            mDelayMs = 0;
             if (mNumTasks == 0) {
-                mCallback.onResult(Pair.create(mInstalledApps, mDelayMs));
+                onFilteredInstalledApps(mInstalledApps, mDelayMs, mCallback);
             }
         }
 
         public void onResult(@Nullable RelatedApplication app, int taskIdx, int delayMs) {
             assert mNumTasks > 0;
 
-            if (app != null) mInstalledApps.add(taskIdx, app);
+            mInstalledApps.set(taskIdx, app);
             mDelayMs += delayMs;
 
             if (--mNumTasks == 0) {
                 mInstalledApps.removeAll(Collections.singleton(null));
-                mCallback.onResult(Pair.create(mInstalledApps, mDelayMs));
+                onFilteredInstalledApps(mInstalledApps, mDelayMs, mCallback);
             }
         }
     }
@@ -162,9 +160,7 @@
         final GURL frameUrl = url == null ? GURL.emptyGURL() : url;
         int delayMillis = 0;
         int numTasks = Math.min(relatedApps.length, MAX_ALLOWED_RELATED_APPS);
-        ResultHolder resultHolder = new ResultHolder(numTasks, (resultPair) -> {
-            onFilteredInstalledApps(resultPair.first, resultPair.second, callback);
-        });
+        ResultHolder resultHolder = new ResultHolder(numTasks, callback);
 
         // NOTE: For security, it must not be possible to distinguish (from the time taken to
         // respond) between the app not being installed and the origin not being associated with the
diff --git a/components/installedapp/android/java/src/org/chromium/components/installedapp/InstalledAppProviderTest.java b/components/installedapp/android/java/src/org/chromium/components/installedapp/InstalledAppProviderTest.java
index 80e7e8d3..3f04941 100644
--- a/components/installedapp/android/java/src/org/chromium/components/installedapp/InstalledAppProviderTest.java
+++ b/components/installedapp/android/java/src/org/chromium/components/installedapp/InstalledAppProviderTest.java
@@ -75,6 +75,8 @@
             "https://example.com:8000/path/to/page.html?key=value#fragment";
     private static final String MANIFEST_URL = "https://example.com:8000/manifest.json";
     private static final String OTHER_MANIFEST_URL = "https://example2.com:8000/manifest.json";
+    private static final String OTHER_MANIFEST_URL3 = "https://example3.com:8000/manifest.json";
+    private static final String OTHER_MANIFEST_URL4 = "https://example4.com:8000/manifest.json";
     private static final String ORIGIN_SYNTAX_ERROR = "https:{";
     private static final String ORIGIN_MISSING_SCHEME = "path/only";
     private static final String ORIGIN_MISSING_HOST = "file:///path/piece";
@@ -157,6 +159,7 @@
     private static class TestInstalledAppProviderImplJni
             implements InstalledAppProviderImpl.Natives {
         private final Map<String, String> mRelationMap = new HashMap<>();
+        private ArrayList<Pair<Callback<Boolean>, Boolean>> mCallbacks;
 
         public void addVerfication(String webDomain, String manifestUrl) {
             mRelationMap.put(webDomain, manifestUrl);
@@ -166,8 +169,29 @@
         public void checkDigitalAssetLinksRelationshipForWebApk(
                 BrowserContextHandle browserContextHandle, String webDomain, String manifestUrl,
                 Callback<Boolean> callback) {
-            callback.onResult(mRelationMap.containsKey(webDomain)
-                    && mRelationMap.get(webDomain).equals(manifestUrl));
+            boolean result = mRelationMap.containsKey(webDomain)
+                    && mRelationMap.get(webDomain).equals(manifestUrl);
+            if (mCallbacks == null) {
+                callback.onResult(result);
+                return;
+            }
+
+            mCallbacks.add(Pair.create(callback, result));
+            if (mCallbacks.size() == 3) {
+                Pair<Callback<Boolean>, Boolean> stashed = mCallbacks.get(1);
+                stashed.first.onResult(stashed.second);
+                stashed = mCallbacks.get(0);
+                stashed.first.onResult(stashed.second);
+                stashed = mCallbacks.get(2);
+                stashed.first.onResult(stashed.second);
+            }
+        }
+
+        // If called, the callbacks passed to {@link checkDigitalAssetLinksRelationshipForWebApk}
+        // won't be executed until it's been called three times, and then they'll be executed out of
+        // order.
+        void rearrangeOrderOfResults() {
+            mCallbacks = new ArrayList<>();
         }
     }
 
@@ -1011,4 +1035,27 @@
         mTestInstalledAppProviderImplJni.addVerfication(MANIFEST_URL, OTHER_MANIFEST_URL);
         verifyInstalledApps(manifestRelatedApps, new RelatedApplication[] {});
     }
+
+    /**
+     * Tests that the order of returned filtered apps matches the order of the apps passed to {@link
+     * filterInstalledApps}.
+     */
+    @Test
+    @SmallTest
+    @UiThreadTest
+    public void testOrderOfResults() throws Exception {
+        RelatedApplication manifestRelatedApps[] = new RelatedApplication[] {
+                createRelatedApplication(PLATFORM_WEBAPP, null, OTHER_MANIFEST_URL),
+                createRelatedApplication(PLATFORM_WEBAPP, null, OTHER_MANIFEST_URL3),
+                createRelatedApplication(PLATFORM_WEBAPP, null, OTHER_MANIFEST_URL4)};
+        mFakePackageManager.addWebApk(OTHER_MANIFEST_URL);
+        mFakePackageManager.addWebApk(OTHER_MANIFEST_URL3);
+        mFakePackageManager.addWebApk(OTHER_MANIFEST_URL4);
+        mTestInstalledAppProviderImplJni.addVerfication(OTHER_MANIFEST_URL, MANIFEST_URL);
+        mTestInstalledAppProviderImplJni.addVerfication(OTHER_MANIFEST_URL3, MANIFEST_URL);
+        mTestInstalledAppProviderImplJni.addVerfication(OTHER_MANIFEST_URL4, MANIFEST_URL);
+
+        mTestInstalledAppProviderImplJni.rearrangeOrderOfResults();
+        verifyInstalledApps(manifestRelatedApps, manifestRelatedApps);
+    }
 }
diff --git a/components/memories/content/BUILD.gn b/components/memories/content/BUILD.gn
deleted file mode 100644
index f9373eb..0000000
--- a/components/memories/content/BUILD.gn
+++ /dev/null
@@ -1,16 +0,0 @@
-# Copyright 2021 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("content") {
-  sources = [
-    "memories_service_factory.cc",
-    "memories_service_factory.h",
-  ]
-
-  public_deps = [
-    "//base",
-    "//components/keyed_service/content",
-    "//components/memories/core",
-  ]
-}
diff --git a/components/memories/content/DEPS b/components/memories/content/DEPS
deleted file mode 100644
index 98a0a0d..0000000
--- a/components/memories/content/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-  "+components/keyed_service/content",
-]
diff --git a/components/memories/content/memories_service_factory.cc b/components/memories/content/memories_service_factory.cc
deleted file mode 100644
index b70c437..0000000
--- a/components/memories/content/memories_service_factory.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2021 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/memories/content/memories_service_factory.h"
-
-#include "components/keyed_service/content/browser_context_dependency_manager.h"
-#include "components/memories/core/memories_service.h"
-
-// static
-memories::MemoriesService* MemoriesServiceFactory::GetForBrowserContext(
-    content::BrowserContext* browser_context) {
-  return static_cast<memories::MemoriesService*>(
-      GetInstance().GetServiceForBrowserContext(browser_context, true));
-}
-
-// static
-MemoriesServiceFactory& MemoriesServiceFactory::GetInstance() {
-  static base::NoDestructor<MemoriesServiceFactory> instance;
-  return *instance;
-}
-
-MemoriesServiceFactory::MemoriesServiceFactory()
-    : BrowserContextKeyedServiceFactory(
-          "MemoriesService",
-          BrowserContextDependencyManager::GetInstance()) {}
-
-MemoriesServiceFactory::~MemoriesServiceFactory() = default;
-
-KeyedService* MemoriesServiceFactory::BuildServiceInstanceFor(
-    content::BrowserContext* context) const {
-  return new memories::MemoriesService();
-}
-
-content::BrowserContext* MemoriesServiceFactory::GetBrowserContextToUse(
-    content::BrowserContext* context) const {
-  // Give incognito its own isolated service.
-  return context;
-}
diff --git a/components/memories/core/BUILD.gn b/components/memories/core/BUILD.gn
index 8a888757..97634d4e 100644
--- a/components/memories/core/BUILD.gn
+++ b/components/memories/core/BUILD.gn
@@ -8,6 +8,8 @@
   sources = [
     "memories_features.cc",
     "memories_features.h",
+    "memories_remote_model_helper.cc",
+    "memories_remote_model_helper.h",
     "memories_service.cc",
     "memories_service.h",
     "visit_data.h",
@@ -15,7 +17,10 @@
   deps = [
     ":mojo_bindings",
     "//base",
+    "//components/history/core/browser",
     "//components/keyed_service/core",
+    "//services/data_decoder/public/cpp",
+    "//services/network/public/cpp",
     "//url",
   ]
 }
@@ -28,3 +33,15 @@
     "//url/mojom:url_mojom_gurl",
   ]
 }
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [ "memories_service_unittest.cc" ]
+  deps = [
+    ":core",
+    "//base/test:test_support",
+    "//services/data_decoder/public/cpp:test_support",
+    "//services/network:test_support",
+    "//testing/gtest",
+  ]
+}
diff --git a/components/memories/core/DEPS b/components/memories/core/DEPS
index f0bf3d9..654cc9f4a 100644
--- a/components/memories/core/DEPS
+++ b/components/memories/core/DEPS
@@ -1,3 +1,7 @@
 include_rules = [
+  "+components/history/core",
   "+components/keyed_service/core",
+  "+services/data_decoder/public/cpp",
+  "+services/network/public/cpp",
+  "+services/network/test",
 ]
diff --git a/components/memories/core/memories_features.cc b/components/memories/core/memories_features.cc
index 476ec2a..e0cd9baa 100644
--- a/components/memories/core/memories_features.cc
+++ b/components/memories/core/memories_features.cc
@@ -10,6 +10,7 @@
 
 // Enables the Chrome Memories history clustering feature.
 const base::Feature kMemories{"Memories", base::FEATURE_DISABLED_BY_DEFAULT};
+const char kMemoriesRemoteModelEndpointParam[] = "MemoriesRemoteModelEndpoint";
 
 // Enables debug info; e.g. shows visit metadata on chrome://history entries.
 const base::Feature kDebug{"MemoriesDebug", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/memories/core/memories_features.h b/components/memories/core/memories_features.h
index 5375a56..edcb7fb 100644
--- a/components/memories/core/memories_features.h
+++ b/components/memories/core/memories_features.h
@@ -10,6 +10,10 @@
 namespace memories {
 
 extern const base::Feature kMemories;
+// The remote model endpoint used to cluster visits into memories.
+extern const char kMemoriesRemoteModelEndpointParam[];
+
+// Enables debug features; e.g. displaying typed_count on chrome://history.
 extern const base::Feature kDebug;
 
 }  // namespace memories
diff --git a/components/memories/core/memories_remote_model_helper.cc b/components/memories/core/memories_remote_model_helper.cc
new file mode 100644
index 0000000..9dcdefc3
--- /dev/null
+++ b/components/memories/core/memories_remote_model_helper.cc
@@ -0,0 +1,185 @@
+// Copyright 2021 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/memories/core/memories_remote_model_helper.h"
+
+#include <algorithm>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/json/json_writer.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/optional.h"
+#include "base/values.h"
+#include "components/memories/core/memories_features.h"
+#include "services/data_decoder/public/cpp/data_decoder.h"
+
+namespace {
+
+const size_t kMaxExpectedResponseSize = 1024 * 1024;
+
+// Helpers to translate from |MemoriesVisit|s to |base::Value|; and from
+// |base::Value| to |mojom::MemoryPtr|s.
+
+base::Value VisitToValue(const memories::MemoriesVisit& visit) {
+  base::Value dict(base::Value::Type::DICTIONARY);
+  dict.SetKey("visitId", base::Value(0));
+  dict.SetKey("url", base::Value(visit.url.spec()));
+  dict.SetKey("origin", base::Value(""));
+  dict.SetKey("foreground_time_secs", base::Value(0));
+  dict.SetKey("navigation_time_ms", base::Value(0));
+  dict.SetKey("site_engagement_score", base::Value(0));
+  dict.SetKey("page_end_reason",
+              base::Value(visit.context_signals.page_end_reason));
+  dict.SetKey("page_transition", base::Value(0));
+  dict.SetKey("is_from_google_search", base::Value(false));
+  // TODO(manukh): Form a proper request by joining |visit| with local tables.
+  return dict;
+}
+
+base::Value VisitsToValue(const std::vector<memories::MemoriesVisit>& visits) {
+  base::Value visits_list(base::Value::Type::LIST);
+  for (const auto& visit : visits)
+    visits_list.Append(VisitToValue(visit));
+
+  base::Value dict(base::Value::Type::DICTIONARY);
+  dict.SetKey("visits", std::move(visits_list));
+  return dict;
+}
+
+// A helper method to get the values of the |base::ListValue| at |value[key]|.
+template <typename T>
+std::vector<T> FindListKeyAndCast(
+    const base::Value& value,
+    std::string key,
+    base::RepeatingCallback<T(const base::Value&)> cast_callback) {
+  const base::Value* list_ptr = value.FindListKey(key);
+  if (!list_ptr)
+    return {};
+
+  base::Value::ConstListView list = list_ptr->GetList();
+  std::vector<T> casted(list.size());
+
+  std::transform(
+      list.begin(), list.end(), casted.begin(),
+      [&](const base::Value& value) { return cast_callback.Run(value); });
+  return casted;
+}
+
+memories::mojom::MemoryPtr ValueToMemory(const base::Value& value) {
+  // TODO(manukh): Form a proper response by joining value with local tables.
+
+  return memories::mojom::Memory::New();
+}
+
+memories::Memories ValueToMemories(const base::Value& value) {
+  return FindListKeyAndCast<memories::mojom::MemoryPtr>(
+      value, "memories", base::BindRepeating(&ValueToMemory));
+}
+
+}  // namespace
+
+namespace memories {
+
+MemoriesRemoteModelHelper::MemoriesRemoteModelHelper(
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+    : url_loader_(nullptr), url_loader_factory_(url_loader_factory) {}
+
+MemoriesRemoteModelHelper::~MemoriesRemoteModelHelper() = default;
+
+void MemoriesRemoteModelHelper::GetMemories(
+    const std::vector<MemoriesVisit>& visits,
+    MemoriesCallback callback) {
+  const GURL endpoint(base::GetFieldTrialParamValueByFeature(
+      kMemories, kMemoriesRemoteModelEndpointParam));
+  if (!endpoint.is_valid()) {
+    std::move(callback).Run({});
+    return;
+  }
+  StopPendingRequests();
+
+  std::string request_body;
+  base::JSONWriter::Write(VisitsToValue(visits), &request_body);
+  auto request = CreateRequest(endpoint);
+  url_loader_ = CreateLoader(CreateRequest(endpoint), request_body);
+
+  url_loader_->DownloadToString(
+      url_loader_factory_.get(),
+      base::BindOnce(
+          [](MemoriesCallback callback, std::unique_ptr<std::string> response) {
+            if (!response) {
+              std::move(callback).Run({});
+              return;
+            }
+            data_decoder::DataDecoder::ParseJsonIsolated(
+                *response,
+                base::BindOnce([](data_decoder::DataDecoder::ValueOrError
+                                      value_or_error) -> Memories {
+                  return value_or_error.value
+                             ? ValueToMemories(value_or_error.value.value())
+                             : Memories{};
+                }).Then(std::move(callback)));
+          },
+          std::move(callback)),
+      kMaxExpectedResponseSize);
+}
+
+void MemoriesRemoteModelHelper::StopPendingRequests() {
+  url_loader_.reset();
+}
+
+// static
+std::unique_ptr<network::ResourceRequest>
+MemoriesRemoteModelHelper::CreateRequest(const GURL& endpoint) {
+  auto request = std::make_unique<network::ResourceRequest>();
+  request->url = GURL(endpoint);
+  request->method = "POST";
+  return request;
+}
+
+// static
+std::unique_ptr<network::SimpleURLLoader>
+MemoriesRemoteModelHelper::CreateLoader(
+    std::unique_ptr<network::ResourceRequest> request,
+    const std::string& request_body) {
+  const net::NetworkTrafficAnnotationTag traffic_annotation =
+      net::DefineNetworkTrafficAnnotation("memories_remote_model_request", R"(
+        semantics {
+          sender: "Memories"
+          description:
+            "chrome://memories clusters the user's history entries into "
+            "'memories' for easier browsing and searching. This request is "
+            "made only if the user explicitly sets the appropriate feature and "
+            "param through the command line. The param is intentionally not in "
+            "chrome://flags to avoid users accidentally setting it. The "
+            "request will send the user's previous navigations and searches. "
+          trigger: "User must set a command line param. The request is sent "
+            "for both explicit user actions (e.g. navigating, visiting "
+            "chrome://memories, or typing in the omnibox) and passively (e.g. "
+            " on browser startup or periodically)."
+          data: "The user's navigation and search history."
+          destination: OTHER
+          destination_other: "With the expected param configuration, the "
+            "destination will be a GOOGLE_OWNED_SERVICE. As the endpoint is "
+            "set through a command line param, a user could set it to any "
+            "destination."
+        }
+        policy {
+          cookies_allowed: YES
+          cookies_store: "user"
+          setting:
+            "Disabled unless the user explicitly enables the 'Memories' "
+            "feature and sets the 'MemoriesRemoteModelEndpoint' param to a "
+            "valid URL."
+          policy_exception_justification:
+            "The request is only made if the user explicitly configures it."
+        })");
+  std::unique_ptr<network::SimpleURLLoader> loader =
+      network::SimpleURLLoader::Create(std::move(request), traffic_annotation);
+  if (!request_body.empty())
+    loader->AttachStringForUpload(request_body, "application/json");
+  return loader;
+}
+
+}  // namespace memories
diff --git a/components/memories/core/memories_remote_model_helper.h b/components/memories/core/memories_remote_model_helper.h
new file mode 100644
index 0000000..b27b3ad
--- /dev/null
+++ b/components/memories/core/memories_remote_model_helper.h
@@ -0,0 +1,59 @@
+// Copyright 2021 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_MEMORIES_CORE_MEMORIES_REMOTE_MODEL_HELPER_H_
+#define COMPONENTS_MEMORIES_CORE_MEMORIES_REMOTE_MODEL_HELPER_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/scoped_refptr.h"
+#include "components/memories/core/memories.mojom.h"
+#include "components/memories/core/visit_data.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "services/network/public/cpp/simple_url_loader.h"
+#include "url/gurl.h"
+
+namespace memories {
+
+using Memories = std::vector<mojom::MemoryPtr>;
+using MemoriesCallback = base::OnceCallback<void(Memories)>;
+
+// A helper class to communicate with the remote model. Forms requests from
+// |MemoriesVisit|s and parses the response into |mojom::MemoryPtr|s.
+class MemoriesRemoteModelHelper {
+ public:
+  explicit MemoriesRemoteModelHelper(
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+  ~MemoriesRemoteModelHelper();
+
+  // POSTs |visits| to |endpoint_| and invokes |callback| with the retrieved
+  // |MemoryPtr|s.
+  void GetMemories(const std::vector<MemoriesVisit>& visits,
+                   MemoriesCallback callback);
+
+ private:
+  // Stops pending requests. Invoking |GetMemories| multiple times will stop
+  // incomplete previous requests.
+  void StopPendingRequests();
+
+  // Helpers for making requests used by |GetMemories()|.
+  static std::unique_ptr<network::ResourceRequest> CreateRequest(
+      const GURL& endpoint);
+  static std::unique_ptr<network::SimpleURLLoader> CreateLoader(
+      std::unique_ptr<network::ResourceRequest> request,
+      const std::string& request_body);
+
+  // The most recent request.
+  std::unique_ptr<network::SimpleURLLoader> url_loader_;
+  // Used to make requests.
+  const scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
+};
+
+}  // namespace memories
+
+#endif  // COMPONENTS_MEMORIES_CORE_MEMORIES_REMOTE_MODEL_HELPER_H_
diff --git a/components/memories/core/memories_service.cc b/components/memories/core/memories_service.cc
index 9226e72..da2544b 100644
--- a/components/memories/core/memories_service.cc
+++ b/components/memories/core/memories_service.cc
@@ -2,13 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "components/memories/core/memories_service.h"
+#include <utility>
+
 #include "base/feature_list.h"
 #include "components/memories/core/memories_features.h"
+#include "components/memories/core/memories_service.h"
 
 namespace memories {
 
-MemoriesService::MemoriesService() = default;
+MemoriesService::MemoriesService(
+    history::HistoryService* history_service,
+    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
+    : remote_model_helper_(
+          std::make_unique<memories::MemoriesRemoteModelHelper>(
+              url_loader_factory)) {}
 
 MemoriesService::~MemoriesService() = default;
 
@@ -17,7 +24,7 @@
 void MemoriesService::AddVisit(const GURL& url,
                                const base::Time& time,
                                const VisitContextSignals& context_signals) {
-  if (!base::FeatureList::IsEnabled(memories::kMemories))
+  if (!base::FeatureList::IsEnabled(kMemories))
     return;
 
   MemoriesVisit visit;
@@ -33,4 +40,8 @@
   // TODO(tommycli/manukh): Persist to History, and take out of in-memory.
 }
 
+void MemoriesService::GetMemories(MemoriesCallback callback) {
+  remote_model_helper_->GetMemories(visits_, std::move(callback));
+}
+
 }  // namespace memories
diff --git a/components/memories/core/memories_service.h b/components/memories/core/memories_service.h
index 0aba7f4..299b529e 100644
--- a/components/memories/core/memories_service.h
+++ b/components/memories/core/memories_service.h
@@ -5,18 +5,27 @@
 #ifndef COMPONENTS_MEMORIES_CORE_MEMORIES_SERVICE_H_
 #define COMPONENTS_MEMORIES_CORE_MEMORIES_SERVICE_H_
 
+#include <memory>
 #include <vector>
 
 #include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/time/time.h"
+#include "components/history/core/browser/history_service.h"
 #include "components/keyed_service/core/keyed_service.h"
+#include "components/memories/core/memories_remote_model_helper.h"
 #include "components/memories/core/visit_data.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "url/gurl.h"
 
 namespace memories {
 
 // This Service is the API for UIs to fetch Chrome Memories.
 class MemoriesService : public KeyedService {
  public:
-  MemoriesService();
+  explicit MemoriesService(
+      history::HistoryService* history_service,
+      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
   ~MemoriesService() override;
 
   // KeyedService:
@@ -28,12 +37,20 @@
                 const base::Time& time,
                 const VisitContextSignals& context_signals);
 
+  // Asks |remote_model_helper_| to construct memories from |visits_|.
+  void GetMemories(MemoriesCallback callback);
+
  private:
   // If the Memories flag is enabled, this contains all the visits in-memory
   // during the Profile lifetime.
   // TODO(tommycli): Hide this better behind a new debug flag.
   std::vector<MemoriesVisit> visits_;
 
+  // Helper service to handle communicating with the remote model. This will be
+  // used for debugging only; the launch ready feature will use a local model
+  // instead.
+  std::unique_ptr<MemoriesRemoteModelHelper> remote_model_helper_;
+
   DISALLOW_COPY_AND_ASSIGN(MemoriesService);
 };
 
diff --git a/components/memories/core/memories_service_unittest.cc b/components/memories/core/memories_service_unittest.cc
new file mode 100644
index 0000000..a9e7b27
--- /dev/null
+++ b/components/memories/core/memories_service_unittest.cc
@@ -0,0 +1,245 @@
+// Copyright 2021 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/memories/core/memories_service.h"
+
+#include "base/bind.h"
+#include "base/callback_forward.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
+#include "base/test/bind.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/task_environment.h"
+#include "components/memories/core/memories_features.h"
+#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
+#include "services/network/public/cpp/data_element.h"
+#include "services/network/public/cpp/resource_request_body.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace {
+
+class MemoriesServiceTest : public testing::Test {
+ public:
+  MemoriesServiceTest()
+      : shared_url_loader_factory_(
+            base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
+                &test_url_loader_factory_)),
+        memories_service_(std::make_unique<memories::MemoriesService>(
+            nullptr,
+            shared_url_loader_factory_)),
+        task_environment_(base::test::TaskEnvironment::MainThreadType::UI),
+        run_loop_quit_(run_loop_.QuitClosure()) {}
+
+  MemoriesServiceTest(const MemoriesServiceTest&) = delete;
+  MemoriesServiceTest& operator=(const MemoriesServiceTest&) = delete;
+
+  // Helper to get the most recent remote request body.
+  std::string GetPendingRequestBody() {
+    const scoped_refptr<network::ResourceRequestBody>& request_body =
+        test_url_loader_factory_.GetPendingRequest(0)->request.request_body;
+    const network::DataElement& element = (*request_body->elements())[0];
+    return std::string(element.As<network::DataElementBytes>().AsStringPiece());
+  }
+
+  network::TestURLLoaderFactory test_url_loader_factory_;
+  scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
+  std::unique_ptr<memories::MemoriesService> memories_service_;
+
+  // Used to allow decoding in tests without spinning up an isolated process.
+  base::test::TaskEnvironment task_environment_;
+  data_decoder::test::InProcessDataDecoder in_process_data_decoder_;
+
+  // Used to verify the async callback is invoked.
+  base::RunLoop run_loop_;
+  base::RepeatingClosure run_loop_quit_;
+};
+
+TEST_F(MemoriesServiceTest, GetMemories) {
+  const char endpoint[] = "https://endpoint.com/";
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeatureWithParameters(
+      memories::kMemories,
+      {{memories::kMemoriesRemoteModelEndpointParam, endpoint}});
+
+  memories_service_->AddVisit(GURL{"google.com"}, {}, {});
+  memories_service_->AddVisit(GURL{"github.com"}, {}, {});
+
+  EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
+  memories_service_->GetMemories(
+      base::BindLambdaForTesting([&](memories::Memories memories) {
+        // Verify the parsed response.
+        EXPECT_EQ(memories.size(), 2u);
+        run_loop_quit_.Run();
+      }));
+
+  // Verify a request is made.
+  EXPECT_TRUE(test_url_loader_factory_.IsPending(endpoint));
+  EXPECT_EQ(
+      GetPendingRequestBody(),
+      R"({"visits":[{"foreground_time_secs":0,"is_from_google_search":false,)"
+      R"("navigation_time_ms":0,"origin":"","page_end_reason":0,)"
+      R"("page_transition":0,"site_engagement_score":0,"url":"","visitId":0},)"
+      R"({"foreground_time_secs":0,"is_from_google_search":false,)"
+      R"("navigation_time_ms":0,"origin":"","page_end_reason":0,)"
+      R"("page_transition":0,"site_engagement_score":0,"url":"",)"
+      R"("visitId":0}]})");
+
+  // Fake a response from the endpoint.
+  test_url_loader_factory_.AddResponse(endpoint, R"({"memories": [{}, {}]})");
+  EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
+
+  // Verify the callback is invoked.
+  run_loop_.Run();
+}
+
+TEST_F(MemoriesServiceTest, GetMemoriesWithEmptyEndpoint) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeatureWithParameters(
+      memories::kMemories, {{memories::kMemoriesRemoteModelEndpointParam, ""}});
+
+  memories_service_->AddVisit(GURL{"google.com"}, {}, {});
+  memories_service_->AddVisit(GURL{"github.com"}, {}, {});
+
+  memories_service_->GetMemories(
+      base::BindLambdaForTesting([&](memories::Memories memories) {
+        // Verify the parsed response.
+        EXPECT_EQ(memories.size(), 0u);
+        run_loop_quit_.Run();
+      }));
+
+  // Verify no request is made.
+  EXPECT_EQ(test_url_loader_factory_.NumPending(), 0);
+
+  // Verify the callback is invoked.
+  run_loop_.Run();
+}
+
+TEST_F(MemoriesServiceTest, GetMemoriesWithEmptyResponse) {
+  const char endpoint[] = "https://endpoint.com/";
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeatureWithParameters(
+      memories::kMemories,
+      {{memories::kMemoriesRemoteModelEndpointParam, endpoint}});
+
+  memories_service_->AddVisit(GURL{"google.com"}, {}, {});
+  memories_service_->AddVisit(GURL{"github.com"}, {}, {});
+
+  EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
+  memories_service_->GetMemories(
+      base::BindLambdaForTesting([&](memories::Memories memories) {
+        // Verify the parsed response.
+        EXPECT_EQ(memories.size(), 0u);
+        run_loop_quit_.Run();
+      }));
+
+  // Verify a request is made.
+  EXPECT_TRUE(test_url_loader_factory_.IsPending(endpoint));
+
+  // Fake a response from the endpoint.
+  test_url_loader_factory_.AddResponse(endpoint, "");
+  EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
+
+  // Verify the callback is invoked.
+  run_loop_.Run();
+}
+
+TEST_F(MemoriesServiceTest, GetMemoriesWithInvalidJsonResponse) {
+  const char endpoint[] = "https://endpoint.com/";
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeatureWithParameters(
+      memories::kMemories,
+      {{memories::kMemoriesRemoteModelEndpointParam, endpoint}});
+
+  memories_service_->AddVisit(GURL{"google.com"}, {}, {});
+  memories_service_->AddVisit(GURL{"github.com"}, {}, {});
+
+  EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
+  memories_service_->GetMemories(
+      base::BindLambdaForTesting([&](memories::Memories memories) {
+        // Verify the parsed response.
+        EXPECT_EQ(memories.size(), 0u);
+        run_loop_quit_.Run();
+      }));
+
+  // Verify a request is made.
+  EXPECT_TRUE(test_url_loader_factory_.IsPending(endpoint));
+
+  // Fake a response from the endpoint.
+  test_url_loader_factory_.AddResponse(endpoint, "{waka404woko.weke) !*(&,");
+  EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
+
+  // Verify the callback is invoked.
+  run_loop_.Run();
+}
+
+TEST_F(MemoriesServiceTest, GetMemoriesWithBadResponse) {
+  const char endpoint[] = "https://endpoint.com/";
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeatureWithParameters(
+      memories::kMemories,
+      {{memories::kMemoriesRemoteModelEndpointParam, endpoint}});
+
+  memories_service_->AddVisit(GURL{"google.com"}, {}, {});
+  memories_service_->AddVisit(GURL{"github.com"}, {}, {});
+
+  EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
+  memories_service_->GetMemories(
+      base::BindLambdaForTesting([&](memories::Memories memories) {
+        // Verify the parsed response.
+        EXPECT_EQ(memories.size(), 0u);
+        run_loop_quit_.Run();
+      }));
+
+  // Verify a request is made.
+  EXPECT_TRUE(test_url_loader_factory_.IsPending(endpoint));
+
+  // Fake a response from the endpoint.
+  test_url_loader_factory_.AddResponse(endpoint, "{}");
+  EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
+
+  // Verify the callback is invoked.
+  run_loop_.Run();
+}
+
+TEST_F(MemoriesServiceTest, GetMemoriesWithPendingRequest) {
+  const char endpoint[] = "https://endpoint.com/";
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeatureWithParameters(
+      memories::kMemories,
+      {{memories::kMemoriesRemoteModelEndpointParam, endpoint}});
+
+  memories_service_->AddVisit(GURL{"google.com"}, {}, {});
+  memories_service_->AddVisit(GURL{"github.com"}, {}, {});
+
+  EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
+  memories_service_->GetMemories(
+      base::BindLambdaForTesting([&](memories::Memories memories) {
+        // Verify not reached.
+        EXPECT_TRUE(false);
+      }));
+
+  EXPECT_TRUE(test_url_loader_factory_.IsPending(endpoint));
+  memories_service_->GetMemories(
+      base::BindLambdaForTesting([&](memories::Memories memories) {
+        // Verify the parsed response.
+        EXPECT_EQ(memories.size(), 2u);
+        run_loop_quit_.Run();
+      }));
+
+  // Verify there's a single request to the endpoint.
+  EXPECT_TRUE(test_url_loader_factory_.IsPending(endpoint));
+  EXPECT_EQ(test_url_loader_factory_.NumPending(), 1);
+
+  // Fake a response from the endpoint.
+  test_url_loader_factory_.AddResponse(endpoint, R"({"memories": [{}, {}]})");
+  EXPECT_FALSE(test_url_loader_factory_.IsPending(endpoint));
+
+  // Verify the callback is invoked.
+  run_loop_.Run();
+}
+
+}  // namespace
diff --git a/components/memories/core/visit_data.h b/components/memories/core/visit_data.h
index ba71232..2f962fea 100644
--- a/components/memories/core/visit_data.h
+++ b/components/memories/core/visit_data.h
@@ -57,7 +57,7 @@
   // An opaque integer representing page_load_metrics::PageEndReason.
   // Do not use this directly, as it's a raw integer for serialization, and not
   // a typesafe page_load_metrics::PageEndReason.
-  int64_t page_end_reason = 0;
+  int page_end_reason = 0;
 };
 
 struct MemoriesVisit {
diff --git a/components/omnibox/browser/in_memory_url_index.cc b/components/omnibox/browser/in_memory_url_index.cc
index ec33fa54..459ece71 100644
--- a/components/omnibox/browser/in_memory_url_index.cc
+++ b/components/omnibox/browser/in_memory_url_index.cc
@@ -25,8 +25,6 @@
 #include "components/omnibox/browser/url_index_private_data.h"
 #include "components/omnibox/common/omnibox_features.h"
 
-using in_memory_url_index::InMemoryURLIndexCacheItem;
-
 // Initializes a allowlist of URL schemes.
 void InitializeSchemeAllowlist(SchemeSet* allowlist,
                                const SchemeSet& client_schemes_to_allowlist) {
diff --git a/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.cc b/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.cc
index de37d4d..df9d203 100644
--- a/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.cc
+++ b/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.cc
@@ -180,13 +180,10 @@
 
 // static
 bool AdsPageLoadMetricsObserver::IsSubframeSameOriginToMainFrame(
-    content::RenderFrameHost* sub_host,
-    bool use_parent_origin) {
+    content::RenderFrameHost* sub_host) {
   DCHECK(sub_host);
   content::RenderFrameHost* main_host =
       content::WebContents::FromRenderFrameHost(sub_host)->GetMainFrame();
-  if (use_parent_origin)
-    sub_host = sub_host->GetParent();
   url::Origin subframe_origin = sub_host->GetLastCommittedOrigin();
   url::Origin mainframe_origin = main_host->GetLastCommittedOrigin();
   return subframe_origin.IsSameOriginWith(mainframe_origin);
@@ -320,8 +317,7 @@
   if (has_new_fcp) {
     ad_metrics::OriginStatus origin_status =
         AdsPageLoadMetricsObserver::IsSubframeSameOriginToMainFrame(
-            subframe_rfh,
-            !ancestor_data->frame_navigated() /* use_parent_origin */)
+            subframe_rfh)
             ? ad_metrics::OriginStatus::kSame
             : ad_metrics::OriginStatus::kCross;
     ancestor_data->set_creative_origin_status(origin_status);
@@ -353,8 +349,7 @@
     FrameTreeNodeId ad_id,
     bool is_adframe,
     bool should_ignore_detected_ad,
-    content::RenderFrameHost* ad_host,
-    bool frame_navigated) {
+    content::RenderFrameHost* ad_host) {
   // If an existing subframe is navigating and it was an ad previously that
   // hasn't navigated yet, then we need to update it.
   const auto& id_and_data = ad_frames_data_.find(ad_id);
@@ -363,12 +358,13 @@
                                      : nullptr;
 
   if (previous_data) {
-    // We should not get new ad frame notifications for frames that have already
-    // navigated unless there is a ongoing navigation in the frame.
-    DCHECK(frame_navigated);
-
-    if (should_ignore_detected_ad &&
-        (ad_id == previous_data->root_frame_tree_node_id())) {
+    // Frames that are no longer ad frames or are ignored as ad frames due to
+    // restricted navigation ad tagging should have their tracked data reset.
+    // TODO(crbug.com/1101584): Simplify the condition when restricted
+    // navigation ad tagging is moved to subresource_filter/.
+    if (!is_adframe || (should_ignore_detected_ad &&
+                        (ad_id == previous_data->root_frame_tree_node_id()))) {
+      DCHECK_EQ(ad_id, previous_data->root_frame_tree_node_id());
       CleanupDeletedFrame(ad_id, previous_data,
                           true /* update_density_tracker */,
                           false /* record_metrics */);
@@ -380,16 +376,16 @@
       ad_frames_data_.emplace(std::piecewise_construct,
                               std::forward_as_tuple(ad_id),
                               std::forward_as_tuple());
-      RecordAdFrameIgnoredByRestrictedAdTagging(true /* ignored */);
+
+      if (should_ignore_detected_ad)
+        RecordAdFrameIgnoredByRestrictedAdTagging(true /* ignored */);
       return;
     }
 
-    // If the frame has already navigated we need to process the new navigation
+    // As the frame has already navigated, we need to process the new navigation
     // resource in the frame.
-    if (previous_data->frame_navigated()) {
-      ProcessOngoingNavigationResource(ad_host);
-      return;
-    }
+    ProcessOngoingNavigationResource(ad_host);
+    return;
   }
 
   // Determine who the parent frame's ad ancestor is.  If we don't know who it
@@ -416,17 +412,12 @@
   }
 
   if (should_create_new_frame_data) {
-    if (previous_data) {
-      previous_data->UpdateForNavigation(ad_host, frame_navigated);
-      return;
-    }
-
     // Construct a new FrameTreeData to track this ad frame, and update it for
     // the navigation.
     auto frame_data = std::make_unique<FrameTreeData>(
         ad_id,
         heavy_ad_threshold_noise_provider_->GetNetworkThresholdNoiseForFrame());
-    frame_data->UpdateForNavigation(ad_host, frame_navigated);
+    frame_data->UpdateForNavigation(ad_host);
     frame_data->MaybeUpdateFrameDepth(ad_host);
 
     FrameInstance frame_instance(std::move(frame_data));
@@ -518,7 +509,7 @@
   }
 
   UpdateAdFrameData(frame_tree_node_id, is_adframe, should_ignore_detected_ad,
-                    frame_host, true /*frame_navigated=*/);
+                    frame_host);
 
   ProcessOngoingNavigationResource(frame_host);
 }
@@ -720,15 +711,6 @@
   }
 }
 
-void AdsPageLoadMetricsObserver::OnAdSubframeDetected(
-    content::RenderFrameHost* render_frame_host,
-    const subresource_filter::FrameAdEvidence& ad_evidence) {
-  FrameTreeNodeId frame_tree_node_id = render_frame_host->GetFrameTreeNodeId();
-  UpdateAdFrameData(frame_tree_node_id, true /* is_adframe */,
-                    false /* should_ignore_detected_ad */, render_frame_host,
-                    /*frame_navigated=*/false);
-}
-
 void AdsPageLoadMetricsObserver::OnSubresourceFilterGoingAway() {
   subresource_observer_.RemoveAll();
 }
diff --git a/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.h b/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.h
index 3ffb570..82736ba 100644
--- a/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.h
+++ b/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer.h
@@ -78,12 +78,9 @@
       const ApplicationLocaleGetter& application_local_getter);
 
   // For a given subframe, returns whether or not the subframe's url would be
-  // considering same origin to the main frame's url. |use_parent_origin|
-  // indicates that the subframe's parent frames's origin should be used when
-  // performing the comparison.
+  // considering same origin to the main frame's url.
   static bool IsSubframeSameOriginToMainFrame(
-      content::RenderFrameHost* sub_host,
-      bool use_parent_origin);
+      content::RenderFrameHost* sub_host);
 
   // |clock| and |blocklist| should be set only by tests. In particular,
   // |blocklist| should be set only if |heavy_ad_service| is null.
@@ -185,9 +182,6 @@
   void CheckForAdDensityViolation();
 
   // subresource_filter::SubresourceFilterObserver:
-  void OnAdSubframeDetected(
-      content::RenderFrameHost* render_frame_host,
-      const subresource_filter::FrameAdEvidence& ad_evidence) override;
   void OnSubresourceFilterGoingAway() override;
   void OnPageActivationComputed(
       content::NavigationHandle* navigation_handle,
@@ -197,8 +191,7 @@
   void UpdateAdFrameData(FrameTreeNodeId ad_id,
                          bool is_adframe,
                          bool should_ignored_detected_ad,
-                         content::RenderFrameHost* ad_host,
-                         bool frame_navigated);
+                         content::RenderFrameHost* ad_host);
 
   // Gets the number of bytes that we may have not attributed to ad
   // resources due to the resource being reported as an ad late.
diff --git a/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc b/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc
index bbbed4dd..dade4528 100644
--- a/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc
+++ b/components/page_load_metrics/browser/observers/ad_metrics/ads_page_load_metrics_observer_unittest.cc
@@ -1118,7 +1118,7 @@
       NavigationSimulator::CreateRendererInitiated(GURL(kAdUrl), subframe_ad);
   // The sub-frame renavigates before it commits.
   navigation_simulator->Start();
-  TagSubframeAsAd(subframe_ad);
+  SetIsAdSubframe(subframe_ad, /*is_ad_subframe=*/true);
   navigation_simulator->Fail(net::ERR_ABORTED);
 
   // Load resources for the aborted frame (e.g., simulate the navigation
@@ -1147,7 +1147,7 @@
       NavigationSimulator::CreateRendererInitiated(GURL(kAdUrl), sub_frame);
   // The sub-frame renavigates before it commits.
   navigation_simulator->Start();
-  TagSubframeAsAd(sub_frame);
+  SetIsAdSubframe(sub_frame, /*is_ad_subframe=*/true);
   navigation_simulator->Fail(net::ERR_ABORTED);
 
   // Load resources for the aborted frame (e.g., simulate the navigation
@@ -1178,7 +1178,7 @@
 
   // The sub-frame renavigates before it commits.
   navigation_simulator->Start();
-  TagSubframeAsAd(subframe_ad);
+  SetIsAdSubframe(subframe_ad, /*is_ad_subframe=*/true);
   navigation_simulator->Fail(net::ERR_ABORTED);
 
   // Renavigate the subframe to a successful commit. But again, the resource
@@ -1193,6 +1193,30 @@
                  0 /* non_ad_cached_kb */, 10 /* non_ad_uncached_kb */);
 }
 
+TEST_F(AdsPageLoadMetricsObserverTest, UntaggingAdFrame) {
+  RenderFrameHost* main_frame = NavigateMainFrame(kNonAdUrl);
+  RenderFrameHost* ad_frame = CreateAndNavigateSubFrame(kAdUrl, main_frame);
+
+  ResourceDataUpdate(main_frame, ResourceCached::kNotCached, 10);
+  ResourceDataUpdate(ad_frame, ResourceCached::kNotCached, 10);
+
+  // Renavigate and untag the ad frame.
+  auto navigation_simulator =
+      NavigationSimulator::CreateRendererInitiated(GURL(kNonAdUrl), ad_frame);
+  SetIsAdSubframe(ad_frame, /*is_ad_subframe=*/false);
+  navigation_simulator->Commit();
+
+  ResourceDataUpdate(navigation_simulator->GetFinalRenderFrameHost(),
+                     ResourceCached::kNotCached, 10);
+
+  // Navigate again to trigger histograms.
+  NavigateFrame(kNonAdUrl, main_frame);
+
+  // As the frame was untagged, no ad bytes should have been recorded.
+  TestHistograms(histogram_tester(), test_ukm_recorder(), {},
+                 0 /* non_ad_cached_kb */, 20 /* non_ad_uncached_kb */);
+}
+
 TEST_F(AdsPageLoadMetricsObserverTest, MainFrameResource) {
   // Start main-frame navigation
   auto navigation_simulator = NavigationSimulator::CreateRendererInitiated(
@@ -1389,7 +1413,7 @@
       RenderFrameHostTester::For(main_frame)->AppendChild("frame_name");
   auto navigation_simulator = NavigationSimulator::CreateRendererInitiated(
       GURL("https://foo.com"), subframe);
-  TagSubframeAsAd(subframe);
+  SetIsAdSubframe(subframe, /*is_ad_subframe=*/true);
   navigation_simulator->Commit();
 
   subframe = navigation_simulator->GetFinalRenderFrameHost();
diff --git a/components/page_load_metrics/browser/observers/ad_metrics/frame_data.cc b/components/page_load_metrics/browser/observers/ad_metrics/frame_data.cc
index 01f172cc..ea899e4d 100644
--- a/components/page_load_metrics/browser/observers/ad_metrics/frame_data.cc
+++ b/components/page_load_metrics/browser/observers/ad_metrics/frame_data.cc
@@ -310,9 +310,7 @@
 }
 
 void FrameTreeData::UpdateForNavigation(
-    content::RenderFrameHost* render_frame_host,
-    bool frame_navigated) {
-  frame_navigated_ = frame_navigated;
+    content::RenderFrameHost* render_frame_host) {
   if (!render_frame_host)
     return;
 
@@ -321,11 +319,10 @@
     SetFrameSize(*(render_frame_host->GetFrameSize()));
 
   // For frames triggered on render, their origin is their parent's origin.
-  origin_status_ =
-      AdsPageLoadMetricsObserver::IsSubframeSameOriginToMainFrame(
-          render_frame_host, !frame_navigated /* use_parent_origin */)
-          ? OriginStatus::kSame
-          : OriginStatus::kCross;
+  origin_status_ = AdsPageLoadMetricsObserver::IsSubframeSameOriginToMainFrame(
+                       render_frame_host)
+                       ? OriginStatus::kSame
+                       : OriginStatus::kCross;
 
   root_frame_depth_ = render_frame_host->GetFrameDepth();
 }
diff --git a/components/page_load_metrics/browser/observers/ad_metrics/frame_data.h b/components/page_load_metrics/browser/observers/ad_metrics/frame_data.h
index 332b0e18..0415f6af 100644
--- a/components/page_load_metrics/browser/observers/ad_metrics/frame_data.h
+++ b/components/page_load_metrics/browser/observers/ad_metrics/frame_data.h
@@ -283,8 +283,7 @@
   base::TimeDelta GetTotalCpuUsage() const;
 
   // Update the metadata of this frame if it is being navigated.
-  void UpdateForNavigation(content::RenderFrameHost* render_frame_host,
-                           bool frame_navigated);
+  void UpdateForNavigation(content::RenderFrameHost* render_frame_host);
 
   // Returns how the frame should be treated by the heavy ad intervention.
   // This intervention is triggered when the frame is considered heavy, has not
@@ -348,8 +347,6 @@
     return user_activation_status_;
   }
 
-  bool frame_navigated() const { return frame_navigated_; }
-
   FrameVisibility visibility() const { return visibility_; }
 
   gfx::Size frame_size() const { return frame_size_; }
@@ -431,10 +428,6 @@
   // The origin status of the creative content.
   OriginStatus creative_origin_status_ = OriginStatus::kUnknown;
 
-  // Whether or not the frame has been navigated, to determine if there's an
-  // ongoing request.
-  bool frame_navigated_ = false;
-
   // Whether or not the frame is set to not display.
   bool is_display_none_ = false;
 
diff --git a/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc b/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc
index 59df0a9..b1a1e54f 100644
--- a/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc
+++ b/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc
@@ -303,7 +303,7 @@
   LoadHTML(
       "<!doctype html>"
       "<body style='min-height:1000px;'>"
-      "  <iframe style='width: 500px, height: 500px'"
+      "  <iframe style='width: 500px; height: 500px'"
       "          srcdoc=\"<div style='width: 100px; height: 100px;"
       "          background-color: #000000'>&nbsp;</div>\"></iframe>"
       "</body>");
@@ -318,6 +318,48 @@
   EXPECT_EQ(out_response->content_id_to_embedding_token.size(), 0U);
 }
 
+TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureUnclippedLocalFrame) {
+  LoadHTML(
+      "<!doctype html>"
+      "<body style='min-height:1000px;'>"
+      "  <iframe style='width: 500px; height: 500px'"
+      "          srcdoc=\"<div style='width: 500px; height: 100px;"
+      "          background-color: #00FF00'>&nbsp;</div>"
+      "          <div style='width: 500px; height: 900px;"
+      "          background-color: #FF0000'>&nbsp;</div>\"></iframe>"
+      "</body>");
+  auto out_response = mojom::PaintPreviewCaptureResponse::New();
+  auto* child_web_frame =
+      GetFrame()->GetWebFrame()->FirstChild()->ToWebLocalFrame();
+  auto* child_frame = content::RenderFrame::FromWebFrame(child_web_frame);
+  ASSERT_TRUE(child_frame);
+
+  child_web_frame->SetScrollOffset(gfx::ScrollOffset(0, 400));
+
+  base::FilePath skp_path = RunCapture(child_frame, &out_response, false);
+
+  EXPECT_TRUE(out_response->embedding_token.has_value());
+  EXPECT_EQ(out_response->content_id_to_embedding_token.size(), 0U);
+
+  sk_sp<SkPicture> pic;
+  {
+    base::ScopedAllowBlockingForTesting scope;
+    FileRStream rstream(base::File(
+        skp_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ));
+    pic = SkPicture::MakeFromStream(&rstream, nullptr);
+  }
+  EXPECT_EQ(pic->cullRect().width(), child_web_frame->DocumentSize().width());
+  EXPECT_EQ(pic->cullRect().height(), child_web_frame->DocumentSize().height());
+
+  SkBitmap bitmap;
+  ASSERT_TRUE(bitmap.tryAllocN32Pixels(pic->cullRect().width(),
+                                       pic->cullRect().height()));
+  SkCanvas canvas(bitmap);
+  canvas.drawPicture(pic);
+  EXPECT_EQ(bitmap.getColor(50, 50), 0xFF00FF00U);
+  EXPECT_EQ(bitmap.getColor(50, 800), 0xFFFF0000U);
+}
+
 TEST_F(PaintPreviewRecorderRenderViewTest, TestCaptureCustomClipRect) {
   LoadHTML(
       "<!doctype html>"
diff --git a/components/password_manager/content/browser/content_password_manager_driver.h b/components/password_manager/content/browser/content_password_manager_driver.h
index a0eb0eef..27509e19 100644
--- a/components/password_manager/content/browser/content_password_manager_driver.h
+++ b/components/password_manager/content/browser/content_password_manager_driver.h
@@ -14,7 +14,7 @@
 #include "components/autofill/content/common/mojom/autofill_agent.mojom.h"
 #include "components/autofill/content/common/mojom/autofill_driver.mojom.h"
 #include "components/autofill/core/common/password_form_generation_data.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/browser/password_autofill_manager.h"
 #include "components/password_manager/core/browser/password_generation_frame_helper.h"
 #include "components/password_manager/core/browser/password_manager.h"
diff --git a/components/password_manager/core/browser/browser_save_password_progress_logger_unittest.cc b/components/password_manager/core/browser/browser_save_password_progress_logger_unittest.cc
index 6dbbd7c..84aba31 100644
--- a/components/password_manager/core/browser/browser_save_password_progress_logger_unittest.cc
+++ b/components/password_manager/core/browser/browser_save_password_progress_logger_unittest.cc
@@ -9,8 +9,8 @@
 #include "components/autofill/core/browser/form_structure.h"
 #include "components/autofill/core/browser/logging/stub_log_manager.h"
 #include "components/autofill/core/browser/proto/server.pb.h"
-#include "components/autofill/core/common/renderer_id.h"
 #include "components/autofill/core/common/save_password_progress_logger.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/password_manager/core/browser/form_parsing/form_parser.cc b/components/password_manager/core/browser/form_parsing/form_parser.cc
index 4526e805..c957af3 100644
--- a/components/password_manager/core/browser/form_parsing/form_parser.cc
+++ b/components/password_manager/core/browser/form_parsing/form_parser.cc
@@ -27,7 +27,7 @@
 #include "components/autofill/core/browser/autofill_regexes.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/common/form_data.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 
diff --git a/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc b/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc
index 4f44452..c405420 100644
--- a/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc
+++ b/components/password_manager/core/browser/form_parsing/form_parser_unittest.cc
@@ -21,7 +21,7 @@
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_field_data.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "testing/gmock/include/gmock/gmock.h"
diff --git a/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.cc b/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.cc
index aed5909..e69019b 100644
--- a/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.cc
+++ b/components/password_manager/core/browser/form_parsing/fuzzer/form_data_producer.cc
@@ -9,8 +9,8 @@
 #include "build/build_config.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/common/form_field_data.h"
-#include "components/autofill/core/common/renderer_id.h"
 #include "components/autofill/core/common/signatures.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/browser/form_parsing/fuzzer/data_accessor.h"
 #include "url/gurl.h"
 #include "url/origin.h"
diff --git a/components/password_manager/core/browser/form_parsing/password_field_prediction.h b/components/password_manager/core/browser/form_parsing/password_field_prediction.h
index 0e496d4..812842c 100644
--- a/components/password_manager/core/browser/form_parsing/password_field_prediction.h
+++ b/components/password_manager/core/browser/form_parsing/password_field_prediction.h
@@ -10,8 +10,8 @@
 
 #include "build/build_config.h"
 #include "components/autofill/core/browser/field_types.h"
-#include "components/autofill/core/common/renderer_id.h"
 #include "components/autofill/core/common/signatures.h"
+#include "components/autofill/core/common/unique_ids.h"
 
 namespace autofill {
 class FormStructure;
diff --git a/components/password_manager/core/browser/form_parsing/password_field_prediction_unittest.cc b/components/password_manager/core/browser/form_parsing/password_field_prediction_unittest.cc
index 7fbc8c5..8bb29dcd 100644
--- a/components/password_manager/core/browser/form_parsing/password_field_prediction_unittest.cc
+++ b/components/password_manager/core/browser/form_parsing/password_field_prediction_unittest.cc
@@ -11,7 +11,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "components/autofill/core/browser/form_structure.h"
 #include "components/autofill/core/common/form_data.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/common/password_manager_features.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/components/password_manager/core/browser/multi_store_password_save_manager_unittest.cc b/components/password_manager/core/browser/multi_store_password_save_manager_unittest.cc
index d6e3cce..ea8eb35 100644
--- a/components/password_manager/core/browser/multi_store_password_save_manager_unittest.cc
+++ b/components/password_manager/core/browser/multi_store_password_save_manager_unittest.cc
@@ -7,7 +7,7 @@
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/metrics/histogram_tester.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/browser/fake_form_fetcher.h"
 #include "components/password_manager/core/browser/password_form_metrics_recorder.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
diff --git a/components/password_manager/core/browser/password_form.h b/components/password_manager/core/browser/password_form.h
index a7e1711..f1aec6b 100644
--- a/components/password_manager/core/browser/password_form.h
+++ b/components/password_manager/core/browser/password_form.h
@@ -15,7 +15,7 @@
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/gaia_id_hash.h"
 #include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "url/gurl.h"
 #include "url/origin.h"
 
diff --git a/components/password_manager/core/browser/password_form_filling_unittest.cc b/components/password_manager/core/browser/password_form_filling_unittest.cc
index ab94ed8..e0f20076 100644
--- a/components/password_manager/core/browser/password_form_filling_unittest.cc
+++ b/components/password_manager/core/browser/password_form_filling_unittest.cc
@@ -16,7 +16,7 @@
 #include "build/build_config.h"
 #include "components/autofill/core/common/autofill_features.h"
 #include "components/autofill/core/common/password_form_fill_data.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/browser/password_form.h"
 #include "components/password_manager/core/browser/password_form_metrics_recorder.h"
 #include "components/password_manager/core/browser/stub_password_manager_client.h"
diff --git a/components/password_manager/core/browser/password_form_manager.cc b/components/password_manager/core/browser/password_form_manager.cc
index cf0fe0a..b7e235d 100644
--- a/components/password_manager/core/browser/password_form_manager.cc
+++ b/components/password_manager/core/browser/password_form_manager.cc
@@ -579,8 +579,10 @@
   driver_ = driver;
 }
 
-void PasswordFormManager::UpdateObservedFormDataWithFieldDataManagerInfo(
-    const FieldDataManager* field_data_manager) {
+void PasswordFormManager::ProvisionallySaveFieldDataManagerInfo(
+    const FieldDataManager* field_data_manager,
+    const PasswordManagerDriver* driver) {
+  bool data_found = false;
   for (FormFieldData& field : mutable_observed_form()->fields) {
     FieldRendererId field_id = field.unique_renderer_id;
     if (!field_data_manager->HasFieldData(field_id))
@@ -588,7 +590,13 @@
     field.user_input = field_data_manager->GetUserInput(field_id);
     field.properties_mask =
         field_data_manager->GetFieldPropertiesMask(field_id);
+    data_found = true;
   }
+
+  // Provisionally save form and set the manager to be submitted if valid
+  // data was recovered.
+  if (data_found)
+    ProvisionallySave(*observed_form(), driver, nullptr);
 }
 #endif  // defined(OS_IOS)
 
diff --git a/components/password_manager/core/browser/password_form_manager.h b/components/password_manager/core/browser/password_form_manager.h
index 5a7b80ca..636923d3 100644
--- a/components/password_manager/core/browser/password_form_manager.h
+++ b/components/password_manager/core/browser/password_form_manager.h
@@ -18,8 +18,8 @@
 #include "components/autofill/core/common/field_data_manager.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/password_generation_util.h"
-#include "components/autofill/core/common/renderer_id.h"
 #include "components/autofill/core/common/signatures.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/browser/form_fetcher.h"
 #include "components/password_manager/core/browser/form_parsing/form_parser.h"
 #include "components/password_manager/core/browser/form_parsing/password_field_prediction.h"
@@ -209,9 +209,11 @@
 
   void SetDriver(const base::WeakPtr<PasswordManagerDriver>& driver);
 
-  // Copies all known field data from FieldDataManager to |observed_form()|.
-  void UpdateObservedFormDataWithFieldDataManagerInfo(
-      const autofill::FieldDataManager* field_data_manager);
+  // Copies all known field data from FieldDataManager to |observed_form()|
+  // and provisionally saves the manager if the relevant data is found.
+  void ProvisionallySaveFieldDataManagerInfo(
+      const autofill::FieldDataManager* field_data_manager,
+      const PasswordManagerDriver* driver);
 #endif  // defined(OS_IOS)
 
   // Create a copy of |*this| which can be passed to the code handling
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc
index 90d6fe3f..f6f135b 100644
--- a/components/password_manager/core/browser/password_form_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -26,8 +26,8 @@
 #include "components/autofill/core/common/password_form_fill_data.h"
 #include "components/autofill/core/common/password_form_generation_data.h"
 #include "components/autofill/core/common/password_generation_util.h"
-#include "components/autofill/core/common/renderer_id.h"
 #include "components/autofill/core/common/signatures.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/browser/fake_form_fetcher.h"
 #include "components/password_manager/core/browser/field_info_manager.h"
 #include "components/password_manager/core/browser/multi_store_password_save_manager.h"
@@ -2084,8 +2084,8 @@
       base::UTF8ToUTF16("autofilled_pw"),
       FieldPropertiesFlags::kAutofilledOnUserTrigger);
 
-  form_manager_->UpdateObservedFormDataWithFieldDataManagerInfo(
-      field_data_manager.get());
+  form_manager_->ProvisionallySaveFieldDataManagerInfo(field_data_manager.get(),
+                                                       &driver_);
 
   EXPECT_EQ(form_manager_->observed_form()->fields[1].user_input,
             base::UTF8ToUTF16("typed_username"));
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc
index af899b8..3e0d82d 100644
--- a/components/password_manager/core/browser/password_manager.cc
+++ b/components/password_manager/core/browser/password_manager.cc
@@ -808,6 +808,14 @@
     }
   }
 }
+
+void PasswordManager::PropagateFieldDataManagerInfo(
+    const FieldDataManager* field_data_manager,
+    const PasswordManagerDriver* driver) {
+  for (auto& manager : form_managers_) {
+    manager->ProvisionallySaveFieldDataManagerInfo(field_data_manager, driver);
+  }
+}
 #endif
 
 bool PasswordManager::IsAutomaticSavePromptAvailable() {
@@ -1293,12 +1301,8 @@
     PasswordManagerDriver* driver) {
   // If the manager is not submitted, it still can have autofilled data.
   if (!form_manager->is_submitted()) {
-    form_manager->UpdateObservedFormDataWithFieldDataManagerInfo(
-        field_data_manager);
-    // Provisionally save form and set the manager to be submitted if valid
-    // data was recovered.
-    form_manager->ProvisionallySave(*form_manager->observed_form(), driver,
-                                    nullptr);
+    form_manager->ProvisionallySaveFieldDataManagerInfo(field_data_manager,
+                                                        driver);
   }
   // If the manager was set to be submitted, either prior to this function call
   // or on provisional save above, consider submission successful.
diff --git a/components/password_manager/core/browser/password_manager.h b/components/password_manager/core/browser/password_manager.h
index aeb1fc4..ae2b47f9 100644
--- a/components/password_manager/core/browser/password_manager.h
+++ b/components/password_manager/core/browser/password_manager.h
@@ -17,8 +17,8 @@
 #include "build/build_config.h"
 #include "components/autofill/core/common/password_form_fill_data.h"
 #include "components/autofill/core/common/password_generation_util.h"
-#include "components/autofill/core/common/renderer_id.h"
 #include "components/autofill/core/common/signatures.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/browser/credential_cache.h"
 #include "components/password_manager/core/browser/form_parsing/password_field_prediction.h"
 #include "components/password_manager/core/browser/form_submission_observer.h"
@@ -108,6 +108,9 @@
       const std::string& frame_id,
       PasswordManagerDriver* driver,
       const autofill::FieldDataManager* field_data_manager) override;
+  void PropagateFieldDataManagerInfo(
+      const autofill::FieldDataManager* field_data_manager,
+      const PasswordManagerDriver* driver) override;
 #endif
 
   // Notifies the renderer to start the generation flow or pops up additional UI
diff --git a/components/password_manager/core/browser/password_manager_driver.h b/components/password_manager/core/browser/password_manager_driver.h
index 753ac442..3351d9f 100644
--- a/components/password_manager/core/browser/password_manager_driver.h
+++ b/components/password_manager/core/browser/password_manager_driver.h
@@ -14,7 +14,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/types/strong_alias.h"
 #include "components/autofill/core/common/mojom/autofill_types.mojom.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 
 namespace autofill {
 class AutofillDriver;
diff --git a/components/password_manager/core/browser/password_manager_interface.h b/components/password_manager/core/browser/password_manager_interface.h
index 6dffdc14..1629a4e 100644
--- a/components/password_manager/core/browser/password_manager_interface.h
+++ b/components/password_manager/core/browser/password_manager_interface.h
@@ -12,7 +12,7 @@
 #include "build/build_config.h"
 #include "components/autofill/core/common/field_data_manager.h"
 #include "components/autofill/core/common/form_data.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/browser/form_submission_observer.h"
 #include "components/password_manager/core/browser/password_manager_driver.h"
 
@@ -98,6 +98,12 @@
       const std::string& frame_id,
       PasswordManagerDriver* driver,
       const autofill::FieldDataManager* field_data_manager) = 0;
+
+  // Propagates all available field data manager info to existing form managers
+  // and provisionally saves them if the relevant data is retrieved.
+  virtual void PropagateFieldDataManagerInfo(
+      const autofill::FieldDataManager* field_data_manager,
+      const PasswordManagerDriver* driver) = 0;
 #endif
 };
 
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc
index a066475..26555a2 100644
--- a/components/password_manager/core/browser/password_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -26,8 +26,8 @@
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/form_field_data.h"
 #include "components/autofill/core/common/password_generation_util.h"
-#include "components/autofill/core/common/renderer_id.h"
 #include "components/autofill/core/common/signatures.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/browser/field_info_manager.h"
 #include "components/password_manager/core/browser/form_fetcher_impl.h"
 #include "components/password_manager/core/browser/leak_detection/leak_detection_check.h"
diff --git a/components/password_manager/core/browser/password_save_manager_impl_unittest.cc b/components/password_manager/core/browser/password_save_manager_impl_unittest.cc
index 3964451..7412b13 100644
--- a/components/password_manager/core/browser/password_save_manager_impl_unittest.cc
+++ b/components/password_manager/core/browser/password_save_manager_impl_unittest.cc
@@ -10,7 +10,7 @@
 #include "base/test/test_mock_time_task_runner.h"
 #include "build/build_config.h"
 #include "components/autofill/core/browser/autofill_download_manager.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/browser/fake_form_fetcher.h"
 #include "components/password_manager/core/browser/form_parsing/form_parser.h"
 #include "components/password_manager/core/browser/multi_store_password_save_manager.h"
diff --git a/components/password_manager/core/browser/possible_username_data.h b/components/password_manager/core/browser/possible_username_data.h
index 401a2785b..1be16551 100644
--- a/components/password_manager/core/browser/possible_username_data.h
+++ b/components/password_manager/core/browser/possible_username_data.h
@@ -10,7 +10,7 @@
 
 #include "base/optional.h"
 #include "base/time/time.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/browser/form_parsing/password_field_prediction.h"
 
 namespace password_manager {
diff --git a/components/password_manager/core/browser/possible_username_data_unittest.cc b/components/password_manager/core/browser/possible_username_data_unittest.cc
index c18052a..9136b32 100644
--- a/components/password_manager/core/browser/possible_username_data_unittest.cc
+++ b/components/password_manager/core/browser/possible_username_data_unittest.cc
@@ -6,7 +6,7 @@
 
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/task_environment.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using base::Time;
diff --git a/components/password_manager/core/browser/votes_uploader.h b/components/password_manager/core/browser/votes_uploader.h
index 35dae8aa..dd21c3d 100644
--- a/components/password_manager/core/browser/votes_uploader.h
+++ b/components/password_manager/core/browser/votes_uploader.h
@@ -12,8 +12,8 @@
 #include "base/optional.h"
 #include "components/autofill/core/browser/field_types.h"
 #include "components/autofill/core/browser/proto/server.pb.h"
-#include "components/autofill/core/common/renderer_id.h"
 #include "components/autofill/core/common/signatures.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/browser/form_parsing/password_field_prediction.h"
 #include "components/password_manager/core/browser/password_form.h"
 
diff --git a/components/password_manager/core/browser/votes_uploader_unittest.cc b/components/password_manager/core/browser/votes_uploader_unittest.cc
index 7dd6ac27..4cf608e 100644
--- a/components/password_manager/core/browser/votes_uploader_unittest.cc
+++ b/components/password_manager/core/browser/votes_uploader_unittest.cc
@@ -18,8 +18,8 @@
 #include "components/autofill/core/browser/autofill_download_manager.h"
 #include "components/autofill/core/browser/form_structure.h"
 #include "components/autofill/core/common/form_data.h"
-#include "components/autofill/core/common/renderer_id.h"
 #include "components/autofill/core/common/signatures.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/password_manager/core/browser/field_info_manager.h"
 #include "components/password_manager/core/browser/mock_password_store.h"
 #include "components/password_manager/core/browser/stub_password_manager_client.h"
diff --git a/components/password_manager/ios/account_select_fill_data.h b/components/password_manager/ios/account_select_fill_data.h
index 5fdcda1..87facd77 100644
--- a/components/password_manager/ios/account_select_fill_data.h
+++ b/components/password_manager/ios/account_select_fill_data.h
@@ -11,7 +11,7 @@
 #include <vector>
 
 #include "base/macros.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "url/gurl.h"
 
 namespace autofill {
diff --git a/components/password_manager/ios/js_password_manager.h b/components/password_manager/ios/js_password_manager.h
index 90f17a86..ee62f3a0 100644
--- a/components/password_manager/ios/js_password_manager.h
+++ b/components/password_manager/ios/js_password_manager.h
@@ -6,7 +6,7 @@
 #define COMPONENTS_PASSWORD_MANAGER_IOS_JS_PASSWORD_MANAGER_H_
 
 #include "base/ios/block_types.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "ios/web/public/js_messaging/web_frame.h"
 
 namespace autofill {
diff --git a/components/password_manager/ios/password_form_helper.h b/components/password_manager/ios/password_form_helper.h
index f7a31a76..5f3c87954 100644
--- a/components/password_manager/ios/password_form_helper.h
+++ b/components/password_manager/ios/password_form_helper.h
@@ -8,7 +8,7 @@
 #import <Foundation/Foundation.h>
 
 #include "base/memory/ref_counted_memory.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #import "components/autofill/ios/form_util/form_activity_observer_bridge.h"
 #import "ios/web/public/web_state_observer_bridge.h"
 #include "url/gurl.h"
diff --git a/components/password_manager/ios/password_form_helper.mm b/components/password_manager/ios/password_form_helper.mm
index 36ff09e..1edda69 100644
--- a/components/password_manager/ios/password_form_helper.mm
+++ b/components/password_manager/ios/password_form_helper.mm
@@ -158,12 +158,6 @@
   _formActivityObserverBridge.reset();
 }
 
-- (void)webState:(web::WebState*)webState
-    didFinishNavigation:(web::NavigationContext*)navigation {
-  // Delete collected field data.
-  _fieldDataManager->ClearData();
-}
-
 #pragma mark - FormActivityObserver
 
 - (void)webState:(web::WebState*)webState
diff --git a/components/password_manager/ios/password_form_helper_unittest.mm b/components/password_manager/ios/password_form_helper_unittest.mm
index 9b64f45..0d3f99dd 100644
--- a/components/password_manager/ios/password_form_helper_unittest.mm
+++ b/components/password_manager/ios/password_form_helper_unittest.mm
@@ -405,9 +405,9 @@
   }));
   EXPECT_EQ(success, NO);
 
-  // Make sure that this form can be filled again after a navigation.
-  web::FakeNavigationContext context;
-  [helper_ webState:web_state() didFinishNavigation:&context];
+  // Make sure that this form can be filled again after a navigation when the
+  // field data manager data is cleared.
+  helper_.fieldDataManager->ClearData();
 
   success = NO;
   [helper_ fillPasswordForm:form_data
diff --git a/components/password_manager/ios/password_suggestion_helper.h b/components/password_manager/ios/password_suggestion_helper.h
index 623dc35..23485856 100644
--- a/components/password_manager/ios/password_suggestion_helper.h
+++ b/components/password_manager/ios/password_suggestion_helper.h
@@ -8,7 +8,7 @@
 #import <Foundation/Foundation.h>
 #include <memory>
 
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #import "components/autofill/ios/browser/form_suggestion_provider.h"
 
 NS_ASSUME_NONNULL_BEGIN
diff --git a/components/password_manager/ios/shared_password_controller.mm b/components/password_manager/ios/shared_password_controller.mm
index 75d1b81..cf45275 100644
--- a/components/password_manager/ios/shared_password_controller.mm
+++ b/components/password_manager/ios/shared_password_controller.mm
@@ -25,8 +25,8 @@
 #include "components/autofill/core/common/password_form_fill_data.h"
 #include "components/autofill/core/common/password_form_generation_data.h"
 #include "components/autofill/core/common/password_generation_util.h"
-#include "components/autofill/core/common/renderer_id.h"
 #include "components/autofill/core/common/signatures.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/autofill/ios/browser/autofill_util.h"
 #import "components/autofill/ios/browser/form_suggestion_provider_query.h"
 #import "components/autofill/ios/form_util/form_activity_observer_bridge.h"
@@ -53,6 +53,7 @@
 #error "This file requires ARC support."
 #endif
 
+using autofill::FieldDataManager;
 using autofill::FieldRendererId;
 using autofill::FormActivityObserverBridge;
 using autofill::FormData;
@@ -190,6 +191,10 @@
   if (!GetPageURLAndCheckTrustLevel(webState, nullptr))
     return;
 
+  auto fieldDataManager =
+      UniqueIDDataTabHelper::FromWebState(_webState)->GetFieldDataManager();
+  _passwordManager->PropagateFieldDataManagerInfo(
+      fieldDataManager.get(), _delegate.passwordManagerDriver);
   // On non-iOS platforms navigations initiated by link click are excluded from
   // navigations which might be form submssions. On iOS there is no easy way to
   // check that the navigation is link initiated, so it is skipped. It should
@@ -197,6 +202,7 @@
   // after filling password form w/o submitting it.
   _passwordManager->DidNavigateMainFrame(
       /*form_may_be_submitted=*/navigation->IsRendererInitiated());
+  fieldDataManager->ClearData();
 }
 
 - (void)webState:(web::WebState*)webState didLoadPageWithSuccess:(BOOL)success {
diff --git a/components/password_manager/ios/shared_password_controller_unittest.mm b/components/password_manager/ios/shared_password_controller_unittest.mm
index 02ead83..836e64e 100644
--- a/components/password_manager/ios/shared_password_controller_unittest.mm
+++ b/components/password_manager/ios/shared_password_controller_unittest.mm
@@ -98,6 +98,10 @@
                PasswordManagerDriver*,
                const autofill::FieldDataManager*),
               (override));
+  MOCK_METHOD(void,
+              PropagateFieldDataManagerInfo,
+              (const autofill::FieldDataManager*, const PasswordManagerDriver*),
+              (override));
 };
 
 class SharedPasswordControllerTest : public PlatformTest {
@@ -146,6 +150,7 @@
   navigation_context.SetIsSameDocument(false);
   navigation_context.SetIsRendererInitiated(true);
 
+  EXPECT_CALL(password_manager_, PropagateFieldDataManagerInfo);
   EXPECT_CALL(password_manager_, DidNavigateMainFrame(true));
   web_state_.OnNavigationFinished(&navigation_context);
 }
diff --git a/components/performance_manager/execution_context_priority/ad_frame_voter.cc b/components/performance_manager/execution_context_priority/ad_frame_voter.cc
index eb4ea70d..8d1e68c 100644
--- a/components/performance_manager/execution_context_priority/ad_frame_voter.cc
+++ b/components/performance_manager/execution_context_priority/ad_frame_voter.cc
@@ -50,12 +50,12 @@
 }
 
 void AdFrameVoter::OnIsAdFrameChanged(const FrameNode* frame_node) {
-  // The IsAdFrame() bit is a one-way switch that can only go from false to
-  // true.
-  DCHECK(frame_node->IsAdFrame());
-
-  const Vote vote(base::TaskPriority::LOWEST, kAdFrameReason);
-  voting_channel_.SubmitVote(GetExecutionContext(frame_node), vote);
+  if (frame_node->IsAdFrame()) {
+    const Vote vote(base::TaskPriority::LOWEST, kAdFrameReason);
+    voting_channel_.SubmitVote(GetExecutionContext(frame_node), vote);
+  } else {
+    voting_channel_.InvalidateVote(GetExecutionContext(frame_node));
+  }
 }
 
 }  // namespace execution_context_priority
diff --git a/components/performance_manager/execution_context_priority/ad_frame_voter_unittest.cc b/components/performance_manager/execution_context_priority/ad_frame_voter_unittest.cc
index 17120f95..06be3d165 100644
--- a/components/performance_manager/execution_context_priority/ad_frame_voter_unittest.cc
+++ b/components/performance_manager/execution_context_priority/ad_frame_voter_unittest.cc
@@ -86,7 +86,7 @@
 };
 
 // Tests that the AdFrameVoter correctly casts a vote for an ad frame.
-TEST_F(AdFrameVoterTest, SetIsAdFrame) {
+TEST_F(AdFrameVoterTest, SetIsAdFrameTrue) {
   // Create a graph with a single frame. It should not initially be an ad frame.
   MockSinglePageInSingleProcessGraph mock_graph(graph());
   auto& frame_node = mock_graph.frame;
@@ -96,7 +96,7 @@
       observer().HasVote(voter_id(), GetExecutionContext(frame_node.get())));
 
   // Make the frame an ad frame. This should cast a low priority vote.
-  mock_graph.frame->SetIsAdFrame();
+  mock_graph.frame->SetIsAdFrame(true);
   EXPECT_EQ(observer().GetVoteCount(), 1u);
   EXPECT_TRUE(observer().HasVote(
       voter_id(), GetExecutionContext(frame_node.get()),
@@ -107,5 +107,26 @@
   EXPECT_EQ(observer().GetVoteCount(), 0u);
 }
 
+// Tests that the AdFrameVoter correctly does not cast a vote for an untagged
+// frame.
+TEST_F(AdFrameVoterTest, SetIsAdFrameFalse) {
+  // Create a graph with a single ad frame.
+  MockSinglePageInSingleProcessGraph mock_graph(graph());
+  auto& frame_node = mock_graph.frame;
+  mock_graph.frame->SetIsAdFrame(true);
+  EXPECT_TRUE(frame_node->is_ad_frame());
+
+  // Unset the frame as an ad. This should invalidate any vote.
+  mock_graph.frame->SetIsAdFrame(false);
+  EXPECT_FALSE(frame_node->is_ad_frame());
+  EXPECT_EQ(observer().GetVoteCount(), 0u);
+  EXPECT_FALSE(
+      observer().HasVote(voter_id(), GetExecutionContext(frame_node.get())));
+
+  // Deleting the frame should not affect the vote count.
+  frame_node.reset();
+  EXPECT_EQ(observer().GetVoteCount(), 0u);
+}
+
 }  // namespace execution_context_priority
 }  // namespace performance_manager
diff --git a/components/performance_manager/graph/frame_node_impl.cc b/components/performance_manager/graph/frame_node_impl.cc
index 3c2cdcd7..0ec42a16 100644
--- a/components/performance_manager/graph/frame_node_impl.cc
+++ b/components/performance_manager/graph/frame_node_impl.cc
@@ -82,9 +82,9 @@
   document_.has_nonempty_beforeunload = has_nonempty_beforeunload;
 }
 
-void FrameNodeImpl::SetIsAdFrame() {
+void FrameNodeImpl::SetIsAdFrame(bool is_ad_frame) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  is_ad_frame_.SetAndMaybeNotify(this, true);
+  is_ad_frame_.SetAndMaybeNotify(this, is_ad_frame);
 }
 
 void FrameNodeImpl::SetHadFormInteraction() {
diff --git a/components/performance_manager/graph/frame_node_impl.h b/components/performance_manager/graph/frame_node_impl.h
index 5318731..4f4a276 100644
--- a/components/performance_manager/graph/frame_node_impl.h
+++ b/components/performance_manager/graph/frame_node_impl.h
@@ -85,7 +85,7 @@
   void SetLifecycleState(LifecycleState state) override;
   void SetHasNonEmptyBeforeUnload(bool has_nonempty_beforeunload) override;
   void SetViewportIntersection(const gfx::Rect& viewport_intersection) override;
-  void SetIsAdFrame() override;
+  void SetIsAdFrame(bool is_ad_frame) override;
   void SetHadFormInteraction() override;
   void OnNonPersistentNotificationCreated() override;
   void OnFirstContentfulPaint(
@@ -296,7 +296,6 @@
       &FrameNodeObserver::OnFrameLifecycleStateChanged>
       lifecycle_state_{LifecycleState::kRunning};
 
-  // This is a one way switch. Once marked an ad-frame, always an ad-frame.
   ObservedProperty::
       NotifiesOnlyOnChanges<bool, &FrameNodeObserver::OnIsAdFrameChanged>
           is_ad_frame_{false};
diff --git a/components/performance_manager/graph/frame_node_impl_unittest.cc b/components/performance_manager/graph/frame_node_impl_unittest.cc
index 7d423b78..12b73d7 100644
--- a/components/performance_manager/graph/frame_node_impl_unittest.cc
+++ b/components/performance_manager/graph/frame_node_impl_unittest.cc
@@ -231,13 +231,19 @@
   MockObserver obs;
   graph()->AddFrameNodeObserver(&obs);
 
+  // Observer will be notified once when IsAdFrame goes from false to true, and
+  // again when it goes from true to false.
+  EXPECT_CALL(obs, OnIsAdFrameChanged(frame_node.get())).Times(2);
+
   EXPECT_FALSE(frame_node->is_ad_frame());
-  EXPECT_CALL(obs, OnIsAdFrameChanged(frame_node.get()));
-  frame_node->SetIsAdFrame();
+  frame_node->SetIsAdFrame(true);
   EXPECT_TRUE(frame_node->is_ad_frame());
-  frame_node->SetIsAdFrame();
+  frame_node->SetIsAdFrame(true);
   EXPECT_TRUE(frame_node->is_ad_frame());
 
+  frame_node->SetIsAdFrame(false);
+  EXPECT_FALSE(frame_node->is_ad_frame());
+
   graph()->RemoveFrameNodeObserver(&obs);
 }
 
diff --git a/components/performance_manager/public/mojom/coordination_unit.mojom b/components/performance_manager/public/mojom/coordination_unit.mojom
index 6660e5c..99853b1 100644
--- a/components/performance_manager/public/mojom/coordination_unit.mojom
+++ b/components/performance_manager/public/mojom/coordination_unit.mojom
@@ -33,7 +33,9 @@
   // Called the first time a form in this document is interacted with.
   SetHadFormInteraction();
 
-  SetIsAdFrame();
+  // Called whenever the frame associated with this document is tagged or
+  // untagged as an ad, providing the new status.
+  SetIsAdFrame(bool is_ad_frame);
 
   // Called when the intersection between this frame and the viewport changes.
   // The viewport is the rectangular area of the top-level document that is
diff --git a/components/remote_cocoa/app_shim/bridged_content_view.mm b/components/remote_cocoa/app_shim/bridged_content_view.mm
index 3a3eac55..3b61d81 100644
--- a/components/remote_cocoa/app_shim/bridged_content_view.mm
+++ b/components/remote_cocoa/app_shim/bridged_content_view.mm
@@ -443,6 +443,15 @@
     text = [text string];
 
   bool isCharacterEvent = _keyDownEvent && [text length] == 1;
+
+  // For some reason, shift-enter (not shift-return) results in the insertion of
+  // a string with a single character, U+0003, END OF TEXT. Continuing on this
+  // route will result in a forged event that loses the shift modifier.
+  // Therefore, early return. When -keyDown: resumes, it will use a ui::KeyEvent
+  // constructor that works. See https://crbug.com/1188713#c4 for the analysis.
+  if (isCharacterEvent && [text characterAtIndex:0] == 0x0003)
+    return;
+
   // Pass "character" events to the View hierarchy. Cases this handles (non-
   // exhaustive)-
   //    - Space key press on controls. Unlike Tab and newline which have
diff --git a/components/rlz/rlz_tracker.cc b/components/rlz/rlz_tracker.cc
index 1221e30..61d4420 100644
--- a/components/rlz/rlz_tracker.cc
+++ b/components/rlz/rlz_tracker.cc
@@ -180,7 +180,6 @@
 
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
@@ -189,14 +188,14 @@
       override {
     if (main_thread_task_runner_->RunsTasksInCurrentSequence()) {
       url_loader_factory_->CreateLoaderAndStart(
-          std::move(loader), routing_id, request_id, options, request,
-          std::move(client), traffic_annotation);
+          std::move(loader), request_id, options, request, std::move(client),
+          traffic_annotation);
     } else {
       main_thread_task_runner_->PostTask(
           FROM_HERE,
           base::BindOnce(&WrapperURLLoaderFactory::CreateLoaderAndStart,
-                         base::Unretained(this), std::move(loader), routing_id,
-                         request_id, options, request, std::move(client),
+                         base::Unretained(this), std::move(loader), request_id,
+                         options, request, std::move(client),
                          traffic_annotation));
     }
   }
diff --git a/components/safe_browsing/core/browser/safe_browsing_network_context.cc b/components/safe_browsing/core/browser/safe_browsing_network_context.cc
index c22db020..1a3e3a8 100644
--- a/components/safe_browsing/core/browser/safe_browsing_network_context.cc
+++ b/components/safe_browsing/core/browser/safe_browsing_network_context.cc
@@ -68,7 +68,6 @@
   // network::URLLoaderFactory implementation:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
@@ -77,8 +76,8 @@
       override {
     DCHECK(CurrentlyOnThread(ThreadID::UI));
     GetURLLoaderFactory()->CreateLoaderAndStart(
-        std::move(loader), routing_id, request_id, options, request,
-        std::move(client), traffic_annotation);
+        std::move(loader), request_id, options, request, std::move(client),
+        traffic_annotation);
   }
 
   void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver)
diff --git a/components/subresource_filter/content/browser/ad_tagging_browser_test_utils.cc b/components/subresource_filter/content/browser/ad_tagging_browser_test_utils.cc
index d3f6eba..f4bde06 100644
--- a/components/subresource_filter/content/browser/ad_tagging_browser_test_utils.cc
+++ b/components/subresource_filter/content/browser/ad_tagging_browser_test_utils.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/strings/stringprintf.h"
+#include "components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -55,4 +56,33 @@
   return CreateFrameImpl(adapter, url, false /* ad_script */);
 }
 
+void ExpectFrameAdEvidence(content::RenderFrameHost* frame_host,
+                           bool parent_is_ad,
+                           FilterListEvidence filter_list_result,
+                           ScriptHeuristicEvidence created_by_ad_script) {
+  ExpectFrameAdEvidence(frame_host, parent_is_ad, filter_list_result,
+                        filter_list_result, created_by_ad_script);
+}
+
+void ExpectFrameAdEvidence(
+    content::RenderFrameHost* frame_host,
+    bool parent_is_ad,
+    FilterListEvidence latest_filter_list_result,
+    FilterListEvidence most_restrictive_filter_list_result,
+    ScriptHeuristicEvidence created_by_ad_script) {
+  auto* throttle_manager =
+      ContentSubresourceFilterThrottleManager::FromWebContents(
+          content::WebContents::FromRenderFrameHost(frame_host));
+  base::Optional<FrameAdEvidence> ad_evidence =
+      throttle_manager->GetAdEvidenceForFrame(frame_host);
+  ASSERT_TRUE(ad_evidence.has_value());
+  EXPECT_TRUE(ad_evidence->is_complete());
+  EXPECT_EQ(ad_evidence->parent_is_ad(), parent_is_ad);
+  EXPECT_EQ(ad_evidence->latest_filter_list_result(),
+            latest_filter_list_result);
+  EXPECT_EQ(ad_evidence->most_restrictive_filter_list_result(),
+            most_restrictive_filter_list_result);
+  EXPECT_EQ(ad_evidence->created_by_ad_script(), created_by_ad_script);
+}
+
 }  // namespace subresource_filter
diff --git a/components/subresource_filter/content/browser/ad_tagging_browser_test_utils.h b/components/subresource_filter/content/browser/ad_tagging_browser_test_utils.h
index 7380a0f..7b779ed 100644
--- a/components/subresource_filter/content/browser/ad_tagging_browser_test_utils.h
+++ b/components/subresource_filter/content/browser/ad_tagging_browser_test_utils.h
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "components/subresource_filter/content/common/ad_evidence.h"
 #include "url/gurl.h"
 
 namespace content {
@@ -32,6 +33,20 @@
     const content::ToRenderFrameHost& adapter,
     const GURL& url);
 
+// Verifies that the ad evidence associated with the frame matches the
+// provided values. The first signature assumes that the most restrictive and
+// latest filter list results are the same.
+void ExpectFrameAdEvidence(content::RenderFrameHost* frame_host,
+                           bool parent_is_ad,
+                           FilterListEvidence filter_list_result,
+                           ScriptHeuristicEvidence created_by_ad_script);
+void ExpectFrameAdEvidence(
+    content::RenderFrameHost* frame_host,
+    bool parent_is_ad,
+    FilterListEvidence latest_filter_list_result,
+    FilterListEvidence most_restrictive_filter_list_result,
+    ScriptHeuristicEvidence created_by_ad_script);
+
 }  // namespace subresource_filter
 
 #endif  // COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_AD_TAGGING_BROWSER_TEST_UTILS_H_
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc
index a541a6f..1f28a27 100644
--- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc
+++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc
@@ -168,16 +168,14 @@
     content::NavigationHandle* navigation_handle) {
   content::RenderFrameHost* frame_host =
       navigation_handle->GetRenderFrameHost();
-  int frame_tree_node_id = navigation_handle->GetFrameTreeNodeId();
 
-  if (!navigation_handle->IsInMainFrame() &&
-      !base::Contains(ad_frames_, frame_tree_node_id)) {
+  // Update the ad status of a frame given the new navigation. This may tag or
+  // untag a frame as an ad.
+  if (!navigation_handle->IsInMainFrame()) {
     FrameAdEvidence& ad_evidence = EnsureFrameAdEvidence(frame_host);
     ad_evidence.set_is_complete();
 
-    if (ad_evidence.IndicatesAdSubframe()) {
-      SetFrameAsAdSubframe(frame_host);
-    }
+    SetIsAdSubframe(frame_host, ad_evidence.IndicatesAdSubframe());
   }
 
   if (navigation_handle->GetNetErrorCode() != net::OK)
@@ -220,9 +218,6 @@
   if (is_ad_subframe) {
     ad_frame_type = parent_is_ad ? blink::mojom::AdFrameType::kChildAd
                                  : blink::mojom::AdFrameType::kRootAd;
-    // Replicate ad frame type to this frame's proxies, so that it can be looked
-    // up in any process involved in rendering the current page.
-    frame_host->UpdateAdFrameType(ad_frame_type);
   }
 
   mojo::AssociatedRemote<mojom::SubresourceFilterAgent> agent;
@@ -292,7 +287,6 @@
              EnsureFrameAdEvidence(frame_host).IndicatesAdSubframe()));
   } else {
     DCHECK(navigation_handle->IsInMainFrame() ||
-           base::Contains(ad_frames_, frame_tree_node_id) ||
            EnsureFrameAdEvidence(frame_host).is_complete());
   }
 
@@ -468,18 +462,12 @@
           navigation_handle->GetFrameTreeNodeId());
   DCHECK(starting_rfh);
 
-  // Update `starting_rfh`'s FrameAdEvidence, unless it is already tagged as an
-  // ad. Once a frame is tagged as an ad, the evidence should be frozen and
-  // stored in `ad_frames_`.
-  if (base::Contains(ad_frames_, frame_tree_node_id))
-    return;
-
   FrameAdEvidence& ad_evidence = EnsureFrameAdEvidence(starting_rfh);
   DCHECK_EQ(ad_evidence.parent_is_ad(),
             base::Contains(ad_frames_,
                            starting_rfh->GetParent()->GetFrameTreeNodeId()));
 
-  ad_evidence.set_filter_list_result(
+  ad_evidence.UpdateFilterListResult(
       InterpretLoadPolicyAsEvidence(load_policy));
 }
 
@@ -668,42 +656,73 @@
   // through `DidFinishNavigation()`), we know it won't be updated further.
   EnsureFrameAdEvidence(render_frame_host).set_is_complete();
 
-  SetFrameAsAdSubframe(render_frame_host);
+  // The renderer has indicated that the frame is an ad.
+  SetIsAdSubframe(render_frame_host, /*is_ad_subframe=*/true);
 }
 
-void ContentSubresourceFilterThrottleManager::SetFrameAsAdSubframe(
-    content::RenderFrameHost* render_frame_host) {
+void ContentSubresourceFilterThrottleManager::SetIsAdSubframe(
+    content::RenderFrameHost* render_frame_host,
+    bool is_ad_subframe) {
   int frame_tree_node_id = render_frame_host->GetFrameTreeNodeId();
+  DCHECK(base::Contains(tracked_ad_evidence_, frame_tree_node_id));
+  DCHECK_EQ(tracked_ad_evidence_.at(frame_tree_node_id).IndicatesAdSubframe(),
+            is_ad_subframe);
+  DCHECK(render_frame_host->GetParent());
 
-  auto ad_evidence_it = tracked_ad_evidence_.find(frame_tree_node_id);
-  DCHECK(ad_evidence_it != tracked_ad_evidence_.end());
-  DCHECK(ad_evidence_it->second.IndicatesAdSubframe());
+  // `ad_frames_` does not need updating.
+  if (is_ad_subframe == base::Contains(ad_frames_, frame_tree_node_id))
+    return;
 
-  const FrameAdEvidence& frozen_evidence =
-      ad_frames_.emplace(frame_tree_node_id, ad_evidence_it->second)
-          .first->second;
-  tracked_ad_evidence_.erase(ad_evidence_it);
+  blink::mojom::AdFrameType ad_frame_type = blink::mojom::AdFrameType::kNonAd;
+  if (is_ad_subframe) {
+    ad_frames_.insert(frame_tree_node_id);
 
-  bool parent_is_ad = base::Contains(
-      ad_frames_, render_frame_host->GetParent()->GetFrameTreeNodeId());
-  blink::mojom::AdFrameType ad_frame_type =
-      parent_is_ad ? blink::mojom::AdFrameType::kChildAd
-                   : blink::mojom::AdFrameType::kRootAd;
+    bool parent_is_ad = base::Contains(
+        ad_frames_, render_frame_host->GetParent()->GetFrameTreeNodeId());
+    ad_frame_type = parent_is_ad ? blink::mojom::AdFrameType::kChildAd
+                                 : blink::mojom::AdFrameType::kRootAd;
+  } else {
+    ad_frames_.erase(frame_tree_node_id);
+  }
 
   // Replicate ad frame type to this frame's proxies, so that it can be looked
   // up in any process involved in rendering the current page.
   render_frame_host->UpdateAdFrameType(ad_frame_type);
 
   SubresourceFilterObserverManager::FromWebContents(web_contents())
-      ->NotifyAdSubframeDetected(render_frame_host, frozen_evidence);
+      ->NotifyIsAdSubframeChanged(render_frame_host, is_ad_subframe);
 }
 
-void ContentSubresourceFilterThrottleManager::SetFrameAsAdSubframeForTesting(
+void ContentSubresourceFilterThrottleManager::SetIsAdSubframeForTesting(
+    content::RenderFrameHost* render_frame_host,
+    bool is_ad_subframe) {
+  if (is_ad_subframe ==
+      base::Contains(ad_frames_, render_frame_host->GetFrameTreeNodeId())) {
+    return;
+  }
+
+  if (is_ad_subframe) {
+    // We mark the frame as created by ad script so that the ad evidence
+    // indicates an ad subframe.
+    OnSubframeWasCreatedByAdScript(render_frame_host);
+    OnFrameIsAdSubframe(render_frame_host);
+  } else {
+    // There's currently no legal transition that can untag a frame. Instead, to
+    // mimic future behavior, we simply replace the FrameAdEvidence.
+    // TODO(crbug.com/1101584): Replace with legal transition when one exists.
+    tracked_ad_evidence_.erase(render_frame_host->GetFrameTreeNodeId());
+    EnsureFrameAdEvidence(render_frame_host).set_is_complete();
+  }
+}
+
+base::Optional<FrameAdEvidence>
+ContentSubresourceFilterThrottleManager::GetAdEvidenceForFrame(
     content::RenderFrameHost* render_frame_host) {
-  // We mark the frame as created by ad script so that the ad evidence indicates
-  // an ad subframe.
-  OnSubframeWasCreatedByAdScript(render_frame_host);
-  OnFrameIsAdSubframe(render_frame_host);
+  auto tracked_ad_evidence_it =
+      tracked_ad_evidence_.find(render_frame_host->GetFrameTreeNodeId());
+  if (tracked_ad_evidence_it == tracked_ad_evidence_.end())
+    return base::nullopt;
+  return tracked_ad_evidence_it->second;
 }
 
 void ContentSubresourceFilterThrottleManager::DidDisallowFirstSubresource() {
@@ -746,7 +765,6 @@
     content::RenderFrameHost* frame_host) {
   DCHECK(frame_host);
   DCHECK(frame_host->GetParent());
-  DCHECK(!base::Contains(ad_frames_, frame_host->GetFrameTreeNodeId()));
   return tracked_ad_evidence_
       .emplace(frame_host->GetFrameTreeNodeId(),
                /*parent_is_ad=*/base::Contains(
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h
index adc9d13..5f151ba 100644
--- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h
+++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h
@@ -7,9 +7,9 @@
 
 #include <map>
 #include <memory>
-#include <set>
 #include <vector>
 
+#include "base/containers/flat_set.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
@@ -149,7 +149,15 @@
 
   static void LogAction(SubresourceFilterAction action);
 
-  void SetFrameAsAdSubframeForTesting(content::RenderFrameHost* frame_host);
+  void SetIsAdSubframeForTesting(content::RenderFrameHost* render_frame_host,
+                                 bool is_ad_subframe);
+
+  // Returns the matching FrameAdEvidence for the frame indicated by
+  // `render_frame_host` or `base::nullopt` if there is none (i.e. the frame is
+  // a main frame, or no navigation or commit has yet occurred and no evidence
+  // has been reported by the renderer).
+  base::Optional<FrameAdEvidence> GetAdEvidenceForFrame(
+      content::RenderFrameHost* render_frame_host);
 
  protected:
   // content::WebContentsObserver:
@@ -246,9 +254,10 @@
       const mojom::ActivationLevel& activation_level,
       bool did_inherit_opener_activation);
 
-  // Sets a frame as an ad subframe by moving its ad evidence from
-  // `tracked_ad_evidence_` to `ad_frames_` (and thus freezing it).
-  void SetFrameAsAdSubframe(content::RenderFrameHost* render_frame_host);
+  // Sets whether the frame is considered an ad subframe. If the value has
+  // changed, we also update the replication state and inform observers.
+  void SetIsAdSubframe(content::RenderFrameHost* render_frame_host,
+                       bool is_ad_subframe);
 
   // For each RenderFrameHost where the last committed load (or the initial load
   // if no committed load has occurred) has subresource filtering activated,
@@ -268,25 +277,14 @@
   std::map<int64_t, ActivationStateComputingNavigationThrottle*>
       ongoing_activation_throttles_;
 
-  // Map of frames that have been identified as ads, keyed by FrameTreeNode ID,
-  // with value being the evidence that the respective frames are ads. This
-  // evidence object is frozen upon the frame being tagged as an ad and is no
-  // longer updated. An RFH is an ad subframe if any of the following conditions
-  // are met:
-  // 1. Its navigation URL is in the filter list
-  // 2. Its parent is a known ad subframe
-  // 3. Ad script was on the v8 stack when the frame was created (see AdTracker
-  //    in Blink)
-  // 4. It's the result of moving an old ad subframe RFH to a new RFH (e.g.,
-  //    OOPIF)
-  std::map<int, const FrameAdEvidence> ad_frames_;
+  // Set of frames that have been identified as ads, identified by FrameTreeNode
+  // ID. A RenderFrameHost is an ad subframe iff the FrameAdEvidence
+  // corresponding to the frame indicates that it is.
+  base::flat_set<int> ad_frames_;
 
-  // Map of subframes that have not (yet) been tagged as ads, keyed by
-  // FrameTreeNode ID, with value being the evidence that the frames are ads.
-  // Once a subframe is tagged as an ad, the evidence is moved to `ad_frames_`
-  // and no longer updated. This will be called prior to commit time in the case
-  // of an initial synchronous load or at ReadyToCommitNavigation otherwise.
-  // Otherwise, it is updated whenever a navigation's LoadPolicy is calculated.
+  // Map of subframes, keyed by FrameTreeNode ID, with value being the evidence
+  // for or against the frames being ads. This evidence is updated whenever a
+  // navigation's LoadPolicy is calculated.
   std::map<int, FrameAdEvidence> tracked_ad_evidence_;
 
   // Map of frames whose navigations have been identified as ads, keyed by
diff --git a/components/subresource_filter/content/browser/subresource_filter_observer.h b/components/subresource_filter/content/browser/subresource_filter_observer.h
index 89f305b..3f205e8 100644
--- a/components/subresource_filter/content/browser/subresource_filter_observer.h
+++ b/components/subresource_filter/content/browser/subresource_filter_observer.h
@@ -56,11 +56,13 @@
       content::NavigationHandle* navigation_handle,
       LoadPolicy load_policy) {}
 
-  // Called when a frame is tagged as an ad, along with evidence for it being
-  // an ad at tagging time. This will be called after frame creation and prior
-  // to DidFinishNavigation.
-  virtual void OnAdSubframeDetected(content::RenderFrameHost* render_frame_host,
-                                    const FrameAdEvidence& ad_evidence) {}
+  // Called when a frame is tagged or untagged as an ad, along with the frame's
+  // current status as an ad subframe and the evidence which resulted in the
+  // change. This will be called prior to commit time in the case of an initial
+  // synchronous load or at ReadyToCommitNavigation otherwise.
+  virtual void OnIsAdSubframeChanged(
+      content::RenderFrameHost* render_frame_host,
+      bool is_ad_subframe) {}
 };
 
 }  // namespace subresource_filter
diff --git a/components/subresource_filter/content/browser/subresource_filter_observer_manager.cc b/components/subresource_filter/content/browser/subresource_filter_observer_manager.cc
index 2fba884..3b91a3c 100644
--- a/components/subresource_filter/content/browser/subresource_filter_observer_manager.cc
+++ b/components/subresource_filter/content/browser/subresource_filter_observer_manager.cc
@@ -49,11 +49,11 @@
     observer.OnSubframeNavigationEvaluated(navigation_handle, load_policy);
 }
 
-void SubresourceFilterObserverManager::NotifyAdSubframeDetected(
+void SubresourceFilterObserverManager::NotifyIsAdSubframeChanged(
     content::RenderFrameHost* render_frame_host,
-    const FrameAdEvidence& ad_evidence) {
+    bool is_ad_subframe) {
   for (auto& observer : observers_)
-    observer.OnAdSubframeDetected(render_frame_host, ad_evidence);
+    observer.OnIsAdSubframeChanged(render_frame_host, is_ad_subframe);
 }
 
 WEB_CONTENTS_USER_DATA_KEY_IMPL(SubresourceFilterObserverManager)
diff --git a/components/subresource_filter/content/browser/subresource_filter_observer_manager.h b/components/subresource_filter/content/browser/subresource_filter_observer_manager.h
index 0eab0cf..23332de8 100644
--- a/components/subresource_filter/content/browser/subresource_filter_observer_manager.h
+++ b/components/subresource_filter/content/browser/subresource_filter_observer_manager.h
@@ -58,11 +58,11 @@
       LoadPolicy load_policy);
 
   // Called in DidCreateNewDocument or ReadyToCommitNavigation to notify
-  // observers that an ad frame has been detected with the associated
-  // RenderFrameHost. The evidence that caused the frame to be tagged is passed
-  // as `ad_evidence`.
-  void NotifyAdSubframeDetected(content::RenderFrameHost* render_frame_host,
-                                const FrameAdEvidence& ad_evidence);
+  // observers that an frame with the associated RenderFrameHost has either been
+  // detected as an ad or is no longer considered one. The frame's new status is
+  // passed as `is_ad_subframe`.
+  void NotifyIsAdSubframeChanged(content::RenderFrameHost* render_frame_host,
+                                 bool is_ad_subframe);
 
  private:
   friend class content::WebContentsUserData<SubresourceFilterObserverManager>;
diff --git a/components/subresource_filter/content/browser/subresource_filter_observer_test_utils.cc b/components/subresource_filter/content/browser/subresource_filter_observer_test_utils.cc
index 0dcb9a4..c6f9d9a 100644
--- a/components/subresource_filter/content/browser/subresource_filter_observer_test_utils.cc
+++ b/components/subresource_filter/content/browser/subresource_filter_observer_test_utils.cc
@@ -43,10 +43,13 @@
   subframe_load_evaluations_[navigation_handle->GetURL()] = load_policy;
 }
 
-void TestSubresourceFilterObserver::OnAdSubframeDetected(
+void TestSubresourceFilterObserver::OnIsAdSubframeChanged(
     content::RenderFrameHost* render_frame_host,
-    const FrameAdEvidence& ad_evidence) {
-  ad_evidence_.emplace(render_frame_host->GetFrameTreeNodeId(), ad_evidence);
+    bool is_ad_subframe) {
+  if (is_ad_subframe)
+    ad_frames_.insert(render_frame_host->GetFrameTreeNodeId());
+  else
+    ad_frames_.erase(render_frame_host->GetFrameTreeNodeId());
 }
 
 void TestSubresourceFilterObserver::DidFinishNavigation(
@@ -78,14 +81,7 @@
 
 bool TestSubresourceFilterObserver::GetIsAdSubframe(
     int frame_tree_node_id) const {
-  return base::Contains(ad_evidence_, frame_tree_node_id);
-}
-
-const FrameAdEvidence& TestSubresourceFilterObserver::GetEvidenceForAdSubframe(
-    int frame_tree_node_id) const {
-  auto it = ad_evidence_.find(frame_tree_node_id);
-  DCHECK(it != ad_evidence_.end());
-  return it->second;
+  return base::Contains(ad_frames_, frame_tree_node_id);
 }
 
 base::Optional<LoadPolicy> TestSubresourceFilterObserver::GetSubframeLoadPolicy(
@@ -109,17 +105,4 @@
   return base::Optional<SafeBrowsingCheck>();
 }
 
-void TestSubresourceFilterObserver::VerifyEvidenceForAdSubframe(
-    content::RenderFrameHost* frame_host,
-    bool parent_is_ad,
-    FilterListEvidence filter_list_result,
-    ScriptHeuristicEvidence created_by_ad_script) const {
-  const FrameAdEvidence& ad_evidence =
-      GetEvidenceForAdSubframe(frame_host->GetFrameTreeNodeId());
-  EXPECT_TRUE(ad_evidence.is_complete());
-  EXPECT_EQ(ad_evidence.parent_is_ad(), parent_is_ad);
-  EXPECT_EQ(ad_evidence.filter_list_result(), filter_list_result);
-  EXPECT_EQ(ad_evidence.created_by_ad_script(), created_by_ad_script);
-}
-
 }  // namespace subresource_filter
diff --git a/components/subresource_filter/content/browser/subresource_filter_observer_test_utils.h b/components/subresource_filter/content/browser/subresource_filter_observer_test_utils.h
index 9736e05..40fed6e 100644
--- a/components/subresource_filter/content/browser/subresource_filter_observer_test_utils.h
+++ b/components/subresource_filter/content/browser/subresource_filter_observer_test_utils.h
@@ -6,6 +6,7 @@
 #define COMPONENTS_SUBRESOURCE_FILTER_CONTENT_BROWSER_SUBRESOURCE_FILTER_OBSERVER_TEST_UTILS_H_
 
 #include <map>
+#include <set>
 #include <utility>
 
 #include "base/macros.h"
@@ -15,7 +16,6 @@
 #include "components/safe_browsing/core/db/v4_protocol_manager_util.h"
 #include "components/subresource_filter/content/browser/subresource_filter_observer.h"
 #include "components/subresource_filter/content/browser/subresource_filter_observer_manager.h"
-#include "components/subresource_filter/content/common/ad_evidence.h"
 #include "components/subresource_filter/core/common/load_policy.h"
 #include "components/subresource_filter/core/mojom/subresource_filter.mojom.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -45,8 +45,8 @@
   void OnSubframeNavigationEvaluated(
       content::NavigationHandle* navigation_handle,
       LoadPolicy load_policy) override;
-  void OnAdSubframeDetected(content::RenderFrameHost* render_frame_host,
-                            const FrameAdEvidence& ad_evidence) override;
+  void OnIsAdSubframeChanged(content::RenderFrameHost* render_frame_host,
+                             bool is_ad_subframe) override;
 
   // content::WebContentsObserver
   void DidFinishNavigation(
@@ -58,19 +58,9 @@
 
   bool GetIsAdSubframe(int frame_tree_node_id) const;
 
-  // Should only be called on a subframe tagged as an ad.
-  const FrameAdEvidence& GetEvidenceForAdSubframe(int frame_tree_node_id) const;
   base::Optional<mojom::ActivationLevel> GetPageActivationForLastCommittedLoad()
       const;
 
-  // Verifies that the evidence associated with the frame matches the provided
-  // values. Should only be called on subframes tagged as ads.
-  void VerifyEvidenceForAdSubframe(
-      content::RenderFrameHost* frame_host,
-      bool parent_is_ad,
-      FilterListEvidence filter_list_result,
-      ScriptHeuristicEvidence created_by_ad_script) const;
-
   using SafeBrowsingCheck =
       std::pair<safe_browsing::SBThreatType, safe_browsing::ThreatMetadata>;
   base::Optional<SafeBrowsingCheck> GetSafeBrowsingResult(
@@ -78,7 +68,9 @@
 
  private:
   std::map<GURL, LoadPolicy> subframe_load_evaluations_;
-  std::map<int, const FrameAdEvidence> ad_evidence_;
+
+  // Set of FrameTreeNode IDs representing frames tagged as ads.
+  std::set<int> ad_frames_;
 
   std::map<GURL, mojom::ActivationLevel> page_activations_;
   std::map<GURL, SafeBrowsingCheck> safe_browsing_checks_;
diff --git a/components/subresource_filter/content/browser/subresource_filter_test_harness.cc b/components/subresource_filter/content/browser/subresource_filter_test_harness.cc
index bfaea14..99a3347a 100644
--- a/components/subresource_filter/content/browser/subresource_filter_test_harness.cc
+++ b/components/subresource_filter/content/browser/subresource_filter_test_harness.cc
@@ -161,10 +161,11 @@
   return client_->profile_context()->settings_manager();
 }
 
-void SubresourceFilterTestHarness::TagSubframeAsAd(
-    content::RenderFrameHost* render_frame_host) {
+void SubresourceFilterTestHarness::SetIsAdSubframe(
+    content::RenderFrameHost* render_frame_host,
+    bool is_ad_subframe) {
   ContentSubresourceFilterThrottleManager::FromWebContents(web_contents())
-      ->SetFrameAsAdSubframeForTesting(render_frame_host);
+      ->SetIsAdSubframeForTesting(render_frame_host, is_ad_subframe);
 }
 
 }  // namespace subresource_filter
diff --git a/components/subresource_filter/content/browser/subresource_filter_test_harness.h b/components/subresource_filter/content/browser/subresource_filter_test_harness.h
index dffc792..21986bc 100644
--- a/components/subresource_filter/content/browser/subresource_filter_test_harness.h
+++ b/components/subresource_filter/content/browser/subresource_filter_test_harness.h
@@ -75,7 +75,8 @@
     return client_->fake_safe_browsing_database_manager();
   }
 
-  void TagSubframeAsAd(content::RenderFrameHost* render_frame_host);
+  void SetIsAdSubframe(content::RenderFrameHost* render_frame_host,
+                       bool is_ad_subframe);
 
   content::WebContents* web_contents() {
     return content::RenderViewHostTestHarness::web_contents();
diff --git a/components/subresource_filter/content/common/ad_evidence.cc b/components/subresource_filter/content/common/ad_evidence.cc
index 318a3d8a..bd3553e8 100644
--- a/components/subresource_filter/content/common/ad_evidence.cc
+++ b/components/subresource_filter/content/common/ad_evidence.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <algorithm>
+
 #include "components/subresource_filter/content/common/ad_evidence.h"
 
 namespace subresource_filter {
@@ -22,6 +24,11 @@
   }
 }
 
+FilterListEvidence MoreRestrictiveFilterListEvidence(FilterListEvidence a,
+                                                     FilterListEvidence b) {
+  return std::max(a, b);
+}
+
 FrameAdEvidence::FrameAdEvidence(bool parent_is_ad)
     : parent_is_ad_(parent_is_ad) {}
 
@@ -32,9 +39,18 @@
 bool FrameAdEvidence::IndicatesAdSubframe() const {
   DCHECK(is_complete_);
 
+  // We tag a frame as an ad if its parent is one, it was created by ad script
+  // or the frame has ever navigated to an URL matching a blocking rule.
   return parent_is_ad_ ||
-         filter_list_result_ == FilterListEvidence::kMatchedBlockingRule ||
-         created_by_ad_script_ == ScriptHeuristicEvidence::kCreatedByAdScript;
+         created_by_ad_script_ == ScriptHeuristicEvidence::kCreatedByAdScript ||
+         most_restrictive_filter_list_result_ ==
+             FilterListEvidence::kMatchedBlockingRule;
+}
+
+void FrameAdEvidence::UpdateFilterListResult(FilterListEvidence value) {
+  latest_filter_list_result_ = value;
+  most_restrictive_filter_list_result_ = MoreRestrictiveFilterListEvidence(
+      most_restrictive_filter_list_result_, value);
 }
 
 }  // namespace subresource_filter
diff --git a/components/subresource_filter/content/common/ad_evidence.h b/components/subresource_filter/content/common/ad_evidence.h
index a71560c..7a07738 100644
--- a/components/subresource_filter/content/common/ad_evidence.h
+++ b/components/subresource_filter/content/common/ad_evidence.h
@@ -10,17 +10,18 @@
 
 namespace subresource_filter {
 
+// Ordered by increasing severity. See `MoreRestrictiveFilterListEvidence()`.
 enum class FilterListEvidence {
   // No URL the frame has navigated to has been checked against the filter list.
   // This occurs for initial navigations that are either not handled by the
   // network stack or were not committed.
-  kNotChecked,
-  // The last URL checked against the filter list did not match any rules.
-  kMatchedNoRules,
-  // The last URL checked against the filter list matched a blocking rule.
-  kMatchedBlockingRule,
+  kNotChecked = 0,
   // The last URL checked against the filter list matched an allowing rule.
-  kMatchedAllowingRule,
+  kMatchedAllowingRule = 1,
+  // The last URL checked against the filter list did not match any rules.
+  kMatchedNoRules = 2,
+  // The last URL checked against the filter list matched a blocking rule.
+  kMatchedBlockingRule = 3,
 };
 
 enum class ScriptHeuristicEvidence {
@@ -38,6 +39,12 @@
 FilterListEvidence InterpretLoadPolicyAsEvidence(
     const base::Optional<LoadPolicy>& load_policy);
 
+// Returns the stricter of the two load policies, as determined by the order
+// of the FilterListEvidence enum. Should mirror
+// `LoadPolicy::MoreRestrictiveLoadPolicy()`.
+FilterListEvidence MoreRestrictiveFilterListEvidence(FilterListEvidence a,
+                                                     FilterListEvidence b);
+
 // Enumeration of evidence for or against a subframe being an ad.
 class FrameAdEvidence {
  public:
@@ -62,10 +69,16 @@
 
   bool parent_is_ad() const { return parent_is_ad_; }
 
-  FilterListEvidence filter_list_result() const { return filter_list_result_; }
-  void set_filter_list_result(FilterListEvidence value) {
-    filter_list_result_ = value;
+  FilterListEvidence latest_filter_list_result() const {
+    return latest_filter_list_result_;
   }
+  FilterListEvidence most_restrictive_filter_list_result() const {
+    return most_restrictive_filter_list_result_;
+  }
+
+  // Updates the latest filter list result and, if necessary, the most
+  // restrictive filter list result as well.
+  void UpdateFilterListResult(FilterListEvidence value);
 
   ScriptHeuristicEvidence created_by_ad_script() const {
     return created_by_ad_script_;
@@ -85,7 +98,16 @@
   // and, if so, the result of the latest lookup. This is set once the filter
   // list evaluates a frame url, or it is known a frame will not consult the
   // the filter list (and has never done so yet).
-  FilterListEvidence filter_list_result_ = FilterListEvidence::kNotChecked;
+  // TODO(crbug.com/1148058): Update to only include load policies from
+  // navigations that commit.
+  FilterListEvidence latest_filter_list_result_ =
+      FilterListEvidence::kNotChecked;
+
+  // The most restrictive value of `latest_filter_list_result_` ever set. This
+  // tracks whether any URL for this frame has been checked against the filter
+  // list and, if so, the most restrictive result of any lookup.
+  FilterListEvidence most_restrictive_filter_list_result_ =
+      FilterListEvidence::kNotChecked;
 
   // Whether ad script was on the v8 stack at the time this frame was created.
   ScriptHeuristicEvidence created_by_ad_script_ =
diff --git a/components/subresource_filter/content/renderer/subresource_filter_agent.cc b/components/subresource_filter/content/renderer/subresource_filter_agent.cc
index 4316804..378cb5d 100644
--- a/components/subresource_filter/content/renderer/subresource_filter_agent.cc
+++ b/components/subresource_filter/content/renderer/subresource_filter_agent.cc
@@ -237,8 +237,10 @@
     mojom::ActivationStatePtr activation_state,
     blink::mojom::AdFrameType ad_frame_type) {
   activation_state_for_next_document_ = *activation_state;
-  if (ad_frame_type != blink::mojom::AdFrameType::kNonAd) {
+  if (!IsMainFrame()) {
     SetIsAdSubframe(ad_frame_type);
+  } else {
+    DCHECK_EQ(ad_frame_type, blink::mojom::AdFrameType::kNonAd);
   }
 }
 
diff --git a/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc b/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc
index 469b375..e149f333 100644
--- a/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc
+++ b/components/subresource_filter/content/renderer/subresource_filter_agent_unittest.cc
@@ -646,6 +646,10 @@
   ASSERT_NO_FATAL_FAILURE(
       SetTestRulesetToDisallowURLsWithPathSuffix(kTestFirstURLPathSuffix));
 
+  ResetAgent(/*is_main_frame=*/false, /*is_provisional=*/false,
+             /*is_parent_ad_subframe=*/false,
+             /*is_subframe_created_by_ad_script=*/false);
+
   ExpectSubresourceFilterGetsInjected();
   StartLoadAndSetActivationState(
       mojom::ActivationLevel::kDryRun,
@@ -660,6 +664,37 @@
   EXPECT_TRUE(agent()->IsAdSubframe());
 }
 
+TEST_F(SubresourceFilterAgentTest, DryRun_AdSubframeIsUntaggedByBrowser) {
+  ASSERT_NO_FATAL_FAILURE(
+      SetTestRulesetToDisallowURLsWithPathSuffix(kTestFirstURLPathSuffix));
+
+  ResetAgent(/*is_main_frame=*/false, /*is_provisional=*/false,
+             /*is_parent_ad_subframe=*/false,
+             /*is_subframe_created_by_ad_script=*/false);
+
+  // Browser tags the frame as an ad subframe.
+  ExpectSubresourceFilterGetsInjected();
+  StartLoadAndSetActivationState(
+      mojom::ActivationLevel::kDryRun,
+      AdFrameType::kRootAd /* is_associated_with_ad_subframe */);
+  ASSERT_TRUE(::testing::Mock::VerifyAndClearExpectations(agent()));
+
+  EXPECT_TRUE(agent()->IsAdSubframe());
+  ExpectDocumentLoadStatisticsSent();
+  FinishLoad();
+
+  // Browser then untags the frame as an ad subframe.
+  ExpectSubresourceFilterGetsInjected();
+  StartLoadAndSetActivationState(
+      mojom::ActivationLevel::kDryRun,
+      AdFrameType::kNonAd /* is_associated_with_ad_subframe */);
+  ASSERT_TRUE(::testing::Mock::VerifyAndClearExpectations(agent()));
+
+  EXPECT_FALSE(agent()->IsAdSubframe());
+  ExpectDocumentLoadStatisticsSent();
+  FinishLoad();
+}
+
 TEST_F(SubresourceFilterAgentTest, DryRun_SendsFrameIsAdSubframe) {
   ResetAgentWithoutInitialize(/*is_main_frame=*/false, /*is_provisional=*/false,
                               /*is_parent_ad_subframe=*/true,
@@ -730,6 +765,24 @@
   agent_as_rfo()->DidCreateNewDocument();
 }
 
+TEST_F(SubresourceFilterAgentTest,
+       DryRun_SendFrameIsAdSubframeNotSentFromNonAdSubframe) {
+  ResetAgentWithoutInitialize(/*is_main_frame=*/false, /*is_provisional=*/false,
+                              /*is_parent_ad_subframe=*/false,
+                              /*is_subframe_created_by_ad_script*/ false);
+  ExpectSendFrameIsAdSubframe(0);
+  agent()->Initialize();
+  // SendFrameIsAdSubframe() is not sent from Initialize() since the frame is
+  // the main frame, even though it's an ad frame.
+  ::testing::Mock::VerifyAndClearExpectations(agent());
+
+  // Call DidCreateNewDocument and verify that SendFrameIsAdSubframe is
+  // not called from there either.
+  EXPECT_CALL(*agent(), GetDocumentURL())
+      .WillOnce(::testing::Return(GURL("about:blank")));
+  agent_as_rfo()->DidCreateNewDocument();
+}
+
 TEST_F(SubresourceFilterAgentTest, DryRun_SendsSubframeWasCreatedByAdScript) {
   ResetAgentWithoutInitialize(/*is_main_frame=*/false, /*is_provisional=*/false,
                               /*is_parent_ad_subframe=*/false,
diff --git a/components/viz/OWNERS b/components/viz/OWNERS
index 9266937..cbe1272 100644
--- a/components/viz/OWNERS
+++ b/components/viz/OWNERS
@@ -43,9 +43,9 @@
 
 # overlays
 ccameron@chromium.org
-dcastagna@chromium.org
 vasilyt@chromium.org
 magchen@chromium.org
+petermcneeley@chromium.org
 
 # scheduling / begin frames
 sunnyps@chromium.org
diff --git a/components/viz/service/display/overlay_unittest.cc b/components/viz/service/display/overlay_unittest.cc
index a9565798..1f7b4e3 100644
--- a/components/viz/service/display/overlay_unittest.cc
+++ b/components/viz/service/display/overlay_unittest.cc
@@ -1388,6 +1388,35 @@
   EXPECT_EQ(1U, candidate_list.size());
 }
 
+TEST_F(UnderlayTest, ReplacementQuad) {
+  auto pass = CreateRenderPass();
+  CreateFullscreenCandidateQuad(
+      resource_provider_.get(), child_resource_provider_.get(),
+      child_provider_.get(), pass->shared_quad_state_list.back(), pass.get());
+
+  OverlayCandidateList candidate_list;
+  OverlayProcessorInterface::FilterOperationsMap render_pass_filters;
+  OverlayProcessorInterface::FilterOperationsMap render_pass_backdrop_filters;
+  AggregatedRenderPassList pass_list;
+  pass_list.push_back(std::move(pass));
+  SurfaceDamageRectList surface_damage_rect_list;
+
+  overlay_processor_->ProcessForOverlays(
+      resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
+      render_pass_filters, render_pass_backdrop_filters,
+      std::move(surface_damage_rect_list), nullptr, &candidate_list,
+      &damage_rect_, &content_bounds_);
+  ASSERT_EQ(1U, pass_list.size());
+  ASSERT_EQ(1U, pass_list.front()->quad_list.size());
+  EXPECT_EQ(SK_ColorTRANSPARENT, static_cast<SolidColorDrawQuad*>(
+                                     pass_list.front()->quad_list.front())
+                                     ->color);
+  EXPECT_FALSE(pass_list.front()->quad_list.front()->ShouldDrawWithBlending());
+  EXPECT_FALSE(pass_list.front()
+                   ->quad_list.front()
+                   ->shared_quad_state->are_contents_opaque);
+}
+
 TEST_F(UnderlayTest, AllowVerticalFlip) {
   gfx::Rect rect = kOverlayRect;
   rect.set_width(rect.width() / 2);
@@ -2949,6 +2978,34 @@
   }
 }
 
+TEST_F(UnderlayCastTest, ReplacementQuad) {
+  auto pass = CreateRenderPass();
+  CreateVideoHoleDrawQuadAt(pass->shared_quad_state_list.back(), pass.get(),
+                            kOverlayRect);
+
+  OverlayCandidateList candidate_list;
+  OverlayProcessorInterface::FilterOperationsMap render_pass_filters;
+  OverlayProcessorInterface::FilterOperationsMap render_pass_backdrop_filters;
+  AggregatedRenderPassList pass_list;
+  pass_list.push_back(std::move(pass));
+  SurfaceDamageRectList surface_damage_rect_list;
+
+  overlay_processor_->ProcessForOverlays(
+      resource_provider_.get(), &pass_list, GetIdentityColorMatrix(),
+      render_pass_filters, render_pass_backdrop_filters,
+      std::move(surface_damage_rect_list), nullptr, &candidate_list,
+      &damage_rect_, &content_bounds_);
+  ASSERT_EQ(1U, pass_list.size());
+  ASSERT_EQ(1U, pass_list.front()->quad_list.size());
+  EXPECT_EQ(SK_ColorTRANSPARENT, static_cast<SolidColorDrawQuad*>(
+                                     pass_list.front()->quad_list.front())
+                                     ->color);
+  EXPECT_FALSE(pass_list.front()->quad_list.front()->ShouldDrawWithBlending());
+  EXPECT_FALSE(pass_list.front()
+                   ->quad_list.front()
+                   ->shared_quad_state->are_contents_opaque);
+}
+
 TEST_F(UnderlayCastTest, NoOverlayContentBounds) {
   auto pass = CreateRenderPass();
 
diff --git a/content/browser/about_url_loader_factory.cc b/content/browser/about_url_loader_factory.cc
index 59254dc..3e89ca2 100644
--- a/content/browser/about_url_loader_factory.cc
+++ b/content/browser/about_url_loader_factory.cc
@@ -18,7 +18,6 @@
 
 void AboutURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> loader,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
diff --git a/content/browser/about_url_loader_factory.h b/content/browser/about_url_loader_factory.h
index 4cd87e83..d24169b13 100644
--- a/content/browser/about_url_loader_factory.h
+++ b/content/browser/about_url_loader_factory.h
@@ -31,7 +31,6 @@
   ~AboutURLLoaderFactory() override;
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
index ff884d19..fcc8a24 100644
--- a/content/browser/accessibility/dump_accessibility_events_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -29,6 +29,7 @@
 #include "content/public/test/content_browser_test_utils.h"
 #include "content/public/test/test_utils.h"
 #include "content/shell/browser/shell.h"
+#include "net/base/escape.h"
 #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "ui/accessibility/platform/inspect/ax_tree_formatter.h"
 #if defined(OS_WIN)
@@ -201,7 +202,7 @@
     for (auto& event_log : event_logs) {
       if (AXTreeFormatter::MatchesPropertyFilters(scenario_.property_filters,
                                                   event_log, true)) {
-        result.push_back(event_log);
+        result.push_back(net::EscapeNonASCII(event_log));
       }
     }
 
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index f957482..58efe94 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -663,9 +663,6 @@
 
 IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
                        AccessibilityAriaColumnHeader) {
-  // TODO(crbug.com/1152126): Enable extra mac nodes in AXTree.
-  base::AutoReset<bool> disable_extra_mac_nodes(
-      &disable_extra_mac_nodes_for_testing_, true);
   RunAriaTest(FILE_PATH_LITERAL("aria-columnheader.html"));
 }
 
diff --git a/content/browser/android/content_url_loader_factory.cc b/content/browser/android/content_url_loader_factory.cc
index 518dc8b..c98b68d 100644
--- a/content/browser/android/content_url_loader_factory.cc
+++ b/content/browser/android/content_url_loader_factory.cc
@@ -309,7 +309,6 @@
 
 void ContentURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> loader,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
diff --git a/content/browser/android/content_url_loader_factory.h b/content/browser/android/content_url_loader_factory.h
index f3bb9b9..2b776a6 100644
--- a/content/browser/android/content_url_loader_factory.h
+++ b/content/browser/android/content_url_loader_factory.h
@@ -37,7 +37,6 @@
   ~ContentURLLoaderFactory() override;
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/content/browser/appcache/appcache_browsertest.cc b/content/browser/appcache/appcache_browsertest.cc
index 8788373..7fa3a33 100644
--- a/content/browser/appcache/appcache_browsertest.cc
+++ b/content/browser/appcache/appcache_browsertest.cc
@@ -247,7 +247,6 @@
 
     void CreateLoaderAndStart(
         mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
-        int32_t routing_id,
         int32_t request_id,
         uint32_t options,
         const network::ResourceRequest& request,
@@ -256,7 +255,7 @@
         override {
       client_->intercepted_request_map_[request.url] = request_initiator_;
       target_factory_->CreateLoaderAndStart(
-          std::move(loader_receiver), routing_id, request_id, options, request,
+          std::move(loader_receiver), request_id, options, request,
           std::move(client), traffic_annotation);
     }
 
diff --git a/content/browser/appcache/appcache_subresource_url_factory.cc b/content/browser/appcache/appcache_subresource_url_factory.cc
index ddddbe2..f177fc0 100644
--- a/content/browser/appcache/appcache_subresource_url_factory.cc
+++ b/content/browser/appcache/appcache_subresource_url_factory.cc
@@ -46,7 +46,6 @@
  public:
   SubresourceLoader(
       mojo::PendingReceiver<network::mojom::URLLoader> url_loader_receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
@@ -57,7 +56,6 @@
       : remote_receiver_(this, std::move(url_loader_receiver)),
         remote_client_(std::move(client)),
         request_(request),
-        routing_id_(routing_id),
         request_id_(request_id),
         options_(options),
         traffic_annotation_(annotation),
@@ -118,8 +116,8 @@
   void CreateAndStartNetworkLoader() {
     DCHECK(!appcache_loader_);
     network_loader_factory_->CreateLoaderAndStart(
-        network_loader_.BindNewPipeAndPassReceiver(), routing_id_, request_id_,
-        options_, request_, local_client_receiver_.BindNewPipeAndPassRemote(),
+        network_loader_.BindNewPipeAndPassReceiver(), request_id_, options_,
+        request_, local_client_receiver_.BindNewPipeAndPassRemote(),
         traffic_annotation_);
     if (has_set_priority_)
       network_loader_->SetPriority(priority_, intra_priority_value_);
@@ -293,7 +291,6 @@
   mojo::Remote<network::mojom::URLLoaderClient> remote_client_;
 
   network::ResourceRequest request_;
-  int32_t routing_id_;
   int32_t request_id_;
   uint32_t options_;
   net::MutableNetworkTrafficAnnotationTag traffic_annotation_;
@@ -365,7 +362,6 @@
 
 void AppCacheSubresourceURLFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> url_loader_receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
@@ -393,8 +389,8 @@
     return;
   }
 
-  new SubresourceLoader(std::move(url_loader_receiver), routing_id, request_id,
-                        options, request, std::move(client), traffic_annotation,
+  new SubresourceLoader(std::move(url_loader_receiver), request_id, options,
+                        request, std::move(client), traffic_annotation,
                         appcache_host_, network_loader_factory_);
 }
 
diff --git a/content/browser/appcache/appcache_subresource_url_factory.h b/content/browser/appcache/appcache_subresource_url_factory.h
index 2c8a063..fd4fcfc 100644
--- a/content/browser/appcache/appcache_subresource_url_factory.h
+++ b/content/browser/appcache/appcache_subresource_url_factory.h
@@ -43,7 +43,6 @@
   // network::mojom::URLLoaderFactory implementation.
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> url_loader_receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/content/browser/appcache/appcache_update_url_loader_request.cc b/content/browser/appcache/appcache_update_url_loader_request.cc
index 4a2c5a7..c116c42 100644
--- a/content/browser/appcache/appcache_update_url_loader_request.cc
+++ b/content/browser/appcache/appcache_update_url_loader_request.cc
@@ -60,7 +60,7 @@
     return;
   partition_->GetURLLoaderFactoryForBrowserProcessWithCORBEnabled()
       ->CreateLoaderAndStart(
-          url_loader_.BindNewPipeAndPassReceiver(), -1, -1,
+          url_loader_.BindNewPipeAndPassReceiver(), -1,
           network::mojom::kURLLoadOptionSendSSLInfoWithResponse, request_,
           client_receiver_.BindNewPipeAndPassRemote(),
           net::MutableNetworkTrafficAnnotationTag(kAppCacheTrafficAnnotation));
diff --git a/content/browser/blob_storage/blob_url_unittest.cc b/content/browser/blob_storage/blob_url_unittest.cc
index bbbf1b9d..0a7e8fb 100644
--- a/content/browser/blob_storage/blob_url_unittest.cc
+++ b/content/browser/blob_storage/blob_url_unittest.cc
@@ -208,7 +208,7 @@
     mojo::PendingRemote<network::mojom::URLLoader> url_loader;
     network::TestURLLoaderClient url_loader_client;
     url_loader_factory->CreateLoaderAndStart(
-        url_loader.InitWithNewPipeAndPassReceiver(), 0, 0,
+        url_loader.InitWithNewPipeAndPassReceiver(), 0,
         network::mojom::kURLLoadOptionNone, request,
         url_loader_client.CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
diff --git a/content/browser/data_url_loader_factory.cc b/content/browser/data_url_loader_factory.cc
index b545cce..d7f64d04 100644
--- a/content/browser/data_url_loader_factory.cc
+++ b/content/browser/data_url_loader_factory.cc
@@ -49,7 +49,6 @@
 
 void DataURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> loader,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
diff --git a/content/browser/data_url_loader_factory.h b/content/browser/data_url_loader_factory.h
index f01085b..570123d 100644
--- a/content/browser/data_url_loader_factory.h
+++ b/content/browser/data_url_loader_factory.h
@@ -41,7 +41,6 @@
   ~DataURLLoaderFactory() override;
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/content/browser/device/device_service.cc b/content/browser/device/device_service.cc
index 7ae7c84..ca5bd15 100644
--- a/content/browser/device/device_service.cc
+++ b/content/browser/device/device_service.cc
@@ -41,7 +41,6 @@
   // mojom::URLLoaderFactory implementation:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& url_request,
@@ -53,8 +52,8 @@
     if (!factory)
       return;
 
-    factory->CreateLoaderAndStart(std::move(receiver), routing_id, request_id,
-                                  options, url_request, std::move(client),
+    factory->CreateLoaderAndStart(std::move(receiver), request_id, options,
+                                  url_request, std::move(client),
                                   traffic_annotation);
   }
 
diff --git a/content/browser/devtools/devtools_url_loader_interceptor.cc b/content/browser/devtools/devtools_url_loader_interceptor.cc
index fa64ad2..e5f9187 100644
--- a/content/browser/devtools/devtools_url_loader_interceptor.cc
+++ b/content/browser/devtools/devtools_url_loader_interceptor.cc
@@ -136,18 +136,15 @@
 
 struct CreateLoaderParameters {
   CreateLoaderParameters(
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       network::ResourceRequest request,
       net::MutableNetworkTrafficAnnotationTag traffic_annotation)
-      : routing_id(routing_id),
-        request_id(request_id),
+      : request_id(request_id),
         options(options),
         request(request),
         traffic_annotation(traffic_annotation) {}
 
-  const int32_t routing_id;
   const int32_t request_id;
   const uint32_t options;
   network::ResourceRequest request;
@@ -482,7 +479,6 @@
   // network::mojom::URLLoaderFactory implementation
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
@@ -541,7 +537,6 @@
 
 void DevToolsURLLoaderFactoryProxy::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> loader,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
@@ -551,13 +546,13 @@
 
   DevToolsURLLoaderInterceptor* interceptor = interceptor_.get();
   if (!interceptor_ || request.url.SchemeIs(url::kDataScheme)) {
-    target_factory_->CreateLoaderAndStart(
-        std::move(loader), routing_id, request_id, options, request,
-        std::move(client), traffic_annotation);
+    target_factory_->CreateLoaderAndStart(std::move(loader), request_id,
+                                          options, request, std::move(client),
+                                          traffic_annotation);
     return;
   }
   auto creation_params = std::make_unique<CreateLoaderParameters>(
-      routing_id, request_id, options, request, traffic_annotation);
+      request_id, options, request, traffic_annotation);
   mojo::PendingRemote<network::mojom::URLLoaderFactory> factory_clone;
   target_factory_->Clone(factory_clone.InitWithNewPipeAndPassReceiver());
   mojo::PendingRemote<network::mojom::CookieManager> cookie_manager_clone;
@@ -1205,9 +1200,8 @@
   state_ = State::kRequestSent;
 
   target_factory_->CreateLoaderAndStart(
-      loader_.BindNewPipeAndPassReceiver(), create_loader_params_->routing_id,
-      create_loader_params_->request_id, create_loader_params_->options,
-      create_loader_params_->request,
+      loader_.BindNewPipeAndPassReceiver(), create_loader_params_->request_id,
+      create_loader_params_->options, create_loader_params_->request,
       client_receiver_.BindNewPipeAndPassRemote(),
       create_loader_params_->traffic_annotation);
   client_receiver_.set_disconnect_handler(
@@ -1544,14 +1538,13 @@
 
 void DevToolsURLLoaderFactoryAdapter::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> loader,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
     mojo::PendingRemote<network::mojom::URLLoaderClient> client,
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
-  factory_->CreateLoaderAndStart(std::move(loader), routing_id, request_id,
-                                 options, request, std::move(client),
+  factory_->CreateLoaderAndStart(std::move(loader), request_id, options,
+                                 request, std::move(client),
                                  traffic_annotation);
 }
 
diff --git a/content/browser/devtools/devtools_url_loader_interceptor.h b/content/browser/devtools/devtools_url_loader_interceptor.h
index 35befa2..5b28332 100644
--- a/content/browser/devtools/devtools_url_loader_interceptor.h
+++ b/content/browser/devtools/devtools_url_loader_interceptor.h
@@ -263,7 +263,6 @@
   // network::mojom::URLLoaderFactory implementation
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/content/browser/file_system/file_system_url_loader_factory.cc b/content/browser/file_system/file_system_url_loader_factory.cc
index 7a63e44..62f80d48 100644
--- a/content/browser/file_system/file_system_url_loader_factory.cc
+++ b/content/browser/file_system/file_system_url_loader_factory.cc
@@ -616,7 +616,6 @@
  private:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/content/browser/file_system/file_system_url_loader_factory_browsertest.cc b/content/browser/file_system/file_system_url_loader_factory_browsertest.cc
index 121614c..eadf46e 100644
--- a/content/browser/file_system/file_system_url_loader_factory_browsertest.cc
+++ b/content/browser/file_system/file_system_url_loader_factory_browsertest.cc
@@ -473,7 +473,7 @@
     auto client = std::make_unique<network::TestURLLoaderClient>();
     loader_.reset();
     factory->CreateLoaderAndStart(
-        loader_.BindNewPipeAndPassReceiver(), 0, 0,
+        loader_.BindNewPipeAndPassReceiver(), 0,
         network::mojom::kURLLoadOptionNone, request, client->CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
diff --git a/content/browser/loader/file_url_loader_factory.cc b/content/browser/loader/file_url_loader_factory.cc
index 824c198f..96e8e5a6 100644
--- a/content/browser/loader/file_url_loader_factory.cc
+++ b/content/browser/loader/file_url_loader_factory.cc
@@ -804,7 +804,6 @@
 
 void FileURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> loader,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
diff --git a/content/browser/loader/file_url_loader_factory.h b/content/browser/loader/file_url_loader_factory.h
index e4b8910c..26eed2c 100644
--- a/content/browser/loader/file_url_loader_factory.h
+++ b/content/browser/loader/file_url_loader_factory.h
@@ -52,7 +52,6 @@
   ~FileURLLoaderFactory() override;
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc
index cf3a090..f349a44 100644
--- a/content/browser/loader/navigation_url_loader_impl.cc
+++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -367,9 +367,9 @@
     url_loader_ = blink::ThrottlingURLLoader::CreateLoaderAndStart(
         base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
             std::move(factory_for_webui)),
-        CreateURLLoaderThrottles(), 0 /* routing_id */,
-        global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
-        resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
+        CreateURLLoaderThrottles(), global_request_id_.request_id,
+        network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
+        kNavigationUrlLoaderTrafficAnnotation,
         base::ThreadTaskRunnerHandle::Get());
     return;
   }
@@ -381,9 +381,9 @@
     url_loader_ = blink::ThrottlingURLLoader::CreateLoaderAndStart(
         network::SharedURLLoaderFactory::Create(
             std::move(request_info_->blob_url_loader_factory)),
-        CreateURLLoaderThrottles(), 0 /* routing_id */,
-        global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
-        resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
+        CreateURLLoaderThrottles(), global_request_id_.request_id,
+        network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
+        kNavigationUrlLoaderTrafficAnnotation,
         base::ThreadTaskRunnerHandle::Get());
     return;
   }
@@ -512,9 +512,8 @@
       url_loader_->ResetForFollowRedirect();
     url_loader_ = blink::ThrottlingURLLoader::CreateLoaderAndStart(
         std::move(single_request_factory), std::move(throttles),
-        frame_tree_node_id_, global_request_id_.request_id,
-        network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
-        kNavigationUrlLoaderTrafficAnnotation,
+        global_request_id_.request_id, network::mojom::kURLLoadOptionNone,
+        resource_request_.get(), this, kNavigationUrlLoaderTrafficAnnotation,
         base::ThreadTaskRunnerHandle::Get());
 
     subresource_loader_params_ =
@@ -572,7 +571,7 @@
   scoped_refptr<network::SharedURLLoaderFactory> factory =
       PrepareForNonInterceptedRequest(&options);
   url_loader_ = blink::ThrottlingURLLoader::CreateLoaderAndStart(
-      std::move(factory), CreateURLLoaderThrottles(), frame_tree_node_id_,
+      std::move(factory), CreateURLLoaderThrottles(),
       global_request_id_.request_id, options, resource_request_.get(),
       this /* client */, kNavigationUrlLoaderTrafficAnnotation,
       base::ThreadTaskRunnerHandle::Get());
@@ -597,7 +596,7 @@
     DCHECK(response_loader_receiver_.is_bound());
     response_loader_receiver_.reset();
     url_loader_ = blink::ThrottlingURLLoader::CreateLoaderAndStart(
-        std::move(factory), CreateURLLoaderThrottles(), frame_tree_node_id_,
+        std::move(factory), CreateURLLoaderThrottles(),
         global_request_id_.request_id, options, resource_request_.get(),
         this /* client */, kNavigationUrlLoaderTrafficAnnotation,
         base::ThreadTaskRunnerHandle::Get());
diff --git a/content/browser/loader/prefetch_url_loader.cc b/content/browser/loader/prefetch_url_loader.cc
index 22d21945..8f842070 100644
--- a/content/browser/loader/prefetch_url_loader.cc
+++ b/content/browser/loader/prefetch_url_loader.cc
@@ -31,7 +31,6 @@
 }  // namespace
 
 PrefetchURLLoader::PrefetchURLLoader(
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     int frame_tree_node_id,
@@ -84,7 +83,7 @@
   }
 
   network_loader_factory_->CreateLoaderAndStart(
-      loader_.BindNewPipeAndPassReceiver(), routing_id, request_id, options,
+      loader_.BindNewPipeAndPassReceiver(), request_id, options,
       resource_request_, client_receiver_.BindNewPipeAndPassRemote(),
       traffic_annotation);
   client_receiver_.set_disconnect_handler(base::BindOnce(
diff --git a/content/browser/loader/prefetch_url_loader.h b/content/browser/loader/prefetch_url_loader.h
index 0d214be..ffa21b4 100644
--- a/content/browser/loader/prefetch_url_loader.h
+++ b/content/browser/loader/prefetch_url_loader.h
@@ -61,7 +61,6 @@
   // additionally create a request (e.g. for fetching certificate if the
   // prefetch was for a signed exchange).
   PrefetchURLLoader(
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       int frame_tree_node_id,
diff --git a/content/browser/loader/prefetch_url_loader_service.cc b/content/browser/loader/prefetch_url_loader_service.cc
index 1e2bc1e..5211d55 100644
--- a/content/browser/loader/prefetch_url_loader_service.cc
+++ b/content/browser/loader/prefetch_url_loader_service.cc
@@ -106,7 +106,6 @@
 
 void PrefetchURLLoaderService::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& resource_request_in,
@@ -209,7 +208,7 @@
   // TODO(kinuko): Revisit this.
   mojo::MakeSelfOwnedReceiver(
       std::make_unique<PrefetchURLLoader>(
-          routing_id, request_id, options, current_context.frame_tree_node_id,
+          request_id, options, current_context.frame_tree_node_id,
           resource_request,
           resource_request.trusted_params
               ? resource_request.trusted_params->isolation_info
diff --git a/content/browser/loader/prefetch_url_loader_service.h b/content/browser/loader/prefetch_url_loader_service.h
index fb693e1..2107949 100644
--- a/content/browser/loader/prefetch_url_loader_service.h
+++ b/content/browser/loader/prefetch_url_loader_service.h
@@ -76,7 +76,6 @@
   // network::mojom::URLLoaderFactory:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& resource_request_in,
diff --git a/content/browser/loader/single_request_url_loader_factory.cc b/content/browser/loader/single_request_url_loader_factory.cc
index 4f2ee51e..b5c4e00 100644
--- a/content/browser/loader/single_request_url_loader_factory.cc
+++ b/content/browser/loader/single_request_url_loader_factory.cc
@@ -84,7 +84,6 @@
 
 void SingleRequestURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> loader,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
diff --git a/content/browser/loader/single_request_url_loader_factory.h b/content/browser/loader/single_request_url_loader_factory.h
index 9a2bc73..b7278031 100644
--- a/content/browser/loader/single_request_url_loader_factory.h
+++ b/content/browser/loader/single_request_url_loader_factory.h
@@ -32,7 +32,6 @@
   // SharedURLLoaderFactory:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/content/browser/network_service_browsertest.cc b/content/browser/network_service_browsertest.cc
index b10571c..5cc2ff3 100644
--- a/content/browser/network_service_browsertest.cc
+++ b/content/browser/network_service_browsertest.cc
@@ -502,7 +502,6 @@
    public:
     void CreateLoaderAndStart(
         mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-        int32_t routing_id,
         int32_t request_id,
         uint32_t options,
         const network::ResourceRequest& resource_request,
diff --git a/content/browser/permissions/permission_service_context.cc b/content/browser/permissions/permission_service_context.cc
index c3ab8129..0e4ed37 100644
--- a/content/browser/permissions/permission_service_context.cc
+++ b/content/browser/permissions/permission_service_context.cc
@@ -57,19 +57,15 @@
   int id_ = 0;
 };
 
+RENDER_DOCUMENT_HOST_USER_DATA_KEY_IMPL(PermissionServiceContext)
+
 PermissionServiceContext::PermissionServiceContext(
     RenderFrameHost* render_frame_host)
-    : WebContentsObserver(WebContents::FromRenderFrameHost(render_frame_host)),
-      render_frame_host_(render_frame_host),
-      render_process_host_(nullptr) {
-}
+    : render_frame_host_(render_frame_host), render_process_host_(nullptr) {}
 
 PermissionServiceContext::PermissionServiceContext(
     RenderProcessHost* render_process_host)
-    : WebContentsObserver(nullptr),
-      render_frame_host_(nullptr),
-      render_process_host_(render_process_host) {
-}
+    : render_frame_host_(nullptr), render_process_host_(render_process_host) {}
 
 PermissionServiceContext::~PermissionServiceContext() {
 }
@@ -124,40 +120,9 @@
   DCHECK_EQ(1u, erased);
 }
 
-void PermissionServiceContext::RenderFrameHostChanged(
-    RenderFrameHost* old_host,
-    RenderFrameHost* new_host) {
-  CloseBindings(old_host);
-}
-
-void PermissionServiceContext::FrameDeleted(
-    RenderFrameHost* render_frame_host) {
-  CloseBindings(render_frame_host);
-}
-
-void PermissionServiceContext::DidFinishNavigation(
-    NavigationHandle* navigation_handle) {
-  if (!navigation_handle->HasCommitted() || navigation_handle->IsSameDocument())
-    return;
-
-  CloseBindings(navigation_handle->GetRenderFrameHost());
-}
-
-void PermissionServiceContext::CloseBindings(
-    RenderFrameHost* render_frame_host) {
-  DCHECK(render_frame_host_);
-  if (render_frame_host != render_frame_host_)
-    return;
-
-  services_.Clear();
-  subscriptions_.clear();
-}
-
 BrowserContext* PermissionServiceContext::GetBrowserContext() const {
-  // web_contents() may return nullptr during teardown, or when showing
-  // an interstitial.
-  if (web_contents())
-    return web_contents()->GetBrowserContext();
+  if (render_frame_host_)
+    return render_frame_host_->GetBrowserContext();
 
   if (render_process_host_)
     return render_process_host_->GetBrowserContext();
@@ -166,8 +131,12 @@
 }
 
 GURL PermissionServiceContext::GetEmbeddingOrigin() const {
-  return web_contents() ? web_contents()->GetLastCommittedURL().GetOrigin()
-                        : GURL();
+  // TODO(https://crbug.com/1170277): This will return the wrong origin for a
+  // non primary FrameTree.
+  WebContents* web_contents =
+      WebContents::FromRenderFrameHost(render_frame_host_);
+  return web_contents ? web_contents->GetLastCommittedURL().GetOrigin()
+                      : GURL();
 }
 
 }  // namespace content
diff --git a/content/browser/permissions/permission_service_context.h b/content/browser/permissions/permission_service_context.h
index 4f93be5..3feec2c7 100644
--- a/content/browser/permissions/permission_service_context.h
+++ b/content/browser/permissions/permission_service_context.h
@@ -10,11 +10,12 @@
 
 #include "content/common/content_export.h"
 #include "content/public/browser/permission_type.h"
-#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/render_document_host_user_data.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/unique_receiver_set.h"
 #include "third_party/blink/public/mojom/permissions/permission.mojom.h"
+#include "url/gurl.h"
 
 namespace url {
 class Origin;
@@ -22,6 +23,7 @@
 
 namespace content {
 
+class BrowserContext;
 class RenderFrameHost;
 class RenderProcessHost;
 
@@ -30,9 +32,13 @@
 // There is one PermissionServiceContext per RenderFrameHost/RenderProcessHost
 // which owns it. It then owns all PermissionServiceImpl associated to their
 // owner.
-class CONTENT_EXPORT PermissionServiceContext : public WebContentsObserver {
+//
+// PermissionServiceContext instances associated with a RenderFrameHost must be
+// created via the RenderDocumentHostUserData static factories, as these
+// instances are deleted when a new document is commited.
+class CONTENT_EXPORT PermissionServiceContext
+    : public RenderDocumentHostUserData<PermissionServiceContext> {
  public:
-  explicit PermissionServiceContext(RenderFrameHost* render_frame_host);
   explicit PermissionServiceContext(RenderProcessHost* render_process_host);
   PermissionServiceContext(const PermissionServiceContext&) = delete;
   PermissionServiceContext& operator=(const PermissionServiceContext&) = delete;
@@ -66,14 +72,11 @@
 
  private:
   class PermissionSubscription;
-
-  // WebContentsObserver
-  void RenderFrameHostChanged(RenderFrameHost* old_host,
-                              RenderFrameHost* new_host) override;
-  void FrameDeleted(RenderFrameHost* render_frame_host) override;
-  void DidFinishNavigation(NavigationHandle* navigation_handle) override;
-
-  void CloseBindings(RenderFrameHost* render_frame_host);
+  friend class RenderDocumentHostUserData<PermissionServiceContext>;
+  RENDER_DOCUMENT_HOST_USER_DATA_KEY_DECL();
+  // Use RenderDocumentHostUserData static methods to create instances attached
+  // to a RenderFrameHost.
+  explicit PermissionServiceContext(RenderFrameHost* render_frame_host);
 
   RenderFrameHost* const render_frame_host_;
   RenderProcessHost* const render_process_host_;
diff --git a/content/browser/renderer_host/frame_tree_node.cc b/content/browser/renderer_host/frame_tree_node.cc
index 3d1e37e9..0f296d0 100644
--- a/content/browser/renderer_host/frame_tree_node.cc
+++ b/content/browser/renderer_host/frame_tree_node.cc
@@ -792,13 +792,11 @@
 }
 
 void FrameTreeNode::SetAdFrameType(blink::mojom::AdFrameType ad_frame_type) {
-  DCHECK_NE(ad_frame_type, blink::mojom::AdFrameType::kNonAd);
-  if (replication_state_->ad_frame_type == blink::mojom::AdFrameType::kNonAd) {
-    replication_state_->ad_frame_type = ad_frame_type;
-    render_manager()->OnDidSetAdFrameType(ad_frame_type);
-  } else {
-    DCHECK_EQ(ad_frame_type, replication_state_->ad_frame_type);
-  }
+  if (ad_frame_type == replication_state_->ad_frame_type)
+    return;
+
+  replication_state_->ad_frame_type = ad_frame_type;
+  render_manager()->OnDidSetAdFrameType(ad_frame_type);
 }
 
 void FrameTreeNode::SetInitialPopupURL(const GURL& initial_popup_url) {
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index 6dc2e7296..a4f8f71 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -1755,6 +1755,148 @@
 void NavigationRequest::ResetForCrossDocumentRestart() {
   DCHECK(IsSameDocument());
 
+  // TODO(crbug.com/1188513): A same document history navigation was performed
+  // but the renderer thinks there's a different document loaded. Where did
+  // this navigation come from?
+  if (common_params_->navigation_type ==
+      mojom::NavigationType::HISTORY_SAME_DOCUMENT) {
+    NavigationControllerImpl* const controller = GetNavigationController();
+
+    // Dump stuff from NavigationRequest.
+    SCOPED_CRASH_KEY_BOOL("history_bad_seq", "is_same_document",
+                          IsSameDocument());
+    SCOPED_CRASH_KEY_BOOL("history_bad_seq", "in_main_frame", IsInMainFrame());
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "request_item_seq",
+                            frame_entry_item_sequence_number_);
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "request_doc_seq",
+                            frame_entry_document_sequence_number_);
+    SCOPED_CRASH_KEY_BOOL(
+        "history_bad_seq", "in_new_child",
+        common_params_->is_history_navigation_in_new_child_frame);
+
+    // Compare the NavigationEntry id from the NavigationRequest, the commit
+    // sent to the renderer (and returned from it), and the RenderFrameHost.
+    int request_nav_entry_id = nav_entry_id_;
+    int commit_nav_entry_id = commit_params_->nav_entry_id;
+    int rfh_nav_entry_id = render_frame_host_->nav_entry_id();
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "request_nav_entry_id",
+                            request_nav_entry_id);
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "commit_nav_entry_id",
+                            commit_nav_entry_id);
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "rfh_nav_entry_id",
+                            rfh_nav_entry_id);
+
+    // Compare the NavigationEntry existence from the NavigationRequest, the
+    // commit sent to the renderer (and returned from it), and the
+    // RenderFrameHost.
+    auto* request_entry =
+        static_cast<NavigationEntryImpl*>(GetNavigationEntry());
+    NavigationEntryImpl* commit_entry =
+        controller->GetEntryWithUniqueID(commit_nav_entry_id);
+    NavigationEntryImpl* rfh_entry =
+        controller->GetEntryWithUniqueID(rfh_nav_entry_id);
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "request_entry",
+                            reinterpret_cast<uintptr_t>(request_entry));
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "commit_entry",
+                            reinterpret_cast<uintptr_t>(commit_entry));
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "rfh_entry",
+                            reinterpret_cast<uintptr_t>(rfh_entry));
+
+    FrameNavigationEntry* request_frame_entry = nullptr;
+    FrameNavigationEntry* commit_frame_entry = nullptr;
+    FrameNavigationEntry* rfh_frame_entry = nullptr;
+
+    if (request_entry) {
+      request_frame_entry =
+          request_entry->GetFrameEntry(render_frame_host_->frame_tree_node());
+    }
+    if (commit_entry) {
+      commit_frame_entry =
+          commit_entry->GetFrameEntry(render_frame_host_->frame_tree_node());
+    }
+    if (rfh_entry) {
+      request_frame_entry =
+          rfh_entry->GetFrameEntry(render_frame_host_->frame_tree_node());
+    }
+
+    // Compare the FrameNavigationEntry existence.
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "request_frameentry",
+                            reinterpret_cast<uintptr_t>(request_frame_entry));
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "commit_frameentry",
+                            reinterpret_cast<uintptr_t>(commit_frame_entry));
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "rfh_frameentry",
+                            reinterpret_cast<uintptr_t>(rfh_frame_entry));
+
+    // Dump stuff from each FrameNavigationEntry.
+    int request_entry_doc_seq = 0;
+    int request_entry_item_seq = 0;
+    int32_t request_entry_site_instance_id = 0;
+    int32_t request_entry_browsing_instance_id = 0;
+    int commit_entry_doc_seq = 0;
+    int commit_entry_item_seq = 0;
+    int32_t commit_entry_site_instance_id = 0;
+    int32_t commit_entry_browsing_instance_id = 0;
+    int rfh_entry_doc_seq = 0;
+    int rfh_entry_item_seq = 0;
+    int32_t rfh_entry_site_instance_id = 0;
+    int32_t rfh_entry_browsing_instance_id = 0;
+
+    if (request_frame_entry) {
+      request_entry_doc_seq = request_frame_entry->document_sequence_number();
+      request_entry_item_seq = request_frame_entry->item_sequence_number();
+      if (SiteInstanceImpl* inst = request_frame_entry->site_instance()) {
+        request_entry_site_instance_id = inst->GetId();
+        request_entry_browsing_instance_id = inst->GetBrowsingInstanceId();
+      }
+    }
+    if (commit_frame_entry) {
+      commit_entry_doc_seq = commit_frame_entry->document_sequence_number();
+      commit_entry_item_seq = commit_frame_entry->item_sequence_number();
+      if (SiteInstanceImpl* inst = commit_frame_entry->site_instance()) {
+        commit_entry_site_instance_id = inst->GetId();
+        commit_entry_browsing_instance_id = inst->GetBrowsingInstanceId();
+      }
+    }
+    if (rfh_frame_entry) {
+      rfh_entry_doc_seq = rfh_frame_entry->document_sequence_number();
+      rfh_entry_item_seq = rfh_frame_entry->item_sequence_number();
+      if (SiteInstanceImpl* inst = rfh_frame_entry->site_instance()) {
+        rfh_entry_site_instance_id = inst->GetId();
+        rfh_entry_browsing_instance_id = inst->GetBrowsingInstanceId();
+      }
+    }
+
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "request_entry_doc_seq",
+                            request_entry_doc_seq);
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "commit_entry_doc_seq",
+                            commit_entry_doc_seq);
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "rfh_entry_doc_seq",
+                            rfh_entry_doc_seq);
+
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "request_entry_item_seq",
+                            request_entry_item_seq);
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "commit_entry_item_seq",
+                            commit_entry_item_seq);
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "rfh_entry_item_seq",
+                            rfh_entry_item_seq);
+
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "request_site_inst",
+                            request_entry_site_instance_id);
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "commit_site_inst",
+                            commit_entry_site_instance_id);
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "rfh_site_inst",
+                            rfh_entry_site_instance_id);
+
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "request_browsing_inst",
+                            request_entry_browsing_instance_id);
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "commit_browsing_inst",
+                            commit_entry_browsing_instance_id);
+    SCOPED_CRASH_KEY_NUMBER("history_bad_seq", "rfh_browsing_inst",
+                            rfh_entry_browsing_instance_id);
+
+    base::debug::DumpWithoutCrashing();
+  }
+
   // Reset the NavigationHandle, which is now incorrectly marked as
   // same-document. Ensure |loader_| does not exist as it can hold raw pointers
   // to objects owned by the handle (see the comment in the header).
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 839f683..492c0767 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -8338,11 +8338,8 @@
 
 void RenderFrameHostImpl::CreatePermissionService(
     mojo::PendingReceiver<blink::mojom::PermissionService> receiver) {
-  if (!permission_service_context_)
-    permission_service_context_ =
-        std::make_unique<PermissionServiceContext>(this);
-
-  permission_service_context_->CreateService(std::move(receiver));
+  PermissionServiceContext::GetOrCreateForCurrentDocument(this)->CreateService(
+      std::move(receiver));
 }
 
 void RenderFrameHostImpl::GetAuthenticator(
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h
index 97b6e88..6ea24fc 100644
--- a/content/browser/renderer_host/render_frame_host_impl.h
+++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -218,7 +218,6 @@
 class NavigationRequest;
 class PeerConnectionTrackerHost;
 class PepperPluginInstanceHost;
-class PermissionServiceContext;
 class Portal;
 class PrefetchedSignedExchangeCache;
 class PresentationServiceImpl;
@@ -3025,10 +3024,6 @@
   // already exists it will still be used.
   bool no_create_browser_accessibility_manager_for_testing_ = false;
 
-  // Context shared for each mojom::PermissionService instance created for this
-  // RFH.
-  std::unique_ptr<PermissionServiceContext> permission_service_context_;
-
   // Holder of Mojo connection with ImageDownloader service in Blink.
   mojo::Remote<blink::mojom::ImageDownloader> mojo_image_downloader_;
 
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc
index 8423b85..cd71394 100644
--- a/content/browser/renderer_host/render_frame_host_manager.cc
+++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -813,6 +813,13 @@
   // since we did load the current document, but we don't want to reload it if
   // that is the case. See crbug.com/1125106.
   DCHECK(!request->IsSameDocument());
+  // TODO(crbug.com/1188513): Verify that we're not resetting the document
+  // sequence number in a same-document navigation. This method will reset it
+  // if the site instance changed. But this method should not be called for a
+  // same document history navigation. Change back to a DCHECK() once this is
+  // resolved.
+  if (request->IsSameDocument())
+    base::debug::DumpWithoutCrashing();
 
   // Even though prerendering is considered an inactive state (i.e., not allowed
   // to show any UI changes) it is still allowed to navigate, fetch, load and
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
index 9f4dc39..5b3d5b68 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -19,6 +19,7 @@
 #include "base/check.h"
 #include "base/command_line.h"
 #include "base/debug/alias.h"
+#include "base/debug/dump_without_crashing.h"
 #include "base/files/file_path.h"
 #include "base/hash/hash.h"
 #include "base/i18n/rtl.h"
@@ -1985,8 +1986,99 @@
   // Use GetScreenInfo here to retain legacy behavior for the current screen.
   blink::ScreenInfo current_screen_info;
   GetScreenInfo(&current_screen_info);
-  // TODO(enne): Temporary workaround for http://crbug.com/1183146.
+
+  // TODO(enne): RenderWidgetHostViewMac caches the ScreenInfo and chooses
+  // not to change it during resizes.  This means that the RWHV::GetScreenInfo
+  // returned might be stale wrt GetAllDisplays() below.  Fix this.
+  // For now, just return the legacy screen info for mac.
+#if defined(OS_MAC)
   return blink::ScreenInfos(current_screen_info);
+#else
+
+  // If this widget has not been connected to a view yet (or has been
+  // disconnected), the display code may be using a fake primary display.
+  // In these cases, temporarily return the legacy screen info until
+  // it is connected and visual properties updates this correctly.
+  if (!view_) {
+    return blink::ScreenInfos(current_screen_info);
+  }
+
+  // TODO(enne): add ScreenInfos to FrameVisualProperties and store these
+  // on CrossProcessFrameConnector.  For now, only return the legacy
+  // screen info for any child widgets to avoid races between visual
+  // property propagation of legacy screen info vs GetAllDisplays.
+  // In the future, child frames should use screen_infos from the connector.
+  if (!view_->IsRenderWidgetHostViewChildFrame()) {
+    return blink::ScreenInfos(current_screen_info);
+  }
+
+  display::Screen* screen = display::Screen::GetScreen();
+  if (!screen) {
+    return blink::ScreenInfos(current_screen_info);
+  }
+
+  const std::vector<display::Display>& displays = screen->GetAllDisplays();
+
+  // Just return the legacy singular ScreenInfo, if its id is invalid or if the
+  // display::Screen is not initialized; each of which occurs in various tests.
+  // When there are no valid displays, some platforms can also create a
+  // fake default Display as well (e.g. Display::GetDefaultDisplay).
+  if (current_screen_info.display_id == display::kInvalidDisplayId ||
+      current_screen_info.display_id == display::kDefaultDisplayId ||
+      displays.empty()) {
+    return blink::ScreenInfos(current_screen_info);
+  }
+
+  // If we get here, we are asserting that the current display as reported
+  // by the RenderWidgetHostView is inside of GetAllDisplays().
+
+  blink::ScreenInfos result;
+  bool current_display_added = false;
+  for (const auto& display : displays) {
+    if (display.id() == current_screen_info.display_id) {
+      DCHECK(!current_display_added);
+      result.screen_infos.push_back(current_screen_info);
+      result.current_display_id = current_screen_info.display_id;
+      current_display_added = true;
+      continue;
+    }
+    blink::ScreenInfo screen_info;
+    DisplayUtil::DisplayToScreenInfo(&screen_info, display);
+    if (display::Display::HasForceRasterColorProfile()) {
+      screen_info.display_color_spaces = gfx::DisplayColorSpaces(
+          display::Display::GetForcedRasterColorProfile());
+    }
+    result.screen_infos.push_back(screen_info);
+  }
+
+  if (current_display_added)
+    return result;
+
+  // TODO(enne): temporary debugging logic.  GetScreens() is called during
+  // frequent visual property updates, and so will crash even when the
+  // multi-screen window placement api is not enabled.  Instead of CHECK, do a
+  // dump here so we can check if this is happening without having a full-on
+  // browser crash.
+  static bool have_crash_dumped = false;
+  if (!have_crash_dumped) {
+    have_crash_dumped = true;
+
+    SCOPED_CRASH_KEY_NUMBER("GetScreenInfos", "display_id",
+                            current_screen_info.display_id);
+    SCOPED_CRASH_KEY_NUMBER("GetScreenInfos", "num_displays", displays.size());
+
+    std::string display_ids;
+    for (const auto& display : displays) {
+      base::StringAppendF(&display_ids, "%" PRId64 ",", display.id());
+    }
+    SCOPED_CRASH_KEY_STRING256("GetScreenInfos", "displays", display_ids);
+
+    base::debug::DumpWithoutCrashing();
+  }
+
+  // Fall back to legacy screen info, if we are in a bad state.
+  return blink::ScreenInfos(current_screen_info);
+#endif
 }
 
 void RenderWidgetHostImpl::GetSnapshotFromBrowser(
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
index 08de932..99753b0 100644
--- a/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -788,7 +788,7 @@
   }
 
   factory->CreateLoaderAndStart(
-      url_loader.InitWithNewPipeAndPassReceiver(), -1 /* routing_id? */,
+      url_loader.InitWithNewPipeAndPassReceiver(),
       GlobalRequestID::MakeBrowserInitiated().request_id,
       network::mojom::kURLLoadOptionNone, resource_request,
       std::move(url_loader_client_to_pass),
diff --git a/content/browser/service_worker/service_worker_new_script_fetcher.cc b/content/browser/service_worker/service_worker_new_script_fetcher.cc
index bbc31821..321c63d 100644
--- a/content/browser/service_worker/service_worker_new_script_fetcher.cc
+++ b/content/browser/service_worker/service_worker_new_script_fetcher.cc
@@ -100,7 +100,7 @@
 
   mojo::MakeSelfOwnedReceiver(
       ServiceWorkerNewScriptLoader::CreateAndStart(
-          MSG_ROUTING_NONE, request_id_, options, request,
+          request_id_, options, request,
           url_loader_client_receiver_.BindNewPipeAndPassRemote(),
           std::move(version_), std::move(loader_factory_),
           net::MutableNetworkTrafficAnnotationTag(
diff --git a/content/browser/service_worker/service_worker_new_script_loader.cc b/content/browser/service_worker/service_worker_new_script_loader.cc
index e7643d6..6df0e22 100644
--- a/content/browser/service_worker/service_worker_new_script_loader.cc
+++ b/content/browser/service_worker/service_worker_new_script_loader.cc
@@ -45,7 +45,6 @@
 
 std::unique_ptr<ServiceWorkerNewScriptLoader>
 ServiceWorkerNewScriptLoader::CreateAndStart(
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& original_request,
@@ -55,14 +54,13 @@
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
     int64_t cache_resource_id) {
   return base::WrapUnique(new ServiceWorkerNewScriptLoader(
-      routing_id, request_id, options, original_request, std::move(client),
-      version, loader_factory, traffic_annotation, cache_resource_id));
+      request_id, options, original_request, std::move(client), version,
+      loader_factory, traffic_annotation, cache_resource_id));
 }
 
 // TODO(nhiroki): We're doing multiple things in the ctor. Consider factors out
 // some of them into a separate function.
 ServiceWorkerNewScriptLoader::ServiceWorkerNewScriptLoader(
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& original_request,
@@ -133,9 +131,9 @@
   options &= ~network::mojom::kURLLoadOptionSniffMimeType;
 
   loader_factory_->CreateLoaderAndStart(
-      network_loader_.BindNewPipeAndPassReceiver(), routing_id, request_id,
-      options, resource_request,
-      network_client_receiver_.BindNewPipeAndPassRemote(), traffic_annotation);
+      network_loader_.BindNewPipeAndPassReceiver(), request_id, options,
+      resource_request, network_client_receiver_.BindNewPipeAndPassRemote(),
+      traffic_annotation);
   DCHECK_EQ(LoaderState::kNotStarted, network_loader_state_);
   network_loader_state_ = LoaderState::kLoadingHeader;
 }
diff --git a/content/browser/service_worker/service_worker_new_script_loader.h b/content/browser/service_worker/service_worker_new_script_loader.h
index 85e0db0..6a45518 100644
--- a/content/browser/service_worker/service_worker_new_script_loader.h
+++ b/content/browser/service_worker/service_worker_new_script_loader.h
@@ -67,7 +67,6 @@
   enum class WriterState { kNotStarted, kWriting, kCompleted };
 
   static std::unique_ptr<ServiceWorkerNewScriptLoader> CreateAndStart(
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& original_request,
@@ -113,7 +112,6 @@
   class WrappedIOBuffer;
 
   ServiceWorkerNewScriptLoader(
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& original_request,
diff --git a/content/browser/service_worker/service_worker_new_script_loader_unittest.cc b/content/browser/service_worker/service_worker_new_script_loader_unittest.cc
index c0496f2d..82b7f05 100644
--- a/content/browser/service_worker/service_worker_new_script_loader_unittest.cc
+++ b/content/browser/service_worker/service_worker_new_script_loader_unittest.cc
@@ -209,7 +209,6 @@
     DCHECK(version_);
 
     // Dummy values.
-    int routing_id = 0;
     int request_id = 10;
     uint32_t options = 0;
     int64_t resource_id = GetNewResourceIdSync(context()->GetStorageControl());
@@ -224,8 +223,8 @@
 
     *out_client = std::make_unique<network::TestURLLoaderClient>();
     *out_loader = ServiceWorkerNewScriptLoader::CreateAndStart(
-        routing_id, request_id, options, request, (*out_client)->CreateRemote(),
-        version_, helper_->url_loader_factory_getter()->GetNetworkFactory(),
+        request_id, options, request, (*out_client)->CreateRemote(), version_,
+        helper_->url_loader_factory_getter()->GetNetworkFactory(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
         resource_id);
   }
diff --git a/content/browser/service_worker/service_worker_script_loader_factory.cc b/content/browser/service_worker/service_worker_script_loader_factory.cc
index 1e6c835..a979353 100644
--- a/content/browser/service_worker/service_worker_script_loader_factory.cc
+++ b/content/browser/service_worker/service_worker_script_loader_factory.cc
@@ -42,7 +42,6 @@
 
 void ServiceWorkerScriptLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& resource_request,
@@ -139,8 +138,8 @@
   // Assign a new resource ID for the script from network.
   context_->GetStorageControl()->GetNewResourceId(base::BindOnce(
       &ServiceWorkerScriptLoaderFactory::OnResourceIdAssignedForNewScriptLoader,
-      weak_factory_.GetWeakPtr(), std::move(receiver), routing_id, request_id,
-      options, resource_request, std::move(client), traffic_annotation));
+      weak_factory_.GetWeakPtr(), std::move(receiver), request_id, options,
+      resource_request, std::move(client), traffic_annotation));
 }
 
 void ServiceWorkerScriptLoaderFactory::Clone(
@@ -267,7 +266,6 @@
 
 void ServiceWorkerScriptLoaderFactory::OnResourceIdAssignedForNewScriptLoader(
     mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& resource_request,
@@ -288,7 +286,7 @@
 
   mojo::MakeSelfOwnedReceiver(
       ServiceWorkerNewScriptLoader::CreateAndStart(
-          routing_id, request_id, options, resource_request, std::move(client),
+          request_id, options, resource_request, std::move(client),
           worker_host_->version(), loader_factory_for_new_scripts_,
           traffic_annotation, resource_id),
       std::move(receiver));
diff --git a/content/browser/service_worker/service_worker_script_loader_factory.h b/content/browser/service_worker/service_worker_script_loader_factory.h
index ccda38c..ae554d3 100644
--- a/content/browser/service_worker/service_worker_script_loader_factory.h
+++ b/content/browser/service_worker/service_worker_script_loader_factory.h
@@ -58,7 +58,6 @@
   // network::mojom::URLLoaderFactory:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& resource_request,
@@ -99,7 +98,6 @@
 
   void OnResourceIdAssignedForNewScriptLoader(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& resource_request,
diff --git a/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc b/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc
index 4b8fe6a..918eaad 100644
--- a/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc
+++ b/content/browser/service_worker/service_worker_script_loader_factory_unittest.cc
@@ -61,9 +61,9 @@
     resource_request.destination =
         network::mojom::RequestDestination::kServiceWorker;
     factory_->CreateLoaderAndStart(
-        loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-        0 /* request_id */, network::mojom::kURLLoadOptionNone,
-        resource_request, client->CreateRemote(),
+        loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+        network::mojom::kURLLoadOptionNone, resource_request,
+        client->CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
     return loader;
   }
diff --git a/content/browser/service_worker/service_worker_single_script_update_checker.cc b/content/browser/service_worker/service_worker_single_script_update_checker.cc
index 497ecda..7f596cd 100644
--- a/content/browser/service_worker/service_worker_single_script_update_checker.cc
+++ b/content/browser/service_worker/service_worker_single_script_update_checker.cc
@@ -178,9 +178,8 @@
       network_client_receiver_.BindNewPipeAndPassRemote());
   network_loader_ = blink::ThrottlingURLLoader::CreateLoaderAndStart(
       network::SharedURLLoaderFactory::Create(loader_factory->Clone()),
-      std::move(throttles), MSG_ROUTING_NONE,
-      GlobalRequestID::MakeBrowserInitiated().request_id, options,
-      &resource_request, network_client_remote_.get(),
+      std::move(throttles), GlobalRequestID::MakeBrowserInitiated().request_id,
+      options, &resource_request, network_client_remote_.get(),
       kUpdateCheckTrafficAnnotation, base::ThreadTaskRunnerHandle::Get());
   DCHECK_EQ(network_loader_state_,
             ServiceWorkerUpdatedScriptLoader::LoaderState::kNotStarted);
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index e6f8072..172922b 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -741,7 +741,6 @@
 
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& url_request,
@@ -753,8 +752,8 @@
       return;
     storage_partition_
         ->GetURLLoaderFactoryForBrowserProcessInternal(corb_enabled_)
-        ->CreateLoaderAndStart(std::move(receiver), routing_id, request_id,
-                               options, url_request, std::move(client),
+        ->CreateLoaderAndStart(std::move(receiver), request_id, options,
+                               url_request, std::move(client),
                                traffic_annotation);
   }
 
diff --git a/content/browser/storage_partition_impl_browsertest.cc b/content/browser/storage_partition_impl_browsertest.cc
index e6f8ea9..1a8bd504e 100644
--- a/content/browser/storage_partition_impl_browsertest.cc
+++ b/content/browser/storage_partition_impl_browsertest.cc
@@ -179,7 +179,7 @@
   request.method = "GET";
   mojo::PendingRemote<network::mojom::URLLoader> loader;
   loader_factory->CreateLoaderAndStart(
-      loader.InitWithNewPipeAndPassReceiver(), 2, 1,
+      loader.InitWithNewPipeAndPassReceiver(), 1,
       network::mojom::kURLLoadOptionNone, request, client.CreateRemote(),
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
diff --git a/content/browser/url_loader_factory_getter.cc b/content/browser/url_loader_factory_getter.cc
index 111f092a..09e767e5 100644
--- a/content/browser/url_loader_factory_getter.cc
+++ b/content/browser/url_loader_factory_getter.cc
@@ -72,7 +72,6 @@
   // mojom::URLLoaderFactory implementation:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& url_request,
@@ -83,8 +82,8 @@
     if (!factory_getter_)
       return;
     factory_getter_->GetURLLoaderFactory(is_corb_enabled_)
-        ->CreateLoaderAndStart(std::move(receiver), routing_id, request_id,
-                               options, url_request, std::move(client),
+        ->CreateLoaderAndStart(std::move(receiver), request_id, options,
+                               url_request, std::move(client),
                                traffic_annotation);
   }
 
diff --git a/content/browser/web_database/web_database_host_impl.cc b/content/browser/web_database/web_database_host_impl.cc
index 8bd536c..f1f6b15 100644
--- a/content/browser/web_database/web_database_host_impl.cc
+++ b/content/browser/web_database/web_database_host_impl.cc
@@ -17,6 +17,7 @@
 #include "content/public/browser/render_process_host.h"
 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
 #include "services/network/public/cpp/is_potentially_trustworthy.h"
+#include "storage/browser/database/database_tracker.h"
 #include "storage/browser/database/database_util.h"
 #include "storage/browser/database/vfs_backend.h"
 #include "storage/browser/quota/quota_manager.h"
@@ -301,8 +302,7 @@
 
 void WebDatabaseHostImpl::Opened(const url::Origin& origin,
                                  const std::u16string& database_name,
-                                 const std::u16string& database_description,
-                                 int64_t estimated_size) {
+                                 const std::u16string& database_description) {
   DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
 
   if (!observer_added_) {
@@ -312,15 +312,13 @@
 
   ValidateOrigin(origin, base::BindOnce(&WebDatabaseHostImpl::OpenedValidated,
                                         weak_ptr_factory_.GetWeakPtr(), origin,
-                                        database_name, database_description,
-                                        estimated_size));
+                                        database_name, database_description));
 }
 
 void WebDatabaseHostImpl::OpenedValidated(
     const url::Origin& origin,
     const std::u16string& database_name,
-    const std::u16string& database_description,
-    int64_t estimated_size) {
+    const std::u16string& database_description) {
   DCHECK(db_tracker_->task_runner()->RunsTasksInCurrentSequence());
 
   // TODO(https://crbug.com/1158302): Use IsOriginPotentiallyTrustworthy?
@@ -330,8 +328,7 @@
   int64_t database_size = 0;
   std::string origin_identifier(storage::GetIdentifierFromOrigin(origin));
   db_tracker_->DatabaseOpened(origin_identifier, database_name,
-                              database_description, estimated_size,
-                              &database_size);
+                              database_description, &database_size);
 
   database_connections_.AddConnection(origin_identifier, database_name);
 
diff --git a/content/browser/web_database/web_database_host_impl.h b/content/browser/web_database/web_database_host_impl.h
index c2289e74..3720aec 100644
--- a/content/browser/web_database/web_database_host_impl.h
+++ b/content/browser/web_database/web_database_host_impl.h
@@ -60,8 +60,7 @@
 
   void Opened(const url::Origin& origin,
               const std::u16string& database_name,
-              const std::u16string& database_description,
-              int64_t estimated_size) override;
+              const std::u16string& database_description) override;
 
   void Modified(const url::Origin& origin,
                 const std::u16string& database_name) override;
@@ -109,8 +108,7 @@
 
   void OpenedValidated(const url::Origin& origin,
                        const std::u16string& database_name,
-                       const std::u16string& database_description,
-                       int64_t estimated_size);
+                       const std::u16string& database_description);
 
   void ModifiedValidated(const url::Origin& origin,
                          const std::u16string& database_name);
diff --git a/content/browser/web_database/web_database_host_impl_unittest.cc b/content/browser/web_database/web_database_host_impl_unittest.cc
index 2451f72..1f27da4 100644
--- a/content/browser/web_database/web_database_host_impl_unittest.cc
+++ b/content/browser/web_database/web_database_host_impl_unittest.cc
@@ -159,8 +159,8 @@
   });
 
   CheckUnauthorizedOrigin([&]() {
-    host()->Opened(incorrect_origin, db_name, base::ASCIIToUTF16("description"),
-                   /*estimated_size=*/0);
+    host()->Opened(incorrect_origin, db_name,
+                   base::ASCIIToUTF16("description"));
   });
 
   CheckUnauthorizedOrigin(
@@ -181,8 +181,7 @@
       [&]() { host()->GetSpaceAvailable(opaque_origin, base::DoNothing()); });
 
   CheckInvalidOrigin([&]() {
-    host()->Opened(opaque_origin, db_name, base::ASCIIToUTF16("description"),
-                   /*estimated_size=*/0);
+    host()->Opened(opaque_origin, db_name, base::ASCIIToUTF16("description"));
   });
 
   CheckInvalidOrigin([&]() { host()->Modified(opaque_origin, db_name); });
diff --git a/content/browser/web_package/prefetched_signed_exchange_cache.cc b/content/browser/web_package/prefetched_signed_exchange_cache.cc
index cf26b4b..0f940ad 100644
--- a/content/browser/web_package/prefetched_signed_exchange_cache.cc
+++ b/content/browser/web_package/prefetched_signed_exchange_cache.cc
@@ -352,7 +352,6 @@
   // network::mojom::URLLoaderFactory implementation.
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/content/browser/web_package/signed_exchange_cert_fetcher.cc b/content/browser/web_package/signed_exchange_cert_fetcher.cc
index 93c6785..9ebf91fe 100644
--- a/content/browser/web_package/signed_exchange_cert_fetcher.cc
+++ b/content/browser/web_package/signed_exchange_cert_fetcher.cc
@@ -155,7 +155,6 @@
   }
   url_loader_ = blink::ThrottlingURLLoader::CreateLoaderAndStart(
       std::move(shared_url_loader_factory_), std::move(throttles_),
-      0 /* routing_id */,
       signed_exchange_utils::MakeRequestID() /* request_id */,
       network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
       kCertFetcherTrafficAnnotation, base::ThreadTaskRunnerHandle::Get());
@@ -343,7 +342,7 @@
   mojo::Remote<network::mojom::URLLoaderFactory> factory(
       DataURLLoaderFactory::Create());
   factory->CreateLoaderAndStart(
-      std::move(url_loader_receiver), 0, 0, 0, resource_request,
+      std::move(url_loader_receiver), 0, 0, resource_request,
       std::move(url_loader_client_remote),
       net::MutableNetworkTrafficAnnotationTag(kCertFetcherTrafficAnnotation));
 }
diff --git a/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc b/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc
index e4ae19a..c8c0fb5 100644
--- a/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc
+++ b/content/browser/web_package/signed_exchange_cert_fetcher_unittest.cc
@@ -114,7 +114,6 @@
   // network::mojom::URLLoaderFactory implementation.
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> url_loader_receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& url_request,
diff --git a/content/browser/web_package/signed_exchange_loader_unittest.cc b/content/browser/web_package/signed_exchange_loader_unittest.cc
index 6c4e436..ca79fac 100644
--- a/content/browser/web_package/signed_exchange_loader_unittest.cc
+++ b/content/browser/web_package/signed_exchange_loader_unittest.cc
@@ -114,7 +114,6 @@
 
     void CreateLoaderAndStart(
         mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-        int32_t routing_id,
         int32_t request_id,
         uint32_t options,
         const network::ResourceRequest& url_request,
diff --git a/content/browser/web_package/signed_exchange_validity_pinger.cc b/content/browser/web_package/signed_exchange_validity_pinger.cc
index 39bed13..f1ec804a1 100644
--- a/content/browser/web_package/signed_exchange_validity_pinger.cc
+++ b/content/browser/web_package/signed_exchange_validity_pinger.cc
@@ -100,7 +100,7 @@
   resource_request->throttling_profile_id = throttling_profile_id;
 
   url_loader_ = blink::ThrottlingURLLoader::CreateLoaderAndStart(
-      std::move(url_loader_factory), std::move(throttles), 0 /* routing_id */,
+      std::move(url_loader_factory), std::move(throttles),
       signed_exchange_utils::MakeRequestID() /* request_id */,
       network::mojom::kURLLoadOptionNone, resource_request.get(), this,
       kValidityPingerTrafficAnnotation, base::ThreadTaskRunnerHandle::Get());
diff --git a/content/browser/web_package/web_bundle_interceptor_for_file.cc b/content/browser/web_package/web_bundle_interceptor_for_file.cc
index 9a14632..f75344c 100644
--- a/content/browser/web_package/web_bundle_interceptor_for_file.cc
+++ b/content/browser/web_package/web_bundle_interceptor_for_file.cc
@@ -102,7 +102,7 @@
   network::ResourceRequest new_resource_request = resource_request;
   new_resource_request.url = primary_url_;
   url_loader_factory_->CreateLoaderAndStart(
-      std::move(receiver), /*routing_id=*/0, /*request_id=*/0, /*options=*/0,
+      std::move(receiver), /*request_id=*/0, /*options=*/0,
       new_resource_request, std::move(client),
       net::MutableNetworkTrafficAnnotationTag(
           web_bundle_utils::kTrafficAnnotation));
diff --git a/content/browser/web_package/web_bundle_interceptor_for_history_navigation.cc b/content/browser/web_package/web_bundle_interceptor_for_history_navigation.cc
index 0be143a..aa34c0a 100644
--- a/content/browser/web_package/web_bundle_interceptor_for_history_navigation.cc
+++ b/content/browser/web_package/web_bundle_interceptor_for_history_navigation.cc
@@ -39,7 +39,7 @@
   network::ResourceRequest new_resource_request = resource_request;
   new_resource_request.url = target_inner_url_;
   url_loader_factory_->CreateLoaderAndStart(
-      std::move(receiver), /*routing_id=*/0, /*request_id=*/0,
+      std::move(receiver), /*request_id=*/0,
       /*options=*/0, new_resource_request, std::move(client),
       net::MutableNetworkTrafficAnnotationTag(
           web_bundle_utils::kTrafficAnnotation));
diff --git a/content/browser/web_package/web_bundle_interceptor_for_network.cc b/content/browser/web_package/web_bundle_interceptor_for_network.cc
index 13d3ce4c..69c9a92 100644
--- a/content/browser/web_package/web_bundle_interceptor_for_network.cc
+++ b/content/browser/web_package/web_bundle_interceptor_for_network.cc
@@ -146,7 +146,7 @@
   network::ResourceRequest new_resource_request = resource_request;
   new_resource_request.url = primary_url_;
   url_loader_factory_->CreateLoaderAndStart(
-      std::move(receiver), 0, 0, 0, new_resource_request, std::move(client),
+      std::move(receiver), 0, 0, new_resource_request, std::move(client),
       net::MutableNetworkTrafficAnnotationTag(
           web_bundle_utils::kTrafficAnnotation));
   std::move(done_callback_).Run(primary_url_, std::move(url_loader_factory_));
diff --git a/content/browser/web_package/web_bundle_interceptor_for_tracked_navigation_from_file.cc b/content/browser/web_package/web_bundle_interceptor_for_tracked_navigation_from_file.cc
index 8ca4292..c6ddf4e 100644
--- a/content/browser/web_package/web_bundle_interceptor_for_tracked_navigation_from_file.cc
+++ b/content/browser/web_package/web_bundle_interceptor_for_tracked_navigation_from_file.cc
@@ -83,7 +83,7 @@
   network::ResourceRequest new_resource_request = resource_request;
   new_resource_request.url = original_request_url_;
   url_loader_factory_->CreateLoaderAndStart(
-      std::move(receiver), /*routing_id=*/0, /*request_id=*/0, /*options=*/0,
+      std::move(receiver), /*request_id=*/0, /*options=*/0,
       new_resource_request, std::move(client),
       net::MutableNetworkTrafficAnnotationTag(
           web_bundle_utils::kTrafficAnnotation));
diff --git a/content/browser/web_package/web_bundle_interceptor_for_tracked_navigation_from_trustable_file_or_from_network.cc b/content/browser/web_package/web_bundle_interceptor_for_tracked_navigation_from_trustable_file_or_from_network.cc
index 42bb96c..b1ebb30 100644
--- a/content/browser/web_package/web_bundle_interceptor_for_tracked_navigation_from_trustable_file_or_from_network.cc
+++ b/content/browser/web_package/web_bundle_interceptor_for_tracked_navigation_from_trustable_file_or_from_network.cc
@@ -65,7 +65,7 @@
         mojo::PendingRemote<network::mojom::URLLoaderClient> client) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   url_loader_factory_->CreateLoaderAndStart(
-      std::move(receiver), /*routing_id=*/0, /*request_id=*/0,
+      std::move(receiver), /*request_id=*/0,
       /*options=*/0, resource_request, std::move(client),
       net::MutableNetworkTrafficAnnotationTag(
           web_bundle_utils::kTrafficAnnotation));
diff --git a/content/browser/web_package/web_bundle_interceptor_for_trustable_file.cc b/content/browser/web_package/web_bundle_interceptor_for_trustable_file.cc
index 71c4a3c..e5f64c2 100644
--- a/content/browser/web_package/web_bundle_interceptor_for_trustable_file.cc
+++ b/content/browser/web_package/web_bundle_interceptor_for_trustable_file.cc
@@ -70,7 +70,7 @@
   // URL.
   if (source_->url() != resource_request.url) {
     url_loader_factory_->CreateLoaderAndStart(
-        std::move(receiver), /*routing_id=*/0, /*request_id=*/0,
+        std::move(receiver), /*request_id=*/0,
         /*options=*/0, resource_request, std::move(client),
         net::MutableNetworkTrafficAnnotationTag(
             web_bundle_utils::kTrafficAnnotation));
diff --git a/content/browser/web_package/web_bundle_url_loader_factory.cc b/content/browser/web_package/web_bundle_url_loader_factory.cc
index 48a8fdb..49eefff3 100644
--- a/content/browser/web_package/web_bundle_url_loader_factory.cc
+++ b/content/browser/web_package/web_bundle_url_loader_factory.cc
@@ -193,7 +193,6 @@
 
 void WebBundleURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& resource_request,
@@ -209,8 +208,8 @@
                                    std::move(loader_receiver)));
   } else if (fallback_factory_) {
     fallback_factory_->CreateLoaderAndStart(
-        std::move(loader_receiver), routing_id, request_id, options,
-        resource_request, std::move(loader_client), traffic_annotation);
+        std::move(loader_receiver), request_id, options, resource_request,
+        std::move(loader_client), traffic_annotation);
   } else {
     mojo::Remote<network::mojom::URLLoaderClient>(std::move(loader_client))
         ->OnComplete(network::URLLoaderCompletionStatus(net::ERR_FAILED));
diff --git a/content/browser/web_package/web_bundle_url_loader_factory.h b/content/browser/web_package/web_bundle_url_loader_factory.h
index d41e183..ad5e56c 100644
--- a/content/browser/web_package/web_bundle_url_loader_factory.h
+++ b/content/browser/web_package/web_bundle_url_loader_factory.h
@@ -36,7 +36,6 @@
   // mojom::URLLoaderFactory implementation.
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& resource_request,
diff --git a/content/browser/web_package/web_bundle_url_loader_factory_unittest.cc b/content/browser/web_package/web_bundle_url_loader_factory_unittest.cc
index 5e0c26c..b2293a58 100644
--- a/content/browser/web_package/web_bundle_url_loader_factory_unittest.cc
+++ b/content/browser/web_package/web_bundle_url_loader_factory_unittest.cc
@@ -87,14 +87,14 @@
       loader_factory_->Clone(loader_factory.BindNewPipeAndPassReceiver());
       loader_factory->CreateLoaderAndStart(
           loader.BindNewPipeAndPassReceiver(),
-          /*routing_id=*/0, /*request_id=*/0, /*options=*/0, resource_request_,
+          /*request_id=*/0, /*options=*/0, resource_request_,
           test_client_.CreateRemote(),
           net::MutableNetworkTrafficAnnotationTag(
               TRAFFIC_ANNOTATION_FOR_TESTS));
     } else {
       loader_factory_->CreateLoaderAndStart(
           loader.BindNewPipeAndPassReceiver(),
-          /*routing_id=*/0, /*request_id=*/0, /*options=*/0, resource_request_,
+          /*request_id=*/0, /*options=*/0, resource_request_,
           test_client_.CreateRemote(),
           net::MutableNetworkTrafficAnnotationTag(
               TRAFFIC_ANNOTATION_FOR_TESTS));
diff --git a/content/browser/webui/web_ui_url_loader_factory.cc b/content/browser/webui/web_ui_url_loader_factory.cc
index 665f7e2..51fc775 100644
--- a/content/browser/webui/web_ui_url_loader_factory.cc
+++ b/content/browser/webui/web_ui_url_loader_factory.cc
@@ -235,7 +235,6 @@
   // network::mojom::URLLoaderFactory implementation:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/content/browser/worker_host/worker_script_fetcher.cc b/content/browser/worker_host/worker_script_fetcher.cc
index 1c3975bbeff..c07ff16 100644
--- a/content/browser/worker_host/worker_script_fetcher.cc
+++ b/content/browser/worker_host/worker_script_fetcher.cc
@@ -86,16 +86,10 @@
       base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
           script_loader_factory_.get());
 
-  // SharedWorker doesn't have a frame.
-  // TODO(nhiroki): Make the caller pass the frame id to support dedicated
-  // workers (https://crbug.com/906991).
-  int32_t routing_id = MSG_ROUTING_NONE;
-
   url_loader_ = blink::ThrottlingURLLoader::CreateLoaderAndStart(
-      std::move(shared_url_loader_factory), std::move(throttles), routing_id,
-      request_id_, network::mojom::kURLLoadOptionNone, resource_request_.get(),
-      this, kWorkerScriptLoadTrafficAnnotation,
-      base::ThreadTaskRunnerHandle::Get());
+      std::move(shared_url_loader_factory), std::move(throttles), request_id_,
+      network::mojom::kURLLoadOptionNone, resource_request_.get(), this,
+      kWorkerScriptLoadTrafficAnnotation, base::ThreadTaskRunnerHandle::Get());
 }
 
 void WorkerScriptFetcher::OnReceiveEarlyHints(
diff --git a/content/browser/worker_host/worker_script_loader.cc b/content/browser/worker_host/worker_script_loader.cc
index caf2aae..d56cf24 100644
--- a/content/browser/worker_host/worker_script_loader.cc
+++ b/content/browser/worker_host/worker_script_loader.cc
@@ -21,7 +21,6 @@
 WorkerScriptLoader::WorkerScriptLoader(
     int process_id,
     const DedicatedOrSharedWorkerToken& worker_token,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& resource_request,
@@ -32,8 +31,7 @@
     scoped_refptr<network::SharedURLLoaderFactory> default_loader_factory,
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
     ukm::SourceId ukm_source_id)
-    : routing_id_(routing_id),
-      request_id_(request_id),
+    : request_id_(request_id),
       options_(options),
       resource_request_(resource_request),
       client_(std::move(client)),
@@ -136,8 +134,8 @@
     url_loader_factory_ = std::move(single_request_factory);
     url_loader_.reset();
     url_loader_factory_->CreateLoaderAndStart(
-        url_loader_.BindNewPipeAndPassReceiver(), routing_id_, request_id_,
-        options_, resource_request_,
+        url_loader_.BindNewPipeAndPassReceiver(), request_id_, options_,
+        resource_request_,
         url_loader_client_receiver_.BindNewPipeAndPassRemote(),
         traffic_annotation_);
     // We continue in URLLoaderClient calls.
@@ -163,9 +161,8 @@
   url_loader_factory_ = default_loader_factory_;
   url_loader_.reset();
   url_loader_factory_->CreateLoaderAndStart(
-      url_loader_.BindNewPipeAndPassReceiver(), routing_id_, request_id_,
-      options_, resource_request_,
-      url_loader_client_receiver_.BindNewPipeAndPassRemote(),
+      url_loader_.BindNewPipeAndPassReceiver(), request_id_, options_,
+      resource_request_, url_loader_client_receiver_.BindNewPipeAndPassRemote(),
       traffic_annotation_);
   // We continue in URLLoaderClient calls.
 }
diff --git a/content/browser/worker_host/worker_script_loader.h b/content/browser/worker_host/worker_script_loader.h
index aeeb25e..2f2958c 100644
--- a/content/browser/worker_host/worker_script_loader.h
+++ b/content/browser/worker_host/worker_script_loader.h
@@ -71,7 +71,6 @@
   WorkerScriptLoader(
       int process_id,
       const DedicatedOrSharedWorkerToken& worker_token,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& resource_request,
@@ -148,7 +147,6 @@
 
   base::Optional<SubresourceLoaderParams> subresource_loader_params_;
 
-  const int32_t routing_id_;
   const int32_t request_id_;
   const uint32_t options_;
   network::ResourceRequest resource_request_;
diff --git a/content/browser/worker_host/worker_script_loader_factory.cc b/content/browser/worker_host/worker_script_loader_factory.cc
index 6226dfe..1850b26 100644
--- a/content/browser/worker_host/worker_script_loader_factory.cc
+++ b/content/browser/worker_host/worker_script_loader_factory.cc
@@ -47,7 +47,6 @@
 
 void WorkerScriptLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& resource_request,
@@ -63,10 +62,10 @@
 
   // Create a WorkerScriptLoader to load the script.
   auto script_loader = std::make_unique<WorkerScriptLoader>(
-      process_id_, worker_token_, routing_id, request_id, options,
-      resource_request, std::move(client), service_worker_handle_,
-      appcache_host_, browser_context_getter_, loader_factory_,
-      traffic_annotation, worker_source_id_);
+      process_id_, worker_token_, request_id, options, resource_request,
+      std::move(client), service_worker_handle_, appcache_host_,
+      browser_context_getter_, loader_factory_, traffic_annotation,
+      worker_source_id_);
   script_loader_ = script_loader->GetWeakPtr();
   mojo::MakeSelfOwnedReceiver(std::move(script_loader), std::move(receiver));
 }
diff --git a/content/browser/worker_host/worker_script_loader_factory.h b/content/browser/worker_host/worker_script_loader_factory.h
index 34b50d67..1d8cbd3 100644
--- a/content/browser/worker_host/worker_script_loader_factory.h
+++ b/content/browser/worker_host/worker_script_loader_factory.h
@@ -62,7 +62,6 @@
   // network::mojom::URLLoaderFactory:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& resource_request,
diff --git a/content/browser/worker_host/worker_script_loader_factory_unittest.cc b/content/browser/worker_host/worker_script_loader_factory_unittest.cc
index ea8c2572..aed0872 100644
--- a/content/browser/worker_host/worker_script_loader_factory_unittest.cc
+++ b/content/browser/worker_host/worker_script_loader_factory_unittest.cc
@@ -77,9 +77,9 @@
     resource_request.destination =
         network::mojom::RequestDestination::kSharedWorker;
     factory->CreateLoaderAndStart(
-        loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-        0 /* request_id */, network::mojom::kURLLoadOptionNone,
-        resource_request, client->CreateRemote(),
+        loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+        network::mojom::kURLLoadOptionNone, resource_request,
+        client->CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
     return loader;
   }
diff --git a/content/public/test/browser_test_base.cc b/content/public/test/browser_test_base.cc
index 88799cc..1f66b7e 100644
--- a/content/public/test/browser_test_base.cc
+++ b/content/public/test/browser_test_base.cc
@@ -892,7 +892,7 @@
 bool BrowserTestBase::UsingSoftwareGL() const {
   base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
   return cmd->GetSwitchValueASCII(switches::kUseGL) ==
-         gl::GetGLImplementationName(gl::GetSoftwareGLImplementation());
+         gl::GetGLImplementationGLName(gl::GetSoftwareGLImplementation());
 }
 
 void BrowserTestBase::SetInitialWebContents(WebContents* web_contents) {
diff --git a/content/public/test/url_loader_interceptor.cc b/content/public/test/url_loader_interceptor.cc
index b85a52c..4ddef68 100644
--- a/content/public/test/url_loader_interceptor.cc
+++ b/content/public/test/url_loader_interceptor.cc
@@ -167,8 +167,8 @@
     std::move(factory_getter)
         .Run()
         ->CreateLoaderAndStart(
-            std::move(params.receiver), params.routing_id, params.request_id,
-            params.options, std::move(params.url_request),
+            std::move(params.receiver), params.request_id, params.options,
+            std::move(params.url_request),
             delegating_client_receiver_.BindNewPipeAndPassRemote(),
             params.traffic_annotation);
   }
@@ -253,7 +253,6 @@
   // network::mojom::URLLoaderFactory implementation:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& url_request,
@@ -263,7 +262,6 @@
     RequestParams params;
     params.process_id = process_id_getter_.Run();
     params.receiver = std::move(receiver);
-    params.routing_id = routing_id;
     params.request_id = request_id;
     params.options = options;
     params.url_request = std::move(url_request);
diff --git a/content/public/test/url_loader_interceptor.h b/content/public/test/url_loader_interceptor.h
index 6042139..2109824 100644
--- a/content/public/test/url_loader_interceptor.h
+++ b/content/public/test/url_loader_interceptor.h
@@ -65,7 +65,6 @@
     int process_id;
     // The following are the parameters to CreateLoaderAndStart.
     mojo::PendingReceiver<network::mojom::URLLoader> receiver;
-    int32_t routing_id;
     int32_t request_id;
     uint32_t options;
     network::ResourceRequest url_request;
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index d8dfd7f..e5e014e 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -5124,8 +5124,23 @@
     // renderer has committed a different document. In such case, the navigation
     // cannot be loaded as a same-document navigation. The browser shouldn't let
     // this happen.
-    CHECK_EQ(GetWebFrame()->GetCurrentHistoryItem().DocumentSequenceNumber(),
-             item_for_history_navigation->DocumentSequenceNumber());
+    // TODO(crbug.com/1188513): A same document history navigation was performed
+    // but the renderer thinks there's a different document loaded. Where did
+    // this bad state of a different document + same-document navigation come
+    // from? Figure it out, make this a CHECK again, and drop the Restart.
+    DCHECK_EQ(GetWebFrame()->GetCurrentHistoryItem().DocumentSequenceNumber(),
+              item_for_history_navigation->DocumentSequenceNumber());
+    if (GetWebFrame()->GetCurrentHistoryItem().DocumentSequenceNumber() !=
+        item_for_history_navigation->DocumentSequenceNumber()) {
+      SCOPED_CRASH_KEY_NUMBER(
+          "history_bad_seq", "browser_doc_seq_num",
+          item_for_history_navigation->DocumentSequenceNumber());
+      SCOPED_CRASH_KEY_NUMBER(
+          "history_bad_seq", "renderer_doc_seq_num",
+          GetWebFrame()->GetCurrentHistoryItem().DocumentSequenceNumber());
+      base::debug::DumpWithoutCrashing();
+      return blink::mojom::CommitResult::RestartCrossDocument;
+    }
   }
 
   // Note: we used to check that initial history navigation in the child frame
diff --git a/content/renderer/service_worker/service_worker_provider_context_unittest.cc b/content/renderer/service_worker/service_worker_provider_context_unittest.cc
index 9ba8b18..d3a9ab9 100644
--- a/content/renderer/service_worker/service_worker_provider_context_unittest.cc
+++ b/content/renderer/service_worker/service_worker_provider_context_unittest.cc
@@ -140,7 +140,6 @@
   // network::mojom::URLLoaderFactory:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& url_request,
@@ -295,8 +294,8 @@
     mojo::PendingRemote<network::mojom::URLLoader> loader;
     network::TestURLLoaderClient loader_client;
     factory->CreateLoaderAndStart(
-        loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-        NextRequestId(), network::mojom::kURLLoadOptionNone, request,
+        loader.InitWithNewPipeAndPassReceiver(), NextRequestId(),
+        network::mojom::kURLLoadOptionNone, request,
         loader_client.CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
   }
@@ -832,7 +831,7 @@
   mojo::PendingRemote<network::mojom::URLLoader> loader;
   network::TestURLLoaderClient loader_client;
   wrapped_loader_factory->CreateLoaderAndStart(
-      loader.InitWithNewPipeAndPassReceiver(), 0, 0,
+      loader.InitWithNewPipeAndPassReceiver(), 0,
       network::mojom::kURLLoadOptionNone, request, loader_client.CreateRemote(),
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 }
diff --git a/content/renderer/service_worker/service_worker_subresource_loader.cc b/content/renderer/service_worker/service_worker_subresource_loader.cc
index 63b9ace..ceded80 100644
--- a/content/renderer/service_worker/service_worker_subresource_loader.cc
+++ b/content/renderer/service_worker/service_worker_subresource_loader.cc
@@ -152,7 +152,6 @@
 
 ServiceWorkerSubresourceLoader::ServiceWorkerSubresourceLoader(
     mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& resource_request,
@@ -171,7 +170,6 @@
       fetch_request_restarted_(false),
       body_reading_complete_(false),
       side_data_reading_complete_(false),
-      routing_id_(routing_id),
       request_id_(request_id),
       options_(options),
       traffic_annotation_(traffic_annotation),
@@ -242,7 +240,7 @@
       // The controller was lost after this loader or its loader factory was
       // created.
       fallback_factory_->CreateLoaderAndStart(
-          url_loader_receiver_.Unbind(), routing_id_, request_id_, options_,
+          url_loader_receiver_.Unbind(), request_id_, options_,
           resource_request_, url_loader_client_.Unbind(), traffic_annotation_);
       delete this;
       return;
@@ -459,8 +457,8 @@
                               client.InitWithNewPipeAndPassReceiver());
 
   fallback_factory_->CreateLoaderAndStart(
-      url_loader_receiver_.Unbind(), routing_id_, request_id_, options_,
-      resource_request_, std::move(client), traffic_annotation_);
+      url_loader_receiver_.Unbind(), request_id_, options_, resource_request_,
+      std::move(client), traffic_annotation_);
 
   // Per spec, redirects after this point are not intercepted by the service
   // worker again (https://crbug.com/517364). So this loader is done.
@@ -875,7 +873,6 @@
 
 void ServiceWorkerSubresourceLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& resource_request,
@@ -886,7 +883,7 @@
   // the request, passes the request to the fallback factory, and
   // destructs itself (while the loader client continues to work).
   new ServiceWorkerSubresourceLoader(
-      std::move(receiver), routing_id, request_id, options, resource_request,
+      std::move(receiver), request_id, options, resource_request,
       std::move(client), traffic_annotation, controller_connector_,
       fallback_factory_, task_runner_, weak_factory_.GetWeakPtr());
 }
diff --git a/content/renderer/service_worker/service_worker_subresource_loader.h b/content/renderer/service_worker/service_worker_subresource_loader.h
index fc5a133..ad177bd 100644
--- a/content/renderer/service_worker/service_worker_subresource_loader.h
+++ b/content/renderer/service_worker/service_worker_subresource_loader.h
@@ -48,7 +48,6 @@
   // to see how each parameter is used.
   ServiceWorkerSubresourceLoader(
       mojo::PendingReceiver<network::mojom::URLLoader>,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& resource_request,
@@ -181,7 +180,6 @@
 
   // These are given by the constructor (as the params for
   // URLLoaderFactory::CreateLoaderAndStart).
-  const int routing_id_;
   const int request_id_;
   const uint32_t options_;
   net::MutableNetworkTrafficAnnotationTag traffic_annotation_;
@@ -248,7 +246,6 @@
   // network::mojom::URLLoaderFactory overrides:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& resource_request,
diff --git a/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc b/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
index 73a1651..baf0c4d9 100644
--- a/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
+++ b/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
@@ -555,7 +555,7 @@
       std::unique_ptr<network::TestURLLoaderClient>* out_loader_client) {
     *out_loader_client = std::make_unique<network::TestURLLoaderClient>();
     loader_factory->CreateLoaderAndStart(
-        out_loader->BindNewPipeAndPassReceiver(), 0, 0,
+        out_loader->BindNewPipeAndPassReceiver(), 0,
         network::mojom::kURLLoadOptionNone, request,
         (*out_loader_client)->CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
diff --git a/content/test/data/accessibility/aria/aria-columnheader-expected-mac.txt b/content/test/data/accessibility/aria/aria-columnheader-expected-mac.txt
index fee0094c..f8c5eee 100644
--- a/content/test/data/accessibility/aria/aria-columnheader-expected-mac.txt
+++ b/content/test/data/accessibility/aria/aria-columnheader-expected-mac.txt
@@ -1,5 +1,5 @@
 AXWebArea
-++AXTable AXColumnHeaderUIElements=[:4, :6]
+++AXTable AXColumnHeaderUIElements=[:4, :6] AXHeader=:unknown
 ++++AXRow AXIndex=0
 ++++++AXCell AXColumnIndexRange={len: 1, loc: 0} AXRowIndexRange={len: 1, loc: 0}
 ++++++++AXStaticText AXValue='Browser'
@@ -15,3 +15,22 @@
 ++++++++AXStaticText AXValue='Safari'
 ++++++AXCell AXColumnHeaderUIElements=[:6] AXColumnIndexRange={len: 1, loc: 1} AXRowIndexRange={len: 1, loc: 2}
 ++++++++AXStaticText AXValue='WebKit'
+++++AXColumn AXHeader=:4 AXIndex=0
+++++++AXCell AXColumnIndexRange={len: 1, loc: 0} AXRowIndexRange={len: 1, loc: 0}
+++++++++AXStaticText AXValue='Browser'
+++++++AXCell AXColumnHeaderUIElements=[:4] AXColumnIndexRange={len: 1, loc: 0} AXRowIndexRange={len: 1, loc: 1}
+++++++++AXStaticText AXValue='Chrome'
+++++++AXCell AXColumnHeaderUIElements=[:4] AXColumnIndexRange={len: 1, loc: 0} AXRowIndexRange={len: 1, loc: 2}
+++++++++AXStaticText AXValue='Safari'
+++++AXColumn AXHeader=:6 AXIndex=1
+++++++AXCell AXColumnIndexRange={len: 1, loc: 1} AXRowIndexRange={len: 1, loc: 0}
+++++++++AXStaticText AXValue='Rendering Engine'
+++++++AXCell AXColumnHeaderUIElements=[:6] AXColumnIndexRange={len: 1, loc: 1} AXRowIndexRange={len: 1, loc: 1}
+++++++++AXStaticText AXValue='Blink'
+++++++AXCell AXColumnHeaderUIElements=[:6] AXColumnIndexRange={len: 1, loc: 1} AXRowIndexRange={len: 1, loc: 2}
+++++++++AXStaticText AXValue='WebKit'
+++++AXGroup
+++++++AXCell AXColumnIndexRange={len: 1, loc: 0} AXRowIndexRange={len: 1, loc: 0}
+++++++++AXStaticText AXValue='Browser'
+++++++AXCell AXColumnIndexRange={len: 1, loc: 1} AXRowIndexRange={len: 1, loc: 0}
+++++++++AXStaticText AXValue='Rendering Engine'
diff --git a/content/test/data/accessibility/event/focus-listbox-expected-auralinux.txt b/content/test/data/accessibility/event/focus-listbox-expected-auralinux.txt
index 9f2255a..4151906 100644
--- a/content/test/data/accessibility/event/focus-listbox-expected-auralinux.txt
+++ b/content/test/data/accessibility/event/focus-listbox-expected-auralinux.txt
@@ -1,10 +1,10 @@
 FOCUS-EVENT:FALSE role=ROLE_DOCUMENT_WEB name='(null)' ENABLED,FOCUSABLE,SENSITIVE,SHOWING,VISIBLE
-FOCUS-EVENT:FALSE role=ROLE_LIST_ITEM name='c' ENABLED,FOCUSABLE,FOCUSED,SELECTABLE,SELECTED,SENSITIVE,SHOWING,VISIBLE
-FOCUS-EVENT:TRUE role=ROLE_LIST_ITEM name='c' ENABLED,FOCUSABLE,FOCUSED,SELECTABLE,SELECTED,SENSITIVE,SHOWING,VISIBLE
-FOCUS-EVENT:TRUE role=ROLE_LIST_ITEM name='c' ENABLED,FOCUSABLE,SELECTABLE,SELECTED,SENSITIVE,SHOWING,VISIBLE
+FOCUS-EVENT:FALSE role=ROLE_LIST_ITEM name='%C3%A7' ENABLED,FOCUSABLE,FOCUSED,SELECTABLE,SELECTED,SENSITIVE,SHOWING,VISIBLE
+FOCUS-EVENT:TRUE role=ROLE_LIST_ITEM name='%C3%A7' ENABLED,FOCUSABLE,FOCUSED,SELECTABLE,SELECTED,SENSITIVE,SHOWING,VISIBLE
+FOCUS-EVENT:TRUE role=ROLE_LIST_ITEM name='%C3%A7' ENABLED,FOCUSABLE,SELECTABLE,SELECTED,SENSITIVE,SHOWING,VISIBLE
 SELECTION-CHANGED role=ROLE_LIST_BOX name='(null)' ENABLED,FOCUSABLE,FOCUSED,SENSITIVE,SHOWING,VERTICAL,VISIBLE
 STATE-CHANGE:FOCUSED:FALSE role=ROLE_DOCUMENT_WEB name='(null)' ENABLED,FOCUSABLE,SENSITIVE,SHOWING,VISIBLE
-STATE-CHANGE:FOCUSED:FALSE role=ROLE_LIST_ITEM name='c' ENABLED,FOCUSABLE,FOCUSED,SELECTABLE,SELECTED,SENSITIVE,SHOWING,VISIBLE
-STATE-CHANGE:FOCUSED:TRUE role=ROLE_LIST_ITEM name='c' ENABLED,FOCUSABLE,FOCUSED,SELECTABLE,SELECTED,SENSITIVE,SHOWING,VISIBLE
-STATE-CHANGE:FOCUSED:TRUE role=ROLE_LIST_ITEM name='c' ENABLED,FOCUSABLE,SELECTABLE,SELECTED,SENSITIVE,SHOWING,VISIBLE
-STATE-CHANGE:SELECTED:TRUE role=ROLE_LIST_ITEM name='c' ENABLED,FOCUSABLE,FOCUSED,SELECTABLE,SELECTED,SENSITIVE,SHOWING,VISIBLE
+STATE-CHANGE:FOCUSED:FALSE role=ROLE_LIST_ITEM name='%C3%A7' ENABLED,FOCUSABLE,FOCUSED,SELECTABLE,SELECTED,SENSITIVE,SHOWING,VISIBLE
+STATE-CHANGE:FOCUSED:TRUE role=ROLE_LIST_ITEM name='%C3%A7' ENABLED,FOCUSABLE,FOCUSED,SELECTABLE,SELECTED,SENSITIVE,SHOWING,VISIBLE
+STATE-CHANGE:FOCUSED:TRUE role=ROLE_LIST_ITEM name='%C3%A7' ENABLED,FOCUSABLE,SELECTABLE,SELECTED,SENSITIVE,SHOWING,VISIBLE
+STATE-CHANGE:SELECTED:TRUE role=ROLE_LIST_ITEM name='%C3%A7' ENABLED,FOCUSABLE,FOCUSED,SELECTABLE,SELECTED,SENSITIVE,SHOWING,VISIBLE
diff --git a/content/test/data/accessibility/event/focus-listbox-expected-mac.txt b/content/test/data/accessibility/event/focus-listbox-expected-mac.txt
index e35f7f7..054cfc4 100644
--- a/content/test/data/accessibility/event/focus-listbox-expected-mac.txt
+++ b/content/test/data/accessibility/event/focus-listbox-expected-mac.txt
@@ -1,2 +1,2 @@
-AXFocusedUIElementChanged on AXStaticText AXValue="c"
+AXFocusedUIElementChanged on AXStaticText AXValue="%C3%A7"
 AXSelectedChildrenChanged on AXList
diff --git a/content/test/data/accessibility/event/focus-listbox-expected-uia-win.txt b/content/test/data/accessibility/event/focus-listbox-expected-uia-win.txt
index f85e13b8..07339e2 100644
--- a/content/test/data/accessibility/event/focus-listbox-expected-uia-win.txt
+++ b/content/test/data/accessibility/event/focus-listbox-expected-uia-win.txt
@@ -1,5 +1,5 @@
 AriaProperties changed on role=option, name=b
-AriaProperties changed on role=option, name=c
-AutomationFocusChanged on role=option, name=c
-AutomationFocusChanged on role=option, name=c
-SelectionItem_ElementSelected on role=option, name=c
\ No newline at end of file
+AriaProperties changed on role=option, name=%C3%A7
+AutomationFocusChanged on role=option, name=%C3%A7
+AutomationFocusChanged on role=option, name=%C3%A7
+SelectionItem_ElementSelected on role=option, name=%C3%A7
diff --git a/content/test/data/accessibility/event/focus-listbox-expected-win.txt b/content/test/data/accessibility/event/focus-listbox-expected-win.txt
index d58e898..a306eab 100644
--- a/content/test/data/accessibility/event/focus-listbox-expected-win.txt
+++ b/content/test/data/accessibility/event/focus-listbox-expected-win.txt
@@ -1,6 +1,6 @@
-EVENT_OBJECT_FOCUS on <option> role=ROLE_SYSTEM_LISTITEM name="c" SELECTED,FOCUSED,FOCUSABLE,SELECTABLE PosInSet=3 SetSize=3
-EVENT_OBJECT_SELECTION on <option> role=ROLE_SYSTEM_LISTITEM name="c" SELECTED,FOCUSED,FOCUSABLE,SELECTABLE PosInSet=3 SetSize=3
+EVENT_OBJECT_FOCUS on <option> role=ROLE_SYSTEM_LISTITEM name="%C3%A7" SELECTED,FOCUSED,FOCUSABLE,SELECTABLE PosInSet=3 SetSize=3
+EVENT_OBJECT_SELECTION on <option> role=ROLE_SYSTEM_LISTITEM name="%C3%A7" SELECTED,FOCUSED,FOCUSABLE,SELECTABLE PosInSet=3 SetSize=3
 EVENT_OBJECT_SELECTIONWITHIN on <select> role=ROLE_SYSTEM_LIST FOCUSABLE IA2_STATE_VERTICAL SetSize=3
 EVENT_OBJECT_STATECHANGE on <option> role=ROLE_SYSTEM_LISTITEM name="b" FOCUSABLE,SELECTABLE PosInSet=2 SetSize=3
-EVENT_OBJECT_STATECHANGE on <option> role=ROLE_SYSTEM_LISTITEM name="c" SELECTED,FOCUSED,FOCUSABLE,SELECTABLE PosInSet=3 SetSize=3
-IA2_EVENT_ACTIVE_DESCENDANT_CHANGED on <select> role=ROLE_SYSTEM_LIST FOCUSABLE IA2_STATE_VERTICAL SetSize=3
\ No newline at end of file
+EVENT_OBJECT_STATECHANGE on <option> role=ROLE_SYSTEM_LISTITEM name="%C3%A7" SELECTED,FOCUSED,FOCUSABLE,SELECTABLE PosInSet=3 SetSize=3
+IA2_EVENT_ACTIVE_DESCENDANT_CHANGED on <select> role=ROLE_SYSTEM_LIST FOCUSABLE IA2_STATE_VERTICAL SetSize=3
diff --git a/content/test/data/accessibility/event/focus-listbox.html b/content/test/data/accessibility/event/focus-listbox.html
index d91a5da1..c70140e0 100644
--- a/content/test/data/accessibility/event/focus-listbox.html
+++ b/content/test/data/accessibility/event/focus-listbox.html
@@ -4,7 +4,7 @@
   <select size="3">
     <option>a</option>
     <option selected>b</option>
-    <option>c</option>
+    <option>&ccedil;</option>
   </select>
   <script>
     function go() {
diff --git a/content/test/fake_network_url_loader_factory.cc b/content/test/fake_network_url_loader_factory.cc
index 70a427d..66f4a72 100644
--- a/content/test/fake_network_url_loader_factory.cc
+++ b/content/test/fake_network_url_loader_factory.cc
@@ -27,7 +27,6 @@
 
 void FakeNetworkURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& url_request,
@@ -35,7 +34,6 @@
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
   URLLoaderInterceptor::RequestParams params;
   params.process_id = ChildProcessHost::kInvalidUniqueID;  // unused
-  params.routing_id = routing_id;
   params.request_id = request_id;
   params.options = options;
   params.url_request = url_request;
diff --git a/content/test/fake_network_url_loader_factory.h b/content/test/fake_network_url_loader_factory.h
index 8e7883c..5834d16 100644
--- a/content/test/fake_network_url_loader_factory.h
+++ b/content/test/fake_network_url_loader_factory.h
@@ -31,7 +31,6 @@
   // network::mojom::URLLoaderFactory implementation.
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& url_request,
diff --git a/content/test/url_loader_interceptor_test.cc b/content/test/url_loader_interceptor_test.cc
index d36ba16..f29b1eb 100644
--- a/content/test/url_loader_interceptor_test.cc
+++ b/content/test/url_loader_interceptor_test.cc
@@ -274,7 +274,7 @@
                       ->GetURLLoaderFactoryForBrowserProcess()
                       .get();
   factory->CreateLoaderAndStart(
-      loader.InitWithNewPipeAndPassReceiver(), 0, 0, 0, request,
+      loader.InitWithNewPipeAndPassReceiver(), 0, 0, request,
       client.CreateRemote(),
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
   client.RunUntilComplete();
diff --git a/content/web_test/browser/web_test_browser_main_runner.cc b/content/web_test/browser/web_test_browser_main_runner.cc
index 5465a09b..a8bb35f 100644
--- a/content/web_test/browser/web_test_browser_main_runner.cc
+++ b/content/web_test/browser/web_test_browser_main_runner.cc
@@ -149,7 +149,7 @@
       !command_line.HasSwitch(switches::kUseGL)) {
     command_line.AppendSwitchASCII(
         switches::kUseGL,
-        gl::GetGLImplementationName(gl::GetSoftwareGLImplementation()));
+        gl::GetGLImplementationGLName(gl::GetSoftwareGLImplementation()));
   }
   command_line.AppendSwitchASCII(switches::kTouchEventFeatureDetection,
                                  switches::kTouchEventFeatureDetectionEnabled);
diff --git a/docs/branch_sheriff.md b/docs/branch_sheriff.md
index 2b21073..5d535ad 100644
--- a/docs/branch_sheriff.md
+++ b/docs/branch_sheriff.md
@@ -124,6 +124,8 @@
 The current branch sheriff is listed [here][rotation-home]. The configuration
 and source of truth for the schedule lives [here][rotation-config]. To swap,
 simply send a CL changing schedule at the bottom of the file.
+You can also use [Oncall Swapper](https://oncallswapper.corp.google.com/)
+to find the swap and submit the CL for you.
 
 [chromiumdash]: https://chromiumdash.appspot.com
 [chromiumdash-branches]: https://chromiumdash.appspot.com/branches
diff --git a/docs/callback.md b/docs/callback.md
index c97c86d..f547565 100644
--- a/docs/callback.md
+++ b/docs/callback.md
@@ -676,25 +676,74 @@
 `base::RetainedRef` holds a reference to the object and passes a raw pointer to
 the object when the Callback is run.
 
-### Passing Parameters By Reference
+### Binding Const Reference Parameters
 
-References are *copied* unless `std::ref` or `std::cref` is used. Example:
+If the callback function takes a const reference parameter then the value is
+*copied* when bound unless `std::ref` or `std::cref` is used. Example:
 
 ```cpp
 void foo(const int& arg) { printf("%d %p\n", arg, &arg); }
 int n = 1;
-base::Closure has_copy = base::Bind(&foo, n);
-base::Closure has_ref = base::Bind(&foo, std::cref(n));
+base::OnceClosure has_copy = base::BindOnce(&foo, n);
+base::OnceClosure has_ref = base::BindOnce(&foo, std::cref(n));
 n = 2;
-foo(n);                        // Prints "2 0xaaaaaaaaaaaa"
-has_copy.Run();                // Prints "1 0xbbbbbbbbbbbb"
-has_ref.Run();                 // Prints "2 0xaaaaaaaaaaaa"
+foo(n);                                   // Prints "2 0xaaaaaaaaaaaa"
+std::move(has_copy).Run();                // Prints "1 0xbbbbbbbbbbbb"
+std::move(has_ref).Run();                 // Prints "2 0xaaaaaaaaaaaa"
 ```
 
-Normally parameters are copied in the closure.
-**DANGER**: `std::ref` and `std::cref` store a (const) reference instead,
-referencing the original parameter. This means that you must ensure the object
-outlives the callback!
+Normally parameters are copied in the closure. **DANGER**: `std::ref` and
+`std::cref` store a (const) reference instead, referencing the original
+parameter. This means that you must ensure the object outlives the callback!
+
+### Binding Non-Const Reference Parameters
+
+If the callback function takes a non-const reference then the bind statement
+must specify what behavior is desired. If a reference that can mutate the
+original value is desired then `std::ref` is used. If the callback should take
+ownership of the value, either by making a copy or moving an existing value,
+then `base::OwnedRef` is used. If neither is used the bind statement will fail
+to compile. Example:
+
+```cpp
+void foo(int& arg) {
+  printf("%d\n", arg);
+  ++arg;
+}
+
+int n = 0;
+base::RepeatingClosure has_ref = base::BindRepeating(&foo, std::ref(n));
+base::RepeatingClosure has_copy = base::BindRepeating(&foo, base::OwnedRef(n));
+
+foo(n);                        // Prints "0"
+has_ref.Run();                 // Prints "1"
+has_ref.Run();                 // Prints "2"
+foo(n);                        // Prints "3"
+
+has_copy.Run();                // Prints "0"
+has_copy.Run();                // Prints "1"
+
+// This will fail to compile.
+base::RepeatingClosure cb = base::BindRepeating(&foo, n);
+```
+
+Normally parameters are copied in the closure. **DANGER**: `std::ref` stores a
+reference instead, referencing the original parameter. This means that you must
+ensure the object outlives the callback!
+
+If the callback function has an output reference parameter but the output value
+isn't needed then `base::OwnedRef()` is a convenient way to handle it. The
+callback owned value will be mutated by the callback function and then deleted
+along with the callback. Example:
+
+```cpp
+bool Compute(size_t index, int& output);
+
+// The `output` parameter isn't important for the callback, it only cares about
+// the return value.
+base::OnceClosure cb = base::BindOnce(&Compute, index, base::OwnedRef(0));
+bool success = std::move(cb).Run();
+```
 
 ## Implementation notes
 
diff --git a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
index 48ad49a..f6818e03 100644
--- a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
+++ b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.cc
@@ -660,7 +660,7 @@
     if (has_any_extra_headers_listeners_)
       options |= network::mojom::kURLLoadOptionUseHeaderClient;
     factory_->target_factory_->CreateLoaderAndStart(
-        target_loader_.BindNewPipeAndPassReceiver(), info_->view_routing_id,
+        target_loader_.BindNewPipeAndPassReceiver(),
         network_service_request_id_, options, request_,
         proxied_client_receiver_.BindNewPipeAndPassRemote(),
         traffic_annotation_);
@@ -1175,7 +1175,6 @@
 
 void WebRequestProxyingURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
diff --git a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h
index 33a63836..a967133 100644
--- a/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h
+++ b/extensions/browser/api/web_request/web_request_proxying_url_loader_factory.h
@@ -287,7 +287,6 @@
   // network::mojom::URLLoaderFactory:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader_receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/extensions/browser/extension_protocols.cc b/extensions/browser/extension_protocols.cc
index b5832215..9fa07e3 100644
--- a/extensions/browser/extension_protocols.cc
+++ b/extensions/browser/extension_protocols.cc
@@ -527,7 +527,6 @@
   // network::mojom::URLLoaderFactory:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/fuchsia/engine/browser/content_directory_loader_factory.cc b/fuchsia/engine/browser/content_directory_loader_factory.cc
index 337448d..80ed7cc 100644
--- a/fuchsia/engine/browser/content_directory_loader_factory.cc
+++ b/fuchsia/engine/browser/content_directory_loader_factory.cc
@@ -401,7 +401,6 @@
 
 void ContentDirectoryLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> loader,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
diff --git a/fuchsia/engine/browser/content_directory_loader_factory.h b/fuchsia/engine/browser/content_directory_loader_factory.h
index 218b90e..1fc4e879 100644
--- a/fuchsia/engine/browser/content_directory_loader_factory.h
+++ b/fuchsia/engine/browser/content_directory_loader_factory.h
@@ -45,7 +45,6 @@
   // network::mojom::URLLoaderFactory:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/fuchsia/engine/features.h b/fuchsia/engine/features.h
index 4331250..9211f46f 100644
--- a/fuchsia/engine/features.h
+++ b/fuchsia/engine/features.h
@@ -10,7 +10,7 @@
 namespace features {
 
 constexpr base::Feature kHandleMemoryPressureInRenderer{
-    "HandleMemoryPressureInRenderer", base::FEATURE_ENABLED_BY_DEFAULT};
+    "HandleMemoryPressureInRenderer", base::FEATURE_DISABLED_BY_DEFAULT};
 
 }  // namespace features
 
diff --git a/fuchsia/engine/renderer/web_engine_content_renderer_client.cc b/fuchsia/engine/renderer/web_engine_content_renderer_client.cc
index 80bdf1d..a44fc38 100644
--- a/fuchsia/engine/renderer/web_engine_content_renderer_client.cc
+++ b/fuchsia/engine/renderer/web_engine_content_renderer_client.cc
@@ -143,17 +143,15 @@
 }
 
 void WebEngineContentRendererClient::RenderThreadStarted() {
-  // Behavior of browser tests should not depend on things outside of their
-  // control (like the amount of memory on the system running the tests).
-  if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kBrowserTest))
-    return;
-
-  if (!base::FeatureList::IsEnabled(features::kHandleMemoryPressureInRenderer))
-    return;
-
-  memory_pressure_monitor_ =
-      std::make_unique<util::MultiSourceMemoryPressureMonitor>();
-  memory_pressure_monitor_->Start();
+  if (base::FeatureList::IsEnabled(features::kHandleMemoryPressureInRenderer) &&
+      // Behavior of browser tests should not depend on things outside of their
+      // control (like the amount of memory on the system running the tests).
+      !base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kBrowserTest)) {
+    memory_pressure_monitor_ =
+        std::make_unique<util::MultiSourceMemoryPressureMonitor>();
+    memory_pressure_monitor_->Start();
+  }
 }
 
 void WebEngineContentRendererClient::RenderFrameCreated(
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
index 7047ac4..0f50014 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc
@@ -2434,7 +2434,7 @@
   context_creation_attribs_.bind_generates_resource = true;
 
   gl::init::InitializeStaticGLBindingsImplementation(
-      gl::kGLImplementationEGLANGLE, false);
+      gl::GLImplementationParts(gl::kGLImplementationEGLANGLE), false);
   gl::init::InitializeGLOneOffPlatformImplementation(false, false, true);
 
   scoped_refptr<gles2::FeatureInfo> feature_info = new gles2::FeatureInfo();
diff --git a/gpu/command_buffer/service/image_reader_gl_owner_unittest.cc b/gpu/command_buffer/service/image_reader_gl_owner_unittest.cc
index f3de965..a91e640 100644
--- a/gpu/command_buffer/service/image_reader_gl_owner_unittest.cc
+++ b/gpu/command_buffer/service/image_reader_gl_owner_unittest.cc
@@ -33,7 +33,7 @@
       return;
 
     gl::init::InitializeStaticGLBindingsImplementation(
-        gl::kGLImplementationEGLGLES2, false);
+        gl::GLImplementationParts(gl::kGLImplementationEGLGLES2), false);
     gl::init::InitializeGLOneOffPlatformImplementation(false, false, true);
 
     surface_ = new gl::PbufferGLSurfaceEGL(gfx::Size(320, 240));
diff --git a/gpu/command_buffer/service/surface_texture_gl_owner_unittest.cc b/gpu/command_buffer/service/surface_texture_gl_owner_unittest.cc
index 4ef50c9..2afd4c1f 100644
--- a/gpu/command_buffer/service/surface_texture_gl_owner_unittest.cc
+++ b/gpu/command_buffer/service/surface_texture_gl_owner_unittest.cc
@@ -34,7 +34,7 @@
  protected:
   void SetUp() override {
     gl::init::InitializeStaticGLBindingsImplementation(
-        gl::kGLImplementationEGLGLES2, false);
+        gl::GLImplementationParts(gl::kGLImplementationEGLGLES2), false);
     gl::init::InitializeGLOneOffPlatformImplementation(false, false, true);
 
     surface_ = new gl::PbufferGLSurfaceEGL(gfx::Size(320, 240));
diff --git a/gpu/command_buffer/tests/fuzzer_main.cc b/gpu/command_buffer/tests/fuzzer_main.cc
index 2c71da7..d8fb127 100644
--- a/gpu/command_buffer/tests/fuzzer_main.cc
+++ b/gpu/command_buffer/tests/fuzzer_main.cc
@@ -336,14 +336,14 @@
 #endif
 
     CHECK(gl::init::InitializeStaticGLBindingsImplementation(
-        gl::kGLImplementationEGLANGLE, false));
+        gl::GLImplementationParts(gl::kGLImplementationEGLANGLE), false));
     CHECK(
         gl::init::InitializeGLOneOffPlatformImplementation(false, false, true));
 #elif defined(GPU_FUZZER_USE_SWIFTSHADER)
     command_line->AppendSwitchASCII(switches::kUseGL,
                                     gl::kGLImplementationSwiftShaderName);
     CHECK(gl::init::InitializeStaticGLBindingsImplementation(
-        gl::kGLImplementationSwiftShaderGL, false));
+        gl::GLImplementationParts(gl::kGLImplementationSwiftShaderGL), false));
     CHECK(
         gl::init::InitializeGLOneOffPlatformImplementation(false, false, true));
 #elif defined(GPU_FUZZER_USE_STUB)
diff --git a/gpu/command_buffer/tests/gl_test_utils.cc b/gpu/command_buffer/tests/gl_test_utils.cc
index 786c9f0..7409e65 100644
--- a/gpu/command_buffer/tests/gl_test_utils.cc
+++ b/gpu/command_buffer/tests/gl_test_utils.cc
@@ -41,7 +41,8 @@
       return false;
   } else {
     if (!gl::init::InitializeStaticGLBindingsImplementation(
-            gl_impl, /*fallback_to_software_gl*/ false))
+            gl::GLImplementationParts(gl_impl),
+            /*fallback_to_software_gl*/ false))
       return false;
 
     if (!gl::init::InitializeGLOneOffPlatformImplementation(
@@ -396,18 +397,19 @@
     }
     // The native EGL driver is not supported with the passthrough command
     // decoder, in that case use ANGLE
-    const gl::GLImplementation new_impl =
-        (gpu_info.passthrough_cmd_decoder ? gl::kGLImplementationEGLANGLE
-                                          : gl::kGLImplementationEGLGLES2);
+    gl::GLImplementationParts new_impl(gl::kGLImplementationEGLGLES2);
+    if (gpu_info.passthrough_cmd_decoder)
+      new_impl = gl::GLImplementationParts(gl::kGLImplementationEGLANGLE);
+
     const auto allowed_impls = gl::init::GetAllowedGLImplementations();
-    if (!base::Contains(allowed_impls, new_impl)) {
+    if (!base::Contains(allowed_impls, new_impl.gl)) {
       LOG(INFO) << "Skip test, no EGL implementation is available";
       return false;
     }
 
     gl_reinitialized_ = true;
     gl::init::ShutdownGL(false /* due_to_fallback */);
-    if (!GLTestHelper::InitializeGL(new_impl)) {
+    if (!GLTestHelper::InitializeGL(new_impl.gl)) {
       LOG(INFO) << "Skip test, failed to initialize EGL";
       return false;
     }
diff --git a/gpu/config/gpu_info_collector.cc b/gpu/config/gpu_info_collector.cc
index b8ec898..22b6560 100644
--- a/gpu/config/gpu_info_collector.cc
+++ b/gpu/config/gpu_info_collector.cc
@@ -235,7 +235,7 @@
   }
 
   base::StringPiece software_gl_impl_name =
-      gl::GetGLImplementationName(gl::GetSoftwareGLImplementation());
+      gl::GetGLImplementationGLName(gl::GetSoftwareGLImplementation());
   if (use_gl == software_gl_impl_name ||
       command_line->HasSwitch(switches::kOverrideUseSoftwareGLForTests)) {
     // If using the software GL implementation, use fake vendor and
diff --git a/gpu/ipc/service/gpu_init.cc b/gpu/ipc/service/gpu_init.cc
index a4ad5e38..b12e9cf 100644
--- a/gpu/ipc/service/gpu_init.cc
+++ b/gpu/ipc/service/gpu_init.cc
@@ -430,7 +430,7 @@
     LOG_IF(ERROR, !gpu_info_.passthrough_cmd_decoder)
 #endif
         << "Passthrough is not supported, GL is "
-        << gl::GetGLImplementationName(gl::GetGLImplementation());
+        << gl::GetGLImplementationGLName(gl::GetGLImplementationParts());
   } else {
     gpu_info_.passthrough_cmd_decoder = false;
   }
@@ -586,7 +586,7 @@
     }
   }
   if (gl_use_swiftshader_ ||
-      gl::GetGLImplementation() == gl::GetSoftwareGLImplementation()) {
+      gl::GetGLImplementationParts() == gl::GetSoftwareGLImplementation()) {
     gpu_info_.software_rendering = true;
     watchdog_thread_ = nullptr;
     watchdog_init.SetGpuWatchdogPtr(nullptr);
diff --git a/gpu/vulkan/vulkan_swap_chain.cc b/gpu/vulkan/vulkan_swap_chain.cc
index cd1de474..68ed4cf8 100644
--- a/gpu/vulkan/vulkan_swap_chain.cc
+++ b/gpu/vulkan/vulkan_swap_chain.cc
@@ -6,6 +6,7 @@
 
 #include "base/bind.h"
 #include "base/compiler_specific.h"
+#include "base/debug/crash_logging.h"
 #include "base/logging.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
@@ -503,6 +504,12 @@
   FenceAndSemaphores fence_and_semaphores;
   do {
 #if !defined(OS_FUCHSIA)
+    // This crash key is for diagnosing OOM crash.
+    // TODO(penghuang): remove it when OOM crash is fixed, or find out it is not
+    // related.
+    SCOPED_CRASH_KEY_NUMBER("VulkanSwapChian", "queue_.size()",
+                            fence_and_semaphores_queue_.size());
+
     if (LIKELY(!fence_and_semaphores_queue_.empty())) {
       fence_and_semaphores = fence_and_semaphores_queue_.front();
       auto result = vkGetFenceStatus(device, fence_and_semaphores.fence);
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg
index 52e36ec2..6a8ff7e 100644
--- a/infra/config/generated/cr-buildbucket.cfg
+++ b/infra/config/generated/cr-buildbucket.cfg
@@ -4321,7 +4321,7 @@
         cmd: "recipes"
       }
       properties: "{\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"chromium.android\",\"recipe\":\"swarming/deterministic_build\"}"
-      execution_timeout_secs: 21600
+      execution_timeout_secs: 25200
       build_numbers: YES
       service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
       experiments {
diff --git a/infra/config/subprojects/chromium/ci.star b/infra/config/subprojects/chromium/ci.star
index 3856507c..ca70122 100644
--- a/infra/config/subprojects/chromium/ci.star
+++ b/infra/config/subprojects/chromium/ci.star
@@ -582,7 +582,7 @@
         short_name = "rel",
     ),
     executable = "recipe:swarming/deterministic_build",
-    execution_timeout = 6 * time.hour,
+    execution_timeout = 7 * time.hour,
     notifies = ["Deterministic Android"],
     tree_closing = True,
 )
diff --git a/ios/chrome/app/application_delegate/user_activity_handler.h b/ios/chrome/app/application_delegate/user_activity_handler.h
index a63feb6..30244fa2 100644
--- a/ios/chrome/app/application_delegate/user_activity_handler.h
+++ b/ios/chrome/app/application_delegate/user_activity_handler.h
@@ -57,8 +57,8 @@
 
 // Return YES if the user intends to open links in a certain mode and the
 // browser will proceed the request.
-+ (BOOL)canProceeedWithUserActivity:(NSUserActivity*)userActivity
-                        prefService:(PrefService*)prefService;
++ (BOOL)canProceedWithUserActivity:(NSUserActivity*)userActivity
+                       prefService:(PrefService*)prefService;
 
 @end
 
diff --git a/ios/chrome/app/application_delegate/user_activity_handler.mm b/ios/chrome/app/application_delegate/user_activity_handler.mm
index bf374b4..a5fa0be 100644
--- a/ios/chrome/app/application_delegate/user_activity_handler.mm
+++ b/ios/chrome/app/application_delegate/user_activity_handler.mm
@@ -76,16 +76,16 @@
 
 // Returns the compatible mode array for an user activity.
 NSArray* CompatibleModeForActivityType(NSString* activityType) {
-  if (activityType == CSSearchableItemActionType ||
-      activityType == kShortcutNewSearch ||
-      activityType == kShortcutVoiceSearch ||
-      activityType == kShortcutQRScanner ||
-      activityType == kSiriShortcutSearchInChrome) {
+  if ([activityType isEqualToString:CSSearchableItemActionType] ||
+      [activityType isEqualToString:kShortcutNewSearch] ||
+      [activityType isEqualToString:kShortcutVoiceSearch] ||
+      [activityType isEqualToString:kShortcutQRScanner] ||
+      [activityType isEqualToString:kSiriShortcutSearchInChrome]) {
     return @[ kRegularMode, kIncognitoMode ];
-  } else if (activityType == kSiriShortcutOpenInChrome) {
+  } else if ([activityType isEqualToString:kSiriShortcutOpenInChrome]) {
     return @[ kRegularMode ];
-  } else if (activityType == kShortcutNewIncognitoSearch ||
-             activityType == kSiriShortcutOpenInIncognito) {
+  } else if ([activityType isEqualToString:kShortcutNewIncognitoSearch] ||
+             [activityType isEqualToString:kSiriShortcutOpenInIncognito]) {
     return @[ kIncognitoMode ];
   } else {
     NOTREACHED();
@@ -558,8 +558,8 @@
   }
 }
 
-+ (BOOL)canProceeedWithUserActivity:(NSUserActivity*)userActivity
-                        prefService:(PrefService*)prefService {
++ (BOOL)canProceedWithUserActivity:(NSUserActivity*)userActivity
+                       prefService:(PrefService*)prefService {
   NSArray* array = CompatibleModeForActivityType(userActivity.activityType);
 
   if (IsIncognitoModeDisabled(prefService)) {
diff --git a/ios/chrome/browser/autofill/form_structure_browsertest.mm b/ios/chrome/browser/autofill/form_structure_browsertest.mm
index 9e52ff41..1a29d951 100644
--- a/ios/chrome/browser/autofill/form_structure_browsertest.mm
+++ b/ios/chrome/browser/autofill/form_structure_browsertest.mm
@@ -18,7 +18,7 @@
 #include "components/autofill/core/browser/data_driven_test.h"
 #include "components/autofill/core/browser/form_structure.h"
 #include "components/autofill/core/common/autofill_features.h"
-#include "components/autofill/core/common/renderer_id.h"
+#include "components/autofill/core/common/unique_ids.h"
 #import "components/autofill/ios/browser/autofill_agent.h"
 #include "components/autofill/ios/browser/autofill_driver_ios.h"
 #include "components/autofill/ios/form_util/unique_id_data_tab_helper.h"
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index b3bef67e..19a1a07 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -384,9 +384,6 @@
      flag_descriptions::kOmniboxLocalHistoryZeroSuggestName,
      flag_descriptions::kOmniboxLocalHistoryZeroSuggestDescription,
      flags_ui::kOsIos, FEATURE_VALUE_TYPE(omnibox::kLocalHistoryZeroSuggest)},
-    {"snapshot-draw-view", flag_descriptions::kSnapshotDrawViewName,
-     flag_descriptions::kSnapshotDrawViewDescription, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(kSnapshotDrawView)},
 #if defined(DCHECK_IS_CONFIGURABLE)
     {"dcheck-is-fatal", flag_descriptions::kDcheckIsFatalName,
      flag_descriptions::kDcheckIsFatalDescription, flags_ui::kOsIos,
@@ -456,12 +453,6 @@
      flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(
          autofill::features::kAutofillSaveCardInfobarEditSupport)},
-    {"managed-bookmarks-ios", flag_descriptions::kManagedBookmarksIOSName,
-     flag_descriptions::kManagedBookmarksIOSDescription, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(kManagedBookmarksIOS)},
-    {"edit-bookmarks-ios", flag_descriptions::kEditBookmarksIOSName,
-     flag_descriptions::kEditBookmarksIOSDescription, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(kEditBookmarksIOS)},
     {"url-blocklist-ios", flag_descriptions::kURLBlocklistIOSName,
      flag_descriptions::kURLBlocklistIOSDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(kURLBlocklistIOS)},
@@ -469,9 +460,6 @@
      flag_descriptions::kEnableIOSManagedSettingsUIName,
      flag_descriptions::kEnableIOSManagedSettingsUIDescription,
      flags_ui::kOsIos, FEATURE_VALUE_TYPE(kEnableIOSManagedSettingsUI)},
-    {"safety-check-ios", flag_descriptions::kSafetyCheckIOSName,
-     flag_descriptions::kSafetyCheckIOSDescription, flags_ui::kOsIos,
-     FEATURE_VALUE_TYPE(kSafetyCheckIOS)},
     {"new-content-suggestions-feed", flag_descriptions::kDiscoverFeedInNtpName,
      flag_descriptions::kDiscoverFeedInNtpDescription, flags_ui::kOsIos,
      FEATURE_WITH_PARAMS_VALUE_TYPE(kDiscoverFeedInNtp,
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index b6f52f5..f1983f1c 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -153,10 +153,6 @@
     "When enabled, replaces articles feed with new content Suggestion Feed in "
     "the NTP.";
 
-const char kEditBookmarksIOSName[] = "Edit Bookmarks IOS";
-const char kEditBookmarksIOSDescription[] =
-    "Enables support for the EditBookmarksEnabled enterprise policy on iOS";
-
 const char kEditPasswordsInSettingsName[] = "Edit passwords in settings";
 const char kEditPasswordsInSettingsDescription[] =
     "Enables password editing in settings.";
@@ -289,11 +285,6 @@
     "When enabled, the bottom toolbar will not get collapsed when scrolling "
     "into fullscreen mode.";
 
-const char kManagedBookmarksIOSName[] = "Managed Bookmarks IOS";
-const char kManagedBookmarksIOSDescription[] =
-    "When enabled, managed bookmarks set by an enterprise policy can be shown "
-    "in the bookmarks UI on iOS";
-
 const char kMobileGoogleSRPName[] = "Mobile version of Google SRP by default";
 const char kMobileGoogleSRPDescription[] =
     "Request the Mobile version of Google SRP by default when the desktop mode "
@@ -375,11 +366,6 @@
     "When enabled, navigation URLs are checked using real-time queries to Safe "
     "Browsing servers, subject to an opt-in preference.";
 
-const char kSafetyCheckIOSName[] = "Enable safety check on iOS";
-const char kSafetyCheckIOSDescription[] =
-    "When enabled, the iOS version of safety check is available in Chrome "
-    "settings.";
-
 const char kScreenTimeIntegrationName[] = "Enables ScreenTime Integration";
 const char kScreenTimeIntegrationDescription[] =
     "Enables integration with ScreenTime in iOS 14.0 and above.";
@@ -415,10 +401,6 @@
     "Annotates web forms with Autofill field type predictions as placeholder "
     "text.";
 
-const char kSnapshotDrawViewName[] = "Use DrawViewHierarchy for Snapshots";
-const char kSnapshotDrawViewDescription[] =
-    "When enabled, snapshots will be taken using |-drawViewHierarchy:|.";
-
 const char kSimplifySignOutIOSName[] = "Simplify sign-out";
 const char kSimplifySignOutIOSDescription[] =
     "When enabled, sign-out UI in the account table view is simplified.";
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index 2393a36..2e2cfe9 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -135,11 +135,6 @@
 extern const char kDiscoverFeedInNtpName[];
 extern const char kDiscoverFeedInNtpDescription[];
 
-// Title and description for the flag to enable EditBookmarks enterprise
-// policy on iOS.
-extern const char kEditBookmarksIOSName[];
-extern const char kEditBookmarksIOSDescription[];
-
 // Title and description for the flag to enable kEditPasswordsInSettings flag on
 // iOS.
 extern const char kEditPasswordsInSettingsName[];
@@ -242,11 +237,6 @@
 extern const char kLockBottomToolbarName[];
 extern const char kLockBottomToolbarDescription[];
 
-// Title and description for the flag to enable ManagedBookmarks enterprise
-// policy on iOS.
-extern const char kManagedBookmarksIOSName[];
-extern const char kManagedBookmarksIOSDescription[];
-
 // Title and description for the flag where the Google SRP is requested in
 // mobile mode by default.
 extern const char kMobileGoogleSRPName[];
@@ -309,10 +299,6 @@
 extern const char kSafeBrowsingRealTimeLookupName[];
 extern const char kSafeBrowsingRealTimeLookupDescription[];
 
-// Title and description for the flag to enable safety check on iOS.
-extern const char kSafetyCheckIOSName[];
-extern const char kSafetyCheckIOSDescription[];
-
 // Title and description for the flag to enable integration with the ScreenTime
 // system.
 extern const char kScreenTimeIntegrationName[];
@@ -355,11 +341,6 @@
 extern const char kSimplifySignOutIOSName[];
 extern const char kSimplifySignOutIOSDescription[];
 
-// Title and description for the flag to use |-drawViewHierarchy:| for taking
-// snapshots.
-extern const char kSnapshotDrawViewName[];
-extern const char kSnapshotDrawViewDescription[];
-
 // Title and description for the flag to enable the Start Surface.
 extern const char kStartSurfaceName[];
 extern const char kStartSurfaceDescription[];
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm
index 4621a5e..c1e8337e 100644
--- a/ios/chrome/browser/passwords/password_controller.mm
+++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -26,8 +26,8 @@
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/password_form_fill_data.h"
 #include "components/autofill/core/common/password_form_generation_data.h"
-#include "components/autofill/core/common/renderer_id.h"
 #include "components/autofill/core/common/signatures.h"
+#include "components/autofill/core/common/unique_ids.h"
 #include "components/autofill/ios/browser/autofill_util.h"
 #import "components/autofill/ios/form_util/form_activity_observer_bridge.h"
 #include "components/autofill/ios/form_util/form_activity_params.h"
diff --git a/ios/chrome/browser/policy/policy_features.cc b/ios/chrome/browser/policy/policy_features.cc
index bff0b42..29398b95 100644
--- a/ios/chrome/browser/policy/policy_features.cc
+++ b/ios/chrome/browser/policy/policy_features.cc
@@ -12,12 +12,6 @@
 #include "ios/chrome/common/channel_info.h"
 #include "ios/web/common/features.h"
 
-const base::Feature kEditBookmarksIOS{"EditBookmarksIOS",
-                                      base::FEATURE_ENABLED_BY_DEFAULT};
-
-const base::Feature kManagedBookmarksIOS{"ManagedBookmarksIOS",
-                                         base::FEATURE_ENABLED_BY_DEFAULT};
-
 const base::Feature kEnableIncognitoModeAvailabilityIOS{
     "EnableIncognitoModeAvailabilityIOS", base::FEATURE_DISABLED_BY_DEFAULT};
 
@@ -43,10 +37,6 @@
 
 }  // namespace
 
-bool IsEditBookmarksIOSEnabled() {
-  return base::FeatureList::IsEnabled(kEditBookmarksIOS);
-}
-
 bool IsEnterprisePolicyEnabled() {
   return !IsDisableEnterprisePolicySwitchPresent();
 }
@@ -59,10 +49,6 @@
   return IsEnterprisePolicyEnabled();
 }
 
-bool IsManagedBookmarksEnabled() {
-  return base::FeatureList::IsEnabled(kManagedBookmarksIOS);
-}
-
 bool ShouldInstallURLBlocklistPolicyHandlers() {
   return HasSwitch(switches::kInstallURLBlocklistHandlers);
 }
diff --git a/ios/chrome/browser/policy/policy_features.h b/ios/chrome/browser/policy/policy_features.h
index 29101d99..1330634d 100644
--- a/ios/chrome/browser/policy/policy_features.h
+++ b/ios/chrome/browser/policy/policy_features.h
@@ -7,11 +7,6 @@
 
 #include "base/feature_list.h"
 
-// Feature flag for supporting the EditBookmarks enterprise policy on iOS.
-extern const base::Feature kEditBookmarksIOS;
-// Feature flag for supporting the ManagedBookmarks enterprise policy on iOS.
-extern const base::Feature kManagedBookmarksIOS;
-
 // Feature flag for supporting the URLBlocklist enterprise policy on iOS.
 extern const base::Feature kURLBlocklistIOS;
 
@@ -23,9 +18,6 @@
 // Returns true if the Chrome Browser Cloud Management flow is enabled.
 bool IsChromeBrowserCloudManagementEnabled();
 
-// Returns true if EditBookmarksEnabled enterprise policy is supported on iOS.
-bool IsEditBookmarksIOSEnabled();
-
 // Returns true if the core enterprise policy infrastructure is enabled. Does
 // not control whether policy data is parsed and made user visible; that is
 // controlled by |ShouldInstallEnterprisePolicyHandlers()| below.
@@ -39,13 +31,6 @@
 // policy data and make it user visible.
 bool ShouldInstallEnterprisePolicyHandlers();
 
-// Returns true if the ManagedBookmarks policy handler should be installed to
-// parse policy data and make it user visible.
-bool ShouldInstallManagedBookmarksPolicyHandler();
-
-// Returns true if ManagedBookmarks enterprise policy is enabled.
-bool IsManagedBookmarksEnabled();
-
 // Returns true if the URLBlocklist and URLAllowlist policy handlers should be
 // installed.
 bool ShouldInstallURLBlocklistPolicyHandlers();
diff --git a/ios/chrome/browser/policy/policy_util.h b/ios/chrome/browser/policy/policy_util.h
index 461008e..a99be6e 100644
--- a/ios/chrome/browser/policy/policy_util.h
+++ b/ios/chrome/browser/policy/policy_util.h
@@ -21,6 +21,9 @@
   kForced,
 };
 
+// Returns true if IncognitoModeAvailability policy is set by enterprise.
+bool IsIncognitoPolicyApplied(PrefService* pref_service);
+
 // Returns true if incognito mode is disabled by enterprise policy.
 bool IsIncognitoModeDisabled(PrefService* pref_service);
 
diff --git a/ios/chrome/browser/policy/policy_util.mm b/ios/chrome/browser/policy/policy_util.mm
index 6e917ef7..7c375f61 100644
--- a/ios/chrome/browser/policy/policy_util.mm
+++ b/ios/chrome/browser/policy/policy_util.mm
@@ -12,20 +12,21 @@
 #error "This file requires ARC support."
 #endif
 
-bool IsIncognitoModeDisabled(PrefService* pref_service) {
+bool IsIncognitoPolicyApplied(PrefService* pref_service) {
   if (!pref_service)
     return NO;
   return IsEnterprisePolicyEnabled() &&
-         pref_service->IsManagedPreference(prefs::kIncognitoModeAvailability) &&
+         pref_service->IsManagedPreference(prefs::kIncognitoModeAvailability);
+}
+
+bool IsIncognitoModeDisabled(PrefService* pref_service) {
+  return IsIncognitoPolicyApplied(pref_service) &&
          pref_service->GetInteger(prefs::kIncognitoModeAvailability) ==
              static_cast<int>(IncognitoModePrefs::kDisabled);
 }
 
 bool IsIncognitoModeForced(PrefService* pref_service) {
-  if (!pref_service)
-    return NO;
-  return IsEnterprisePolicyEnabled() &&
-         pref_service->IsManagedPreference(prefs::kIncognitoModeAvailability) &&
+  return IsIncognitoPolicyApplied(pref_service) &&
          pref_service->GetInteger(prefs::kIncognitoModeAvailability) ==
              static_cast<int>(IncognitoModePrefs::kForced);
 }
diff --git a/ios/chrome/browser/snapshots/snapshot_generator.mm b/ios/chrome/browser/snapshots/snapshot_generator.mm
index ade84a5..54a2ef52 100644
--- a/ios/chrome/browser/snapshots/snapshot_generator.mm
+++ b/ios/chrome/browser/snapshots/snapshot_generator.mm
@@ -16,7 +16,6 @@
 #include "base/task/post_task.h"
 #import "ios/chrome/browser/snapshots/snapshot_cache.h"
 #import "ios/chrome/browser/snapshots/snapshot_generator_delegate.h"
-#include "ios/chrome/browser/ui/ui_feature_flags.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
 #include "ios/web/public/thread/web_task_traits.h"
 #include "ios/web/public/thread/web_thread.h"
@@ -215,24 +214,20 @@
                         -frameInBaseView.origin.y);
   BOOL snapshotSuccess = YES;
 
-  // TODO(crbug.com/636188): |-drawViewHierarchyInRect:afterScreenUpdates:| is
-  // buggy on iOS 8/9/10 (and state is unknown for iOS 11) causing GPU glitches,
-  // screen redraws during animations, broken pinch to dismiss on tablet, etc.
-  // Ensure iOS 11 is not affected by these issues before turning on
-  // |kSnapshotDrawView| experiment. On the other hand, |-renderInContext:| is
-  // buggy for WKWebView, which is used for some Chromium pages such as "No
-  // internet" or "Site can't be reached".
-  BOOL useDrawViewHierarchy = ViewHierarchyContainsWKWebView(baseView) ||
-                              base::FeatureList::IsEnabled(kSnapshotDrawView);
   // |drawViewHierarchyInRect:| has undefined behavior when the view is not
   // in the visible view hierarchy. In practice, when this method is called
   // on a view that is part of view controller containment and not in the view
   // hierarchy, an UIViewControllerHierarchyInconsistency exception will be
   // thrown.
-  if (useDrawViewHierarchy && baseView.window) {
+  if (baseView.window && ViewHierarchyContainsWKWebView(baseView)) {
+    // TODO(crbug.com/636188): |-drawViewHierarchyInRect:afterScreenUpdates:| is
+    // buggy causing GPU glitches, screen redraws during animations, broken
+    // pinch to dismiss on tablet, etc.
     snapshotSuccess = [baseView drawViewHierarchyInRect:baseView.bounds
                                      afterScreenUpdates:YES];
   } else {
+    // |-renderInContext:| is buggy for WKWebView, which is used for some
+    // Chromium pages such as "No internet" or "Site can't be reached".
     [[baseView layer] renderInContext:context];
   }
   UIImage* image = nil;
@@ -293,16 +288,7 @@
     // This shifts the context so that drawing starts at the overlay's offset.
     CGContextTranslateCTM(context, frameInWindow.origin.x,
                           frameInWindow.origin.y);
-    // |drawViewHierarchyInRect:| has undefined behavior when the view is not
-    // in the visible view hierarchy. In practice, when this method is called
-    // on a view that is part of view controller containment, an
-    // UIViewControllerHierarchyInconsistency exception will be thrown.
-    if (base::FeatureList::IsEnabled(kSnapshotDrawView) && overlay.window) {
-      // The rect's origin is ignored. Only size is used.
-      [overlay drawViewHierarchyInRect:overlay.bounds afterScreenUpdates:YES];
-    } else {
-      [[overlay layer] renderInContext:context];
-    }
+    [[overlay layer] renderInContext:context];
     CGContextRestoreGState(context);
   }
 }
diff --git a/ios/chrome/browser/ui/activity_services/activities/bookmark_activity.mm b/ios/chrome/browser/ui/activity_services/activities/bookmark_activity.mm
index 5cdc4f7..77508092 100644
--- a/ios/chrome/browser/ui/activity_services/activities/bookmark_activity.mm
+++ b/ios/chrome/browser/ui/activity_services/activities/bookmark_activity.mm
@@ -9,7 +9,6 @@
 #import "components/bookmarks/browser/bookmark_model.h"
 #import "components/bookmarks/common/bookmark_pref_names.h"
 #import "components/prefs/pref_service.h"
-#import "ios/chrome/browser/policy/policy_features.h"
 #import "ios/chrome/browser/ui/commands/bookmark_page_command.h"
 #import "ios/chrome/browser/ui/commands/bookmarks_commands.h"
 #import "ios/chrome/browser/ui/commands/browser_commands.h"
@@ -105,10 +104,8 @@
 
 // Verifies if, based on preferences, the user can edit their bookmarks or not.
 - (BOOL)isEditBookmarksEnabledInPrefs {
-  if (IsEditBookmarksIOSEnabled())
     return self.prefService->GetBoolean(
         bookmarks::prefs::kEditBookmarksEnabled);
-  return YES;
 }
 
 @end
diff --git a/ios/chrome/browser/ui/activity_services/activities/bookmark_activity_unittest.mm b/ios/chrome/browser/ui/activity_services/activities/bookmark_activity_unittest.mm
index 3915f201..98eb76fe 100644
--- a/ios/chrome/browser/ui/activity_services/activities/bookmark_activity_unittest.mm
+++ b/ios/chrome/browser/ui/activity_services/activities/bookmark_activity_unittest.mm
@@ -4,13 +4,11 @@
 
 #import "ios/chrome/browser/ui/activity_services/activities/bookmark_activity.h"
 
-#include "base/test/scoped_feature_list.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/browser/bookmark_node.h"
 #include "components/bookmarks/common/bookmark_pref_names.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
-#include "ios/chrome/browser/policy/policy_features.h"
 #include "ios/chrome/browser/ui/bookmarks/bookmark_ios_unittest.h"
 #include "ios/chrome/browser/ui/commands/bookmark_page_command.h"
 #include "ios/chrome/browser/ui/commands/bookmarks_commands.h"
@@ -37,9 +35,6 @@
   void SetUp() override {
     BookmarkIOSUnitTest::SetUp();
 
-    // Turn off flag by default.
-    scoped_features_.InitAndDisableFeature(kEditBookmarksIOS);
-
     mocked_handler_ = OCMProtocolMock(@protocol(BookmarksCommands));
 
     RegisterPrefs();
@@ -66,31 +61,14 @@
                                      prefService:&testing_pref_service_];
   }
 
-  base::test::ScopedFeatureList scoped_features_;
   TestingPrefServiceSimple testing_pref_service_;
   id mocked_handler_;
 };
 
-// Tests that the activity can always be performed when the kEditBookmarksIOS
-// feature flag is disabled.
-TEST_F(BookmarkActivityTest, FlagOff_ActivityAlwaysAvailable) {
-  BookmarkActivity* activity = CreateActivity(GURL());
-
-  // Flag Off, Editable bookmark pref true.
-  EXPECT_TRUE([activity canPerformWithActivityItems:@[]]);
-
-  SetCanEditBookmarkPref(false);
-
-  // Flag off, Editable bookmark pref false.
-  EXPECT_TRUE([activity canPerformWithActivityItems:@[]]);
-}
-
-// Tests that, when the kEditBookmarksIOS is enabled, the activity can only be
-// performed if the preferences indicate that bookmarks can be edited.
+// Tests that the activity can only be performed if the preferences indicate
+// that bookmarks can be edited.
 TEST_F(BookmarkActivityTest, FlagOn_ActivityHiddenByPref) {
   BookmarkActivity* activity = CreateActivity(GURL());
-  scoped_features_.Reset();
-  scoped_features_.InitAndEnableFeature(kEditBookmarksIOS);
 
   // Flag On, Editable bookmark pref true.
   EXPECT_TRUE([activity canPerformWithActivityItems:@[]]);
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.mm
index 74b83836..58eb4c7f 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_mediator.mm
@@ -109,15 +109,11 @@
   _prefChangeRegistrar->Init(self.browserState->GetPrefs());
   _prefObserverBridge.reset(new PrefObserverBridge(self));
 
-  if (IsEditBookmarksIOSEnabled()) {
     _prefObserverBridge->ObserveChangesForPreference(
         bookmarks::prefs::kEditBookmarksEnabled, _prefChangeRegistrar.get());
-  }
 
-  if (IsManagedBookmarksEnabled()) {
     _prefObserverBridge->ObserveChangesForPreference(
         bookmarks::prefs::kManagedBookmarks, _prefChangeRegistrar.get());
-  }
 
   [self computePromoTableViewData];
   [self computeBookmarkTableViewData];
@@ -218,7 +214,6 @@
         toSectionWithIdentifier:BookmarkHomeSectionIdentifierBookmarks];
   }
 
-  if (IsManagedBookmarksEnabled()) {
     // Add "Managed Bookmarks" to the table if it exists.
     bookmarks::ManagedBookmarkService* managedBookmarkService =
         ManagedBookmarkServiceFactory::GetForBrowserState(self.browserState);
@@ -231,7 +226,6 @@
                           addItem:managedItem
           toSectionWithIdentifier:BookmarkHomeSectionIdentifierBookmarks];
     }
-  }
 }
 
 - (void)computeBookmarkTableViewDataMatching:(NSString*)searchText
diff --git a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
index 9d2aa26..a55139d 100644
--- a/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
+++ b/ios/chrome/browser/ui/bookmarks/bookmark_home_view_controller.mm
@@ -1322,10 +1322,8 @@
 
 // Returns YES if user is allowed to edit any bookmarks.
 - (BOOL)isEditBookmarksEnabled {
-  if (IsEditBookmarksIOSEnabled())
     return self.browserState->GetPrefs()->GetBoolean(
         bookmarks::prefs::kEditBookmarksEnabled);
-  return YES;
 }
 
 // Returns the bookmark node associated with |indexPath|.
diff --git a/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm b/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm
index 8c3c056..2701872b 100644
--- a/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm
+++ b/ios/chrome/browser/ui/find_bar/find_in_page_egtest.mm
@@ -113,7 +113,8 @@
 
 // Tests that find in page allows iteration between search results and displays
 // correct number of results.
-- (void)testFindInPage {
+// TODO(crbug.com/1188709) : Fix failing test.
+- (void)DISABLED_testFindInPage {
   // Type "find".
   [self typeFindInPageText:@"find"];
   // Should be highlighting result 1 of 2.
@@ -171,7 +172,8 @@
 }
 
 // Tests accessibility of the Find in Page screen.
-- (void)testAccessibilityOnFindInPage {
+// TODO(crbug.com/1188709) : Fix failing test.
+- (void)DISABLED_testAccessibilityOnFindInPage {
   [self typeFindInPageText:@"find"];
   [self assertResultStringIsResult:1 outOfTotal:2];
 
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm
index a110cc9..4f9cfc03 100644
--- a/ios/chrome/browser/ui/main/scene_controller.mm
+++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -656,10 +656,10 @@
   }
   self.sceneState.startupHadExternalIntent = YES;
 
-  if (![UserActivityHandler
-          canProceeedWithUserActivity:userActivity
-                          prefService:self.currentInterface.browserState
-                                          ->GetPrefs()]) {
+  PrefService* prefs = self.currentInterface.browserState->GetPrefs();
+  if (IsIncognitoPolicyApplied(prefs) &&
+      ![UserActivityHandler canProceedWithUserActivity:userActivity
+                                           prefService:prefs]) {
     // If users request opening url in a unavailable mode, don't open the url
     // but show a toast.
     [self showToastWhenOpenExternalIntentInUnexpectedMode];
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
index 7a9fc7e5b..7001561 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator.mm
@@ -1148,10 +1148,8 @@
 
 // Returns YES if user is allowed to edit any bookmarks.
 - (BOOL)isEditBookmarksEnabled {
-  if (IsEditBookmarksIOSEnabled())
     return self.prefService->GetBoolean(
         bookmarks::prefs::kEditBookmarksEnabled);
-  return YES;
 }
 
 @end
diff --git a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator_unittest.mm b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator_unittest.mm
index 1558aeec..add5df8c 100644
--- a/ios/chrome/browser/ui/popup_menu/popup_menu_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/popup_menu/popup_menu_mediator_unittest.mm
@@ -537,9 +537,6 @@
 // Tests that the bookmark button is disabled when EditBookmarksEnabled pref is
 // changed to false.
 TEST_F(PopupMenuMediatorTest, TestDisableBookmarksButton) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(kEditBookmarksIOS);
-
   CreateMediator(PopupMenuTypeToolsMenu, /*is_incognito=*/NO,
                  /*trigger_incognito_hint=*/NO);
   CreatePrefs();
diff --git a/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_settings_egtest.mm b/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_settings_egtest.mm
index 2025ab10..ddd26e4 100644
--- a/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_settings_egtest.mm
@@ -226,59 +226,6 @@
   [self exitSettingsMenu];
 }
 
-// Checks that the Autofill credit card switch can be turned off and the add
-// payment method button in the toolbar is disabled.
-- (void)testToggleCreditCardSwitchPaymentMethodDisabled {
-  [self openCreditCardsSettings];
-
-  // Toggle the Autofill credit cards switch off.
-  [[EarlGrey
-      selectElementWithMatcher:chrome_test_util::SettingsSwitchCell(
-                                   kAutofillCreditCardSwitchViewId, YES, YES)]
-      performAction:chrome_test_util::TurnSettingsSwitchOn(NO)];
-
-  // Expect Add Payment Method button to be disabled.
-  [[EarlGrey
-      selectElementWithMatcher:chrome_test_util::AddPaymentMethodButton()]
-      assertWithMatcher:grey_not(grey_enabled())];
-
-  // Toggle the Autofill credit cards switch back on.
-  [[EarlGrey
-      selectElementWithMatcher:chrome_test_util::SettingsSwitchCell(
-                                   kAutofillCreditCardSwitchViewId, NO, YES)]
-      performAction:chrome_test_util::TurnSettingsSwitchOn(YES)];
-
-  // Expect Add Payment Method button to be visible.
-  [[EarlGrey
-      selectElementWithMatcher:chrome_test_util::AddPaymentMethodButton()]
-      assertWithMatcher:grey_sufficientlyVisible()];
-
-  [self exitSettingsMenu];
-}
-
-// Checks that when the Autofill credit card switch can be turned off and the
-// edit button is pressed, Add Payment Method button is removed from the
-// toolbar.
-- (void)testToggleCreditCardSwitchInEditModePaymentMethodRemoved {
-  [AutofillAppInterface saveLocalCreditCard];
-  [self openCreditCardsSettings];
-
-  // Toggle the Autofill credit cards switch off.
-  [[EarlGrey
-      selectElementWithMatcher:chrome_test_util::SettingsSwitchCell(
-                                   kAutofillCreditCardSwitchViewId, YES, YES)]
-      performAction:chrome_test_util::TurnSettingsSwitchOn(NO)];
-
-  // Open Edit Mode.
-  [[EarlGrey selectElementWithMatcher:NavigationBarEditButton()]
-      performAction:grey_tap()];
-
-  // Expect Add Payment Method to be removed.
-  [[EarlGrey
-      selectElementWithMatcher:chrome_test_util::AddPaymentMethodButton()]
-      assertWithMatcher:grey_not(grey_sufficientlyVisible())];
-}
-
 // Checks that the toolbar always appears in edit mode.
 - (void)testToolbarInEditModeAddPaymentMethodFeatureEnabled {
   NSString* lastDigits = [AutofillAppInterface saveLocalCreditCard];
diff --git a/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_table_view_controller.mm b/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_table_view_controller.mm
index c936084..7c01de8 100644
--- a/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/autofill/autofill_credit_card_table_view_controller.mm
@@ -123,7 +123,6 @@
   self.navigationController.toolbar.accessibilityIdentifier =
       kAutofillPaymentMethodsToolbarId;
 
-  self.addPaymentMethodButton.enabled = [self isAutofillCreditCardEnabled];
   [self setToolbarItems:@[ [self flexibleSpace], self.addPaymentMethodButton ]
                animated:YES];
   [self updateUIForEditState];
@@ -349,7 +348,6 @@
 - (void)autofillCardSwitchChanged:(UISwitch*)switchView {
   [self setSwitchItemOn:[switchView isOn] itemType:ItemTypeAutofillCardSwitch];
   [self setAutofillCreditCardEnabled:[switchView isOn]];
-  self.addPaymentMethodButton.enabled = [self isAutofillCreditCardEnabled];
 }
 
 #pragma mark - Switch Helpers
@@ -567,15 +565,9 @@
 
 // Adds delete button to the bottom toolbar.
 - (void)showDeleteButton {
-  if ([self isAutofillCreditCardEnabled]) {
-    [self setToolbarItems:@[
-      self.deleteButton, [self flexibleSpace], self.addPaymentMethodButton
-    ]
-                 animated:YES];
-  } else {
-    [self setToolbarItems:@[ self.deleteButton, [self flexibleSpace] ]
-                 animated:YES];
-  }
+  NSArray* customToolbarItems =
+      @[ self.deleteButton, [self flexibleSpace], self.addPaymentMethodButton ];
+  [self setToolbarItems:customToolbarItems animated:YES];
 }
 
 // Removes delete button from the bottom toolbar.
diff --git a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm
index 63374a1..37a6f55 100644
--- a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm
@@ -325,13 +325,10 @@
 
     PrefService* prefService = _browserState->GetPrefs();
 
-    if (base::FeatureList::IsEnabled(kSafetyCheckIOS)) {
-      _passwordCheckManager =
-          IOSChromePasswordCheckManagerFactory::GetForBrowserState(
-              _browserState);
-      _passwordCheckObserver = std::make_unique<PasswordCheckObserverBridge>(
-          self, _passwordCheckManager.get());
-    }
+    _passwordCheckManager =
+        IOSChromePasswordCheckManagerFactory::GetForBrowserState(_browserState);
+    _passwordCheckObserver = std::make_unique<PasswordCheckObserverBridge>(
+        self, _passwordCheckManager.get());
 
     _articlesEnabled = [[PrefBackedBoolean alloc]
         initWithPrefService:prefService
@@ -447,10 +444,8 @@
   [model addSectionWithIdentifier:SettingsSectionIdentifierAdvanced];
   [model addItem:[self voiceSearchDetailItem]
       toSectionWithIdentifier:SettingsSectionIdentifierAdvanced];
-  if (base::FeatureList::IsEnabled(kSafetyCheckIOS)) {
-    [model addItem:[self safetyCheckDetailItem]
-        toSectionWithIdentifier:SettingsSectionIdentifierAdvanced];
-  }
+  [model addItem:[self safetyCheckDetailItem]
+      toSectionWithIdentifier:SettingsSectionIdentifierAdvanced];
   [model addItem:[self privacyDetailItem]
       toSectionWithIdentifier:SettingsSectionIdentifierAdvanced];
   _articlesForYouItem = [self articlesForYouSwitchItem];
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_mediator.mm b/ios/chrome/browser/ui/toolbar/toolbar_mediator.mm
index c054e16e..247bd1f 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_mediator.mm
+++ b/ios/chrome/browser/ui/toolbar/toolbar_mediator.mm
@@ -336,10 +336,8 @@
 
 // Returns YES if user is allowed to edit any bookmarks.
 - (BOOL)isEditBookmarksEnabled {
-  if (IsEditBookmarksIOSEnabled())
     return self.prefService->GetBoolean(
         bookmarks::prefs::kEditBookmarksEnabled);
-  return YES;
 }
 
 #pragma mark - BookmarkModelBridgeObserver
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_mediator_unittest.mm b/ios/chrome/browser/ui/toolbar/toolbar_mediator_unittest.mm
index 8610fda..96b6f44 100644
--- a/ios/chrome/browser/ui/toolbar/toolbar_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/toolbar/toolbar_mediator_unittest.mm
@@ -9,7 +9,6 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_feature_list.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/bookmarks/browser/bookmark_node.h"
 #include "components/bookmarks/common/bookmark_pref_names.h"
@@ -19,7 +18,6 @@
 #include "ios/chrome/browser/bookmarks/bookmark_model_factory.h"
 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
 #include "ios/chrome/browser/chrome_url_constants.h"
-#include "ios/chrome/browser/policy/policy_features.h"
 #import "ios/chrome/browser/ui/toolbar/test/toolbar_test_navigation_manager.h"
 #import "ios/chrome/browser/ui/toolbar/test/toolbar_test_web_state.h"
 #import "ios/chrome/browser/ui/toolbar/toolbar_consumer.h"
@@ -320,9 +318,6 @@
 // Tests that the bookmark button is disabled when the EditBookmarksEnabled pref
 // is false.
 TEST_F(ToolbarMediatorTest, TestBookmarkDisabled) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitAndEnableFeature(kEditBookmarksIOS);
-
   OCMExpect([consumer_ setBookmarkEnabled:YES]);
   SetUpBookmarks();
   mediator_.consumer = consumer_;
diff --git a/ios/chrome/browser/ui/ui_feature_flags.cc b/ios/chrome/browser/ui/ui_feature_flags.cc
index 4376cebe..25d049c 100644
--- a/ios/chrome/browser/ui/ui_feature_flags.cc
+++ b/ios/chrome/browser/ui/ui_feature_flags.cc
@@ -7,12 +7,6 @@
 const base::Feature kExpandedTabStrip{"ExpandedTabStrip",
                                       base::FEATURE_DISABLED_BY_DEFAULT};
 
-// TODO(crbug.com/945811): Using |-drawViewHierarchyInRect:afterScreenUpdates:|
-// has adverse flickering when taking a snapshot of the NTP while in the app
-// switcher.
-const base::Feature kSnapshotDrawView{"SnapshotDrawView",
-                                      base::FEATURE_DISABLED_BY_DEFAULT};
-
 const base::Feature kSettingsRefresh{"SettingsRefresh",
                                      base::FEATURE_DISABLED_BY_DEFAULT};
 
@@ -28,9 +22,6 @@
 const base::Feature kEnableIOSManagedSettingsUI{
     "EnableIOSManagedSettingsUI", base::FEATURE_ENABLED_BY_DEFAULT};
 
-const base::Feature kSafetyCheckIOS{"SafetyCheckIOS",
-                                    base::FEATURE_ENABLED_BY_DEFAULT};
-
 const base::Feature kIllustratedEmptyStates{"IllustratedEmptyStates",
                                             base::FEATURE_ENABLED_BY_DEFAULT};
 
diff --git a/ios/chrome/browser/ui/ui_feature_flags.h b/ios/chrome/browser/ui/ui_feature_flags.h
index ea2e484..6aa77b2 100644
--- a/ios/chrome/browser/ui/ui_feature_flags.h
+++ b/ios/chrome/browser/ui/ui_feature_flags.h
@@ -11,9 +11,6 @@
 // Feature to open tab switcher after sliding down the toolbar.
 extern const base::Feature kExpandedTabStrip;
 
-// Feature to take snapshots using |-drawViewHierarchy:|.
-extern const base::Feature kSnapshotDrawView;
-
 // Feature to apply UI Refresh theme to the settings.
 extern const base::Feature kSettingsRefresh;
 
@@ -32,9 +29,6 @@
 // an enterprise policy.
 extern const base::Feature kEnableIOSManagedSettingsUI;
 
-// Enables the safety check in settings on iOS.
-extern const base::Feature kSafetyCheckIOS;
-
 // Feature flag to enable new illustrations and UI on empty states.
 extern const base::Feature kIllustratedEmptyStates;
 
diff --git a/media/gpu/android/codec_image_unittest.cc b/media/gpu/android/codec_image_unittest.cc
index bc0b5e4..29a09b3 100644
--- a/media/gpu/android/codec_image_unittest.cc
+++ b/media/gpu/android/codec_image_unittest.cc
@@ -49,7 +49,7 @@
         .WillByDefault(Return(MEDIA_CODEC_OK));
 
     gl::init::InitializeStaticGLBindingsImplementation(
-        gl::kGLImplementationEGLGLES2, false);
+        gl::GLImplementationParts(gl::kGLImplementationEGLGLES2), false);
     gl::init::InitializeGLOneOffPlatformImplementation(false, false, false);
 
     surface_ = new gl::PbufferGLSurfaceEGL(gfx::Size(320, 240));
diff --git a/media/gpu/vaapi/vaapi_wrapper.cc b/media/gpu/vaapi/vaapi_wrapper.cc
index 4d36646..a7c377d 100644
--- a/media/gpu/vaapi/vaapi_wrapper.cc
+++ b/media/gpu/vaapi/vaapi_wrapper.cc
@@ -586,7 +586,8 @@
 
     default:
       LOG(WARNING) << "VAAPI video acceleration not available for "
-                   << gl::GetGLImplementationName(gl::GetGLImplementation());
+                   << gl::GetGLImplementationGLName(
+                          gl::GetGLImplementationParts());
       return false;
   }
 
diff --git a/media/gpu/windows/d3d11_texture_wrapper_unittest.cc b/media/gpu/windows/d3d11_texture_wrapper_unittest.cc
index 5c28dd1..3142782 100644
--- a/media/gpu/windows/d3d11_texture_wrapper_unittest.cc
+++ b/media/gpu/windows/d3d11_texture_wrapper_unittest.cc
@@ -45,7 +45,7 @@
     task_runner_ = task_environment_.GetMainThreadTaskRunner();
 
     gl::GLSurfaceTestSupport::InitializeOneOffImplementation(
-        gl::kGLImplementationEGLANGLE, false);
+        gl::GLImplementationParts(gl::ANGLEImplementation::kD3D11), false);
     surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size());
     share_group_ = new gl::GLShareGroup();
     context_ = gl::init::CreateGLContext(share_group_.get(), surface_.get(),
diff --git a/services/cert_verifier/integration_tests/network_context_unittest.cc b/services/cert_verifier/integration_tests/network_context_unittest.cc
index 908bb2c..454f182 100644
--- a/services/cert_verifier/integration_tests/network_context_unittest.cc
+++ b/services/cert_verifier/integration_tests/network_context_unittest.cc
@@ -139,8 +139,8 @@
   auto client = std::make_unique<network::TestURLLoaderClient>();
   mojo::PendingRemote<network::mojom::URLLoader> loader;
   loader_factory->CreateLoaderAndStart(
-      loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-      0 /* request_id */, url_loader_options, request, client->CreateRemote(),
+      loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+      url_loader_options, request, client->CreateRemote(),
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
   client->RunUntilComplete();
diff --git a/services/cert_verifier/integration_tests/network_service_unittest.cc b/services/cert_verifier/integration_tests/network_service_unittest.cc
index cbf9862..e2ebd50 100644
--- a/services/cert_verifier/integration_tests/network_service_unittest.cc
+++ b/services/cert_verifier/integration_tests/network_service_unittest.cc
@@ -109,7 +109,7 @@
 
     loader_.reset();
     loader_factory->CreateLoaderAndStart(
-        loader_.BindNewPipeAndPassReceiver(), 1, 1, options, request,
+        loader_.BindNewPipeAndPassReceiver(), 1, options, request,
         client_->CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
   }
diff --git a/services/network/cors/cors_url_loader.cc b/services/network/cors/cors_url_loader.cc
index 8163a17..374ea34 100644
--- a/services/network/cors/cors_url_loader.cc
+++ b/services/network/cors/cors_url_loader.cc
@@ -60,7 +60,6 @@
 CorsURLLoader::CorsURLLoader(
     mojo::PendingReceiver<mojom::URLLoader> loader_receiver,
     int32_t process_id,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     DeleteCallback delete_callback,
@@ -78,7 +77,6 @@
     mojo::PendingRemote<mojom::DevToolsObserver> devtools_observer)
     : receiver_(this, std::move(loader_receiver)),
       process_id_(process_id),
-      routing_id_(routing_id),
       request_id_(request_id),
       options_(options),
       delete_callback_(std::move(delete_callback)),
@@ -532,8 +530,8 @@
   // |network_client_receiver_| shares this object's lifetime.
   network_loader_.reset();
   network_loader_factory_->CreateLoaderAndStart(
-      network_loader_.BindNewPipeAndPassReceiver(), routing_id_, request_id_,
-      options_, request_, network_client_receiver_.BindNewPipeAndPassRemote(),
+      network_loader_.BindNewPipeAndPassReceiver(), request_id_, options_,
+      request_, network_client_receiver_.BindNewPipeAndPassRemote(),
       traffic_annotation_);
   network_client_receiver_.set_disconnect_handler(
       base::BindOnce(&CorsURLLoader::OnMojoDisconnect, base::Unretained(this)));
diff --git a/services/network/cors/cors_url_loader.h b/services/network/cors/cors_url_loader.h
index 6c6e170..817dd52 100644
--- a/services/network/cors/cors_url_loader.h
+++ b/services/network/cors/cors_url_loader.h
@@ -40,7 +40,6 @@
   CorsURLLoader(
       mojo::PendingReceiver<mojom::URLLoader> loader_receiver,
       int32_t process_id,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       DeleteCallback delete_callback,
@@ -134,7 +133,6 @@
 
   // We need to save these for redirect, and DevTools.
   const int32_t process_id_;
-  const int32_t routing_id_;
   const int32_t request_id_;
   const uint32_t options_;
 
diff --git a/services/network/cors/cors_url_loader_factory.cc b/services/network/cors/cors_url_loader_factory.cc
index ae5daab0..58148c7b 100644
--- a/services/network/cors/cors_url_loader_factory.cc
+++ b/services/network/cors/cors_url_loader_factory.cc
@@ -111,7 +111,6 @@
     // mojom::URLLoaderFactory implementation
     void CreateLoaderAndStart(
         mojo::PendingReceiver<mojom::URLLoader> receiver,
-        int32_t routing_id,
         int32_t request_id,
         uint32_t options,
         const ResourceRequest& request,
@@ -119,8 +118,8 @@
         const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
         override {
       return network_loader_factory_->CreateLoaderAndStart(
-          std::move(receiver), routing_id, request_id, options, request,
-          std::move(client), traffic_annotation);
+          std::move(receiver), request_id, options, request, std::move(client),
+          traffic_annotation);
     }
     void Clone(
         mojo::PendingReceiver<mojom::URLLoaderFactory> receiver) override {
@@ -223,7 +222,6 @@
 
 void CorsURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<mojom::URLLoader> receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const ResourceRequest& resource_request,
@@ -266,7 +264,7 @@
     }
 
     auto loader = std::make_unique<CorsURLLoader>(
-        std::move(receiver), process_id_, routing_id, request_id, options,
+        std::move(receiver), process_id_, request_id, options,
         base::BindOnce(&CorsURLLoaderFactory::DestroyURLLoader,
                        base::Unretained(this)),
         resource_request, ignore_isolated_world_origin_,
@@ -282,7 +280,7 @@
     raw_loader->Start();
   } else {
     inner_url_loader_factory->CreateLoaderAndStart(
-        std::move(receiver), routing_id, request_id, options, resource_request,
+        std::move(receiver), request_id, options, resource_request,
         std::move(client), traffic_annotation);
   }
 }
diff --git a/services/network/cors/cors_url_loader_factory.h b/services/network/cors/cors_url_loader_factory.h
index 73e8501..239b392 100644
--- a/services/network/cors/cors_url_loader_factory.h
+++ b/services/network/cors/cors_url_loader_factory.h
@@ -73,7 +73,6 @@
 
   // Implements mojom::URLLoaderFactory.
   void CreateLoaderAndStart(mojo::PendingReceiver<mojom::URLLoader> receiver,
-                            int32_t routing_id,
                             int32_t request_id,
                             uint32_t options,
                             const ResourceRequest& resource_request,
diff --git a/services/network/cors/cors_url_loader_factory_unittest.cc b/services/network/cors/cors_url_loader_factory_unittest.cc
index 13811282..d27f7e1 100644
--- a/services/network/cors/cors_url_loader_factory_unittest.cc
+++ b/services/network/cors/cors_url_loader_factory_unittest.cc
@@ -82,7 +82,7 @@
 
   void CreateLoaderAndStart(const ResourceRequest& request) {
     cors_url_loader_factory_->CreateLoaderAndStart(
-        url_loader_.BindNewPipeAndPassReceiver(), kRouteId, kRequestId,
+        url_loader_.BindNewPipeAndPassReceiver(), kRequestId,
         mojom::kURLLoadOptionNone, request,
         test_cors_loader_client_.CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
diff --git a/services/network/cors/cors_url_loader_unittest.cc b/services/network/cors/cors_url_loader_unittest.cc
index e3b3dc04..21e07b5b 100644
--- a/services/network/cors/cors_url_loader_unittest.cc
+++ b/services/network/cors/cors_url_loader_unittest.cc
@@ -109,7 +109,6 @@
  private:
   // mojom::URLLoaderFactory implementation.
   void CreateLoaderAndStart(mojo::PendingReceiver<mojom::URLLoader> receiver,
-                            int32_t routing_id,
                             int32_t request_id,
                             uint32_t options,
                             const ResourceRequest& resource_request,
@@ -196,8 +195,8 @@
     test_cors_loader_client_ = std::make_unique<TestURLLoaderClient>();
     url_loader_.reset();
     cors_url_loader_factory_->CreateLoaderAndStart(
-        url_loader_.BindNewPipeAndPassReceiver(), 0 /* routing_id */,
-        0 /* request_id */, mojom::kURLLoadOptionNone, request,
+        url_loader_.BindNewPipeAndPassReceiver(), 0 /* request_id */,
+        mojom::kURLLoadOptionNone, request,
         test_cors_loader_client_->CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
   }
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc
index bea8617..d8c833c6 100644
--- a/services/network/network_context_unittest.cc
+++ b/services/network/network_context_unittest.cc
@@ -244,8 +244,8 @@
   auto client = std::make_unique<TestURLLoaderClient>();
   mojo::PendingRemote<mojom::URLLoader> loader;
   loader_factory->CreateLoaderAndStart(
-      loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-      0 /* request_id */, url_loader_options, request, client->CreateRemote(),
+      loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+      url_loader_options, request, client->CreateRemote(),
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
   client->RunUntilComplete();
@@ -533,8 +533,8 @@
   mojo::PendingRemote<mojom::URLLoader> loader;
   TestURLLoaderClient client;
   loader_factory->CreateLoaderAndStart(
-      loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-      0 /* request_id */, 0 /* options */, request, client.CreateRemote(),
+      loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+      0 /* options */, request, client.CreateRemote(),
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
   client.RunUntilResponseReceived();
@@ -697,8 +697,8 @@
     ResourceRequest request;
     request.url = url;
     loader_factory->CreateLoaderAndStart(
-        loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-        0 /* request_id */, 0 /* options */, request, client.CreateRemote(),
+        loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+        0 /* options */, request, client.CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
     client.RunUntilComplete();
@@ -1257,8 +1257,8 @@
     mojo::PendingRemote<mojom::URLLoader> loader;
     TestURLLoaderClient client;
     loader_factory->CreateLoaderAndStart(
-        loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-        0 /* request_id */, 0 /* options */, request, client.CreateRemote(),
+        loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+        0 /* options */, request, client.CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
     client.RunUntilComplete();
@@ -1321,8 +1321,8 @@
   mojo::PendingRemote<mojom::URLLoader> loader;
   TestURLLoaderClient client;
   loader_factory->CreateLoaderAndStart(
-      loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-      0 /* request_id */, 0 /* options */, request, client.CreateRemote(),
+      loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+      0 /* options */, request, client.CreateRemote(),
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
   client.RunUntilComplete();
@@ -1443,8 +1443,8 @@
       mojo::PendingRemote<mojom::URLLoader> loader;
       TestURLLoaderClient client;
       loader_factory->CreateLoaderAndStart(
-          loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-          0 /* request_id */, 0 /* options */, request, client.CreateRemote(),
+          loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+          0 /* options */, request, client.CreateRemote(),
           net::MutableNetworkTrafficAnnotationTag(
               TRAFFIC_ANNOTATION_FOR_TESTS));
 
@@ -4497,8 +4497,8 @@
     mojo::PendingRemote<mojom::URLLoader> loader;
     TestURLLoaderClient client;
     loader_factory->CreateLoaderAndStart(
-        loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-        0 /* request_id */, 0 /* options */, request, client.CreateRemote(),
+        loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+        0 /* options */, request, client.CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
     client.RunUntilComplete();
@@ -4556,8 +4556,8 @@
     mojo::PendingRemote<mojom::URLLoader> loader;
     TestURLLoaderClient client;
     loader_factory->CreateLoaderAndStart(
-        loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-        0 /* request_id */, 0 /* options */, request, client.CreateRemote(),
+        loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+        0 /* options */, request, client.CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
     client.RunUntilComplete();
@@ -4602,8 +4602,8 @@
     auto client = std::make_unique<TestURLLoaderClient>();
     mojo::Remote<mojom::URLLoader> loader;
     loader_factory->CreateLoaderAndStart(
-        loader.BindNewPipeAndPassReceiver(), 0 /* routing_id */,
-        0 /* request_id */, 0 /* options */, request, client->CreateRemote(),
+        loader.BindNewPipeAndPassReceiver(), 0 /* request_id */,
+        0 /* options */, request, client->CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
     client->RunUntilComplete();
@@ -5055,8 +5055,8 @@
   mojo::PendingRemote<mojom::URLLoader> loader;
   TestURLLoaderClient client;
   loader_factory->CreateLoaderAndStart(
-      loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-      0 /* request_id */, 0 /* options */, request, client.CreateRemote(),
+      loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+      0 /* options */, request, client.CreateRemote(),
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
   // Confirm the the resource request failed due to an unreachable proxy.
@@ -5110,8 +5110,8 @@
   mojo::PendingRemote<mojom::URLLoader> loader;
   TestURLLoaderClient client;
   loader_factory->CreateLoaderAndStart(
-      loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-      0 /* request_id */, 0 /* options */, request, client.CreateRemote(),
+      loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+      0 /* options */, request, client.CreateRemote(),
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
   // Confirm the the resource request failed.
@@ -5184,8 +5184,8 @@
   mojo::PendingRemote<mojom::URLLoader> loader;
   TestURLLoaderClient client;
   loader_factory->CreateLoaderAndStart(
-      loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-      0 /* request_id */, 0 /* options */, request, client.CreateRemote(),
+      loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+      0 /* options */, request, client.CreateRemote(),
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
   // Confirm the the resource request failed.
@@ -5265,8 +5265,8 @@
     mojo::PendingRemote<mojom::URLLoader> loader;
     TestURLLoaderClient client;
     loader_factory->CreateLoaderAndStart(
-        loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-        0 /* request_id */, 0 /* options */, request, client.CreateRemote(),
+        loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+        0 /* options */, request, client.CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
     client.RunUntilComplete();
@@ -5381,9 +5381,8 @@
     mojo::PendingRemote<mojom::URLLoader> loader;
     TestURLLoaderClient client;
     loader_factory->CreateLoaderAndStart(
-        loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-        0 /* request_id */, mojom::kURLLoadOptionUseHeaderClient, request,
-        client.CreateRemote(),
+        loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+        mojom::kURLLoadOptionUseHeaderClient, request, client.CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
     client.RunUntilComplete();
@@ -5405,8 +5404,8 @@
     mojo::PendingRemote<mojom::URLLoader> loader;
     TestURLLoaderClient client;
     loader_factory->CreateLoaderAndStart(
-        loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-        0 /* request_id */, 0 /* options */, request, client.CreateRemote(),
+        loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+        0 /* options */, request, client.CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
     client.RunUntilComplete();
@@ -5449,9 +5448,8 @@
     mojo::PendingRemote<mojom::URLLoader> loader;
     TestURLLoaderClient client;
     loader_factory->CreateLoaderAndStart(
-        loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-        0 /* request_id */, mojom::kURLLoadOptionUseHeaderClient, request,
-        client.CreateRemote(),
+        loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+        mojom::kURLLoadOptionUseHeaderClient, request, client.CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
     client.RunUntilComplete();
@@ -5465,9 +5463,8 @@
     mojo::PendingRemote<mojom::URLLoader> loader;
     TestURLLoaderClient client;
     loader_factory->CreateLoaderAndStart(
-        loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-        0 /* request_id */, mojom::kURLLoadOptionUseHeaderClient, request,
-        client.CreateRemote(),
+        loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+        mojom::kURLLoadOptionUseHeaderClient, request, client.CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
     client.RunUntilComplete();
@@ -5600,9 +5597,8 @@
   mojo::PendingRemote<mojom::URLLoader> loader;
   TestURLLoaderClient client;
   loader_factory->CreateLoaderAndStart(
-      loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-      0 /* request_id */, mojom::kURLLoadOptionUseHeaderClient, request,
-      client.CreateRemote(),
+      loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+      mojom::kURLLoadOptionUseHeaderClient, request, client.CreateRemote(),
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
   header_client.WaitForOnBeforeSendHeaders();
@@ -5651,9 +5647,8 @@
   mojo::PendingRemote<mojom::URLLoader> loader;
   TestURLLoaderClient client;
   loader_factory->CreateLoaderAndStart(
-      loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-      0 /* request_id */, mojom::kURLLoadOptionUseHeaderClient, request,
-      client.CreateRemote(),
+      loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+      mojom::kURLLoadOptionUseHeaderClient, request, client.CreateRemote(),
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
   header_client.WaitForOnBeforeSendHeaders();
@@ -5696,9 +5691,8 @@
   mojo::PendingRemote<mojom::URLLoader> loader;
   TestURLLoaderClient client;
   loader_factory->CreateLoaderAndStart(
-      loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-      0 /* request_id */, mojom::kURLLoadOptionUseHeaderClient, request,
-      client.CreateRemote(),
+      loader.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+      mojom::kURLLoadOptionUseHeaderClient, request, client.CreateRemote(),
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
   header_client.WaitForOnBeforeSendHeaders();
@@ -5823,16 +5817,16 @@
   auto client1 = std::make_unique<TestURLLoaderClient>();
   mojo::PendingRemote<mojom::URLLoader> loader1;
   loader_factory->CreateLoaderAndStart(
-      loader1.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-      0 /* request_id */, 0 /* options */, request, client1->CreateRemote(),
+      loader1.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+      0 /* options */, request, client1->CreateRemote(),
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
   request.url = test_server.GetURL(kPath2);
   auto client2 = std::make_unique<TestURLLoaderClient>();
   mojo::PendingRemote<mojom::URLLoader> loader2;
   loader_factory->CreateLoaderAndStart(
-      loader2.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
-      0 /* request_id */, 0 /* options */, request, client2->CreateRemote(),
+      loader2.InitWithNewPipeAndPassReceiver(), 0 /* request_id */,
+      0 /* options */, request, client2->CreateRemote(),
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
   // A third request should fail, since the first two are outstanding and the
@@ -5841,8 +5835,8 @@
   auto client3 = std::make_unique<TestURLLoaderClient>();
   mojo::Remote<mojom::URLLoader> loader3;
   loader_factory->CreateLoaderAndStart(
-      loader3.BindNewPipeAndPassReceiver(), 0 /* routing_id */,
-      0 /* request_id */, 0 /* options */, request, client3->CreateRemote(),
+      loader3.BindNewPipeAndPassReceiver(), 0 /* request_id */, 0 /* options */,
+      request, client3->CreateRemote(),
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
   client3->RunUntilComplete();
@@ -5860,8 +5854,8 @@
   client3 = std::make_unique<TestURLLoaderClient>();
   loader3.reset();
   loader_factory->CreateLoaderAndStart(
-      loader3.BindNewPipeAndPassReceiver(), 0 /* routing_id */,
-      0 /* request_id */, 0 /* options */, request, client3->CreateRemote(),
+      loader3.BindNewPipeAndPassReceiver(), 0 /* request_id */, 0 /* options */,
+      request, client3->CreateRemote(),
       net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
   client3->RunUntilComplete();
@@ -6492,9 +6486,8 @@
     auto client = std::make_unique<TestURLLoaderClient>();
     mojo::Remote<mojom::URLLoader> loader;
     loader_factory->CreateLoaderAndStart(
-        loader.BindNewPipeAndPassReceiver(), 0 /* routing_id */,
-        0 /* request_id */, mojom::kURLLoadOptionNone, request,
-        client->CreateRemote(),
+        loader.BindNewPipeAndPassReceiver(), 0 /* request_id */,
+        mojom::kURLLoadOptionNone, request, client->CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
 
     if (expect_redirect) {
diff --git a/services/network/network_service_unittest.cc b/services/network/network_service_unittest.cc
index a0db7c7..d624b771 100644
--- a/services/network/network_service_unittest.cc
+++ b/services/network/network_service_unittest.cc
@@ -938,7 +938,7 @@
 
     loader_.reset();
     loader_factory->CreateLoaderAndStart(
-        loader_.BindNewPipeAndPassReceiver(), 1, 1, options, request,
+        loader_.BindNewPipeAndPassReceiver(), 1, options, request,
         client_->CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
   }
@@ -1436,7 +1436,7 @@
 
     loader_.reset();
     loader_factory->CreateLoaderAndStart(
-        loader_.BindNewPipeAndPassReceiver(), 1, 1, options, request,
+        loader_.BindNewPipeAndPassReceiver(), 1, options, request,
         client_->CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
   }
diff --git a/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.cc b/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.cc
index 89f797c..e8439fc 100644
--- a/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.cc
+++ b/services/network/public/cpp/cross_thread_pending_shared_url_loader_factory.cc
@@ -39,7 +39,6 @@
   // Delegation for mojom::URLLoaderFactory API.
   void CreateLoaderAndStart(
       mojo::PendingReceiver<mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const ResourceRequest& request,
@@ -83,7 +82,6 @@
 
   // mojom::URLLoaderFactory implementation:
   void CreateLoaderAndStart(mojo::PendingReceiver<mojom::URLLoader> loader,
-                            int32_t routing_id,
                             int32_t request_id,
                             uint32_t options,
                             const ResourceRequest& request,
@@ -116,7 +114,6 @@
 
 void CrossThreadSharedURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<mojom::URLLoader> loader,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const ResourceRequest& request,
@@ -126,14 +123,14 @@
   base::SequencedTaskRunner* runner = state_->task_runner();
   if (runner->RunsTasksInCurrentSequence()) {
     state_->base_factory()->CreateLoaderAndStart(
-        std::move(loader), routing_id, request_id, options, request,
-        std::move(client), traffic_annotation);
+        std::move(loader), request_id, options, request, std::move(client),
+        traffic_annotation);
   } else {
     state_->task_runner()->PostTask(
         FROM_HERE,
         base::BindOnce(&State::CreateLoaderAndStart, state_, std::move(loader),
-                       routing_id, request_id, options, request,
-                       std::move(client), traffic_annotation));
+                       request_id, options, request, std::move(client),
+                       traffic_annotation));
   }
 }
 
@@ -192,15 +189,14 @@
 
 void CrossThreadPendingSharedURLLoaderFactory::State::CreateLoaderAndStart(
     mojo::PendingReceiver<mojom::URLLoader> loader,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const ResourceRequest& request,
     mojo::PendingRemote<mojom::URLLoaderClient> client,
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  base_factory_->CreateLoaderAndStart(std::move(loader), routing_id, request_id,
-                                      options, request, std::move(client),
+  base_factory_->CreateLoaderAndStart(std::move(loader), request_id, options,
+                                      request, std::move(client),
                                       traffic_annotation);
 }
 
diff --git a/services/network/public/cpp/not_implemented_url_loader_factory.cc b/services/network/public/cpp/not_implemented_url_loader_factory.cc
index aef437b8..99918f1 100644
--- a/services/network/public/cpp/not_implemented_url_loader_factory.cc
+++ b/services/network/public/cpp/not_implemented_url_loader_factory.cc
@@ -18,7 +18,6 @@
 
 void NotImplementedURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& url_request,
diff --git a/services/network/public/cpp/not_implemented_url_loader_factory.h b/services/network/public/cpp/not_implemented_url_loader_factory.h
index a630aade..045d9450 100644
--- a/services/network/public/cpp/not_implemented_url_loader_factory.h
+++ b/services/network/public/cpp/not_implemented_url_loader_factory.h
@@ -32,7 +32,6 @@
   // network::mojom::URLLoaderFactory implementation.
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& url_request,
diff --git a/services/network/public/cpp/simple_url_loader.cc b/services/network/public/cpp/simple_url_loader.cc
index 513011a..c4e1aedc 100644
--- a/services/network/public/cpp/simple_url_loader.cc
+++ b/services/network/public/cpp/simple_url_loader.cc
@@ -1541,7 +1541,7 @@
         string_upload_data_pipe_getter_->GetRemoteForNewUpload());
   }
   url_loader_factory->CreateLoaderAndStart(
-      url_loader_.BindNewPipeAndPassReceiver(), 0 /* routing_id */, request_id_,
+      url_loader_.BindNewPipeAndPassReceiver(), request_id_,
       url_loader_factory_options_, *resource_request_,
       client_receiver_.BindNewPipeAndPassRemote(),
       net::MutableNetworkTrafficAnnotationTag(annotation_tag_));
diff --git a/services/network/public/cpp/simple_url_loader_unittest.cc b/services/network/public/cpp/simple_url_loader_unittest.cc
index 0ecbbd7..dc86db8 100644
--- a/services/network/public/cpp/simple_url_loader_unittest.cc
+++ b/services/network/public/cpp/simple_url_loader_unittest.cc
@@ -2254,7 +2254,6 @@
 
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> url_loader_receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& url_request,
diff --git a/services/network/public/cpp/weak_wrapper_shared_url_loader_factory.cc b/services/network/public/cpp/weak_wrapper_shared_url_loader_factory.cc
index 5d149886..be627c65 100644
--- a/services/network/public/cpp/weak_wrapper_shared_url_loader_factory.cc
+++ b/services/network/public/cpp/weak_wrapper_shared_url_loader_factory.cc
@@ -23,7 +23,6 @@
 
 void WeakWrapperSharedURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<mojom::URLLoader> loader,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
@@ -31,8 +30,8 @@
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
   if (!factory())
     return;
-  factory()->CreateLoaderAndStart(std::move(loader), routing_id, request_id,
-                                  options, request, std::move(client),
+  factory()->CreateLoaderAndStart(std::move(loader), request_id, options,
+                                  request, std::move(client),
                                   traffic_annotation);
 }
 
diff --git a/services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h b/services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h
index 274751a2..9d2f001 100644
--- a/services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h
+++ b/services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h
@@ -34,7 +34,6 @@
 
   // SharedURLLoaderFactory implementation.
   void CreateLoaderAndStart(mojo::PendingReceiver<mojom::URLLoader> loader,
-                            int32_t routing_id,
                             int32_t request_id,
                             uint32_t options,
                             const network::ResourceRequest& request,
diff --git a/services/network/public/cpp/wrapper_shared_url_loader_factory.h b/services/network/public/cpp/wrapper_shared_url_loader_factory.h
index 88a47dc..67684fb 100644
--- a/services/network/public/cpp/wrapper_shared_url_loader_factory.h
+++ b/services/network/public/cpp/wrapper_shared_url_loader_factory.h
@@ -52,7 +52,6 @@
 
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
@@ -61,9 +60,9 @@
       override {
     if (!factory_remote_)
       return;
-    factory_remote_->CreateLoaderAndStart(
-        std::move(loader), routing_id, request_id, options, request,
-        std::move(client), traffic_annotation);
+    factory_remote_->CreateLoaderAndStart(std::move(loader), request_id,
+                                          options, request, std::move(client),
+                                          traffic_annotation);
   }
 
   void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver)
diff --git a/services/network/public/mojom/url_loader_factory.mojom b/services/network/public/mojom/url_loader_factory.mojom
index 100c7c88..7b9b030 100644
--- a/services/network/public/mojom/url_loader_factory.mojom
+++ b/services/network/public/mojom/url_loader_factory.mojom
@@ -61,18 +61,12 @@
   // methods will be called when certain events related to that loading
   // (e.g., response arrival) happen.
   //
-  // |routing_id| is the routing_id for subframe requests, and is the
-  // frame_tree_node_id for frame requests.
-  // TODO: once MojoLoading is only codepath and we have one factory per frame,
-  // remove this.
-  //
   // |request_id| is an arbitrary id for the request. The (routing_id,
   // request_id) pair must be unique over all calls to CreateLoaderAndStart()
   // on this factory.
   //
   // |options| is a bitfield of the options defined above.
   CreateLoaderAndStart(pending_receiver<URLLoader> loader,
-                       int32 routing_id,
                        int32 request_id,
                        uint32 options,
                        URLRequest request,
diff --git a/services/network/test/test_shared_url_loader_factory.cc b/services/network/test/test_shared_url_loader_factory.cc
index 29963a5..88144d3 100644
--- a/services/network/test/test_shared_url_loader_factory.cc
+++ b/services/network/test/test_shared_url_loader_factory.cc
@@ -33,7 +33,6 @@
 
 void TestSharedURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<mojom::URLLoader> loader,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const ResourceRequest& request,
@@ -41,7 +40,7 @@
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
   num_created_loaders_++;
   url_loader_factory_->CreateLoaderAndStart(
-      std::move(loader), routing_id, request_id, options, std::move(request),
+      std::move(loader), request_id, options, std::move(request),
       std::move(client), traffic_annotation);
 }
 
diff --git a/services/network/test/test_shared_url_loader_factory.h b/services/network/test/test_shared_url_loader_factory.h
index 91ed010f..46936b1 100644
--- a/services/network/test/test_shared_url_loader_factory.h
+++ b/services/network/test/test_shared_url_loader_factory.h
@@ -32,7 +32,6 @@
 
   // URLLoaderFactory implementation:
   void CreateLoaderAndStart(mojo::PendingReceiver<mojom::URLLoader> loader,
-                            int32_t routing_id,
                             int32_t request_id,
                             uint32_t options,
                             const ResourceRequest& request,
diff --git a/services/network/test/test_url_loader_factory.cc b/services/network/test/test_url_loader_factory.cc
index 8dd112b7..8d9ab72 100644
--- a/services/network/test/test_url_loader_factory.cc
+++ b/services/network/test/test_url_loader_factory.cc
@@ -117,7 +117,6 @@
 
 void TestURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<mojom::URLLoader> receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const ResourceRequest& url_request,
diff --git a/services/network/test/test_url_loader_factory.h b/services/network/test/test_url_loader_factory.h
index 4b59a35..7d30b15 100644
--- a/services/network/test/test_url_loader_factory.h
+++ b/services/network/test/test_url_loader_factory.h
@@ -145,7 +145,6 @@
 
   // mojom::URLLoaderFactory implementation.
   void CreateLoaderAndStart(mojo::PendingReceiver<mojom::URLLoader> receiver,
-                            int32_t routing_id,
                             int32_t request_id,
                             uint32_t options,
                             const ResourceRequest& url_request,
diff --git a/services/network/test/test_url_loader_factory_unittest.cc b/services/network/test/test_url_loader_factory_unittest.cc
index c95a1f52..57d28faf 100644
--- a/services/network/test/test_url_loader_factory_unittest.cc
+++ b/services/network/test/test_url_loader_factory_unittest.cc
@@ -32,7 +32,7 @@
     request.report_raw_headers = report_raw_headers;
     loader_.reset();
     factory_.CreateLoaderAndStart(
-        loader_.BindNewPipeAndPassReceiver(), 0, 0, 0, request,
+        loader_.BindNewPipeAndPassReceiver(), 0, 0, request,
         client->CreateRemote(),
         net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
   }
diff --git a/services/network/url_loader_factory.cc b/services/network/url_loader_factory.cc
index 766d3433..60a6152 100644
--- a/services/network/url_loader_factory.cc
+++ b/services/network/url_loader_factory.cc
@@ -109,7 +109,6 @@
 
 void URLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<mojom::URLLoader> receiver,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const ResourceRequest& url_request,
diff --git a/services/network/url_loader_factory.h b/services/network/url_loader_factory.h
index f0e423b..dff6224 100644
--- a/services/network/url_loader_factory.h
+++ b/services/network/url_loader_factory.h
@@ -54,7 +54,6 @@
 
   // mojom::URLLoaderFactory implementation.
   void CreateLoaderAndStart(mojo::PendingReceiver<mojom::URLLoader> receiver,
-                            int32_t routing_id,
                             int32_t request_id,
                             uint32_t options,
                             const ResourceRequest& url_request,
diff --git a/storage/browser/blob/blob_url_loader_factory.cc b/storage/browser/blob/blob_url_loader_factory.cc
index 48399bfb..a6ac1405 100644
--- a/storage/browser/blob/blob_url_loader_factory.cc
+++ b/storage/browser/blob/blob_url_loader_factory.cc
@@ -59,7 +59,6 @@
 
 void BlobURLLoaderFactory::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> loader,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
diff --git a/storage/browser/blob/blob_url_loader_factory.h b/storage/browser/blob/blob_url_loader_factory.h
index 7fcb2447..76ba963 100644
--- a/storage/browser/blob/blob_url_loader_factory.h
+++ b/storage/browser/blob/blob_url_loader_factory.h
@@ -39,7 +39,6 @@
   // URLLoaderFactory:
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/storage/browser/database/database_tracker.cc b/storage/browser/database/database_tracker.cc
index 44fa2e1..57ac076b 100644
--- a/storage/browser/database/database_tracker.cc
+++ b/storage/browser/database/database_tracker.cc
@@ -102,7 +102,6 @@
 void DatabaseTracker::DatabaseOpened(const std::string& origin_identifier,
                                      const std::u16string& database_name,
                                      const std::u16string& database_description,
-                                     int64_t estimated_size,
                                      int64_t* database_size) {
   DCHECK(task_runner_->RunsTasksInCurrentSequence());
   if (shutting_down_ || !LazyInit()) {
@@ -116,7 +115,7 @@
         blink::mojom::StorageType::kTemporary, base::Time::Now());
 
   InsertOrUpdateDatabaseDetails(origin_identifier, database_name,
-                                database_description, estimated_size);
+                                database_description);
   if (database_connections_.AddConnection(origin_identifier, database_name)) {
     *database_size = SeedOpenDatabaseInfo(origin_identifier,
                                           database_name,
@@ -528,8 +527,7 @@
 void DatabaseTracker::InsertOrUpdateDatabaseDetails(
     const std::string& origin_identifier,
     const std::u16string& database_name,
-    const std::u16string& database_description,
-    int64_t estimated_size) {
+    const std::u16string& database_description) {
   DCHECK(task_runner_->RunsTasksInCurrentSequence());
   DatabaseDetails details;
   if (!databases_table_->GetDatabaseDetails(
@@ -537,12 +535,9 @@
     details.origin_identifier = origin_identifier;
     details.database_name = database_name;
     details.description = database_description;
-    details.estimated_size = estimated_size;
     databases_table_->InsertDatabaseDetails(details);
-  } else if ((details.description != database_description) ||
-             (details.estimated_size != estimated_size)) {
+  } else if (details.description != database_description) {
     details.description = database_description;
-    details.estimated_size = estimated_size;
     databases_table_->UpdateDatabaseDetails(details);
   }
 }
diff --git a/storage/browser/database/database_tracker.h b/storage/browser/database/database_tracker.h
index a46bc25..b8cf349 100644
--- a/storage/browser/database/database_tracker.h
+++ b/storage/browser/database/database_tracker.h
@@ -96,7 +96,6 @@
   void DatabaseOpened(const std::string& origin_identifier,
                       const std::u16string& database_name,
                       const std::u16string& database_details,
-                      int64_t estimated_size,
                       int64_t* database_size);
   void DatabaseModified(const std::string& origin_identifier,
                         const std::u16string& database_name);
@@ -234,8 +233,7 @@
   bool UpgradeToCurrentVersion();
   void InsertOrUpdateDatabaseDetails(const std::string& origin_identifier,
                                      const std::u16string& database_name,
-                                     const std::u16string& database_details,
-                                     int64_t estimated_size);
+                                     const std::u16string& database_details);
 
   void ClearAllCachedOriginInfo();
   CachedOriginInfo* MaybeGetCachedOriginInfo(
diff --git a/storage/browser/database/database_tracker_unittest.cc b/storage/browser/database/database_tracker_unittest.cc
index d39a934..b4a517f4 100644
--- a/storage/browser/database/database_tracker_unittest.cc
+++ b/storage/browser/database/database_tracker_unittest.cc
@@ -230,12 +230,9 @@
           const std::u16string kDB3 = u"db3";
           const std::u16string kDescription = u"database_description";
 
-          tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
-                                  &database_size);
-          tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0,
-                                  &database_size);
-          tracker->DatabaseOpened(kOrigin2, kDB3, kDescription, 0,
-                                  &database_size);
+          tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, &database_size);
+          tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, &database_size);
+          tracker->DatabaseOpened(kOrigin2, kDB3, kDescription, &database_size);
 
           EXPECT_TRUE(
               base::CreateDirectory(tracker->GetOriginDirectory(kOrigin1)));
@@ -266,8 +263,7 @@
           EXPECT_FALSE(base::PathExists(tracker->GetOriginDirectory(kOrigin1)));
 
           // Recreate db1.
-          tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
-                                  &database_size);
+          tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, &database_size);
           EXPECT_TRUE(
               base::CreateDirectory(tracker->GetOriginDirectory(kOrigin1)));
           EXPECT_TRUE(
@@ -355,14 +351,11 @@
           EXPECT_TRUE(origin1_info);
           EXPECT_TRUE(origin2_info);
 
-          tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
-                                  &database_size);
+          tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, &database_size);
           EXPECT_EQ(0, database_size);
-          tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0,
-                                  &database_size);
+          tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, &database_size);
           EXPECT_EQ(0, database_size);
-          tracker->DatabaseOpened(kOrigin1, kDB3, kDescription, 0,
-                                  &database_size);
+          tracker->DatabaseOpened(kOrigin1, kDB3, kDescription, &database_size);
           EXPECT_EQ(0, database_size);
 
           // Write some data to each file and check that the listeners are
@@ -393,8 +386,7 @@
           tracker->DatabaseClosed(kOrigin1, kDB3);
 
           // Open an existing database and check the reported size
-          tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
-                                  &database_size);
+          tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, &database_size);
           EXPECT_EQ(1, database_size);
           tracker->DatabaseClosed(kOrigin1, kDB1);
 
@@ -405,8 +397,7 @@
           // Then make sure that DatabaseOpened() still returns the correct
           // result.
           tracker->CloseTrackerDatabaseAndClearCaches();
-          tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
-                                  &database_size);
+          tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, &database_size);
           EXPECT_EQ(1, database_size);
           tracker->DatabaseClosed(kOrigin1, kDB1);
 
@@ -414,8 +405,7 @@
           tracker->RemoveObserver(&observer1);
 
           // Trying to delete a database in use should fail
-          tracker->DatabaseOpened(kOrigin1, kDB3, kDescription, 0,
-                                  &database_size);
+          tracker->DatabaseOpened(kOrigin1, kDB3, kDescription, &database_size);
           EXPECT_FALSE(tracker->DeleteClosedDatabase(kOrigin1, kDB3));
           origin1_info = tracker->GetCachedOriginInfo(kOrigin1);
           EXPECT_TRUE(origin1_info);
@@ -443,8 +433,7 @@
           EXPECT_EQ(2, origins_info[1].TotalSize());
 
           // Trying to delete an origin with databases in use should fail
-          tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
-                                  &database_size);
+          tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, &database_size);
           EXPECT_FALSE(tracker->DeleteOrigin(kOrigin1, false));
           origin1_info = tracker->GetCachedOriginInfo(kOrigin1);
           EXPECT_TRUE(origin1_info);
@@ -494,7 +483,7 @@
           // then delete it. Observe the tracker notifies accordingly.
 
           int64_t database_size = 0;
-          tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
+          tracker->DatabaseOpened(kOriginId, kName, kDescription,
                                   &database_size);
           EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
           test_quota_proxy->reset();
@@ -531,7 +520,7 @@
           // then close it (at which time deletion will actually occur).
           // Observe the tracker notifies accordingly.
 
-          tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
+          tracker->DatabaseOpened(kOriginId, kName, kDescription,
                                   &database_size);
           EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
           test_quota_proxy->reset();
@@ -568,7 +557,7 @@
           // a renderer crash.
           // Observe the tracker notifies accordingly.
 
-          tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
+          tracker->DatabaseOpened(kOriginId, kName, kDescription,
                                   &database_size);
           EXPECT_TRUE(test_quota_proxy->WasAccessNotified(kOrigin));
           test_quota_proxy->reset();
@@ -620,10 +609,10 @@
                 base::BindLambdaForTesting([&]() { run_loop.Quit(); }));
 
             // Open two new databases.
-            tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
+            tracker->DatabaseOpened(kOrigin1, kDB1, kDescription,
                                     &database_size);
             EXPECT_EQ(0, database_size);
-            tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0,
+            tracker->DatabaseOpened(kOrigin2, kDB2, kDescription,
                                     &database_size);
             EXPECT_EQ(0, database_size);
 
@@ -717,10 +706,10 @@
             tracker->SetForceKeepSessionState();
 
             // Open two new databases.
-            tracker->DatabaseOpened(kOrigin1, kDB1, kDescription, 0,
+            tracker->DatabaseOpened(kOrigin1, kDB1, kDescription,
                                     &database_size);
             EXPECT_EQ(0, database_size);
-            tracker->DatabaseOpened(kOrigin2, kDB2, kDescription, 0,
+            tracker->DatabaseOpened(kOrigin2, kDB2, kDescription,
                                     &database_size);
             EXPECT_EQ(0, database_size);
 
@@ -807,7 +796,7 @@
 
           // Create a db with an empty name.
           int64_t database_size = -1;
-          tracker->DatabaseOpened(kOriginId, kEmptyName, kDescription, 0,
+          tracker->DatabaseOpened(kOriginId, kEmptyName, kDescription,
                                   &database_size);
           EXPECT_EQ(0, database_size);
           tracker->DatabaseModified(kOriginId, kEmptyName);
@@ -815,7 +804,7 @@
           EXPECT_EQ(1u, infos.size());
           EXPECT_FALSE(
               tracker->GetFullDBFilePath(kOriginId, kEmptyName).empty());
-          tracker->DatabaseOpened(kOriginId, kEmptyName, kChangedDescription, 0,
+          tracker->DatabaseOpened(kOriginId, kEmptyName, kChangedDescription,
                                   &database_size);
           infos.clear();
           EXPECT_TRUE(tracker->GetAllOriginsInfo(&infos));
@@ -870,7 +859,7 @@
           // Create a record of a database in the tracker db and create
           // a spoof_db_file on disk in the expected location.
           int64_t database_size = 0;
-          tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
+          tracker->DatabaseOpened(kOriginId, kName, kDescription,
                                   &database_size);
           base::FilePath spoof_db_file =
               tracker->GetFullDBFilePath(kOriginId, kName);
@@ -901,7 +890,7 @@
           // --------------------------------------------------------
           // Create another record of a database in the tracker db and create
           // a spoof_db_file on disk in the expected location.
-          tracker->DatabaseOpened(kOriginId, kName, kDescription, 0,
+          tracker->DatabaseOpened(kOriginId, kName, kDescription,
                                   &database_size);
           base::FilePath spoof_db_file2 =
               tracker->GetFullDBFilePath(kOriginId, kName);
diff --git a/storage/browser/database/databases_table.cc b/storage/browser/database/databases_table.cc
index 9193aa5..a43bcd0 100644
--- a/storage/browser/database/databases_table.cc
+++ b/storage/browser/database/databases_table.cc
@@ -11,7 +11,7 @@
 
 namespace storage {
 
-DatabaseDetails::DatabaseDetails() : estimated_size(0) { }
+DatabaseDetails::DatabaseDetails() = default;
 
 DatabaseDetails::DatabaseDetails(const DatabaseDetails& other) = default;
 
@@ -59,7 +59,7 @@
                                         DatabaseDetails* details) {
   DCHECK(details);
   sql::Statement select_statement(db_->GetCachedStatement(
-      SQL_FROM_HERE, "SELECT description, estimated_size FROM Databases "
+      SQL_FROM_HERE, "SELECT description FROM Databases "
                      "WHERE origin = ? AND name = ?"));
   select_statement.BindString(0, origin_identifier);
   select_statement.BindString16(1, database_name);
@@ -68,7 +68,6 @@
     details->origin_identifier = origin_identifier;
     details->database_name = database_name;
     details->description = select_statement.ColumnString16(0);
-    details->estimated_size = select_statement.ColumnInt64(1);
     return true;
   }
 
@@ -78,23 +77,21 @@
 bool DatabasesTable::InsertDatabaseDetails(const DatabaseDetails& details) {
   sql::Statement insert_statement(db_->GetCachedStatement(
       SQL_FROM_HERE, "INSERT INTO Databases (origin, name, description, "
-                     "estimated_size) VALUES (?, ?, ?, ?)"));
+                     "estimated_size) VALUES (?, ?, ?, 0)"));
   insert_statement.BindString(0, details.origin_identifier);
   insert_statement.BindString16(1, details.database_name);
   insert_statement.BindString16(2, details.description);
-  insert_statement.BindInt64(3, details.estimated_size);
 
   return insert_statement.Run();
 }
 
 bool DatabasesTable::UpdateDatabaseDetails(const DatabaseDetails& details) {
   sql::Statement update_statement(db_->GetCachedStatement(
-      SQL_FROM_HERE, "UPDATE Databases SET description = ?, "
-                     "estimated_size = ? WHERE origin = ? AND name = ?"));
+      SQL_FROM_HERE, "UPDATE Databases SET description = ? "
+                     "WHERE origin = ? AND name = ?"));
   update_statement.BindString16(0, details.description);
-  update_statement.BindInt64(1, details.estimated_size);
-  update_statement.BindString(2, details.origin_identifier);
-  update_statement.BindString16(3, details.database_name);
+  update_statement.BindString(1, details.origin_identifier);
+  update_statement.BindString16(2, details.database_name);
 
   return (update_statement.Run() && db_->GetLastChangeCount());
 }
@@ -125,7 +122,7 @@
     const std::string& origin_identifier,
     std::vector<DatabaseDetails>* details_vector) {
   sql::Statement statement(db_->GetCachedStatement(
-      SQL_FROM_HERE, "SELECT name, description, estimated_size "
+      SQL_FROM_HERE, "SELECT name, description "
                      "FROM Databases WHERE origin = ? ORDER BY name"));
   statement.BindString(0, origin_identifier);
 
@@ -134,7 +131,6 @@
     details.origin_identifier = origin_identifier;
     details.database_name = statement.ColumnString16(0);
     details.description = statement.ColumnString16(1);
-    details.estimated_size = statement.ColumnInt64(2);
     details_vector->push_back(details);
   }
 
diff --git a/storage/browser/database/databases_table.h b/storage/browser/database/databases_table.h
index 1306c146..fc7bc701 100644
--- a/storage/browser/database/databases_table.h
+++ b/storage/browser/database/databases_table.h
@@ -26,7 +26,6 @@
   std::string origin_identifier;
   std::u16string database_name;
   std::u16string description;
-  int64_t estimated_size;
 };
 
 class COMPONENT_EXPORT(STORAGE_BROWSER) DatabasesTable {
diff --git a/storage/browser/database/databases_table_unittest.cc b/storage/browser/database/databases_table_unittest.cc
index 52b6720..e2d24fc 100644
--- a/storage/browser/database/databases_table_unittest.cc
+++ b/storage/browser/database/databases_table_unittest.cc
@@ -22,7 +22,6 @@
   EXPECT_EQ(d1.origin_identifier, d2.origin_identifier);
   EXPECT_EQ(d1.database_name, d2.database_name);
   EXPECT_EQ(d1.description, d2.description);
-  EXPECT_EQ(d1.estimated_size, d2.estimated_size);
 }
 
 static bool DatabasesTableIsEmpty(sql::Database* db) {
@@ -57,7 +56,6 @@
   details_in1.origin_identifier = "origin1";
   details_in1.database_name = u"db1";
   details_in1.description = u"description_db1";
-  details_in1.estimated_size = 100;
 
   // Updating details for this database should fail.
   EXPECT_FALSE(databases_table.UpdateDatabaseDetails(details_in1));
@@ -82,7 +80,6 @@
   details_in2.origin_identifier = "origin1";
   details_in2.database_name = u"db2";
   details_in2.description = u"description_db2";
-  details_in2.estimated_size = 200;
   EXPECT_TRUE(databases_table.InsertDatabaseDetails(details_in2));
   EXPECT_EQ(2, databases_table.GetDatabaseID(details_in2.origin_identifier,
                                              details_in2.database_name));
@@ -92,7 +89,6 @@
   details_in3.origin_identifier = "origin2";
   details_in3.database_name = u"db3";
   details_in3.description = u"description_db3";
-  details_in3.estimated_size = 300;
   EXPECT_TRUE(databases_table.InsertDatabaseDetails(details_in3));
   EXPECT_EQ(3, databases_table.GetDatabaseID(details_in3.origin_identifier,
                                              details_in3.database_name));
diff --git a/testing/scripts/wpt_common.py b/testing/scripts/wpt_common.py
index 4f257dc..2a1198f 100644
--- a/testing/scripts/wpt_common.py
+++ b/testing/scripts/wpt_common.py
@@ -14,6 +14,7 @@
 BLINK_TOOLS_DIR = os.path.join(common.SRC_DIR, 'third_party', 'blink', 'tools')
 WEB_TESTS_DIR = os.path.join(BLINK_TOOLS_DIR, os.pardir, 'web_tests')
 EXTERNAL_WPT_TESTS_DIR = os.path.join(WEB_TESTS_DIR, 'external', 'wpt')
+LAYOUT_TEST_RESULTS_SUBDIR = 'layout-test-results'
 
 if BLINK_TOOLS_DIR not in sys.path:
     sys.path.append(BLINK_TOOLS_DIR)
@@ -60,7 +61,8 @@
 
         # Move json results into layout-test-results directory
         results_dir = os.path.dirname(self.wpt_output)
-        layout_test_results = os.path.join(results_dir, 'layout-test-results')
+        layout_test_results = os.path.join(results_dir,
+                                           LAYOUT_TEST_RESULTS_SUBDIR)
         if self.fs.exists(layout_test_results):
             self.fs.rmtree(layout_test_results)
         self.fs.maybe_make_directory(layout_test_results)
@@ -320,7 +322,7 @@
               to the |results_dir|.
         """
         log_artifact_sub_path = (
-            os.path.join("layout-test-results",
+            os.path.join(LAYOUT_TEST_RESULTS_SUBDIR,
                          self.port.output_filename(
                              test_name, suffix, extension))
         )
@@ -353,6 +355,9 @@
              path of the file for that screenshot
         """
         result={}
+        # Remember the two images so we can diff them later.
+        actual_image_bytes = None
+        expected_image_bytes = None
         for screenshot_pair in screenshot_artifact:
             screenshot_split = screenshot_pair.split(":")
             url = screenshot_split[0]
@@ -368,8 +373,13 @@
                 screenshot_key = "actual_image"
                 file_suffix = test_failures.FILENAME_SUFFIX_ACTUAL
 
+            if screenshot_key == "expected_image":
+                expected_image_bytes = image_bytes
+            else:
+                actual_image_bytes = image_bytes
+
             screenshot_sub_path = (
-                os.path.join("layout-test-results",
+                os.path.join(LAYOUT_TEST_RESULTS_SUBDIR,
                              self.port.output_filename(
                                  test_name, file_suffix, ".png"))
             )
@@ -381,4 +391,25 @@
                     os.path.dirname(screenshot_full_path))
             # Note: we are writing raw bytes to this file
             self.fs.write_binary_file(screenshot_full_path, image_bytes)
+
+        # Diff the two images and output the diff file.
+        diff_bytes, error = self.port.diff_image(expected_image_bytes,
+                                                 actual_image_bytes)
+        if diff_bytes and not error:
+            diff_sub_path = (
+                os.path.join(LAYOUT_TEST_RESULTS_SUBDIR,
+                             self.port.output_filename(
+                                 test_name, test_failures.FILENAME_SUFFIX_DIFF,
+                                 ".png")))
+            result["image_diff"] = diff_sub_path
+            diff_full_path = os.path.join(results_dir, diff_sub_path)
+            if not self.fs.exists(os.path.dirname(diff_full_path)):
+                self.fs.maybe_make_directory(os.path.dirname(diff_full_path))
+            # Note: we are writing raw bytes to this file
+            self.fs.write_binary_file(diff_full_path, diff_bytes)
+        else:
+            print("Error creating diff image for test %s. "
+                  "Error=%s, diff_bytes is None? %s\n"
+                  % (test_name, error, diff_bytes is None))
+
         return result
diff --git a/testing/scripts/wpt_common_unittest.py b/testing/scripts/wpt_common_unittest.py
index c68085c9..06077731 100755
--- a/testing/scripts/wpt_common_unittest.py
+++ b/testing/scripts/wpt_common_unittest.py
@@ -12,7 +12,8 @@
 import unittest
 
 from wpt_common import (
-    BaseWptScriptAdapter, EXTERNAL_WPT_TESTS_DIR, WEB_TESTS_DIR
+    BaseWptScriptAdapter, EXTERNAL_WPT_TESTS_DIR, WEB_TESTS_DIR,
+    LAYOUT_TEST_RESULTS_SUBDIR
 )
 
 from blinkpy.common.host_mock import MockHost
@@ -121,15 +122,15 @@
         written_files = self.wpt_adapter.fs.written_files
         self.assertEqual(written_files[OUTPUT_JSON_FILENAME],
                          written_files[os.path.join(
-                             'layout-test-results', 'full_results.json')])
+                             LAYOUT_TEST_RESULTS_SUBDIR, 'full_results.json')])
         # Verify JSONP
         full_results_jsonp = written_files[os.path.join(
-            'layout-test-results', 'full_results_jsonp.js')]
+            LAYOUT_TEST_RESULTS_SUBDIR, 'full_results_jsonp.js')]
         match = re.match(r'ADD_FULL_RESULTS\((.*)\);$', full_results_jsonp)
         self.assertIsNotNone(match)
         self.assertEqual(match.group(1), written_files[OUTPUT_JSON_FILENAME])
         failing_results_jsonp = written_files[os.path.join(
-            'layout-test-results', 'failing_results.json')]
+            LAYOUT_TEST_RESULTS_SUBDIR, 'failing_results.json')]
         match = re.match(r'ADD_RESULTS\((.*)\);$', failing_results_jsonp)
         self.assertIsNotNone(match)
         failing_results = json.loads(match.group(1))
@@ -160,9 +161,10 @@
         self._create_json_output(json_dict)
         self.wpt_adapter.do_post_test_run_tasks()
         written_files = self.wpt_adapter.fs.written_files
-        actual_path = os.path.join("layout-test-results", "test-actual.txt")
-        diff_path = os.path.join("layout-test-results", "test-diff.txt")
-        pretty_diff_path = os.path.join("layout-test-results",
+        actual_path = os.path.join(LAYOUT_TEST_RESULTS_SUBDIR,
+                                   "test-actual.txt")
+        diff_path = os.path.join(LAYOUT_TEST_RESULTS_SUBDIR, "test-diff.txt")
+        pretty_diff_path = os.path.join(LAYOUT_TEST_RESULTS_SUBDIR,
                                         "test-pretty-diff.html")
         self.assertNotIn(actual_path, written_files)
         self.assertNotIn(diff_path, written_files)
@@ -174,7 +176,8 @@
         self._create_json_output(json_dict)
         self.wpt_adapter.do_post_test_run_tasks()
         written_files = self.wpt_adapter.fs.written_files
-        actual_path = os.path.join("layout-test-results", "test-actual.txt")
+        actual_path = os.path.join(LAYOUT_TEST_RESULTS_SUBDIR,
+                                   "test-actual.txt")
         self.assertEqual("test.html actual text", written_files[actual_path])
         # Ensure the artifact in the json was replaced with the location of
         # the newly-created file.
@@ -188,12 +191,12 @@
         # Ensure that a diff was also generated. Since there's no expected
         # output, the actual text is all new. We don't validate the entire diff
         # files to avoid checking line numbers/markup.
-        diff_path = os.path.join("layout-test-results", "test-diff.txt")
+        diff_path = os.path.join(LAYOUT_TEST_RESULTS_SUBDIR, "test-diff.txt")
         self.assertIn("+test.html actual text", written_files[diff_path])
         self.assertEqual(
             [diff_path],
             updated_json["tests"]["test.html"]["artifacts"]["text_diff"])
-        pretty_diff_path = os.path.join("layout-test-results",
+        pretty_diff_path = os.path.join(LAYOUT_TEST_RESULTS_SUBDIR,
                                         "test-pretty-diff.html")
         self.assertIn("test.html actual text", written_files[pretty_diff_path])
         self.assertEqual(
@@ -218,7 +221,8 @@
         self._create_json_output(json_dict)
         self.wpt_adapter.do_post_test_run_tasks()
         written_files = self.wpt_adapter.fs.written_files
-        stderr_path = os.path.join("layout-test-results", "test-stderr.txt")
+        stderr_path = os.path.join(LAYOUT_TEST_RESULTS_SUBDIR,
+                                   "test-stderr.txt")
         self.assertEqual("test.html exceptions", written_files[stderr_path])
         # Ensure the artifact in the json was replaced with the location of
         # the newly-created file.
@@ -248,7 +252,7 @@
         self._create_json_output(json_dict)
         self.wpt_adapter.do_post_test_run_tasks()
         written_files = self.wpt_adapter.fs.written_files
-        crash_log_path = os.path.join("layout-test-results",
+        crash_log_path = os.path.join(LAYOUT_TEST_RESULTS_SUBDIR,
                                       "test-crash-log.txt")
         self.assertEqual("test.html crashed!", written_files[crash_log_path])
         # Ensure the artifact in the json was replaced with the location of
@@ -262,7 +266,7 @@
 
     def test_write_screenshot_artifacts(self):
         # Ensure that screenshots are written to the correct filenames and
-        # their bytes are base64 decoded.
+        # their bytes are base64 decoded. The image diff should also be created.
         json_dict = {
             'tests': {
                 'reftest.html': {
@@ -282,14 +286,19 @@
         self._create_json_output(json_dict)
         self.wpt_adapter.do_post_test_run_tasks()
         written_files = self.wpt_adapter.fs.written_files
-        actual_image_path = os.path.join("layout-test-results",
+        actual_image_path = os.path.join(LAYOUT_TEST_RESULTS_SUBDIR,
                                          "reftest-actual.png")
         self.assertEqual(base64.b64decode('abcd'),
                          written_files[actual_image_path])
-        expected_image_path = os.path.join("layout-test-results",
+        expected_image_path = os.path.join(LAYOUT_TEST_RESULTS_SUBDIR,
                                            "reftest-expected.png")
         self.assertEqual(base64.b64decode('bcde'),
                          written_files[expected_image_path])
+        diff_image_path = os.path.join(LAYOUT_TEST_RESULTS_SUBDIR,
+                                       "reftest-diff.png")
+        # Make sure the diff image was written but don't check the contents,
+        # assume that diff_image does the right thing.
+        self.assertIsNotNone(written_files[diff_image_path])
         # Ensure the artifacts in the json were replaced with the location of
         # the newly-created files.
         updated_json = self._load_json_output()
@@ -302,6 +311,9 @@
             [expected_image_path],
             updated_json["tests"]["reftest.html"]["artifacts"]
                 ["expected_image"])
+        self.assertEqual([diff_image_path],
+                         updated_json["tests"]["reftest.html"]["artifacts"]
+                         ["image_diff"])
 
     def test_copy_expected_output(self):
         # Check that an -expected.txt file is created from a checked-in metadata
@@ -326,10 +338,12 @@
             "test.html checked-in metadata")
         self.wpt_adapter.do_post_test_run_tasks()
         written_files = self.wpt_adapter.fs.written_files
-        actual_path = os.path.join("layout-test-results", "test-actual.txt")
+        actual_path = os.path.join(LAYOUT_TEST_RESULTS_SUBDIR,
+                                   "test-actual.txt")
         self.assertEqual("test.html actual text", written_files[actual_path])
         # The checked-in metadata file gets renamed from .ini to -expected.txt
-        expected_path = os.path.join("layout-test-results", "test-expected.txt")
+        expected_path = os.path.join(LAYOUT_TEST_RESULTS_SUBDIR,
+                                     "test-expected.txt")
         self.assertEqual("test.html checked-in metadata",
                          written_files[expected_path])
         # Ensure the artifacts in the json were replaced with the locations of
@@ -347,14 +361,14 @@
         # Ensure that a diff was also generated. There should be both additions
         # and deletions for this test since we have expected output. We don't
         # validate the entire diff files to avoid checking line numbers/markup.
-        diff_path = os.path.join("layout-test-results", "test-diff.txt")
+        diff_path = os.path.join(LAYOUT_TEST_RESULTS_SUBDIR, "test-diff.txt")
         self.assertIn("-test.html checked-in metadata",
                       written_files[diff_path])
         self.assertIn("+test.html actual text", written_files[diff_path])
         self.assertEqual(
             [diff_path],
             updated_json["tests"]["test.html"]["artifacts"]["text_diff"])
-        pretty_diff_path = os.path.join("layout-test-results",
+        pretty_diff_path = os.path.join(LAYOUT_TEST_RESULTS_SUBDIR,
                                         "test-pretty-diff.html")
         self.assertIn("test.html checked-in metadata",
                       written_files[pretty_diff_path])
@@ -392,12 +406,12 @@
             "variant.html checked-in metadata")
         self.wpt_adapter.do_post_test_run_tasks()
         written_files = self.wpt_adapter.fs.written_files
-        actual_path = os.path.join("layout-test-results",
+        actual_path = os.path.join(LAYOUT_TEST_RESULTS_SUBDIR,
                                    "variant_foo=bar_abc-actual.txt")
         self.assertEqual("variant bar/abc actual text",
                          written_files[actual_path])
         # The checked-in metadata file gets renamed from .ini to -expected.txt
-        expected_path = os.path.join("layout-test-results",
+        expected_path = os.path.join(LAYOUT_TEST_RESULTS_SUBDIR,
                                      "variant_foo=bar_abc-expected.txt")
         self.assertEqual("variant.html checked-in metadata",
                          written_files[expected_path])
@@ -448,13 +462,13 @@
             "dir/multiglob checked-in metadata")
         self.wpt_adapter.do_post_test_run_tasks()
         written_files = self.wpt_adapter.fs.written_files
-        actual_path = os.path.join("layout-test-results",
+        actual_path = os.path.join(LAYOUT_TEST_RESULTS_SUBDIR,
                                    "dir/multiglob.https.any.worker-actual.txt")
         self.assertEqual("dir/multiglob worker actual text",
                          written_files[actual_path])
         # The checked-in metadata file gets renamed from .ini to -expected.txt
         expected_path = os.path.join(
-            "layout-test-results",
+            LAYOUT_TEST_RESULTS_SUBDIR,
             "dir/multiglob.https.any.worker-expected.txt")
         self.assertEqual("dir/multiglob checked-in metadata",
                          written_files[expected_path])
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index d974cbe..20481cf 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -49,24 +49,6 @@
             ]
         }
     ],
-    "AndroidAppMenuUiReworkPhase4And5": [
-        {
-            "platforms": [
-                "android"
-            ],
-            "experiments": [
-                {
-                    "name": "AddToOption",
-                    "params": {
-                        "three_button_action_bar": "add_to_option"
-                    },
-                    "enable_features": [
-                        "TabbedAppOverflowMenuThreeButtonActionbar"
-                    ]
-                }
-            ]
-        }
-    ],
     "AndroidAutofillQueryServerFieldTypes": [
         {
             "platforms": [
@@ -3096,8 +3078,7 @@
                         "session_rate": "==0"
                     },
                     "enable_features": [
-                        "IPH_FeedHeaderMenu",
-                        "ReportFeedUserActions"
+                        "IPH_FeedHeaderMenu"
                     ]
                 }
             ]
diff --git a/third_party/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy b/third_party/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy
index 8b53b28..bf6af02 100644
--- a/third_party/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy
+++ b/third_party/android_deps/buildSrc/src/main/groovy/ChromiumDepGraph.groovy
@@ -342,6 +342,7 @@
 
     void collectDependencies() {
         Set<ResolvedConfiguration> deps = []
+        Set<ResolvedConfiguration> depsNoRecurse = []
         Set<ResolvedDependency> firstLevelModuleDependencies = []
         Map<String, List<ResolvedArtifact>> resolvedArtifacts = new HashMap<>()
         String[] configNames = [
@@ -349,12 +350,16 @@
             'compileListenableFuture',
             'buildCompile',
             'testCompile',
-            'androidTestCompile'
+            'androidTestCompile',
+            'buildCompileNoDeps'
         ]
         for (Project project : projects) {
             for (String configName : configNames) {
                 def config = project.configurations.getByName(configName).resolvedConfiguration
                 deps += config.firstLevelModuleDependencies
+                if (configName == 'buildCompileNoDeps') {
+                  depsNoRecurse += config.firstLevelModuleDependencies
+                }
                 if (!resolvedArtifacts.containsKey(configName)) {
                   resolvedArtifacts[configName] = []
                 }
@@ -369,7 +374,7 @@
         List<String> topLevelIds = []
         deps.each { dependency ->
             topLevelIds.add(makeModuleId(dependency.module))
-            collectDependenciesInternal(dependency)
+            collectDependenciesInternal(dependency, !depsNoRecurse.contains(dependency))
         }
 
         topLevelIds.each { id -> dependencies.get(id).visible = true }
@@ -406,6 +411,14 @@
             dep.isShipped = true
         }
 
+        depsNoRecurse.each { resolvedDep ->
+            def id = makeModuleId(resolvedDep.module)
+            def dep = dependencies.get(id)
+            assert dep != null : "No dependency collected for artifact ${artifact.name}"
+            dep.testOnly = false
+        }
+
+
         PROPERTY_OVERRIDES.each { id, fallbackProperties ->
             if (fallbackProperties?.isShipped != null) {
                 def dep = dependencies.get(id)
@@ -418,7 +431,7 @@
         }
     }
 
-    private void collectDependenciesInternal(ResolvedDependency dependency) {
+    private void collectDependenciesInternal(ResolvedDependency dependency, boolean recurse = true) {
         def id = makeModuleId(dependency.module)
         if (dependencies.containsKey(id)) {
             if (dependencies.get(id).version == dependency.module.id.version) return
@@ -427,17 +440,12 @@
             // crbug.com/1040958
             // https://docs.gradle.org/current/userguide/dependency_resolution.html#sec:version-conflict
             def useLowerVersion = (id in lowerVersionOverride)
-            def versionIsLower = dependency.module.id.version < dependencies.get(id).version 
+            def versionIsLower = dependency.module.id.version < dependencies.get(id).version
             if (useLowerVersion != versionIsLower) {
                 return
             }
         }
 
-        def childModules = []
-        dependency.children.each { childDependency ->
-            childModules += makeModuleId(childDependency.module)
-        }
-
         if (dependency.getModuleArtifacts().size() != 1) {
             throw new IllegalStateException("The dependency ${id} does not have exactly one " +
                                             "artifact: ${dependency.getModuleArtifacts()}")
@@ -447,9 +455,17 @@
             throw new IllegalStateException("Type ${artifact.extension} of ${id} not supported.")
         }
 
-        dependencies.put(id, buildDepDescription(id, dependency, artifact, childModules))
-        dependency.children.each {
-            childDependency -> collectDependenciesInternal(childDependency)
+        if (recurse) {
+          def childModules = []
+          dependency.children.each { childDependency ->
+              childModules += makeModuleId(childDependency.module)
+          }
+          dependencies.put(id, buildDepDescription(id, dependency, artifact, childModules))
+          dependency.children.each {
+              childDependency -> collectDependenciesInternal(childDependency)
+          }
+        } else {
+          dependencies.put(id, buildDepDescription(id, dependency, artifact, []))
         }
     }
 
diff --git a/third_party/android_deps/buildSrc/src/main/groovy/ChromiumPlugin.groovy b/third_party/android_deps/buildSrc/src/main/groovy/ChromiumPlugin.groovy
index 0814b69..5c3d085 100644
--- a/third_party/android_deps/buildSrc/src/main/groovy/ChromiumPlugin.groovy
+++ b/third_party/android_deps/buildSrc/src/main/groovy/ChromiumPlugin.groovy
@@ -29,6 +29,12 @@
             /** Libraries that are only used during build. These support android. */
             buildCompile
 
+            /**
+             * Libraries that are only used during build but should not
+             * automatically retrieve their dependencies.
+             */
+            buildCompileNoDeps
+
             /** Libraries that are used for testing only and support android. */
             androidTestCompile
         }
diff --git a/third_party/blink/common/loader/throttling_url_loader.cc b/third_party/blink/common/loader/throttling_url_loader.cc
index bc114fc..9534d9c 100644
--- a/third_party/blink/common/loader/throttling_url_loader.cc
+++ b/third_party/blink/common/loader/throttling_url_loader.cc
@@ -243,14 +243,12 @@
 
 ThrottlingURLLoader::StartInfo::StartInfo(
     scoped_refptr<network::SharedURLLoaderFactory> in_url_loader_factory,
-    int32_t in_routing_id,
     int32_t in_request_id,
     uint32_t in_options,
     network::ResourceRequest* in_url_request,
     scoped_refptr<base::SingleThreadTaskRunner> in_task_runner,
     base::Optional<std::vector<std::string>> in_cors_exempt_header_list)
     : url_loader_factory(std::move(in_url_loader_factory)),
-      routing_id(in_routing_id),
       request_id(in_request_id),
       options(in_options),
       url_request(*in_url_request),
@@ -283,7 +281,6 @@
 std::unique_ptr<ThrottlingURLLoader> ThrottlingURLLoader::CreateLoaderAndStart(
     scoped_refptr<network::SharedURLLoaderFactory> factory,
     std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     network::ResourceRequest* url_request,
@@ -294,9 +291,8 @@
   DCHECK(url_request);
   std::unique_ptr<ThrottlingURLLoader> loader(new ThrottlingURLLoader(
       std::move(throttles), client, traffic_annotation));
-  loader->Start(std::move(factory), routing_id, request_id, options,
-                url_request, std::move(task_runner),
-                std::move(cors_exempt_header_list));
+  loader->Start(std::move(factory), request_id, options, url_request,
+                std::move(task_runner), std::move(cors_exempt_header_list));
   return loader;
 }
 
@@ -427,7 +423,6 @@
 
 void ThrottlingURLLoader::Start(
     scoped_refptr<network::SharedURLLoaderFactory> factory,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     network::ResourceRequest* url_request,
@@ -489,9 +484,9 @@
     }
   }
 
-  start_info_ = std::make_unique<StartInfo>(
-      factory, routing_id, request_id, options, url_request,
-      std::move(task_runner), std::move(cors_exempt_header_list));
+  start_info_ = std::make_unique<StartInfo>(factory, request_id, options,
+                                            url_request, std::move(task_runner),
+                                            std::move(cors_exempt_header_list));
   if (deferred)
     deferred_stage_ = DEFERRED_START;
   else
@@ -553,8 +548,7 @@
   DCHECK(start_info_->url_loader_factory);
   start_info_->url_loader_factory->CreateLoaderAndStart(
       url_loader_.BindNewPipeAndPassReceiver(start_info_->task_runner),
-      start_info_->routing_id, start_info_->request_id, start_info_->options,
-      start_info_->url_request,
+      start_info_->request_id, start_info_->options, start_info_->url_request,
       client_receiver_.BindNewPipeAndPassRemote(start_info_->task_runner),
       net::MutableNetworkTrafficAnnotationTag(traffic_annotation_));
 
diff --git a/third_party/blink/common/loader/throttling_url_loader_unittest.cc b/third_party/blink/common/loader/throttling_url_loader_unittest.cc
index 66cbbda8..567f6d0 100644
--- a/third_party/blink/common/loader/throttling_url_loader_unittest.cc
+++ b/third_party/blink/common/loader/throttling_url_loader_unittest.cc
@@ -103,7 +103,6 @@
   // network::mojom::URLLoaderFactory implementation.
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& url_request,
@@ -383,8 +382,8 @@
     network::ResourceRequest request;
     request.url = request_url;
     loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
-        factory_.shared_factory(), std::move(throttles_), 0, 0, options,
-        &request, &client_, TRAFFIC_ANNOTATION_FOR_TESTS,
+        factory_.shared_factory(), std::move(throttles_), 0, options, &request,
+        &client_, TRAFFIC_ANNOTATION_FOR_TESTS,
         base::ThreadTaskRunnerHandle::Get());
     factory_.factory_remote().FlushForTesting();
   }
@@ -584,7 +583,7 @@
   network::ResourceRequest request;
   request.url = request_url;
   loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
-      factory_.shared_factory(), std::move(throttles_), 0, 0, 0, &request,
+      factory_.shared_factory(), std::move(throttles_), 0, 0, &request,
       &client_, TRAFFIC_ANNOTATION_FOR_TESTS,
       base::ThreadTaskRunnerHandle::Get());
 
diff --git a/third_party/blink/common/loader/url_loader_factory_bundle.cc b/third_party/blink/common/loader/url_loader_factory_bundle.cc
index ef75d3c..12184b2 100644
--- a/third_party/blink/common/loader/url_loader_factory_bundle.cc
+++ b/third_party/blink/common/loader/url_loader_factory_bundle.cc
@@ -97,15 +97,14 @@
 
 void URLLoaderFactoryBundle::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> loader,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
     mojo::PendingRemote<network::mojom::URLLoaderClient> client,
     const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
   network::mojom::URLLoaderFactory* factory_ptr = GetFactory(request);
-  factory_ptr->CreateLoaderAndStart(std::move(loader), routing_id, request_id,
-                                    options, request, std::move(client),
+  factory_ptr->CreateLoaderAndStart(std::move(loader), request_id, options,
+                                    request, std::move(client),
                                     traffic_annotation);
 }
 
diff --git a/third_party/blink/public/common/loader/throttling_url_loader.h b/third_party/blink/public/common/loader/throttling_url_loader.h
index ff9608d29..d934b2ab 100644
--- a/third_party/blink/public/common/loader/throttling_url_loader.h
+++ b/third_party/blink/public/common/loader/throttling_url_loader.h
@@ -50,7 +50,6 @@
   static std::unique_ptr<ThrottlingURLLoader> CreateLoaderAndStart(
       scoped_refptr<network::SharedURLLoaderFactory> factory,
       std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       network::ResourceRequest* url_request,
@@ -114,7 +113,6 @@
       const net::NetworkTrafficAnnotationTag& traffic_annotation);
 
   void Start(scoped_refptr<network::SharedURLLoaderFactory> factory,
-             int32_t routing_id,
              int32_t request_id,
              uint32_t options,
              network::ResourceRequest* url_request,
@@ -233,7 +231,6 @@
   struct StartInfo {
     StartInfo(
         scoped_refptr<network::SharedURLLoaderFactory> in_url_loader_factory,
-        int32_t in_routing_id,
         int32_t in_request_id,
         uint32_t in_options,
         network::ResourceRequest* in_url_request,
@@ -242,7 +239,6 @@
     ~StartInfo();
 
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory;
-    int32_t routing_id;
     int32_t request_id;
     uint32_t options;
 
diff --git a/third_party/blink/public/common/loader/url_loader_factory_bundle.h b/third_party/blink/public/common/loader/url_loader_factory_bundle.h
index 4361ec8..994a4c3 100644
--- a/third_party/blink/public/common/loader/url_loader_factory_bundle.h
+++ b/third_party/blink/public/common/loader/url_loader_factory_bundle.h
@@ -103,7 +103,6 @@
   // SharedURLLoaderFactory implementation.
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/third_party/blink/public/mojom/webdatabase/web_database.mojom b/third_party/blink/public/mojom/webdatabase/web_database.mojom
index d6e168d..54483c0 100644
--- a/third_party/blink/public/mojom/webdatabase/web_database.mojom
+++ b/third_party/blink/public/mojom/webdatabase/web_database.mojom
@@ -46,7 +46,7 @@
 
   // Notifies the browser process that a new database has been opened
   Opened(url.mojom.Origin origin, mojo_base.mojom.String16 database_name,
-         mojo_base.mojom.String16 database_description, int64 estimated_size);
+         mojo_base.mojom.String16 database_description);
 
   // Notifies the browser process that a database might have been modified
   Modified(url.mojom.Origin origin, mojo_base.mojom.String16 database_name);
diff --git a/third_party/blink/public/platform/child_url_loader_factory_bundle.h b/third_party/blink/public/platform/child_url_loader_factory_bundle.h
index 82acf1f..8929f3b 100644
--- a/third_party/blink/public/platform/child_url_loader_factory_bundle.h
+++ b/third_party/blink/public/platform/child_url_loader_factory_bundle.h
@@ -117,7 +117,6 @@
   // URLLoaderFactoryBundle overrides.
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,
diff --git a/third_party/blink/public/platform/web_resource_request_sender.h b/third_party/blink/public/platform/web_resource_request_sender.h
index 3e15e1a..edc63d0 100644
--- a/third_party/blink/public/platform/web_resource_request_sender.h
+++ b/third_party/blink/public/platform/web_resource_request_sender.h
@@ -87,15 +87,12 @@
   // interrupt this method. Errors are reported via the status field of the
   // response parameter.
   //
-  // |routing_id| is used to associated the bridge with a frame's network
-  // context.
   // |timeout| is used to abort the sync request on timeouts. TimeDelta::Max()
   // is interpreted as no-timeout.
   // If |download_to_blob_registry| is not null, it is used to redirect the
   // download to a blob.
   virtual void SendSync(
       std::unique_ptr<network::ResourceRequest> request,
-      int routing_id,
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
       uint32_t loader_options,
       SyncLoadResponse* response,
@@ -114,14 +111,10 @@
   // the peer's methods will be called asynchronously to report various events.
   // Returns the request id. |url_loader_factory| must be non-null.
   //
-  // |routing_id| is used to associated the bridge with a frame's network
-  // context.
-  //
   // You need to pass a non-null |loading_task_runner| to specify task queue to
   // execute loading tasks on.
   virtual int SendAsync(
       std::unique_ptr<network::ResourceRequest> request,
-      int routing_id,
       scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner,
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
       uint32_t loader_options,
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
index d317c4a..16404cc1 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
@@ -1654,6 +1654,9 @@
         return T("bindings::V8SetReturnValue"
                  "(${info}, ${return_value}.V8Value());")
 
+    if return_type.is_nullable:
+        return T("bindings::V8SetReturnValue(${info}, ${v8_return_value});")
+
     return T("bindings::V8SetReturnValue(${info}, "
              "ToV8(${return_value}, ${creation_context_object}, ${isolate}));")
 
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 98e2a10..bd6c8b5d 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1497,6 +1497,7 @@
     "page/scrolling/snap_coordinator_test.cc",
     "page/scrolling/text_fragment_anchor_metrics_test.cc",
     "page/scrolling/text_fragment_anchor_test.cc",
+    "page/scrolling/text_fragment_finder_test.cc",
     "page/scrolling/text_fragment_selector_generator_test.cc",
     "page/scrolling/text_fragment_selector_test.cc",
     "page/slot_scoped_traversal_test.cc",
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.cc b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
index d8fd26a..c5e02567 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.cc
@@ -1211,8 +1211,9 @@
     return false;
   }
 
-  CalculateAnimationUpdate(state);
-
+  CSSAnimations::CalculateAnimationUpdate(
+      state.AnimationUpdate(), animating_element, state.GetElement(),
+      *state.Style(), state.ParentStyle(), this);
   CSSAnimations::CalculateCompositorAnimationUpdate(
       state.AnimationUpdate(), animating_element, element, *state.Style(),
       state.ParentStyle(), WasViewportResized());
@@ -1402,20 +1403,6 @@
   }
 }
 
-void StyleResolver::CalculateAnimationUpdate(StyleResolverState& state) {
-  Element* animating_element = state.GetAnimatingElement();
-
-  DCHECK(state.Style()->Animations() || state.Style()->Transitions() ||
-         (animating_element && animating_element->HasAnimations()));
-  DCHECK(!state.IsAnimationInterpolationMapReady());
-
-  CSSAnimations::CalculateAnimationUpdate(
-      state.AnimationUpdate(), animating_element, state.GetElement(),
-      *state.Style(), state.ParentStyle(), this);
-
-  state.SetIsAnimationInterpolationMapReady();
-}
-
 bool StyleResolver::CanReuseBaseComputedStyle(const StyleResolverState& state) {
   // TODO(crbug.com/1180159): @container and transitions properly.
   if (RuntimeEnabledFeatures::CSSContainerQueriesEnabled())
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver.h b/third_party/blink/renderer/core/css/resolver/style_resolver.h
index 3d4f4312..98ffbc0 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver.h
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver.h
@@ -234,8 +234,6 @@
   void CascadeAndApplyMatchedProperties(StyleResolverState&,
                                         StyleCascade& cascade);
 
-  void CalculateAnimationUpdate(StyleResolverState&);
-
   bool ApplyAnimatedStyle(StyleResolverState&, StyleCascade&);
 
   void ApplyCallbackSelectors(StyleResolverState&);
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_state.h b/third_party/blink/renderer/core/css/resolver/style_resolver_state.h
index 825d102..f44e967 100644
--- a/third_party/blink/renderer/core/css/resolver/style_resolver_state.h
+++ b/third_party/blink/renderer/core/css/resolver/style_resolver_state.h
@@ -112,13 +112,6 @@
     return animation_update_;
   }
 
-  bool IsAnimationInterpolationMapReady() const {
-    return is_animation_interpolation_map_ready_;
-  }
-  void SetIsAnimationInterpolationMapReady() {
-    is_animation_interpolation_map_ready_ = true;
-  }
-
   Element* GetAnimatingElement() const;
 
   void SetParentStyle(scoped_refptr<const ComputedStyle>);
@@ -191,7 +184,6 @@
   scoped_refptr<const ComputedStyle> layout_parent_style_;
 
   CSSAnimationUpdate animation_update_;
-  bool is_animation_interpolation_map_ready_ = false;
   StyleRequest::RequestType pseudo_request_type_;
 
   FontBuilder font_builder_;
diff --git a/third_party/blink/renderer/core/editing/build.gni b/third_party/blink/renderer/core/editing/build.gni
index 030a9db..0ada2a05 100644
--- a/third_party/blink/renderer/core/editing/build.gni
+++ b/third_party/blink/renderer/core/editing/build.gni
@@ -251,6 +251,8 @@
   "position_iterator.h",
   "position_with_affinity.cc",
   "position_with_affinity.h",
+  "range_in_flat_tree.cc",
+  "range_in_flat_tree.h",
   "relocatable_position.cc",
   "relocatable_position.h",
   "reveal_selection_scope.cc",
diff --git a/third_party/blink/renderer/core/editing/finder/async_find_buffer.cc b/third_party/blink/renderer/core/editing/finder/async_find_buffer.cc
index dc8b97ee..8163219 100644
--- a/third_party/blink/renderer/core/editing/finder/async_find_buffer.cc
+++ b/third_party/blink/renderer/core/editing/finder/async_find_buffer.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 #include "third_party/blink/renderer/core/editing/finder/async_find_buffer.h"
 
-#include "third_party/blink/renderer/core/dom/range.h"
 #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
 #include "third_party/blink/renderer/core/editing/finder/find_buffer.h"
 
@@ -15,7 +14,7 @@
     base::TimeDelta::FromMilliseconds(100);
 }  // namespace
 
-void AsyncFindBuffer::FindMatchInRange(Range* search_range,
+void AsyncFindBuffer::FindMatchInRange(RangeInFlatTree* search_range,
                                        String search_text,
                                        FindOptions options,
                                        Callback completeCallback) {
@@ -29,20 +28,26 @@
   pending_find_match_task_.Cancel();
 }
 
-void AsyncFindBuffer::Run(Range* search_range,
+void AsyncFindBuffer::Run(RangeInFlatTree* search_range,
                           String search_text,
                           FindOptions options,
                           Callback completeCallback) {
-  search_range->OwnerDocument().UpdateStyleAndLayout(
+  // If range is not connected we should stop the search.
+  if (search_range->IsNull() || !search_range->IsConnected()) {
+    std::move(completeCallback).Run(EphemeralRangeInFlatTree());
+    return;
+  }
+  search_range->StartPosition().GetDocument()->UpdateStyleAndLayout(
       DocumentUpdateReason::kFindInPage);
+
   EphemeralRangeInFlatTree range = FindBuffer::FindMatchInRange(
-      EphemeralRangeInFlatTree(search_range), search_text, options,
+      search_range->ToEphemeralRange(), search_text, options,
       kFindBufferTaskTimeoutMs);
 
   if (range.IsNotNull() && range.IsCollapsed()) {
     // FindBuffer reached time limit - Start/End of range is last checked
     // position
-    search_range->setStart(ToPositionInDOMTree(range.StartPosition()));
+    search_range->SetStart(range.StartPosition());
     NextIteration(search_range, search_text, options,
                   std::move(completeCallback));
     return;
@@ -57,14 +62,15 @@
   std::move(completeCallback).Run(range);
 }
 
-void AsyncFindBuffer::NextIteration(Range* search_range,
+void AsyncFindBuffer::NextIteration(RangeInFlatTree* search_range,
                                     String search_text,
                                     FindOptions options,
                                     Callback completeCallback) {
   iterations_++;
   pending_find_match_task_ = PostCancellableTask(
-      *search_range->OwnerDocument()
-           .GetTaskRunner(TaskType::kInternalFindInPage)
+      *search_range->StartPosition()
+           .GetDocument()
+           ->GetTaskRunner(TaskType::kInternalFindInPage)
            .get(),
       FROM_HERE,
       WTF::Bind(&AsyncFindBuffer::Run, WrapWeakPersistent(this),
diff --git a/third_party/blink/renderer/core/editing/finder/async_find_buffer.h b/third_party/blink/renderer/core/editing/finder/async_find_buffer.h
index e426f2f..9a8bc48 100644
--- a/third_party/blink/renderer/core/editing/finder/async_find_buffer.h
+++ b/third_party/blink/renderer/core/editing/finder/async_find_buffer.h
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/core/editing/finder/find_buffer_runner.h"
 #include "third_party/blink/renderer/core/editing/finder/find_options.h"
 #include "third_party/blink/renderer/core/editing/forward.h"
+#include "third_party/blink/renderer/core/editing/range_in_flat_tree.h"
 #include "third_party/blink/renderer/platform/scheduler/public/post_cancellable_task.h"
 
 namespace blink {
@@ -19,7 +20,7 @@
   explicit AsyncFindBuffer() = default;
   ~AsyncFindBuffer() = default;
 
-  void FindMatchInRange(Range* search_range,
+  void FindMatchInRange(RangeInFlatTree* search_range,
                         String search_text,
                         FindOptions options,
                         Callback completeCallback) override;
@@ -27,12 +28,12 @@
   bool IsActive() override { return pending_find_match_task_.IsActive(); }
 
  private:
-  void Run(Range* search_range,
+  void Run(RangeInFlatTree* search_range,
            String search_text,
            FindOptions options,
            Callback completeCallback);
 
-  void NextIteration(Range* search_range,
+  void NextIteration(RangeInFlatTree* search_range,
                      String search_text,
                      FindOptions options,
                      Callback completeCallback);
diff --git a/third_party/blink/renderer/core/editing/finder/find_buffer_runner.h b/third_party/blink/renderer/core/editing/finder/find_buffer_runner.h
index f99ed7b..94fdcfa 100644
--- a/third_party/blink/renderer/core/editing/finder/find_buffer_runner.h
+++ b/third_party/blink/renderer/core/editing/finder/find_buffer_runner.h
@@ -5,8 +5,8 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_FINDER_FIND_BUFFER_RUNNER_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_FINDER_FIND_BUFFER_RUNNER_H_
 
-#include "third_party/blink/renderer/core/dom/range.h"
 #include "third_party/blink/renderer/core/editing/finder/find_options.h"
+#include "third_party/blink/renderer/core/editing/range_in_flat_tree.h"
 
 namespace blink {
 
@@ -16,7 +16,7 @@
  public:
   using Callback = base::OnceCallback<void(const EphemeralRangeInFlatTree&)>;
 
-  virtual void FindMatchInRange(Range* search_range,
+  virtual void FindMatchInRange(RangeInFlatTree* search_range,
                                 String search_text,
                                 FindOptions options,
                                 Callback completeCallback) = 0;
diff --git a/third_party/blink/renderer/core/editing/finder/sync_find_buffer.cc b/third_party/blink/renderer/core/editing/finder/sync_find_buffer.cc
index 9c8307c..3f9eac8 100644
--- a/third_party/blink/renderer/core/editing/finder/sync_find_buffer.cc
+++ b/third_party/blink/renderer/core/editing/finder/sync_find_buffer.cc
@@ -3,18 +3,17 @@
 // found in the LICENSE file.
 #include "third_party/blink/renderer/core/editing/finder/sync_find_buffer.h"
 
-#include "third_party/blink/renderer/core/dom/range.h"
 #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
 #include "third_party/blink/renderer/core/editing/finder/find_buffer.h"
 
 namespace blink {
 
-void SyncFindBuffer::FindMatchInRange(Range* search_range,
+void SyncFindBuffer::FindMatchInRange(RangeInFlatTree* search_range,
                                       String search_text,
                                       FindOptions options,
                                       Callback completeCallback) {
   EphemeralRangeInFlatTree range = FindBuffer::FindMatchInRange(
-      EphemeralRangeInFlatTree(search_range), search_text, options);
+      search_range->ToEphemeralRange(), search_text, options);
 
   DCHECK(range.IsNull() || !range.IsCollapsed());
 
diff --git a/third_party/blink/renderer/core/editing/finder/sync_find_buffer.h b/third_party/blink/renderer/core/editing/finder/sync_find_buffer.h
index 0f74bf8..f4717e93 100644
--- a/third_party/blink/renderer/core/editing/finder/sync_find_buffer.h
+++ b/third_party/blink/renderer/core/editing/finder/sync_find_buffer.h
@@ -8,6 +8,7 @@
 #include "third_party/blink/renderer/core/editing/finder/find_buffer_runner.h"
 #include "third_party/blink/renderer/core/editing/finder/find_options.h"
 #include "third_party/blink/renderer/core/editing/forward.h"
+#include "third_party/blink/renderer/core/editing/range_in_flat_tree.h"
 
 namespace blink {
 
@@ -18,7 +19,7 @@
   explicit SyncFindBuffer() = default;
   ~SyncFindBuffer() = default;
 
-  void FindMatchInRange(Range* search_range,
+  void FindMatchInRange(RangeInFlatTree* search_range,
                         String search_text,
                         FindOptions options,
                         Callback completeCallback) override;
diff --git a/third_party/blink/renderer/core/editing/range_in_flat_tree.cc b/third_party/blink/renderer/core/editing/range_in_flat_tree.cc
new file mode 100644
index 0000000..51020f0
--- /dev/null
+++ b/third_party/blink/renderer/core/editing/range_in_flat_tree.cc
@@ -0,0 +1,57 @@
+// Copyright 2021 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/editing/range_in_flat_tree.h"
+
+#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
+
+namespace blink {
+
+RangeInFlatTree::RangeInFlatTree(const PositionInFlatTree& start,
+                                 const PositionInFlatTree& end)
+    : start_(MakeGarbageCollected<RelocatablePosition>(
+          ToPositionInDOMTree(start))),
+      end_(
+          MakeGarbageCollected<RelocatablePosition>(ToPositionInDOMTree(end))) {
+  DCHECK_LE(start, end);
+}
+
+void RangeInFlatTree::SetStart(const PositionInFlatTree& start) {
+  start_->SetPosition(ToPositionInDOMTree(start));
+}
+
+void RangeInFlatTree::SetEnd(const PositionInFlatTree& end) {
+  LOG(ERROR) << "end " << end;
+  end_->SetPosition(ToPositionInDOMTree(end));
+}
+
+PositionInFlatTree RangeInFlatTree::StartPosition() const {
+  return ToPositionInFlatTree(start_->GetPosition());
+}
+
+PositionInFlatTree RangeInFlatTree::EndPosition() const {
+  return ToPositionInFlatTree(end_->GetPosition());
+}
+
+bool RangeInFlatTree::IsCollapsed() const {
+  return start_ == end_;
+}
+
+bool RangeInFlatTree::IsConnected() const {
+  return StartPosition().ComputeContainerNode()->isConnected() &&
+         EndPosition().ComputeContainerNode()->isConnected();
+}
+
+bool RangeInFlatTree::IsNull() const {
+  return StartPosition().IsNull() || EndPosition().IsNull();
+}
+
+EphemeralRangeInFlatTree RangeInFlatTree::ToEphemeralRange() const {
+  return EphemeralRangeInFlatTree(StartPosition(), EndPosition());
+}
+
+void RangeInFlatTree::Trace(Visitor* visitor) const {
+  visitor->Trace(start_);
+  visitor->Trace(end_);
+}
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/editing/range_in_flat_tree.h b/third_party/blink/renderer/core/editing/range_in_flat_tree.h
new file mode 100644
index 0000000..c1091b5
--- /dev/null
+++ b/third_party/blink/renderer/core/editing/range_in_flat_tree.h
@@ -0,0 +1,45 @@
+// Copyright 2021 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_EDITING_RANGE_IN_FLAT_TREE_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_RANGE_IN_FLAT_TREE_H_
+
+#include "third_party/blink/renderer/core/editing/ephemeral_range.h"
+#include "third_party/blink/renderer/core/editing/relocatable_position.h"
+
+namespace blink {
+
+// This is a wrapper class for a range in flat tree that is relocatable by
+// relacating the start and end positions in DOM tree.
+class RangeInFlatTree final : public GarbageCollected<RangeInFlatTree> {
+ public:
+  RangeInFlatTree(const PositionInFlatTree& start,
+                  const PositionInFlatTree& end);
+
+  void SetStart(const PositionInFlatTree& start);
+
+  void SetEnd(const PositionInFlatTree& end);
+
+  PositionInFlatTree StartPosition() const;
+
+  PositionInFlatTree EndPosition() const;
+
+  bool IsCollapsed() const;
+
+  bool IsConnected() const;
+
+  bool IsNull() const;
+
+  EphemeralRangeInFlatTree ToEphemeralRange() const;
+
+  void Trace(Visitor* visitor) const;
+
+ private:
+  Member<RelocatablePosition> start_;
+  Member<RelocatablePosition> end_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_RANGE_IN_FLAT_TREE_H_
diff --git a/third_party/blink/renderer/core/editing/relocatable_position.cc b/third_party/blink/renderer/core/editing/relocatable_position.cc
index 464ceb3..a11dddb 100644
--- a/third_party/blink/renderer/core/editing/relocatable_position.cc
+++ b/third_party/blink/renderer/core/editing/relocatable_position.cc
@@ -14,10 +14,12 @@
                                                position)
                  : nullptr) {}
 
-RelocatablePosition::~RelocatablePosition() {
-  if (!range_)
-    return;
-  range_->Dispose();
+void RelocatablePosition::SetPosition(const Position& position) {
+  DCHECK(position.IsNotNull());
+  DCHECK(range_);
+  DCHECK_EQ(position.GetDocument(), range_->StartPosition().GetDocument());
+  range_->setStart(position);
+  range_->setEnd(position);
 }
 
 Position RelocatablePosition::GetPosition() const {
@@ -27,4 +29,8 @@
   return range_->StartPosition();
 }
 
+void RelocatablePosition::Trace(Visitor* visitor) const {
+  visitor->Trace(range_);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/editing/relocatable_position.h b/third_party/blink/renderer/core/editing/relocatable_position.h
index 99fa3ba..8d3ba42 100644
--- a/third_party/blink/renderer/core/editing/relocatable_position.h
+++ b/third_party/blink/renderer/core/editing/relocatable_position.h
@@ -15,19 +15,18 @@
 // anchor node is moved out of document. The class is implemented by using a
 // temporary |Range| object to keep track of the |Position|, and disposing the
 // |Range| when out of scope.
-class CORE_EXPORT RelocatablePosition final {
-  STACK_ALLOCATED();
-
+class CORE_EXPORT RelocatablePosition final
+    : public GarbageCollected<RelocatablePosition> {
  public:
   explicit RelocatablePosition(const Position&);
-  ~RelocatablePosition();
 
+  void SetPosition(const Position&);
   Position GetPosition() const;
 
- private:
-  Range* const range_;
+  void Trace(Visitor* visitor) const;
 
-  DISALLOW_COPY_AND_ASSIGN(RelocatablePosition);
+ private:
+  Member<Range> const range_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index 16a7766..65f3e30 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -2228,35 +2228,36 @@
 void LocalFrame::SetIsAdSubframe(blink::mojom::AdFrameType ad_frame_type) {
   DCHECK(!IsMainFrame());
 
-  // Once |ad_frame_type_| has been set to an ad type on this frame, it cannot
-  // be changed.
-  if (ad_frame_type == blink::mojom::AdFrameType::kNonAd)
+  if (ad_frame_type_ == ad_frame_type)
     return;
-  if (ad_frame_type_ != blink::mojom::AdFrameType::kNonAd)
-    return;
+
+  bool is_ad_subframe = ad_frame_type != blink::mojom::AdFrameType::kNonAd;
   if (auto* document = GetDocument()) {
     // TODO(fdoray): It is possible for the document not to be installed when
     // this method is called. Consider inheriting frame bit in the graph instead
     // of sending an IPC.
     auto* document_resource_coordinator = document->GetResourceCoordinator();
     if (document_resource_coordinator)
-      document_resource_coordinator->SetIsAdFrame();
+      document_resource_coordinator->SetIsAdFrame(is_ad_subframe);
   }
+
   ad_frame_type_ = ad_frame_type;
   UpdateAdHighlight();
-  frame_scheduler_->SetIsAdFrame();
+  frame_scheduler_->SetIsAdFrame(is_ad_subframe);
 
-  UseCounter::Count(DomWindow(), WebFeature::kAdFrameDetected);
-  InstanceCounters::IncrementCounter(InstanceCounters::kAdSubframeCounter);
+  if (is_ad_subframe) {
+    UseCounter::Count(DomWindow(), WebFeature::kAdFrameDetected);
+    InstanceCounters::IncrementCounter(InstanceCounters::kAdSubframeCounter);
+  } else {
+    InstanceCounters::DecrementCounter(InstanceCounters::kAdSubframeCounter);
+  }
 }
 
 void LocalFrame::UpdateAdHighlight() {
-  if (!IsAdRoot()) {
-    // Verify that non root ad subframes do not have an overlay.
-    DCHECK(IsMainFrame() || !frame_color_overlay_);
+  if (IsMainFrame())
     return;
-  }
-  if (GetPage()->GetSettings().GetHighlightAds())
+
+  if (IsAdRoot() && GetPage()->GetSettings().GetHighlightAds())
     SetSubframeColorOverlay(SkColorSetARGB(128, 255, 0, 0));
   else
     SetSubframeColorOverlay(Color::kTransparent);
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h
index 7fbd059..440cdc0 100644
--- a/third_party/blink/renderer/core/frame/local_frame.h
+++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -503,9 +503,9 @@
   // be removed.
   bool IsProvisional() const;
 
-  // Called by the embedder if the evidence indicates the frame is an ad
-  // subframe. Called on creation of the initial empty document or, for
-  // LocalFrames created on behalf of OOPIF, just before commit
+  // Called by the embedder according to whether the evidence indicates the
+  // frame is an ad subframe. Called on creation of the initial empty document
+  // or, for LocalFrames created on behalf of OOPIF, just before commit
   // (ReadyToCommitNavigation time).
   void SetIsAdSubframe(blink::mojom::AdFrameType ad_frame_type);
 
diff --git a/third_party/blink/renderer/core/frame/remote_frame.cc b/third_party/blink/renderer/core/frame/remote_frame.cc
index 3540d99..36c8981d 100644
--- a/third_party/blink/renderer/core/frame/remote_frame.cc
+++ b/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -570,11 +570,7 @@
 
 void RemoteFrame::SetReplicatedAdFrameType(
     mojom::blink::AdFrameType ad_frame_type) {
-  if (ad_frame_type_ == mojom::blink::AdFrameType::kNonAd) {
-    ad_frame_type_ = ad_frame_type;
-  } else {
-    DCHECK_EQ(ad_frame_type_, ad_frame_type);
-  }
+  ad_frame_type_ = ad_frame_type;
 }
 
 void RemoteFrame::SetReplicatedName(const String& name,
diff --git a/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.cc b/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.cc
index 998e7bd..0dd3687b 100644
--- a/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.cc
+++ b/third_party/blink/renderer/core/layout/ng/custom/custom_layout_work_task.cc
@@ -154,8 +154,7 @@
   DCHECK_EQ(type_, CustomLayoutWorkTask::TaskType::kIntrinsicSizes);
   DCHECK(resolver_);
 
-  MinMaxSizesInput input(child_percentage_resolution_block_size_for_min_max,
-                         MinMaxSizesType::kContent);
+  MinMaxSizesInput input(child_percentage_resolution_block_size_for_min_max);
   MinMaxSizesResult result = ComputeMinAndMaxContentContribution(
       parent_style, To<NGBlockNode>(child), input);
   resolver_->Resolve(MakeGarbageCollected<CustomIntrinsicSizes>(
diff --git a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
index 44381ac..16835f0 100644
--- a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
@@ -542,9 +542,9 @@
         // pass child's writing mode as the first parameter, which is nominally
         // |container_writing_mode|.
         NGConstraintSpace child_space = BuildSpaceForIntrinsicBlockSize(child);
-        MinMaxSizesInput input(ChildAvailableSize().block_size, type);
+        MinMaxSizesInput input(ChildAvailableSize().block_size);
         min_max_sizes = child.ComputeMinMaxSizes(child_style.GetWritingMode(),
-                                                 input, &child_space);
+                                                 type, input, &child_space);
       }
       return *min_max_sizes;
     };
@@ -850,9 +850,8 @@
       MinMaxSizes table_intrinsic_widths =
           child
               .ComputeMinMaxSizes(
-                  ConstraintSpace().GetWritingMode(),
-                  MinMaxSizesInput(child_percentage_size_.block_size,
-                                   MinMaxSizesType::kContent),
+                  ConstraintSpace().GetWritingMode(), MinMaxSizesType::kContent,
+                  MinMaxSizesInput(child_percentage_size_.block_size),
                   ortho_child_space)
               .sizes;
 
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
index 394971e..3e0a0ad 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
@@ -714,7 +714,7 @@
     // We'll want to determine this using the base or used track-sizes instead.
     // This should match the %-resolution sizes we use for layout during
     // measuring.
-    MinMaxSizesInput input(kIndefiniteSize, MinMaxSizesType::kContent);
+    MinMaxSizesInput input(kIndefiniteSize);
     return ComputeMinAndMaxContentContributionForSelf(node, input).sizes;
   };
 
@@ -802,9 +802,9 @@
                   [&](MinMaxSizesType type) -> MinMaxSizesResult {
                 // TODO(ikilpatrick): Again, kIndefiniteSize here is incorrect,
                 // and needs to use the base or resolved track sizes.
-                MinMaxSizesInput input(kIndefiniteSize, type);
+                MinMaxSizesInput input(kIndefiniteSize);
                 return node.ComputeMinMaxSizes(item_style.GetWritingMode(),
-                                               input, &space);
+                                               type, input, &space);
               };
 
               contribution = ResolveMinInlineLength(
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
index 19059a78..41cc5575 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.cc
@@ -1694,8 +1694,7 @@
       const ComputedStyle& float_style = float_node.Style();
 
       // Floats don't intrude into floats.
-      MinMaxSizesInput float_input(input.percentage_resolution_block_size,
-                                   MinMaxSizesType::kContent);
+      MinMaxSizesInput float_input(input.percentage_resolution_block_size);
       MinMaxSizesResult child_result =
           ComputeMinAndMaxContentContribution(style, float_node, float_input);
       LayoutUnit child_inline_margins =
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
index c15455a..f8b83f15e 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node_test.cc
@@ -106,8 +106,7 @@
         .ComputeMinMaxSizes(
             node.Style().GetWritingMode(),
             MinMaxSizesInput(
-                /* percentage_resolution_block_size */ LayoutUnit(),
-                MinMaxSizesType::kContent))
+                /* percentage_resolution_block_size */ LayoutUnit()))
         .sizes;
   }
 
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
index 354b3dac..f9fe26c 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.cc
@@ -1589,8 +1589,7 @@
   } else {
     DCHECK(mode_ == NGLineBreakerMode::kMinContent || !max_size_cache_);
     NGBlockNode child(To<LayoutBox>(item.GetLayoutObject()));
-    MinMaxSizesInput input(percentage_resolution_block_size_for_min_max,
-                           MinMaxSizesType::kContent);
+    MinMaxSizesInput input(percentage_resolution_block_size_for_min_max);
     MinMaxSizesResult result =
         ComputeMinAndMaxContentContribution(node_.Style(), child, input);
     if (mode_ == NGLineBreakerMode::kMinContent) {
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
index 2f12a09..d68c050 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker_test.cc
@@ -567,12 +567,11 @@
     <div id=container>12345 6789 </div>
   )HTML");
 
-  auto sizes =
-      node.ComputeMinMaxSizes(
-              WritingMode::kHorizontalTb,
-              MinMaxSizesInput(/* percentage_resolution_block_size */
-                               LayoutUnit(), MinMaxSizesType::kContent))
-          .sizes;
+  auto sizes = node.ComputeMinMaxSizes(
+                       WritingMode::kHorizontalTb,
+                       MinMaxSizesInput(
+                           /* percentage_resolution_block_size */ LayoutUnit()))
+                   .sizes;
   EXPECT_EQ(sizes.min_size, LayoutUnit(60));
   EXPECT_EQ(sizes.max_size, LayoutUnit(110));
 }
@@ -656,8 +655,7 @@
 
   node.ComputeMinMaxSizes(
       WritingMode::kHorizontalTb,
-      MinMaxSizesInput(/* percentage_resolution_block_size */ LayoutUnit(),
-                       MinMaxSizesType::kContent));
+      MinMaxSizesInput(/* percentage_resolution_block_size */ LayoutUnit()));
   // Pass if |ComputeMinMaxSize| doesn't hit DCHECK failures.
 }
 
@@ -697,8 +695,7 @@
 
   node.ComputeMinMaxSizes(
       WritingMode::kHorizontalTb,
-      MinMaxSizesInput(/* percentage_resolution_block_size */ LayoutUnit(),
-                       MinMaxSizesType::kContent));
+      MinMaxSizesInput(/* percentage_resolution_block_size */ LayoutUnit()));
   // This test passes if no CHECK failures.
 }
 
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
index 1bb3783..c07b397 100644
--- a/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
+++ b/third_party/blink/renderer/core/layout/ng/layout_ng_mixin.cc
@@ -181,10 +181,9 @@
 
   NGConstraintSpace space = ConstraintSpaceForMinMaxSizes();
   MinMaxSizes sizes =
-      node.ComputeMinMaxSizes(node.Style().GetWritingMode(),
-                              MinMaxSizesInput(available_logical_height,
-                                               MinMaxSizesType::kContent),
-                              &space)
+      node.ComputeMinMaxSizes(
+              node.Style().GetWritingMode(), MinMaxSizesType::kContent,
+              MinMaxSizesInput(available_logical_height), &space)
           .sizes;
 
   if (Base::IsTableCell()) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
index c93df5f8..c2685cb 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -280,8 +280,7 @@
         float_right_inline_size = LayoutUnit();
     }
 
-    MinMaxSizesInput child_input(input.percentage_resolution_block_size,
-                                 input.type);
+    MinMaxSizesInput child_input(input.percentage_resolution_block_size);
     if (child.IsInline() || child.IsAnonymousBlock()) {
       child_input.float_left_inline_size = float_left_inline_size;
       child_input.float_right_inline_size = float_right_inline_size;
@@ -2677,7 +2676,6 @@
     SetupSpaceBuilderForFragmentation(ConstraintSpace(), child,
                                       fragmentainer_offset_delta, &builder,
                                       is_new_fc);
-    builder.SetEarlyBreakAppeal(container_builder_.BreakAppeal());
   }
 
   return builder.ToConstraintSpace();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc
index ded2845..dd6ec139 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm_test.cc
@@ -45,8 +45,7 @@
 
     NGBlockLayoutAlgorithm algorithm({node, fragment_geometry, space});
     MinMaxSizesInput input(
-        /* percentage_resolution_block_size */ LayoutUnit(),
-        MinMaxSizesType::kContent);
+        /* percentage_resolution_block_size */ (LayoutUnit()));
     return algorithm.ComputeMinMaxSizes(input).sizes;
   }
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
index 9cbb22b..5690440c 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -769,6 +769,7 @@
 
 MinMaxSizesResult NGBlockNode::ComputeMinMaxSizes(
     WritingMode container_writing_mode,
+    const MinMaxSizesType type,
     const MinMaxSizesInput& input,
     const NGConstraintSpace* constraint_space) const {
   // TODO(layoutng) Can UpdateMarkerTextIfNeeded call be moved
@@ -790,7 +791,7 @@
     // of the layout phase.
     // TODO(ikilpatrick): Remove this check.
     if (!box_->GetFrameView()->IsInPerformLayout()) {
-      sizes = ComputeMinMaxSizesFromLegacy(input, *constraint_space);
+      sizes = ComputeMinMaxSizesFromLegacy(type, *constraint_space);
       return MinMaxSizesResult(sizes,
                                /* depends_on_percentage_block_size */ false);
     }
@@ -812,7 +813,7 @@
     constraint_space = &zero_constraint_space;
 
   if (!Style().AspectRatio().IsAuto() && !IsReplaced() &&
-      input.type == MinMaxSizesType::kContent) {
+      type == MinMaxSizesType::kContent) {
     LayoutUnit block_size(kIndefiniteSize);
     if (IsOutOfFlowPositioned()) {
       // For out-of-flow, the input percentage block size is actually our
@@ -847,7 +848,7 @@
        !box_->IntrinsicLogicalWidthsChildDependsOnPercentageBlockSize())) {
     MinMaxSizes sizes = box_->IsTable() && !box_->IsLayoutNGMixin()
                             ? box_->PreferredLogicalWidths()
-                            : box_->IntrinsicLogicalWidths(input.type);
+                            : box_->IntrinsicLogicalWidths(type);
     bool depends_on_percentage_block_size =
         box_->IntrinsicLogicalWidthsDependsOnPercentageBlockSize();
     return MinMaxSizesResult(sizes, depends_on_percentage_block_size);
@@ -877,14 +878,14 @@
       !cache_depends_on_percentage_block_size) {
     MinMaxSizes sizes = box_->IsTable() && !box_->IsLayoutNGMixin()
                             ? box_->PreferredLogicalWidths()
-                            : box_->IntrinsicLogicalWidths(input.type);
+                            : box_->IntrinsicLogicalWidths(type);
     return MinMaxSizesResult(sizes, cache_depends_on_percentage_block_size);
   }
 
   box_->SetIntrinsicLogicalWidthsDirty(kMarkOnlyThis);
 
   if (!CanUseNewLayout()) {
-    MinMaxSizes sizes = ComputeMinMaxSizesFromLegacy(input, *constraint_space);
+    MinMaxSizes sizes = ComputeMinMaxSizesFromLegacy(type, *constraint_space);
 
     // Update the cache bits for this legacy root (but not the intrinsic
     // inline-sizes themselves).
@@ -945,7 +946,7 @@
 }
 
 MinMaxSizes NGBlockNode::ComputeMinMaxSizesFromLegacy(
-    const MinMaxSizesInput& input,
+    const MinMaxSizesType type,
     const NGConstraintSpace& space) const {
   BoxLayoutExtraInput extra_input(*box_);
   SetupBoxLayoutExtraInput(space, *box_, &extra_input);
@@ -955,9 +956,8 @@
   // meaning for tables.
   //
   // Due to this the min/max content contribution is their min/max content size.
-  MinMaxSizes sizes = box_->IsTable()
-                          ? box_->PreferredLogicalWidths()
-                          : box_->IntrinsicLogicalWidths(input.type);
+  MinMaxSizes sizes = box_->IsTable() ? box_->PreferredLogicalWidths()
+                                      : box_->IntrinsicLogicalWidths(type);
 
   return sizes;
 }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.h b/third_party/blink/renderer/core/layout/ng/ng_block_node.h
index 931c2666..1b33306 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_node.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.h
@@ -85,10 +85,11 @@
   // space is not optional.
   MinMaxSizesResult ComputeMinMaxSizes(
       WritingMode container_writing_mode,
+      const MinMaxSizesType,
       const MinMaxSizesInput&,
       const NGConstraintSpace* = nullptr) const;
 
-  MinMaxSizes ComputeMinMaxSizesFromLegacy(const MinMaxSizesInput&,
+  MinMaxSizes ComputeMinMaxSizesFromLegacy(const MinMaxSizesType,
                                            const NGConstraintSpace&) const;
 
   NGLayoutInputNode FirstChild() const;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node_test.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node_test.cc
index 91375bf..6aae0e4 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_node_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_node_test.cc
@@ -176,10 +176,9 @@
   NGBlockNode box(GetLayoutBoxByElementId("box"));
   MinMaxSizes sizes =
       box.ComputeMinMaxSizes(
-             WritingMode::kHorizontalTb,
+             WritingMode::kHorizontalTb, MinMaxSizesType::kContent,
              MinMaxSizesInput(
-                 /* percentage_resolution_block_size */ LayoutUnit(),
-                 MinMaxSizesType::kContent))
+                 /* percentage_resolution_block_size */ LayoutUnit()))
           .sizes;
   EXPECT_EQ(LayoutUnit(kWidth), sizes.min_size);
   EXPECT_EQ(LayoutUnit(kWidth), sizes.max_size);
@@ -202,10 +201,9 @@
     NGBlockNode box(GetLayoutBoxByElementId(id));
     MinMaxSizes sizes =
         box.ComputeMinMaxSizes(
-               WritingMode::kHorizontalTb,
+               WritingMode::kHorizontalTb, MinMaxSizesType::kContent,
                MinMaxSizesInput(
-                   /* percentage_resolution_block_size */ LayoutUnit(-1),
-                   MinMaxSizesType::kContent))
+                   /* percentage_resolution_block_size */ LayoutUnit(-1)))
             .sizes;
     EXPECT_EQ(LayoutUnit(kExpectedMinWidth), sizes.min_size);
   }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
index f8f45dee..71e13a6 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm_test.cc
@@ -2709,8 +2709,7 @@
   NGColumnLayoutAlgorithm algorithm({node, fragment_geometry, space});
   base::Optional<MinMaxSizes> sizes;
   MinMaxSizesInput zero_input(
-      /* percentage_resolution_block_size */ LayoutUnit(),
-      MinMaxSizesType::kContent);
+      /* percentage_resolution_block_size */ (LayoutUnit()));
 
   // Both column-count and column-width set.
   style->SetColumnCount(3);
diff --git a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
index 64701ed..fe0a7e9 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_constraint_space.h
@@ -496,15 +496,6 @@
     return HasRareData() && rare_data_->is_in_column_bfc;
   }
 
-  // Get the appeal of the best breakpoint found so far. When progressing
-  // through layout, we know that we don't need to consider less appealing
-  // breakpoints than this.
-  NGBreakAppeal EarlyBreakAppeal() const {
-    if (!HasRareData())
-      return kBreakAppealLastResort;
-    return static_cast<NGBreakAppeal>(rare_data_->early_break_appeal);
-  }
-
   // Returns if this node is a table cell child, and which table layout mode
   // is occurring.
   NGTableCellChildLayoutMode TableCellChildLayoutMode() const {
@@ -756,8 +747,7 @@
           block_direction_fragmentation_type(
               static_cast<unsigned>(kFragmentNone)),
           is_inside_balanced_columns(false),
-          is_in_column_bfc(false),
-          early_break_appeal(kBreakAppealLastResort) {}
+          is_in_column_bfc(false) {}
     RareData(const RareData& other)
         : percentage_resolution_size(other.percentage_resolution_size),
           replaced_percentage_resolution_block_size(
@@ -773,8 +763,7 @@
           block_direction_fragmentation_type(
               other.block_direction_fragmentation_type),
           is_inside_balanced_columns(other.is_inside_balanced_columns),
-          is_in_column_bfc(other.is_in_column_bfc),
-          early_break_appeal(other.early_break_appeal) {
+          is_in_column_bfc(other.is_in_column_bfc) {
       switch (data_union_type) {
         case kNone:
           break;
@@ -838,8 +827,7 @@
           block_direction_fragmentation_type !=
               other.block_direction_fragmentation_type ||
           is_inside_balanced_columns != other.is_inside_balanced_columns ||
-          is_in_column_bfc != other.is_in_column_bfc ||
-          early_break_appeal != other.early_break_appeal)
+          is_in_column_bfc != other.is_in_column_bfc)
         return false;
 
       switch (data_union_type) {
@@ -868,8 +856,7 @@
           fragmentainer_offset_at_bfc || is_restricted_block_size_table_cell ||
           hide_table_cell_if_empty ||
           block_direction_fragmentation_type != kFragmentNone ||
-          is_inside_balanced_columns || is_in_column_bfc ||
-          early_break_appeal != kBreakAppealLastResort)
+          is_inside_balanced_columns || is_in_column_bfc)
         return false;
 
       switch (data_union_type) {
@@ -1117,7 +1104,6 @@
     unsigned block_direction_fragmentation_type : 2;
     unsigned is_inside_balanced_columns : 1;
     unsigned is_in_column_bfc : 1;
-    unsigned early_break_appeal : 2;  // NGBreakAppeal
    private:
     struct BlockData {
       bool MaySkipLayout(const BlockData& other) const {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h b/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h
index 818ed92..eb6e25a 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_constraint_space_builder.h
@@ -175,12 +175,6 @@
 
   void SetIsInColumnBfc() { space_.EnsureRareData()->is_in_column_bfc = true; }
 
-  void SetEarlyBreakAppeal(NGBreakAppeal appeal) {
-    if (appeal == kBreakAppealLastResort && !space_.rare_data_)
-      return;
-    space_.EnsureRareData()->early_break_appeal = appeal;
-  }
-
   // is_legacy_table_cell must always be assigned if is_table_cell is true.
   void SetIsTableCell(bool is_table_cell, bool is_legacy_table_cell) {
     space_.bitfields_.is_table_cell = is_table_cell;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
index c9f3062..9c73274 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm.cc
@@ -465,7 +465,6 @@
     SetupSpaceBuilderForFragmentation(ConstraintSpace(), fieldset_content,
                                       block_offset, &builder,
                                       /* is_new_fc */ true);
-    builder.SetEarlyBreakAppeal(container_builder_.BreakAppeal());
   }
   return builder.ToConstraintSpace();
 }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc
index 2d0c3cb..eb89e16 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_fieldset_layout_algorithm_test.cc
@@ -40,8 +40,7 @@
 
     NGFieldsetLayoutAlgorithm algorithm({node, fragment_geometry, space});
     MinMaxSizesInput input(
-        /* percentage_resolution_block_size */ LayoutUnit(),
-        MinMaxSizesType::kContent);
+        /* percentage_resolution_block_size */ (LayoutUnit()));
     return algorithm.ComputeMinMaxSizes(input).sizes;
   }
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
index 8570672..1f40850 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
@@ -217,11 +217,6 @@
   builder->SetHasBlockFragmentation();
   builder->SetPreviousBreakToken(previous_break_token);
 
-  // The whereabouts of our container's so far best breakpoint is none of our
-  // business, but we store its appeal, so that we don't look for breakpoints
-  // with lower appeal than that.
-  builder->SetBreakAppeal(space.EarlyBreakAppeal());
-
   if (space.IsInitialColumnBalancingPass())
     builder->SetIsInitialColumnBalancingPass();
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h b/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h
index 4e5c15b..2d2586a 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h
@@ -40,15 +40,11 @@
   //
   // As we don't perform any tree walking, we need to pass the percentage
   // resolution block-size for min/max down the min/max size calculation.
-  MinMaxSizesInput(LayoutUnit percentage_resolution_block_size,
-                   MinMaxSizesType type)
-      : percentage_resolution_block_size(percentage_resolution_block_size),
-        type(type) {}
+  explicit MinMaxSizesInput(LayoutUnit percentage_resolution_block_size)
+      : percentage_resolution_block_size(percentage_resolution_block_size) {}
   LayoutUnit float_left_inline_size;
   LayoutUnit float_right_inline_size;
   LayoutUnit percentage_resolution_block_size;
-
-  MinMaxSizesType type;
 };
 
 // The output of the min/max inline size calculation algorithm. Contains the
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
index 31ac83d..b9a87e6 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
@@ -399,26 +399,26 @@
 
   if (IsParallelWritingMode(parent_writing_mode, child_writing_mode)) {
     // Legacy tables are special - always let the legacy table code handle this.
-    if (child.IsTable() && !child.IsNGTable())
-      return child.ComputeMinMaxSizes(parent_writing_mode, input, nullptr);
+    if (child.IsTable() && !child.IsNGTable()) {
+      return child.ComputeMinMaxSizes(
+          parent_writing_mode, MinMaxSizesType::kContent, input, nullptr);
+    }
 
     if (child.IsReplaced())
       return ComputeMinAndMaxContentContributionForReplaced(child, input);
   }
 
   auto MinMaxSizesFunc = [&](MinMaxSizesType type) -> MinMaxSizesResult {
-    MinMaxSizesInput input_copy(input);
-    input_copy.type = type;
     // We need to set up a constraint space with correct fallback available
     // inline-size in case of orthogonal children.
     NGConstraintSpace indefinite_constraint_space;
     const NGConstraintSpace* child_constraint_space = nullptr;
     if (!IsParallelWritingMode(parent_writing_mode, child_writing_mode)) {
-      indefinite_constraint_space = CreateIndefiniteConstraintSpaceForChild(
-          parent_style, input_copy, child);
+      indefinite_constraint_space =
+          CreateIndefiniteConstraintSpaceForChild(parent_style, input, child);
       child_constraint_space = &indefinite_constraint_space;
     }
-    return child.ComputeMinMaxSizes(parent_writing_mode, input_copy,
+    return child.ComputeMinMaxSizes(parent_writing_mode, type, input,
                                     child_constraint_space);
   };
 
@@ -433,16 +433,16 @@
   WritingMode writing_mode = child_style.GetWritingMode();
 
   // Legacy tables are special - always let the legacy table code handle this.
-  if (child.IsTable() && !child.IsNGTable())
-    return child.ComputeMinMaxSizes(writing_mode, input, nullptr);
+  if (child.IsTable() && !child.IsNGTable()) {
+    return child.ComputeMinMaxSizes(writing_mode, MinMaxSizesType::kContent,
+                                    input, nullptr);
+  }
 
   if (child.IsReplaced())
     return ComputeMinAndMaxContentContributionForReplaced(child, input);
 
   auto MinMaxSizesFunc = [&](MinMaxSizesType type) -> MinMaxSizesResult {
-    MinMaxSizesInput input_copy(input);
-    input_copy.type = type;
-    return child.ComputeMinMaxSizes(writing_mode, input_copy);
+    return child.ComputeMinMaxSizes(writing_mode, type, input);
   };
 
   return ComputeMinAndMaxContentContributionInternal(writing_mode, child,
@@ -499,8 +499,8 @@
                                /* depends_on_percentage_block_size */ false);
     }
 
-    MinMaxSizesInput input(space.PercentageResolutionBlockSize(), type);
-    return node.ComputeMinMaxSizes(space.GetWritingMode(), input, &space);
+    MinMaxSizesInput input(space.PercentageResolutionBlockSize());
+    return node.ComputeMinMaxSizes(space.GetWritingMode(), type, input, &space);
   };
 
   const ComputedStyle& style = node.Style();
@@ -1326,11 +1326,10 @@
   if (node.IsReplaced()) {
     LogicalSize border_box_size;
     MinMaxSizesInput min_max_input(
-        constraint_space.ReplacedPercentageResolutionBlockSize(),
-        MinMaxSizesType::kIntrinsic);
+        constraint_space.ReplacedPercentageResolutionBlockSize());
     MinMaxSizes intrinsic_min_max_sizes =
         node.ComputeMinMaxSizes(constraint_space.GetWritingMode(),
-                                min_max_input)
+                                MinMaxSizesType::kIntrinsic, min_max_input)
             .sizes;
     base::Optional<LogicalSize> replaced_size;
     base::Optional<LogicalSize> aspect_ratio;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
index b2c3bba..bdafc6ed 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -965,7 +965,7 @@
   if (AbsoluteNeedsChildInlineSize(node_info.node) ||
       NeedMinMaxSize(candidate_style) || should_be_considered_as_replaced ||
       compute_inline_from_ar) {
-    MinMaxSizesInput input(kIndefiniteSize, MinMaxSizesType::kContent);
+    MinMaxSizesInput input(kIndefiniteSize);
     if (is_replaced) {
       input.percentage_resolution_block_size =
           container_content_size_in_candidate_writing_mode.block_size;
@@ -982,19 +982,19 @@
     }
     if (compute_inline_from_ar &&
         candidate_style.OverflowInlineDirection() == EOverflow::kVisible) {
-      MinMaxSizesInput intrinsic_input(input);
-      intrinsic_input.type = MinMaxSizesType::kIntrinsic;
       minmax_intrinsic_sizes_for_ar =
           node_info.node
               .ComputeMinMaxSizes(candidate_writing_direction.GetWritingMode(),
-                                  intrinsic_input, &node_info.constraint_space)
+                                  MinMaxSizesType::kIntrinsic, input,
+                                  &node_info.constraint_space)
               .sizes;
     }
 
     min_max_sizes =
         node_info.node
             .ComputeMinMaxSizes(candidate_writing_direction.GetWritingMode(),
-                                input, &node_info.constraint_space)
+                                MinMaxSizesType::kContent, input,
+                                &node_info.constraint_space)
             .sizes;
   }
 
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
index d6e218fb..b20f9f8 100644
--- a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm.cc
@@ -41,9 +41,8 @@
     // block-size to resolve against.
     NGBoxStrut margins = ComputeMinMaxMargins(table_style, caption);
     MinMaxSizes min_max_size =
-        ComputeMinAndMaxContentContribution(
-            table_style, caption,
-            MinMaxSizesInput(kIndefiniteSize, MinMaxSizesType::kContent))
+        ComputeMinAndMaxContentContribution(table_style, caption,
+                                            MinMaxSizesInput(kIndefiniteSize))
             .sizes;
     min_max_size += margins.InlineSum();
     caption_min_max.Encompass(min_max_size);
diff --git a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_types.cc b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_types.cc
index a823e00..0e89dd5 100644
--- a/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_types.cc
+++ b/third_party/blink/renderer/core/layout/ng/table/ng_table_layout_algorithm_types.cc
@@ -147,9 +147,11 @@
       builder.SetAvailableSize({kIndefiniteSize, kIndefiniteSize});
       const auto space = builder.ToConstraintSpace();
 
-      MinMaxSizesInput input(kIndefiniteSize, MinMaxSizesType::kIntrinsic);
+      MinMaxSizesInput input(kIndefiniteSize);
       cached_min_max_sizes =
-          node.ComputeMinMaxSizes(table_writing_mode, input, &space).sizes;
+          node.ComputeMinMaxSizes(table_writing_mode,
+                                  MinMaxSizesType::kIntrinsic, input, &space)
+              .sizes;
     }
 
     return *cached_min_max_sizes;
diff --git a/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc b/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
index 62c621a..8780e785 100644
--- a/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
+++ b/third_party/blink/renderer/core/page/scrolling/snap_coordinator.cc
@@ -21,6 +21,17 @@
 // This is experimentally determined and corresponds to the UA decided
 // parameter as mentioned in spec.
 constexpr float kProximityRatio = 1.0 / 3.0;
+
+cc::SnapAlignment AdjustForRtlWritingMode(cc::SnapAlignment align) {
+  if (align == cc::SnapAlignment::kStart)
+    return cc::SnapAlignment::kEnd;
+
+  if (align == cc::SnapAlignment::kEnd)
+    return cc::SnapAlignment::kStart;
+
+  return align;
+}
+
 }  // namespace
 // TODO(sunyunjia): Move the static functions to an anonymous namespace.
 
@@ -328,25 +339,42 @@
   }
 }
 
+// https://drafts.csswg.org/css-scroll-snap-1/#scroll-snap-align
+// After normalization:
+//   * inline corresponds to x, and block corresponds to y
+//   * start corresponds to left or top
+//   * end corresponds to right or bottom
+// In other words, the adjusted logical properties map to a physical layout
+// as if the writing mode were horizontal left to right and top to bottom.
 static cc::ScrollSnapAlign GetPhysicalAlignment(
     const ComputedStyle& area_style,
     const ComputedStyle& container_style) {
   cc::ScrollSnapAlign align = area_style.GetScrollSnapAlign();
-  if (container_style.IsHorizontalWritingMode())
-    return align;
-
-  cc::SnapAlignment tmp = align.alignment_inline;
-  align.alignment_inline = align.alignment_block;
-  align.alignment_block = tmp;
-
-  if (container_style.IsFlippedBlocksWritingMode()) {
-    if (align.alignment_inline == cc::SnapAlignment::kStart) {
-      align.alignment_inline = cc::SnapAlignment::kEnd;
-    } else if (align.alignment_inline == cc::SnapAlignment::kEnd) {
-      align.alignment_inline = cc::SnapAlignment::kStart;
-    }
+  cc::ScrollSnapAlign adjusted_alignment;
+  // TODO(crbug.com/1169092): Align choice of box for determining the writing
+  // mode with the spec, which states:
+  //   Start and end alignments are resolved with respect to the writing mode
+  //   of the snap container unless the scroll snap area is larger than the
+  //   snapport, in which case they are resolved with respect to the writing
+  //   mode of the box itself. (This allows items in a container to have
+  //   consistent snap alignment in general, while ensuring that start always
+  //   aligns the item to allow reading its contents from the beginning.)
+  WritingDirectionMode writing_direction =
+      container_style.GetWritingDirection();
+  if (writing_direction.IsHorizontal()) {
+    bool rtl = (writing_direction.IsRtl());
+    adjusted_alignment.alignment_inline =
+        rtl ? AdjustForRtlWritingMode(align.alignment_inline)
+            : align.alignment_inline;
+    adjusted_alignment.alignment_block = align.alignment_block;
+  } else {
+    bool rtl = writing_direction.IsFlippedBlocks();
+    adjusted_alignment.alignment_inline =
+        rtl ? AdjustForRtlWritingMode(align.alignment_block)
+            : align.alignment_block;
+    adjusted_alignment.alignment_block = align.alignment_inline;
   }
-  return align;
+  return adjusted_alignment;
 }
 
 cc::SnapAreaData SnapCoordinator::CalculateSnapAreaData(
@@ -372,9 +400,8 @@
   area_rect.Expand(area_margin);
   snap_area_data.rect = FloatRect(area_rect);
 
-  cc::ScrollSnapAlign align =
+  snap_area_data.scroll_snap_align =
       GetPhysicalAlignment(*area_style, *container_style);
-  snap_area_data.scroll_snap_align = align;
 
   snap_area_data.must_snap =
       (area_style->ScrollSnapStop() == EScrollSnapStop::kAlways);
diff --git a/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.cc b/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.cc
index a6615d2..ff343ac 100644
--- a/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.cc
+++ b/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.cc
@@ -127,10 +127,18 @@
 
 void TextFragmentFinder::OnFindMatchInRangeComplete(
     String search_text,
-    Range* search_range,
+    RangeInFlatTree* search_range,
     bool word_start_bounded,
     bool word_end_bounded,
     const EphemeralRangeInFlatTree& match) {
+  // If any of our ranges became invalid, stop the search.
+  if (!HasValidRanges()) {
+    potential_match_.Clear();
+    first_match_.Clear();
+    OnMatchComplete();
+    return;
+  }
+
   if (match.IsNull() ||
       IsWordBounded(match, word_start_bounded, word_end_bounded)) {
     switch (step_) {
@@ -149,14 +157,13 @@
     }
     return;
   }
-
-  search_range->setStart(ToPositionInDOMTree(match.EndPosition()));
+  search_range->SetStart(match.EndPosition());
   FindMatchInRange(search_text, search_range, word_start_bounded,
                    word_end_bounded);
 }
 
 void TextFragmentFinder::FindMatchInRange(String search_text,
-                                          Range* search_range,
+                                          RangeInFlatTree* search_range,
                                           bool word_start_bounded,
                                           bool word_end_bounded) {
   find_buffer_runner_->FindMatchInRange(
@@ -168,8 +175,8 @@
 }
 
 void TextFragmentFinder::FindPrefix() {
-  search_range_->setStart(match_range_->StartPosition());
-  if (search_range_->collapsed()) {
+  search_range_->SetStart(match_range_->StartPosition());
+  if (search_range_->IsCollapsed()) {
     OnMatchComplete();
     return;
   }
@@ -199,8 +206,7 @@
   // with the current one. e.g. If |prefix| is "a a" and our search range
   // currently starts with "a a a b...", the next iteration should start at
   // the second a which is part of the current |prefix_match|.
-  match_range_->setStart(ToPositionInDOMTree(
-      FirstWordBoundaryAfter(prefix_match.StartPosition())));
+  match_range_->SetStart(FirstWordBoundaryAfter(prefix_match.StartPosition()));
   SetPrefixMatch(prefix_match);
   GoToStep(kMatchTextStart);
   return;
@@ -217,12 +223,9 @@
   // details.
   const bool end_at_word_boundary =
       !selector_.End().IsEmpty() || selector_.Suffix().IsEmpty();
-  EphemeralRangeInFlatTree prefix_match(prefix_match_);
-  EphemeralRangeInFlatTree potential_match;
-  if (prefix_match.IsNotNull()) {
-    search_range_->setStart(ToPositionInDOMTree(
-        NextTextPosition(prefix_match.EndPosition(),
-                         ToPositionInFlatTree(match_range_->EndPosition()))));
+  if (prefix_match_) {
+    search_range_->SetStart(NextTextPosition(prefix_match_->EndPosition(),
+                                             match_range_->EndPosition()));
     FindMatchInRange(selector_.Start(), search_range_,
                      /*word_start_bounded=*/false, end_at_word_boundary);
   } else {
@@ -233,15 +236,12 @@
 
 void TextFragmentFinder::OnTextStartMatchComplete(
     EphemeralRangeInFlatTree potential_match) {
-  EphemeralRangeInFlatTree prefix_match(prefix_match_);
-  if (prefix_match.IsNotNull()) {
-    EphemeralRangeInFlatTree match_range(
-        NextTextPosition(prefix_match.EndPosition(),
-                         ToPositionInFlatTree(match_range_->EndPosition())),
-        ToPositionInFlatTree(match_range_->EndPosition()));
+  if (prefix_match_) {
+    PositionInFlatTree next_position_after_prefix = NextTextPosition(
+        prefix_match_->EndPosition(), match_range_->EndPosition());
     // We found a potential match but it didn't immediately follow the prefix.
     if (!potential_match.IsNull() &&
-        potential_match.StartPosition() != match_range.StartPosition()) {
+        potential_match.StartPosition() != next_position_after_prefix) {
       potential_match_.Clear();
       GoToStep(kMatchPrefix);
       return;
@@ -253,11 +253,17 @@
     OnMatchComplete();
     return;
   }
-  if (prefix_match.IsNull()) {
-    match_range_->setStart(ToPositionInDOMTree(
-        FirstWordBoundaryAfter(potential_match.StartPosition())));
+  if (!prefix_match_) {
+    match_range_->SetStart(
+        FirstWordBoundaryAfter(potential_match.StartPosition()));
   }
-  range_end_search_start_ = potential_match.EndPosition();
+  if (!range_end_search_start_) {
+    range_end_search_start_ = MakeGarbageCollected<RelocatablePosition>(
+        ToPositionInDOMTree(potential_match.EndPosition()));
+  } else {
+    range_end_search_start_->SetPosition(
+        ToPositionInDOMTree(potential_match.EndPosition()));
+  }
   SetPotentialMatch(potential_match);
   GoToStep(kMatchTextEnd);
 }
@@ -267,7 +273,8 @@
   // that's followed by the |start_text|. We'll now try to expand that into
   // a range match if |end_text| is specified.
   if (!selector_.End().IsEmpty()) {
-    search_range_->setStart(ToPositionInDOMTree(range_end_search_start_));
+    search_range_->SetStart(
+        ToPositionInFlatTree(range_end_search_start_->GetPosition()));
     const bool end_at_word_boundary = selector_.Suffix().IsEmpty();
 
     FindMatchInRange(selector_.End(), search_range_,
@@ -285,15 +292,12 @@
     return;
   }
 
-  EphemeralRangeInFlatTree potential_match(potential_match_);
-  SetPotentialMatch(EphemeralRangeInFlatTree(potential_match.StartPosition(),
-                                             text_end_match.EndPosition()));
+  potential_match_->SetEnd(text_end_match.EndPosition());
   GoToStep(kMatchSuffix);
 }
 
 void TextFragmentFinder::FindSuffix() {
-  EphemeralRangeInFlatTree potential_match(potential_match_);
-  DCHECK(!potential_match.IsNull());
+  DCHECK(!potential_match_->IsNull());
 
   if (selector_.Suffix().IsEmpty()) {
     OnMatchComplete();
@@ -301,9 +305,8 @@
   }
 
   // Now we just have to ensure the match is followed by the |suffix|.
-  search_range_->setStart(ToPositionInDOMTree(
-      NextTextPosition(potential_match.EndPosition(),
-                       ToPositionInFlatTree(match_range_->EndPosition()))));
+  search_range_->SetStart(NextTextPosition(potential_match_->EndPosition(),
+                                           match_range_->EndPosition()));
   FindMatchInRange(selector_.Suffix(), search_range_,
                    /*word_start_bounded=*/false, /*word_end_bounded=*/true);
 }
@@ -317,12 +320,10 @@
     OnMatchComplete();
     return;
   }
-  EphemeralRangeInFlatTree potential_match(potential_match_);
-  EphemeralRangeInFlatTree suffix_range(
-      NextTextPosition(potential_match.EndPosition(),
-                       ToPositionInFlatTree(match_range_->EndPosition())),
-      ToPositionInFlatTree(match_range_->EndPosition()));
-  if (suffix_match.StartPosition() == suffix_range.StartPosition()) {
+
+  PositionInFlatTree next_position_after_match = NextTextPosition(
+      potential_match_->EndPosition(), match_range_->EndPosition());
+  if (suffix_match.StartPosition() == next_position_after_match) {
     OnMatchComplete();
     return;
   }
@@ -339,7 +340,8 @@
   // If this is a range match(e.g. |end_text| is specified), it is possible
   // that we found the correct range start, but not the correct range end.
   // Continue searching for it, without restarting the range start search.
-  range_end_search_start_ = potential_match.EndPosition();
+  range_end_search_start_->SetPosition(
+      ToPositionInDOMTree(potential_match_->EndPosition()));
   GoToStep(kMatchTextEnd);
 }
 
@@ -412,12 +414,10 @@
   } else {
     search_end = PositionInFlatTree::LastPositionInNode(*document_);
   }
-  search_range_ = Range::Create(*document_);
-  search_range_->setStart(ToPositionInDOMTree(search_start));
-  search_range_->setEnd(ToPositionInDOMTree(search_end));
-  match_range_ = Range::Create(*document_);
-  match_range_->setStart(ToPositionInDOMTree(search_start));
-  match_range_->setEnd(ToPositionInDOMTree(search_end));
+  search_range_ =
+      MakeGarbageCollected<RangeInFlatTree>(search_start, search_end);
+  match_range_ =
+      MakeGarbageCollected<RangeInFlatTree>(search_start, search_end);
   potential_match_.Clear();
   prefix_match_.Clear();
   GoToStep(kMatchPrefix);
@@ -431,11 +431,10 @@
     // TODO(crbug.com/919204): This is temporary and only for measuring
     // ambiguous matching during prototyping.
     first_match_ = potential_match_;
-    EphemeralRangeInFlatTree match(first_match_);
-    FindMatchFromPosition(match.EndPosition());
+    FindMatchFromPosition(first_match_->EndPosition());
   } else {
     TextFragmentAnchorMetrics::Match match_metrics(selector_);
-    EphemeralRangeInFlatTree potential_match(first_match_);
+    EphemeralRangeInFlatTree potential_match = first_match_->ToEphemeralRange();
     if (selector_.Type() == TextFragmentSelector::SelectorType::kExact) {
       // If it's an exact match, we don't need to do the PlainText conversion,
       // we can just use the text from the selector.
@@ -470,14 +469,34 @@
 }
 
 void TextFragmentFinder::SetPotentialMatch(EphemeralRangeInFlatTree range) {
-  potential_match_ = MakeGarbageCollected<Range>(
-      range.GetDocument(), ToPositionInDOMTree(range.StartPosition()),
-      ToPositionInDOMTree(range.EndPosition()));
+  if (potential_match_) {
+    potential_match_->SetStart(range.StartPosition());
+    potential_match_->SetEnd(range.EndPosition());
+  } else {
+    potential_match_ = MakeGarbageCollected<RangeInFlatTree>(
+        range.StartPosition(), range.EndPosition());
+  }
 }
 
 void TextFragmentFinder::SetPrefixMatch(EphemeralRangeInFlatTree range) {
-  prefix_match_ = MakeGarbageCollected<Range>(
-      range.GetDocument(), ToPositionInDOMTree(range.StartPosition()),
-      ToPositionInDOMTree(range.EndPosition()));
+  if (prefix_match_) {
+    prefix_match_->SetStart(range.StartPosition());
+    prefix_match_->SetEnd(range.EndPosition());
+  } else {
+    prefix_match_ = MakeGarbageCollected<RangeInFlatTree>(range.StartPosition(),
+                                                          range.EndPosition());
+  }
 }
+
+bool TextFragmentFinder::HasValidRanges() {
+  return !((prefix_match_ &&
+            (prefix_match_->IsNull() || !prefix_match_->IsConnected())) ||
+           (potential_match_ &&
+            (potential_match_->IsNull() || !potential_match_->IsConnected())) ||
+           (search_range_ &&
+            (search_range_->IsNull() || !search_range_->IsConnected())) ||
+           (match_range_ &&
+            (match_range_->IsNull() || !match_range_->IsConnected())));
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.h b/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.h
index 9f4a2edc..c02f8a0 100644
--- a/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.h
+++ b/third_party/blink/renderer/core/page/scrolling/text_fragment_finder.h
@@ -12,6 +12,7 @@
 #include "third_party/blink/renderer/core/editing/forward.h"
 #include "third_party/blink/renderer/core/editing/position.h"
 #include "third_party/blink/renderer/core/editing/position_iterator.h"
+#include "third_party/blink/renderer/core/editing/relocatable_position.h"
 #include "third_party/blink/renderer/core/page/scrolling/text_fragment_anchor_metrics.h"
 #include "third_party/blink/renderer/core/page/scrolling/text_fragment_selector.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -22,8 +23,8 @@
 
 // This is a helper class to TextFragmentAnchor. It's responsible for actually
 // performing the text search for the anchor and returning the results to the
-// anchor.
-class CORE_EXPORT TextFragmentFinder final
+// anchor. Has derived class |MockTextFragmentFinder|.
+class CORE_EXPORT TextFragmentFinder
     : public GarbageCollected<TextFragmentFinder> {
  public:
   class Client {
@@ -47,7 +48,7 @@
                      const TextFragmentSelector& selector,
                      Document* document,
                      FindBufferRunnerType runner_type);
-  ~TextFragmentFinder() = default;
+  virtual ~TextFragmentFinder() = default;
 
   // Begins searching in the given top-level document.
   void FindMatch();
@@ -56,7 +57,14 @@
 
   void Trace(Visitor*) const;
 
- private:
+ protected:
+  friend class TextFragmentFinderTest;
+  FRIEND_TEST_ALL_PREFIXES(TextFragmentFinderTest, DOMMutation);
+  void FindPrefix();
+  void FindTextStart();
+  void FindTextEnd();
+  void FindSuffix();
+
   // Used for tracking what should be the next match stage.
   enum SelectorMatchStep {
     kMatchPrefix,
@@ -65,61 +73,63 @@
     kMatchSuffix
   };
 
+  SelectorMatchStep step_ = kMatchPrefix;
+
+ private:
   void FindMatchFromPosition(PositionInFlatTree search_start);
 
   void OnFindMatchInRangeComplete(String search_text,
-                                  Range* range,
+                                  RangeInFlatTree* range,
                                   bool word_start_bounded,
                                   bool word_end_bounded,
                                   const EphemeralRangeInFlatTree& match);
 
   void FindMatchInRange(String search_text,
-                        Range* range,
+                        RangeInFlatTree* range,
                         bool word_start_bounded,
                         bool word_end_bounded);
 
-  void FindPrefix();
-  void FindTextStart();
-  void FindTextEnd();
-  void FindSuffix();
-
   void OnPrefixMatchComplete(EphemeralRangeInFlatTree match);
   void OnTextStartMatchComplete(EphemeralRangeInFlatTree match);
   void OnTextEndMatchComplete(EphemeralRangeInFlatTree match);
   void OnSuffixMatchComplete(EphemeralRangeInFlatTree match);
 
-  void GoToStep(SelectorMatchStep step);
+  virtual void GoToStep(SelectorMatchStep step);
 
   void OnMatchComplete();
 
   void SetPotentialMatch(EphemeralRangeInFlatTree range);
   void SetPrefixMatch(EphemeralRangeInFlatTree range);
 
+  bool HasValidRanges();
+
   Client& client_;
   const TextFragmentSelector selector_;
   Member<Document> document_;
-  SelectorMatchStep step_ = kMatchPrefix;
 
   // Start positions for the next text end |FindTask|, this is separate as the
   // search for end might move the position, which should be discarded.
-  PositionInFlatTree range_end_search_start_;
+  Member<RelocatablePosition> range_end_search_start_;
+
+  // For all the following ranges use |RangeInFlatTree| relocatable range to be
+  // safe for DOM mutations during the Find tasks.
 
   // Successful match after |FindMatchFromPosition| first run.
-  Member<Range> first_match_;
+  Member<RangeInFlatTree> first_match_;
   // Current match after |FindMatchFromPosition| run. See
   // https://wicg.github.io/scroll-to-text-fragment/#ref-for-range-collapsed:~:text=Let-,potentialMatch
-  Member<Range> potential_match_;
+  Member<RangeInFlatTree> potential_match_;
   // Used for text start match, the presence will change how the text start is
   // matched. See
   // https://wicg.github.io/scroll-to-text-fragment/#ref-for-range-collapsed:~:text=Let-,prefixMatch
-  Member<Range> prefix_match_;
+  Member<RangeInFlatTree> prefix_match_;
   // Range for the current match task, including |prefix_match_|,
   // |potential_match_| and |suffix_match|. See
   // https://wicg.github.io/scroll-to-text-fragment/#ref-for-range-collapsed:~:text=Let-,searchRange
-  Member<Range> search_range_;
-  // Range used for search for |potential_match_|.
+  Member<RangeInFlatTree> search_range_;
+  // Start and end positions used for search for |potential_match_|.
   // https://wicg.github.io/scroll-to-text-fragment/#ref-for-range-collapsed:~:text=Let-,matchRange
-  Member<Range> match_range_;
+  Member<RangeInFlatTree> match_range_;
   // Used for running FindBuffer tasks.
   Member<FindBufferRunner> find_buffer_runner_;
 };
diff --git a/third_party/blink/renderer/core/page/scrolling/text_fragment_finder_test.cc b/third_party/blink/renderer/core/page/scrolling/text_fragment_finder_test.cc
new file mode 100644
index 0000000..7694fa4
--- /dev/null
+++ b/third_party/blink/renderer/core/page/scrolling/text_fragment_finder_test.cc
@@ -0,0 +1,76 @@
+// 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/page/scrolling/text_fragment_finder.h"
+
+#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
+#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
+
+namespace blink {
+
+class MockTextFragmentFinder : public TextFragmentFinder {
+ public:
+  MockTextFragmentFinder(Client& client,
+                         const TextFragmentSelector& selector,
+                         Document* document,
+                         FindBufferRunnerType runner_type)
+      : TextFragmentFinder(client, selector, document, runner_type) {}
+
+ private:
+  void GoToStep(SelectorMatchStep step) override { step_ = step; }
+};
+
+class TextFragmentFinderTest : public SimTest,
+                               public TextFragmentFinder::Client {
+ public:
+  void SetUp() override {
+    SimTest::SetUp();
+    WebView().MainFrameViewWidget()->Resize(gfx::Size(800, 600));
+  }
+
+  void NoMatchFound() override { no_match_called_ = true; }
+
+  void DidFindMatch(const EphemeralRangeInFlatTree& match,
+                    const TextFragmentAnchorMetrics::Match match_metrics,
+                    bool is_unique) override {}
+  bool IsNoMatchFoundCalled() { return no_match_called_; }
+
+ private:
+  bool no_match_called_ = false;
+};
+
+// Tests that Find tasks will fail gracefully when DOM mutations invalidate the
+// Find task properties.
+TEST_F(TextFragmentFinderTest, DOMMutation) {
+  SimRequest request("https://example.com/test.html", "text/html");
+  LoadURL("https://example.com/test.html");
+  request.Complete(R"HTML(
+    <!DOCTYPE html>
+    <input id="input" type='submit' value="button text">
+    <p id='first'>First paragraph prefix to unique snippet of text.</p>
+  )HTML");
+
+  TextFragmentSelector selector(TextFragmentSelector::SelectorType::kExact,
+                                "First paragraph", "", "button text",
+                                "prefix to unique");
+
+  MockTextFragmentFinder* finder = MakeGarbageCollected<MockTextFragmentFinder>(
+      *this, selector, &GetDocument(),
+      TextFragmentFinder::FindBufferRunnerType::kSynchronous);
+  finder->FindMatch();
+
+  finder->FindPrefix();
+  EXPECT_EQ(false, IsNoMatchFoundCalled());
+
+  finder->FindTextStart();
+  EXPECT_EQ(false, IsNoMatchFoundCalled());
+
+  Node* input = GetDocument().getElementById("input");
+  input->remove();
+  GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kTest);
+
+  finder->FindSuffix();
+  EXPECT_EQ(true, IsNoMatchFoundCalled());
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc
index 413672c..30073f4 100644
--- a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc
+++ b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator.cc
@@ -391,7 +391,7 @@
     const TextFragmentAnchorMetrics::Match match_metrics,
     bool is_unique) {
   if (is_unique && PlainText(match).StripWhiteSpace().length() ==
-                       PlainText(EphemeralRange(selection_range_))
+                       PlainText(EphemeralRangeInFlatTree(selection_range_))
                            .StripWhiteSpace()
                            .length()) {
     state_ = kSuccess;
diff --git a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc
index dca2f4e..8ec97703 100644
--- a/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc
+++ b/third_party/blink/renderer/core/page/scrolling/text_fragment_selector_generator_test.cc
@@ -1186,6 +1186,46 @@
   VerifySelector(start, end, "First%20paragraph,Second");
 }
 
+// Checks selection across a shadow tree. Input that has text value will create
+// a shadow tree,
+TEST_P(TextFragmentSelectorGeneratorTest, InputSubmit) {
+  SimRequest request("https://example.com/test.html", "text/html");
+  LoadURL("https://example.com/test.html");
+  request.Complete(R"HTML(
+    <!DOCTYPE html>
+  <div id='div'>
+    First paragraph<input type='submit' value="button text"> Second paragraph
+  </div>
+  )HTML");
+  GetDocument().UpdateStyleAndLayoutTree();
+  Node* div = GetDocument().getElementById("div");
+  const auto& start = Position(div->firstChild(), 0);
+  const auto& end = Position(div->lastChild(), 7);
+  ASSERT_EQ("First paragraph Second", PlainText(EphemeralRange(start, end)));
+
+  VerifySelector(start, end, "First%20paragraph,Second");
+}
+
+// Checks selection right after a shadow tree will use the shadow tree for
+// prefix. Input with text value will create a shadow tree.
+TEST_P(TextFragmentSelectorGeneratorTest, InputSubmitPrefix) {
+  SimRequest request("https://example.com/test.html", "text/html");
+  LoadURL("https://example.com/test.html");
+  request.Complete(R"HTML(
+    <!DOCTYPE html>
+  <div id='div'>
+    <input type='submit' value="button text"> paragraph text
+  </div>
+  )HTML");
+  GetDocument().UpdateStyleAndLayoutTree();
+  Node* div = GetDocument().getElementById("div");
+  const auto& start = Position(div->lastChild(), 0);
+  const auto& end = Position(div->lastChild(), 10);
+  ASSERT_EQ(" paragraph", PlainText(EphemeralRange(start, end)));
+
+  VerifySelector(start, end, "button%20text-,paragraph,-text");
+}
+
 // Basic test case for |GetNextTextBlock|.
 TEST_P(TextFragmentSelectorGeneratorTest, GetPreviousTextBlock) {
   SimRequest request("https://example.com/test.html", "text/html");
diff --git a/third_party/blink/renderer/modules/webdatabase/database.cc b/third_party/blink/renderer/modules/webdatabase/database.cc
index 0949be54..30b4a903 100644
--- a/third_party/blink/renderer/modules/webdatabase/database.cc
+++ b/third_party/blink/renderer/modules/webdatabase/database.cc
@@ -223,13 +223,11 @@
 Database::Database(DatabaseContext* database_context,
                    const String& name,
                    const String& expected_version,
-                   const String& display_name,
-                   uint32_t estimated_size)
+                   const String& display_name)
     : database_context_(database_context),
       name_(name.IsolatedCopy()),
       expected_version_(expected_version.IsolatedCopy()),
       display_name_(display_name.IsolatedCopy()),
-      estimated_size_(estimated_size),
       guid_(0),
       opened_(false),
       new_(false),
@@ -623,10 +621,6 @@
   return display_name_.IsolatedCopy();
 }
 
-uint32_t Database::EstimatedSize() const {
-  return estimated_size_;
-}
-
 String Database::FileName() const {
   // Return a deep copy for ref counting thread safety
   return filename_.IsolatedCopy();
diff --git a/third_party/blink/renderer/modules/webdatabase/database.h b/third_party/blink/renderer/modules/webdatabase/database.h
index 99fc289..dcd5316 100644
--- a/third_party/blink/renderer/modules/webdatabase/database.h
+++ b/third_party/blink/renderer/modules/webdatabase/database.h
@@ -57,8 +57,7 @@
   Database(DatabaseContext*,
            const String& name,
            const String& expected_version,
-           const String& display_name,
-           uint32_t estimated_size);
+           const String& display_name);
   ~Database() override;
   void Trace(Visitor*) const override;
 
@@ -101,7 +100,6 @@
   const SecurityOrigin* GetSecurityOrigin() const;
   String StringIdentifier() const;
   String DisplayName() const;
-  uint32_t EstimatedSize() const;
   String FileName() const;
   SQLiteDatabase& SqliteDatabase() { return sqlite_database_; }
 
@@ -178,7 +176,6 @@
   String name_;
   String expected_version_;
   String display_name_;
-  uint32_t estimated_size_;
   String filename_;
 
   DatabaseGuid guid_;
diff --git a/third_party/blink/renderer/modules/webdatabase/database_manager.cc b/third_party/blink/renderer/modules/webdatabase/database_manager.cc
index af523812..9193c0e 100644
--- a/third_party/blink/renderer/modules/webdatabase/database_manager.cc
+++ b/third_party/blink/renderer/modules/webdatabase/database_manager.cc
@@ -135,7 +135,6 @@
     const String& name,
     const String& expected_version,
     const String& display_name,
-    uint32_t estimated_size,
     V8DatabaseCallback* creation_callback,
     bool set_version_in_new_database,
     DatabaseError& error,
@@ -145,7 +144,7 @@
   DatabaseContext* backend_context = DatabaseContextFor(context)->Backend();
   if (DatabaseTracker::Tracker().CanEstablishDatabase(backend_context, error)) {
     Database* backend = MakeGarbageCollected<Database>(
-        backend_context, name, expected_version, display_name, estimated_size);
+        backend_context, name, expected_version, display_name);
     if (backend->OpenAndVerifyVersion(set_version_in_new_database, error,
                                       error_message, creation_callback))
       return backend;
@@ -171,7 +170,6 @@
                                         const String& name,
                                         const String& expected_version,
                                         const String& display_name,
-                                        uint32_t estimated_size,
                                         V8DatabaseCallback* creation_callback,
                                         DatabaseError& error,
                                         String& error_message) {
@@ -179,8 +177,8 @@
 
   bool set_version_in_new_database = !creation_callback;
   Database* database = OpenDatabaseInternal(
-      context, name, expected_version, display_name, estimated_size,
-      creation_callback, set_version_in_new_database, error, error_message);
+      context, name, expected_version, display_name, creation_callback,
+      set_version_in_new_database, error, error_message);
   if (!database)
     return nullptr;
 
diff --git a/third_party/blink/renderer/modules/webdatabase/database_manager.h b/third_party/blink/renderer/modules/webdatabase/database_manager.h
index 50a7cc7..7fa00456 100644
--- a/third_party/blink/renderer/modules/webdatabase/database_manager.h
+++ b/third_party/blink/renderer/modules/webdatabase/database_manager.h
@@ -70,7 +70,6 @@
                          const String& name,
                          const String& expected_version,
                          const String& display_name,
-                         uint32_t estimated_size,
                          V8DatabaseCallback*,
                          DatabaseError&,
                          String& error_message);
@@ -94,7 +93,6 @@
                                  const String& name,
                                  const String& expected_version,
                                  const String& display_name,
-                                 uint32_t estimated_size,
                                  V8DatabaseCallback*,
                                  bool set_version_in_new_database,
                                  DatabaseError&,
diff --git a/third_party/blink/renderer/modules/webdatabase/database_tracker.cc b/third_party/blink/renderer/modules/webdatabase/database_tracker.cc
index 2c3459b1..8f2f86720 100644
--- a/third_party/blink/renderer/modules/webdatabase/database_tracker.cc
+++ b/third_party/blink/renderer/modules/webdatabase/database_tracker.cc
@@ -146,9 +146,9 @@
   // where the database is in an unusable state. To assist, we will record the
   // size of the database straight away so we can use it immediately, and the
   // real size will eventually be updated by the RPC from the browser.
-  WebDatabaseHost::GetInstance().DatabaseOpened(
-      *database->GetSecurityOrigin(), database->StringIdentifier(),
-      database->DisplayName(), database->EstimatedSize());
+  WebDatabaseHost::GetInstance().DatabaseOpened(*database->GetSecurityOrigin(),
+                                                database->StringIdentifier(),
+                                                database->DisplayName());
   // We write a temporary size of 0 to the QuotaTracker - we will be updated
   // with the correct size via RPC asynchronously.
   QuotaTracker::Instance().UpdateDatabaseSize(database->GetSecurityOrigin(),
diff --git a/third_party/blink/renderer/modules/webdatabase/dom_window_web_database.cc b/third_party/blink/renderer/modules/webdatabase/dom_window_web_database.cc
index 72d474a..870c097 100644
--- a/third_party/blink/renderer/modules/webdatabase/dom_window_web_database.cc
+++ b/third_party/blink/renderer/modules/webdatabase/dom_window_web_database.cc
@@ -69,8 +69,7 @@
 
     String error_message;
     database = db_manager.OpenDatabase(&window, name, version, display_name,
-                                       estimated_size, creation_callback, error,
-                                       error_message);
+                                       creation_callback, error, error_message);
     DCHECK(database || error != DatabaseError::kNone);
     if (error != DatabaseError::kNone)
       DatabaseManager::ThrowExceptionForDatabaseError(error, error_message,
diff --git a/third_party/blink/renderer/modules/webdatabase/web_database_host.cc b/third_party/blink/renderer/modules/webdatabase/web_database_host.cc
index 3581f00..2247d79 100644
--- a/third_party/blink/renderer/modules/webdatabase/web_database_host.cc
+++ b/third_party/blink/renderer/modules/webdatabase/web_database_host.cc
@@ -78,11 +78,9 @@
 
 void WebDatabaseHost::DatabaseOpened(const SecurityOrigin& origin,
                                      const String& database_name,
-                                     const String& database_display_name,
-                                     uint32_t estimated_size) {
+                                     const String& database_display_name) {
   DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
-  GetWebDatabaseHost().Opened(&origin, database_name, database_display_name,
-                              estimated_size);
+  GetWebDatabaseHost().Opened(&origin, database_name, database_display_name);
 }
 
 void WebDatabaseHost::DatabaseModified(const SecurityOrigin& origin,
diff --git a/third_party/blink/renderer/modules/webdatabase/web_database_host.h b/third_party/blink/renderer/modules/webdatabase/web_database_host.h
index b459cd0..dad4f425 100644
--- a/third_party/blink/renderer/modules/webdatabase/web_database_host.h
+++ b/third_party/blink/renderer/modules/webdatabase/web_database_host.h
@@ -52,8 +52,7 @@
 
   void DatabaseOpened(const SecurityOrigin& origin,
                       const String& database_name,
-                      const String& database_display_name,
-                      uint32_t estimated_size);
+                      const String& database_display_name);
   void DatabaseModified(const SecurityOrigin& origin,
                         const String& database_name);
   void DatabaseClosed(const SecurityOrigin& origin,
diff --git a/third_party/blink/renderer/platform/fonts/font_description.h b/third_party/blink/renderer/platform/fonts/font_description.h
index a0b9c3a..769bdaa 100644
--- a/third_party/blink/renderer/platform/fonts/font_description.h
+++ b/third_party/blink/renderer/platform/fonts/font_description.h
@@ -504,10 +504,8 @@
     : SimpleClassHashTraits<blink::FontDescription> {
   // FontDescription default constructor creates a regular value instead of the
   // empty value.
-  static const blink::FontDescription& EmptyValue() {
-    DEFINE_STATIC_LOCAL(blink::FontDescription, empty_value,
-                        (blink::FontDescription::CreateHashTableEmptyValue()));
-    return empty_value;
+  static blink::FontDescription EmptyValue() {
+    return blink::FontDescription::CreateHashTableEmptyValue();
   }
 };
 
diff --git a/third_party/blink/renderer/platform/heap/collection_support/heap_hash_table_backing.h b/third_party/blink/renderer/platform/heap/collection_support/heap_hash_table_backing.h
index ec11bf75..73814f4 100644
--- a/third_party/blink/renderer/platform/heap/collection_support/heap_hash_table_backing.h
+++ b/third_party/blink/renderer/platform/heap/collection_support/heap_hash_table_backing.h
@@ -176,17 +176,46 @@
 
 template <typename Key, typename Value, typename Traits>
 struct TraceInCollectionTrait<kWeakHandling, KeyValuePair<Key, Value>, Traits> {
+ private:
+  template <typename T>
+  struct NullReferenceChecker {
+    static bool IsNull(const T& t) { return false; }
+  };
+  template <typename T>
+  struct NullReferenceChecker<blink::Member<T>> {
+    static bool IsNull(const blink::Member<T>& t) { return !t; }
+  };
+  template <typename T>
+  struct NullReferenceChecker<blink::WeakMember<T>> {
+    static bool IsNull(const blink::WeakMember<T>& t) { return !t; }
+  };
+
+ public:
   static bool IsAlive(const blink::LivenessBroker& info,
                       const KeyValuePair<Key, Value>& self) {
     // Needed for Weak/Weak, Strong/Weak (reverse ephemeron), and Weak/Strong
     // (ephemeron). Order of invocation does not matter as tracing weak key or
     // value does not have any side effects.
-    return blink::TraceCollectionIfEnabled<
-               WeakHandlingTrait<Key>::value, Key,
-               typename Traits::KeyTraits>::IsAlive(info, self.key) &&
-           blink::TraceCollectionIfEnabled<
-               WeakHandlingTrait<Value>::value, Value,
-               typename Traits::ValueTraits>::IsAlive(info, self.value);
+    //
+    // Blink (reverse) ephemerons are allowed to temporarily contain a null key.
+    // In case a GC happens before the key is overwritten with a non-null value,
+    // IsAlive of weak KeyValuePair needs to consider null keys as alive (null
+    // is generally treated as dead). Otherwise, weakness processing for the
+    // hash table will delete the bucket even though it is still actively in
+    // use. Since only the key of the (reverse) ephemeron can be null, pairs in
+    // which both key and value are null do not need to be kept alive and can be
+    // regarded as dead.
+    bool key_is_null = NullReferenceChecker<Key>::IsNull(self.key);
+    bool value_is_null = NullReferenceChecker<Value>::IsNull(self.value);
+    return (key_is_null ||
+            blink::TraceCollectionIfEnabled<
+                WeakHandlingTrait<Key>::value, Key,
+                typename Traits::KeyTraits>::IsAlive(info, self.key)) &&
+           (value_is_null ||
+            blink::TraceCollectionIfEnabled<
+                WeakHandlingTrait<Value>::value, Value,
+                typename Traits::ValueTraits>::IsAlive(info, self.value)) &&
+           (!key_is_null || !value_is_null);
   }
 
   static void Trace(blink::Visitor* visitor,
diff --git a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc
index 92acf76..825c015 100644
--- a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc
+++ b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.cc
@@ -49,8 +49,8 @@
   service_->SetViewportIntersection(viewport_intersection);
 }
 
-void DocumentResourceCoordinator::SetIsAdFrame() {
-  service_->SetIsAdFrame();
+void DocumentResourceCoordinator::SetIsAdFrame(bool is_ad_frame) {
+  service_->SetIsAdFrame(is_ad_frame);
 }
 
 void DocumentResourceCoordinator::OnNonPersistentNotificationCreated() {
diff --git a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h
index f7d4cfc..6c1674b 100644
--- a/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h
+++ b/third_party/blink/renderer/platform/instrumentation/resource_coordinator/document_resource_coordinator.h
@@ -35,8 +35,7 @@
   void SetLifecycleState(performance_manager::mojom::LifecycleState);
   void SetHasNonEmptyBeforeUnload(bool has_nonempty_beforeunload);
   void SetViewportIntersection(const gfx::Rect& viewport_intersection);
-  // A one way switch that marks a frame as being an adframe.
-  void SetIsAdFrame();
+  void SetIsAdFrame(bool is_ad_frame);
   void OnNonPersistentNotificationCreated();
   void SetHadFormInteraction();
   void OnFirstContentfulPaint(base::TimeDelta time_since_navigation_start);
diff --git a/third_party/blink/renderer/platform/loader/child_url_loader_factory_bundle.cc b/third_party/blink/renderer/platform/loader/child_url_loader_factory_bundle.cc
index 95f40ff8..0bcf7a4a 100644
--- a/third_party/blink/renderer/platform/loader/child_url_loader_factory_bundle.cc
+++ b/third_party/blink/renderer/platform/loader/child_url_loader_factory_bundle.cc
@@ -256,7 +256,6 @@
 
 void ChildURLLoaderFactoryBundle::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> loader,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
@@ -290,14 +289,14 @@
     // This is no-state prefetch (see
     // WebURLRequest::GetLoadFlagsForWebUrlRequest).
     prefetch_loader_factory_->CreateLoaderAndStart(
-        std::move(loader), routing_id, request_id, options, request,
-        std::move(client), traffic_annotation);
+        std::move(loader), request_id, options, request, std::move(client),
+        traffic_annotation);
     return;
   }
 
   URLLoaderFactoryBundle::CreateLoaderAndStart(
-      std::move(loader), routing_id, request_id, options, request,
-      std::move(client), traffic_annotation);
+      std::move(loader), request_id, options, request, std::move(client),
+      traffic_annotation);
 }
 
 std::unique_ptr<network::PendingSharedURLLoaderFactory>
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client_unittest.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client_unittest.cc
index caad3c8..bcdf885 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client_unittest.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/mojo_url_loader_client_unittest.cc
@@ -210,10 +210,9 @@
     context_->url_laoder_client = client_.get();
     url_loader_ = ThrottlingURLLoader::CreateLoaderAndStart(
         std::move(url_loader_factory),
-        std::vector<std::unique_ptr<blink::URLLoaderThrottle>>(),
-        /*routing_id=*/0, request_id_, /*loader_options=0*/ 0, request.get(),
-        client_.get(), TRAFFIC_ANNOTATION_FOR_TESTS,
-        std::move(loading_task_runner),
+        std::vector<std::unique_ptr<blink::URLLoaderThrottle>>(), request_id_,
+        /*loader_options=0*/ 0, request.get(), client_.get(),
+        TRAFFIC_ANNOTATION_FOR_TESTS, std::move(loading_task_runner),
         base::make_optional(std::vector<std::string>()));
 
     base::RunLoop().RunUntilIdle();
@@ -226,7 +225,6 @@
 
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& url_request,
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.cc
index 7fdb866..7913b10 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.cc
@@ -92,7 +92,6 @@
 // static
 void SyncLoadContext::StartAsyncWithWaitableEvent(
     std::unique_ptr<network::ResourceRequest> request,
-    int routing_id,
     scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner,
     const net::NetworkTrafficAnnotationTag& traffic_annotation,
     uint32_t loader_options,
@@ -113,10 +112,10 @@
       context_for_redirect, redirect_or_response_event, abort_event, timeout,
       std::move(download_to_blob_registry), loading_task_runner);
   context->resource_request_sender_->SendAsync(
-      std::move(request), routing_id, std::move(loading_task_runner),
-      traffic_annotation, loader_options, cors_exempt_header_list,
-      base::WrapRefCounted(context), context->url_loader_factory_,
-      std::move(throttles), std::move(resource_load_info_notifier_wrapper),
+      std::move(request), std::move(loading_task_runner), traffic_annotation,
+      loader_options, cors_exempt_header_list, base::WrapRefCounted(context),
+      context->url_loader_factory_, std::move(throttles),
+      std::move(resource_load_info_notifier_wrapper),
       WebBackForwardCacheLoaderHelper());
 }
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h b/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h
index 7f30c109..1d8a003 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context.h
@@ -57,7 +57,6 @@
   // |response|.
   static void StartAsyncWithWaitableEvent(
       std::unique_ptr<network::ResourceRequest> request,
-      int routing_id,
       scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner,
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
       uint32_t loader_options,
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context_unittest.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context_unittest.cc
index 836fde66..461f156 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context_unittest.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/sync_load_context_unittest.cc
@@ -29,7 +29,6 @@
   // mojom::URLLoaderFactory implementation.
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& url_request,
@@ -37,7 +36,7 @@
       const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
       override {
     network::TestURLLoaderFactory::CreateLoaderAndStart(
-        std::move(receiver), routing_id, request_id, options, url_request,
+        std::move(receiver), request_id, options, url_request,
         std::move(client), traffic_annotation);
   }
 
@@ -106,9 +105,8 @@
         FROM_HERE,
         base::BindOnce(
             &SyncLoadContext::StartAsyncWithWaitableEvent, std::move(request),
-            MSG_ROUTING_NONE, loading_thread_.task_runner(),
-            TRAFFIC_ANNOTATION_FOR_TESTS, 0 /* loader_options */,
-            std::move(pending_factory),
+            loading_thread_.task_runner(), TRAFFIC_ANNOTATION_FOR_TESTS,
+            0 /* loader_options */, std::move(pending_factory),
             WebVector<std::unique_ptr<URLLoaderThrottle>>(), out_response,
             context_for_redirect, redirect_or_response_event,
             nullptr /* terminate_sync_load_event */,
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender.cc
index 744da0d0..f99b294 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender.cc
@@ -160,7 +160,6 @@
 
 void WebResourceRequestSender::SendSync(
     std::unique_ptr<network::ResourceRequest> request,
-    int routing_id,
     const net::NetworkTrafficAnnotationTag& traffic_annotation,
     uint32_t loader_options,
     SyncLoadResponse* response,
@@ -212,7 +211,7 @@
       *task_runner, FROM_HERE,
       WTF::CrossThreadBindOnce(
           &SyncLoadContext::StartAsyncWithWaitableEvent, std::move(request),
-          routing_id, task_runner, traffic_annotation, loader_options,
+          task_runner, traffic_annotation, loader_options,
           std::move(pending_factory), std::move(throttles),
           CrossThreadUnretained(response),
           CrossThreadUnretained(&context_for_redirect),
@@ -246,7 +245,6 @@
 
 int WebResourceRequestSender::SendAsync(
     std::unique_ptr<network::ResourceRequest> request,
-    int routing_id,
     scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner,
     const net::NetworkTrafficAnnotationTag& traffic_annotation,
     uint32_t loader_options,
@@ -292,9 +290,9 @@
                  [](const WebString& h) { return h.Latin1(); });
   std::unique_ptr<ThrottlingURLLoader> url_loader =
       ThrottlingURLLoader::CreateLoaderAndStart(
-          std::move(url_loader_factory), throttles.ReleaseVector(), routing_id,
-          request_id, loader_options, request.get(), client.get(),
-          traffic_annotation, std::move(loading_task_runner),
+          std::move(url_loader_factory), throttles.ReleaseVector(), request_id,
+          loader_options, request.get(), client.get(), traffic_annotation,
+          std::move(loading_task_runner),
           base::make_optional(std_cors_exempt_header_list));
   request_info_->url_loader = std::move(url_loader);
   request_info_->url_loader_client = std::move(client);
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender_unittest.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender_unittest.cc
index 48e373a..1058d3a 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender_unittest.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/web_resource_request_sender_unittest.cc
@@ -205,7 +205,6 @@
 
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& url_request,
@@ -255,7 +254,7 @@
   void StartAsync(std::unique_ptr<network::ResourceRequest> request,
                   scoped_refptr<WebRequestPeer> peer) {
     sender()->SendAsync(
-        std::move(request), 0, scheduler::GetSingleThreadTaskRunnerForTesting(),
+        std::move(request), scheduler::GetSingleThreadTaskRunnerForTesting(),
         TRAFFIC_ANNOTATION_FOR_TESTS, false, WebVector<WebString>(),
         std::move(peer),
         base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(this),
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader.cc
index d176a5ae..15a14ed 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader.cc
@@ -587,9 +587,9 @@
     net::NetworkTrafficAnnotationTag tag =
         GetTrafficAnnotationTag(request.get());
     resource_request_sender_->SendSync(
-        std::move(request), requestor_id, tag, loader_options,
-        sync_load_response, url_loader_factory_, std::move(throttles),
-        timeout_interval, cors_exempt_header_list_, terminate_sync_load_event_,
+        std::move(request), tag, loader_options, sync_load_response,
+        url_loader_factory_, std::move(throttles), timeout_interval,
+        cors_exempt_header_list_, terminate_sync_load_event_,
         std::move(download_to_blob_registry), base::WrapRefCounted(this),
         std::move(resource_load_info_notifier_wrapper),
         back_forward_cache_loader_helper_);
@@ -600,10 +600,9 @@
                          TRACE_EVENT_FLAG_FLOW_OUT);
   net::NetworkTrafficAnnotationTag tag = GetTrafficAnnotationTag(request.get());
   request_id_ = resource_request_sender_->SendAsync(
-      std::move(request), requestor_id, unfreezable_task_runner_, tag,
-      loader_options, cors_exempt_header_list_, base::WrapRefCounted(this),
-      url_loader_factory_, std::move(throttles),
-      std::move(resource_load_info_notifier_wrapper),
+      std::move(request), unfreezable_task_runner_, tag, loader_options,
+      cors_exempt_header_list_, base::WrapRefCounted(this), url_loader_factory_,
+      std::move(throttles), std::move(resource_load_info_notifier_wrapper),
       back_forward_cache_loader_helper_);
 
   if (defers_loading_ != WebURLLoader::DeferType::kNotDeferred) {
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader_unittest.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader_unittest.cc
index 6f5e2e2..bc201b82 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader_unittest.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/web_url_loader_unittest.cc
@@ -70,7 +70,6 @@
   // WebResourceRequestSender implementation:
   void SendSync(
       std::unique_ptr<network::ResourceRequest> request,
-      int routing_id,
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
       uint32_t loader_options,
       SyncLoadResponse* response,
@@ -90,7 +89,6 @@
 
   int SendAsync(
       std::unique_ptr<network::ResourceRequest> request,
-      int routing_id,
       scoped_refptr<base::SingleThreadTaskRunner> loading_task_runner,
       const net::NetworkTrafficAnnotationTag& traffic_annotation,
       uint32_t loader_options,
@@ -145,7 +143,6 @@
   ~FakeURLLoaderFactory() override = default;
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> receiver,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& url_request,
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 87bdbd85..c9ba35b 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1705,7 +1705,7 @@
     },
     {
       name: "RemoveMobileViewportDoubleTap",
-      status: "experimental"
+      status: "stable"
     },
     {
       // See https://crbug.com/1012063
diff --git a/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc b/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
index 05ba47d..0d8f272 100644
--- a/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/dummy_schedulers.cc
@@ -48,7 +48,7 @@
   void SetShouldReportPostedTasksWhenDisabled(bool) override {}
   void SetCrossOriginToMainFrame(bool) override {}
   bool IsCrossOriginToMainFrame() const override { return false; }
-  void SetIsAdFrame() override {}
+  void SetIsAdFrame(bool is_ad_frame) override {}
   bool IsAdFrame() const override { return false; }
   void TraceUrlChange(const String&) override {}
   void AddTaskTime(base::TimeDelta) override {}
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
index 4e09e56..7efd8e8 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.cc
@@ -335,8 +335,8 @@
   UpdatePolicy();
 }
 
-void FrameSchedulerImpl::SetIsAdFrame() {
-  is_ad_frame_ = true;
+void FrameSchedulerImpl::SetIsAdFrame(bool is_ad_frame) {
+  is_ad_frame_ = is_ad_frame;
   UpdatePolicy();
 }
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
index f9d874d..b13ef70 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl.h
@@ -96,7 +96,7 @@
   void SetCrossOriginToMainFrame(bool cross_origin) override;
   bool IsCrossOriginToMainFrame() const override;
 
-  void SetIsAdFrame() override;
+  void SetIsAdFrame(bool is_ad_frame) override;
   bool IsAdFrame() const override;
 
   void TraceUrlChange(const String& url) override;
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
index 9d48ab9..9013077 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/frame_scheduler_impl_unittest.cc
@@ -1959,7 +1959,7 @@
   EXPECT_EQ(UnpausableTaskQueue()->GetTaskQueue()->GetQueuePriority(),
             TaskQueue::QueuePriority::kNormalPriority);
 
-  frame_scheduler_->SetIsAdFrame();
+  frame_scheduler_->SetIsAdFrame(true);
 
   EXPECT_TRUE(frame_scheduler_->IsAdFrame());
 
@@ -1975,6 +1975,23 @@
             TaskQueue::QueuePriority::kLowPriority);
   EXPECT_EQ(UnpausableTaskQueue()->GetTaskQueue()->GetQueuePriority(),
             TaskQueue::QueuePriority::kLowPriority);
+
+  frame_scheduler_->SetIsAdFrame(false);
+
+  EXPECT_FALSE(frame_scheduler_->IsAdFrame());
+
+  EXPECT_EQ(LoadingTaskQueue()->GetTaskQueue()->GetQueuePriority(),
+            TaskQueue::QueuePriority::kNormalPriority);
+  EXPECT_EQ(LoadingControlTaskQueue()->GetTaskQueue()->GetQueuePriority(),
+            TaskQueue::QueuePriority::kHighPriority);
+  EXPECT_EQ(DeferrableTaskQueue()->GetTaskQueue()->GetQueuePriority(),
+            TaskQueue::QueuePriority::kNormalPriority);
+  EXPECT_EQ(ThrottleableTaskQueue()->GetTaskQueue()->GetQueuePriority(),
+            TaskQueue::QueuePriority::kNormalPriority);
+  EXPECT_EQ(PausableTaskQueue()->GetTaskQueue()->GetQueuePriority(),
+            TaskQueue::QueuePriority::kNormalPriority);
+  EXPECT_EQ(UnpausableTaskQueue()->GetTaskQueue()->GetQueuePriority(),
+            TaskQueue::QueuePriority::kNormalPriority);
 }
 
 class LowPriorityAdFrameDuringLoadingExperimentTest
@@ -1987,7 +2004,7 @@
 };
 
 TEST_F(LowPriorityAdFrameDuringLoadingExperimentTest, FrameQueuesPriorities) {
-  frame_scheduler_->SetIsAdFrame();
+  frame_scheduler_->SetIsAdFrame(true);
 
   EXPECT_TRUE(frame_scheduler_->IsAdFrame());
 
@@ -2055,7 +2072,7 @@
   EXPECT_EQ(UnpausableTaskQueue()->GetTaskQueue()->GetQueuePriority(),
             TaskQueue::QueuePriority::kNormalPriority);
 
-  frame_scheduler_->SetIsAdFrame();
+  frame_scheduler_->SetIsAdFrame(true);
 
   EXPECT_TRUE(frame_scheduler_->IsAdFrame());
 
@@ -2071,6 +2088,22 @@
             TaskQueue::QueuePriority::kBestEffortPriority);
   EXPECT_EQ(UnpausableTaskQueue()->GetTaskQueue()->GetQueuePriority(),
             TaskQueue::QueuePriority::kBestEffortPriority);
+
+  frame_scheduler_->SetIsAdFrame(false);
+  EXPECT_FALSE(frame_scheduler_->IsAdFrame());
+
+  EXPECT_EQ(LoadingTaskQueue()->GetTaskQueue()->GetQueuePriority(),
+            TaskQueue::QueuePriority::kNormalPriority);
+  EXPECT_EQ(LoadingControlTaskQueue()->GetTaskQueue()->GetQueuePriority(),
+            TaskQueue::QueuePriority::kHighPriority);
+  EXPECT_EQ(DeferrableTaskQueue()->GetTaskQueue()->GetQueuePriority(),
+            TaskQueue::QueuePriority::kNormalPriority);
+  EXPECT_EQ(ThrottleableTaskQueue()->GetTaskQueue()->GetQueuePriority(),
+            TaskQueue::QueuePriority::kNormalPriority);
+  EXPECT_EQ(PausableTaskQueue()->GetTaskQueue()->GetQueuePriority(),
+            TaskQueue::QueuePriority::kNormalPriority);
+  EXPECT_EQ(UnpausableTaskQueue()->GetTaskQueue()->GetQueuePriority(),
+            TaskQueue::QueuePriority::kNormalPriority);
 }
 
 class BestEffortPriorityAdFrameDuringLoadingExperimentTest
@@ -2084,7 +2117,7 @@
 
 TEST_F(BestEffortPriorityAdFrameDuringLoadingExperimentTest,
        FrameQueuesPriorities) {
-  frame_scheduler_->SetIsAdFrame();
+  frame_scheduler_->SetIsAdFrame(true);
 
   EXPECT_TRUE(frame_scheduler_->IsAdFrame());
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
index cf1ea907..91b9d5e 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -2274,8 +2274,16 @@
   // If this either isn't a history inert commit or it's a reload then we must
   // reset the task cost estimators.
   if (is_main_frame && (!is_web_history_inert_commit || is_reload)) {
-    base::AutoLock lock(any_thread_lock_);
-    ResetForNavigationLocked();
+    RAILMode old_rail_mode;
+    RAILMode new_rail_mode;
+    {
+      base::AutoLock lock(any_thread_lock_);
+      old_rail_mode = main_thread_only().current_policy.rail_mode();
+      ResetForNavigationLocked();
+      new_rail_mode = main_thread_only().current_policy.rail_mode();
+    }
+    if (old_rail_mode == new_rail_mode && isolate())
+      isolate()->UpdateLoadStartTime();
   }
 }
 
diff --git a/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h b/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h
index 068ed55..dcfe768 100644
--- a/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h
+++ b/third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h
@@ -96,7 +96,7 @@
   virtual void SetCrossOriginToMainFrame(bool) = 0;
   virtual bool IsCrossOriginToMainFrame() const = 0;
 
-  virtual void SetIsAdFrame() = 0;
+  virtual void SetIsAdFrame(bool is_ad_frame) = 0;
   virtual bool IsAdFrame() const = 0;
 
   virtual void TraceUrlChange(const String&) = 0;
diff --git a/third_party/blink/renderer/platform/weborigin/scheme_registry.cc b/third_party/blink/renderer/platform/weborigin/scheme_registry.cc
index 473b9170..927914a 100644
--- a/third_party/blink/renderer/platform/weborigin/scheme_registry.cc
+++ b/third_party/blink/renderer/platform/weborigin/scheme_registry.cc
@@ -40,13 +40,13 @@
 // Function defined in third_party/blink/public/web/blink.h.
 void SetDomainRelaxationForbiddenForTest(bool forbidden,
                                          const WebString& scheme) {
-  SchemeRegistry::SetDomainRelaxationForbiddenForURLScheme(forbidden,
-                                                           String(scheme));
+  SchemeRegistry::SetDomainRelaxationForbiddenForURLSchemeForTest(
+      forbidden, String(scheme));
 }
 
 // Function defined in third_party/blink/public/web/blink.h.
 void ResetDomainRelaxationForTest() {
-  SchemeRegistry::ResetDomainRelaxation();
+  SchemeRegistry::ResetDomainRelaxationForTest();
 }
 
 namespace {
@@ -107,6 +107,7 @@
  private:
   friend const URLSchemesRegistry& GetURLSchemesRegistry();
   friend URLSchemesRegistry& GetMutableURLSchemesRegistry();
+  friend URLSchemesRegistry& GetMutableURLSchemesRegistryForTest();
 
   static URLSchemesRegistry& GetInstance() {
     DEFINE_STATIC_LOCAL(URLSchemesRegistry, schemes, ());
@@ -125,6 +126,13 @@
   return URLSchemesRegistry::GetInstance();
 }
 
+URLSchemesRegistry& GetMutableURLSchemesRegistryForTest() {
+  // Bypasses thread check. This is used when TestRunner tries to mutate
+  // schemes_forbidden_from_domain_relaxation during a test or on resetting
+  // its internal states.
+  return URLSchemesRegistry::GetInstance();
+}
+
 }  // namespace
 
 void SchemeRegistry::RegisterURLSchemeAsDisplayIsolated(const String& scheme) {
@@ -153,7 +161,7 @@
   return GetURLSchemesRegistry().empty_document_schemes.Contains(scheme);
 }
 
-void SchemeRegistry::SetDomainRelaxationForbiddenForURLScheme(
+void SchemeRegistry::SetDomainRelaxationForbiddenForURLSchemeForTest(
     bool forbidden,
     const String& scheme) {
   DCHECK_EQ(scheme, scheme.LowerASCII());
@@ -161,16 +169,16 @@
     return;
 
   if (forbidden) {
-    GetMutableURLSchemesRegistry()
+    GetMutableURLSchemesRegistryForTest()
         .schemes_forbidden_from_domain_relaxation.insert(scheme);
   } else {
-    GetMutableURLSchemesRegistry()
+    GetMutableURLSchemesRegistryForTest()
         .schemes_forbidden_from_domain_relaxation.erase(scheme);
   }
 }
 
-void SchemeRegistry::ResetDomainRelaxation() {
-  GetMutableURLSchemesRegistry()
+void SchemeRegistry::ResetDomainRelaxationForTest() {
+  GetMutableURLSchemesRegistryForTest()
       .schemes_forbidden_from_domain_relaxation.clear();
 }
 
diff --git a/third_party/blink/renderer/platform/weborigin/scheme_registry.h b/third_party/blink/renderer/platform/weborigin/scheme_registry.h
index 279f0b0..01f2d02 100644
--- a/third_party/blink/renderer/platform/weborigin/scheme_registry.h
+++ b/third_party/blink/renderer/platform/weborigin/scheme_registry.h
@@ -58,9 +58,9 @@
 
   static bool ShouldLoadURLSchemeAsEmptyDocument(const String&);
 
-  static void SetDomainRelaxationForbiddenForURLScheme(bool forbidden,
-                                                       const String&);
-  static void ResetDomainRelaxation();
+  static void SetDomainRelaxationForbiddenForURLSchemeForTest(bool forbidden,
+                                                              const String&);
+  static void ResetDomainRelaxationForTest();
   static bool IsDomainRelaxationForbiddenForURLScheme(const String&);
 
   // Such schemes should delegate to SecurityOrigin::canRequest for any URL
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests
index 747980556..0d11bc4 100644
--- a/third_party/blink/web_tests/SlowTests
+++ b/third_party/blink/web_tests/SlowTests
@@ -689,7 +689,6 @@
 crbug.com/1046784 http/tests/devtools/editor/text-editor-code-folding.js [ Slow ]
 crbug.com/1046784 http/tests/devtools/coverage/coverage-suspended.js [ Slow ]
 crbug.com/1046784 http/tests/devtools/network/network-search.js [ Slow ]
-crbug.com/1046784 http/tests/devtools/components/linkifier.js [ Slow ]
 crbug.com/1046784 http/tests/devtools/elements/styles-4/styles-update-links-1.js [ Slow ]
 crbug.com/1046784 http/tests/devtools/editor/text-editor-block-indent.js [ Slow ]
 crbug.com/1046784 http/tests/devtools/elements/edit/set-outer-html.js [ Slow ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 1547a51..47302951 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -2101,9 +2101,6 @@
 crbug.com/910421 external/wpt/is-input-pending/* [ Skip ]
 crbug.com/910421 virtual/threaded-composited-iframes/external/wpt/is-input-pending/* [ Pass ]
 
-# Need to support 'direction: rtl' for scroll snap
-crbug.com/1012173 external/wpt/css/css-scroll-snap/snap-after-initial-layout/direction-rtl.html [ Failure ]
-
 # WebVTT is off because additional padding
 crbug.com/1012242 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_completely_move_up.html [ Failure ]
 crbug.com/1012242 external/wpt/webvtt/rendering/cues-with-video/processing-model/2_cues_overlapping_partially_move_down.html [ Failure ]
@@ -5687,3 +5684,5 @@
 crbug.com/1188098 [ Linux ] http/tests/devtools/oopif/oopif-presentation-console-messages.js [ Pass Crash Timeout Failure ]
 crbug.com/1188098 [ Linux ] http/tests/devtools/network/network-worker-fetch-blocked.js [ Pass Failure ]
 crbug.com/1188098 [ Linux ] http/tests/devtools/profiler/cpu-profiler-flame-chart-overview.js [ Pass Failure ]
+crbug.com/1188098 [ Linux ] http/tests/devtools/service-workers/service-worker-pause.js [ Pass Failure ]
+crbug.com/1188098 [ Linux ] http/tests/devtools/sources/debugger-ui/script-snippet-model.js [ Pass Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-inline-block-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-inline-block-expected.txt
deleted file mode 100644
index 49f8a89..0000000
--- a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-inline-block-expected.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-This is a testharness.js-based test.
-PASS Snaps correctly for horizontal-tb writing mode with 'scroll-snap-align: end start' alignment
-PASS Snaps correctly for vertical-lr writing mode with 'scroll-snap-align: end start' alignment
-PASS Snaps correctly for vertical-rl writing mode with 'scroll-snap-align: end start' alignment
-PASS Snaps correctly for horizontal-tb writing mode with 'scroll-snap-align: start end' alignment
-PASS Snaps correctly for vertical-lr writing mode with 'scroll-snap-align: start end' alignment
-PASS Snaps correctly for vertical-rl writing mode with 'scroll-snap-align: start end' alignment
-FAIL Snaps correctly for 'direction: rtl' with 'scroll-snap-align: end start' alignment assert_equals: aligns correctly on x expected -500 but got -315
-FAIL Snaps correctly for 'direction: rtl' with 'scroll-snap-align: start end' alignment assert_equals: aligns correctly on x expected -315 but got -500
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/TrustedTypePolicyFactory-getPropertyType.tentative.html b/third_party/blink/web_tests/external/wpt/trusted-types/TrustedTypePolicyFactory-getPropertyType.tentative.html
index 861dd8b..9c65ef9 100644
--- a/third_party/blink/web_tests/external/wpt/trusted-types/TrustedTypePolicyFactory-getPropertyType.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/trusted-types/TrustedTypePolicyFactory-getPropertyType.tentative.html
@@ -86,7 +86,7 @@
     assert_equals(trustedTypes.getTypeMapping()["*"].attributes["foo"], undefined);
 ;
     // Unknown namespaces:
-    assert_equals(trustedTypes.getTypeMapping("http://foo/bar"), undefined);
+    assert_equals(trustedTypes.getTypeMapping("http://foo/bar"), null);
   }, "getTypeMapping tests adapted from WICG/trusted-types polyfill");
 
   // Test case handling for both attributes and properties.
diff --git a/third_party/blink/web_tests/http/tests/devtools/a11y-axe-core/sources/event-listener-breakpoints-a11y-test.js b/third_party/blink/web_tests/http/tests/devtools/a11y-axe-core/sources/event-listener-breakpoints-a11y-test.js
index 29dc450..3c49e1f9 100644
--- a/third_party/blink/web_tests/http/tests/devtools/a11y-axe-core/sources/event-listener-breakpoints-a11y-test.js
+++ b/third_party/blink/web_tests/http/tests/devtools/a11y-axe-core/sources/event-listener-breakpoints-a11y-test.js
@@ -5,6 +5,7 @@
 (async function () {
   await TestRunner.loadModule('axe_core_test_runner');
   await TestRunner.showPanel('sources');
+  await TestRunner.loadLegacyModule('browser_debugger');
 
   await UI.viewManager.showView('sources.eventListenerBreakpoints');
   const eventListenerWidget = self.runtime.sharedInstance(
diff --git a/third_party/blink/web_tests/http/tests/devtools/a11y-axe-core/sources/xhr-breakpoints-sidebar-a11y-test.js b/third_party/blink/web_tests/http/tests/devtools/a11y-axe-core/sources/xhr-breakpoints-sidebar-a11y-test.js
index 97d8401..1643eb3 100644
--- a/third_party/blink/web_tests/http/tests/devtools/a11y-axe-core/sources/xhr-breakpoints-sidebar-a11y-test.js
+++ b/third_party/blink/web_tests/http/tests/devtools/a11y-axe-core/sources/xhr-breakpoints-sidebar-a11y-test.js
@@ -5,6 +5,7 @@
 (async function () {
   await TestRunner.loadModule('axe_core_test_runner');
   await TestRunner.showPanel('sources');
+  await TestRunner.loadLegacyModule('browser_debugger');
 
   // this rule causes false negatives due to axe not handling the shadow DOM properly
   const noRequiredParent = {'aria-required-parent': {enabled: false}};
diff --git a/third_party/blink/web_tests/http/tests/devtools/components/linkifier-expected.txt b/third_party/blink/web_tests/http/tests/devtools/components/linkifier-expected.txt
deleted file mode 100644
index 356e66e..0000000
--- a/third_party/blink/web_tests/http/tests/devtools/components/linkifier-expected.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-Tests that Linkifier works correctly.
-
-Live locations count: 0
-
-Created linkifier
-Live locations count: 0
-
-Linkified script location A
-Live locations count: 1
-
-Linkified script location B
-Live locations count: 2
-
-Reseted linkifier
-Live locations count: 0
-
-Disposed linkifier
-Live locations count: 0
-
-
diff --git a/third_party/blink/web_tests/http/tests/devtools/components/linkifier.js b/third_party/blink/web_tests/http/tests/devtools/components/linkifier.js
deleted file mode 100644
index 64a3e05f..0000000
--- a/third_party/blink/web_tests/http/tests/devtools/components/linkifier.js
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-(async function() {
-  TestRunner.addResult(`Tests that Linkifier works correctly.\n`);
-  await TestRunner.loadModule('sources_test_runner');
-  await TestRunner.loadLegacyModule('components');
-  await TestRunner.showPanel('sources');
-  await TestRunner.evaluateInPagePromise(`function foo () {} //# sourceURL=linkifier.js`)
-  var script;
-  var sourceURL = 'linkifier.js';
-  SourcesTestRunner.startDebuggerTest(waitForScripts);
-
-  function waitForScripts() {
-    SourcesTestRunner.showScriptSource(sourceURL, debuggerTest);
-  }
-
-  function debuggerTest() {
-    var target = SDK.targetManager.mainTarget();
-    for (var scriptCandidate of TestRunner.debuggerModel.scripts()) {
-      if (scriptCandidate.sourceURL === sourceURL) {
-        script = scriptCandidate;
-        break;
-      }
-    }
-
-    dumpLiveLocationsCount();
-
-    var linkifier = new Components.Linkifier();
-    TestRunner.addResult('Created linkifier');
-    dumpLiveLocationsCount();
-
-    var linkA = linkifier.linkifyScriptLocation(target, null, sourceURL, 10);
-    TestRunner.addResult('Linkified script location A');
-    dumpLiveLocationsCount();
-
-    var linkB = linkifier.linkifyScriptLocation(target, null, sourceURL, 15);
-    TestRunner.addResult('Linkified script location B');
-    dumpLiveLocationsCount();
-
-    linkifier.reset();
-    TestRunner.addResult('Reseted linkifier');
-    dumpLiveLocationsCount();
-
-    linkifier.dispose();
-    TestRunner.addResult('Disposed linkifier');
-    dumpLiveLocationsCount();
-
-    TestRunner.completeTest();
-  }
-
-  function dumpLiveLocationsCount() {
-    var modelData = Bindings.debuggerWorkspaceBinding._debuggerModelToData.get(script.debuggerModel);
-    var locations = modelData._locations.get(script.scriptId);
-    TestRunner.addResult('Live locations count: ' + locations.size);
-    TestRunner.addResult('');
-  }
-})();
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index c68bc1e..08693954 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -44299,6 +44299,7 @@
   <int value="-1473537658" label="DeprecateLowUsageCodecs:disabled"/>
   <int value="-1473136627" label="enable-web-payments"/>
   <int value="-1472825316" label="ContextualSearchLongpressResolve:enabled"/>
+  <int value="-1471353813" label="AddToHomescreenIPH:disabled"/>
   <int value="-1471021059"
       label="OmniboxUIExperimentShowSuggestionFavicons:disabled"/>
   <int value="-1469555275"
@@ -46135,6 +46136,7 @@
   <int value="179871410" label="ui-debug-tools:disabled"/>
   <int value="180074362" label="memory-pressure-thresholds"/>
   <int value="181150000" label="CrosVmCupsProxy:enabled"/>
+  <int value="182358203" label="AddToHomescreenIPH:enabled"/>
   <int value="182788555" label="DecoupleSyncFromAndroidMasterSync:disabled"/>
   <int value="183208826" label="TabGroups:enabled"/>
   <int value="185991204" label="enable-webrtc-srtp-encrypted-headers"/>
diff --git a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
index eb5cf13..33dcbaa 100644
--- a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
+++ b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
@@ -14096,13 +14096,18 @@
   <suffix name="BrowserProcess" label=""/>
   <suffix name="GPUProcess" label=""/>
   <suffix name="PluginProcess" label=""/>
-  <suffix name="PPAPIFlashProcess" label=""/>
+  <suffix name="PPAPIFlashProcess" label="">
+    <obsolete>
+      Removed 2021-03 now that support for Flash has been removed.
+    </obsolete>
+  </suffix>
   <suffix name="PPAPIProcess" label=""/>
   <suffix name="RendererExtensionEventProcess" label=""/>
   <suffix name="RendererExtensionPersistentProcess" label=""/>
   <suffix name="RendererProcess" label=""/>
   <suffix name="WorkerProcess" label=""/>
   <affected-histogram name="PerformanceMonitor.AverageCPU"/>
+  <affected-histogram name="PerformanceMonitor.AverageCPU2"/>
   <affected-histogram name="PerformanceMonitor.AverageDisk"/>
   <affected-histogram name="PerformanceMonitor.EnergyImpact"/>
   <affected-histogram name="PerformanceMonitor.HighCPU"/>
diff --git a/tools/metrics/histograms/histograms_xml/memory/histograms.xml b/tools/metrics/histograms/histograms_xml/memory/histograms.xml
index 39f2c23..2e5e0b9 100644
--- a/tools/metrics/histograms/histograms_xml/memory/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/memory/histograms.xml
@@ -22,9 +22,7 @@
 <histograms>
 
 <histogram name="Memory.AudioService.PrivateMemoryFootprint" units="MB"
-    expires_after="never">
-<!-- expires-never: "heartbeat" metric (internal: go/uma-heartbeats) -->
-
+    expires_after="2022-03-16">
   <owner>marinaciocea@chromium.org</owner>
   <owner>maxmorin@chromium.org</owner>
   <owner>olka@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/others/histograms.xml b/tools/metrics/histograms/histograms_xml/others/histograms.xml
index 6cc46732a..5e9a5ac 100644
--- a/tools/metrics/histograms/histograms_xml/others/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/others/histograms.xml
@@ -11022,6 +11022,11 @@
 
 <histogram name="PerformanceMonitor.AverageCPU" units="PercentCPUUsage"
     expires_after="2021-10-30">
+  <obsolete>
+    Replaced in 2021-03 by PerformanceMonitor.AverageCPU2, which reports this
+    value in permyriad (1/10000) instead of percent and changes the upper bound
+    of the histogram.
+  </obsolete>
   <owner>fdoray@chromium.org</owner>
   <owner>oysteine@chromium.org</owner>
   <owner>catan-team@chromium.org</owner>
@@ -11032,6 +11037,20 @@
   </summary>
 </histogram>
 
+<histogram name="PerformanceMonitor.AverageCPU2" units="hundredth of percent"
+    expires_after="2022-01-30">
+  <owner>fdoray@chromium.org</owner>
+  <owner>sebmarchand@chromium.org</owner>
+  <owner>catan-team@chromium.org</owner>
+  <summary>
+    Average CPU utilization of a process, read out at each two-minute interval.
+    The utilization is in the 0-100% range per CPU, which is then summed up and
+    multiplied by 100. The histogram is capped at 20000 (equivalent to 2 cores
+    fully loaded). I.e. 4 cores busy at 25% each will read as 25 * 4 * 100 =
+    10000.
+  </summary>
+</histogram>
+
 <histogram name="PerformanceMonitor.AverageDisk" units="BytesPerSecond"
     expires_after="M85">
   <owner>etienneb@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 7e7a2924..cad2baac 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -1,16 +1,16 @@
 {
     "trace_processor_shell": {
         "win": {
-            "hash": "c490b300106dbf909633a65af57bb3ab0e41befb",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/d3947788a9bc7d664c6f53c915369792e0367aa8/trace_processor_shell.exe"
+            "hash": "c80b858c77b82ec7e89933de81938d53be761d22",
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/e7a3007adf25b4c59b99aef58ff41b179b3b66ef/trace_processor_shell.exe"
         },
         "mac": {
             "hash": "59667644a3ec6354704a6933d5df2dfb903fd734",
             "remote_path": "perfetto_binaries/trace_processor_shell/mac/e7a3007adf25b4c59b99aef58ff41b179b3b66ef/trace_processor_shell"
         },
         "linux": {
-            "hash": "b6f6aa77a1513823db7e1c2f4fc46c85901f313a",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/e7a3007adf25b4c59b99aef58ff41b179b3b66ef/trace_processor_shell"
+            "hash": "b053a22b4b34b7da28445e2e26d19695a6d8edbf",
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/375eac05933d48f729014597f8f34e5733d7cedb/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/perf/core/results_dashboard.py b/tools/perf/core/results_dashboard.py
index 32c6015..513b842 100755
--- a/tools/perf/core/results_dashboard.py
+++ b/tools/perf/core/results_dashboard.py
@@ -317,10 +317,6 @@
 
 
 def _MakeBuildStatusUrl(project, buildbucket, buildername, buildnumber):
-  # Temporary logging to debug crbug.com/1169299
-  logging.info('_MakeBuildStatusUrl(%s, %s, %s, %s)' %
-               (project, buildbucket, buildername, str(buildnumber)))
-
   if not (buildername and buildnumber):
     return None
   if not project:
diff --git a/tools/perf/page_sets/login_helpers/pinterest_login.py b/tools/perf/page_sets/login_helpers/pinterest_login.py
index 991c555..0aa3750b 100644
--- a/tools/perf/page_sets/login_helpers/pinterest_login.py
+++ b/tools/perf/page_sets/login_helpers/pinterest_login.py
@@ -68,4 +68,4 @@
   })()
   """
   _LoginAccount(action_runner, credential, credentials_path)
-  action_runner.WaitForJavaScriptCondition(wait_for_local_storage, timeout=10)
+  action_runner.WaitForJavaScriptCondition(wait_for_local_storage, timeout=20)
diff --git a/tools/traffic_annotation/summary/annotations.xml b/tools/traffic_annotation/summary/annotations.xml
index e1f19e70..17d13a81 100644
--- a/tools/traffic_annotation/summary/annotations.xml
+++ b/tools/traffic_annotation/summary/annotations.xml
@@ -179,6 +179,7 @@
  <item id="media_feeds" added_in_milestone="83" hash_code="116778918" type="0" content_hash_code="48909601" os_list="linux,windows" file_path="chrome/browser/media/feeds/media_feeds_fetcher.cc"/>
  <item id="media_feeds_checker" added_in_milestone="84" hash_code="107707089" type="0" content_hash_code="125348528" os_list="linux,windows" file_path="chrome/browser/media/feeds/media_feeds_service.cc"/>
  <item id="media_router_global_media_controls_image" added_in_milestone="81" hash_code="95983790" type="0" content_hash_code="48851217" os_list="linux,windows" file_path="chrome/browser/ui/global_media_controls/cast_media_notification_item.cc"/>
+ <item id="memories_remote_model_request" added_in_milestone="90" hash_code="41799176" type="0" content_hash_code="53277182" os_list="linux,windows" file_path="components/memories/core/memories_remote_model_helper.cc"/>
  <item id="metrics_report_ukm" added_in_milestone="62" hash_code="727478" type="0" content_hash_code="8746987" os_list="linux,windows" file_path="components/metrics/net/net_metrics_log_uploader.cc"/>
  <item id="metrics_report_uma" added_in_milestone="62" hash_code="727528" type="0" content_hash_code="10176197" os_list="linux,windows" file_path="components/metrics/net/net_metrics_log_uploader.cc"/>
  <item id="mirroring_get_setup_info" added_in_milestone="68" hash_code="78447809" type="0" content_hash_code="64839410" os_list="windows,linux" file_path="components/mirroring/service/receiver_setup_querier.cc"/>
diff --git a/tools/traffic_annotation/summary/grouping.xml b/tools/traffic_annotation/summary/grouping.xml
index adad355..06e77682 100644
--- a/tools/traffic_annotation/summary/grouping.xml
+++ b/tools/traffic_annotation/summary/grouping.xml
@@ -435,5 +435,8 @@
       <traffic_annotation unique_id="cablev2_websocket_from_client"/>
       <traffic_annotation unique_id="cablev2_websocket_from_authenticator"/>
     </sender>
+    <sender name="Memories">
+      <traffic_annotation unique_id="memories_remote_model_request"/>
+    </sender>
   </group>
 </groups>
diff --git a/ui/gl/gl_image_d3d_unittest.cc b/ui/gl/gl_image_d3d_unittest.cc
index e76c559..febd42ee 100644
--- a/ui/gl/gl_image_d3d_unittest.cc
+++ b/ui/gl/gl_image_d3d_unittest.cc
@@ -25,9 +25,10 @@
 
   void WillTearDown() override { d3d11_device_ = nullptr; }
 
-  base::Optional<GLImplementation> GetPreferedGLImplementation()
+  base::Optional<GLImplementationParts> GetPreferedGLImplementation()
       const override {
-    return base::Optional<GLImplementation>(kGLImplementationEGLANGLE);
+    return base::Optional<GLImplementationParts>(
+        GLImplementationParts(ANGLEImplementation::kD3D11));
   }
 
   bool SkipTest() const override { return !d3d11_device_; }
diff --git a/ui/gl/gl_image_native_pixmap_unittest.cc b/ui/gl/gl_image_native_pixmap_unittest.cc
index c7ded389..cc1ec60 100644
--- a/ui/gl/gl_image_native_pixmap_unittest.cc
+++ b/ui/gl/gl_image_native_pixmap_unittest.cc
@@ -32,12 +32,14 @@
 template <gfx::BufferFormat format>
 class GLImageNativePixmapTestDelegate : public GLImageTestDelegateBase {
  public:
-  base::Optional<GLImplementation> GetPreferedGLImplementation()
+  base::Optional<GLImplementationParts> GetPreferedGLImplementation()
       const override {
 #if defined(OS_WIN)
-    return base::Optional<GLImplementation>(kGLImplementationEGLANGLE);
+    return base::Optional<GLImplementationParts>(GLImplementationParts(
+        kGLImplementationEGLANGLE, ANGLEImplementation::kNone));
 #else
-    return base::Optional<GLImplementation>(kGLImplementationEGLGLES2);
+    return base::Optional<GLImplementationParts>(
+        GLImplementationParts(kGLImplementationEGLGLES2));
 #endif
   }
 
diff --git a/ui/gl/gl_implementation.cc b/ui/gl/gl_implementation.cc
index 763c1cc1..f794479 100644
--- a/ui/gl/gl_implementation.cc
+++ b/ui/gl/gl_implementation.cc
@@ -25,27 +25,83 @@
 
 namespace gl {
 
+ANGLEImplementation MakeANGLEImplementation(
+    const GLImplementation gl_impl,
+    const ANGLEImplementation angle_impl) {
+  if (gl_impl == kGLImplementationEGLANGLE) {
+    if (angle_impl == ANGLEImplementation::kNone) {
+      return ANGLEImplementation::kDefault;
+    } else {
+      return angle_impl;
+    }
+  } else {
+    return ANGLEImplementation::kNone;
+  }
+}
+
+GLImplementationParts::GLImplementationParts(
+    const ANGLEImplementation angle_impl)
+    : gl(kGLImplementationEGLANGLE),
+      angle(MakeANGLEImplementation(kGLImplementationEGLANGLE, angle_impl)) {}
+
+GLImplementationParts::GLImplementationParts(const GLImplementation gl_impl)
+    : gl(gl_impl),
+      angle(MakeANGLEImplementation(gl_impl, ANGLEImplementation::kNone)) {}
+
+bool GLImplementationParts::IsValid() const {
+  if (angle == ANGLEImplementation::kNone) {
+    return (gl != kGLImplementationEGLANGLE);
+  } else {
+    return (gl == kGLImplementationEGLANGLE);
+  }
+}
+
 namespace {
 
 const struct {
-  const char* name;
-  GLImplementation implementation;
+  const char* gl_name;
+  const char* angle_name;
+  GLImplementationParts implementation;
 } kGLImplementationNamePairs[] = {
-    {kGLImplementationDesktopName, kGLImplementationDesktopGL},
-    {kGLImplementationSwiftShaderName, kGLImplementationSwiftShaderGL},
+    {kGLImplementationDesktopName, kANGLEImplementationNoneName,
+     GLImplementationParts(kGLImplementationDesktopGL)},
+    {kGLImplementationSwiftShaderName, kANGLEImplementationNoneName,
+     GLImplementationParts(kGLImplementationSwiftShaderGL)},
 #if defined(OS_APPLE)
-    {kGLImplementationAppleName, kGLImplementationAppleGL},
+    {kGLImplementationAppleName, kANGLEImplementationNoneName,
+     GLImplementationParts(kGLImplementationAppleGL)},
 #endif
-    {kGLImplementationEGLName, kGLImplementationEGLGLES2},
-    {kGLImplementationANGLEName, kGLImplementationEGLANGLE},
-    {kGLImplementationMockName, kGLImplementationMockGL},
-    {kGLImplementationStubName, kGLImplementationStubGL},
-    {kGLImplementationDisabledName, kGLImplementationDisabled}};
+    {kGLImplementationEGLName, kANGLEImplementationNoneName,
+     GLImplementationParts(kGLImplementationEGLGLES2)},
+    {kGLImplementationANGLEName, kANGLEImplementationNoneName,
+     GLImplementationParts(ANGLEImplementation::kDefault)},
+    {kGLImplementationANGLEName, kANGLEImplementationD3D9Name,
+     GLImplementationParts(ANGLEImplementation::kD3D9)},
+    {kGLImplementationANGLEName, kANGLEImplementationD3D11Name,
+     GLImplementationParts(ANGLEImplementation::kD3D11)},
+    {kGLImplementationANGLEName, kANGLEImplementationOpenGLName,
+     GLImplementationParts(ANGLEImplementation::kOpenGL)},
+    {kGLImplementationANGLEName, kANGLEImplementationOpenGLESName,
+     GLImplementationParts(ANGLEImplementation::kOpenGLES)},
+    {kGLImplementationANGLEName, kANGLEImplementationVulkanName,
+     GLImplementationParts(ANGLEImplementation::kVulkan)},
+    {kGLImplementationANGLEName, kANGLEImplementationMetalName,
+     GLImplementationParts(ANGLEImplementation::kMetal)},
+    {kGLImplementationANGLEName, kANGLEImplementationDefaultName,
+     GLImplementationParts(ANGLEImplementation::kDefault)},
+    {kGLImplementationANGLEName, kANGLEImplementationSwiftShaderName,
+     GLImplementationParts(ANGLEImplementation::kSwiftShader)},
+    {kGLImplementationMockName, kANGLEImplementationNoneName,
+     GLImplementationParts(kGLImplementationMockGL)},
+    {kGLImplementationStubName, kANGLEImplementationNoneName,
+     GLImplementationParts(kGLImplementationStubGL)},
+    {kGLImplementationDisabledName, kANGLEImplementationNoneName,
+     GLImplementationParts(kGLImplementationDisabled)}};
 
 typedef std::vector<base::NativeLibrary> LibraryArray;
 
-GLImplementation g_gl_implementation = kGLImplementationNone;
-ANGLEImplementation g_angle_implementation = ANGLEImplementation::kNone;
+GLImplementationParts g_gl_implementation =
+    GLImplementationParts(kGLImplementationNone);
 LibraryArray* g_libraries;
 GLGetProcAddressProc g_get_proc_address;
 
@@ -105,48 +161,71 @@
 GLXApi* g_current_glx_context;
 #endif
 
-GLImplementation GetNamedGLImplementation(const std::string& name) {
-  for (size_t i = 0; i < base::size(kGLImplementationNamePairs); ++i) {
-    if (name == kGLImplementationNamePairs[i].name)
-      return kGLImplementationNamePairs[i].implementation;
+GLImplementationParts GetNamedGLImplementation(const std::string& gl_name,
+                                               const std::string& angle_name) {
+  for (auto name_pair : kGLImplementationNamePairs) {
+    if (gl_name == name_pair.gl_name && angle_name == name_pair.angle_name)
+      return name_pair.implementation;
   }
 
-  return kGLImplementationNone;
+  return GLImplementationParts(kGLImplementationNone);
 }
 
-GLImplementation GetSoftwareGLImplementation() {
-  return kGLImplementationSwiftShaderGL;
+GLImplementationParts GetSoftwareGLImplementation() {
+  return GLImplementationParts(kGLImplementationSwiftShaderGL);
 }
 
-const char* GetGLImplementationName(GLImplementation implementation) {
-  for (size_t i = 0; i < base::size(kGLImplementationNamePairs); ++i) {
-    if (implementation == kGLImplementationNamePairs[i].implementation)
-      return kGLImplementationNamePairs[i].name;
+const char* GetGLImplementationGLName(GLImplementationParts implementation) {
+  for (auto name_pair : kGLImplementationNamePairs) {
+    if (implementation.gl == name_pair.implementation.gl &&
+        implementation.angle == name_pair.implementation.angle)
+      return name_pair.gl_name;
   }
 
   return "unknown";
 }
 
-void SetGLImplementation(GLImplementation implementation) {
-  g_gl_implementation = implementation;
+const char* GetGLImplementationANGLEName(GLImplementationParts implementation) {
+  for (auto name_pair : kGLImplementationNamePairs) {
+    if (implementation.gl == name_pair.implementation.gl &&
+        implementation.angle == name_pair.implementation.angle)
+      return name_pair.angle_name;
+  }
+
+  return "";
 }
 
-GLImplementation GetGLImplementation() {
+void SetGLImplementationParts(GLImplementationParts& implementation) {
+  DCHECK(implementation.IsValid());
+  g_gl_implementation = GLImplementationParts(implementation);
+}
+
+GLImplementationParts GetGLImplementationParts() {
   return g_gl_implementation;
 }
 
+void SetGLImplementation(GLImplementation implementation) {
+  g_gl_implementation = GLImplementationParts(implementation);
+  DCHECK(g_gl_implementation.IsValid());
+}
+
+GLImplementation GetGLImplementation() {
+  return g_gl_implementation.gl;
+}
+
 void SetANGLEImplementation(ANGLEImplementation implementation) {
-  g_angle_implementation = implementation;
+  g_gl_implementation = GLImplementationParts(implementation);
+  DCHECK(g_gl_implementation.IsValid());
 }
 
 ANGLEImplementation GetANGLEImplementation() {
-  return g_angle_implementation;
+  return g_gl_implementation.angle;
 }
 
 bool HasDesktopGLFeatures() {
-  return kGLImplementationDesktopGL == g_gl_implementation ||
-         kGLImplementationDesktopGLCoreProfile == g_gl_implementation ||
-         kGLImplementationAppleGL == g_gl_implementation;
+  return kGLImplementationDesktopGL == g_gl_implementation.gl ||
+         kGLImplementationDesktopGLCoreProfile == g_gl_implementation.gl ||
+         kGLImplementationAppleGL == g_gl_implementation.gl;
 }
 
 void AddGLNativeLibrary(base::NativeLibrary library) {
@@ -171,7 +250,7 @@
 
 NO_SANITIZE("cfi-icall")
 GLFunctionPointerType GetGLProcAddress(const char* name) {
-  DCHECK(g_gl_implementation != kGLImplementationNone);
+  DCHECK(g_gl_implementation.gl != kGLImplementationNone);
 
   if (g_libraries) {
     for (size_t i = 0; i < g_libraries->size(); ++i) {
diff --git a/ui/gl/gl_implementation.h b/ui/gl/gl_implementation.h
index c6cefe2..c0860cf1e 100644
--- a/ui/gl/gl_implementation.h
+++ b/ui/gl/gl_implementation.h
@@ -49,7 +49,22 @@
   kVulkan = 6,
   kSwiftShader = 7,
   kMetal = 8,
-  kMaxValue = kMetal,
+  kDefault = 9,
+  kMaxValue = kDefault,
+};
+
+struct GL_EXPORT GLImplementationParts {
+  explicit GLImplementationParts(const ANGLEImplementation angle_impl);
+  explicit GLImplementationParts(const GLImplementation gl_impl);
+
+  GLImplementation gl = kGLImplementationNone;
+  ANGLEImplementation angle = ANGLEImplementation::kNone;
+
+  constexpr bool operator==(const GLImplementationParts& other) const {
+    return (gl == other.gl && angle == other.angle);
+  }
+
+  bool IsValid() const;
 };
 
 struct GL_EXPORT GLWindowSystemBindingInfo {
@@ -93,6 +108,12 @@
   bool initial_enabled_;
 };
 
+// Set the current GL and ANGLE implementation.
+GL_EXPORT void SetGLImplementationParts(GLImplementationParts& implementation);
+
+// Get the current GL and ANGLE implementation.
+GL_EXPORT GLImplementationParts GetGLImplementationParts();
+
 // Set the current GL implementation.
 GL_EXPORT void SetGLImplementation(GLImplementation implementation);
 
@@ -106,17 +127,22 @@
 GL_EXPORT ANGLEImplementation GetANGLEImplementation();
 
 // Get the software GL implementation for the current platform.
-GL_EXPORT GLImplementation GetSoftwareGLImplementation();
+GL_EXPORT GLImplementationParts GetSoftwareGLImplementation();
 
 // Does the underlying GL support all features from Desktop GL 2.0 that were
 // removed from the ES 2.0 spec without requiring specific extension strings.
 GL_EXPORT bool HasDesktopGLFeatures();
 
 // Get the GL implementation with a given name.
-GL_EXPORT GLImplementation GetNamedGLImplementation(const std::string& name);
+GL_EXPORT GLImplementationParts
+GetNamedGLImplementation(const std::string& gl_name,
+                         const std::string& angle_name);
 
 // Get the name of a GL implementation.
-GL_EXPORT const char* GetGLImplementationName(GLImplementation implementation);
+GL_EXPORT const char* GetGLImplementationGLName(
+    GLImplementationParts implementation);
+GL_EXPORT const char* GetGLImplementationANGLEName(
+    GLImplementationParts implementation);
 
 // Add a native library to those searched for GL entry points.
 GL_EXPORT void AddGLNativeLibrary(base::NativeLibrary library);
diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc
index 1dc9306..cec45c1 100644
--- a/ui/gl/gl_surface_egl.cc
+++ b/ui/gl/gl_surface_egl.cc
@@ -1358,9 +1358,9 @@
     }
 
     std::ostringstream display_type_string;
-    auto gl_implementation = GetGLImplementation();
-    display_type_string << GetGLImplementationName(gl_implementation);
-    if (gl_implementation == kGLImplementationEGLANGLE) {
+    auto gl_implementation = GetGLImplementationParts();
+    display_type_string << GetGLImplementationGLName(gl_implementation);
+    if (gl_implementation.gl == kGLImplementationEGLANGLE) {
       display_type_string << ":" << DisplayTypeString(display_type);
     }
 
diff --git a/ui/gl/gl_surface_egl_unittest.cc b/ui/gl/gl_surface_egl_unittest.cc
index 9f75776..c8efb7e 100644
--- a/ui/gl/gl_surface_egl_unittest.cc
+++ b/ui/gl/gl_surface_egl_unittest.cc
@@ -33,10 +33,10 @@
   void SetUp() override {
 #if defined(OS_WIN)
     GLSurfaceTestSupport::InitializeOneOffImplementation(
-        GLImplementation::kGLImplementationEGLANGLE, true);
+        GLImplementationParts(kGLImplementationEGLANGLE), true);
 #else
     GLSurfaceTestSupport::InitializeOneOffImplementation(
-        GLImplementation::kGLImplementationEGLGLES2, true);
+        GLImplementationParts(kGLImplementationEGLGLES2), true);
 #endif
   }
 
diff --git a/ui/gl/gl_switches.cc b/ui/gl/gl_switches.cc
index c17e67fd1..9ade60c9 100644
--- a/ui/gl/gl_switches.cc
+++ b/ui/gl/gl_switches.cc
@@ -35,6 +35,7 @@
 const char kANGLEImplementationVulkanName[] = "vulkan";
 const char kANGLEImplementationSwiftShaderName[] = "swiftshader";
 const char kANGLEImplementationMetalName[] = "metal";
+const char kANGLEImplementationNoneName[] = "";
 
 // Special switches for "NULL"/stub driver implementations.
 const char kANGLEImplementationD3D11NULLName[] = "d3d11-null";
diff --git a/ui/gl/gl_switches.h b/ui/gl/gl_switches.h
index 81ae0db..184f9a44 100644
--- a/ui/gl/gl_switches.h
+++ b/ui/gl/gl_switches.h
@@ -35,6 +35,7 @@
 GL_EXPORT extern const char kANGLEImplementationVulkanName[];
 GL_EXPORT extern const char kANGLEImplementationSwiftShaderName[];
 GL_EXPORT extern const char kANGLEImplementationMetalName[];
+GL_EXPORT extern const char kANGLEImplementationNoneName[];
 
 GL_EXPORT extern const char kANGLEImplementationD3D11NULLName[];
 GL_EXPORT extern const char kANGLEImplementationOpenGLNULLName[];
diff --git a/ui/gl/init/gl_factory.cc b/ui/gl/init/gl_factory.cc
index facdc5a..bfd1e9e 100644
--- a/ui/gl/init/gl_factory.cc
+++ b/ui/gl/init/gl_factory.cc
@@ -26,23 +26,26 @@
 
 bool ShouldFallbackToSoftwareGL() {
   const base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
-  std::string requested_implementation_name =
+  std::string requested_implementation_gl_name =
       cmd->GetSwitchValueASCII(switches::kUseGL);
 
   if (cmd->HasSwitch(switches::kUseGL) &&
-      requested_implementation_name == "any") {
+      requested_implementation_gl_name == "any") {
     return true;
   } else {
     return false;
   }
 }
 
-GLImplementation GetRequestedGLImplementation(bool* fallback_to_software_gl) {
+GLImplementationParts GetRequestedGLImplementation(
+    bool* fallback_to_software_gl) {
   const base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
-  std::string requested_implementation_name =
+  std::string requested_implementation_gl_name =
       cmd->GetSwitchValueASCII(switches::kUseGL);
-  if (requested_implementation_name == kGLImplementationDisabledName) {
-    return gl::kGLImplementationDisabled;
+  std::string requested_implementation_angle_name =
+      cmd->GetSwitchValueASCII(switches::kUseANGLE);
+  if (requested_implementation_gl_name == kGLImplementationDisabledName) {
+    return GLImplementationParts(kGLImplementationDisabled);
   }
 
   std::vector<GLImplementation> allowed_impls = GetAllowedGLImplementations();
@@ -70,27 +73,28 @@
 
   if (allowed_impls.empty()) {
     LOG(ERROR) << "List of allowed GL implementations is empty.";
-    return kGLImplementationNone;
+    return GLImplementationParts(kGLImplementationNone);
   }
 
   // The default implementation is always the first one in list.
-  GLImplementation impl = allowed_impls[0];
+  GLImplementationParts impl = GLImplementationParts(allowed_impls[0]);
   *fallback_to_software_gl = false;
   if (cmd->HasSwitch(switches::kOverrideUseSoftwareGLForTests)) {
     impl = GetSoftwareGLImplementation();
   } else if (cmd->HasSwitch(switches::kUseGL)) {
-    if (requested_implementation_name == "any") {
+    if (requested_implementation_gl_name == "any") {
       *fallback_to_software_gl = true;
-    } else if ((requested_implementation_name ==
+    } else if ((requested_implementation_gl_name ==
                 kGLImplementationSwiftShaderName) ||
-               (requested_implementation_name ==
+               (requested_implementation_gl_name ==
                 kGLImplementationSwiftShaderForWebGLName)) {
-      impl = kGLImplementationSwiftShaderGL;
+      impl = GLImplementationParts(kGLImplementationSwiftShaderGL);
     } else {
-      impl = GetNamedGLImplementation(requested_implementation_name);
-      if (!base::Contains(allowed_impls, impl)) {
+      impl = GetNamedGLImplementation(requested_implementation_gl_name,
+                                      requested_implementation_angle_name);
+      if (!base::Contains(allowed_impls, impl.gl)) {
         LOG(ERROR) << "Requested GL implementation is not available.";
-        return kGLImplementationNone;
+        return GLImplementationParts(kGLImplementationNone);
       }
     }
   }
@@ -140,12 +144,12 @@
   DCHECK_EQ(kGLImplementationNone, GetGLImplementation());
 
   bool fallback_to_software_gl = false;
-  GLImplementation impl =
+  GLImplementationParts impl =
       GetRequestedGLImplementation(&fallback_to_software_gl);
-  if (impl == gl::kGLImplementationDisabled) {
+  if (impl.gl == gl::kGLImplementationDisabled) {
     gl::SetGLImplementation(gl::kGLImplementationDisabled);
     return true;
-  } else if (impl == gl::kGLImplementationNone) {
+  } else if (impl.gl == gl::kGLImplementationNone) {
     return false;
   }
 
@@ -153,7 +157,7 @@
                                                   fallback_to_software_gl);
 }
 
-bool InitializeStaticGLBindingsImplementation(GLImplementation impl,
+bool InitializeStaticGLBindingsImplementation(GLImplementationParts impl,
                                               bool fallback_to_software_gl) {
   if (impl == GetSoftwareGLImplementation())
     fallback_to_software_gl = false;
@@ -173,7 +177,7 @@
 bool InitializeGLOneOffPlatformImplementation(bool fallback_to_software_gl,
                                               bool disable_gl_drawing,
                                               bool init_extensions) {
-  if (GetGLImplementation() == GetSoftwareGLImplementation())
+  if (GetGLImplementationParts() == GetSoftwareGLImplementation())
     fallback_to_software_gl = false;
 
   bool initialized = InitializeGLOneOffPlatform();
@@ -190,7 +194,8 @@
     ShutdownGL(false);
 
   if (initialized) {
-    DVLOG(1) << "Using " << GetGLImplementationName(GetGLImplementation())
+    DVLOG(1) << "Using "
+             << GetGLImplementationGLName(GetGLImplementationParts())
              << " GL implementation.";
     if (disable_gl_drawing)
       InitializeNullDrawGLBindings();
diff --git a/ui/gl/init/gl_factory.h b/ui/gl/init/gl_factory.h
index 43028f7b..58a77d8 100644
--- a/ui/gl/init/gl_factory.h
+++ b/ui/gl/init/gl_factory.h
@@ -49,7 +49,7 @@
 // Initializes GL bindings using the provided parameters. This might be required
 // for use in tests.
 GL_INIT_EXPORT bool InitializeStaticGLBindingsImplementation(
-    GLImplementation impl,
+    GLImplementationParts impl,
     bool fallback_to_software_gl);
 
 // Initializes GL platform using the provided parameters. This might be required
diff --git a/ui/gl/init/gl_initializer.h b/ui/gl/init/gl_initializer.h
index 4fa1888..95a5a55 100644
--- a/ui/gl/init/gl_initializer.h
+++ b/ui/gl/init/gl_initializer.h
@@ -21,7 +21,7 @@
 bool InitializeGLOneOffPlatform();
 
 // Initializes a particular GL implementation.
-bool InitializeStaticGLBindings(GLImplementation implementation);
+bool InitializeStaticGLBindings(GLImplementationParts implementation);
 
 #if BUILDFLAG(USE_STATIC_ANGLE)
 bool InitializeStaticANGLEEGL();
diff --git a/ui/gl/init/gl_initializer_android.cc b/ui/gl/init/gl_initializer_android.cc
index d1c269e..175fd82 100644
--- a/ui/gl/init/gl_initializer_android.cc
+++ b/ui/gl/init/gl_initializer_android.cc
@@ -48,12 +48,12 @@
   return true;
 }
 
-bool InitializeStaticEGLInternal(GLImplementation implementation) {
+bool InitializeStaticEGLInternal(GLImplementationParts implementation) {
   bool initialized = false;
 
 #if BUILDFLAG(USE_STATIC_ANGLE)
   // Use ANGLE if it is requested and it is statically linked
-  if (implementation == kGLImplementationEGLANGLE) {
+  if (implementation.gl == kGLImplementationEGLANGLE) {
     initialized = InitializeStaticANGLEEGL();
   }
 #endif  // BUILDFLAG(USE_STATIC_ANGLE)
@@ -66,7 +66,7 @@
     return false;
   }
 
-  SetGLImplementation(implementation);
+  SetGLImplementationParts(implementation);
 
   InitializeStaticGLBindingsGL();
   InitializeStaticGLBindingsEGL();
@@ -91,19 +91,19 @@
   }
 }
 
-bool InitializeStaticGLBindings(GLImplementation implementation) {
+bool InitializeStaticGLBindings(GLImplementationParts implementation) {
   // Prevent reinitialization with a different implementation. Once the gpu
   // unit tests have initialized with kGLImplementationMock, we don't want to
   // later switch to another GL implementation.
   DCHECK_EQ(kGLImplementationNone, GetGLImplementation());
 
-  switch (implementation) {
+  switch (implementation.gl) {
     case kGLImplementationEGLGLES2:
     case kGLImplementationEGLANGLE:
       return InitializeStaticEGLInternal(implementation);
     case kGLImplementationMockGL:
     case kGLImplementationStubGL:
-      SetGLImplementation(implementation);
+      SetGLImplementationParts(implementation);
       InitializeStaticGLBindingsGL();
       return true;
     default:
diff --git a/ui/gl/init/gl_initializer_linux_x11.cc b/ui/gl/init/gl_initializer_linux_x11.cc
index d4f6b70..016046d 100644
--- a/ui/gl/init/gl_initializer_linux_x11.cc
+++ b/ui/gl/init/gl_initializer_linux_x11.cc
@@ -134,22 +134,22 @@
   return true;
 }
 
-bool InitializeStaticEGLInternal(GLImplementation implementation) {
+bool InitializeStaticEGLInternal(GLImplementationParts implementation) {
 #if BUILDFLAG(USE_STATIC_ANGLE)
-  if (implementation == kGLImplementationEGLANGLE) {
+  if (implementation.gl == kGLImplementationEGLANGLE) {
     // Use ANGLE if it is requested and it is statically linked
     if (!InitializeStaticANGLEEGL())
       return false;
-  } else if (!InitializeStaticEGLInternalFromLibrary(implementation)) {
+  } else if (!InitializeStaticEGLInternalFromLibrary(implementation.gl)) {
     return false;
   }
 #else
-  if (!InitializeStaticEGLInternalFromLibrary(implementation)) {
+  if (!InitializeStaticEGLInternalFromLibrary(implementation.gl)) {
     return false;
   }
 #endif  // !BUILDFLAG(USE_STATIC_ANGLE)
 
-  SetGLImplementation(implementation);
+  SetGLImplementationParts(implementation);
 
   InitializeStaticGLBindingsGL();
   InitializeStaticGLBindingsEGL();
@@ -184,7 +184,7 @@
   }
 }
 
-bool InitializeStaticGLBindingsX11(GLImplementation implementation) {
+bool InitializeStaticGLBindingsX11(GLImplementationParts implementation) {
   // Prevent reinitialization with a different implementation. Once the gpu
   // unit tests have initialized with kGLImplementationMock, we don't want to
   // later switch to another GL implementation.
@@ -196,7 +196,7 @@
   // one-time initialization cost is small, between 2 and 5 ms.
   base::ThreadRestrictions::ScopedAllowIO allow_io;
 
-  switch (implementation) {
+  switch (implementation.gl) {
     case kGLImplementationDesktopGL:
       return InitializeStaticGLXInternal();
     case kGLImplementationSwiftShaderGL:
@@ -205,7 +205,7 @@
       return InitializeStaticEGLInternal(implementation);
     case kGLImplementationMockGL:
     case kGLImplementationStubGL:
-      SetGLImplementation(implementation);
+      SetGLImplementation(implementation.gl);
       InitializeStaticGLBindingsGL();
       return true;
     default:
diff --git a/ui/gl/init/gl_initializer_linux_x11.h b/ui/gl/init/gl_initializer_linux_x11.h
index 07e0f86..202054b 100644
--- a/ui/gl/init/gl_initializer_linux_x11.h
+++ b/ui/gl/init/gl_initializer_linux_x11.h
@@ -26,7 +26,7 @@
 bool InitializeGLOneOffPlatformX11();
 
 // Initializes a particular GL implementation.
-bool InitializeStaticGLBindingsX11(GLImplementation implementation);
+bool InitializeStaticGLBindingsX11(GLImplementationParts implementation);
 
 // Clears GL bindings for all implementations supported by platform.
 void ShutdownGLPlatformX11();
diff --git a/ui/gl/init/gl_initializer_mac.cc b/ui/gl/init/gl_initializer_mac.cc
index f659291..98f3c5a4 100644
--- a/ui/gl/init/gl_initializer_mac.cc
+++ b/ui/gl/init/gl_initializer_mac.cc
@@ -159,22 +159,22 @@
   return true;
 }
 
-bool InitializeStaticEGLInternal(GLImplementation implementation) {
+bool InitializeStaticEGLInternal(GLImplementationParts implementation) {
 #if BUILDFLAG(USE_STATIC_ANGLE)
-  if (implementation == kGLImplementationEGLANGLE) {
+  if (implementation.gl == kGLImplementationEGLANGLE) {
     // Use ANGLE if it is requested and it is statically linked
     if (!InitializeStaticANGLEEGL())
       return false;
-  } else if (!InitializeStaticEGLInternalFromLibrary(implementation)) {
+  } else if (!InitializeStaticEGLInternalFromLibrary(implementation.gl)) {
     return false;
   }
 #else
-  if (!InitializeStaticEGLInternalFromLibrary(implementation)) {
+  if (!InitializeStaticEGLInternalFromLibrary(implementation.gl)) {
     return false;
   }
 #endif  // !BUILDFLAG(USE_STATIC_ANGLE)
 
-  SetGLImplementation(implementation);
+  SetGLImplementationParts(implementation);
   InitializeStaticGLBindingsGL();
   InitializeStaticGLBindingsEGL();
 
@@ -209,7 +209,7 @@
   }
 }
 
-bool InitializeStaticGLBindings(GLImplementation implementation) {
+bool InitializeStaticGLBindings(GLImplementationParts implementation) {
   // Prevent reinitialization with a different implementation. Once the gpu
   // unit tests have initialized with kGLImplementationMock, we don't want to
   // later switch to another GL implementation.
@@ -221,11 +221,11 @@
   // one-time initialization cost is small, between 2 and 5 ms.
   base::ThreadRestrictions::ScopedAllowIO allow_io;
 
-  switch (implementation) {
+  switch (implementation.gl) {
     case kGLImplementationDesktopGL:
     case kGLImplementationDesktopGLCoreProfile:
     case kGLImplementationAppleGL:
-      return InitializeStaticCGLInternal(implementation);
+      return InitializeStaticCGLInternal(implementation.gl);
 #if defined(USE_EGL)
     case kGLImplementationEGLGLES2:
     case kGLImplementationEGLANGLE:
@@ -234,7 +234,7 @@
 #endif  // #if defined(USE_EGL)
     case kGLImplementationMockGL:
     case kGLImplementationStubGL:
-      SetGLImplementation(implementation);
+      SetGLImplementationParts(implementation);
       InitializeStaticGLBindingsGL();
       return true;
     default:
diff --git a/ui/gl/init/gl_initializer_ozone.cc b/ui/gl/init/gl_initializer_ozone.cc
index aac4833f6..dbe04bd 100644
--- a/ui/gl/init/gl_initializer_ozone.cc
+++ b/ui/gl/init/gl_initializer_ozone.cc
@@ -47,7 +47,7 @@
   return false;
 }
 
-bool InitializeStaticGLBindings(GLImplementation implementation) {
+bool InitializeStaticGLBindings(GLImplementationParts implementation) {
 #if defined(USE_X11)
   if (!features::IsUsingOzonePlatform())
     return gl::init::InitializeStaticGLBindingsX11(implementation);
@@ -59,15 +59,15 @@
   // later switch to another GL implementation.
   DCHECK_EQ(kGLImplementationNone, GetGLImplementation());
 
-  if (HasGLOzone(implementation)) {
-    return GetGLOzone(implementation)
-        ->InitializeStaticGLBindings(implementation);
+  if (HasGLOzone(implementation.gl)) {
+    return GetGLOzone(implementation.gl)
+        ->InitializeStaticGLBindings(implementation.gl);
   }
 
-  switch (implementation) {
+  switch (implementation.gl) {
     case kGLImplementationMockGL:
     case kGLImplementationStubGL:
-      SetGLImplementation(implementation);
+      SetGLImplementation(implementation.gl);
       InitializeStaticGLBindingsGL();
       return true;
     default:
diff --git a/ui/gl/init/gl_initializer_win.cc b/ui/gl/init/gl_initializer_win.cc
index 8e3b73b..dae3a19 100644
--- a/ui/gl/init/gl_initializer_win.cc
+++ b/ui/gl/init/gl_initializer_win.cc
@@ -109,22 +109,22 @@
   return true;
 }
 
-bool InitializeStaticEGLInternal(GLImplementation implementation) {
+bool InitializeStaticEGLInternal(GLImplementationParts implementation) {
 #if BUILDFLAG(USE_STATIC_ANGLE)
-  if (implementation == kGLImplementationEGLANGLE) {
+  if (implementation.gl == kGLImplementationEGLANGLE) {
     // Use ANGLE if it is requested and it is statically linked
     if (!InitializeStaticANGLEEGL())
       return false;
-  } else if (!InitializeStaticEGLInternalFromLibrary(implementation)) {
+  } else if (!InitializeStaticEGLInternalFromLibrary(implementation.gl)) {
     return false;
   }
 #else
-  if (!InitializeStaticEGLInternalFromLibrary(implementation)) {
+  if (!InitializeStaticEGLInternalFromLibrary(implementation.gl)) {
     return false;
   }
 #endif  // !BUILDFLAG(USE_STATIC_ANGLE)
 
-  SetGLImplementation(implementation);
+  SetGLImplementationParts(implementation);
   InitializeStaticGLBindingsGL();
   InitializeStaticGLBindingsEGL();
 
@@ -153,7 +153,7 @@
   return true;
 }
 
-bool InitializeStaticGLBindings(GLImplementation implementation) {
+bool InitializeStaticGLBindings(GLImplementationParts implementation) {
   // Prevent reinitialization with a different implementation. Once the gpu
   // unit tests have initialized with kGLImplementationMock, we don't want to
   // later switch to another GL implementation.
@@ -165,13 +165,13 @@
   // one-time initialization cost is small, between 2 and 5 ms.
   base::ThreadRestrictions::ScopedAllowIO allow_io;
 
-  switch (implementation) {
+  switch (implementation.gl) {
     case kGLImplementationSwiftShaderGL:
     case kGLImplementationEGLANGLE:
       return InitializeStaticEGLInternal(implementation);
     case kGLImplementationMockGL:
     case kGLImplementationStubGL:
-      SetGLImplementation(implementation);
+      SetGLImplementationParts(implementation);
       InitializeStaticGLBindingsGL();
       return true;
     default:
diff --git a/ui/gl/test/gl_image_test_support.cc b/ui/gl/test/gl_image_test_support.cc
index 9ef9a77c5..be55c88 100644
--- a/ui/gl/test/gl_image_test_support.cc
+++ b/ui/gl/test/gl_image_test_support.cc
@@ -36,7 +36,7 @@
 
 // static
 void GLImageTestSupport::InitializeGL(
-    base::Optional<GLImplementation> prefered_impl) {
+    base::Optional<GLImplementationParts> prefered_impl) {
 #if defined(USE_OZONE)
   if (features::IsUsingOzonePlatform()) {
     ui::OzonePlatform::InitParams params;
@@ -49,8 +49,9 @@
       init::GetAllowedGLImplementations();
   DCHECK(!allowed_impls.empty());
 
-  GLImplementation impl = prefered_impl ? *prefered_impl : allowed_impls[0];
-  DCHECK(base::Contains(allowed_impls, impl));
+  GLImplementationParts impl =
+      prefered_impl ? *prefered_impl : GLImplementationParts(allowed_impls[0]);
+  DCHECK(base::Contains(allowed_impls, impl.gl));
 
   GLSurfaceTestSupport::InitializeOneOffImplementation(impl, true);
 #if defined(USE_OZONE)
diff --git a/ui/gl/test/gl_image_test_support.h b/ui/gl/test/gl_image_test_support.h
index c4c7a286..50d7006c 100644
--- a/ui/gl/test/gl_image_test_support.h
+++ b/ui/gl/test/gl_image_test_support.h
@@ -18,7 +18,7 @@
   // Initialize GL for image testing. |prefered_impl| is the GL implementation
   // to select if it is an allowed GL implementation. Otherwise it selects the
   // first allowed GL implementation.
-  static void InitializeGL(base::Optional<GLImplementation> prefered_impl);
+  static void InitializeGL(base::Optional<GLImplementationParts> prefered_impl);
 
   // Cleanup GL after being initialized for image testing.
   static void CleanupGL();
diff --git a/ui/gl/test/gl_image_test_template.cc b/ui/gl/test/gl_image_test_template.cc
index 741a7d3..84a58ab2 100644
--- a/ui/gl/test/gl_image_test_template.cc
+++ b/ui/gl/test/gl_image_test_template.cc
@@ -137,7 +137,7 @@
 
 }  // namespace internal
 
-base::Optional<GLImplementation>
+base::Optional<GLImplementationParts>
 GLImageTestDelegateBase::GetPreferedGLImplementation() const {
   return base::nullopt;
 }
diff --git a/ui/gl/test/gl_image_test_template.h b/ui/gl/test/gl_image_test_template.h
index 486d308b..07cc2d51 100644
--- a/ui/gl/test/gl_image_test_template.h
+++ b/ui/gl/test/gl_image_test_template.h
@@ -62,7 +62,8 @@
   virtual void DidSetUp() {}
   virtual void WillTearDown() {}
 
-  virtual base::Optional<GLImplementation> GetPreferedGLImplementation() const;
+  virtual base::Optional<GLImplementationParts> GetPreferedGLImplementation()
+      const;
   virtual bool SkipTest() const;
 };
 
diff --git a/ui/gl/test/gl_surface_test_support.cc b/ui/gl/test/gl_surface_test_support.cc
index ef4a3cc36..91fd2dc 100644
--- a/ui/gl/test/gl_surface_test_support.cc
+++ b/ui/gl/test/gl_surface_test_support.cc
@@ -65,7 +65,7 @@
       init::GetAllowedGLImplementations();
   DCHECK(!allowed_impls.empty());
 
-  GLImplementation impl = allowed_impls[0];
+  GLImplementationParts impl = GLImplementationParts(allowed_impls[0]);
   if (use_software_gl) {
     impl = gl::GetSoftwareGLImplementation();
 
@@ -78,7 +78,7 @@
       // SwiftShader GL
       for (auto i : allowed_impls) {
         if (i == kGLImplementationEGLANGLE) {
-          impl = kGLImplementationEGLANGLE;
+          impl = GLImplementationParts(ANGLEImplementation::kSwiftShader);
           base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
               switches::kUseANGLE, kANGLEImplementationSwiftShaderName);
           break;
@@ -113,7 +113,7 @@
 
 // static
 void GLSurfaceTestSupport::InitializeOneOffImplementation(
-    GLImplementation impl,
+    GLImplementationParts impl,
     bool fallback_to_software_gl) {
   DCHECK(!base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL))
       << "kUseGL has not effect in tests";
@@ -140,7 +140,8 @@
   }
 #endif
 
-  InitializeOneOffImplementation(kGLImplementationMockGL, false);
+  InitializeOneOffImplementation(GLImplementationParts(kGLImplementationMockGL),
+                                 false);
 }
 
 // static
@@ -153,7 +154,8 @@
   }
 #endif
 
-  InitializeOneOffImplementation(kGLImplementationStubGL, false);
+  InitializeOneOffImplementation(GLImplementationParts(kGLImplementationStubGL),
+                                 false);
 }
 
 // static
diff --git a/ui/gl/test/gl_surface_test_support.h b/ui/gl/test/gl_surface_test_support.h
index e3dabf5..89c662cf 100644
--- a/ui/gl/test/gl_surface_test_support.h
+++ b/ui/gl/test/gl_surface_test_support.h
@@ -13,7 +13,7 @@
  public:
   static void InitializeOneOff();
   static void InitializeNoExtensionsOneOff();
-  static void InitializeOneOffImplementation(GLImplementation impl,
+  static void InitializeOneOffImplementation(GLImplementationParts impl,
                                              bool fallback_to_swiftshader);
   static void InitializeOneOffWithMockBindings();
   static void InitializeOneOffWithStubBindings();
diff --git a/ui/gtk/gtk_ui.cc b/ui/gtk/gtk_ui.cc
index fe18a2a8..0d5d5b34 100644
--- a/ui/gtk/gtk_ui.cc
+++ b/ui/gtk/gtk_ui.cc
@@ -720,7 +720,7 @@
     return {};
 #endif
 
-  ui::DomKeyboardLayoutManager* layouts = new ui::DomKeyboardLayoutManager();
+  auto layouts = std::make_unique<ui::DomKeyboardLayoutManager>();
   auto map = base::flat_map<std::string, std::string>();
 
   for (unsigned int i_domcode = 0;
diff --git a/ui/views/accessibility/view_ax_platform_node_delegate_auralinux_unittest.cc b/ui/views/accessibility/view_ax_platform_node_delegate_auralinux_unittest.cc
index ea0c81b..09c03eb2 100644
--- a/ui/views/accessibility/view_ax_platform_node_delegate_auralinux_unittest.cc
+++ b/ui/views/accessibility/view_ax_platform_node_delegate_auralinux_unittest.cc
@@ -33,7 +33,7 @@
   View* content = widget.SetContentsView(std::make_unique<View>());
 
   Textfield* textfield = new Textfield;
-  textfield->SetAccessibleName(base::UTF8ToUTF16("Name"));
+  textfield->SetAccessibleName(u"Name");
   content->AddChildView(textfield);
 
   ASSERT_EQ(0, atk_object_get_n_accessible_children(
@@ -59,7 +59,7 @@
   g_signal_connect(atk_text, "text-insert", callback, &text_insert_events);
   g_signal_connect(atk_text, "text-remove", callback, &text_remove_events);
 
-  textfield->SetText(base::UTF8ToUTF16("Value"));
+  textfield->SetText(u"Value");
   ASSERT_EQ(text_remove_events.size(), 0ul);
   ASSERT_EQ(text_insert_events.size(), 1ul);
   EXPECT_EQ(text_insert_events[0].position, 0);
@@ -67,7 +67,7 @@
   EXPECT_EQ(text_insert_events[0].text, "Value");
   text_insert_events.clear();
 
-  textfield->SetText(base::UTF8ToUTF16("Value A"));
+  textfield->SetText(u"Value A");
   ASSERT_EQ(text_remove_events.size(), 0ul);
   ASSERT_EQ(text_insert_events.size(), 1ul);
   EXPECT_EQ(text_insert_events[0].position, 5);
@@ -75,7 +75,7 @@
   EXPECT_EQ(text_insert_events[0].text, " A");
   text_insert_events.clear();
 
-  textfield->SetText(base::UTF8ToUTF16("Value"));
+  textfield->SetText(u"Value");
   ASSERT_EQ(text_remove_events.size(), 1ul);
   ASSERT_EQ(text_insert_events.size(), 0ul);
   EXPECT_EQ(text_remove_events[0].position, 5);
@@ -83,7 +83,7 @@
   EXPECT_EQ(text_remove_events[0].text, " A");
   text_remove_events.clear();
 
-  textfield->SetText(base::UTF8ToUTF16("Prefix Value"));
+  textfield->SetText(u"Prefix Value");
   ASSERT_EQ(text_remove_events.size(), 0ul);
   ASSERT_EQ(text_insert_events.size(), 1ul);
   EXPECT_EQ(text_insert_events[0].position, 0);
@@ -91,7 +91,7 @@
   EXPECT_EQ(text_insert_events[0].text, "Prefix ");
   text_insert_events.clear();
 
-  textfield->SetText(base::UTF8ToUTF16("Value"));
+  textfield->SetText(u"Value");
   ASSERT_EQ(text_remove_events.size(), 1ul);
   ASSERT_EQ(text_insert_events.size(), 0ul);
   EXPECT_EQ(text_remove_events[0].position, 0);
diff --git a/ui/views/cocoa/bridged_native_widget_unittest.mm b/ui/views/cocoa/bridged_native_widget_unittest.mm
index ac89174..1715c46 100644
--- a/ui/views/cocoa/bridged_native_widget_unittest.mm
+++ b/ui/views/cocoa/bridged_native_widget_unittest.mm
@@ -1503,7 +1503,7 @@
       },
       &saw_vkey_return));
 
-  EXPECT_EQ(base::UTF8ToUTF16(""), textfield->GetText());
+  EXPECT_EQ(u"", textfield->GetText());
 
   g_fake_interpret_key_events = &handle_q_in_ime;
   [ns_view_ keyDown:q_in_ime];
@@ -1573,7 +1573,7 @@
         [view doCommandBySelector:@selector(insertNewLine:)];
       });
 
-  EXPECT_EQ(base::UTF8ToUTF16(""), textfield->GetText());
+  EXPECT_EQ(u"", textfield->GetText());
   EXPECT_EQ(0, enter_view->count());
 
   object_setClass(ns_view_, [InterpretKeyEventMockedBridgedContentView class]);
@@ -1643,7 +1643,7 @@
         [view doCommandBySelector:@selector(insertNewLine:)];
       });
 
-  EXPECT_EQ(base::UTF8ToUTF16(""), textfield->GetText());
+  EXPECT_EQ(u"", textfield->GetText());
   EXPECT_EQ(0, enter_view->count());
 
   object_setClass(ns_view_, [InterpretKeyEventMockedBridgedContentView class]);
@@ -1713,7 +1713,7 @@
   InterpretKeyEventsCallback handle_second_return_in_ime = base::BindRepeating(
       [](id view) { [view doCommandBySelector:@selector(insertNewLine:)]; });
 
-  EXPECT_EQ(base::UTF8ToUTF16(""), textfield->GetText());
+  EXPECT_EQ(u"", textfield->GetText());
   EXPECT_EQ(0, enter_view->count());
 
   object_setClass(ns_view_, [InterpretKeyEventMockedBridgedContentView class]);
@@ -1780,7 +1780,7 @@
         [view doCommandBySelector:@selector(insertNewLine:)];
       });
 
-  EXPECT_EQ(base::UTF8ToUTF16(""), textfield->GetText());
+  EXPECT_EQ(u"", textfield->GetText());
   EXPECT_EQ(0, enter_view->count());
 
   object_setClass(ns_view_, [InterpretKeyEventMockedBridgedContentView class]);
diff --git a/ui/views/controls/label_unittest.cc b/ui/views/controls/label_unittest.cc
index 1e538e0..b84c0fe 100644
--- a/ui/views/controls/label_unittest.cc
+++ b/ui/views/controls/label_unittest.cc
@@ -13,7 +13,6 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/i18n/rtl.h"
-#include "base/strings/utf_string_conversions.h"
 #include "base/test/gtest_util.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
@@ -459,13 +458,13 @@
 TEST_F(LabelTest, ObscuredSurrogatePair) {
   // 'MUSICAL SYMBOL G CLEF': represented in UTF-16 as two characters
   // forming the surrogate pair 0x0001D11E.
-  std::u16string test_text = base::UTF8ToUTF16("\xF0\x9D\x84\x9E");
-  label()->SetText(test_text);
+  const std::u16string kTestText = u"𝄞";
+  label()->SetText(kTestText);
   label()->SetObscured(true);
   label()->SizeToPreferredSize();
   EXPECT_EQ(std::u16string(1, gfx::RenderText::kPasswordReplacementChar),
             label()->GetDisplayTextForTesting());
-  EXPECT_EQ(test_text, label()->GetText());
+  EXPECT_EQ(kTestText, label()->GetText());
 }
 
 // This test case verifies the label preferred size will change based on the
diff --git a/ui/views/controls/textfield/textfield_model_unittest.cc b/ui/views/controls/textfield/textfield_model_unittest.cc
index 254d92d..1da236b 100644
--- a/ui/views/controls/textfield/textfield_model_unittest.cc
+++ b/ui/views/controls/textfield/textfield_model_unittest.cc
@@ -12,7 +12,6 @@
 
 #include "base/auto_reset.h"
 #include "base/stl_util.h"
-#include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -1349,7 +1348,7 @@
   EXPECT_EQ(10U, model.render_text()->cursor_position());
 #endif
 
-  model.InsertText(base::UTF8ToUTF16("-"));
+  model.InsertText(u"-");
   EXPECT_TRUE(composition_text_confirmed_or_cleared_);
   composition_text_confirmed_or_cleared_ = false;
   EXPECT_STR_EQ("1234567890-", model.text());
@@ -1362,7 +1361,7 @@
   model.SetCompositionText(composition);
   EXPECT_STR_EQ("1234567890678", model.text());
 
-  model.ReplaceText(base::UTF8ToUTF16("-"));
+  model.ReplaceText(u"-");
   EXPECT_TRUE(composition_text_confirmed_or_cleared_);
   composition_text_confirmed_or_cleared_ = false;
   EXPECT_STR_EQ("1234567890-", model.text());
@@ -1370,7 +1369,7 @@
   EXPECT_FALSE(model.HasSelection());
 
   model.SetCompositionText(composition);
-  model.Append(base::UTF8ToUTF16("-"));
+  model.Append(u"-");
   EXPECT_TRUE(composition_text_confirmed_or_cleared_);
   composition_text_confirmed_or_cleared_ = false;
   EXPECT_STR_EQ("1234567890-678-", model.text());
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc
index 35fa278..955dae8 100644
--- a/ui/views/widget/widget_unittest.cc
+++ b/ui/views/widget/widget_unittest.cc
@@ -10,7 +10,6 @@
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
-#include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
 #include "build/chromeos_buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -2179,9 +2178,9 @@
         widget->native_widget_private();
 
     std::u16string empty;
-    std::u16string s1(base::UTF8ToUTF16("Title1"));
-    std::u16string s2(base::UTF8ToUTF16("Title2"));
-    std::u16string s3(base::UTF8ToUTF16("TitleLong"));
+    std::u16string s1(u"Title1");
+    std::u16string s2(u"Title2");
+    std::u16string s3(u"TitleLong");
 
     // The widget starts with no title, setting empty should not change
     // anything.
diff --git a/ui/views/window/dialog_client_view_unittest.cc b/ui/views/window/dialog_client_view_unittest.cc
index 6f945cd..5fa7e31 100644
--- a/ui/views/window/dialog_client_view_unittest.cc
+++ b/ui/views/window/dialog_client_view_unittest.cc
@@ -11,7 +11,6 @@
 #include <utility>
 
 #include "base/macros.h"
-#include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
 #include "ui/base/ui_base_types.h"
@@ -96,8 +95,9 @@
     DialogModelChanged();
   }
 
-  void SetDialogButtonLabel(ui::DialogButton button, const std::string& label) {
-    DialogDelegate::SetButtonLabel(button, base::UTF8ToUTF16(label));
+  void SetDialogButtonLabel(ui::DialogButton button,
+                            const std::u16string& label) {
+    DialogDelegate::SetButtonLabel(button, label);
     DialogModelChanged();
   }
 
@@ -147,9 +147,8 @@
     return nullptr;
   }
 
-  Button* GetButtonByAccessibleName(const std::string& label) {
-    return GetButtonByAccessibleName(widget_->GetRootView(),
-                                     base::UTF8ToUTF16(label));
+  Button* GetButtonByAccessibleName(const std::u16string& name) {
+    return GetButtonByAccessibleName(widget_->GetRootView(), name);
   }
 
   DialogClientView* client_view() {
@@ -580,16 +579,16 @@
   // Note that cancel & ok may swap order depending on
   // PlatformStyle::kIsOkButtonLeading; these invariants hold for either order.
   SetDialogButtons(ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL);
-  SetDialogButtonLabel(ui::DIALOG_BUTTON_OK, "ok");
-  SetDialogButtonLabel(ui::DIALOG_BUTTON_CANCEL, "cancel");
-  SetExtraView(std::make_unique<LabelButton>(Button::PressedCallback(),
-                                             base::UTF8ToUTF16("extra")));
+  SetDialogButtonLabel(ui::DIALOG_BUTTON_OK, u"ok");
+  SetDialogButtonLabel(ui::DIALOG_BUTTON_CANCEL, u"cancel");
+  SetExtraView(
+      std::make_unique<LabelButton>(Button::PressedCallback(), u"extra"));
 
   widget()->Show();
 
-  Button* ok = GetButtonByAccessibleName("ok");
-  Button* cancel = GetButtonByAccessibleName("cancel");
-  Button* extra = GetButtonByAccessibleName("extra");
+  Button* ok = GetButtonByAccessibleName(u"ok");
+  Button* cancel = GetButtonByAccessibleName(u"cancel");
+  Button* extra = GetButtonByAccessibleName(u"extra");
 
   ASSERT_NE(ok, cancel);
   ASSERT_NE(ok, extra);
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.html b/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.html
index a1ac361..85b5832 100644
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.html
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.html
@@ -1,5 +1,6 @@
 <link rel="import" href="../../../html/polymer.html">
 
+<link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
 <link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html">
@@ -213,7 +214,9 @@
             label="[[i18n('activationCode')]]"
             value="{{activationCode}}"
             disabled="[[showBusy]]"
-            on-keydown="onKeyDown_">
+            on-keydown="onKeyDown_"
+            invalid="[[showError]]"
+            error-message="[[i18n('scanQrCodeInvalid')]]">
           </cr-input>
           <paper-spinner-lite active
               hidden$="[[!showBusy]]">
diff --git a/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.js b/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.js
index 088cf29..0dfb6bb 100644
--- a/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.js
+++ b/ui/webui/resources/cr_components/chromeos/cellular_setup/activation_code_page.js
@@ -17,6 +17,7 @@
   SWITCHING_CAM_ENVIRONMENT_TO_USER: 5,
   SCANNING_SUCCESS: 6,
   SCANNING_FAILURE: 7,
+  MANUAL_ENTRY_INSTALL_FAILURE: 8,
 };
 
 /** @enum {number} */
@@ -394,14 +395,18 @@
 
   /** @private */
   onShowErrorChanged_() {
+    // TODO(crbug.com/1093185) Handle install failure from scanning.
     if (this.showError) {
-      this.state_ = PageState.SCANNING_FAILURE;
+      this.state_ = PageState.MANUAL_ENTRY_INSTALL_FAILURE;
+      Polymer.RenderStatus.afterNextRender(this, () => {
+        cr.ui.focusWithoutInk(this.$.activationCode);
+      });
     }
   },
 
   /** @private */
   onStateChanged_() {
-    if (this.state_ !== PageState.SCANNING_FAILURE) {
+    if (this.state_ !== PageState.MANUAL_ENTRY_INSTALL_FAILURE) {
       this.showError = false;
     }
     if (this.state_ === PageState.MANUAL_ENTRY) {
@@ -435,7 +440,8 @@
   isUiElementHidden_(uiElement, state, cameraCount) {
     switch (uiElement) {
       case UiElement.START_SCANNING:
-        return state !== PageState.MANUAL_ENTRY;
+        return state !== PageState.MANUAL_ENTRY &&
+            state !== PageState.MANUAL_ENTRY_INSTALL_FAILURE;
       case UiElement.VIDEO:
         return state !== PageState.SCANNING_USER_FACING &&
             state !== PageState.SCANNING_ENVIRONMENT_FACING;
diff --git a/weblayer/browser/ad_tagging_browsertest.cc b/weblayer/browser/ad_tagging_browsertest.cc
index 64e29b9..84026ce2 100644
--- a/weblayer/browser/ad_tagging_browsertest.cc
+++ b/weblayer/browser/ad_tagging_browsertest.cc
@@ -120,7 +120,7 @@
   content::RenderFrameHost* ad_child = subresource_filter::CreateSrcFrame(
       web_contents(), GetURL("frame_factory.html?2&ad=true"));
   EXPECT_TRUE(observer.GetIsAdSubframe(ad_child->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
+  subresource_filter::ExpectFrameAdEvidence(
       ad_child, /*parent_is_ad=*/false,
       subresource_filter::FilterListEvidence::kMatchedBlockingRule,
       subresource_filter::ScriptHeuristicEvidence::kNotCreatedByAdScript);
@@ -129,9 +129,9 @@
   content::RenderFrameHost* ad_child_2 = subresource_filter::CreateSrcFrame(
       ad_child, GetURL("frame_factory.html?sub=1&3&ad=true"));
   EXPECT_TRUE(observer.GetIsAdSubframe(ad_child_2->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
+  subresource_filter::ExpectFrameAdEvidence(
       ad_child_2, /*parent_is_ad=*/true,
-      subresource_filter::FilterListEvidence::kNotChecked,
+      subresource_filter::FilterListEvidence::kMatchedBlockingRule,
       subresource_filter::ScriptHeuristicEvidence::kCreatedByAdScript);
 
   // (4) Vanilla child of 2.
@@ -139,9 +139,9 @@
       subresource_filter::CreateSrcFrame(ad_child,
                                          GetURL("frame_factory.html?4"));
   EXPECT_TRUE(observer.GetIsAdSubframe(vanilla_child_2->GetFrameTreeNodeId()));
-  observer.VerifyEvidenceForAdSubframe(
+  subresource_filter::ExpectFrameAdEvidence(
       vanilla_child_2, /*parent_is_ad=*/true,
-      subresource_filter::FilterListEvidence::kNotChecked,
+      subresource_filter::FilterListEvidence::kMatchedNoRules,
       subresource_filter::ScriptHeuristicEvidence::kCreatedByAdScript);
 
   // (5) Vanilla child of 1. This tests something subtle.
diff --git a/weblayer/browser/proxying_url_loader_factory_impl.cc b/weblayer/browser/proxying_url_loader_factory_impl.cc
index 8d3a35e..9771454d 100644
--- a/weblayer/browser/proxying_url_loader_factory_impl.cc
+++ b/weblayer/browser/proxying_url_loader_factory_impl.cc
@@ -222,7 +222,6 @@
 
 void ProxyingURLLoaderFactoryImpl::CreateLoaderAndStart(
     mojo::PendingReceiver<network::mojom::URLLoader> loader,
-    int32_t routing_id,
     int32_t request_id,
     uint32_t options,
     const network::ResourceRequest& request,
@@ -252,9 +251,9 @@
     }
   }
 
-  target_factory_->CreateLoaderAndStart(std::move(loader), routing_id,
-                                        request_id, options, request,
-                                        std::move(client), traffic_annotation);
+  target_factory_->CreateLoaderAndStart(std::move(loader), request_id, options,
+                                        request, std::move(client),
+                                        traffic_annotation);
 }
 
 void ProxyingURLLoaderFactoryImpl::Clone(
diff --git a/weblayer/browser/proxying_url_loader_factory_impl.h b/weblayer/browser/proxying_url_loader_factory_impl.h
index e691bb7..01de2a94 100644
--- a/weblayer/browser/proxying_url_loader_factory_impl.h
+++ b/weblayer/browser/proxying_url_loader_factory_impl.h
@@ -37,7 +37,6 @@
 
   void CreateLoaderAndStart(
       mojo::PendingReceiver<network::mojom::URLLoader> loader,
-      int32_t routing_id,
       int32_t request_id,
       uint32_t options,
       const network::ResourceRequest& request,