diff --git a/DEPS b/DEPS
index 5f4888a2..6b8be416 100644
--- a/DEPS
+++ b/DEPS
@@ -121,7 +121,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '094ab18b457e0a5c79c2159231dea2b7252e8275',
+  'skia_revision': 'd41c1876d8341e3486939b93d266975e81950147',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -133,7 +133,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': '59b1ed4a60fc9cf57c3914eb4851ec94c8df21a9',
+  'angle_revision': '5904ee3f58e31185d588c9568aad065a59f72b1e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling build tools
   # and whatever else without interference from each other.
@@ -145,7 +145,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': 'e24ead1a89472203125c8ad84269e1e7cf86e8b2',
+  'pdfium_revision': '578e24839231b120681cb75dde5d47917b592c20',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling openmax_dl
   # and whatever else without interference from each other.
@@ -181,7 +181,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '1879ca54b91657625dc272025635348a07eebe0f',
+  'catapult_revision': '514fe3e70db895bb83486d1349b7cfe8ff8b52d6',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -197,7 +197,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'feed_revision': 'd6031f504fcff6f34c4847f110a695fa54e90a9b',
+  'feed_revision': 'ed7c2ae304814efdb0e85cfbfe5205897b0d8d03',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling android_sdk_build-tools_version
   # and whatever else without interference from each other.
@@ -704,7 +704,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '60574b5f91b9a82f93d0d6d99f971bf42ba77e26',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'db34d87aff442e9676506dda26535c7fecee3a02',
 
   'src/third_party/devtools-node-modules':
     Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'),
@@ -1240,7 +1240,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@03e626851265893c03418f9c3ba1181efb525881',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@bfb698e79191c48a05d487152ef07d573a994ebc',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/browser/aw_quota_manager_bridge.cc b/android_webview/browser/aw_quota_manager_bridge.cc
index 8a8949f..dde9606 100644
--- a/android_webview/browser/aw_quota_manager_bridge.cc
+++ b/android_webview/browser/aw_quota_manager_bridge.cc
@@ -11,6 +11,7 @@
 #include "base/android/jni_array.h"
 #include "base/android/jni_string.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/task/post_task.h"
diff --git a/ash/accessibility/accessibility_focus_ring_layer.cc b/ash/accessibility/accessibility_focus_ring_layer.cc
index 0df3b6c..fa31c6c 100644
--- a/ash/accessibility/accessibility_focus_ring_layer.cc
+++ b/ash/accessibility/accessibility_focus_ring_layer.cc
@@ -10,7 +10,6 @@
 #include "third_party/skia/include/core/SkPath.h"
 #include "ui/aura/window.h"
 #include "ui/compositor/layer.h"
-#include "ui/compositor/paint_recorder.h"
 #include "ui/gfx/canvas.h"
 
 namespace ash {
@@ -20,10 +19,8 @@
 // The number of pixels in the color gradient that fades to transparent.
 const int kGradientWidth = 6;
 
-// The color of the focus ring. In the future this might be a parameter.
-const int kFocusRingColorRed = 247;
-const int kFocusRingColorGreen = 152;
-const int kFocusRingColorBlue = 58;
+// The default color of the focus ring.
+const SkColor kDefaultFocusRingColor = SkColorSetARGB(255, 247, 152, 58);
 
 int sign(int x) {
   return ((x > 0) ? 1 : (x == 0) ? 0 : -1);
@@ -106,6 +103,15 @@
   CreateOrUpdateLayer(root_window, "AccessibilityFocusRing", bounds);
 }
 
+void AccessibilityFocusRingLayer::EnableDoubleFocusRing(
+    SkColor secondary_color) {
+  secondary_color_ = secondary_color;
+}
+
+void AccessibilityFocusRingLayer::DisableDoubleFocusRing() {
+  secondary_color_.reset();
+}
+
 void AccessibilityFocusRingLayer::OnPaintLayer(
     const ui::PaintContext& context) {
   ui::PaintRecorder recorder(context, layer()->size());
@@ -115,11 +121,33 @@
   flags.setStyle(cc::PaintFlags::kStroke_Style);
   flags.setStrokeWidth(2);
 
+  if (secondary_color_)
+    DrawDoubleFocusRing(recorder, flags);
+  else
+    DrawFocusRing(recorder, flags);
+}
+
+void AccessibilityFocusRingLayer::DrawDoubleFocusRing(
+    ui::PaintRecorder& recorder,
+    cc::PaintFlags& flags) {
   SkColor base_color =
-      has_custom_color()
-          ? custom_color()
-          : SkColorSetARGB(255, kFocusRingColorRed, kFocusRingColorGreen,
-                           kFocusRingColorBlue);
+      has_custom_color() ? custom_color() : kDefaultFocusRingColor;
+
+  SkPath path;
+  gfx::Vector2d offset = layer()->bounds().OffsetFromOrigin();
+  flags.setColor(base_color);
+  path = MakePath(ring_, 0, offset);
+  recorder.canvas()->DrawPath(path, flags);
+
+  flags.setColor(*(secondary_color_));
+  path = MakePath(ring_, 2, offset);
+  recorder.canvas()->DrawPath(path, flags);
+}
+
+void AccessibilityFocusRingLayer::DrawFocusRing(ui::PaintRecorder& recorder,
+                                                cc::PaintFlags& flags) {
+  SkColor base_color =
+      has_custom_color() ? custom_color() : kDefaultFocusRingColor;
 
   SkPath path;
   gfx::Vector2d offset = layer()->bounds().OffsetFromOrigin();
diff --git a/ash/accessibility/accessibility_focus_ring_layer.h b/ash/accessibility/accessibility_focus_ring_layer.h
index ce035339..b1f0b9b78 100644
--- a/ash/accessibility/accessibility_focus_ring_layer.h
+++ b/ash/accessibility/accessibility_focus_ring_layer.h
@@ -9,6 +9,7 @@
 #include "ash/accessibility/focus_ring_layer.h"
 #include "ash/ash_export.h"
 #include "base/macros.h"
+#include "ui/compositor/paint_recorder.h"
 
 namespace ash {
 
@@ -23,12 +24,20 @@
   // Create the layer and update its bounds and position in the hierarchy.
   void Set(const AccessibilityFocusRing& ring);
 
+  void EnableDoubleFocusRing(SkColor secondary_color);
+  void DisableDoubleFocusRing();
+
  private:
   // ui::LayerDelegate overrides:
   void OnPaintLayer(const ui::PaintContext& context) override;
 
+  void DrawFocusRing(ui::PaintRecorder& recorder, cc::PaintFlags& flags);
+  void DrawDoubleFocusRing(ui::PaintRecorder& recorder, cc::PaintFlags& flags);
+
   // The outline of the current focus ring.
   AccessibilityFocusRing ring_;
+  // The secondary color, if there is a double focus ring.
+  base::Optional<SkColor> secondary_color_;
 
   DISALLOW_COPY_AND_ASSIGN(AccessibilityFocusRingLayer);
 };
diff --git a/ash/app_list/app_list_presenter_delegate_unittest.cc b/ash/app_list/app_list_presenter_delegate_unittest.cc
index 86d5207..edfc24a9 100644
--- a/ash/app_list/app_list_presenter_delegate_unittest.cc
+++ b/ash/app_list/app_list_presenter_delegate_unittest.cc
@@ -44,6 +44,7 @@
 #include "ash/wm/window_state.h"
 #include "ash/wm/window_util.h"
 #include "ash/wm/workspace_controller_test_api.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
@@ -112,6 +113,11 @@
     app_list::AppListView::SetShortAnimationForTesting(true);
     AshTestBase::SetUp();
 
+    // Zeros state changes expected UI behavior. Most test cases in this suite
+    // are the expected UI behavior with zero state being disabled.
+    // TODO(jennyz): Add new test cases for zero state, crbug.com/925195.
+    scoped_feature_list_.InitAndDisableFeature(
+        app_list_features::kEnableZeroStateSuggestions);
     // Make the display big enough to hold the app list.
     UpdateDisplay("1024x768");
   }
@@ -140,6 +146,8 @@
   }
 
  private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+
   DISALLOW_COPY_AND_ASSIGN(AppListPresenterDelegateTest);
 };
 
diff --git a/ash/app_list/home_launcher_gesture_handler.cc b/ash/app_list/home_launcher_gesture_handler.cc
index 1e8b210..c37b049 100644
--- a/ash/app_list/home_launcher_gesture_handler.cc
+++ b/ash/app_list/home_launcher_gesture_handler.cc
@@ -22,6 +22,7 @@
 #include "ash/wm/workspace/workspace_layout_manager.h"
 #include "ash/wm/workspace_controller.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/metrics/user_metrics.h"
 #include "base/numerics/ranges.h"
 #include "ui/aura/client/window_types.h"
diff --git a/ash/app_list/presenter/app_list_presenter_impl.cc b/ash/app_list/presenter/app_list_presenter_impl.cc
index afaf808..675351d 100644
--- a/ash/app_list/presenter/app_list_presenter_impl.cc
+++ b/ash/app_list/presenter/app_list_presenter_impl.cc
@@ -16,6 +16,7 @@
 #include "ash/public/cpp/app_list/app_list_features.h"
 #include "ash/public/cpp/app_list/app_list_switches.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "ui/aura/client/focus_client.h"
diff --git a/ash/app_list/views/app_list_view_unittest.cc b/ash/app_list/views/app_list_view_unittest.cc
index 89f8b2b..b561c28 100644
--- a/ash/app_list/views/app_list_view_unittest.cc
+++ b/ash/app_list/views/app_list_view_unittest.cc
@@ -38,6 +38,7 @@
 #include "ash/app_list/views/test/apps_grid_view_test_api.h"
 #include "ash/public/cpp/app_list/app_list_config.h"
 #include "ash/public/cpp/app_list/app_list_constants.h"
+#include "ash/public/cpp/app_list/app_list_features.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
@@ -333,6 +334,7 @@
             std::make_unique<TestSearchResult>();
         result->set_display_type(data.first);
         result->set_display_score(display_score);
+        result->set_title(base::ASCIIToUTF16("Test"));
         if (data.first == ash::SearchResultDisplayType::kCard) {
           const GURL kFakeCardUrl = GURL("https://www.google.com/coac?q=fake");
           result->set_query_url(kFakeCardUrl);
@@ -345,6 +347,21 @@
     RunPendingMessages();
   }
 
+  void ClearSearchResults() {
+    delegate_->GetSearchModel()->results()->DeleteAll();
+  }
+
+  void AddSearchResultWithTitleAndScore(const base::StringPiece& title,
+                                        double score) {
+    std::unique_ptr<TestSearchResult> result =
+        std::make_unique<TestSearchResult>();
+    result->set_display_type(ash::SearchResultDisplayType::kList);
+    result->set_display_score(score);
+    result->set_title(ASCIIToUTF16(title));
+    delegate_->GetSearchModel()->results()->Add(std::move(result));
+    RunPendingMessages();
+  }
+
   int GetOpenFirstSearchResultCount() {
     std::map<size_t, int>& counts = delegate_->open_search_result_counts();
     if (counts.size() == 0)
@@ -527,13 +544,14 @@
 
  protected:
   bool is_rtl_ = false;
+  base::test::ScopedFeatureList scoped_feature_list_;
 
  private:
   AppListView* view_ = nullptr;  // Owned by native widget.
   SearchResultContainerView* suggestions_container_ =
       nullptr;                                    // Owned by view hierarchy.
   ExpandArrowView* expand_arrow_view_ = nullptr;  // Owned by view hierarchy.
-  base::test::ScopedFeatureList scoped_feature_list_;
+
   std::unique_ptr<AppListTestViewDelegate> delegate_;
   std::unique_ptr<AppsGridViewTestApi> test_api_;
   // Restores the locale to default when destructor is called.
@@ -941,6 +959,14 @@
 // Tests that key event which is not handled by focused view will be redirected
 // to search box.
 TEST_F(AppListViewFocusTest, RedirectFocusToSearchBox) {
+  // UI behavior is different with Zero State enabled. This test is
+  // the expected UI behavior with zero state feature being disabled.
+  // TODO(jennyz): Add new test case for UI behavior for zero state.
+  // crbug.com/925195.
+  scoped_feature_list_.InitAndDisableFeature(
+      app_list_features::kEnableZeroStateSuggestions);
+  EXPECT_FALSE(app_list_features::IsZeroStateSuggestionsEnabled());
+
   Show();
 
   // Set focus to first suggestion app and type a character.
@@ -950,6 +976,7 @@
   EXPECT_EQ(search_box_view()->search_box()->text(), base::UTF8ToUTF16(" "));
   EXPECT_FALSE(search_box_view()->search_box()->HasSelection());
 
+  // UI and Focus behavior is different with Zero State enabled.
   // Set focus to expand arrow and type a character.
   expand_arrow_view()->RequestFocus();
   SimulateKeyPress(ui::VKEY_A, false);
@@ -986,6 +1013,35 @@
   EXPECT_FALSE(search_box_view()->search_box()->HasSelection());
 }
 
+// Tests that focus changes update the search box text.
+TEST_F(AppListViewFocusTest, SearchBoxTextUpdatesOnResultFocus) {
+  Show();
+  views::Textfield* search_box = search_box_view()->search_box();
+  search_box->InsertText(base::ASCIIToUTF16("TestText"));
+
+  // Set up test results with unique titles
+  ClearSearchResults();
+  AddSearchResultWithTitleAndScore("TestResult1", 3);
+  AddSearchResultWithTitleAndScore("TestResult2", 2);
+  AddSearchResultWithTitleAndScore("TestResult3", 1);
+
+  // Change focus to the first result
+  SimulateKeyPress(ui::VKEY_TAB, false);
+  SimulateKeyPress(ui::VKEY_TAB, false);
+
+  EXPECT_EQ(search_box->text(), base::UTF8ToUTF16("TestResult1"));
+
+  // Change focus to the next result
+  SimulateKeyPress(ui::VKEY_TAB, false);
+
+  EXPECT_EQ(search_box->text(), base::UTF8ToUTF16("TestResult2"));
+
+  // Change focus to the final result
+  SimulateKeyPress(ui::VKEY_TAB, false);
+
+  EXPECT_EQ(search_box->text(), base::UTF8ToUTF16("TestResult3"));
+}
+
 // Tests that the search box selects the whole query when focus moves to the
 // SearchBoxTextfield.
 TEST_F(AppListViewFocusTest, SearchBoxSelectionCoversWholeQueryOnFocus) {
diff --git a/ash/app_list/views/search_box_view_unittest.cc b/ash/app_list/views/search_box_view_unittest.cc
index b32e3ce..84c4377d 100644
--- a/ash/app_list/views/search_box_view_unittest.cc
+++ b/ash/app_list/views/search_box_view_unittest.cc
@@ -173,7 +173,12 @@
 // activated.
 TEST_F(SearchBoxViewTest, CloseButtonInvisibleAfterSearchBoxActived) {
   SetSearchBoxActive(true, ui::ET_MOUSE_PRESSED);
-  EXPECT_FALSE(view()->close_button()->visible());
+
+  // UI behavior is different with Zero State enabled.
+  if (app_list_features::IsZeroStateSuggestionsEnabled())
+    EXPECT_TRUE(view()->close_button()->visible());
+  else
+    EXPECT_FALSE(view()->close_button()->visible());
 }
 
 // Tests that the close button becomes invisible after close button is clicked.
@@ -302,8 +307,12 @@
 // Tests that the assistant button is visible after the search box is activated.
 TEST_F(SearchBoxViewAssistantButtonTest,
        AssistantButtonVisibleAfterSearchBoxActived) {
-  SetSearchBoxActive(true, ui::ET_MOUSE_PRESSED);
-  EXPECT_TRUE(view()->assistant_button()->visible());
+  // Assistant button is not showing up under zero state for now.
+  // TODO(jennyz): Make assistant button show up under zero state.
+  if (!app_list_features::IsZeroStateSuggestionsEnabled()) {
+    SetSearchBoxActive(true, ui::ET_MOUSE_PRESSED);
+    EXPECT_TRUE(view()->assistant_button()->visible());
+  }
 }
 
 // Tests that the assistant button is invisible after typing in the search box,
@@ -313,8 +322,12 @@
   KeyPress(ui::VKEY_A);
   EXPECT_FALSE(view()->assistant_button()->visible());
 
-  KeyPress(ui::VKEY_BACK);
-  EXPECT_TRUE(view()->assistant_button()->visible());
+  // Assistant button is not showing up under zero state for now.
+  // TODO(crbug.com/925455): Make assistant button show up under zero state.
+  if (!app_list_features::IsZeroStateSuggestionsEnabled()) {
+    KeyPress(ui::VKEY_BACK);
+    EXPECT_TRUE(view()->assistant_button()->visible());
+  }
 }
 
 class SearchBoxViewAutocompleteTest
diff --git a/ash/app_list/views/search_result_answer_card_view.cc b/ash/app_list/views/search_result_answer_card_view.cc
index 53e0821a..d10f070 100644
--- a/ash/app_list/views/search_result_answer_card_view.cc
+++ b/ash/app_list/views/search_result_answer_card_view.cc
@@ -318,10 +318,11 @@
     : search_answer_container_view_(
           new AnswerCardResultView(this, view_delegate)) {
   AddChildView(search_answer_container_view_);
+  AddObservedResultView(search_answer_container_view_);
   SetLayoutManager(std::make_unique<views::FillLayout>());
 }
 
-SearchResultAnswerCardView::~SearchResultAnswerCardView() {}
+SearchResultAnswerCardView::~SearchResultAnswerCardView() = default;
 
 const char* SearchResultAnswerCardView::GetClassName() const {
   return "SearchResultAnswerCardView";
diff --git a/ash/app_list/views/search_result_container_view.cc b/ash/app_list/views/search_result_container_view.cc
index c0f0d487..1203e2fd 100644
--- a/ash/app_list/views/search_result_container_view.cc
+++ b/ash/app_list/views/search_result_container_view.cc
@@ -4,6 +4,7 @@
 
 #include "ash/app_list/views/search_result_container_view.h"
 
+#include "ash/app_list/views/search_result_base_view.h"
 #include "base/bind.h"
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
@@ -55,6 +56,23 @@
   return "SearchResultContainerView";
 }
 
+void SearchResultContainerView::OnViewFocused(View* observed_view) {
+  if (delegate_) {
+    delegate_->OnSearchResultContainerResultFocused(
+        static_cast<SearchResultBaseView*>(observed_view));
+  }
+}
+
+void SearchResultContainerView::AddObservedResultView(
+    SearchResultBaseView* result_view) {
+  result_view_observer_.Add(result_view);
+}
+
+void SearchResultContainerView::RemoveObservedResultView(
+    SearchResultBaseView* result_view) {
+  result_view_observer_.Remove(result_view);
+}
+
 void SearchResultContainerView::ListItemsAdded(size_t /*start*/,
                                                size_t /*count*/) {
   ScheduleUpdate();
diff --git a/ash/app_list/views/search_result_container_view.h b/ash/app_list/views/search_result_container_view.h
index 01ec5b1c..95c16b58 100644
--- a/ash/app_list/views/search_result_container_view.h
+++ b/ash/app_list/views/search_result_container_view.h
@@ -12,7 +12,9 @@
 #include "ash/app_list/model/search/search_model.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/scoped_observer.h"
 #include "ui/views/view.h"
+#include "ui/views/view_observer.h"
 
 namespace app_list {
 
@@ -24,11 +26,17 @@
 // selected at a time; moving off the end of one container view selects the
 // first element of the next container view, and vice versa
 class APP_LIST_EXPORT SearchResultContainerView : public views::View,
+                                                  public views::ViewObserver,
                                                   public ui::ListModelObserver {
  public:
   class Delegate {
    public:
+    // Called whenever results in the container change, i.e. during |Update()|
     virtual void OnSearchResultContainerResultsChanged() = 0;
+
+    // Called whenever a result within the container gains focus.
+    virtual void OnSearchResultContainerResultFocused(
+        SearchResultBaseView* focused_result_view) = 0;
   };
   SearchResultContainerView();
   ~SearchResultContainerView() override;
@@ -62,6 +70,13 @@
   // Overridden from views::View:
   const char* GetClassName() const override;
 
+  // Overridden from views::ViewObserver:
+  void OnViewFocused(View* observed_view) override;
+
+  // Functions to allow derivative classes to add/remove observed result views.
+  void AddObservedResultView(SearchResultBaseView* result_view);
+  void RemoveObservedResultView(SearchResultBaseView* result_view);
+
   // Overridden from ui::ListModelObserver:
   void ListItemsAdded(size_t start, size_t count) override;
   void ListItemsRemoved(size_t start, size_t count) override;
@@ -88,6 +103,9 @@
 
   SearchModel::SearchResults* results_ = nullptr;  // Owned by SearchModel.
 
+  ScopedObserver<SearchResultBaseView, ViewObserver> result_view_observer_{
+      this};
+
   // The factory that consolidates multiple Update calls into one.
   base::WeakPtrFactory<SearchResultContainerView> update_factory_{this};
 
diff --git a/ash/app_list/views/search_result_list_view.cc b/ash/app_list/views/search_result_list_view.cc
index 0555562..65a0385 100644
--- a/ash/app_list/views/search_result_list_view.cc
+++ b/ash/app_list/views/search_result_list_view.cc
@@ -42,6 +42,7 @@
     search_result_views_.emplace_back(
         new SearchResultView(this, view_delegate_));
     results_container_->AddChildView(search_result_views_.back());
+    AddObservedResultView(search_result_views_.back());
   }
   AddChildView(results_container_);
 }
diff --git a/ash/app_list/views/search_result_page_view.cc b/ash/app_list/views/search_result_page_view.cc
index f6328dd..a65f74f 100644
--- a/ash/app_list/views/search_result_page_view.cc
+++ b/ash/app_list/views/search_result_page_view.cc
@@ -317,6 +317,19 @@
   first_result_view_->SetBackgroundHighlighted(true);
 }
 
+void SearchResultPageView::OnSearchResultContainerResultFocused(
+    SearchResultBaseView* focused_result_view) {
+  views::Textfield* search_box =
+      AppListPage::contents_view()->GetSearchBoxView()->search_box();
+  if (focused_result_view->result()->result_type() ==
+          ash::SearchResultType::kOmnibox &&
+      !focused_result_view->result()->is_omnibox_search()) {
+    search_box->SetText(focused_result_view->result()->details());
+  } else {
+    search_box->SetText(focused_result_view->result()->title());
+  }
+}
+
 void SearchResultPageView::OnHidden() {
   // Hide the search results page when it is behind search box to avoid focus
   // being moved onto suggested apps when zero state is enabled.
diff --git a/ash/app_list/views/search_result_page_view.h b/ash/app_list/views/search_result_page_view.h
index 1f4bbb01..4c1898b 100644
--- a/ash/app_list/views/search_result_page_view.h
+++ b/ash/app_list/views/search_result_page_view.h
@@ -51,6 +51,8 @@
 
   // Overridden from SearchResultContainerView::Delegate :
   void OnSearchResultContainerResultsChanged() override;
+  void OnSearchResultContainerResultFocused(
+      SearchResultBaseView* focused_result_view) override;
 
   views::View* contents_view() { return contents_view_; }
 
diff --git a/ash/app_list/views/search_result_page_view_unittest.cc b/ash/app_list/views/search_result_page_view_unittest.cc
index 3344542..c2613e9c 100644
--- a/ash/app_list/views/search_result_page_view_unittest.cc
+++ b/ash/app_list/views/search_result_page_view_unittest.cc
@@ -58,13 +58,20 @@
     }
 
     // Setting up the feature set.
-    if (test_with_answer_card)
-      scoped_feature_list_.InitAndEnableFeature(
-          app_list_features::kEnableAnswerCard);
-    else
-      scoped_feature_list_.InitAndDisableFeature(
-          app_list_features::kEnableAnswerCard);
+    // Zero State will affect the UI behavior significantly. This test works
+    // if zero state feature is disabled.
+    // TODO(crbug.com/925195): Add different test suites for zero state.
+    if (test_with_answer_card) {
+      scoped_feature_list_.InitWithFeatures(
+          {app_list_features::kEnableAnswerCard},
+          {app_list_features::kEnableZeroStateSuggestions});
+    } else {
+      scoped_feature_list_.InitWithFeatures(
+          {}, {app_list_features::kEnableAnswerCard,
+               app_list_features::kEnableZeroStateSuggestions});
+    }
 
+    ASSERT_FALSE(app_list_features::IsZeroStateSuggestionsEnabled());
     ASSERT_EQ(test_with_answer_card, app_list_features::IsAnswerCardEnabled());
 
     // Setting up views.
diff --git a/ash/app_list/views/search_result_tile_item_list_view.cc b/ash/app_list/views/search_result_tile_item_list_view.cc
index 5a09ff4..ea09492 100644
--- a/ash/app_list/views/search_result_tile_item_list_view.cc
+++ b/ash/app_list/views/search_result_tile_item_list_view.cc
@@ -76,6 +76,7 @@
         AppListConfig::instance().card_background_color());
     tile_views_.push_back(tile_item);
     AddChildView(tile_item);
+    AddObservedResultView(tile_item);
   }
 }
 
diff --git a/ash/app_list/views/search_result_tile_item_list_view_unittest.cc b/ash/app_list/views/search_result_tile_item_list_view_unittest.cc
index 99da7fc91..93297ac7 100644
--- a/ash/app_list/views/search_result_tile_item_list_view_unittest.cc
+++ b/ash/app_list/views/search_result_tile_item_list_view_unittest.cc
@@ -41,12 +41,17 @@
   void CreateSearchResultTileItemListView() {
     // Enable fullscreen app list for parameterized Play Store app search
     // feature.
+    // Zero State affects the UI behavior significantly. This test tests the
+    // UI behavior with zero state being disable.
+    // TODO(crbug.com/925195): Write new test cases for zero state.
     if (IsPlayStoreAppSearchEnabled()) {
       scoped_feature_list_.InitWithFeatures(
-          {app_list_features::kEnablePlayStoreAppSearch}, {});
+          {app_list_features::kEnablePlayStoreAppSearch},
+          {app_list_features::kEnableZeroStateSuggestions});
     } else {
       scoped_feature_list_.InitWithFeatures(
-          {}, {app_list_features::kEnablePlayStoreAppSearch});
+          {}, {app_list_features::kEnablePlayStoreAppSearch,
+               app_list_features::kEnableZeroStateSuggestions});
     }
     ASSERT_EQ(IsPlayStoreAppSearchEnabled(),
               app_list_features::IsPlayStoreAppSearchEnabled());
diff --git a/ash/assistant/assistant_setup_controller.cc b/ash/assistant/assistant_setup_controller.cc
index 53a7fe15..ed9ace5 100644
--- a/ash/assistant/assistant_setup_controller.cc
+++ b/ash/assistant/assistant_setup_controller.cc
@@ -8,6 +8,7 @@
 #include "ash/assistant/assistant_ui_controller.h"
 #include "ash/assistant/util/deep_link_util.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 
 namespace ash {
 
diff --git a/ash/display/display_configuration_observer.cc b/ash/display/display_configuration_observer.cc
index 731c7e9b..9b7993b 100644
--- a/ash/display/display_configuration_observer.cc
+++ b/ash/display/display_configuration_observer.cc
@@ -29,15 +29,12 @@
   Shell::Get()->tablet_mode_controller()->AddObserver(this);
   // Update the display pref with the initial power state.
   base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-  if (command_line->HasSwitch(chromeos::switches::kFirstExecAfterBoot) &&
-      save_preference_) {
+  if (command_line->HasSwitch(chromeos::switches::kFirstExecAfterBoot))
     Shell::Get()->display_prefs()->MaybeStoreDisplayPrefs();
-  }
 }
 
 void DisplayConfigurationObserver::OnDisplayConfigurationChanged() {
-  if (save_preference_)
-    Shell::Get()->display_prefs()->MaybeStoreDisplayPrefs();
+  Shell::Get()->display_prefs()->MaybeStoreDisplayPrefs();
 }
 
 void DisplayConfigurationObserver::OnTabletModeStarted() {
@@ -63,8 +60,8 @@
   save_preference_ = false;
   display::DisplayManager* display_manager = Shell::Get()->display_manager();
   was_in_mirror_mode_ = display_manager->IsInMirrorMode();
-  display_manager->SetMirrorMode(display::MirrorMode::kNormal, base::nullopt);
   display_manager->layout_store()->set_forced_mirror_mode_for_tablet(true);
+  display_manager->SetMirrorMode(display::MirrorMode::kNormal, base::nullopt);
 }
 
 void DisplayConfigurationObserver::EndMirrorMode() {
diff --git a/ash/display/display_configuration_observer.h b/ash/display/display_configuration_observer.h
index 4d94897..25833a72 100644
--- a/ash/display/display_configuration_observer.h
+++ b/ash/display/display_configuration_observer.h
@@ -23,6 +23,8 @@
   DisplayConfigurationObserver();
   ~DisplayConfigurationObserver() override;
 
+  bool save_preference() const { return save_preference_; }
+
  protected:
   // WindowTreeHostManager::Observer:
   void OnDisplaysInitialized() override;
diff --git a/ash/display/display_manager_unittest.cc b/ash/display/display_manager_unittest.cc
index 2a6c99f..7d0fce9 100644
--- a/ash/display/display_manager_unittest.cc
+++ b/ash/display/display_manager_unittest.cc
@@ -3089,6 +3089,43 @@
   EXPECT_FALSE(app_list_controller->IsVisible());
 }
 
+TEST_F(DisplayManagerTest, DisplayPrefsAndForcedMirrorMode) {
+  UpdateDisplay("400x300,800x800");
+  base::RunLoop().RunUntilIdle();
+
+  // Set the first display as internal display so that the tablet mode can be
+  // enabled.
+  display::test::DisplayManagerTestApi(display_manager())
+      .SetFirstDisplayAsInternalDisplay();
+
+  // Initially we can save display prefs ...
+  EXPECT_TRUE(Shell::Get()->ShouldSaveDisplaySettings());
+  // ... and there are no external displays that are candidates for mirror
+  // restore.
+  EXPECT_TRUE(display_manager()->external_display_mirror_info().empty());
+
+  // Turn on tablet mode, and expect that it's not possible to persist the
+  // display prefs while forced mirror mode is active.
+  Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(display_manager()->IsInSoftwareMirrorMode());
+  EXPECT_TRUE(
+      display_manager()->layout_store()->forced_mirror_mode_for_tablet());
+  EXPECT_FALSE(Shell::Get()->ShouldSaveDisplaySettings());
+  // Forced mirror mode does not add external displays as candidates for mirror
+  // restore.
+  EXPECT_TRUE(display_manager()->external_display_mirror_info().empty());
+
+  // Exit tablet mode and expect everything is back to normal.
+  Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(false);
+  base::RunLoop().RunUntilIdle();
+  EXPECT_FALSE(display_manager()->IsInSoftwareMirrorMode());
+  EXPECT_FALSE(
+      display_manager()->layout_store()->forced_mirror_mode_for_tablet());
+  EXPECT_TRUE(Shell::Get()->ShouldSaveDisplaySettings());
+  EXPECT_TRUE(display_manager()->external_display_mirror_info().empty());
+}
+
 TEST_F(DisplayManagerTest, DockMode) {
   const int64_t internal_id = 1;
   const int64_t external_id = 2;
diff --git a/ash/display/window_tree_host_manager_unittest.cc b/ash/display/window_tree_host_manager_unittest.cc
index baa35da..fe85b10 100644
--- a/ash/display/window_tree_host_manager_unittest.cc
+++ b/ash/display/window_tree_host_manager_unittest.cc
@@ -18,6 +18,7 @@
 #include "ash/wm/cursor_manager_test_api.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/wm_event.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
diff --git a/ash/highlighter/highlighter_controller.cc b/ash/highlighter/highlighter_controller.cc
index 1b721ad9..9d58217 100644
--- a/ash/highlighter/highlighter_controller.cc
+++ b/ash/highlighter/highlighter_controller.cc
@@ -17,6 +17,7 @@
 #include "ash/system/palette/palette_utils.h"
 #include "base/bind.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/timer/timer.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_tree_host.h"
diff --git a/ash/highlighter/highlighter_result_view.cc b/ash/highlighter/highlighter_result_view.cc
index 18c3d724..d3b0532a 100644
--- a/ash/highlighter/highlighter_result_view.cc
+++ b/ash/highlighter/highlighter_result_view.cc
@@ -11,6 +11,7 @@
 #include "ash/public/cpp/shell_window_ids.h"
 #include "ash/shell.h"
 #include "base/bind.h"
+#include "base/timer/timer.h"
 #include "ui/compositor/paint_recorder.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/gfx/geometry/rect_conversions.h"
diff --git a/ash/highlighter/highlighter_view.cc b/ash/highlighter/highlighter_view.cc
index 3c34b26..8b28a45 100644
--- a/ash/highlighter/highlighter_view.cc
+++ b/ash/highlighter/highlighter_view.cc
@@ -9,6 +9,7 @@
 #include "ash/highlighter/highlighter_gesture_util.h"
 #include "base/bind.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/timer/timer.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "third_party/skia/include/core/SkTypes.h"
 #include "ui/aura/window.h"
diff --git a/ash/ime/ime_controller.cc b/ash/ime/ime_controller.cc
index 92388fd..6d08aa3 100644
--- a/ash/ime/ime_controller.cc
+++ b/ash/ime/ime_controller.cc
@@ -8,6 +8,7 @@
 #include "ash/ime/mode_indicator_observer.h"
 #include "ash/shell.h"
 #include "ash/system/tray/system_tray_notifier.h"
+#include "base/bind_helpers.h"
 #include "ui/base/accelerators/accelerator.h"
 #include "ui/base/ime/chromeos/extension_ime_util.h"
 #include "ui/display/manager/display_manager.h"
diff --git a/ash/keyboard/virtual_keyboard_controller.cc b/ash/keyboard/virtual_keyboard_controller.cc
index 86cdbbf..ba77ff15 100644
--- a/ash/keyboard/virtual_keyboard_controller.cc
+++ b/ash/keyboard/virtual_keyboard_controller.cc
@@ -17,6 +17,7 @@
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/window_util.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/strings/string_util.h"
 #include "ui/base/emoji/emoji_panel_helper.h"
diff --git a/ash/keyboard/virtual_keyboard_unittest.cc b/ash/keyboard/virtual_keyboard_unittest.cc
index 6136050..c8f312ad 100644
--- a/ash/keyboard/virtual_keyboard_unittest.cc
+++ b/ash/keyboard/virtual_keyboard_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "ash/shell.h"
 #include "ash/test/ash_test_base.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "ui/aura/test/test_window_delegate.h"
 #include "ui/events/test/event_generator.h"
diff --git a/ash/login/ui/login_auth_user_view.cc b/ash/login/ui/login_auth_user_view.cc
index ef99069..d2291e9 100644
--- a/ash/login/ui/login_auth_user_view.cc
+++ b/ash/login/ui/login_auth_user_view.cc
@@ -27,6 +27,7 @@
 #include "ash/wallpaper/wallpaper_controller.h"
 #include "base/bind.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/timer/timer.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "components/user_manager/user.h"
 #include "ui/accessibility/ax_node_data.h"
diff --git a/ash/login/ui/login_expanded_public_account_view.cc b/ash/login/ui/login_expanded_public_account_view.cc
index 7a857fe..541e275 100644
--- a/ash/login/ui/login_expanded_public_account_view.cc
+++ b/ash/login/ui/login_expanded_public_account_view.cc
@@ -17,6 +17,7 @@
 #include "ash/shell.h"
 #include "ash/strings/grit/ash_strings.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/vector_icons/vector_icons.h"
 #include "ui/base/l10n/l10n_util.h"
diff --git a/ash/login/ui/login_expanded_public_account_view_unittest.cc b/ash/login/ui/login_expanded_public_account_view_unittest.cc
index 3342c93..b40e7f8b 100644
--- a/ash/login/ui/login_expanded_public_account_view_unittest.cc
+++ b/ash/login/ui/login_expanded_public_account_view_unittest.cc
@@ -9,6 +9,7 @@
 #include "ash/login/ui/login_test_utils.h"
 #include "ash/login/ui/public_account_warning_dialog.h"
 #include "ash/login/ui/views_utils.h"
+#include "base/bind_helpers.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/test/event_generator.h"
 #include "ui/views/layout/box_layout.h"
diff --git a/ash/login/ui/login_password_view.cc b/ash/login/ui/login_password_view.cc
index a000a8f..546e51f 100644
--- a/ash/login/ui/login_password_view.cc
+++ b/ash/login/ui/login_password_view.cc
@@ -16,6 +16,7 @@
 #include "base/bind.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/timer/timer.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/resource/resource_bundle.h"
diff --git a/ash/login/ui/scrollable_users_list_view.cc b/ash/login/ui/scrollable_users_list_view.cc
index 1ea1b3a..d4281cd 100644
--- a/ash/login/ui/scrollable_users_list_view.cc
+++ b/ash/login/ui/scrollable_users_list_view.cc
@@ -16,6 +16,7 @@
 #include "ash/wallpaper/wallpaper_controller.h"
 #include "base/bind.h"
 #include "base/numerics/ranges.h"
+#include "base/timer/timer.h"
 #include "ui/compositor/scoped_layer_animation_settings.h"
 #include "ui/display/screen.h"
 #include "ui/gfx/canvas.h"
diff --git a/ash/magnifier/magnification_controller.cc b/ash/magnifier/magnification_controller.cc
index 976381d..601b19f6 100644
--- a/ash/magnifier/magnification_controller.cc
+++ b/ash/magnifier/magnification_controller.cc
@@ -4,7 +4,6 @@
 
 #include "ash/magnifier/magnification_controller.h"
 
-#include <algorithm>
 #include <memory>
 #include <utility>
 #include <vector>
@@ -491,14 +490,14 @@
     SwitchTargetRootWindow(current_root, true);
 }
 
-ui::EventDispatchDetails MagnificationController::RewriteEvent(
+ui::EventRewriteStatus MagnificationController::RewriteEvent(
     const ui::Event& event,
-    const base::WeakPtr<Continuation> continuation) {
+    std::unique_ptr<ui::Event>* rewritten_event) {
   if (!IsEnabled())
-    return SendEvent(continuation, &event);
+    return ui::EVENT_REWRITE_CONTINUE;
 
   if (!event.IsTouchEvent())
-    return SendEvent(continuation, &event);
+    return ui::EVENT_REWRITE_CONTINUE;
 
   const ui::TouchEvent* touch_event = event.AsTouchEvent();
 
@@ -517,7 +516,7 @@
         touch_event_copy.unique_event_id(), false /* event_consumed */,
         false /* is_source_touch_event_set_non_blocking */);
   } else {
-    return DiscardEvent(continuation);
+    return ui::EVENT_REWRITE_DISCARD;
   }
 
   // User can change zoom level with two fingers pinch and pan around with two
@@ -548,13 +547,12 @@
       // TouchExplorationController confused. Send cancelled event for recorded
       // touch events to the next event rewriter here instead of rewriting an
       // event in the stream.
-      ui::EventDispatchDetails details =
-          SendEvent(continuation, &touch_cancel_event);
-      if (details.dispatcher_destroyed || details.target_destroyed)
-        return details;
+      SendEventToEventSource(root_window_->GetHost()->GetEventSource(),
+                             &touch_cancel_event);
     }
     press_event_map_.clear();
   }
+
   bool discard = consume_touch_event_;
 
   // Reset state once no point is touched on the screen.
@@ -572,9 +570,16 @@
   }
 
   if (discard)
-    return DiscardEvent(continuation);
+    return ui::EVENT_REWRITE_DISCARD;
 
-  return SendEvent(continuation, &event);
+  return ui::EVENT_REWRITE_CONTINUE;
+}
+
+ui::EventRewriteStatus MagnificationController::NextDispatchEvent(
+    const ui::Event& last_event,
+    std::unique_ptr<ui::Event>* new_event) {
+  NOTREACHED();
+  return ui::EVENT_REWRITE_CONTINUE;
 }
 
 bool MagnificationController::Redraw(const gfx::PointF& position,
diff --git a/ash/magnifier/magnification_controller.h b/ash/magnifier/magnification_controller.h
index 8dc92a4f..119d396 100644
--- a/ash/magnifier/magnification_controller.h
+++ b/ash/magnifier/magnification_controller.h
@@ -164,9 +164,12 @@
   void OnTouchEvent(ui::TouchEvent* event) override;
 
   // ui::EventRewriter overrides:
-  ui::EventDispatchDetails RewriteEvent(
+  ui::EventRewriteStatus RewriteEvent(
       const ui::Event& event,
-      const base::WeakPtr<Continuation> continuation) override;
+      std::unique_ptr<ui::Event>* new_event) override;
+  ui::EventRewriteStatus NextDispatchEvent(
+      const ui::Event& last_event,
+      std::unique_ptr<ui::Event>* new_event) override;
 
   // Redraws the magnification window with the given origin position and the
   // given scale. Returns true if the window is changed; otherwise, false.
diff --git a/ash/public/cpp/app_list/app_list_features.cc b/ash/public/cpp/app_list/app_list_features.cc
index 292e210..5cba0a4 100644
--- a/ash/public/cpp/app_list/app_list_features.cc
+++ b/ash/public/cpp/app_list/app_list_features.cc
@@ -27,7 +27,7 @@
 const base::Feature kEnableAppsGridGapFeature{"EnableAppsGridGapFeature",
                                               base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kEnableZeroStateSuggestions{
-    "EnableZeroStateSuggestions", base::FEATURE_DISABLED_BY_DEFAULT};
+    "EnableZeroStateSuggestions", base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kEnableAppListSearchAutocomplete{
     "EnableAppListSearchAutocomplete", base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kEnableAppSearchResultRanker{
diff --git a/ash/shelf/shelf.cc b/ash/shelf/shelf.cc
index b87491b6..ad6ce8d 100644
--- a/ash/shelf/shelf.cc
+++ b/ash/shelf/shelf.cc
@@ -19,6 +19,7 @@
 #include "ash/shelf/shelf_widget.h"
 #include "ash/shell.h"
 #include "ash/system/status_area_widget.h"
+#include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "ui/display/types/display_constants.h"
 #include "ui/gfx/geometry/rect.h"
diff --git a/ash/shelf/shelf_widget_unittest.cc b/ash/shelf/shelf_widget_unittest.cc
index 59754097..d27fa6fb 100644
--- a/ash/shelf/shelf_widget_unittest.cc
+++ b/ash/shelf/shelf_widget_unittest.cc
@@ -19,6 +19,7 @@
 #include "ash/test/ash_test_helper.h"
 #include "ash/test_shell_delegate.h"
 #include "ash/wm/window_util.h"
+#include "base/bind_helpers.h"
 #include "base/test/scoped_feature_list.h"
 #include "components/session_manager/session_manager_types.h"
 #include "ui/aura/window_event_dispatcher.h"
diff --git a/ash/shell.cc b/ash/shell.cc
index c0c007d..e3915c4 100644
--- a/ash/shell.cc
+++ b/ash/shell.cc
@@ -487,7 +487,8 @@
 bool Shell::ShouldSaveDisplaySettings() {
   return !(
       screen_orientation_controller_->ignore_display_configuration_updates() ||
-      resolution_notification_controller_->DoesNotificationTimeout());
+      resolution_notification_controller_->DoesNotificationTimeout() ||
+      !display_configuration_observer_->save_preference());
 }
 
 DockedMagnifierController* Shell::docked_magnifier_controller() {
diff --git a/ash/system/bluetooth/bluetooth_power_controller_unittest.cc b/ash/system/bluetooth/bluetooth_power_controller_unittest.cc
index fda5fb8..f2254eb 100644
--- a/ash/system/bluetooth/bluetooth_power_controller_unittest.cc
+++ b/ash/system/bluetooth/bluetooth_power_controller_unittest.cc
@@ -10,6 +10,7 @@
 #include "ash/test/ash_test_base.h"
 #include "ash/test/ash_test_helper.h"
 #include "ash/test_shell_delegate.h"
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
diff --git a/ash/system/bluetooth/tray_bluetooth_helper.h b/ash/system/bluetooth/tray_bluetooth_helper.h
index 92966a6..3ab5d01 100644
--- a/ash/system/bluetooth/tray_bluetooth_helper.h
+++ b/ash/system/bluetooth/tray_bluetooth_helper.h
@@ -10,6 +10,7 @@
 
 #include "ash/ash_export.h"
 #include "base/macros.h"
+#include "base/timer/timer.h"
 #include "device/bluetooth/bluetooth_common.h"
 #include "services/device/public/mojom/bluetooth_system.mojom.h"
 
diff --git a/ash/system/bluetooth/tray_bluetooth_helper_legacy_unittest.cc b/ash/system/bluetooth/tray_bluetooth_helper_legacy_unittest.cc
index dff3aba..5fd96739 100644
--- a/ash/system/bluetooth/tray_bluetooth_helper_legacy_unittest.cc
+++ b/ash/system/bluetooth/tray_bluetooth_helper_legacy_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "ash/system/bluetooth/tray_bluetooth_helper.h"
 #include "ash/test/ash_test_base.h"
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
 #include "dbus/object_path.h"
diff --git a/ash/system/network/auto_connect_notifier.cc b/ash/system/network/auto_connect_notifier.cc
index fbeb90d..5b17a91 100644
--- a/ash/system/network/auto_connect_notifier.cc
+++ b/ash/system/network/auto_connect_notifier.cc
@@ -7,6 +7,7 @@
 #include "ash/public/cpp/network_icon_image_source.h"
 #include "ash/public/cpp/notification_utils.h"
 #include "ash/strings/grit/ash_strings.h"
+#include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "base/strings/string16.h"
 #include "base/time/time.h"
diff --git a/ash/system/network/network_icon.cc b/ash/system/network/network_icon.cc
index ae0f6c6..f335bdd 100644
--- a/ash/system/network/network_icon.cc
+++ b/ash/system/network/network_icon.cc
@@ -14,7 +14,6 @@
 #include "base/memory/ptr_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/vector_icons/vector_icons.h"
-#include "chromeos/network/device_state.h"
 #include "chromeos/network/network_connection_handler.h"
 #include "chromeos/network/network_state.h"
 #include "chromeos/network/network_state_handler.h"
@@ -28,7 +27,6 @@
 #include "ui/gfx/skia_util.h"
 #include "ui/gfx/vector_icon_types.h"
 
-using chromeos::DeviceState;
 using chromeos::NetworkConnectionHandler;
 using chromeos::NetworkHandler;
 using chromeos::NetworkPortalDetector;
@@ -83,7 +81,7 @@
   std::string state_;
 
   // Cached strength index of the network when the icon was last generated.
-  int strength_index_;
+  int strength_index_ = -1;
 
   // Cached technology badge for the network when the icon was last generated.
   Badge technology_badge_ = {};
@@ -92,10 +90,10 @@
   Badge vpn_badge_ = {};
 
   // Cached roaming state of the network when the icon was last generated.
-  std::string roaming_state_;
+  bool is_roaming_ = false;
 
   // Cached portal state of the network when the icon was last generated.
-  bool behind_captive_portal_;
+  bool behind_captive_portal_ = false;
 
   // Generated icon image.
   gfx::ImageSkia image_;
@@ -385,10 +383,7 @@
 NetworkIconImpl::NetworkIconImpl(const std::string& path,
                                  IconType icon_type,
                                  const std::string& network_type)
-    : network_path_(path),
-      icon_type_(icon_type),
-      strength_index_(-1),
-      behind_captive_portal_(false) {
+    : network_path_(path), icon_type_(icon_type) {
   // Default image is null.
 }
 
@@ -439,9 +434,9 @@
     technology_badge_ = technology_badge;
     dirty = true;
   }
-  std::string roaming_state = network->roaming();
-  if (roaming_state != roaming_state_) {
-    roaming_state_ = roaming_state;
+  bool is_roaming = network->IndicateRoaming();
+  if (is_roaming != is_roaming_) {
+    is_roaming_ = is_roaming;
     dirty = true;
   }
   return dirty;
@@ -492,18 +487,8 @@
     technology_badge_ = {&kNetworkBadgeTechnology4gIcon, icon_color};
   } else if (type == shill::kTypeCellular) {
     // technology_badge_ is set in UpdateCellularState.
-    if (network->IsConnectedState() &&
-        network->roaming() == shill::kRoamingStateRoaming) {
-      // For networks that are always in roaming don't show roaming badge.
-      const DeviceState* device =
-          NetworkHandler::Get()->network_state_handler()->GetDeviceState(
-              network->device_path());
-      LOG_IF(WARNING, !device)
-          << "Could not find device state for " << network->device_path();
-      if (!device || !device->provider_requires_roaming()) {
-        badges->bottom_right = {&kNetworkBadgeRoamingIcon, icon_color};
-      }
-    }
+    if (network->IsConnectedState() && network->IndicateRoaming())
+      badges->bottom_right = {&kNetworkBadgeRoamingIcon, icon_color};
   }
   // Only show technology, VPN, and captive portal badges when connected.
   if (network->IsConnectedState()) {
diff --git a/ash/system/network/network_section_header_view.h b/ash/system/network/network_section_header_view.h
index d8085eb..5f3b660 100644
--- a/ash/system/network/network_section_header_view.h
+++ b/ash/system/network/network_section_header_view.h
@@ -8,6 +8,7 @@
 #include "ash/system/network/network_row_title_view.h"
 #include "ash/system/tray/tray_popup_utils.h"
 #include "ash/system/tray/tri_view.h"
+#include "base/timer/timer.h"
 #include "chromeos/network/network_state_handler.h"
 #include "ui/views/controls/button/toggle_button.h"
 #include "ui/views/layout/fill_layout.h"
diff --git a/ash/system/network/tray_network_state_observer.cc b/ash/system/network/tray_network_state_observer.cc
index 85f1723..0b82966 100644
--- a/ash/system/network/tray_network_state_observer.cc
+++ b/ash/system/network/tray_network_state_observer.cc
@@ -87,11 +87,6 @@
   SignalUpdate(false /* notify_a11y */);
 }
 
-void TrayNetworkStateObserver::DevicePropertiesUpdated(
-    const chromeos::DeviceState* device) {
-  SignalUpdate(false /* notify_a11y */);
-}
-
 void TrayNetworkStateObserver::OnPortalDetectionCompleted(
     const chromeos::NetworkState* network,
     const chromeos::NetworkPortalDetector::CaptivePortalState& state) {
diff --git a/ash/system/network/tray_network_state_observer.h b/ash/system/network/tray_network_state_observer.h
index 7716cf8..2ec5e36 100644
--- a/ash/system/network/tray_network_state_observer.h
+++ b/ash/system/network/tray_network_state_observer.h
@@ -37,7 +37,6 @@
   void NetworkConnectionStateChanged(
       const chromeos::NetworkState* network) override;
   void NetworkPropertiesUpdated(const chromeos::NetworkState* network) override;
-  void DevicePropertiesUpdated(const chromeos::DeviceState* device) override;
 
   // NetworkPortalDetector::Observer
   void OnPortalDetectionCompleted(
diff --git a/ash/system/power/video_activity_notifier.h b/ash/system/power/video_activity_notifier.h
index d93cb32..418e3af 100644
--- a/ash/system/power/video_activity_notifier.h
+++ b/ash/system/power/video_activity_notifier.h
@@ -11,6 +11,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/time/time.h"
+#include "base/timer/timer.h"
 
 namespace ash {
 
diff --git a/ash/system/screen_security/screen_security_notification_controller_unittest.cc b/ash/system/screen_security/screen_security_notification_controller_unittest.cc
index 1134450..f83e967e 100644
--- a/ash/system/screen_security/screen_security_notification_controller_unittest.cc
+++ b/ash/system/screen_security/screen_security_notification_controller_unittest.cc
@@ -7,6 +7,7 @@
 #include "ash/shell.h"
 #include "ash/system/tray/system_tray_notifier.h"
 #include "ash/test/ash_test_base.h"
+#include "base/bind_helpers.h"
 #include "ui/message_center/message_center.h"
 
 namespace ash {
diff --git a/ash/system/status_area_widget_unittest.cc b/ash/system/status_area_widget_unittest.cc
index d63a323b4..1457fa9c 100644
--- a/ash/system/status_area_widget_unittest.cc
+++ b/ash/system/status_area_widget_unittest.cc
@@ -19,6 +19,7 @@
 #include "ash/system/unified/unified_system_tray.h"
 #include "ash/system/virtual_keyboard/virtual_keyboard_tray.h"
 #include "ash/test/ash_test_base.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/network/network_handler.h"
diff --git a/ash/system/unified/notification_hidden_view.cc b/ash/system/unified/notification_hidden_view.cc
index 15ba0cc..799a0122 100644
--- a/ash/system/unified/notification_hidden_view.cc
+++ b/ash/system/unified/notification_hidden_view.cc
@@ -11,6 +11,7 @@
 #include "ash/system/tray/tray_constants.h"
 #include "ash/system/unified/sign_out_button.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/message_center/lock_screen/lock_screen_controller.h"
 #include "ui/message_center/message_center.h"
diff --git a/ash/system/unified/unified_slider_bubble_controller.h b/ash/system/unified/unified_slider_bubble_controller.h
index 1fba5a4..c9788c0 100644
--- a/ash/system/unified/unified_slider_bubble_controller.h
+++ b/ash/system/unified/unified_slider_bubble_controller.h
@@ -9,6 +9,7 @@
 #include "ash/system/audio/unified_volume_slider_controller.h"
 #include "ash/system/tray/tray_bubble_view.h"
 #include "ash/system/unified/unified_system_tray_model.h"
+#include "base/timer/timer.h"
 #include "chromeos/audio/cras_audio_handler.h"
 
 namespace ash {
diff --git a/ash/system/virtual_keyboard/virtual_keyboard_tray_unittest.cc b/ash/system/virtual_keyboard/virtual_keyboard_tray_unittest.cc
index 6120c2d..d5c13c0 100644
--- a/ash/system/virtual_keyboard/virtual_keyboard_tray_unittest.cc
+++ b/ash/system/virtual_keyboard/virtual_keyboard_tray_unittest.cc
@@ -7,6 +7,7 @@
 #include "ash/system/status_area_widget.h"
 #include "ash/system/status_area_widget_test_helper.h"
 #include "ash/test/ash_test_base.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "ui/keyboard/keyboard_controller.h"
 #include "ui/keyboard/keyboard_util.h"
diff --git a/ash/wm/overview/overview_session_unittest.cc b/ash/wm/overview/overview_session_unittest.cc
index 6599b1c..92d92bc00 100644
--- a/ash/wm/overview/overview_session_unittest.cc
+++ b/ash/wm/overview/overview_session_unittest.cc
@@ -298,6 +298,13 @@
     return gfx::Rect();
   }
 
+  views::Widget* GetShieldWidget(int index) {
+    if (overview_session())
+      return overview_session()->grid_list_[index]->shield_widget();
+
+    return nullptr;
+  }
+
   views::Widget* item_widget(OverviewItem* item) {
     return item->item_widget_.get();
   }
@@ -2524,6 +2531,30 @@
   ToggleOverview();
 }
 
+TEST_F(OverviewSessionTest, GridShieldAnimation) {
+  ui::ScopedAnimationDurationScaleMode test_duration_mode(
+      ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
+  std::unique_ptr<aura::Window> window(CreateTestWindow(gfx::Rect(200, 200)));
+
+  // Tests that if the window does not cover the workspace, the shield will not
+  // exist since it is created and animated in after position windows animations
+  // are finished.
+  ToggleOverview();
+  EXPECT_FALSE(GetShieldWidget(0));
+  ToggleOverview();
+
+  // Tests that if the window covers the workspace for example maximized, the
+  // shield will exist, and not be animated.
+  wm::GetWindowState(window.get())->Maximize();
+  ToggleOverview();
+  ASSERT_TRUE(GetShieldWidget(0));
+  EXPECT_FALSE(GetShieldWidget(0)
+                   ->GetNativeWindow()
+                   ->layer()
+                   ->GetAnimator()
+                   ->is_animating());
+}
+
 class SplitViewOverviewSessionTest : public OverviewSessionTest {
  public:
   SplitViewOverviewSessionTest() = default;
diff --git a/ash/wm/pip/pip_positioner_unittest.cc b/ash/wm/pip/pip_positioner_unittest.cc
index ae4d2263..66a1779 100644
--- a/ash/wm/pip/pip_positioner_unittest.cc
+++ b/ash/wm/pip/pip_positioner_unittest.cc
@@ -13,6 +13,7 @@
 #include "ash/test/ash_test_base.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/wm_event.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "ui/aura/window.h"
 #include "ui/gfx/geometry/insets.h"
diff --git a/ash/wm/pip/pip_window_resizer_unittest.cc b/ash/wm/pip/pip_window_resizer_unittest.cc
index d6632f3..8c2126a 100644
--- a/ash/wm/pip/pip_window_resizer_unittest.cc
+++ b/ash/wm/pip/pip_window_resizer_unittest.cc
@@ -13,6 +13,7 @@
 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
 #include "ash/wm/window_state.h"
 #include "ash/wm/wm_event.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/aura/window.h"
diff --git a/ash/wm/workspace/workspace_layout_manager_unittest.cc b/ash/wm/workspace/workspace_layout_manager_unittest.cc
index 50dcfb54..574d2c1 100644
--- a/ash/wm/workspace/workspace_layout_manager_unittest.cc
+++ b/ash/wm/workspace/workspace_layout_manager_unittest.cc
@@ -41,6 +41,7 @@
 #include "ash/wm/workspace/backdrop_delegate.h"
 #include "ash/wm/workspace/workspace_window_resizer.h"
 #include "ash/wm/workspace_controller_test_api.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/run_loop.h"
 #include "chromeos/audio/chromeos_sounds.h"
diff --git a/ash/ws/window_service_owner.cc b/ash/ws/window_service_owner.cc
index a48c7386..aca2496 100644
--- a/ash/ws/window_service_owner.cc
+++ b/ash/ws/window_service_owner.cc
@@ -10,6 +10,7 @@
 #include "ash/shell.h"
 #include "ash/wm/non_client_frame_controller.h"
 #include "ash/ws/window_service_delegate_impl.h"
+#include "base/bind_helpers.h"
 #include "base/lazy_instance.h"
 #include "base/unguessable_token.h"
 #include "services/content/public/cpp/buildflags.h"
diff --git a/base/no_destructor_unittest.cc b/base/no_destructor_unittest.cc
index 8f9d4a4..49d314e 100644
--- a/base/no_destructor_unittest.cc
+++ b/base/no_destructor_unittest.cc
@@ -7,7 +7,13 @@
 #include <string>
 #include <utility>
 
+#include "base/atomicops.h"
+#include "base/barrier_closure.h"
+#include "base/bind.h"
 #include "base/logging.h"
+#include "base/system/sys_info.h"
+#include "base/threading/platform_thread.h"
+#include "base/threading/simple_thread.h"
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -73,4 +79,118 @@
 #endif
 }  // namespace
 
+namespace {
+
+// A class whose constructor busy-loops until it is told to complete
+// construction.
+class BlockingConstructor {
+ public:
+  BlockingConstructor() {
+    EXPECT_FALSE(WasConstructorCalled());
+    subtle::NoBarrier_Store(&constructor_called_, 1);
+    EXPECT_TRUE(WasConstructorCalled());
+    while (!subtle::NoBarrier_Load(&complete_construction_))
+      PlatformThread::YieldCurrentThread();
+    done_construction_ = true;
+  }
+
+  ~BlockingConstructor() = delete;
+
+  // Returns true if BlockingConstructor() was entered.
+  static bool WasConstructorCalled() {
+    return subtle::NoBarrier_Load(&constructor_called_);
+  }
+
+  // Instructs BlockingConstructor() that it may now unblock its construction.
+  static void CompleteConstructionNow() {
+    subtle::NoBarrier_Store(&complete_construction_, 1);
+  }
+
+  bool done_construction() { return done_construction_; }
+
+ private:
+  // Use Atomic32 instead of AtomicFlag for them to be trivially initialized.
+  static subtle::Atomic32 constructor_called_;
+  static subtle::Atomic32 complete_construction_;
+
+  bool done_construction_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(BlockingConstructor);
+};
+
+// static
+subtle::Atomic32 BlockingConstructor::constructor_called_ = 0;
+// static
+subtle::Atomic32 BlockingConstructor::complete_construction_ = 0;
+
+// A SimpleThread running at |thread_priority| which invokes |before_get|
+// (optional) and then invokes thread-safe
+// scoped-static-initializationconstruction on its NoDestructor instance.
+class BlockingConstructorThread : public SimpleThread {
+ public:
+  BlockingConstructorThread(ThreadPriority thread_priority,
+                            OnceClosure before_get)
+      : SimpleThread("BlockingConstructorThread", Options(thread_priority)),
+        before_get_(std::move(before_get)) {}
+
+  void Run() override {
+    if (before_get_)
+      std::move(before_get_).Run();
+
+    static NoDestructor<BlockingConstructor> instance;
+    EXPECT_TRUE(instance->done_construction());
+  }
+
+ private:
+  OnceClosure before_get_;
+
+  DISALLOW_COPY_AND_ASSIGN(BlockingConstructorThread);
+};
+
+}  // namespace
+
+// Tests that if the thread assigned to construct the local-static
+// initialization of the NoDestructor runs at background priority : the
+// foreground threads will yield to it enough for it to eventually complete
+// construction. While local-static thread-safe initialization isn't specific to
+// NoDestructor, it is tested here as NoDestructor is set to replace
+// LazyInstance and this is an important regression test for it
+// (https://crbug.com/797129).
+TEST(NoDestructorTest, PriorityInversionAtStaticInitializationResolves) {
+  TimeTicks test_begin = TimeTicks::Now();
+
+  // Construct BlockingConstructor from a background thread.
+  BlockingConstructorThread background_getter(ThreadPriority::BACKGROUND,
+                                              OnceClosure());
+  background_getter.Start();
+
+  while (!BlockingConstructor::WasConstructorCalled())
+    PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
+
+  // Spin 4 foreground thread per core contending to get the already under
+  // construction NoDestructor. When they are all running and poking at it :
+  // allow the background thread to complete its work.
+  const int kNumForegroundThreads = 4 * SysInfo::NumberOfProcessors();
+  std::vector<std::unique_ptr<SimpleThread>> foreground_threads;
+  RepeatingClosure foreground_thread_ready_callback =
+      BarrierClosure(kNumForegroundThreads,
+                     BindOnce(&BlockingConstructor::CompleteConstructionNow));
+  for (int i = 0; i < kNumForegroundThreads; ++i) {
+    foreground_threads.push_back(std::make_unique<BlockingConstructorThread>(
+        ThreadPriority::NORMAL, foreground_thread_ready_callback));
+    foreground_threads.back()->Start();
+  }
+
+  // This test will hang if the foreground threads become stuck in
+  // NoDestructor's construction per the background thread never being scheduled
+  // to complete construction.
+  for (auto& foreground_thread : foreground_threads)
+    foreground_thread->Join();
+  background_getter.Join();
+
+  // Fail if this test takes more than 5 seconds (it takes 5-10 seconds on a
+  // Z840 without r527445 but is expected to be fast (~30ms) with the fix).
+  EXPECT_LT(TimeTicks::Now() - test_begin, TimeDelta::FromSeconds(5));
+}
+
 }  // namespace base
diff --git a/base/timer/mock_timer_unittest.cc b/base/timer/mock_timer_unittest.cc
index 3b27958..b624742 100644
--- a/base/timer/mock_timer_unittest.cc
+++ b/base/timer/mock_timer_unittest.cc
@@ -5,6 +5,7 @@
 #include "base/timer/mock_timer.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/base/trace_event/builtin_categories.h b/base/trace_event/builtin_categories.h
index b4c7cb99..0e40b59 100644
--- a/base/trace_event/builtin_categories.h
+++ b/base/trace_event/builtin_categories.h
@@ -51,7 +51,6 @@
   X("cma")                                                               \
   X("compositor")                                                        \
   X("content")                                                           \
-  X("cpu_profiler")                                                      \
   X("devtools")                                                          \
   X("devtools.timeline")                                                 \
   X("devtools.timeline.async")                                           \
diff --git a/base/trace_event/trace_event_etw_export_win.cc b/base/trace_event/trace_event_etw_export_win.cc
index e2c4f80d..fc6a2547 100644
--- a/base/trace_event/trace_event_etw_export_win.cc
+++ b/base/trace_event/trace_event_etw_export_win.cc
@@ -86,40 +86,39 @@
 const uint64_t kDisabledOtherEventsKeywordBit = 1ULL << 62;
 const size_t kNumberOfCategories = ARRAYSIZE(kFilteredEventGroupNames) + 2U;
 
+static void __stdcall EtwEnableCallback(LPCGUID SourceId,
+                                        ULONG ControlCode,
+                                        UCHAR Level,
+                                        ULONGLONG MatchAnyKeyword,
+                                        ULONGLONG MatchAllKeyword,
+                                        PEVENT_FILTER_DESCRIPTOR FilterData,
+                                        PVOID CallbackContext) {
+  // Invoke the default callback, which updates the information inside
+  // CHROME_Context.
+  McGenControlCallbackV2(SourceId, ControlCode, Level, MatchAnyKeyword,
+                         MatchAllKeyword, FilterData, CallbackContext);
+
+  base::trace_event::TraceEventETWExport::OnETWEnableUpdate();
+}
+
 }  // namespace
 
 namespace base {
 namespace trace_event {
 
-// This object will be created by each process. It's a background (low-priority)
-// thread that will monitor the ETW keyword for any changes.
-class TraceEventETWExport::ETWKeywordUpdateThread
-    : public PlatformThread::Delegate {
- public:
-  ETWKeywordUpdateThread() {}
-  ~ETWKeywordUpdateThread() override {}
+bool TraceEventETWExport::is_registration_complete_ = false;
 
-  // Implementation of PlatformThread::Delegate:
-  void ThreadMain() override {
-    PlatformThread::SetName("ETW Keyword Update Thread");
-    TimeDelta sleep_time = TimeDelta::FromMilliseconds(kUpdateTimerDelayMs);
-    while (1) {
-      PlatformThread::Sleep(sleep_time);
-      trace_event::TraceEventETWExport::UpdateETWKeyword();
-    }
-  }
-
- private:
-  // Time between checks for ETW keyword changes (in milliseconds).
-  unsigned int kUpdateTimerDelayMs = 1000;
-};
-
-
-TraceEventETWExport::TraceEventETWExport()
-    : etw_export_enabled_(false), etw_match_any_keyword_(0ULL) {
+TraceEventETWExport::TraceEventETWExport() : etw_match_any_keyword_(0ULL) {
   // Register the ETW provider. If registration fails then the event logging
-  // calls will fail.
-  EventRegisterChrome();
+  // calls will fail. We're essentially doing the same operation as
+  // EventRegisterChrome (which was auto generated for our provider by the
+  // ETW manifest compiler), but instead we're passing our own callback.
+  // This allows us to detect changes to enable/disable/keyword changes.
+  // ChromeHandle and the other parameters to EventRegister are all generated
+  // globals from chrome_events_win.h
+  DCHECK(!ChromeHandle);
+  EventRegister(&CHROME, &EtwEnableCallback, &CHROME_Context, &ChromeHandle);
+  TraceEventETWExport::is_registration_complete_ = true;
 
   // Make sure to initialize the map with all the group names. Subsequent
   // modifications will be made by the background thread and only affect the
@@ -134,40 +133,21 @@
 
 TraceEventETWExport::~TraceEventETWExport() {
   EventUnregisterChrome();
+  is_registration_complete_ = false;
 }
 
 // static
 void TraceEventETWExport::EnableETWExport() {
   auto* instance = GetInstance();
-  if (instance && !instance->etw_export_enabled_) {
-    instance->etw_export_enabled_ = true;
+  if (instance) {
     // Sync the enabled categories with ETW by calling UpdateEnabledCategories()
-    // that checks the keyword. Then create a thread that will call that same
-    // function periodically, to make sure we stay in sync.
+    // that checks the keyword. We'll stay in sync via the EtwEnableCallback
+    // we register in TraceEventETWExport's constructor.
     instance->UpdateEnabledCategories();
-    if (instance->keyword_update_thread_handle_.is_null()) {
-      instance->keyword_update_thread_.reset(new ETWKeywordUpdateThread);
-      PlatformThread::CreateWithPriority(
-          0, instance->keyword_update_thread_.get(),
-          &instance->keyword_update_thread_handle_, ThreadPriority::BACKGROUND);
-    }
   }
 }
 
 // static
-void TraceEventETWExport::DisableETWExport() {
-  auto* instance = GetInstance();
-  if (instance && instance->etw_export_enabled_)
-    instance->etw_export_enabled_ = false;
-}
-
-// static
-bool TraceEventETWExport::IsETWExportEnabled() {
-  auto* instance = GetInstanceIfExists();
-  return (instance && instance->etw_export_enabled_);
-}
-
-// static
 void TraceEventETWExport::AddEvent(char phase,
                                    const unsigned char* category_group_enabled,
                                    const char* name,
@@ -175,7 +155,7 @@
                                    const TraceArguments* args) {
   // We bail early in case exporting is disabled or no consumer is listening.
   auto* instance = GetInstance();
-  if (!instance || !instance->etw_export_enabled_ || !EventEnabledChromeEvent())
+  if (!instance || !EventEnabledChromeEvent())
     return;
 
   const char* phase_string = nullptr;
@@ -271,7 +251,7 @@
 // static
 void TraceEventETWExport::AddCompleteEndEvent(const char* name) {
   auto* instance = GetInstance();
-  if (!instance || !instance->etw_export_enabled_ || !EventEnabledChromeEvent())
+  if (!instance || !EventEnabledChromeEvent())
     return;
 
   EventWriteChromeEvent(name, "Complete End", "", "", "", "", "", "");
@@ -285,7 +265,7 @@
   if (instance == nullptr)
     return false;
 
-  if (!instance->IsETWExportEnabled())
+  if (!EventEnabledChromeEvent())
     return false;
 
   CStringTokenizer category_group_tokens(category_group_name.begin(),
@@ -357,12 +337,16 @@
 }
 
 // static
-void TraceEventETWExport::UpdateETWKeyword() {
-  if (!IsETWExportEnabled())
-    return;
-  auto* instance = GetInstance();
-  DCHECK(instance);
-  instance->UpdateEnabledCategories();
+void TraceEventETWExport::OnETWEnableUpdate() {
+  // During construction, if tracing is already enabled, we'll get
+  // a callback synchronously on the same thread. Calling GetInstance
+  // in that case will hang since we're in the process of creating the
+  // singleton.
+  if (is_registration_complete_) {
+    auto* instance = GetInstance();
+    if (instance)
+      instance->UpdateEnabledCategories();
+  }
 }
 
 // static
diff --git a/base/trace_event/trace_event_etw_export_win.h b/base/trace_event/trace_event_etw_export_win.h
index ac19553..0f85353 100644
--- a/base/trace_event/trace_event_etw_export_win.h
+++ b/base/trace_event/trace_event_etw_export_win.h
@@ -36,14 +36,9 @@
   // post-AtExit processing.
   static TraceEventETWExport* GetInstanceIfExists();
 
-  // Enables/disables exporting of events to ETW. If disabled,
-  // AddEvent and AddCustomEvent will simply return when called.
+  // Enables exporting of events to ETW. If tracing is disabled for the Chrome
+  // provider, AddEvent and AddCustomEvent will simply return when called.
   static void EnableETWExport();
-  static void DisableETWExport();
-
-  // Returns true if ETW is enabled. For now, this is true if the command line
-  // flag is specified.
-  static bool IsETWExportEnabled();
 
   // Exports an event to ETW. This is mainly used in
   // TraceLog::AddTraceEventWithThreadIdAndTimestamp to export internal events.
@@ -59,12 +54,14 @@
   // Returns true if any category in the group is enabled.
   static bool IsCategoryGroupEnabled(StringPiece category_group_name);
 
+  // Called from the ETW EnableCallback when the state of the provider or
+  // keywords has changed.
+  static void OnETWEnableUpdate();
+
  private:
   // Ensure only the provider can construct us.
   friend struct StaticMemorySingletonTraits<TraceEventETWExport>;
 
-  // To have access to UpdateKeyword().
-  class ETWKeywordUpdateThread;
   TraceEventETWExport();
 
   // Updates the list of enabled categories by consulting the ETW keyword.
@@ -74,12 +71,7 @@
   // Returns true if the category is enabled.
   bool IsCategoryEnabled(StringPiece category_name) const;
 
-  // Called back by the update thread to check for potential changes to the
-  // keyword.
-  static void UpdateETWKeyword();
-
-  // True if ETW is enabled. Allows hiding the exporting behind a flag.
-  bool etw_export_enabled_;
+  static bool is_registration_complete_;
 
   // Maps category names to their status (enabled/disabled).
   std::map<StringPiece, bool> categories_status_;
@@ -87,11 +79,6 @@
   // Local copy of the ETW keyword.
   uint64_t etw_match_any_keyword_;
 
-  // Background thread that monitors changes to the ETW keyword and updates
-  // the enabled categories when a change occurs.
-  std::unique_ptr<ETWKeywordUpdateThread> keyword_update_thread_;
-  PlatformThreadHandle keyword_update_thread_handle_;
-
   DISALLOW_COPY_AND_ASSIGN(TraceEventETWExport);
 };
 
diff --git a/build/android/apk_operations.py b/build/android/apk_operations.py
index 7e3aec1..f05005f 100755
--- a/build/android/apk_operations.py
+++ b/build/android/apk_operations.py
@@ -61,6 +61,8 @@
     r'^WAIT_',
     ]))
 
+BASE_MODULE = 'base'
+
 
 def _Colorize(text, style=''):
   return (style
@@ -115,22 +117,107 @@
   return info.bundle_apks_path
 
 
-def _InstallBundle(devices, bundle_apks, modules):
-  def install(device):
+def _InstallBundle(devices, bundle_apks, package_name, command_line_flags_file,
+                   modules, fake_modules):
+  # Path to push fake modules for Chrome to pick up.
+  MODULES_SRC_DIRECTORY_PATH = '/data/local/tmp/modules'
+  # Path Chrome creates after validating fake modules. This needs to be cleared
+  # for pushed fake modules to be picked up.
+  SPLITCOMPAT_PATH = '/data/data/' + package_name + '/files/splitcompat'
+  # Chrome command line flag needed for fake modules to work.
+  FAKE_FEATURE_MODULE_INSTALL = '--fake-feature-module-install'
+
+  def ShouldWarnFakeFeatureModuleInstallFlag(device):
+    if command_line_flags_file:
+      changer = flag_changer.FlagChanger(device, command_line_flags_file)
+      return FAKE_FEATURE_MODULE_INSTALL not in changer.GetCurrentFlags()
+    return False
+
+  def ClearFakeModules(device):
+    for path in [SPLITCOMPAT_PATH, MODULES_SRC_DIRECTORY_PATH]:
+      if device.PathExists(path, as_root=True):
+        device.RemovePath(path, force=True, recursive=True, as_root=True)
+        logging.info('Removed %s', path)
+      else:
+        logging.info('Skipped removing nonexistent %s', path)
+
+  def InstallFakeModules(device):
+    try:
+      temp_path = tempfile.mkdtemp()
+
+      # Device-spec JSON is needed, so create that first.
+      device_spec_filename = os.path.join(temp_path, 'device_spec.json')
+      get_device_spec_cmd_args = [
+          'get-device-spec', '--adb=' + adb_wrapper.AdbWrapper.GetAdbPath(),
+          '--device-id=' + device.serial, '--output=' + device_spec_filename
+      ]
+      bundletool.RunBundleTool(get_device_spec_cmd_args)
+
+      # Extract fake modules to temp directory. For now, installation requires
+      # running 'bundletool extract-apks'. Unfortunately, this leads to unneeded
+      # compression of module files.
+      extract_apks_cmd_args = [
+          'extract-apks', '--apks=' + bundle_apks,
+          '--device-spec=' + device_spec_filename,
+          '--modules=' + ','.join(fake_modules), '--output-dir=' + temp_path
+      ]
+      bundletool.RunBundleTool(extract_apks_cmd_args)
+
+      # Push fake modules, with renames.
+      for fake_module in fake_modules:
+        remote = posixpath.join(MODULES_SRC_DIRECTORY_PATH,
+                                '%s.apk' % fake_module)
+        # Try |local| filename alternatives, and ensure there's exactly one.
+        # TODO(huangs): Handle fake packages with different languages: See
+        #     http://crbug.com/925358.
+        local_choices = []
+        for suffix in ['-master.apk', '-master_2.apk']:
+          local = os.path.join(temp_path, fake_module + suffix)
+          if os.path.isfile(local):
+            local_choices.append(local)
+        if len(local_choices) != 1:
+          raise Exception('Expect 1 matching local file for %s' % fake_module)
+        device.adb.Push(local_choices[0], remote)
+    finally:
+      shutil.rmtree(temp_path, ignore_errors=True)
+
+  def Install(device):
+    ClearFakeModules(device)
+    if fake_modules:
+      # Print warning if command line is not set up for fake modules.
+      if ShouldWarnFakeFeatureModuleInstallFlag(device):
+        msg = ('Command line has no %s: Fake modules will be ignored.' %
+               FAKE_FEATURE_MODULE_INSTALL)
+        print _Colorize(msg, colorama.Fore.YELLOW + colorama.Style.BRIGHT)
+      InstallFakeModules(device)
+
     # NOTE: For now, installation requires running 'bundletool install-apks'.
     # TODO(digit): Add proper support for bundles to devil instead, then use it.
-    cmd_args = [
-        'install-apks',
-        '--apks=' + bundle_apks,
+    install_cmd_args = [
+        'install-apks', '--apks=' + bundle_apks,
         '--adb=' + adb_wrapper.AdbWrapper.GetAdbPath(),
         '--device-id=' + device.serial
     ]
     if modules:
-      cmd_args += ['--modules=' + ','.join(modules)]
-    bundletool.RunBundleTool(cmd_args)
+      install_cmd_args += ['--modules=' + ','.join(modules)]
+    bundletool.RunBundleTool(install_cmd_args)
+
+  # Basic checks for |modules| and |fake_modules|.
+  # * |fake_modules| cannot include 'base'.
+  # * If |fake_modules| is given, ensure |modules| includes 'base'.
+  # * They must be disjoint.
+  modules_set = set(modules) if modules else set()
+  fake_modules_set = set(fake_modules) if fake_modules else set()
+  if BASE_MODULE in fake_modules_set:
+    raise Exception('\'-f {}\' is disallowed.'.format(BASE_MODULE))
+  if fake_modules_set and BASE_MODULE not in modules_set:
+    raise Exception(
+        '\'-f FAKE\' must be accompanied by \'-m {}\''.format(BASE_MODULE))
+  if fake_modules_set.intersection(modules_set):
+    raise Exception('\'-m\' and \'-f\' entries must be disjoint.')
 
   logging.info('Installing bundle.')
-  device_utils.DeviceUtils.parallel(devices).pMap(install)
+  device_utils.DeviceUtils.parallel(devices).pMap(Install)
 
 
 def _UninstallApk(devices, install_dict, package_name):
@@ -999,14 +1086,26 @@
 
   def _RegisterExtraArgs(self, group):
     if self.is_bundle:
-      group.add_argument('-m', '--module', action='append',
-                         help='Module to install. Can be specified multiple '
-                              'times. One of them has to be \'base\'')
+      group.add_argument(
+          '-m',
+          '--module',
+          action='append',
+          help='Module to install. Can be specified multiple times. ' +
+          'One of them has to be \'{}\''.format(BASE_MODULE))
+      group.add_argument(
+          '-f',
+          '--fake',
+          action='append',
+          help='Fake bundle module install. Can be specified multiple times. '
+          'Requires \'-m {0}\' to be given, and \'-f {0}\' is illegal.'.format(
+              BASE_MODULE))
 
   def Run(self):
     if self.is_bundle:
       bundle_apks_path = _GenerateBundleApks(self.bundle_generation_info)
-      _InstallBundle(self.devices, bundle_apks_path, self.args.module)
+      _InstallBundle(self.devices, bundle_apks_path, self.args.package_name,
+                     self.args.command_line_flags_file, self.args.module,
+                     self.args.fake)
     else:
       _InstallApk(self.devices, self.apk_helper, self.install_dict)
 
diff --git a/build/android/gyp/apkbuilder.py b/build/android/gyp/apkbuilder.py
index b5097aa..ddbfa14 100755
--- a/build/android/gyp/apkbuilder.py
+++ b/build/android/gyp/apkbuilder.py
@@ -250,7 +250,6 @@
 
   native_libs = sorted(options.native_libs)
 
-  input_paths = [options.resource_apk, __file__]
   # Include native libs in the depfile_deps since GN doesn't know about the
   # dependencies when is_component_build=true.
   depfile_deps = list(native_libs)
@@ -260,17 +259,6 @@
     secondary_native_libs = sorted(options.secondary_native_libs)
     depfile_deps += secondary_native_libs
 
-  if options.dex_file:
-    input_paths.append(options.dex_file)
-
-  input_strings = [options.android_abi,
-                   options.native_lib_placeholders,
-                   options.secondary_native_lib_placeholders,
-                   str(options.uncompress_shared_libraries)]
-
-  if options.secondary_android_abi:
-    input_strings.append(options.secondary_android_abi)
-
   if options.java_resources:
     # Included via .build_config, so need to write it to depfile.
     depfile_deps.extend(options.java_resources)
@@ -283,16 +271,9 @@
         options.assets + options.uncompressed_assets)
     depfile_deps.extend(pak_infos)
 
-  for src_path, dest_path in itertools.chain(assets, uncompressed_assets):
-    # Included via .build_config, so need to write it to depfile.
-    depfile_deps.append(src_path)
-    input_strings.append(dest_path)
-
-  output_paths = [options.output_apk]
-  if options.apk_pak_info_path:
-    output_paths.append(options.apk_pak_info_path)
-  if options.apk_res_info_path:
-    output_paths.append(options.apk_res_info_path)
+  # Included via .build_config, so need to write it to depfile.
+  depfile_deps.extend(x[0] for x in assets)
+  depfile_deps.extend(x[0] for x in uncompressed_assets)
 
   # Bundle modules have a structure similar to APKs, except that resources
   # are compiled in protobuf format (instead of binary xml), and that some
@@ -314,119 +295,115 @@
     apk_root_dir = ''
     apk_dex_dir = ''
 
-  def on_stale_md5():
-    with tempfile.NamedTemporaryFile() as tmp_apk:
-      tmp_file = tmp_apk.name
-      with zipfile.ZipFile(options.resource_apk) as resource_apk, \
-           zipfile.ZipFile(tmp_file, 'w', zipfile.ZIP_DEFLATED) as out_apk:
-        def copy_resource(zipinfo, out_dir=''):
-          compress = zipinfo.compress_type != zipfile.ZIP_STORED
-          build_utils.AddToZipHermetic(out_apk, out_dir + zipinfo.filename,
-                                       data=resource_apk.read(zipinfo.filename),
-                                       compress=compress)
+  # Targets generally do not depend on apks, so no need for only_if_changed.
+  with build_utils.AtomicOutput(options.output_apk, only_if_changed=False) as f:
+    with zipfile.ZipFile(options.resource_apk) as resource_apk, \
+         zipfile.ZipFile(f, 'w', zipfile.ZIP_DEFLATED) as out_apk:
 
-        # Make assets come before resources in order to maintain the same file
-        # ordering as GYP / aapt. http://crbug.com/561862
-        resource_infos = resource_apk.infolist()
+      def copy_resource(zipinfo, out_dir=''):
+        compress = zipinfo.compress_type != zipfile.ZIP_STORED
+        build_utils.AddToZipHermetic(
+            out_apk,
+            out_dir + zipinfo.filename,
+            data=resource_apk.read(zipinfo.filename),
+            compress=compress)
 
-        # 1. AndroidManifest.xml
-        copy_resource(
-            resource_apk.getinfo('AndroidManifest.xml'),
-            out_dir=apk_manifest_dir)
+      # Make assets come before resources in order to maintain the same file
+      # ordering as GYP / aapt. http://crbug.com/561862
+      resource_infos = resource_apk.infolist()
 
-        # 2. Assets
-        if options.write_asset_list:
-          data = _CreateAssetsList(
-              itertools.chain(assets, uncompressed_assets))
-          build_utils.AddToZipHermetic(out_apk, 'assets/assets_list', data=data)
+      # 1. AndroidManifest.xml
+      copy_resource(
+          resource_apk.getinfo('AndroidManifest.xml'), out_dir=apk_manifest_dir)
 
-        _AddAssets(out_apk, assets, disable_compression=False)
-        _AddAssets(out_apk, uncompressed_assets, disable_compression=True)
+      # 2. Assets
+      if options.write_asset_list:
+        data = _CreateAssetsList(itertools.chain(assets, uncompressed_assets))
+        build_utils.AddToZipHermetic(out_apk, 'assets/assets_list', data=data)
 
-        # 3. Dex files
-        if options.dex_file and options.dex_file.endswith('.zip'):
-          with zipfile.ZipFile(options.dex_file, 'r') as dex_zip:
-            for dex in (d for d in dex_zip.namelist() if d.endswith('.dex')):
-              build_utils.AddToZipHermetic(out_apk, apk_dex_dir + dex,
-                                           data=dex_zip.read(dex),
-                                           compress=not options.uncompress_dex)
-        elif options.dex_file:
-          build_utils.AddToZipHermetic(out_apk, apk_dex_dir + 'classes.dex',
-                                       src_path=options.dex_file,
-                                       compress=not options.uncompress_dex)
+      _AddAssets(out_apk, assets, disable_compression=False)
+      _AddAssets(out_apk, uncompressed_assets, disable_compression=True)
 
-        # 4. Native libraries.
-        _AddNativeLibraries(out_apk,
-                            native_libs,
-                            options.android_abi,
+      # 3. Dex files
+      if options.dex_file and options.dex_file.endswith('.zip'):
+        with zipfile.ZipFile(options.dex_file, 'r') as dex_zip:
+          for dex in (d for d in dex_zip.namelist() if d.endswith('.dex')):
+            build_utils.AddToZipHermetic(
+                out_apk,
+                apk_dex_dir + dex,
+                data=dex_zip.read(dex),
+                compress=not options.uncompress_dex)
+      elif options.dex_file:
+        build_utils.AddToZipHermetic(
+            out_apk,
+            apk_dex_dir + 'classes.dex',
+            src_path=options.dex_file,
+            compress=not options.uncompress_dex)
+
+      # 4. Native libraries.
+      _AddNativeLibraries(out_apk, native_libs, options.android_abi,
+                          options.uncompress_shared_libraries)
+
+      if options.secondary_android_abi:
+        _AddNativeLibraries(out_apk, secondary_native_libs,
+                            options.secondary_android_abi,
                             options.uncompress_shared_libraries)
 
-        if options.secondary_android_abi:
-          _AddNativeLibraries(out_apk,
-                              secondary_native_libs,
-                              options.secondary_android_abi,
-                              options.uncompress_shared_libraries)
+      for name in sorted(options.native_lib_placeholders):
+        # Note: Empty libs files are ignored by md5check (can cause issues
+        # with stale builds when the only change is adding/removing
+        # placeholders).
+        apk_path = 'lib/%s/%s' % (options.android_abi, name)
+        build_utils.AddToZipHermetic(out_apk, apk_path, data='')
 
-        for name in sorted(options.native_lib_placeholders):
-          # Note: Empty libs files are ignored by md5check (can cause issues
-          # with stale builds when the only change is adding/removing
-          # placeholders).
-          apk_path = 'lib/%s/%s' % (options.android_abi, name)
-          build_utils.AddToZipHermetic(out_apk, apk_path, data='')
+      for name in sorted(options.secondary_native_lib_placeholders):
+        # Note: Empty libs files are ignored by md5check (can cause issues
+        # with stale builds when the only change is adding/removing
+        # placeholders).
+        apk_path = 'lib/%s/%s' % (options.secondary_android_abi, name)
+        build_utils.AddToZipHermetic(out_apk, apk_path, data='')
 
-        for name in sorted(options.secondary_native_lib_placeholders):
-          # Note: Empty libs files are ignored by md5check (can cause issues
-          # with stale builds when the only change is adding/removing
-          # placeholders).
-          apk_path = 'lib/%s/%s' % (options.secondary_android_abi, name)
-          build_utils.AddToZipHermetic(out_apk, apk_path, data='')
+      # 5. Resources
+      for info in resource_infos:
+        if info.filename != 'AndroidManifest.xml':
+          copy_resource(info)
 
-        # 5. Resources
-        for info in resource_infos:
-          if info.filename != 'AndroidManifest.xml':
-            copy_resource(info)
+      # 6. Java resources that should be accessible via
+      # Class.getResourceAsStream(), in particular parts of Emma jar.
+      # Prebuilt jars may contain class files which we shouldn't include.
+      for java_resource in options.java_resources:
+        with zipfile.ZipFile(java_resource, 'r') as java_resource_jar:
+          for apk_path in java_resource_jar.namelist():
+            apk_path_lower = apk_path.lower()
 
-        # 6. Java resources that should be accessible via
-        # Class.getResourceAsStream(), in particular parts of Emma jar.
-        # Prebuilt jars may contain class files which we shouldn't include.
-        for java_resource in options.java_resources:
-          with zipfile.ZipFile(java_resource, 'r') as java_resource_jar:
-            for apk_path in java_resource_jar.namelist():
-              apk_path_lower = apk_path.lower()
+            if apk_path_lower.startswith('meta-inf/'):
+              continue
+            if apk_path_lower.endswith('/'):
+              continue
+            if apk_path_lower.endswith('.class'):
+              continue
 
-              if apk_path_lower.startswith('meta-inf/'):
-                continue
-              if apk_path_lower.endswith('/'):
-                continue
-              if apk_path_lower.endswith('.class'):
-                continue
+            build_utils.AddToZipHermetic(
+                out_apk,
+                apk_root_dir + apk_path,
+                data=java_resource_jar.read(apk_path))
 
-              build_utils.AddToZipHermetic(
-                  out_apk, apk_root_dir + apk_path,
-                  data=java_resource_jar.read(apk_path))
+      if options.apk_pak_info_path:
+        _MergePakInfoFiles(options.apk_pak_info_path, pak_infos)
+      if options.apk_res_info_path:
+        _MergeResInfoFiles(options.apk_res_info_path, options.resource_apk)
 
-        if options.apk_pak_info_path:
-          _MergePakInfoFiles(options.apk_pak_info_path, pak_infos)
-        if options.apk_res_info_path:
-          _MergeResInfoFiles(options.apk_res_info_path, options.resource_apk)
+    if options.format == 'apk':
+      finalize_apk.FinalizeApk(options.apksigner_path, options.zipalign_path,
+                               f.name, f.name, options.key_path,
+                               options.key_passwd, options.key_name)
 
-      if options.format == 'apk':
-        finalize_apk.FinalizeApk(options.apksigner_path, options.zipalign_path,
-                                 tmp_file, options.output_apk,
-                                 options.key_path, options.key_passwd,
-                                 options.key_name)
-      else:
-        shutil.move(tmp_file, options.output_apk)
-        tmp_apk.delete = False
-
-  build_utils.CallAndWriteDepfileIfStale(
-      on_stale_md5,
-      options,
-      input_paths=input_paths + depfile_deps,
-      input_strings=input_strings,
-      output_paths=output_paths,
-      depfile_deps=depfile_deps,
-      add_pydeps=False)
+  if options.depfile:
+    build_utils.WriteDepfile(
+        options.depfile,
+        options.output_apk,
+        inputs=depfile_deps,
+        add_pydeps=False)
 
 
 if __name__ == '__main__':
diff --git a/build/android/gyp/compile_resources.py b/build/android/gyp/compile_resources.py
index 3c3e1066..c957bf7 100755
--- a/build/android/gyp/compile_resources.py
+++ b/build/android/gyp/compile_resources.py
@@ -696,8 +696,6 @@
   else:
     unoptimized_apk_path = options.apk_path
   link_command = _CreateLinkApkArgs(options)
-  link_command += ['-o', unoptimized_apk_path]
-  link_command += ['--output-text-symbols', r_txt_path]
   # TODO(digit): Is this below actually required for R.txt generation?
   link_command += ['--java', gen_dir]
 
@@ -710,22 +708,28 @@
 
   # Creates a .zip with AndroidManifest.xml, resources.arsc, res/*
   # Also creates R.txt
-  build_utils.CheckOutput(
-      link_command, print_stdout=False, print_stderr=False)
+  with build_utils.AtomicOutput(unoptimized_apk_path) as unoptimized, \
+      build_utils.AtomicOutput(r_txt_path) as r_txt:
+    link_command += ['-o', unoptimized.name]
+    link_command += ['--output-text-symbols', r_txt.name]
+    build_utils.CheckOutput(
+        link_command, print_stdout=False, print_stderr=False)
 
-  if options.optimize_resources:
-    _OptimizeApk(options, temp_dir, unoptimized_apk_path, r_txt_path)
+    if options.optimize_resources:
+      with build_utils.AtomicOutput(options.apk_path) as optimized:
+        _OptimizeApk(optimized.name, options, temp_dir, unoptimized.name,
+                     r_txt.name)
 
   _CreateResourceInfoFile(
       renamed_paths, options.apk_info_path, options.dependencies_res_zips)
 
 
-def _OptimizeApk(options, temp_dir, unoptimized_apk_path, r_txt_path):
+def _OptimizeApk(output, options, temp_dir, unoptimized_apk_path, r_txt_path):
   """Optimize intermediate .ap_ file with aapt2.
 
   Args:
-    options: The command-line options tuple. E.g. the generated apk
-      will be written to |options.apk_path|.
+    output: Path to write to.
+    options: The command-line options.
     temp_dir: A temporary directory.
     unoptimized_apk_path: path of the apk to optimize.
     r_txt_path: path to the R.txt file of the unoptimized apk.
@@ -749,7 +753,7 @@
       'optimize',
       '--enable-resource-obfuscation',
       '-o',
-      options.apk_path,
+      output,
       '--resources-config-path',
       gen_config_path,
       unoptimized_apk_path,
@@ -800,7 +804,17 @@
   return r_txt_file
 
 
-def _OnStaleMd5(options, debug_temp_resources_dir):
+def main(args):
+  args = build_utils.ExpandFileArgs(args)
+  options = _ParseArgs(args)
+
+  debug_temp_resources_dir = os.environ.get(_ENV_DEBUG_VARIABLE)
+  if debug_temp_resources_dir:
+    debug_temp_resources_dir = os.path.join(debug_temp_resources_dir,
+                                            os.path.basename(options.apk_path))
+    build_utils.DeleteDirectory(debug_temp_resources_dir)
+    build_utils.MakeDirectory(debug_temp_resources_dir)
+
   with resource_utils.BuildContext(debug_temp_resources_dir) as build:
     dep_subdirs = resource_utils.ExtractDeps(options.dependencies_res_zips,
                                              build.deps_dir)
@@ -843,71 +857,12 @@
         raise Exception('Invalid package ID 0x%x (expected 0x%x)' %
                         (package_id, expected_id))
 
-
-def main(args):
-  args = build_utils.ExpandFileArgs(args)
-  options = _ParseArgs(args)
-
-  # Order of these must match order specified in GN so that the correct one
-  # appears first in the depfile.
-  possible_output_paths = [
-      options.apk_path,
-      options.apk_path + '.info',
-      options.r_text_out,
-      options.srcjar_out,
-      options.proguard_file,
-      options.proguard_file_main_dex,
-      options.unoptimized_resources_path,
-  ]
-  output_paths = [x for x in possible_output_paths if x]
-
-  # List python deps in input_strings rather than input_paths since the contents
-  # of them does not change what gets written to the depsfile.
-  input_strings = options.extra_res_packages + [
-      options.shared_resources,
-      options.resource_blacklist_regex,
-      options.resource_blacklist_exceptions,
-      str(options.debuggable),
-      str(options.png_to_webp),
-      str(options.support_zh_hk),
-      str(options.no_xml_namespaces),
-      str(options.optimize_resources),
-  ]
-
-  input_strings.extend(_CreateLinkApkArgs(options))
-
-  debug_temp_resources_dir = os.environ.get(_ENV_DEBUG_VARIABLE)
-  if debug_temp_resources_dir:
-    debug_temp_resources_dir = os.path.join(debug_temp_resources_dir,
-                                            os.path.basename(options.apk_path))
-    build_utils.DeleteDirectory(debug_temp_resources_dir)
-    build_utils.MakeDirectory(debug_temp_resources_dir)
-
-
-  possible_input_paths = [
-      options.aapt_path,
-      options.aapt2_path,
-      options.android_manifest,
-      options.shared_resources_whitelist,
-      options.resources_config_path,
-  ]
-  possible_input_paths += options.include_resources
-  input_paths = [x for x in possible_input_paths if x]
-  input_paths.extend(options.dependencies_res_zips)
-  input_paths.extend(options.extra_r_text_files)
-
-  if options.webp_binary:
-    input_paths.append(options.webp_binary)
-
-  build_utils.CallAndWriteDepfileIfStale(
-      lambda: _OnStaleMd5(options, debug_temp_resources_dir),
-      options,
-      input_paths=input_paths,
-      input_strings=input_strings,
-      output_paths=output_paths,
-      force=bool(debug_temp_resources_dir),
-      depfile_deps=options.dependencies_res_zips + options.extra_r_text_files,
-      add_pydeps=False)
+  if options.depfile:
+    build_utils.WriteDepfile(
+        options.depfile,
+        options.apk_path,
+        inputs=options.dependencies_res_zips + options.extra_r_text_files,
+        add_pydeps=False)
 
 
 if __name__ == '__main__':
diff --git a/build/android/stacktrace/java/org/chromium/build/FlushingReTrace.java b/build/android/stacktrace/java/org/chromium/build/FlushingReTrace.java
index b142b398..85a92bb3 100644
--- a/build/android/stacktrace/java/org/chromium/build/FlushingReTrace.java
+++ b/build/android/stacktrace/java/org/chromium/build/FlushingReTrace.java
@@ -40,13 +40,17 @@
             // Normal stack trace lines look like:
             // \tat org.chromium.chrome.browser.tab.Tab.handleJavaCrash(Tab.java:682)
             + "(?:.*?(?::|\\bat)\\s+%c\\.%m\\s*\\(\\s*%s(?:\\s*:\\s*%l\\s*)?\\))|"
-            // E.g.: VFY: unable to resolve new-instance 3810 (LSome/Framework/Class;) in Lfoo/Bar;
-            + "(?:.*L%C;.*)|"
             // E.g.: Caused by: java.lang.NullPointerException: Attempt to read from field 'int bLA'
             // on a null object reference
             + "(?:.*java\\.lang\\.NullPointerException.*[\"']%t\\s*%c\\.(?:%f|%m\\(%a\\))[\"'].*)|"
             // E.g.: java.lang.VerifyError: bLA
             + "(?:java\\.lang\\.VerifyError: %c)|"
+            // E.g.: java.lang.NoSuchFieldError: No instance field e of type L...; in class LbxK;
+            + "(?:java\\.lang\\.NoSuchFieldError: No instance field %f of type .*? in class L%C;)|"
+            // E.g.: Object of type Clazz was not destroyed... (See LifetimeAssert.java)
+            + "(?:.*?Object of type %c .*)|"
+            // E.g.: VFY: unable to resolve new-instance 3810 (LSome/Framework/Class;) in Lfoo/Bar;
+            + "(?:.*L%C;.*)|"
             // E.g.: END SomeTestClass#someMethod
             + "(?:.*?%c#%m.*?)|"
             // E.g.: The member "Foo.bar"
@@ -56,6 +60,8 @@
             // Special-case for a common junit logcat message:
             // E.g.: java.lang.NoClassDefFoundError: SomeFrameworkClass in isTestClass for Foo
             + "(?:.* isTestClass for %c)|"
+            // E.g.: Caused by: java.lang.RuntimeException: Intentional Java Crash
+            + "(?:Caused by: %c:.*)|"
             // E.g.: java.lang.RuntimeException: Intentional Java Crash
             + "(?:%c:.*)|"
             // All lines that end with a class / class+method:
diff --git a/build/android/stacktrace/java_deobfuscate_test.py b/build/android/stacktrace/java_deobfuscate_test.py
index 087d0311..59edcd2 100755
--- a/build/android/stacktrace/java_deobfuscate_test.py
+++ b/build/android/stacktrace/java_deobfuscate_test.py
@@ -26,7 +26,10 @@
 
 TEST_MAP = """\
 this.was.Deobfuscated -> FOO:
-    int[] FontFamily -> a
+    int[] mFontFamily -> a
+    1:3:void someMethod(int,android.os.Bundle):65:67 -> bar
+never.Deobfuscated -> NOTFOO:
+    int[] mFontFamily -> a
     1:3:void someMethod(int,android.os.Bundle):65:67 -> bar
 """
 
@@ -45,6 +48,7 @@
     "END FOO#bar",
     "new-instance 3810 (LSome/Framework/Class;) in LFOO;",
     "FOO: Error message",
+    "Caused by: FOO: Error message",
     "\tat FOO.bar(PG:1)",
     "\t at\t FOO.bar\t (\t PG:\t 1\t )",
     ("Unable to start activity ComponentInfo{garbage.in/here.test}:"
@@ -53,6 +57,9 @@
     ("Caused by: java.lang.NullPointerException: Attempt to read from field"
      " 'int[] FOO.a' on a null object reference"),
     "java.lang.VerifyError: FOO",
+    ('java.lang.NoSuchFieldError: No instance field a of type '
+     'Ljava/lang/Class; in class LFOO;'),
+    "NOTFOO: Object of type FOO was not destroyed...",
 ]
 
 EXPECTED_OUTPUT = [
@@ -70,6 +77,7 @@
     "END this.was.Deobfuscated#someMethod",
     "new-instance 3810 (LSome/Framework/Class;) in Lthis/was/Deobfuscated;",
     "this.was.Deobfuscated: Error message",
+    "Caused by: this.was.Deobfuscated: Error message",
     "\tat this.was.Deobfuscated.someMethod(Deobfuscated.java:65)",
     ("\t at\t this.was.Deobfuscated.someMethod\t "
      "(\t Deobfuscated.java:\t 65\t )"),
@@ -78,8 +86,11 @@
      " 'void this.was.Deobfuscated.someMethod(int,android.os.Bundle)' on a null"
      " object reference"),
     ("Caused by: java.lang.NullPointerException: Attempt to read from field"
-     " 'int[] this.was.Deobfuscated.FontFamily' on a null object reference"),
-    "java.lang.VerifyError: this.was.Deobfuscated",
+     " 'int[] this.was.Deobfuscated.mFontFamily' on a null object reference"),
+    'java.lang.VerifyError: this.was.Deobfuscated',
+    ('java.lang.NoSuchFieldError: No instance field mFontFamily of type '
+     'Ljava/lang/Class; in class Lthis/was/Deobfuscated;'),
+    "NOTFOO: Object of type this.was.Deobfuscated was not destroyed...",
 ]
 TEST_DATA = [s + "\n" for s in TEST_DATA]
 EXPECTED_OUTPUT = [s + "\n" for s in EXPECTED_OUTPUT]
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index 05917f1..22954478 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-1704026b98afd73a1d63f9e70a1ce798999cbc73
\ No newline at end of file
+34369b5e7f0761d645deffe9da5b468f982a3592
\ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index e1a67d76..39698eac 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-489221f0ebb1437ed8e0af9df72ecc14faf84a4f
\ No newline at end of file
+bcbbb02ab5fbf764d103ac937271d4adf9adda17
\ No newline at end of file
diff --git a/cc/benchmarks/micro_benchmark_controller_unittest.cc b/cc/benchmarks/micro_benchmark_controller_unittest.cc
index 9d83548..f4a528d 100644
--- a/cc/benchmarks/micro_benchmark_controller_unittest.cc
+++ b/cc/benchmarks/micro_benchmark_controller_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
diff --git a/cc/layers/video_layer_impl_unittest.cc b/cc/layers/video_layer_impl_unittest.cc
index f7b2f20..a8ba9a7 100644
--- a/cc/layers/video_layer_impl_unittest.cc
+++ b/cc/layers/video_layer_impl_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <stddef.h>
 
+#include "base/bind_helpers.h"
 #include "cc/layers/video_frame_provider_client_impl.h"
 #include "cc/test/fake_video_frame_provider.h"
 #include "cc/test/layer_test_common.h"
diff --git a/cc/raster/raster_buffer_provider_unittest.cc b/cc/raster/raster_buffer_provider_unittest.cc
index e2192ad..25535e6 100644
--- a/cc/raster/raster_buffer_provider_unittest.cc
+++ b/cc/raster/raster_buffer_provider_unittest.cc
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/cancelable_callback.h"
 #include "base/location.h"
 #include "base/macros.h"
diff --git a/cc/test/fake_ui_resource_layer_tree_host_impl.cc b/cc/test/fake_ui_resource_layer_tree_host_impl.cc
index 10fd8ca9..2022b67 100644
--- a/cc/test/fake_ui_resource_layer_tree_host_impl.cc
+++ b/cc/test/fake_ui_resource_layer_tree_host_impl.cc
@@ -4,6 +4,7 @@
 
 #include "cc/test/fake_ui_resource_layer_tree_host_impl.h"
 
+#include "base/bind_helpers.h"
 #include "cc/resources/ui_resource_bitmap.h"
 #include "cc/test/fake_layer_tree_host_impl.h"
 
diff --git a/cc/tiles/image_controller_unittest.cc b/cc/tiles/image_controller_unittest.cc
index dad3a619..ba11ee8 100644
--- a/cc/tiles/image_controller_unittest.cc
+++ b/cc/tiles/image_controller_unittest.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/test/test_simple_task_runner.h"
diff --git a/cc/tiles/tile_manager_unittest.cc b/cc/tiles/tile_manager_unittest.cc
index d1d8105..3e9e4aff 100644
--- a/cc/tiles/tile_manager_unittest.cc
+++ b/cc/tiles/tile_manager_unittest.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 29e27769..2dc253b 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -12,6 +12,7 @@
 
 #include "base/base_switches.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/location.h"
 #include "base/memory/memory_pressure_listener.h"
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 42720dc..3c7b8760 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -1861,6 +1861,7 @@
 android_app_bundle("chrome_public_bundle") {
   bundle_name = "ChromePublic"
   base_module_target = ":chrome_public_base_bundle_module"
+  command_line_flags_file = "chrome-command-line"
   if (!is_java_debug) {
     proguard_enabled = true
   }
@@ -1874,6 +1875,7 @@
 android_app_bundle("chrome_modern_public_bundle") {
   bundle_name = "ChromeModernPublic"
   base_module_target = ":chrome_modern_public_base_bundle_module"
+  command_line_flags_file = "chrome-command-line"
   if (!is_java_debug) {
     proguard_enabled = true
   }
@@ -1891,6 +1893,7 @@
 android_app_bundle("monochrome_public_bundle") {
   bundle_name = "MonochromePublic"
   base_module_target = ":monochrome_public_base_bundle_module"
+  command_line_flags_file = "chrome-command-line"
   if (!is_java_debug) {
     proguard_enabled = true
     proguard_android_sdk_dep = webview_framework_dep
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java
index d46fb306..c17238e7 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedLoggingBridge.java
@@ -59,11 +59,12 @@
     }
 
     @Override
-    public void onContentDismissed(ContentLoggingData data) {
+    public void onContentDismissed(ContentLoggingData data, boolean wasCommitted) {
         // Bridge could have been destroyed for policy when this is called.
         // See https://crbug.com/901414.
         if (mNativeFeedLoggingBridge == 0) return;
 
+        // TODO(https://crbug.com/924739): Emit wasCommitted as well.
         nativeOnContentDismissed(
                 mNativeFeedLoggingBridge, data.getPositionInStream(), data.getRepresentationUri());
     }
@@ -126,6 +127,42 @@
     }
 
     @Override
+    public void onNotInterestedInSource(ContentLoggingData data, boolean wasCommitted) {
+        // Bridge could have been destroyed for policy when this is called.
+        // See https://crbug.com/901414.
+        if (mNativeFeedLoggingBridge == 0) return;
+
+        // TODO(https://crbug.com/924739): Implementation.
+    }
+
+    @Override
+    public void onNotInterestedInTopic(ContentLoggingData data, boolean wasCommitted) {
+        // Bridge could have been destroyed for policy when this is called.
+        // See https://crbug.com/901414.
+        if (mNativeFeedLoggingBridge == 0) return;
+
+        // TODO(https://crbug.com/924739): Implementation.
+    }
+
+    @Override
+    public void onInterestHeaderView(ContentLoggingData data) {
+        // Bridge could have been destroyed for policy when this is called.
+        // See https://crbug.com/901414.
+        if (mNativeFeedLoggingBridge == 0) return;
+
+        // TODO(https://crbug.com/924739): Implementation.
+    }
+
+    @Override
+    public void onInterestHeaderClicked(ContentLoggingData data) {
+        // Bridge could have been destroyed for policy when this is called.
+        // See https://crbug.com/901414.
+        if (mNativeFeedLoggingBridge == 0) return;
+
+        // TODO(https://crbug.com/924739): Implementation.
+    }
+
+    @Override
     public void onOpenedWithContent(int timeToPopulateMs, int contentCount) {
         // Bridge could have been destroyed for policy when this is called.
         // See https://crbug.com/901414.
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
index 2c05c05..56ab7b7a 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedNewTabPage.java
@@ -24,6 +24,7 @@
 import com.google.android.libraries.feed.host.action.ActionApi;
 import com.google.android.libraries.feed.host.stream.CardConfiguration;
 import com.google.android.libraries.feed.host.stream.SnackbarApi;
+import com.google.android.libraries.feed.host.stream.SnackbarCallbackApi;
 import com.google.android.libraries.feed.host.stream.StreamConfiguration;
 
 import org.chromium.base.ApiCompatibilityUtils;
@@ -92,6 +93,12 @@
                     new SnackbarManager.SnackbarController() {}, Snackbar.TYPE_ACTION,
                     Snackbar.UMA_FEED_NTP_STREAM));
         }
+
+        @Override
+        public void show(String message, String action, SnackbarCallbackApi callback) {
+            // TODO(https://crbug.com/924742): Set action text and correctly invoke callback.
+            show(message);
+        }
     }
 
     private static class BasicStreamConfiguration implements StreamConfiguration {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTask.java b/chrome/android/java/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTask.java
index 7912bf3..066d50be 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTask.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTask.java
@@ -57,19 +57,35 @@
         ThreadUtils.assertOnUiThread();
         mTaskId = taskParameters.getTaskId();
 
+        TaskFinishedCallback wrappedCallback = needsReschedule -> {
+            BackgroundTaskSchedulerExternalUma.reportNativeTaskFinished(mTaskId);
+            callback.taskFinished(needsReschedule);
+        };
+
+        // WrappedCallback will only be called when the work is done or in onStopTask. If the task
+        // is short-circuited early (by returning DONE or RESCHEDULE as a StartBeforeNativeResult),
+        // the wrappedCallback is not called. Thus task-finished metrics are only recorded if
+        // task-started metrics are.
         @StartBeforeNativeResult
-        int beforeNativeResult = onStartTaskBeforeNativeLoaded(context, taskParameters, callback);
+        int beforeNativeResult =
+                onStartTaskBeforeNativeLoaded(context, taskParameters, wrappedCallback);
 
         if (beforeNativeResult == StartBeforeNativeResult.DONE) return false;
 
         if (beforeNativeResult == StartBeforeNativeResult.RESCHEDULE) {
+            // Do not pass in wrappedCallback because this is a short-circuit reschedule. For UMA
+            // purposes, tasks are started when runWithNative is called and does not consider
+            // short-circuit reschedules such as this.
             ThreadUtils.postOnUiThread(buildRescheduleRunnable(callback));
             return true;
         }
 
+        BackgroundTaskSchedulerExternalUma.reportNativeTaskStarted(mTaskId);
+
         assert beforeNativeResult == StartBeforeNativeResult.LOAD_NATIVE;
-        runWithNative(context, buildStartWithNativeRunnable(context, taskParameters, callback),
-                buildRescheduleRunnable(callback));
+        runWithNative(context,
+                buildStartWithNativeRunnable(context, taskParameters, wrappedCallback),
+                buildRescheduleRunnable(wrappedCallback));
         return true;
     }
 
@@ -77,6 +93,7 @@
     public final boolean onStopTask(Context context, TaskParameters taskParameters) {
         ThreadUtils.assertOnUiThread();
         mTaskStopped = true;
+        BackgroundTaskSchedulerExternalUma.reportNativeTaskFinished(mTaskId);
         if (isNativeLoaded()) {
             return onStopTaskWithNative(context, taskParameters);
         } else {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java
index 9edc6a19..6c16347 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java
@@ -10,6 +10,7 @@
 import android.view.View;
 import android.view.ViewGroup.MarginLayoutParams;
 
+import org.chromium.base.Callback;
 import org.chromium.base.CommandLine;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.JNINamespace;
@@ -213,6 +214,23 @@
     }
 
     /**
+     * Call to get a thumbnail for a given tab ID from disk through a {@link Callback}. If there is
+     * no up to date thumbnail on the cache for the given tab, callback returns a null result.
+     * Currently this read a compressed file from disk and sends the Bitmap over the
+     * JNI boundary after decompressing. In its current form, should be used for experimental
+     * purposes only.
+     * TODO(yusufo): Change the plumbing so that at the least a {@link android.net.Uri} is send
+     * over JNI of an uncompressed file on disk.
+     * @param tabID The ID of the tab.
+     * @param callback The callback to send the {@link Bitmap} with.
+     */
+    public void getTabThumbnailWithCallback(int tabID, Callback<Bitmap> callback) {
+        if (mNativeTabContentManager == 0 || !mSnapshotsEnabled) return;
+
+        nativeGetTabThumbnailWithCallback(mNativeTabContentManager, tabID, callback);
+    }
+
+    /**
      * Cache the content of a tab as a thumbnail.
      * @param tab The tab whose content we will cache.
      */
@@ -302,5 +320,7 @@
     private native void nativeUpdateVisibleIds(
             long nativeTabContentManager, int[] priority, int primaryTabId);
     private native void nativeRemoveTabThumbnail(long nativeTabContentManager, int tabId);
+    private native void nativeGetTabThumbnailWithCallback(
+            long nativeTabContentManager, int tabId, Callback<Bitmap> callback);
     private static native void nativeDestroy(long nativeTabContentManager);
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/AppModalPresenter.java b/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/AppModalPresenter.java
index 51abadc..13382d5 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/AppModalPresenter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/AppModalPresenter.java
@@ -44,7 +44,9 @@
         mDialog = new Dialog(mContext, R.style.ModalDialogTheme);
         mDialog.setOnCancelListener(dialogInterface
                 -> dismissCurrentDialog(DialogDismissalCause.NAVIGATE_BACK_OR_TOUCH_OUTSIDE));
-
+        // Cancel on touch outside should be disabled by default. The ModelChangeProcessor wouldn't
+        // notify change if the property is not set during initialization.
+        mDialog.setCanceledOnTouchOutside(false);
         ModalDialogView dialogView = (ModalDialogView) LayoutInflater.from(mDialog.getContext())
                                              .inflate(R.layout.modal_dialog_view, null);
         mModelChangeProcessor =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java
index b3cbba8..94e27f7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java
@@ -136,7 +136,7 @@
     public boolean doesProcessSuggestion(OmniboxSuggestion suggestion) {
         Tab activeTab = mTabProvider != null ? mTabProvider.getActivityTab() : null;
         if (OmniboxSuggestionType.URL_WHAT_YOU_TYPED != suggestion.getType() || activeTab == null
-                || activeTab.isIncognito()) {
+                || activeTab.isIncognito() || activeTab.isNativePage()) {
             return false;
         }
         mLastProcessedSuggestion = suggestion;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
index 79b0432..3e18e05 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SingleCategoryPreferences.java
@@ -706,7 +706,8 @@
         // that have permission to access each.
         for (Website site : sites) {
             for (ChosenObjectInfo info : site.getChosenObjectInfo()) {
-                if (mSearch.isEmpty() || info.getName().toLowerCase().contains(mSearch)) {
+                if (mSearch == null || mSearch.isEmpty()
+                        || info.getName().toLowerCase().contains(mSearch)) {
                     Pair<ArrayList<ChosenObjectInfo>, ArrayList<Website>> entry =
                             objects.get(info.getObject());
                     if (entry == null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/widget/OverviewListLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/widget/OverviewListLayout.java
index 50bfd31..3e95688 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/widget/OverviewListLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/widget/OverviewListLayout.java
@@ -26,6 +26,7 @@
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
 import org.chromium.chrome.browser.widget.accessibility.AccessibilityTabModelAdapter.AccessibilityTabModelAdapterListener;
 import org.chromium.chrome.browser.widget.accessibility.AccessibilityTabModelWrapper;
+import org.chromium.ui.base.DeviceFormFactor;
 
 /**
  * A {@link Layout} that shows the tabs as two {@link ListView}s, one for each {@link TabModel} to
@@ -163,7 +164,12 @@
     public boolean canHostBeFocusable() {
         // TODO(https://crbug.com/918171): Consider fine-tuning accessibility support for the
         // overview list layout.
-        return false;
+        // We don't allow the host to gain focus for phones so that the CompositorViewHolder doesn't
+        // steal focus when trying to focus the disabled tab switcher button when there are no tabs
+        // open (https://crbug.com/584423). This solution never worked on tablets, however, and
+        // caused a different focus bug, so on tablets we do allow the host to gain focus
+        // (https://crbug.com/925277).
+        return DeviceFormFactor.isNonMultiDisplayContextOnTablet(getContext());
     }
 
     @Override
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTaskTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTaskTest.java
index 3551aa6..0066f89 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTaskTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/background_task_scheduler/NativeBackgroundTaskTest.java
@@ -369,6 +369,7 @@
     @Feature("BackgroundTaskScheduler")
     public void testOnStopTask_BeforeNativeLoaded_NeedsRescheduling() {
         mBrowserStartupController.setIsStartupSuccessfullyCompleted(false);
+        mTask.onStartTask(RuntimeEnvironment.application, getTaskParameters(), mCallback);
         mTask.setNeedsReschedulingAfterStop(true);
 
         assertTrue(mTask.onStopTask(RuntimeEnvironment.application, getTaskParameters()));
@@ -380,6 +381,7 @@
     @Feature("BackgroundTaskScheduler")
     public void testOnStopTask_BeforeNativeLoaded_DoesntNeedRescheduling() {
         mBrowserStartupController.setIsStartupSuccessfullyCompleted(false);
+        mTask.onStartTask(RuntimeEnvironment.application, getTaskParameters(), mCallback);
         mTask.setNeedsReschedulingAfterStop(false);
 
         assertFalse(mTask.onStopTask(RuntimeEnvironment.application, getTaskParameters()));
@@ -391,7 +393,7 @@
     @Feature("BackgroundTaskScheduler")
     public void testOnStopTask_NativeLoaded_NeedsRescheduling() {
         mBrowserStartupController.setIsStartupSuccessfullyCompleted(true);
-        ;
+        mTask.onStartTask(RuntimeEnvironment.application, getTaskParameters(), mCallback);
         mTask.setNeedsReschedulingAfterStop(true);
 
         assertTrue(mTask.onStopTask(RuntimeEnvironment.application, getTaskParameters()));
@@ -403,6 +405,7 @@
     @Feature("BackgroundTaskScheduler")
     public void testOnStopTask_NativeLoaded_DoesntNeedRescheduling() {
         mBrowserStartupController.setIsStartupSuccessfullyCompleted(true);
+        mTask.onStartTask(RuntimeEnvironment.application, getTaskParameters(), mCallback);
         mTask.setNeedsReschedulingAfterStop(false);
 
         assertFalse(mTask.onStopTask(RuntimeEnvironment.application, getTaskParameters()));
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index f73abbf1..b722dc9 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -2731,10 +2731,10 @@
     Off
   </message>
   <message name="IDS_SETTINGS_GOOGLE_ASSISTANT_VOICE_SETTINGS" desc="Title for the Assistant voice settings.">
-    Voice model
+    Voice match
   </message>
   <message name="IDS_SETTINGS_GOOGLE_ASSISTANT_VOICE_SETTINGS_DESCRIPTION" desc="Sub label for the Assistant voice settings.">
-    "Ok Google" voice model
+    Teach your Assistant to recognize your voice
   </message>
   <message name="IDS_SETTINGS_GOOGLE_ASSISTANT_VOICE_SETTINGS_RETRAIN" desc="Button label for retrain voice model.">
     Retrain
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 6ebafc0..95b0c65 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -956,6 +956,8 @@
     "page_load_metrics/observers/data_use_metrics_observer.h",
     "page_load_metrics/observers/document_write_page_load_metrics_observer.cc",
     "page_load_metrics/observers/document_write_page_load_metrics_observer.h",
+    "page_load_metrics/observers/foreground_duration_ukm_observer.cc",
+    "page_load_metrics/observers/foreground_duration_ukm_observer.h",
     "page_load_metrics/observers/from_gws_page_load_metrics_observer.cc",
     "page_load_metrics/observers/from_gws_page_load_metrics_observer.h",
     "page_load_metrics/observers/histogram_suffixes.cc",
@@ -1350,6 +1352,8 @@
     "resource_coordinator/browser_child_process_watcher.h",
     "resource_coordinator/chrome_browser_main_extra_parts_resource_coordinator.cc",
     "resource_coordinator/chrome_browser_main_extra_parts_resource_coordinator.h",
+    "resource_coordinator/chrome_content_browser_client_resource_coordinator_part.cc",
+    "resource_coordinator/chrome_content_browser_client_resource_coordinator_part.h",
     "resource_coordinator/discard_before_unload_helper.cc",
     "resource_coordinator/discard_before_unload_helper.h",
     "resource_coordinator/exponential_moving_average.cc",
@@ -1360,6 +1364,8 @@
     "resource_coordinator/performance_measurement_manager.h",
     "resource_coordinator/render_process_probe.cc",
     "resource_coordinator/render_process_probe.h",
+    "resource_coordinator/render_process_user_data.cc",
+    "resource_coordinator/render_process_user_data.h",
     "resource_coordinator/resource_coordinator_parts.cc",
     "resource_coordinator/resource_coordinator_parts.h",
     "resource_coordinator/session_restore_policy.cc",
@@ -5193,7 +5199,7 @@
     deps += [
       "//chrome/browser/resources/bookmarks:build",
       "//chrome/browser/resources/downloads:build",
-      "//chrome/browser/resources/md_history:build",
+      "//chrome/browser/resources/history:build",
     ]
     if (is_chromeos) {
       deps += [
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 479fbac6..4fb8b2b 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1194,9 +1194,6 @@
     {"show-overdraw-feedback", flag_descriptions::kShowOverdrawFeedbackName,
      flag_descriptions::kShowOverdrawFeedbackDescription, kOsAll,
      SINGLE_VALUE_TYPE(switches::kShowOverdrawFeedback)},
-    {"enable-draw-occlusion", flag_descriptions::kEnableDrawOcclusionName,
-     flag_descriptions::kEnableDrawOcclusionDescription, kOsAll,
-     FEATURE_VALUE_TYPE(features::kEnableDrawOcclusion)},
     {"ui-disable-partial-swap", flag_descriptions::kUiPartialSwapName,
      flag_descriptions::kUiPartialSwapDescription, kOsAll,
      SINGLE_DISABLE_VALUE_TYPE(switches::kUIDisablePartialSwap)},
diff --git a/chrome/browser/android/autofill_assistant/client_android.cc b/chrome/browser/android/autofill_assistant/client_android.cc
index 76e36218..05a305f 100644
--- a/chrome/browser/android/autofill_assistant/client_android.cc
+++ b/chrome/browser/android/autofill_assistant/client_android.cc
@@ -226,11 +226,7 @@
   if (controller_) {
     return;
   }
-  controller_ = std::make_unique<Controller>(
-      web_contents_,
-      /* client= */ this, WebController::CreateForWebContents(web_contents_),
-      Service::Create(web_contents_->GetBrowserContext(),
-                      /* client= */ this));
+  controller_ = std::make_unique<Controller>(web_contents_, /* client= */ this);
 }
 
 WEB_CONTENTS_USER_DATA_KEY_IMPL(ClientAndroid);
diff --git a/chrome/browser/android/compositor/tab_content_manager.cc b/chrome/browser/android/compositor/tab_content_manager.cc
index be9ef723..bd01868 100644
--- a/chrome/browser/android/compositor/tab_content_manager.cc
+++ b/chrome/browser/android/compositor/tab_content_manager.cc
@@ -10,6 +10,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/android/callback_android.h"
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
 #include "base/android/scoped_java_ref.h"
@@ -297,6 +298,18 @@
   NativeRemoveTabThumbnail(tab_id);
 }
 
+void TabContentManager::GetTabThumbnailWithCallback(
+    JNIEnv* env,
+    const base::android::JavaParamRef<jobject>& obj,
+    jint tab_id,
+    const base::android::JavaParamRef<jobject>& j_callback) {
+  thumbnail_cache_->DecompressThumbnailFromFile(
+      tab_id, base::BindRepeating(
+                  &TabContentManager::TabThumbnailAvailableFromDisk,
+                  weak_factory_.GetWeakPtr(),
+                  base::android::ScopedJavaGlobalRef<jobject>(j_callback)));
+}
+
 void TabContentManager::OnUIResourcesWereEvicted() {
   thumbnail_cache_->OnUIResourcesWereEvicted();
 }
@@ -320,6 +333,17 @@
     thumbnail_cache_->Put(tab_id, bitmap, thumbnail_scale);
 }
 
+void TabContentManager::TabThumbnailAvailableFromDisk(
+    base::android::ScopedJavaGlobalRef<jobject> j_callback,
+    bool result,
+    SkBitmap bitmap) {
+  ScopedJavaLocalRef<jobject> j_bitmap;
+  if (!bitmap.isNull() && result)
+    j_bitmap = gfx::ConvertToJavaBitmap(&bitmap);
+
+  RunObjectCallbackAndroid(j_callback, j_bitmap);
+}
+
 // ----------------------------------------------------------------------------
 // Native JNI methods
 // ----------------------------------------------------------------------------
diff --git a/chrome/browser/android/compositor/tab_content_manager.h b/chrome/browser/android/compositor/tab_content_manager.h
index 6e378d0c..95db6be 100644
--- a/chrome/browser/android/compositor/tab_content_manager.h
+++ b/chrome/browser/android/compositor/tab_content_manager.h
@@ -11,6 +11,7 @@
 
 #include "base/android/jni_android.h"
 #include "base/android/jni_weak_ref.h"
+#include "base/android/scoped_java_ref.h"
 #include "base/containers/flat_map.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
@@ -96,6 +97,11 @@
                           const base::android::JavaParamRef<jobject>& obj,
                           jint tab_id);
   void OnUIResourcesWereEvicted();
+  void GetTabThumbnailWithCallback(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jobject>& obj,
+      jint tab_id,
+      const base::android::JavaParamRef<jobject>& j_callback);
 
   // ThumbnailCacheObserver implementation;
   void OnFinishedThumbnailRead(TabId tab_id) override;
@@ -113,6 +119,11 @@
                              float thumbnail_scale,
                              const SkBitmap& bitmap);
 
+  void TabThumbnailAvailableFromDisk(
+      base::android::ScopedJavaGlobalRef<jobject> j_callback,
+      bool result,
+      SkBitmap bitmap);
+
   std::unique_ptr<ThumbnailCache> thumbnail_cache_;
   ThumbnailLayerMap static_layer_cache_;
   LayerMap live_layer_list_;
diff --git a/chrome/browser/android/customtabs/detached_resource_request_android.cc b/chrome/browser/android/customtabs/detached_resource_request_android.cc
index 46875d7..57a5655 100644
--- a/chrome/browser/android/customtabs/detached_resource_request_android.cc
+++ b/chrome/browser/android/customtabs/detached_resource_request_android.cc
@@ -6,6 +6,7 @@
 #include "base/android/jni_string.h"
 #include "base/android/scoped_java_ref.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "chrome/browser/android/customtabs/detached_resource_request.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_android.h"
diff --git a/chrome/browser/android/oom_intervention/oom_intervention_tab_helper.h b/chrome/browser/android/oom_intervention/oom_intervention_tab_helper.h
index 82d12e0..fc1205f 100644
--- a/chrome/browser/android/oom_intervention/oom_intervention_tab_helper.h
+++ b/chrome/browser/android/oom_intervention/oom_intervention_tab_helper.h
@@ -10,6 +10,7 @@
 #include "base/optional.h"
 #include "base/scoped_observer.h"
 #include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/android/oom_intervention/near_oom_monitor.h"
 #include "chrome/browser/ui/interventions/intervention_delegate.h"
 #include "components/crash/content/browser/crash_metrics_reporter_android.h"
diff --git a/chrome/browser/android/vr/vr_shell.h b/chrome/browser/android/vr/vr_shell.h
index 2a404d96..d55c14a1 100644
--- a/chrome/browser/android/vr/vr_shell.h
+++ b/chrome/browser/android/vr/vr_shell.h
@@ -15,6 +15,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/single_thread_task_runner.h"
 #include "base/strings/string16.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/page_info/page_info_ui.h"
 #include "chrome/browser/ui/toolbar/chrome_location_bar_model_delegate.h"
 #include "chrome/browser/vr/assets_load_status.h"
diff --git a/chrome/browser/apps/app_service/arc_apps.cc b/chrome/browser/apps/app_service/arc_apps.cc
index 02f40d5..0728843e 100644
--- a/chrome/browser/apps/app_service/arc_apps.cc
+++ b/chrome/browser/apps/app_service/arc_apps.cc
@@ -231,6 +231,11 @@
 void ArcApps::OpenNativeSettings(const std::string& app_id) {
   const std::unique_ptr<ArcAppListPrefs::AppInfo> app_info =
       prefs_->GetApp(app_id);
+  if (!app_info) {
+    LOG(ERROR) << "Cannot open native settings for " << app_id
+               << ". App is not found.";
+    return;
+  }
   arc::ShowPackageInfo(app_info->package_name,
                        arc::mojom::ShowPackageInfoPage::MAIN,
                        display::Screen::GetScreen()->GetPrimaryDisplay().id());
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
index efd2aea..ae42a24 100644
--- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
+++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "build/build_config.h"
diff --git a/chrome/browser/autofill/autofill_autocomplete_browsertest.cc b/chrome/browser/autofill/autofill_autocomplete_browsertest.cc
index 8727812c..c9c3e51 100644
--- a/chrome/browser/autofill/autofill_autocomplete_browsertest.cc
+++ b/chrome/browser/autofill/autofill_autocomplete_browsertest.cc
@@ -267,7 +267,10 @@
 // retention policy last version ran preference when the flag is enabled.
 IN_PROC_BROWSER_TEST_P(AutofillAutocompleteTest,
                        RetentionPolicy_Init_SavesVersionPref) {
-  // At this point, AutocompleteHistoryManager was already initialized.
+  // Navigate to a file and wait, this will make sure we instantiate
+  // AutocompleteHistoryManager.
+  NavigateToFile(kSimpleFormFileName);
+
   bool retention_policy_enabled = GetParam();
 
   int saved_version = pref_service()->GetInteger(
diff --git a/chrome/browser/background/background_mode_manager.cc b/chrome/browser/background/background_mode_manager.cc
index 3bc3253e..6c7273c 100644
--- a/chrome/browser/background/background_mode_manager.cc
+++ b/chrome/browser/background/background_mode_manager.cc
@@ -12,6 +12,7 @@
 
 #include "base/base_paths.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/location.h"
diff --git a/chrome/browser/browser_resources.grd b/chrome/browser/browser_resources.grd
index a4ea993..cfad0e3 100644
--- a/chrome/browser/browser_resources.grd
+++ b/chrome/browser/browser_resources.grd
@@ -330,49 +330,49 @@
         </if>
 
         <!-- MD History. -->
-        <include name="IDR_MD_HISTORY_CONSTANTS_HTML" file="resources\md_history\constants.html" type="BINDATA" />
-        <include name="IDR_MD_HISTORY_CONSTANTS_JS" file="resources\md_history\constants.js" type="BINDATA" />
-        <include name="IDR_MD_HISTORY_HISTORY_HTML" file="resources\md_history\history.html" preprocess="true" type="BINDATA" compress="gzip" />
-        <include name="IDR_MD_HISTORY_HISTORY_JS" file="resources\md_history\history.js" type="BINDATA" />
-        <include name="IDR_MD_HISTORY_IMAGES_100_SIGN_IN_PROMO_JPG" file="resources\md_history\images\100\sign_in_promo.jpg" type="BINDATA" />
-        <include name="IDR_MD_HISTORY_IMAGES_200_SIGN_IN_PROMO_JPG" file="resources\md_history\images\200\sign_in_promo.jpg" type="BINDATA" />
-        <include name="IDR_MD_HISTORY_STRINGS_HTML" file="resources\md_history\strings.html" type="BINDATA" />
+        <include name="IDR_MD_HISTORY_CONSTANTS_HTML" file="resources\history\constants.html" type="BINDATA" />
+        <include name="IDR_MD_HISTORY_CONSTANTS_JS" file="resources\history\constants.js" type="BINDATA" />
+        <include name="IDR_MD_HISTORY_HISTORY_HTML" file="resources\history\history.html" preprocess="true" type="BINDATA" compress="gzip" />
+        <include name="IDR_MD_HISTORY_HISTORY_JS" file="resources\history\history.js" type="BINDATA" />
+        <include name="IDR_MD_HISTORY_IMAGES_100_SIGN_IN_PROMO_JPG" file="resources\history\images\100\sign_in_promo.jpg" type="BINDATA" />
+        <include name="IDR_MD_HISTORY_IMAGES_200_SIGN_IN_PROMO_JPG" file="resources\history\images\200\sign_in_promo.jpg" type="BINDATA" />
+        <include name="IDR_MD_HISTORY_STRINGS_HTML" file="resources\history\strings.html" type="BINDATA" />
         <if expr="optimize_webui">
           <then>
-            <include name="IDR_MD_HISTORY_APP_VULCANIZED_HTML" file="${root_gen_dir}\chrome\browser\resources\md_history\app.vulcanized.html" preprocess="true" type="BINDATA" compress="gzip" use_base_dir="false" />
-            <include name="IDR_MD_HISTORY_APP_VULCANIZED_P2_HTML" file="${root_gen_dir}\chrome\browser\resources\md_history\app.vulcanized.p2.html" preprocess="true" type="BINDATA" compress="gzip" use_base_dir="false" />
-            <include name="IDR_MD_HISTORY_APP_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\md_history\app.crisper.js" preprocess="true" type="BINDATA" compress="gzip" use_base_dir="false" />
-            <include name="IDR_MD_HISTORY_LAZY_LOAD_VULCANIZED_HTML" file="${root_gen_dir}\chrome\browser\resources\md_history\lazy_load.vulcanized.html" preprocess="true" type="BINDATA" compress="gzip" use_base_dir="false" />
-            <include name="IDR_MD_HISTORY_LAZY_LOAD_VULCANIZED_P2_HTML" file="${root_gen_dir}\chrome\browser\resources\md_history\lazy_load.vulcanized.p2.html" preprocess="true" type="BINDATA" compress="gzip" use_base_dir="false" />
-            <include name="IDR_MD_HISTORY_LAZY_LOAD_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\md_history\lazy_load.crisper.js" preprocess="true" type="BINDATA" compress="gzip" use_base_dir="false" />
+            <include name="IDR_MD_HISTORY_APP_VULCANIZED_HTML" file="${root_gen_dir}\chrome\browser\resources\history\app.vulcanized.html" preprocess="true" type="BINDATA" compress="gzip" use_base_dir="false" />
+            <include name="IDR_MD_HISTORY_APP_VULCANIZED_P2_HTML" file="${root_gen_dir}\chrome\browser\resources\history\app.vulcanized.p2.html" preprocess="true" type="BINDATA" compress="gzip" use_base_dir="false" />
+            <include name="IDR_MD_HISTORY_APP_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\history\app.crisper.js" preprocess="true" type="BINDATA" compress="gzip" use_base_dir="false" />
+            <include name="IDR_MD_HISTORY_LAZY_LOAD_VULCANIZED_HTML" file="${root_gen_dir}\chrome\browser\resources\history\lazy_load.vulcanized.html" preprocess="true" type="BINDATA" compress="gzip" use_base_dir="false" />
+            <include name="IDR_MD_HISTORY_LAZY_LOAD_VULCANIZED_P2_HTML" file="${root_gen_dir}\chrome\browser\resources\history\lazy_load.vulcanized.p2.html" preprocess="true" type="BINDATA" compress="gzip" use_base_dir="false" />
+            <include name="IDR_MD_HISTORY_LAZY_LOAD_CRISPER_JS" file="${root_gen_dir}\chrome\browser\resources\history\lazy_load.crisper.js" preprocess="true" type="BINDATA" compress="gzip" use_base_dir="false" />
           </then>
           <else>
-            <include name="IDR_MD_HISTORY_APP_HTML" file="resources\md_history\app.html" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_APP_JS" file="resources\md_history\app.js" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_BROWSER_SERVICE_HTML" file="resources\md_history\browser_service.html" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_BROWSER_SERVICE_JS" file="resources\md_history\browser_service.js" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_HISTORY_ITEM_HTML" file="resources\md_history\history_item.html" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_HISTORY_ITEM_JS" file="resources\md_history\history_item.js" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_HISTORY_LIST_HTML" file="resources\md_history\history_list.html" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_HISTORY_LIST_JS" file="resources\md_history\history_list.js" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_HISTORY_TOOLBAR_HTML" file="resources\md_history\history_toolbar.html" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_HISTORY_TOOLBAR_JS" file="resources\md_history\history_toolbar.js" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_ICONS_HTML" file="resources\md_history\icons.html" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_LAZY_LOAD_HTML" file="resources\md_history\lazy_load.html" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_QUERY_MANAGER_HTML" file="resources\md_history\query_manager.html" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_QUERY_MANAGER_JS" file="resources\md_history\query_manager.js" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_ROUTER_HTML" file="resources\md_history\router.html" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_ROUTER_JS" file="resources\md_history\router.js" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_SEARCHED_LABEL_HTML" file="resources\md_history\searched_label.html" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_SEARCHED_LABEL_JS" file="resources\md_history\searched_label.js" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_SHARED_STYLE_HTML" file="resources\md_history\shared_style.html" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_SHARED_VARS_HTML" file="resources\md_history\shared_vars.html" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_SIDE_BAR_HTML" file="resources\md_history\side_bar.html" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_SIDE_BAR_JS" file="resources\md_history\side_bar.js" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_SYNCED_DEVICE_CARD_HTML" file="resources\md_history\synced_device_card.html" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_SYNCED_DEVICE_CARD_JS" file="resources\md_history\synced_device_card.js" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_SYNCED_DEVICE_MANAGER_HTML" file="resources\md_history\synced_device_manager.html" type="BINDATA" />
-            <include name="IDR_MD_HISTORY_SYNCED_DEVICE_MANAGER_JS" file="resources\md_history\synced_device_manager.js" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_APP_HTML" file="resources\history\app.html" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_APP_JS" file="resources\history\app.js" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_BROWSER_SERVICE_HTML" file="resources\history\browser_service.html" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_BROWSER_SERVICE_JS" file="resources\history\browser_service.js" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_HISTORY_ITEM_HTML" file="resources\history\history_item.html" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_HISTORY_ITEM_JS" file="resources\history\history_item.js" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_HISTORY_LIST_HTML" file="resources\history\history_list.html" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_HISTORY_LIST_JS" file="resources\history\history_list.js" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_HISTORY_TOOLBAR_HTML" file="resources\history\history_toolbar.html" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_HISTORY_TOOLBAR_JS" file="resources\history\history_toolbar.js" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_ICONS_HTML" file="resources\history\icons.html" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_LAZY_LOAD_HTML" file="resources\history\lazy_load.html" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_QUERY_MANAGER_HTML" file="resources\history\query_manager.html" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_QUERY_MANAGER_JS" file="resources\history\query_manager.js" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_ROUTER_HTML" file="resources\history\router.html" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_ROUTER_JS" file="resources\history\router.js" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_SEARCHED_LABEL_HTML" file="resources\history\searched_label.html" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_SEARCHED_LABEL_JS" file="resources\history\searched_label.js" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_SHARED_STYLE_HTML" file="resources\history\shared_style.html" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_SHARED_VARS_HTML" file="resources\history\shared_vars.html" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_SIDE_BAR_HTML" file="resources\history\side_bar.html" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_SIDE_BAR_JS" file="resources\history\side_bar.js" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_SYNCED_DEVICE_CARD_HTML" file="resources\history\synced_device_card.html" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_SYNCED_DEVICE_CARD_JS" file="resources\history\synced_device_card.js" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_SYNCED_DEVICE_MANAGER_HTML" file="resources\history\synced_device_manager.html" type="BINDATA" />
+            <include name="IDR_MD_HISTORY_SYNCED_DEVICE_MANAGER_JS" file="resources\history\synced_device_manager.js" type="BINDATA" />
           </else>
         </if>
 
diff --git a/chrome/browser/browsing_data/browsing_data_cookie_helper.cc b/chrome/browser/browsing_data/browsing_data_cookie_helper.cc
index f68b053..ac11face 100644
--- a/chrome/browser/browsing_data/browsing_data_cookie_helper.cc
+++ b/chrome/browser/browsing_data/browsing_data_cookie_helper.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/no_destructor.h"
diff --git a/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc
index 134b368..175217b 100644
--- a/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_cookie_helper_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/browsing_data/browsing_data_cookie_helper.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/time/time.h"
 #include "chrome/test/base/testing_profile.h"
diff --git a/chrome/browser/browsing_data/browsing_data_local_storage_helper_unittest.cc b/chrome/browser/browsing_data/browsing_data_local_storage_helper_unittest.cc
index f7639c15..f5ef3efd 100644
--- a/chrome/browser/browsing_data/browsing_data_local_storage_helper_unittest.cc
+++ b/chrome/browser/browsing_data/browsing_data_local_storage_helper_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h"
 
+#include "base/bind_helpers.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/browsing_data/browsing_data_service_worker_helper.cc b/chrome/browser/browsing_data/browsing_data_service_worker_helper.cc
index 5d47892..92add64a 100644
--- a/chrome/browser/browsing_data/browsing_data_service_worker_helper.cc
+++ b/chrome/browser/browsing_data/browsing_data_service_worker_helper.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/location.h"
 #include "base/task/post_task.h"
 #include "chrome/browser/browsing_data/browsing_data_helper.h"
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
index ee7590e..cbfe25d 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -13,6 +13,7 @@
 
 #include "base/barrier_closure.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/callback_helpers.h"
 #include "base/metrics/user_metrics.h"
diff --git a/chrome/browser/browsing_data/cookies_tree_model.cc b/chrome/browser/browsing_data/cookies_tree_model.cc
index 3deb7d5..e53869c 100644
--- a/chrome/browser/browsing_data/cookies_tree_model.cc
+++ b/chrome/browser/browsing_data/cookies_tree_model.cc
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/memory/ptr_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 3af09e5..229b904 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -107,6 +107,7 @@
 #include "chrome/browser/renderer_preferences_util.h"
 #include "chrome/browser/resource_coordinator/background_tab_navigation_throttle.h"
 #include "chrome/browser/resource_coordinator/chrome_browser_main_extra_parts_resource_coordinator.h"
+#include "chrome/browser/resource_coordinator/chrome_content_browser_client_resource_coordinator_part.h"
 #include "chrome/browser/safe_browsing/certificate_reporting_service.h"
 #include "chrome/browser/safe_browsing/certificate_reporting_service_factory.h"
 #include "chrome/browser/safe_browsing/chrome_password_protection_service.h"
@@ -1069,6 +1070,8 @@
   extra_parts_.push_back(new ChromeContentBrowserClientExtensionsPart);
 #endif
 
+  extra_parts_.push_back(new ChromeContentBrowserClientResourceCoordinatorPart);
+
   gpu_binder_registry_.AddInterface(
       base::Bind(&metrics::CallStackProfileCollector::Create));
 }
diff --git a/chrome/browser/chromeos/accessibility/accessibility_manager_browsertest.cc b/chrome/browser/chromeos/accessibility/accessibility_manager_browsertest.cc
index df3533c..90815323 100644
--- a/chrome/browser/chromeos/accessibility/accessibility_manager_browsertest.cc
+++ b/chrome/browser/chromeos/accessibility/accessibility_manager_browsertest.cc
@@ -6,6 +6,7 @@
 
 #include "ash/public/cpp/ash_pref_names.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "chrome/browser/chromeos/login/session/user_session_manager.h"
diff --git a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
index f3236f88..02fb519 100644
--- a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
+++ b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
@@ -11,6 +11,7 @@
 #include "ash/system/status_area_widget.h"
 #include "ash/system/unified/unified_system_tray.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/strings/pattern.h"
diff --git a/chrome/browser/chromeos/android_sms/android_sms_app_manager_impl.cc b/chrome/browser/chromeos/android_sms/android_sms_app_manager_impl.cc
index 7f8ab733..57732ffb 100644
--- a/chrome/browser/chromeos/android_sms/android_sms_app_manager_impl.cc
+++ b/chrome/browser/chromeos/android_sms/android_sms_app_manager_impl.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "chrome/browser/chromeos/android_sms/android_sms_app_setup_controller.h"
 #include "chrome/browser/chromeos/android_sms/android_sms_urls.h"
diff --git a/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc b/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc
index 85effeef..8f93c29 100644
--- a/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc
+++ b/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc
@@ -293,8 +293,8 @@
             &test_url_loader_factory_);
     account_manager->Initialize(
         profile()->GetPath(), test_shared_loader_factory_,
-        base::BindRepeating([](const base::RepeatingClosure& closure) -> void {
-          closure.Run();
+        base::BindRepeating([](base::OnceClosure closure) -> void {
+          std::move(closure).Run();
         }));
     auth_service_->SetURLLoaderFactoryForTesting(test_shared_loader_factory_);
     // It is non-trivial to navigate through the merge session in a testing
diff --git a/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.cc b/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.cc
index 0365d08..df7d2cf6 100644
--- a/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.cc
+++ b/chrome/browser/chromeos/arc/bluetooth/arc_bluetooth_bridge.cc
@@ -15,6 +15,7 @@
 
 #include "ash/public/cpp/ash_pref_names.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/callback_helpers.h"
 #include "base/containers/queue.h"
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.cc b/chrome/browser/chromeos/crostini/crostini_manager.cc
index 8fd76ff..0cd53397 100644
--- a/chrome/browser/chromeos/crostini/crostini_manager.cc
+++ b/chrome/browser/chromeos/crostini/crostini_manager.cc
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/no_destructor.h"
 #include "base/strings/string_split.h"
 #include "base/strings/stringprintf.h"
diff --git a/chrome/browser/chromeos/display/output_protection_delegate.cc b/chrome/browser/chromeos/display/output_protection_delegate.cc
index d72b0c4..01d8e8b 100644
--- a/chrome/browser/chromeos/display/output_protection_delegate.cc
+++ b/chrome/browser/chromeos/display/output_protection_delegate.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/chromeos/display/output_protection_delegate.h"
 
+#include "base/bind_helpers.h"
 #include "chrome/browser/chromeos/display/output_protection_controller_ash.h"
 #include "chrome/browser/chromeos/display/output_protection_controller_mus.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/chromeos/drive/drive_file_stream_reader_unittest.cc b/chrome/browser/chromeos/drive/drive_file_stream_reader_unittest.cc
index 7ba5735c..23155665 100644
--- a/chrome/browser/chromeos/drive/drive_file_stream_reader_unittest.cc
+++ b/chrome/browser/chromeos/drive/drive_file_stream_reader_unittest.cc
@@ -11,6 +11,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/run_loop.h"
diff --git a/chrome/browser/chromeos/drive/drive_integration_service.cc b/chrome/browser/chromeos/drive/drive_integration_service.cc
index 7889040..8c808efe 100644
--- a/chrome/browser/chromeos/drive/drive_integration_service.cc
+++ b/chrome/browser/chromeos/drive/drive_integration_service.cc
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_enumerator.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
diff --git a/chrome/browser/chromeos/drive/write_on_cache_file.cc b/chrome/browser/chromeos/drive/write_on_cache_file.cc
index 2598505..0b32ffad 100644
--- a/chrome/browser/chromeos/drive/write_on_cache_file.cc
+++ b/chrome/browser/chromeos/drive/write_on_cache_file.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/chromeos/drive/write_on_cache_file.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/task/post_task.h"
 #include "components/drive/chromeos/file_system_interface.h"
diff --git a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
index b1b8028..5f0c5de 100644
--- a/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
+++ b/chrome/browser/chromeos/extensions/quick_unlock_private/quick_unlock_private_api_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "ash/public/cpp/ash_pref_names.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/memory/ptr_util.h"
 #include "base/no_destructor.h"
 #include "base/run_loop.h"
diff --git a/chrome/browser/chromeos/file_manager/arc_file_tasks.cc b/chrome/browser/chromeos/file_manager/arc_file_tasks.cc
index d3630873..73e399a5 100644
--- a/chrome/browser/chromeos/file_manager/arc_file_tasks.cc
+++ b/chrome/browser/chromeos/file_manager/arc_file_tasks.cc
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
diff --git a/chrome/browser/chromeos/file_manager/volume_manager.cc b/chrome/browser/chromeos/file_manager/volume_manager.cc
index 2dbe2c29..ea4175c 100644
--- a/chrome/browser/chromeos/file_manager/volume_manager.cc
+++ b/chrome/browser/chromeos/file_manager/volume_manager.cc
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/files/file_path.h"
diff --git a/chrome/browser/chromeos/file_system_provider/provided_file_system.cc b/chrome/browser/chromeos/file_system_provider/provided_file_system.cc
index ccfc7aae..b334141 100644
--- a/chrome/browser/chromeos/file_system_provider/provided_file_system.cc
+++ b/chrome/browser/chromeos/file_system_provider/provided_file_system.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback_helpers.h"
 #include "base/files/file.h"
 #include "base/macros.h"
diff --git a/chrome/browser/chromeos/lock_screen_apps/app_manager_impl_unittest.cc b/chrome/browser/chromeos/lock_screen_apps/app_manager_impl_unittest.cc
index 21830e0..9288b0f3 100644
--- a/chrome/browser/chromeos/lock_screen_apps/app_manager_impl_unittest.cc
+++ b/chrome/browser/chromeos/lock_screen_apps/app_manager_impl_unittest.cc
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/json/json_file_value_serializer.h"
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_resources_unittest.cc b/chrome/browser/chromeos/login/demo_mode/demo_resources_unittest.cc
index d68ad355..519ee79 100644
--- a/chrome/browser/chromeos/login/demo_mode/demo_resources_unittest.cc
+++ b/chrome/browser/chromeos/login/demo_mode/demo_resources_unittest.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "chrome/browser/browser_process.h"
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc
index 170ba29..dcae12b 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/guid.h"
 #include "base/logging.h"
diff --git a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
index b4c73d55..f3e47ea9 100644
--- a/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
+++ b/chrome/browser/chromeos/login/existing_user_controller_browsertest.cc
@@ -17,6 +17,7 @@
 #include "base/run_loop.h"
 #include "base/threading/thread_restrictions.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/chromeos/authpolicy/auth_policy_credentials_manager.h"
 #include "chrome/browser/chromeos/login/existing_user_controller.h"
diff --git a/chrome/browser/chromeos/login/lock/screen_locker.h b/chrome/browser/chromeos/login/lock/screen_locker.h
index 9bfc0d5..0c2ac317 100644
--- a/chrome/browser/chromeos/login/lock/screen_locker.h
+++ b/chrome/browser/chromeos/login/lock/screen_locker.h
@@ -17,6 +17,7 @@
 #include "base/optional.h"
 #include "base/sequenced_task_runner_helpers.h"
 #include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/chromeos/login/help_app_launcher.h"
 #include "chrome/browser/chromeos/login/ui/login_display.h"
 #include "chromeos/login/auth/auth_status_consumer.h"
diff --git a/chrome/browser/chromeos/login/screens/hid_detection_screen.cc b/chrome/browser/chromeos/login/screens/hid_detection_screen.cc
index 21a27f6..124be540 100644
--- a/chrome/browser/chromeos/login/screens/hid_detection_screen.cc
+++ b/chrome/browser/chromeos/login/screens/hid_detection_screen.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/chromeos/login/screens/welcome_screen.cc b/chrome/browser/chromeos/login/screens/welcome_screen.cc
index 2b17a7d..37a8ef1 100644
--- a/chrome/browser/chromeos/login/screens/welcome_screen.cc
+++ b/chrome/browser/chromeos/login/screens/welcome_screen.cc
@@ -8,6 +8,7 @@
 
 #include "ash/public/interfaces/constants.mojom.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
 #include "chrome/browser/browser_process.h"
diff --git a/chrome/browser/chromeos/login/signin_partition_manager.cc b/chrome/browser/chromeos/login/signin_partition_manager.cc
index 8ff242f..43b96cd 100644
--- a/chrome/browser/chromeos/login/signin_partition_manager.cc
+++ b/chrome/browser/chromeos/login/signin_partition_manager.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/chromeos/login/signin_partition_manager.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/guid.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/net/system_network_context_manager.h"
diff --git a/chrome/browser/chromeos/net/delay_network_call.cc b/chrome/browser/chromeos/net/delay_network_call.cc
index ddd9fdd..1982ba62 100644
--- a/chrome/browser/chromeos/net/delay_network_call.cc
+++ b/chrome/browser/chromeos/net/delay_network_call.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/chromeos/net/delay_network_call.h"
 
+#include <utility>
+
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/task/post_task.h"
@@ -18,7 +20,7 @@
 const unsigned chromeos::kDefaultNetworkRetryDelayMS = 3000;
 
 void chromeos::DelayNetworkCall(base::TimeDelta retry,
-                                const base::Closure& callback) {
+                                base::OnceClosure callback) {
   bool delay_network_call = false;
   const NetworkState* default_network =
       NetworkHandler::Get()->network_state_handler()->DefaultNetwork();
@@ -49,8 +51,9 @@
   if (delay_network_call) {
     base::PostDelayedTaskWithTraits(
         FROM_HERE, {content::BrowserThread::UI},
-        base::Bind(&chromeos::DelayNetworkCall, retry, callback), retry);
+        base::BindOnce(&chromeos::DelayNetworkCall, retry, std::move(callback)),
+        retry);
   } else {
-    callback.Run();
+    std::move(callback).Run();
   }
 }
diff --git a/chrome/browser/chromeos/net/delay_network_call.h b/chrome/browser/chromeos/net/delay_network_call.h
index fd2db55..c26739a9 100644
--- a/chrome/browser/chromeos/net/delay_network_call.h
+++ b/chrome/browser/chromeos/net/delay_network_call.h
@@ -21,7 +21,7 @@
 extern const unsigned kDefaultNetworkRetryDelayMS;
 
 // Delay callback until the network is connected or while on a captive portal.
-void DelayNetworkCall(base::TimeDelta retry, const base::Closure& callback);
+void DelayNetworkCall(base::TimeDelta retry, base::OnceClosure callback);
 
 }  // namespace chromeos
 
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl_browsertest.cc b/chrome/browser/chromeos/net/network_portal_detector_impl_browsertest.cc
index ae5488dd..25dbcd1a 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl_browsertest.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl_browsertest.cc
@@ -5,6 +5,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/location.h"
diff --git a/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc b/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
index 0847690a..af62e01 100644
--- a/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
+++ b/chrome/browser/chromeos/net/network_portal_detector_impl_unittest.cc
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/logging.h"
diff --git a/chrome/browser/chromeos/net/wake_on_wifi_connection_observer.cc b/chrome/browser/chromeos/net/wake_on_wifi_connection_observer.cc
index 13e548f1..8e4b4ec 100644
--- a/chrome/browser/chromeos/net/wake_on_wifi_connection_observer.cc
+++ b/chrome/browser/chromeos/net/wake_on_wifi_connection_observer.cc
@@ -4,7 +4,7 @@
 
 #include "chrome/browser/chromeos/net/wake_on_wifi_connection_observer.h"
 
-
+#include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "chrome/browser/chromeos/net/wake_on_wifi_manager.h"
 #include "chrome/browser/gcm/gcm_profile_service_factory.h"
diff --git a/chrome/browser/chromeos/net/wake_on_wifi_manager.cc b/chrome/browser/chromeos/net/wake_on_wifi_manager.cc
index a9fef58..690261c 100644
--- a/chrome/browser/chromeos/net/wake_on_wifi_manager.cc
+++ b/chrome/browser/chromeos/net/wake_on_wifi_manager.cc
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/system/sys_info.h"
diff --git a/chrome/browser/chromeos/night_light/night_light_client_unittest.cc b/chrome/browser/chromeos/night_light/night_light_client_unittest.cc
index 1c83867..cdeda65 100644
--- a/chrome/browser/chromeos/night_light/night_light_client_unittest.cc
+++ b/chrome/browser/chromeos/night_light/night_light_client_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/test/scoped_task_environment.h"
 #include "base/time/clock.h"
 #include "base/time/tick_clock.h"
+#include "base/timer/timer.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/chromeos/oauth2_token_service_delegate_unittest.cc b/chrome/browser/chromeos/oauth2_token_service_delegate_unittest.cc
index fe6095b..2fd9d9d 100644
--- a/chrome/browser/chromeos/oauth2_token_service_delegate_unittest.cc
+++ b/chrome/browser/chromeos/oauth2_token_service_delegate_unittest.cc
@@ -196,7 +196,7 @@
   std::unique_ptr<ChromeOSOAuth2TokenServiceDelegate> delegate_;
   AccountManager::DelayNetworkCallRunner immediate_callback_runner_ =
       base::BindRepeating(
-          [](const base::RepeatingClosure& closure) -> void { closure.Run(); });
+          [](base::OnceClosure closure) -> void { std::move(closure).Run(); });
   sync_preferences::TestingPrefServiceSyncable pref_service_;
   std::unique_ptr<TestSigninClient> client_;
 
diff --git a/chrome/browser/chromeos/policy/display_rotation_default_handler.cc b/chrome/browser/chromeos/policy/display_rotation_default_handler.cc
index ba45d0d..86cc004d 100644
--- a/chrome/browser/chromeos/policy/display_rotation_default_handler.cc
+++ b/chrome/browser/chromeos/policy/display_rotation_default_handler.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/chromeos/policy/display_rotation_default_handler.h"
+#include "base/bind_helpers.h"
 
 #include <utility>
 
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/modeller_impl.h b/chrome/browser/chromeos/power/auto_screen_brightness/modeller_impl.h
index a367194..22ca1fe 100644
--- a/chrome/browser/chromeos/power/auto_screen_brightness/modeller_impl.h
+++ b/chrome/browser/chromeos/power/auto_screen_brightness/modeller_impl.h
@@ -16,6 +16,7 @@
 #include "base/sequenced_task_runner.h"
 #include "base/threading/thread_checker.h"
 #include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/chromeos/power/auto_screen_brightness/als_reader.h"
 #include "chrome/browser/chromeos/power/auto_screen_brightness/als_samples.h"
 #include "chrome/browser/chromeos/power/auto_screen_brightness/brightness_monitor.h"
diff --git a/chrome/browser/chromeos/printing/printer_detector.h b/chrome/browser/chromeos/printing/printer_detector.h
index dc9630b..da8c231 100644
--- a/chrome/browser/chromeos/printing/printer_detector.h
+++ b/chrome/browser/chromeos/printing/printer_detector.h
@@ -34,7 +34,7 @@
     Printer printer;
 
     // Additional metadata used to find a driver.
-    PpdProvider::PrinterSearchData ppd_search_data;
+    PrinterSearchData ppd_search_data;
   };
 
   class Observer {
diff --git a/chrome/browser/chromeos/printing/printer_info.h b/chrome/browser/chromeos/printing/printer_info.h
index df7ca69..35d4dcd7 100644
--- a/chrome/browser/chromeos/printing/printer_info.h
+++ b/chrome/browser/chromeos/printing/printer_info.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_CHROMEOS_PRINTING_PRINTER_INFO_H_
 
 #include <string>
+#include <vector>
 
 #include "base/callback_forward.h"
 
@@ -21,6 +22,7 @@
                         const std::string& make,
                         const std::string& model,
                         const std::string& make_and_model,
+                        const std::vector<std::string>& document_formats,
                         bool autoconf)>;
 
 // Dispatch an IPP request to |host| on |port| for |path| to obtain
diff --git a/chrome/browser/chromeos/printing/printer_info_cups.cc b/chrome/browser/chromeos/printing/printer_info_cups.cc
index 169feb1..d21d0172 100644
--- a/chrome/browser/chromeos/printing/printer_info_cups.cc
+++ b/chrome/browser/chromeos/printing/printer_info_cups.cc
@@ -98,7 +98,7 @@
                       std::unique_ptr<::printing::PrinterInfo> info) {
   if (!info) {
     VLOG(1) << "Could not reach printer";
-    callback.Run(false, std::string(), std::string(), std::string(), false);
+    callback.Run(false, std::string(), std::string(), std::string(), {}, false);
     return;
   }
 
@@ -116,7 +116,7 @@
   }
 
   callback.Run(true, make.as_string(), model.as_string(), info->make_and_model,
-               IsAutoconf(*info));
+               info->document_formats, IsAutoconf(*info));
 }
 
 }  // namespace
diff --git a/chrome/browser/chromeos/printing/printer_info_stub.cc b/chrome/browser/chromeos/printing/printer_info_stub.cc
index fb5a5fa..66ccd18 100644
--- a/chrome/browser/chromeos/printing/printer_info_stub.cc
+++ b/chrome/browser/chromeos/printing/printer_info_stub.cc
@@ -18,7 +18,8 @@
   DCHECK(!host.empty());
 
   base::PostTask(FROM_HERE,
-                 base::Bind(callback, false, "Foo", "Bar", "Foo Bar", false));
+                 base::BindOnce(callback, false, "Foo", "Bar", "Foo Bar",
+                                std::vector<std::string>{}, false));
 }
 
 }  // namespace chromeos
diff --git a/chrome/browser/chromeos/printing/usb_printer_detector.cc b/chrome/browser/chromeos/printing/usb_printer_detector.cc
index 2a6b3e1..d6142ae 100644
--- a/chrome/browser/chromeos/printing/usb_printer_detector.cc
+++ b/chrome/browser/chromeos/printing/usb_printer_detector.cc
@@ -39,9 +39,11 @@
 
 // Given a usb device, guesses the make and model for a driver lookup.
 //
-// TODO(justincarlson): Possibly go deeper and query the IEEE1284 fields
-// for make and model if we determine those are more likely to contain
+// TODO(https://crbug.com/895037): Possibly go deeper and query the IEEE1284
+// fields for make and model if we determine those are more likely to contain
 // what we want.  Strings currently come from udev.
+// TODO(https://crbug.com/895037): When above is added, parse out document
+// formats and add to DetectedPrinter
 std::string GuessEffectiveMakeAndModel(const device::UsbDevice& device) {
   return base::UTF16ToUTF8(device.manufacturer_string()) + " " +
          base::UTF16ToUTF8(device.product_string());
@@ -118,6 +120,9 @@
     entry.ppd_search_data.usb_product_id = device->product_id();
     entry.ppd_search_data.make_and_model.push_back(
         GuessEffectiveMakeAndModel(*device));
+    entry.ppd_search_data.discovery_type =
+        PrinterSearchData::PrinterDiscoveryType::kUsb;
+    // TODO(https://crbug.com/895037): Add in command set from IEEE1284
 
     base::AutoLock auto_lock(printers_lock_);
     printers_[device->guid()] = entry;
diff --git a/chrome/browser/chromeos/printing/zeroconf_printer_detector.cc b/chrome/browser/chromeos/printing/zeroconf_printer_detector.cc
index b7078ec..8dad42f5 100644
--- a/chrome/browser/chromeos/printing/zeroconf_printer_detector.cc
+++ b/chrome/browser/chromeos/printing/zeroconf_printer_detector.cc
@@ -12,6 +12,8 @@
 #include "base/md5.h"
 #include "base/observer_list_threadsafe.h"
 #include "base/stl_util.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/synchronization/lock.h"
 #include "chrome/browser/local_discovery/service_discovery_device_lister.h"
@@ -178,6 +180,8 @@
       base::StringPiece(service_type).ends_with(",_print");
 
   // gather ppd identification candidates.
+  detected_printer->ppd_search_data.discovery_type =
+      PrinterSearchData::PrinterDiscoveryType::kZeroconf;
   if (!metadata.ty.empty()) {
     detected_printer->ppd_search_data.make_and_model.push_back(metadata.ty);
   }
@@ -190,6 +194,22 @@
         base::StringPrintf("%s %s", metadata.usb_MFG.c_str(),
                            metadata.usb_MDL.c_str()));
   }
+  if (!metadata.pdl.empty()) {
+    // Per Bonjour Printer Spec v1.2 section 9.2.8, it is invalid for the pdl to
+    // end with a comma.
+    auto media_types = base::SplitString(
+        metadata.pdl, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+    if (!media_types.empty() && !media_types.back().empty()) {
+      // Prune any empty splits.
+      base::EraseIf(media_types, [](base::StringPiece s) { return s.empty(); });
+
+      std::transform(
+          media_types.begin(), media_types.end(),
+          std::back_inserter(
+              detected_printer->ppd_search_data.supported_document_formats),
+          [](base::StringPiece s) { return base::ToLowerASCII(s); });
+    }
+  }
   return true;
 }
 
diff --git a/chrome/browser/chromeos/smb_client/discovery/netbios_host_locator_unittest.cc b/chrome/browser/chromeos/smb_client/discovery/netbios_host_locator_unittest.cc
index 42773da..92e031b 100644
--- a/chrome/browser/chromeos/smb_client/discovery/netbios_host_locator_unittest.cc
+++ b/chrome/browser/chromeos/smb_client/discovery/netbios_host_locator_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "base/test/test_mock_time_task_runner.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/chromeos/smb_client/discovery/fake_netbios_client.h"
 #include "chrome/browser/chromeos/smb_client/smb_constants.h"
 #include "chromeos/dbus/fake_smb_provider_client.h"
diff --git a/chrome/browser/chromeos/smb_client/smb_file_system.cc b/chrome/browser/chromeos/smb_client/smb_file_system.cc
index c9b9b57d..93fc68ed 100644
--- a/chrome/browser/chromeos/smb_client/smb_file_system.cc
+++ b/chrome/browser/chromeos/smb_client/smb_file_system.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/posix/eintr_wrapper.h"
 #include "base/task/post_task.h"
diff --git a/chrome/browser/devtools/device/devtools_android_bridge.cc b/chrome/browser/devtools/device/devtools_android_bridge.cc
index 9df4c43..93df077 100644
--- a/chrome/browser/devtools/device/devtools_android_bridge.cc
+++ b/chrome/browser/devtools/device/devtools_android_bridge.cc
@@ -13,6 +13,7 @@
 
 #include "base/base64.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/json/json_reader.h"
diff --git a/chrome/browser/devtools/device/devtools_device_discovery.cc b/chrome/browser/devtools/device/devtools_device_discovery.cc
index a34e88b..a9b2b11 100644
--- a/chrome/browser/devtools/device/devtools_device_discovery.cc
+++ b/chrome/browser/devtools/device/devtools_device_discovery.cc
@@ -7,6 +7,7 @@
 #include <map>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/json/json_reader.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/user_metrics.h"
diff --git a/chrome/browser/devtools/devtools_browser_context_manager.cc b/chrome/browser/devtools/devtools_browser_context_manager.cc
index 92b0f559..d3f5253 100644
--- a/chrome/browser/devtools/devtools_browser_context_manager.cc
+++ b/chrome/browser/devtools/devtools_browser_context_manager.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/devtools/devtools_browser_context_manager.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
diff --git a/chrome/browser/devtools/protocol/cast_handler_unittest.cc b/chrome/browser/devtools/protocol/cast_handler_unittest.cc
index 9b825b9..7e9ec8a8 100644
--- a/chrome/browser/devtools/protocol/cast_handler_unittest.cc
+++ b/chrome/browser/devtools/protocol/cast_handler_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/devtools/protocol/cast_handler.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "chrome/browser/media/router/media_router_factory.h"
 #include "chrome/browser/media/router/media_sinks_observer.h"
 #include "chrome/browser/media/router/test/mock_media_router.h"
diff --git a/chrome/browser/download/chrome_download_manager_delegate_unittest.cc b/chrome/browser/download/chrome_download_manager_delegate_unittest.cc
index 769c7c3..8908c76 100644
--- a/chrome/browser/download/chrome_download_manager_delegate_unittest.cc
+++ b/chrome/browser/download/chrome_download_manager_delegate_unittest.cc
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
diff --git a/chrome/browser/download/download_path_reservation_tracker_unittest.cc b/chrome/browser/download/download_path_reservation_tracker_unittest.cc
index 7da9207..1d3cd925 100644
--- a/chrome/browser/download/download_path_reservation_tracker_unittest.cc
+++ b/chrome/browser/download/download_path_reservation_tracker_unittest.cc
@@ -44,7 +44,7 @@
   void SetUp() override;
   void TearDown() override;
 
-  MockDownloadItem* CreateDownloadItem(int32_t id);
+  std::unique_ptr<MockDownloadItem> CreateDownloadItem(int32_t id);
   base::FilePath GetPathInDownloadsDirectory(
       const base::FilePath::CharType* suffix);
   bool IsPathInUse(const base::FilePath& path);
@@ -91,9 +91,9 @@
   content::RunAllTasksUntilIdle();
 }
 
-MockDownloadItem* DownloadPathReservationTrackerTest::CreateDownloadItem(
-    int32_t id) {
-  MockDownloadItem* item = new ::testing::StrictMock<MockDownloadItem>;
+std::unique_ptr<MockDownloadItem>
+DownloadPathReservationTrackerTest::CreateDownloadItem(int32_t id) {
+  auto item = std::make_unique<::testing::StrictMock<MockDownloadItem>>();
   EXPECT_CALL(*item, GetId())
       .WillRepeatedly(Return(id));
   EXPECT_CALL(*item, GetTargetFilePath())
@@ -180,7 +180,7 @@
 
 // A basic reservation is acquired and committed.
 TEST_F(DownloadPathReservationTrackerTest, BasicReservation) {
-  std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1));
+  std::unique_ptr<MockDownloadItem> item = CreateDownloadItem(1);
   base::FilePath path(
       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
   ASSERT_FALSE(IsPathInUse(path));
@@ -205,7 +205,7 @@
 
 // A download that is interrupted should lose its reservation.
 TEST_F(DownloadPathReservationTrackerTest, InterruptedDownload) {
-  std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1));
+  std::unique_ptr<MockDownloadItem> item = CreateDownloadItem(1);
   base::FilePath path(
       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
   ASSERT_FALSE(IsPathInUse(path));
@@ -229,7 +229,7 @@
 
 // A completed download should also lose its reservation.
 TEST_F(DownloadPathReservationTrackerTest, CompleteDownload) {
-  std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1));
+  std::unique_ptr<MockDownloadItem> item = CreateDownloadItem(1);
   base::FilePath path(
       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
   ASSERT_FALSE(IsPathInUse(path));
@@ -257,7 +257,7 @@
 // If there are files on the file system, a unique reservation should uniquify
 // around it.
 TEST_F(DownloadPathReservationTrackerTest, ConflictingFiles) {
-  std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1));
+  std::unique_ptr<MockDownloadItem> item = CreateDownloadItem(1);
   base::FilePath path(
       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
   base::FilePath path1(
@@ -295,7 +295,7 @@
 // If there are conflicting files on the file system, an overwriting reservation
 // should succeed without altering the target path.
 TEST_F(DownloadPathReservationTrackerTest, ConflictingFiles_Overwrite) {
-  std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1));
+  std::unique_ptr<MockDownloadItem> item = CreateDownloadItem(1);
   base::FilePath path(
       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
   // Create a file at |path|.
@@ -322,7 +322,7 @@
 // If the source is a file:// URL that is in the download directory, then Chrome
 // could download the file onto itself. Test that this is flagged by DPRT.
 TEST_F(DownloadPathReservationTrackerTest, ConflictWithSource) {
-  std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1));
+  std::unique_ptr<MockDownloadItem> item = CreateDownloadItem(1);
   base::FilePath path(
       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
   ASSERT_EQ(0, base::WriteFile(path, "", 0));
@@ -346,7 +346,7 @@
 
 // Multiple reservations for the same path should uniquify around each other.
 TEST_F(DownloadPathReservationTrackerTest, ConflictingReservations) {
-  std::unique_ptr<MockDownloadItem> item1(CreateDownloadItem(1));
+  std::unique_ptr<MockDownloadItem> item1 = CreateDownloadItem(1);
   base::FilePath path(
       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
   base::FilePath uniquified_path(
@@ -368,7 +368,7 @@
   {
     // Requesting a reservation for the same path with uniquification results in
     // a uniquified path.
-    std::unique_ptr<MockDownloadItem> item2(CreateDownloadItem(2));
+    std::unique_ptr<MockDownloadItem> item2 = CreateDownloadItem(2);
     base::FilePath reserved_path2;
     CallGetReservedPath(item2.get(), path, create_directory, conflict_action,
                         &reserved_path2, &result);
@@ -384,7 +384,7 @@
   {
     // Since the previous download item was removed, requesting a reservation
     // for the same path should result in the same uniquified path.
-    std::unique_ptr<MockDownloadItem> item2(CreateDownloadItem(2));
+    std::unique_ptr<MockDownloadItem> item2 = CreateDownloadItem(2);
     base::FilePath reserved_path2;
     CallGetReservedPath(item2.get(), path, create_directory, conflict_action,
                         &reserved_path2, &result);
@@ -397,7 +397,7 @@
 
   // Now acquire an overwriting reservation. We should end up with the same
   // non-uniquified path for both reservations.
-  std::unique_ptr<MockDownloadItem> item3(CreateDownloadItem(2));
+  std::unique_ptr<MockDownloadItem> item3 = CreateDownloadItem(2);
   base::FilePath reserved_path3;
   conflict_action = DownloadPathReservationTracker::OVERWRITE;
   CallGetReservedPath(item3.get(), path, create_directory, conflict_action,
@@ -415,8 +415,8 @@
 // Two active downloads shouldn't be able to reserve paths that only differ by
 // case.
 TEST_F(DownloadPathReservationTrackerTest, ConflictingCaseReservations) {
-  std::unique_ptr<MockDownloadItem> item1(CreateDownloadItem(1));
-  std::unique_ptr<MockDownloadItem> item2(CreateDownloadItem(2));
+  std::unique_ptr<MockDownloadItem> item1 = CreateDownloadItem(1);
+  std::unique_ptr<MockDownloadItem> item2 = CreateDownloadItem(2);
 
   base::FilePath path_foo =
       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt"));
@@ -479,7 +479,7 @@
       expected_path =
           path.InsertBeforeExtensionASCII(" - 2019-01-23T163530.020");
     }
-    items[i].reset(CreateDownloadItem(i));
+    items[i] = CreateDownloadItem(i);
     EXPECT_FALSE(IsPathInUse(expected_path));
     CallGetReservedPath(items[i].get(), path, create_directory, conflict_action,
                         &reserved_path, &result);
@@ -488,8 +488,8 @@
     EXPECT_EQ(PathValidationResult::SUCCESS, result);
   }
   // The next reservation for |path| will fail to be unique.
-  std::unique_ptr<MockDownloadItem> item(
-      CreateDownloadItem(DownloadPathReservationTracker::kMaxUniqueFiles + 2));
+  std::unique_ptr<MockDownloadItem> item =
+      CreateDownloadItem(DownloadPathReservationTracker::kMaxUniqueFiles + 2);
   base::FilePath reserved_path;
   PathValidationResult result = PathValidationResult::NAME_TOO_LONG;
   CallGetReservedPath(item.get(), path, create_directory, conflict_action,
@@ -505,7 +505,7 @@
 // If the target directory is unwriteable, then callback should be notified that
 // verification failed.
 TEST_F(DownloadPathReservationTrackerTest, UnwriteableDirectory) {
-  std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1));
+  std::unique_ptr<MockDownloadItem> item = CreateDownloadItem(1);
   base::FilePath path(
       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
   base::FilePath dir(path.DirName());
@@ -541,7 +541,7 @@
   bool create_directory = false;
 
   {
-    std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1));
+    std::unique_ptr<MockDownloadItem> item = CreateDownloadItem(1);
     base::FilePath reserved_path;
     PathValidationResult result = PathValidationResult::NAME_TOO_LONG;
     CallGetReservedPath(item.get(), path, create_directory, conflict_action,
@@ -552,7 +552,7 @@
   }
   ASSERT_FALSE(IsPathInUse(path));
   {
-    std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1));
+    std::unique_ptr<MockDownloadItem> item = CreateDownloadItem(1);
     base::FilePath reserved_path;
     PathValidationResult result = PathValidationResult::NAME_TOO_LONG;
     set_default_download_path(dir);
@@ -568,7 +568,7 @@
 // If the target path of the download item changes, the reservation should be
 // updated to match.
 TEST_F(DownloadPathReservationTrackerTest, UpdatesToTargetPath) {
-  std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1));
+  std::unique_ptr<MockDownloadItem> item = CreateDownloadItem(1);
   base::FilePath path(
       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
   ASSERT_FALSE(IsPathInUse(path));
@@ -626,7 +626,7 @@
   const size_t max_length = real_max_length - 11;
 #endif  // defined(OS_WIN)
 
-  std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1));
+  std::unique_ptr<MockDownloadItem> item = CreateDownloadItem(1);
   base::FilePath path(GetLongNamePathInDownloadsDirectory(
       max_length, FILE_PATH_LITERAL(".txt")));
   ASSERT_FALSE(IsPathInUse(path));
@@ -657,7 +657,7 @@
   const size_t max_length = real_max_length - 11;
 #endif  // defined(OS_WIN)
 
-  std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1));
+  std::unique_ptr<MockDownloadItem> item = CreateDownloadItem(1);
   base::FilePath path(GetLongNamePathInDownloadsDirectory(
       max_length, FILE_PATH_LITERAL(".txt")));
   base::FilePath path0(GetLongNamePathInDownloadsDirectory(
@@ -696,7 +696,7 @@
   const size_t max_length = real_max_length - 11;
 #endif  // defined(OS_WIN)
 
-  std::unique_ptr<MockDownloadItem> item(CreateDownloadItem(1));
+  std::unique_ptr<MockDownloadItem> item = CreateDownloadItem(1);
   base::FilePath path(GetPathInDownloadsDirectory(
       (FILE_PATH_LITERAL("a.") +
           base::FilePath::StringType(max_length, 'b')).c_str()));
diff --git a/chrome/browser/download/download_prefs.cc b/chrome/browser/download/download_prefs.cc
index cd6f9c1..84ce429 100644
--- a/chrome/browser/download/download_prefs.cc
+++ b/chrome/browser/download/download_prefs.cc
@@ -305,7 +305,7 @@
 
 bool DownloadPrefs::IsFromTrustedSource(const download::DownloadItem& item) {
   if (!trusted_sources_manager_)
-    trusted_sources_manager_.reset(TrustedSourcesManager::Create());
+    trusted_sources_manager_ = TrustedSourcesManager::Create();
   return trusted_sources_manager_->IsFromTrustedSource(item.GetURL());
 }
 
diff --git a/chrome/browser/download/trusted_sources_manager.h b/chrome/browser/download/trusted_sources_manager.h
index 62a9aa6..99c5075 100644
--- a/chrome/browser/download/trusted_sources_manager.h
+++ b/chrome/browser/download/trusted_sources_manager.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_DOWNLOAD_TRUSTED_SOURCES_MANAGER_H_
 #define CHROME_BROWSER_DOWNLOAD_TRUSTED_SOURCES_MANAGER_H_
 
+#include <memory>
+
 #include "base/macros.h"
 #include "net/proxy_resolution/proxy_bypass_rules.h"
 
@@ -29,7 +31,7 @@
   // the security zone mapping is used instead to determine whether the source
   // is trusted or not.
   //
-  static TrustedSourcesManager* Create();
+  static std::unique_ptr<TrustedSourcesManager> Create();
 
   // Returns true if the source of this URL is part of the trusted sources.
   virtual bool IsFromTrustedSource(const GURL& url) const;
diff --git a/chrome/browser/download/trusted_sources_manager_posix.cc b/chrome/browser/download/trusted_sources_manager_posix.cc
index 0c0adab..cd8f2b97 100644
--- a/chrome/browser/download/trusted_sources_manager_posix.cc
+++ b/chrome/browser/download/trusted_sources_manager_posix.cc
@@ -4,7 +4,9 @@
 
 #include "chrome/browser/download/trusted_sources_manager.h"
 
+#include "base/memory/ptr_util.h"
+
 // static
-TrustedSourcesManager* TrustedSourcesManager::Create() {
-  return new TrustedSourcesManager;
+std::unique_ptr<TrustedSourcesManager> TrustedSourcesManager::Create() {
+  return base::WrapUnique(new TrustedSourcesManager);
 }
diff --git a/chrome/browser/download/trusted_sources_manager_win.cc b/chrome/browser/download/trusted_sources_manager_win.cc
index 95254447..d88d096 100644
--- a/chrome/browser/download/trusted_sources_manager_win.cc
+++ b/chrome/browser/download/trusted_sources_manager_win.cc
@@ -8,6 +8,7 @@
 #include <wrl/client.h>
 
 #include "base/logging.h"
+#include "base/memory/ptr_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "url/gurl.h"
@@ -49,6 +50,6 @@
 }  // namespace
 
 // static
-TrustedSourcesManager* TrustedSourcesManager::Create() {
-  return new TrustedSourcesManagerWin;
+std::unique_ptr<TrustedSourcesManager> TrustedSourcesManager::Create() {
+  return base::WrapUnique(new TrustedSourcesManagerWin);
 }
diff --git a/chrome/browser/engagement/site_engagement_service_unittest.cc b/chrome/browser/engagement/site_engagement_service_unittest.cc
index fd7452ab..90d2dc0 100644
--- a/chrome/browser/engagement/site_engagement_service_unittest.cc
+++ b/chrome/browser/engagement/site_engagement_service_unittest.cc
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
diff --git a/chrome/browser/extensions/activity_log/counting_policy_unittest.cc b/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
index 6cf08741..0c69032 100644
--- a/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
+++ b/chrome/browser/extensions/activity_log/counting_policy_unittest.cc
@@ -11,6 +11,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/cancelable_callback.h"
 #include "base/command_line.h"
 #include "base/location.h"
diff --git a/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc b/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
index f432e69..f9d8a61 100644
--- a/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
+++ b/chrome/browser/extensions/activity_log/fullstream_ui_policy_unittest.cc
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/cancelable_callback.h"
 #include "base/command_line.h"
 #include "base/location.h"
diff --git a/chrome/browser/extensions/api/chrome_extensions_api_client.cc b/chrome/browser/extensions/api/chrome_extensions_api_client.cc
index 80d9228..25e9e3ee 100644
--- a/chrome/browser/extensions/api/chrome_extensions_api_client.cc
+++ b/chrome/browser/extensions/api/chrome_extensions_api_client.cc
@@ -93,8 +93,7 @@
   printing::InitializePrinting(web_contents);
 #endif
   pdf::PDFWebContentsHelper::CreateForWebContentsWithClient(
-      web_contents, std::unique_ptr<pdf::PDFWebContentsHelperClient>(
-                        new ChromePDFWebContentsHelperClient()));
+      web_contents, std::make_unique<ChromePDFWebContentsHelperClient>());
 
   data_use_measurement::DataUseWebContentsObserver::CreateForWebContents(
       web_contents);
diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc b/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
index 075f13ca..ddbb015 100644
--- a/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
+++ b/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback_helpers.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/json/json_writer.h"
diff --git a/chrome/browser/extensions/api/image_writer_private/operation_unittest.cc b/chrome/browser/extensions/api/image_writer_private/operation_unittest.cc
index 745dc4d6..4cb1802 100644
--- a/chrome/browser/extensions/api/image_writer_private/operation_unittest.cc
+++ b/chrome/browser/extensions/api/image_writer_private/operation_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/extensions/api/image_writer_private/operation.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/run_loop.h"
diff --git a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
index 74398ec..9af3032 100644
--- a/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
+++ b/chrome/browser/extensions/api/networking_private/networking_private_chromeos_apitest.cc
@@ -6,6 +6,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/macros.h"
diff --git a/chrome/browser/extensions/api/sessions/sessions_apitest.cc b/chrome/browser/extensions/api/sessions/sessions_apitest.cc
index c3fd522..9d498a0c 100644
--- a/chrome/browser/extensions/api/sessions/sessions_apitest.cc
+++ b/chrome/browser/extensions/api/sessions/sessions_apitest.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
 #include "base/path_service.h"
diff --git a/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc b/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc
index 4826c309..c0830fac 100644
--- a/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc
+++ b/chrome/browser/extensions/api/vpn_provider/vpn_provider_apitest.cc
@@ -6,6 +6,7 @@
 #include <stdint.h>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/memory/ptr_util.h"
 #include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
diff --git a/chrome/browser/extensions/shared_worker_apitest.cc b/chrome/browser/extensions/shared_worker_apitest.cc
index 40b8eb16..34919b2 100644
--- a/chrome/browser/extensions/shared_worker_apitest.cc
+++ b/chrome/browser/extensions/shared_worker_apitest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/bind_helpers.h"
 #include "base/files/file_path.h"
 #include "chrome/browser/extensions/extension_apitest.h"
 #include "extensions/browser/extension_host.h"
diff --git a/chrome/browser/extensions/updater/local_extension_cache.cc b/chrome/browser/extensions/updater/local_extension_cache.cc
index 2970e22..a70b012 100644
--- a/chrome/browser/extensions/updater/local_extension_cache.cc
+++ b/chrome/browser/extensions/updater/local_extension_cache.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/extensions/updater/local_extension_cache.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file.h"
 #include "base/files/file_enumerator.h"
 #include "base/files/file_util.h"
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index aef8a70f..6923bf5 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -154,15 +154,11 @@
   {
     "name": "ash-debug-shortcuts",
     "owners": [ "//ash/OWNERS" ],
-    // Used by developers for debugging.
+    // Used by developers for debugging and to dump extra information to logs
+    // in official builds.
     "expiry_milestone": -1
   },
   {
-    "name": "ash-disable-login-dim-and-blur",
-    // "owners": [ "your-team" ],
-    "expiry_milestone": 76
-  },
-  {
     "name": "ash-enable-docked-magnifier",
     // "owners": [ "your-team" ],
     "expiry_milestone": 76
@@ -189,8 +185,10 @@
   },
   {
     "name": "ash-enable-unified-desktop",
-    // "owners": [ "your-team" ],
-    "expiry_milestone": 76
+    "owners": [ "//ash/OWNERS" ],
+    // Unified desktop can be enabled by enterprise policy. The switch exists in
+    // about:flags so QA can more easily test the feature.
+    "expiry_milestone": -1
   },
   {
     "name": "ash-shelf-color",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index c01bae7..d8bf89c 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1722,11 +1722,6 @@
     "Use committed error pages instead of transient navigation entries for "
     "supervised user interstitials";
 
-const char kEnableDrawOcclusionName[] = "Enable draw occlusion";
-const char kEnableDrawOcclusionDescription[] =
-    "Enable the system to use draw occlusion to skip draw quads when they are "
-    "not shown on the screen.";
-
 const char kShowSavedCopyName[] = "Show Saved Copy Button";
 const char kShowSavedCopyDescription[] =
     "When a page fails to load, if a stale copy of the page exists in the "
diff --git a/chrome/browser/gpu/gpu_mode_manager.cc b/chrome/browser/gpu/gpu_mode_manager.cc
index a52294dd..19bb596f 100644
--- a/chrome/browser/gpu/gpu_mode_manager.cc
+++ b/chrome/browser/gpu/gpu_mode_manager.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/gpu/gpu_mode_manager.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
 #include "chrome/browser/browser_process.h"
diff --git a/chrome/browser/installable/installable_manager.cc b/chrome/browser/installable/installable_manager.cc
index f4f34d32..20a20c53 100644
--- a/chrome/browser/installable/installable_manager.cc
+++ b/chrome/browser/installable/installable_manager.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/installable/installable_manager.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "build/build_config.h"
diff --git a/chrome/browser/media/android/remote/remote_media_player_bridge.cc b/chrome/browser/media/android/remote/remote_media_player_bridge.cc
index b481661a..1792109 100644
--- a/chrome/browser/media/android/remote/remote_media_player_bridge.cc
+++ b/chrome/browser/media/android/remote/remote_media_player_bridge.cc
@@ -9,6 +9,7 @@
 #include "base/android/jni_android.h"
 #include "base/android/jni_string.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "chrome/browser/media/android/remote/remote_media_player_manager.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
diff --git a/chrome/browser/media/android/router/media_router_android_unittest.cc b/chrome/browser/media/android/router/media_router_android_unittest.cc
index c37c29c0..107552c6 100644
--- a/chrome/browser/media/android/router/media_router_android_unittest.cc
+++ b/chrome/browser/media/android/router/media_router_android_unittest.cc
@@ -4,6 +4,7 @@
 
 #include <memory>
 
+#include "base/bind_helpers.h"
 #include "base/test/mock_callback.h"
 #include "chrome/browser/media/android/router/media_router_android.h"
 #include "chrome/browser/media/android/router/media_router_android_bridge.h"
diff --git a/chrome/browser/media/media_engagement_browsertest.cc b/chrome/browser/media/media_engagement_browsertest.cc
index f7f8b71..ee14e55 100644
--- a/chrome/browser/media/media_engagement_browsertest.cc
+++ b/chrome/browser/media/media_engagement_browsertest.cc
@@ -10,6 +10,7 @@
 #include "base/test/simple_test_clock.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/component_updater/mei_preload_component_installer.h"
 #include "chrome/browser/media/media_engagement_contents_observer.h"
diff --git a/chrome/browser/media/media_engagement_service_unittest.cc b/chrome/browser/media/media_engagement_service_unittest.cc
index 55f3452..3303ff1 100644
--- a/chrome/browser/media/media_engagement_service_unittest.cc
+++ b/chrome/browser/media/media_engagement_service_unittest.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
diff --git a/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer.cc b/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer.cc
index 5b9768a..c488d6db 100644
--- a/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer.cc
+++ b/chrome/browser/media/router/discovery/discovery_network_monitor_metric_observer.cc
@@ -6,6 +6,7 @@
 #include "net/base/network_change_notifier.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "content/public/browser/network_service_instance.h"
 #include "services/network/public/cpp/network_connection_tracker.h"
 
diff --git a/chrome/browser/media/router/providers/dial/dial_media_route_provider.cc b/chrome/browser/media/router/providers/dial/dial_media_route_provider.cc
index 23f4af3..d5f56216 100644
--- a/chrome/browser/media/router/providers/dial/dial_media_route_provider.cc
+++ b/chrome/browser/media/router/providers/dial/dial_media_route_provider.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/containers/flat_map.h"
 #include "base/no_destructor.h"
 #include "base/stl_util.h"
diff --git a/chrome/browser/media/router/providers/dial/dial_media_route_provider_unittest.cc b/chrome/browser/media/router/providers/dial/dial_media_route_provider_unittest.cc
index eadf3cd..5b988f14 100644
--- a/chrome/browser/media/router/providers/dial/dial_media_route_provider_unittest.cc
+++ b/chrome/browser/media/router/providers/dial/dial_media_route_provider_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/media/router/providers/dial/dial_media_route_provider.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "chrome/browser/media/router/test/mock_mojo_media_router.h"
 
 #include "base/run_loop.h"
diff --git a/chrome/browser/media/webrtc/tab_desktop_media_list.cc b/chrome/browser/media/webrtc/tab_desktop_media_list.cc
index c4b338687..56f37e0 100644
--- a/chrome/browser/media/webrtc/tab_desktop_media_list.cc
+++ b/chrome/browser/media/webrtc/tab_desktop_media_list.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/media/webrtc/tab_desktop_media_list.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/hash.h"
 #include "base/task/post_task.h"
 #include "chrome/browser/profiles/profile_manager.h"
diff --git a/chrome/browser/media/webrtc/webrtc_event_log_manager.cc b/chrome/browser/media/webrtc/webrtc_event_log_manager.cc
index 4d134108..d060805 100644
--- a/chrome/browser/media/webrtc/webrtc_event_log_manager.cc
+++ b/chrome/browser/media/webrtc/webrtc_event_log_manager.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/media/webrtc/webrtc_event_log_manager.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/task/post_task.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
diff --git a/chrome/browser/media/webrtc/webrtc_rtp_dump_handler.cc b/chrome/browser/media/webrtc/webrtc_rtp_dump_handler.cc
index 31a079a7..98b5191 100644
--- a/chrome/browser/media/webrtc/webrtc_rtp_dump_handler.cc
+++ b/chrome/browser/media/webrtc/webrtc_rtp_dump_handler.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/strings/string_number_conversions.h"
diff --git a/chrome/browser/media_galleries/chromeos/mtp_device_task_helper.cc b/chrome/browser/media_galleries/chromeos/mtp_device_task_helper.cc
index 1a6035e0..0fbc939 100644
--- a/chrome/browser/media_galleries/chromeos/mtp_device_task_helper.cc
+++ b/chrome/browser/media_galleries/chromeos/mtp_device_task_helper.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "base/task/post_task.h"
 #include "chrome/browser/media_galleries/chromeos/mtp_device_object_enumerator.h"
diff --git a/chrome/browser/metrics/antivirus_metrics_provider_win_unittest.cc b/chrome/browser/metrics/antivirus_metrics_provider_win_unittest.cc
index 5c80bf6..22ecdf8e 100644
--- a/chrome/browser/metrics/antivirus_metrics_provider_win_unittest.cc
+++ b/chrome/browser/metrics/antivirus_metrics_provider_win_unittest.cc
@@ -29,16 +29,26 @@
 
 void VerifySystemProfileData(const metrics::SystemProfileProto& system_profile,
                              bool expect_unhashed_value) {
-  const char kWindowsDefender[] = "Windows Defender";
+  if (base::win::GetVersion() < base::win::VERSION_WIN8)
+    return;
+
+  // The name of Windows Defender changed sometime in Windows 10, so any of the following is
+  // possible.
+  constexpr char kWindowsDefender[] = "Windows Defender";
+  constexpr char kWindowsDefenderAntivirus[] = "Windows Defender Antivirus";
 
   if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
     bool defender_found = false;
     for (const auto& av : system_profile.antivirus_product()) {
-      if (av.product_name_hash() == variations::HashName(kWindowsDefender)) {
+      if (av.product_name_hash() ==
+          variations::HashName(kWindowsDefender) ||
+          av.product_name_hash() ==
+          variations::HashName(kWindowsDefenderAntivirus)) {
         defender_found = true;
         if (expect_unhashed_value) {
           EXPECT_TRUE(av.has_product_name());
-          EXPECT_EQ(kWindowsDefender, av.product_name());
+          EXPECT_TRUE(av.product_name() == kWindowsDefender ||
+                      av.product_name() == kWindowsDefenderAntivirus);
         } else {
           EXPECT_FALSE(av.has_product_name());
         }
@@ -103,8 +113,7 @@
   DISALLOW_COPY_AND_ASSIGN(AntiVirusMetricsProviderTest);
 };
 
-// TODO(crbug.com/682286): Flaky on windows 10.
-TEST_P(AntiVirusMetricsProviderTest, DISABLED_GetMetricsFullName) {
+TEST_P(AntiVirusMetricsProviderTest, GetMetricsFullName) {
   ASSERT_TRUE(thread_checker_.CalledOnValidThread());
   base::HistogramTester histograms;
   SetFullNamesFeatureEnabled(expect_unhashed_value_);
diff --git a/chrome/browser/net/network_context_configuration_browsertest.cc b/chrome/browser/net/network_context_configuration_browsertest.cc
index ec2449f..8c69d6e 100644
--- a/chrome/browser/net/network_context_configuration_browsertest.cc
+++ b/chrome/browser/net/network_context_configuration_browsertest.cc
@@ -1191,9 +1191,7 @@
   EXPECT_EQ(net::ERR_SSL_VERSION_OR_CIPHER_MISMATCH, simple_loader->NetError());
 }
 
-// Flaky on several platforms: https://crbug.com/922876
-IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest,
-                       DISABLED_ProxyConfig) {
+IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationBrowserTest, ProxyConfig) {
   if (IsRestartStateWithInProcessNetworkService())
     return;
   SetProxyPref(embedded_test_server()->host_port_pair());
@@ -1576,9 +1574,8 @@
 
 // Test that when there's a proxy configuration at startup, the initial requests
 // use that configuration.
-// Flaky on several platforms: https://crbug.com/922876
 IN_PROC_BROWSER_TEST_P(NetworkContextConfigurationProxyOnStartBrowserTest,
-                       DISABLED_TestInitialProxyConfig) {
+                       TestInitialProxyConfig) {
   if (IsRestartStateWithInProcessNetworkService())
     return;
   TestProxyConfigured(/*expect_success=*/true);
diff --git a/chrome/browser/notifications/notification_platform_bridge_linux.cc b/chrome/browser/notifications/notification_platform_bridge_linux.cc
index 7adc3fb..c3d1c536 100644
--- a/chrome/browser/notifications/notification_platform_bridge_linux.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_linux.cc
@@ -26,6 +26,7 @@
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
+#include "base/version.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chrome_notification_types.h"
 #include "chrome/browser/dbus/dbus_thread_linux.h"
@@ -171,13 +172,17 @@
           height)));
 }
 
-bool ShouldAddCloseButton(const std::string& server_name) {
+bool ShouldAddCloseButton(const std::string& server_name,
+                          const base::Version& server_version) {
   // Cinnamon doesn't add a close button on notifications.  With eg. calendar
   // notifications, which are stay-on-screen, this can lead to a situation where
   // the only way to dismiss a notification is to click on it, which would
   // create an unwanted web navigation.  For this reason, manually add a close
-  // button. (https://crbug.com/804637)
-  return server_name == "cinnamon";
+  // button (https://crbug.com/804637).  Cinnamon 3.8.0 adds a close button
+  // (https://github.com/linuxmint/Cinnamon/blob/8717fa/debian/changelog#L1075),
+  // so exclude versions that provide one already.
+  return server_name == "cinnamon" && server_version.IsValid() &&
+         server_version.CompareToWildcardString("3.8.0") < 0;
 }
 
 void ForwardNotificationOperationOnUiThread(
@@ -460,6 +465,10 @@
     if (server_information_response) {
       dbus::MessageReader reader(server_information_response.get());
       reader.PopString(&server_name_);
+      std::string server_version;
+      reader.PopString(&server_version);  // Vendor
+      reader.PopString(&server_version);  // Server version
+      server_version_ = base::Version(server_version);
     }
 
     connected_signals_barrier_ = base::BarrierClosure(
@@ -627,7 +636,7 @@
         actions.push_back(
             l10n_util::GetStringUTF8(IDS_NOTIFICATION_BUTTON_SETTINGS));
       }
-      if (ShouldAddCloseButton(server_name_)) {
+      if (ShouldAddCloseButton(server_name_, server_version_)) {
         actions.push_back(kCloseButtonId);
         actions.push_back(
             l10n_util::GetStringUTF8(IDS_NOTIFICATION_BUTTON_CLOSE));
@@ -969,6 +978,7 @@
   std::unordered_set<std::string> capabilities_;
 
   std::string server_name_;
+  base::Version server_version_;
 
   base::Closure connected_signals_barrier_;
 
diff --git a/chrome/browser/notifications/notification_platform_bridge_linux_unittest.cc b/chrome/browser/notifications/notification_platform_bridge_linux_unittest.cc
index 351a25e..fdb0af35 100644
--- a/chrome/browser/notifications/notification_platform_bridge_linux_unittest.cc
+++ b/chrome/browser/notifications/notification_platform_bridge_linux_unittest.cc
@@ -131,6 +131,7 @@
       : capabilities{"actions", "body", "body-hyperlinks", "body-images",
                      "body-markup"},
         server_name("NPBL_unittest"),
+        server_version("1.0"),
         expect_init_success(true),
         expect_shutdown(true),
         connect_signals(true) {}
@@ -145,6 +146,11 @@
     return *this;
   }
 
+  TestParams& SetServerVersion(const std::string& server_version) {
+    this->server_version = server_version;
+    return *this;
+  }
+
   TestParams& SetExpectInitSuccess(bool expect_init_success) {
     this->expect_init_success = expect_init_success;
     return *this;
@@ -162,6 +168,7 @@
 
   std::vector<std::string> capabilities;
   std::string server_name;
+  std::string server_version;
   bool expect_init_success;
   bool expect_shutdown;
   bool connect_signals;
@@ -237,13 +244,13 @@
   return response;
 }
 
-ACTION_P(OnGetServerInformation, server_name) {
+ACTION_P2(OnGetServerInformation, server_name, server_version) {
   std::unique_ptr<dbus::Response> response = dbus::Response::CreateEmpty();
   dbus::MessageWriter writer(response.get());
-  writer.AppendString(server_name);  // name
-  writer.AppendString("chromium");   // vendor
-  writer.AppendString("1.0");        // version
-  writer.AppendString("1.2");        // spec_version
+  writer.AppendString(server_name);     // name
+  writer.AppendString("chromium");      // vendor
+  writer.AppendString(server_version);  // version
+  writer.AppendString("1.2");           // spec_version
   return response;
 }
 
@@ -338,7 +345,8 @@
     if (test_params.expect_init_success) {
       EXPECT_CALL(*mock_notification_proxy_.get(),
                   CallMethodAndBlock(Calls("GetServerInformation"), _))
-          .WillOnce(OnGetServerInformation(test_params.server_name));
+          .WillOnce(OnGetServerInformation(test_params.server_name,
+                                           test_params.server_version));
     }
 
     if (test_params.connect_signals) {
@@ -694,12 +702,12 @@
 }
 
 TEST_F(NotificationPlatformBridgeLinuxTest,
-       CinnamonNotificationsHaveClosebutton) {
+       OldCinnamonNotificationsHaveClosebutton) {
   EXPECT_CALL(*mock_notification_proxy_.get(),
               CallMethodAndBlock(Calls("Notify"), _))
       .WillOnce(OnNotify(
           [](const NotificationRequest& request) {
-            EXPECT_EQ(3UL, request.actions.size());
+            ASSERT_EQ(3UL, request.actions.size());
             EXPECT_EQ("default", request.actions[0].id);
             EXPECT_EQ("Activate", request.actions[0].label);
             EXPECT_EQ("settings", request.actions[1].id);
@@ -709,7 +717,29 @@
           },
           1));
 
-  CreateNotificationBridgeLinux(TestParams().SetServerName("cinnamon"));
+  CreateNotificationBridgeLinux(
+      TestParams().SetServerName("cinnamon").SetServerVersion("3.6.7"));
+  notification_bridge_linux_->Display(
+      NotificationHandler::Type::WEB_PERSISTENT, profile(),
+      NotificationBuilder("").GetResult(), nullptr);
+}
+
+TEST_F(NotificationPlatformBridgeLinuxTest,
+       NewCinnamonNotificationsDontHaveClosebutton) {
+  EXPECT_CALL(*mock_notification_proxy_.get(),
+              CallMethodAndBlock(Calls("Notify"), _))
+      .WillOnce(OnNotify(
+          [](const NotificationRequest& request) {
+            ASSERT_EQ(2UL, request.actions.size());
+            EXPECT_EQ("default", request.actions[0].id);
+            EXPECT_EQ("Activate", request.actions[0].label);
+            EXPECT_EQ("settings", request.actions[1].id);
+            EXPECT_EQ("Settings", request.actions[1].label);
+          },
+          1));
+
+  CreateNotificationBridgeLinux(
+      TestParams().SetServerName("cinnamon").SetServerVersion("3.8.0"));
   notification_bridge_linux_->Display(
       NotificationHandler::Type::WEB_PERSISTENT, profile(),
       NotificationBuilder("").GetResult(), nullptr);
diff --git a/chrome/browser/notifications/persistent_notification_handler_unittest.cc b/chrome/browser/notifications/persistent_notification_handler_unittest.cc
index dcadb579..3b95a72f 100644
--- a/chrome/browser/notifications/persistent_notification_handler_unittest.cc
+++ b/chrome/browser/notifications/persistent_notification_handler_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "chrome/browser/notifications/metrics/mock_notification_metrics_logger.h"
diff --git a/chrome/browser/offline_pages/android/auto_fetch_page_load_watcher.cc b/chrome/browser/offline_pages/android/auto_fetch_page_load_watcher.cc
index 091ccbca..df69f518 100644
--- a/chrome/browser/offline_pages/android/auto_fetch_page_load_watcher.cc
+++ b/chrome/browser/offline_pages/android/auto_fetch_page_load_watcher.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "chrome/browser/android/tab_android.h"
diff --git a/chrome/browser/offline_pages/android/offline_page_auto_fetcher_service_unittest.cc b/chrome/browser/offline_pages/android/offline_page_auto_fetcher_service_unittest.cc
index 1167692..5373e25 100644
--- a/chrome/browser/offline_pages/android/offline_page_auto_fetcher_service_unittest.cc
+++ b/chrome/browser/offline_pages/android/offline_page_auto_fetcher_service_unittest.cc
@@ -7,6 +7,7 @@
 #include <string>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/mock_callback.h"
diff --git a/chrome/browser/offline_pages/android/offline_test_util_jni.cc b/chrome/browser/offline_pages/android/offline_test_util_jni.cc
index a16c0755..4f3b096 100644
--- a/chrome/browser/offline_pages/android/offline_test_util_jni.cc
+++ b/chrome/browser/offline_pages/android/offline_test_util_jni.cc
@@ -10,6 +10,7 @@
 #include "base/android/jni_string.h"
 #include "base/android/jni_utils.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/json/json_writer.h"
 #include "chrome/browser/offline_pages/android/offline_page_bridge.h"
 #include "chrome/browser/offline_pages/offline_page_model_factory.h"
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
index e1e56651..2bd01006 100644
--- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
+++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.cc
@@ -292,6 +292,7 @@
   }
   return nullptr;
 }
+
 void MetricsWebContentsObserver::ResourceLoadComplete(
     content::RenderFrameHost* render_frame_host,
     const content::GlobalRequestID& request_id,
@@ -336,6 +337,21 @@
     committed_load_->FrameReceivedFirstUserActivation(render_frame_host);
 }
 
+void MetricsWebContentsObserver::FrameDisplayStateChanged(
+    content::RenderFrameHost* render_frame_host,
+    bool is_display_none) {
+  if (committed_load_)
+    committed_load_->FrameDisplayStateChanged(render_frame_host,
+                                              is_display_none);
+}
+
+void MetricsWebContentsObserver::FrameSizeChanged(
+    content::RenderFrameHost* render_frame_host,
+    const gfx::Size& frame_size) {
+  if (committed_load_)
+    committed_load_->FrameSizeChanged(render_frame_host, frame_size);
+}
+
 void MetricsWebContentsObserver::OnRequestComplete(
     const GURL& url,
     const net::HostPortPair& host_port_pair,
@@ -375,6 +391,12 @@
   return committed_load_->ComputePageLoadExtraInfo();
 }
 
+void MetricsWebContentsObserver::ReadyToCommitNavigation(
+    content::NavigationHandle* navigation_handle) {
+  if (committed_load_)
+    committed_load_->ReadyToCommitNavigation(navigation_handle);
+}
+
 void MetricsWebContentsObserver::DidFinishNavigation(
     content::NavigationHandle* navigation_handle) {
   if (!navigation_handle->IsInMainFrame()) {
diff --git a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
index 88f44b7..15021396 100644
--- a/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
+++ b/chrome/browser/page_load_metrics/metrics_web_contents_observer.h
@@ -89,6 +89,8 @@
   void WebContentsWillSoonBeDestroyed();
 
   // content::WebContentsObserver implementation:
+  void ReadyToCommitNavigation(
+      content::NavigationHandle* navigation_handle) override;
   void DidFinishNavigation(
       content::NavigationHandle* navigation_handle) override;
   void DidRedirectNavigation(
@@ -109,6 +111,10 @@
       const content::mojom::ResourceLoadInfo& resource_load_info) override;
   void FrameReceivedFirstUserActivation(
       content::RenderFrameHost* render_frame_host) override;
+  void FrameDisplayStateChanged(content::RenderFrameHost* render_frame_host,
+                                bool is_display_none) override;
+  void FrameSizeChanged(content::RenderFrameHost* render_frame_host,
+                        const gfx::Size& frame_size) override;
 
   // These methods are forwarded from the MetricsNavigationThrottle.
   void WillStartNavigationRequest(content::NavigationHandle* navigation_handle);
diff --git a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.cc
index de419063..dbf34e1 100644
--- a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.cc
+++ b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.h"
 
+#include <algorithm>
 #include <string>
 #include <utility>
 
@@ -81,7 +82,9 @@
       frame_tree_node_id(frame_tree_node_id),
       origin_status(origin_status),
       frame_navigated(frame_navigated),
-      user_activation_status(UserActivationStatus::kNoActivation) {}
+      user_activation_status(UserActivationStatus::kNoActivation),
+      is_display_none(false),
+      frame_size(gfx::Size()) {}
 
 // static
 std::unique_ptr<AdsPageLoadMetricsObserver>
@@ -167,6 +170,7 @@
                           ? AdOriginStatus::kSame
                           : AdOriginStatus::kCross;
     }
+
     // If data existed already, update it and exit, otherwise, add it.
     if (previous_data) {
       previous_data->origin_status = origin_status;
@@ -175,13 +179,29 @@
     }
     ad_frames_data_storage_.emplace_back(ad_id, origin_status, frame_navigated);
     ad_data = &ad_frames_data_storage_.back();
-  }
 
+    if (ad_host) {
+      ad_data->is_display_none = ad_host->IsFrameDisplayNone();
+      if (ad_host->GetFrameSize())
+        ad_data->frame_size = *(ad_host->GetFrameSize());
+    }
+  }
   // If there was previous data, then we don't want to overwrite this frame.
   if (!previous_data)
     ad_frames_data_[ad_id] = ad_data;
 }
 
+void AdsPageLoadMetricsObserver::ReadyToCommitNextNavigation(
+    content::NavigationHandle* navigation_handle) {
+  // When the renderer receives a CommitNavigation message for the main frame,
+  // all subframes detach and become display : none. Since this is not user
+  // visible, and not reflective of the frames state during the page lifetime,
+  // ignore any such messages when a navigation is about to commit.
+  if (!navigation_handle->IsInMainFrame())
+    return;
+  process_display_state_updates_ = false;
+}
+
 // Determine if the frame is part of an existing ad, the root of a new ad, or a
 // non-ad frame. Once a frame is labeled as an ad, it is always considered an
 // ad, even if it navigates to a non-ad page. This function labels all of a
@@ -332,6 +352,36 @@
   }
 }
 
+void AdsPageLoadMetricsObserver::FrameDisplayStateChanged(
+    content::RenderFrameHost* render_frame_host,
+    bool is_display_none) {
+  if (!process_display_state_updates_)
+    return;
+  const auto& id_and_data =
+      ad_frames_data_.find(render_frame_host->GetFrameTreeNodeId());
+  if (id_and_data == ad_frames_data_.end())
+    return;
+  AdFrameData* ancestor_data = id_and_data->second;
+  if (ancestor_data && render_frame_host->GetFrameTreeNodeId() ==
+                           ancestor_data->frame_tree_node_id) {
+    ancestor_data->is_display_none = is_display_none;
+  }
+}
+
+void AdsPageLoadMetricsObserver::FrameSizeChanged(
+    content::RenderFrameHost* render_frame_host,
+    const gfx::Size& frame_size) {
+  const auto& id_and_data =
+      ad_frames_data_.find(render_frame_host->GetFrameTreeNodeId());
+  if (id_and_data == ad_frames_data_.end())
+    return;
+  AdFrameData* ancestor_data = id_and_data->second;
+  if (ancestor_data && render_frame_host->GetFrameTreeNodeId() ==
+                           ancestor_data->frame_tree_node_id) {
+    ancestor_data->frame_size = frame_size;
+  }
+}
+
 void AdsPageLoadMetricsObserver::OnAdSubframeDetected(
     content::RenderFrameHost* render_frame_host) {
   FrameTreeNodeId frame_tree_node_id = render_frame_host->GetFrameTreeNodeId();
@@ -588,6 +638,23 @@
   for (const AdFrameData& ad_frame_data : ad_frames_data_storage_) {
     if (ad_frame_data.frame_bytes == 0)
       continue;
+    AdFrameVisibility visibility = ad_frame_data.is_display_none
+                                       ? AdFrameVisibility::kDisplayNone
+                                       : AdFrameVisibility::kVisible;
+    ADS_HISTOGRAM("FrameCounts.AdFrames.PerFrame.Visibility",
+                  UMA_HISTOGRAM_ENUMERATION, visibility);
+
+    // Record pixel metrics only for adframes that are displayed.
+    if (!ad_frame_data.is_display_none) {
+      ADS_HISTOGRAM("FrameCounts.AdFrames.PerFrame.SqrtNumberOfPixels",
+                    UMA_HISTOGRAM_COUNTS_10000,
+                    std::sqrt(ad_frame_data.frame_size.width() *
+                              ad_frame_data.frame_size.height()));
+      ADS_HISTOGRAM("FrameCounts.AdFrames.PerFrame.SmallestDimension",
+                    UMA_HISTOGRAM_COUNTS_10000,
+                    std::min(ad_frame_data.frame_size.width(),
+                             ad_frame_data.frame_size.height()));
+    }
 
     non_zero_ad_frames += 1;
     total_ad_frame_bytes += ad_frame_data.frame_bytes;
@@ -628,7 +695,7 @@
     ADS_HISTOGRAM("Bytes.FullPage.Total.PercentAds", UMA_HISTOGRAM_PERCENTAGE,
                   total_ad_frame_bytes * 100 / page_bytes_);
   }
-  if (page_network_bytes_ > 0) {
+  if (page_network_bytes_) {
     ADS_HISTOGRAM("Bytes.FullPage.Network.PercentAds", UMA_HISTOGRAM_PERCENTAGE,
                   ad_frame_network_bytes * 100 / page_network_bytes_);
   }
diff --git a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.h
index d6da9c5..353196b 100644
--- a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer.h
@@ -36,6 +36,15 @@
     kMaxValue = kCross,
   };
 
+  // Whether or not the ad frame has a display: none styling. These values are
+  // persisted to logs. Entries should not be renumbered and numeric values
+  // should never be reused.
+  enum class AdFrameVisibility {
+    kDisplayNone = 0,
+    kVisible = 1,
+    kMaxValue = kVisible,
+  };
+
   // High level categories of mime types for resources loaded by the page.
   enum class ResourceMimeType {
     kJavascript = 0,
@@ -73,6 +82,8 @@
                          bool is_adframe,
                          content::RenderFrameHost* ad_host,
                          bool frame_navigated);
+  void ReadyToCommitNextNavigation(
+      content::NavigationHandle* navigation_handle) override;
   void OnDidFinishSubFrameNavigation(
       content::NavigationHandle* navigation_handle) override;
   void OnDidInternalNavigationAbort(
@@ -90,6 +101,10 @@
       const page_load_metrics::mojom::PageLoadTiming& timing,
       const page_load_metrics::PageLoadExtraInfo& extra_info) override;
   void FrameReceivedFirstUserActivation(content::RenderFrameHost* rfh) override;
+  void FrameDisplayStateChanged(content::RenderFrameHost* render_frame_host,
+                                bool is_display_none) override;
+  void FrameSizeChanged(content::RenderFrameHost* render_frame_host,
+                        const gfx::Size& frame_size) override;
 
  private:
   struct AdFrameData {
@@ -103,7 +118,10 @@
     const FrameTreeNodeId frame_tree_node_id;
     AdOriginStatus origin_status;
     bool frame_navigated;
+
     UserActivationStatus user_activation_status;
+    bool is_display_none;
+    gfx::Size frame_size;
   };
 
   // subresource_filter::SubresourceFilterObserver:
@@ -192,6 +210,11 @@
   size_t page_main_frame_ad_resource_bytes_ = 0u;
   uint32_t total_number_page_resources_ = 0;
 
+  // Flag denoting that this observer should no longer monitor changes in
+  // display state for frames. This prevents us from receiving the updates when
+  // the frame elements are being destroyed in the renderer.
+  bool process_display_state_updates_ = true;
+
   // Time the page was committed.
   base::Time time_commit_;
 
diff --git a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_browsertest.cc
index ce5778e..5d17571 100644
--- a/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_browsertest.cc
+++ b/chrome/browser/page_load_metrics/observers/ads_page_load_metrics_observer_browsertest.cc
@@ -50,6 +50,18 @@
     "PageLoad.Clients.Ads.SubresourceFilter.FrameCounts.AdFrames.PerFrame."
     "UserActivation";
 
+const char kVisibilityHistogramId[] =
+    "PageLoad.Clients.Ads.FrameCounts.AdFrames.PerFrame."
+    "Visibility";
+
+const char kSqrtNumberOfPixelsHistogramId[] =
+    "PageLoad.Clients.Ads.FrameCounts.AdFrames.PerFrame."
+    "SqrtNumberOfPixels";
+
+const char kSmallestDimensionHistogramId[] =
+    "PageLoad.Clients.Ads.FrameCounts.AdFrames.PerFrame."
+    "SmallestDimension";
+
 enum class Origin {
   kNavigation,
   kAnchorAttribute,
@@ -325,6 +337,89 @@
       2, 1);
 }
 
+// Test that a frame without display:none is reported as visible.
+IN_PROC_BROWSER_TEST_F(AdsPageLoadMetricsObserverBrowserTest,
+                       VisibleAdframeRecorded) {
+  base::HistogramTester histogram_tester;
+  auto waiter = CreatePageLoadMetricsTestWaiter();
+  ui_test_utils::NavigateToURL(browser(),
+                               embedded_test_server()->GetURL(
+                                   "/ads_observer/display_block_adframe.html"));
+  waiter->AddMinimumCompleteResourcesExpectation(4);
+  waiter->Wait();
+  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
+  histogram_tester.ExpectUniqueSample(
+      kVisibilityHistogramId,
+      AdsPageLoadMetricsObserver::AdFrameVisibility::kVisible, 1);
+}
+
+IN_PROC_BROWSER_TEST_F(AdsPageLoadMetricsObserverBrowserTest,
+                       DisplayNoneAdframeRecorded) {
+  base::HistogramTester histogram_tester;
+  auto waiter = CreatePageLoadMetricsTestWaiter();
+  ui_test_utils::NavigateToURL(browser(),
+                               embedded_test_server()->GetURL(
+                                   "/ads_observer/display_none_adframe.html"));
+  waiter->AddMinimumCompleteResourcesExpectation(4);
+  waiter->Wait();
+  // Navigate away to force the histogram recording.
+  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
+  histogram_tester.ExpectUniqueSample(
+      kVisibilityHistogramId,
+      AdsPageLoadMetricsObserver::AdFrameVisibility::kDisplayNone, 1);
+}
+
+IN_PROC_BROWSER_TEST_F(AdsPageLoadMetricsObserverBrowserTest, FramePixelSize) {
+  base::HistogramTester histogram_tester;
+  auto waiter = CreatePageLoadMetricsTestWaiter();
+  ui_test_utils::NavigateToURL(
+      browser(), embedded_test_server()->GetURL(
+                     "/ads_observer/blank_with_adiframe_writer.html"));
+  content::WebContents* web_contents =
+      browser()->tab_strip_model()->GetActiveWebContents();
+
+  // Create a 100x100 iframe.
+  ASSERT_TRUE(ExecJs(
+      web_contents,
+      "let frame = createAdIframe(); frame.width=100; frame.height = 100; "
+      "frame.src = '/ads_observer/pixel.png';"));
+
+  // Create a 300x300 iframe with display none that should not be recorded.
+  ASSERT_TRUE(ExecJs(web_contents,
+                     "frame = createAdIframe(); frame.width=300; frame.src "
+                     "= '/ads_observer/pixel.png';"
+                     "frame.height = 300; frame.style.display= 'none';"));
+
+  // Create a 0x0 iframe.
+  ASSERT_TRUE(ExecJs(
+      web_contents,
+      "frame = createAdIframe(); frame.width=0; frame.height = 0; frame.src = "
+      "'/ads_observer/pixel.png';"));
+
+  // Create a 10 x 1000 iframe.
+  ASSERT_TRUE(
+      ExecJs(web_contents,
+             "frame = createAdIframe(); frame.width=10; frame.height = 1000; "
+             "frame.src = '/ads_observer/pixel.png';"));
+
+  // Wait for each frames resource to load so that they will have non-zero
+  // bytes.
+  waiter->AddMinimumCompleteResourcesExpectation(7);
+  waiter->Wait();
+
+  // Navigate away to force the histogram recording.
+  ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
+  histogram_tester.ExpectBucketCount(kSqrtNumberOfPixelsHistogramId, 100, 2);
+  histogram_tester.ExpectBucketCount(kSqrtNumberOfPixelsHistogramId, 0, 1);
+  histogram_tester.ExpectBucketCount(kSmallestDimensionHistogramId, 0, 1);
+  histogram_tester.ExpectBucketCount(kSmallestDimensionHistogramId, 10, 1);
+  histogram_tester.ExpectBucketCount(kSmallestDimensionHistogramId, 100, 1);
+
+  // Verify the display: none frame is not recorded.
+  histogram_tester.ExpectBucketCount(kSqrtNumberOfPixelsHistogramId, 300, 0);
+  histogram_tester.ExpectBucketCount(kSmallestDimensionHistogramId, 300, 0);
+}
+
 class AdsPageLoadMetricsTestWaiter
     : public page_load_metrics::PageLoadMetricsTestWaiter {
  public:
diff --git a/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.cc b/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.cc
new file mode 100644
index 0000000..92645b8
--- /dev/null
+++ b/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.cc
@@ -0,0 +1,80 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.h"
+
+#include "base/time/time.h"
+#include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
+#include "chrome/browser/page_load_metrics/page_load_metrics_util.h"
+#include "chrome/common/page_load_metrics/page_load_timing.h"
+#include "content/public/browser/navigation_handle.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
+#include "services/metrics/public/cpp/ukm_recorder.h"
+#include "services/metrics/public/cpp/ukm_source.h"
+
+ForegroundDurationUKMObserver::ForegroundDurationUKMObserver() {}
+
+ForegroundDurationUKMObserver::~ForegroundDurationUKMObserver() {}
+
+page_load_metrics::PageLoadMetricsObserver::ObservePolicy
+ForegroundDurationUKMObserver::OnStart(
+    content::NavigationHandle* navigation_handle,
+    const GURL& currently_committed_url,
+    bool started_in_foreground) {
+  currently_in_foreground_ = started_in_foreground;
+  if (currently_in_foreground_) {
+    last_time_shown_ = navigation_handle->NavigationStart();
+  }
+  return CONTINUE_OBSERVING;
+}
+
+page_load_metrics::PageLoadMetricsObserver::ObservePolicy
+ForegroundDurationUKMObserver::OnCommit(
+    content::NavigationHandle* navigation_handle,
+    ukm::SourceId source_id) {
+  source_id_ = source_id;
+  return CONTINUE_OBSERVING;
+}
+
+page_load_metrics::PageLoadMetricsObserver::ObservePolicy
+ForegroundDurationUKMObserver::FlushMetricsOnAppEnterBackground(
+    const page_load_metrics::mojom::PageLoadTiming& timing,
+    const page_load_metrics::PageLoadExtraInfo& info) {
+  RecordUkmIfInForeground();
+  return CONTINUE_OBSERVING;
+}
+
+page_load_metrics::PageLoadMetricsObserver::ObservePolicy
+ForegroundDurationUKMObserver::OnHidden(
+    const page_load_metrics::mojom::PageLoadTiming& timing,
+    const page_load_metrics::PageLoadExtraInfo& info) {
+  RecordUkmIfInForeground();
+  return CONTINUE_OBSERVING;
+}
+page_load_metrics::PageLoadMetricsObserver::ObservePolicy
+ForegroundDurationUKMObserver::OnShown() {
+  if (!currently_in_foreground_) {
+    last_time_shown_ = base::TimeTicks::Now();
+    currently_in_foreground_ = true;
+  }
+  return CONTINUE_OBSERVING;
+}
+
+void ForegroundDurationUKMObserver::OnComplete(
+    const page_load_metrics::mojom::PageLoadTiming& timing,
+    const page_load_metrics::PageLoadExtraInfo& info) {
+  RecordUkmIfInForeground();
+}
+
+void ForegroundDurationUKMObserver::RecordUkmIfInForeground() {
+  if (!currently_in_foreground_)
+    return;
+  base::TimeDelta foreground_duration =
+      base::TimeTicks::Now() - last_time_shown_;
+  ukm::UkmRecorder* ukm_recorder = ukm::UkmRecorder::Get();
+  ukm::builders::PageForegroundSession(source_id_)
+      .SetForegroundDuration(foreground_duration.InMilliseconds())
+      .Record(ukm_recorder);
+  currently_in_foreground_ = false;
+}
diff --git a/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.h b/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.h
new file mode 100644
index 0000000..63b9c85
--- /dev/null
+++ b/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.h
@@ -0,0 +1,45 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_FOREGROUND_DURATION_UKM_OBSERVER_H_
+#define CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_FOREGROUND_DURATION_UKM_OBSERVER_H_
+
+#include "base/time/time.h"
+#include "chrome/browser/page_load_metrics/page_load_metrics_observer.h"
+#include "services/metrics/public/cpp/ukm_source_id.h"
+
+// Observer responsible for appending previews information to the PLM UKM
+// report.
+class ForegroundDurationUKMObserver
+    : public page_load_metrics::PageLoadMetricsObserver {
+ public:
+  ForegroundDurationUKMObserver();
+  ~ForegroundDurationUKMObserver() override;
+
+  // page_load_metrics::PageLoadMetricsObserver:
+  ObservePolicy OnStart(content::NavigationHandle* navigation_handle,
+                        const GURL& currently_committed_url,
+                        bool started_in_foreground) override;
+  ObservePolicy OnCommit(content::NavigationHandle* navigation_handle,
+                         ukm::SourceId source_id) override;
+  ObservePolicy FlushMetricsOnAppEnterBackground(
+      const page_load_metrics::mojom::PageLoadTiming& timing,
+      const page_load_metrics::PageLoadExtraInfo& info) override;
+  ObservePolicy OnHidden(
+      const page_load_metrics::mojom::PageLoadTiming& timing,
+      const page_load_metrics::PageLoadExtraInfo& info) override;
+  ObservePolicy OnShown() override;
+  void OnComplete(const page_load_metrics::mojom::PageLoadTiming& timing,
+                  const page_load_metrics::PageLoadExtraInfo& info) override;
+
+ private:
+  bool currently_in_foreground_ = false;
+  base::TimeTicks last_time_shown_;
+  ukm::SourceId source_id_ = ukm::kInvalidSourceId;
+  void RecordUkmIfInForeground();
+
+  DISALLOW_COPY_AND_ASSIGN(ForegroundDurationUKMObserver);
+};
+
+#endif  // CHROME_BROWSER_PAGE_LOAD_METRICS_OBSERVERS_FOREGROUND_DURATION_UKM_OBSERVER_H_
diff --git a/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer_browsertest.cc b/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer_browsertest.cc
new file mode 100644
index 0000000..c70d1fc0
--- /dev/null
+++ b/chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer_browsertest.cc
@@ -0,0 +1,106 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.h"
+
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_commands.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
+#include "chrome/common/webui_url_constants.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
+#include "components/ukm/test_ukm_recorder.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "services/metrics/public/cpp/ukm_builders.h"
+#include "services/metrics/public/cpp/ukm_source.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/window_open_disposition.h"
+#include "url/gurl.h"
+
+using UkmEntry = ukm::builders::PageForegroundSession;
+
+class ForegroundDurationUKMObserverBrowserTest : public InProcessBrowserTest {
+ public:
+  ForegroundDurationUKMObserverBrowserTest() {}
+  ~ForegroundDurationUKMObserverBrowserTest() override {}
+
+  void PreRunTestOnMainThread() override {
+    InProcessBrowserTest::PreRunTestOnMainThread();
+    test_ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>();
+  }
+
+ protected:
+  void StartHttpsServer(net::EmbeddedTestServer::ServerCertificate cert) {
+    https_test_server_ = std::make_unique<net::EmbeddedTestServer>(
+        net::EmbeddedTestServer::TYPE_HTTPS);
+    https_test_server_->SetSSLConfig(cert);
+    https_test_server_->ServeFilesFromSourceDirectory("chrome/test/data");
+    ASSERT_TRUE(https_test_server_->Start());
+  }
+  void ExpectMetricCountForUrl(const GURL& url,
+                               const char* metric_name,
+                               const int expected_count) {
+    int count = 0;
+    for (auto* entry :
+         test_ukm_recorder_->GetEntriesByName(UkmEntry::kEntryName)) {
+      auto* source = test_ukm_recorder_->GetSourceForSourceId(entry->source_id);
+      if (source && source->url() == url) {
+        test_ukm_recorder_->EntryHasMetric(entry, metric_name);
+        count++;
+      }
+    }
+    EXPECT_EQ(count, expected_count);
+  }
+
+  void CloseAllTabs() {
+    TabStripModel* tab_strip_model = browser()->tab_strip_model();
+    content::WebContentsDestroyedWatcher destroyed_watcher(
+        tab_strip_model->GetActiveWebContents());
+    tab_strip_model->CloseAllTabs();
+    destroyed_watcher.Wait();
+  }
+
+  net::EmbeddedTestServer* https_test_server() {
+    return https_test_server_.get();
+  }
+
+ private:
+  std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_;
+  std::unique_ptr<net::EmbeddedTestServer> https_test_server_;
+
+  DISALLOW_COPY_AND_ASSIGN(ForegroundDurationUKMObserverBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_F(ForegroundDurationUKMObserverBrowserTest, RecordSimple) {
+  StartHttpsServer(net::EmbeddedTestServer::CERT_OK);
+  GURL url = https_test_server()->GetURL("/simple.html");
+  ui_test_utils::NavigateToURL(browser(), url);
+  CloseAllTabs();
+  ExpectMetricCountForUrl(url, "ForegroundDuration", 1);
+}
+
+IN_PROC_BROWSER_TEST_F(ForegroundDurationUKMObserverBrowserTest, TabSwitching) {
+  StartHttpsServer(net::EmbeddedTestServer::CERT_OK);
+  GURL url1 = https_test_server()->GetURL("/simple.html");
+  GURL url2 = https_test_server()->GetURL("/form.html");
+  ui_test_utils::NavigateToURL(browser(), url1);
+  ui_test_utils::NavigateToURLWithDisposition(
+      browser(), url2, WindowOpenDisposition::NEW_FOREGROUND_TAB,
+      ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
+
+  TabStripModel* tab_strip_model = browser()->tab_strip_model();
+  EXPECT_EQ(2, tab_strip_model->count());
+  EXPECT_EQ(url1, tab_strip_model->GetWebContentsAt(0)->GetURL());
+  EXPECT_EQ(url2, tab_strip_model->GetWebContentsAt(1)->GetURL());
+
+  tab_strip_model->ActivateTabAt(0, true);
+  tab_strip_model->ActivateTabAt(1, true);
+  tab_strip_model->ActivateTabAt(0, true);
+  tab_strip_model->ActivateTabAt(1, true);
+  tab_strip_model->CloseAllTabs();
+  ExpectMetricCountForUrl(url1, "ForegroundDuration", 3);
+  ExpectMetricCountForUrl(url2, "ForegroundDuration", 3);
+}
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
index c6be67a..2aed9f82 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
+++ b/chrome/browser/page_load_metrics/page_load_metrics_initialize.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/data_use_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/document_write_page_load_metrics_observer.h"
+#include "chrome/browser/page_load_metrics/observers/foreground_duration_ukm_observer.h"
 #include "chrome/browser/page_load_metrics/observers/from_gws_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer.h"
 #include "chrome/browser/page_load_metrics/observers/live_tab_count_page_load_metrics_observer.h"
@@ -100,6 +101,7 @@
     tracker->AddObserver(
         std::make_unique<data_reduction_proxy::LoFiPageLoadMetricsObserver>());
     tracker->AddObserver(std::make_unique<FromGWSPageLoadMetricsObserver>());
+    tracker->AddObserver(std::make_unique<ForegroundDurationUKMObserver>());
     tracker->AddObserver(
         std::make_unique<DocumentWritePageLoadMetricsObserver>());
     tracker->AddObserver(
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_observer.h b/chrome/browser/page_load_metrics/page_load_metrics_observer.h
index 10b6bcdb..fcc41b6 100644
--- a/chrome/browser/page_load_metrics/page_load_metrics_observer.h
+++ b/chrome/browser/page_load_metrics/page_load_metrics_observer.h
@@ -333,6 +333,13 @@
   virtual void OnDidInternalNavigationAbort(
       content::NavigationHandle* navigation_handle) {}
 
+  // ReadyToCommitNextNavigation is triggered when a frame navigation is
+  // ready to commit, but has not yet been committed. This is only called by
+  // a PageLoadTracker for a committed load, meaning that this call signals we
+  // are ready to commit a navigation to a new page.
+  virtual void ReadyToCommitNextNavigation(
+      content::NavigationHandle* navigation_handle) {}
+
   // OnDidFinishSubFrameNavigation is triggered when a sub-frame of the
   // committed page has finished navigating. It has either committed, aborted,
   // was a same document navigation, or has been replaced. It is up to the
@@ -496,6 +503,15 @@
   virtual void FrameReceivedFirstUserActivation(
       content::RenderFrameHost* render_frame_host) {}
 
+  // Called when the display property changes on the frame.
+  virtual void FrameDisplayStateChanged(
+      content::RenderFrameHost* render_frame_host,
+      bool is_display_none) {}
+
+  // Called when a frames size changes.
+  virtual void FrameSizeChanged(content::RenderFrameHost* render_frame_host,
+                                const gfx::Size& frame_size) {}
+
   // Called when the event corresponding to |event_key| occurs in this page
   // load.
   virtual void OnEventOccurred(const void* const event_key) {}
diff --git a/chrome/browser/page_load_metrics/page_load_tracker.cc b/chrome/browser/page_load_metrics/page_load_tracker.cc
index 86d70f9b..1787d322 100644
--- a/chrome/browser/page_load_metrics/page_load_tracker.cc
+++ b/chrome/browser/page_load_metrics/page_load_tracker.cc
@@ -360,6 +360,13 @@
   }
 }
 
+void PageLoadTracker::ReadyToCommitNavigation(
+    content::NavigationHandle* navigation_handle) {
+  for (const auto& observer : observers_) {
+    observer->ReadyToCommitNextNavigation(navigation_handle);
+  }
+}
+
 void PageLoadTracker::DidFinishSubFrameNavigation(
     content::NavigationHandle* navigation_handle) {
   for (const auto& observer : observers_) {
@@ -431,6 +438,22 @@
   }
 }
 
+void PageLoadTracker::FrameDisplayStateChanged(
+    content::RenderFrameHost* render_frame_host,
+    bool is_display_none) {
+  for (const auto& observer : observers_) {
+    observer->FrameDisplayStateChanged(render_frame_host, is_display_none);
+  }
+}
+
+void PageLoadTracker::FrameSizeChanged(
+    content::RenderFrameHost* render_frame_host,
+    const gfx::Size& frame_size) {
+  for (const auto& observer : observers_) {
+    observer->FrameSizeChanged(render_frame_host, frame_size);
+  }
+}
+
 void PageLoadTracker::StopTracking() {
   did_stop_tracking_ = true;
   observers_.clear();
diff --git a/chrome/browser/page_load_metrics/page_load_tracker.h b/chrome/browser/page_load_metrics/page_load_tracker.h
index b16fc772..b2556be3 100644
--- a/chrome/browser/page_load_metrics/page_load_tracker.h
+++ b/chrome/browser/page_load_metrics/page_load_tracker.h
@@ -192,6 +192,7 @@
   void DidCommitSameDocumentNavigation(
       content::NavigationHandle* navigation_handle);
   void DidInternalNavigationAbort(content::NavigationHandle* navigation_handle);
+  void ReadyToCommitNavigation(content::NavigationHandle* navigation_handle);
   void DidFinishSubFrameNavigation(
       content::NavigationHandle* navigation_handle);
   void FailedProvisionalLoad(content::NavigationHandle* navigation_handle,
@@ -213,6 +214,10 @@
       const ExtraRequestCompleteInfo& extra_request_complete_info);
 
   void FrameReceivedFirstUserActivation(content::RenderFrameHost* rfh);
+  void FrameDisplayStateChanged(content::RenderFrameHost* render_frame_host,
+                                bool is_display_none);
+  void FrameSizeChanged(content::RenderFrameHost* render_frame_host,
+                        const gfx::Size& frame_size);
 
   // Signals that we should stop tracking metrics for the associated page load.
   // We may stop tracking a page load if it doesn't meet the criteria for
diff --git a/chrome/browser/plugins/flash_download_interception.cc b/chrome/browser/plugins/flash_download_interception.cc
index 1ec7e54c..abf8cc2 100644
--- a/chrome/browser/plugins/flash_download_interception.cc
+++ b/chrome/browser/plugins/flash_download_interception.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/plugins/flash_download_interception.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/no_destructor.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
diff --git a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
index 4bea0d7..1d49a41 100644
--- a/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
+++ b/chrome/browser/policy/cloud/user_policy_signin_service_unittest.cc
@@ -23,9 +23,7 @@
 #include "chrome/browser/signin/account_tracker_service_factory.h"
 #include "chrome/browser/signin/chrome_signin_client_factory.h"
 #include "chrome/browser/signin/fake_account_fetcher_service_builder.h"
-#include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
 #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h"
-#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
 #include "chrome/browser/signin/signin_util.h"
 #include "chrome/browser/signin/test_signin_client_builder.h"
 #include "chrome/test/base/testing_browser_process.h"
@@ -41,7 +39,6 @@
 #include "components/prefs/pref_service.h"
 #include "components/signin/core/browser/account_tracker_service.h"
 #include "components/signin/core/browser/fake_account_fetcher_service.h"
-#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/notification_details.h"
@@ -232,14 +229,8 @@
         content::NotificationService::NoDetails());
   }
 
-  FakeProfileOAuth2TokenService* GetTokenService() {
-    ProfileOAuth2TokenService* service =
-        ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
-    return static_cast<FakeProfileOAuth2TokenService*>(service);
-  }
-
   bool IsRequestActive() {
-    if (!GetTokenService()->GetPendingRequests().empty())
+    if (identity_test_env()->IsAccessTokenRequestPending())
       return true;
     return test_url_loader_factory_.NumPending() > 0;
   }
@@ -262,7 +253,7 @@
 
   void MakeOAuthTokenFetchFail() {
 #if defined(OS_ANDROID)
-    ASSERT_TRUE(!GetTokenService()->GetPendingRequests().empty());
+    ASSERT_TRUE(identity_test_env()->IsAccessTokenRequestPending());
     identity_test_env()
         ->WaitForAccessTokenRequestIfNecessaryAndRespondWithError(
             GoogleServiceAuthError::FromServiceError("fail"));
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 71feb27..574453b 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -218,7 +218,7 @@
 #include "chrome/browser/signin/signin_promo.h"
 #include "chrome/browser/ui/startup/startup_browser_creator.h"
 #include "chrome/browser/ui/webui/foreign_session_handler.h"
-#include "chrome/browser/ui/webui/md_history_ui.h"
+#include "chrome/browser/ui/webui/history_ui.h"
 #include "chrome/browser/ui/webui/settings/md_settings_ui.h"
 #include "chrome/browser/upgrade_detector/upgrade_detector.h"
 #endif  // defined(OS_ANDROID)
diff --git a/chrome/browser/printing/cloud_print/privet_url_loader_unittest.cc b/chrome/browser/printing/cloud_print/privet_url_loader_unittest.cc
index 2b83ead8..3930625 100644
--- a/chrome/browser/printing/cloud_print/privet_url_loader_unittest.cc
+++ b/chrome/browser/printing/cloud_print/privet_url_loader_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_util.h"
 #include "base/run_loop.h"
 #include "base/test/bind_test_util.h"
diff --git a/chrome/browser/profiles/profile_impl.h b/chrome/browser/profiles/profile_impl.h
index 4a3aa48..6711bad 100644
--- a/chrome/browser/profiles/profile_impl.h
+++ b/chrome/browser/profiles/profile_impl.h
@@ -14,6 +14,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
+#include "base/timer/timer.h"
 #include "build/build_config.h"
 #include "chrome/browser/net/reporting_permissions_checker.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/profiles/profile_window.cc b/chrome/browser/profiles/profile_window.cc
index 44e2b71..4c19ba505 100644
--- a/chrome/browser/profiles/profile_window.cc
+++ b/chrome/browser/profiles/profile_window.cc
@@ -29,7 +29,6 @@
 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/signin/account_reconcilor_factory.h"
-#include "chrome/browser/signin/account_tracker_service_factory.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/signin/signin_ui_util.h"
 #include "chrome/browser/sync/profile_sync_service_factory.h"
@@ -44,7 +43,6 @@
 #include "components/prefs/pref_service.h"
 #include "components/signin/core/browser/account_info.h"
 #include "components/signin/core/browser/account_reconcilor.h"
-#include "components/signin/core/browser/account_tracker_service.h"
 #include "components/signin/core/browser/signin_pref_names.h"
 #include "content/public/browser/browser_thread.h"
 #include "extensions/buildflags/buildflags.h"
@@ -373,11 +371,10 @@
   // TODO(mlerman): After one release remove any hosted_domain reference to the
   // pref, since all users will have this in the AccountTrackerService.
   if (hosted_domain.empty()) {
-    AccountTrackerService* account_tracker =
-        AccountTrackerServiceFactory::GetForProfile(profile);
-    std::string account_id =
-        IdentityManagerFactory::GetForProfile(profile)->GetPrimaryAccountId();
-    hosted_domain = account_tracker->GetAccountInfo(account_id).hosted_domain;
+    auto* identity_manager = IdentityManagerFactory::GetForProfile(profile);
+    if (identity_manager->HasPrimaryAccount()) {
+      hosted_domain = identity_manager->GetPrimaryAccountInfo().hosted_domain;
+    }
   }
   // TODO(mlerman): Prohibit only users who authenticate using SAML. Until then,
   // prohibited users who use hosted domains (aside from google.com).
diff --git a/chrome/browser/profiling_host/profiling_process_host.h b/chrome/browser/profiling_host/profiling_process_host.h
index ef21767..e33c0db 100644
--- a/chrome/browser/profiling_host/profiling_process_host.h
+++ b/chrome/browser/profiling_host/profiling_process_host.h
@@ -11,6 +11,7 @@
 
 #include "base/macros.h"
 #include "base/memory/singleton.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/profiling_host/background_profiling_triggers.h"
 #include "components/services/heap_profiling/public/mojom/heap_profiling_client.mojom.h"
 
diff --git a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
index e7e3e35..7f51e05 100644
--- a/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
+++ b/chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/base_switches.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/path_service.h"
diff --git a/chrome/browser/resource_coordinator/chrome_content_browser_client_resource_coordinator_part.cc b/chrome/browser/resource_coordinator/chrome_content_browser_client_resource_coordinator_part.cc
new file mode 100644
index 0000000..2a1ebb5
--- /dev/null
+++ b/chrome/browser/resource_coordinator/chrome_content_browser_client_resource_coordinator_part.cc
@@ -0,0 +1,49 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/resource_coordinator/chrome_content_browser_client_resource_coordinator_part.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/threading/sequenced_task_runner_handle.h"
+#include "chrome/browser/resource_coordinator/render_process_user_data.h"
+
+namespace {
+
+void BindProcessResourceCoordinator(
+    content::RenderProcessHost* render_process_host,
+    resource_coordinator::mojom::ProcessCoordinationUnitRequest request) {
+  resource_coordinator::RenderProcessUserData* user_data =
+      resource_coordinator::RenderProcessUserData::GetForRenderProcessHost(
+          render_process_host);
+
+  user_data->process_resource_coordinator()->AddBinding(std::move(request));
+}
+
+}  // namespace
+
+ChromeContentBrowserClientResourceCoordinatorPart::
+    ChromeContentBrowserClientResourceCoordinatorPart() = default;
+ChromeContentBrowserClientResourceCoordinatorPart::
+    ~ChromeContentBrowserClientResourceCoordinatorPart() = default;
+
+void ChromeContentBrowserClientResourceCoordinatorPart::
+    ExposeInterfacesToRenderer(
+        service_manager::BinderRegistry* registry,
+        blink::AssociatedInterfaceRegistry* associated_registry,
+        content::RenderProcessHost* render_process_host) {
+  registry->AddInterface(
+      base::BindRepeating(&BindProcessResourceCoordinator,
+                          base::Unretained(render_process_host)),
+      base::SequencedTaskRunnerHandle::Get());
+
+  // When a RenderFrameHost is "resurrected" with a new process  it will already
+  // have user data attached. This will happen on renderer crash.
+  if (!resource_coordinator::RenderProcessUserData::GetForRenderProcessHost(
+          render_process_host)) {
+    resource_coordinator::RenderProcessUserData::CreateForRenderProcessHost(
+        render_process_host);
+  }
+}
diff --git a/chrome/browser/resource_coordinator/chrome_content_browser_client_resource_coordinator_part.h b/chrome/browser/resource_coordinator/chrome_content_browser_client_resource_coordinator_part.h
new file mode 100644
index 0000000..cfd3af7
--- /dev/null
+++ b/chrome/browser/resource_coordinator/chrome_content_browser_client_resource_coordinator_part.h
@@ -0,0 +1,30 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_CHROME_CONTENT_BROWSER_CLIENT_RESOURCE_COORDINATOR_PART_H_
+#define CHROME_BROWSER_RESOURCE_COORDINATOR_CHROME_CONTENT_BROWSER_CLIENT_RESOURCE_COORDINATOR_PART_H_
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "chrome/browser/chrome_content_browser_client_parts.h"
+
+// Allows tracking RenderProcessHost lifetime and proffering the Resource
+// Coordinator interface to new renderers.
+class ChromeContentBrowserClientResourceCoordinatorPart
+    : public ChromeContentBrowserClientParts {
+ public:
+  ChromeContentBrowserClientResourceCoordinatorPart();
+  ~ChromeContentBrowserClientResourceCoordinatorPart() override;
+
+  // ChromeContentBrowserClientParts overrides.
+  void ExposeInterfacesToRenderer(
+      service_manager::BinderRegistry* registry,
+      blink::AssociatedInterfaceRegistry* associated_registry,
+      content::RenderProcessHost* render_process_host) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(ChromeContentBrowserClientResourceCoordinatorPart);
+};
+
+#endif  // CHROME_BROWSER_RESOURCE_COORDINATOR_CHROME_CONTENT_BROWSER_CLIENT_RESOURCE_COORDINATOR_PART_H_
diff --git a/chrome/browser/resource_coordinator/render_process_user_data.cc b/chrome/browser/resource_coordinator/render_process_user_data.cc
new file mode 100644
index 0000000..19a966a
--- /dev/null
+++ b/chrome/browser/resource_coordinator/render_process_user_data.cc
@@ -0,0 +1,80 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/resource_coordinator/render_process_user_data.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/memory/ptr_util.h"
+#include "content/public/browser/child_process_termination_info.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_process_host_observer.h"
+#include "content/public/common/service_manager_connection.h"
+#include "services/service_manager/public/cpp/connector.h"
+
+namespace resource_coordinator {
+
+namespace {
+
+const void* const kRenderProcessUserDataKey = &kRenderProcessUserDataKey;
+
+class RenderProcessLifetimeWatcher : public content::RenderProcessHostObserver {
+ public:
+  // RenderProcessHostObserver implementation.
+  void RenderProcessReady(content::RenderProcessHost* host) override {
+    RenderProcessUserData* user_data =
+        RenderProcessUserData::GetForRenderProcessHost(host);
+
+    // TODO(siggi): Rename OnProcessLaunched->OnProcessReady.
+    user_data->process_resource_coordinator()->OnProcessLaunched(
+        host->GetProcess());
+  }
+
+  void RenderProcessExited(
+      content::RenderProcessHost* host,
+      const content::ChildProcessTerminationInfo& info) override {
+    RenderProcessUserData* user_data =
+        RenderProcessUserData::GetForRenderProcessHost(host);
+
+    user_data->process_resource_coordinator()->SetProcessExitStatus(
+        info.exit_code);
+  }
+
+  void RenderProcessHostDestroyed(content::RenderProcessHost* host) override {
+    delete this;
+  }
+};
+
+service_manager::Connector* MaybeGetConnectionForProcess() {
+  if (!content::ServiceManagerConnection::GetForProcess())
+    return nullptr;
+  return content::ServiceManagerConnection::GetForProcess()->GetConnector();
+}
+
+}  // namespace
+
+RenderProcessUserData::RenderProcessUserData(
+    content::RenderProcessHost* render_process_host)
+    : process_resource_coordinator_(MaybeGetConnectionForProcess()) {
+  // The process itself shouldn't have been created at this point.
+  DCHECK(!render_process_host->GetProcess().IsValid());
+  render_process_host->AddObserver(new RenderProcessLifetimeWatcher);
+}
+
+void RenderProcessUserData::CreateForRenderProcessHost(
+    content::RenderProcessHost* host) {
+  std::unique_ptr<RenderProcessUserData> user_data =
+      base::WrapUnique(new RenderProcessUserData(host));
+
+  host->SetUserData(kRenderProcessUserDataKey, std::move(user_data));
+}
+
+RenderProcessUserData* RenderProcessUserData::GetForRenderProcessHost(
+    content::RenderProcessHost* host) {
+  return static_cast<RenderProcessUserData*>(
+      host->GetUserData(kRenderProcessUserDataKey));
+}
+
+}  // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/render_process_user_data.h b/chrome/browser/resource_coordinator/render_process_user_data.h
new file mode 100644
index 0000000..de14f2b
--- /dev/null
+++ b/chrome/browser/resource_coordinator/render_process_user_data.h
@@ -0,0 +1,43 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_RENDER_PROCESS_USER_DATA_H_
+#define CHROME_BROWSER_RESOURCE_COORDINATOR_RENDER_PROCESS_USER_DATA_H_
+
+#include "base/macros.h"
+#include "base/supports_user_data.h"
+#include "services/resource_coordinator/public/cpp/process_resource_coordinator.h"
+
+namespace content {
+
+class RenderProcessHost;
+
+}  // namespace content
+
+namespace resource_coordinator {
+
+// Attached to RenderProcessHost as user data, associates the RenderProcessHost
+// with the Resource Coordinator process node.
+class RenderProcessUserData : public base::SupportsUserData::Data {
+ public:
+  static void CreateForRenderProcessHost(content::RenderProcessHost* host);
+  static RenderProcessUserData* GetForRenderProcessHost(
+      content::RenderProcessHost* host);
+
+  ProcessResourceCoordinator* process_resource_coordinator() {
+    return &process_resource_coordinator_;
+  }
+
+ private:
+  explicit RenderProcessUserData(
+      content::RenderProcessHost* render_process_host);
+
+  ProcessResourceCoordinator process_resource_coordinator_;
+
+  DISALLOW_COPY_AND_ASSIGN(RenderProcessUserData);
+};
+
+}  // namespace resource_coordinator
+
+#endif  // CHROME_BROWSER_RESOURCE_COORDINATOR_RENDER_PROCESS_USER_DATA_H_
diff --git a/chrome/browser/resource_coordinator/tab_helper.cc b/chrome/browser/resource_coordinator/tab_helper.cc
index 88e06f05..c81116d 100644
--- a/chrome/browser/resource_coordinator/tab_helper.cc
+++ b/chrome/browser/resource_coordinator/tab_helper.cc
@@ -4,14 +4,17 @@
 
 #include "chrome/browser/resource_coordinator/tab_helper.h"
 
+#include <string>
 #include <utility>
 
 #include "base/atomic_sequence_num.h"
 #include "base/feature_list.h"
+#include "base/stl_util.h"
 #include "base/strings/string_number_conversions.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/resource_coordinator/page_signal_receiver.h"
+#include "chrome/browser/resource_coordinator/render_process_user_data.h"
 #include "chrome/browser/resource_coordinator/resource_coordinator_parts.h"
 #include "chrome/browser/resource_coordinator/tab_load_tracker.h"
 #include "chrome/browser/resource_coordinator/tab_memory_metrics_reporter.h"
@@ -36,13 +39,12 @@
     : content::WebContentsObserver(web_contents) {
   TabLoadTracker::Get()->StartTracking(web_contents);
 
-  service_manager::Connector* connector = nullptr;
   if (content::ServiceManagerConnection::GetForProcess()) {
-    connector =
+    connector_ =
         content::ServiceManagerConnection::GetForProcess()->GetConnector();
     page_resource_coordinator_ =
         std::make_unique<resource_coordinator::PageResourceCoordinator>(
-            connector);
+            connector_);
 
     // Make sure to set the visibility property when we create
     // |page_resource_coordinator_|.
@@ -76,10 +78,72 @@
             web_contents);
   }
 #endif
+
+  // Dispatch creation notifications for any pre-existing frames.
+  // This seems to occur only in tests, but dealing with this allows asserting
+  // a strong invariant on the frames_ collection.
+  std::vector<content::RenderFrameHost*> existing_frames =
+      web_contents->GetAllFrames();
+  for (content::RenderFrameHost* frame : existing_frames) {
+    // Only send notifications for live frames, the non-live ones will generate
+    // creation notifications when animated.
+    if (frame->IsRenderFrameLive())
+      RenderFrameCreated(frame);
+  }
 }
 
 ResourceCoordinatorTabHelper::~ResourceCoordinatorTabHelper() = default;
 
+void ResourceCoordinatorTabHelper::RenderFrameCreated(
+    content::RenderFrameHost* render_frame_host) {
+  DCHECK_NE(nullptr, render_frame_host);
+  // This must not exist in the map yet.
+  DCHECK(!base::ContainsKey(frames_, render_frame_host));
+
+  if (!connector_)
+    return;
+
+  std::unique_ptr<FrameResourceCoordinator> frame =
+      std::make_unique<FrameResourceCoordinator>(connector_);
+  content::RenderFrameHost* parent = render_frame_host->GetParent();
+  if (parent) {
+    DCHECK(base::ContainsKey(frames_, parent));
+    auto& parent_frame_node = frames_[parent];
+    parent_frame_node->AddChildFrame(*frame.get());
+  }
+
+  RenderProcessUserData* user_data =
+      RenderProcessUserData::GetForRenderProcessHost(
+          render_frame_host->GetProcess());
+  // In unittests the user data isn't populated as the relevant main parts
+  // is not in play.
+  // TODO(siggi): Figure out how to assert on this when the main parts are
+  //     registered with the content browser client.
+  if (user_data)
+    frame->SetProcess(*user_data->process_resource_coordinator());
+
+  frames_[render_frame_host] = std::move(frame);
+}
+
+void ResourceCoordinatorTabHelper::RenderFrameDeleted(
+    content::RenderFrameHost* render_frame_host) {
+  if (!connector_)
+    return;
+
+  // TODO(siggi): Ideally this would DCHECK that the deleted render frame host
+  //     is known, e.g. that there was a creation notification for it. This is
+  //     however not always the case. Notably these two unit_tests:
+  //       - TabsApiUnitTest.TabsGoForwardAndBack
+  //       - TabsApiUnitTest.TabsGoForwardAndBackWithoutTabId
+  //     end up issuing deletion notifications for render frame hosts never seen
+  //     before. It appears that the RenderFrameHostManager keeps a queue of
+  //     pending deletions. If a frame is already in this queue at the time
+  //     this tab helper is attached to a WebContents, the eventual deletion
+  //     notification will be singular.
+  // DCHECK(base::ContainsKey(frames_, render_frame_host));
+  frames_.erase(render_frame_host);
+}
+
 void ResourceCoordinatorTabHelper::DidStartLoading() {
   if (page_resource_coordinator_)
     page_resource_coordinator_->SetIsLoading(true);
@@ -106,6 +170,8 @@
 
 void ResourceCoordinatorTabHelper::RenderProcessGone(
     base::TerminationStatus status) {
+  // TODO(siggi): Looks like this can be acquired in a more timely manner from
+  //    the RenderProcessHostObserver.
   TabLoadTracker::Get()->RenderProcessGone(web_contents(), status);
 }
 
@@ -146,9 +212,14 @@
         navigation_handle->GetRenderFrameHost();
     // Make sure the hierarchical structure is constructed before sending signal
     // to Resource Coordinator.
-    auto* frame_resource_coordinator =
-        render_frame_host->GetFrameResourceCoordinator();
-    page_resource_coordinator_->AddFrame(*frame_resource_coordinator);
+    // TODO(siggi): Ideally this would be a DCHECK, but it seems it's possible
+    //     to get a DidFinishNavigation notification for a deleted frame when
+    //     with the network service.
+    auto it = frames_.find(render_frame_host);
+    if (it != frames_.end()) {
+      // TODO(siggi): See whether this can be done in RenderFrameCreated.
+      page_resource_coordinator_->AddFrame(*(it->second));
+    }
 
     if (navigation_handle->IsInMainFrame()) {
       if (auto* page_signal_receiver = GetPageSignalReceiver()) {
@@ -186,6 +257,19 @@
     page_resource_coordinator_->OnFaviconUpdated();
 }
 
+void ResourceCoordinatorTabHelper::OnInterfaceRequestFromFrame(
+    content::RenderFrameHost* render_frame_host,
+    const std::string& interface_name,
+    mojo::ScopedMessagePipeHandle* interface_pipe) {
+  if (interface_name != mojom::FrameCoordinationUnit::Name_)
+    return;
+
+  auto it = frames_.find(render_frame_host);
+  DCHECK(it != frames_.end());
+  it->second->AddBinding(
+      mojom::FrameCoordinationUnitRequest(std::move(*interface_pipe)));
+}
+
 void ResourceCoordinatorTabHelper::UpdateUkmRecorder(int64_t navigation_id) {
   ukm_source_id_ =
       ukm::ConvertToSourceId(navigation_id, ukm::SourceIdType::NAVIGATION_ID);
diff --git a/chrome/browser/resource_coordinator/tab_helper.h b/chrome/browser/resource_coordinator/tab_helper.h
index 88a8efd..527d676 100644
--- a/chrome/browser/resource_coordinator/tab_helper.h
+++ b/chrome/browser/resource_coordinator/tab_helper.h
@@ -5,7 +5,9 @@
 #ifndef CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_HELPER_H_
 #define CHROME_BROWSER_RESOURCE_COORDINATOR_TAB_HELPER_H_
 
+#include <map>
 #include <memory>
+#include <string>
 
 #include "base/macros.h"
 #include "base/process/kill.h"
@@ -14,8 +16,13 @@
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
 #include "services/metrics/public/cpp/ukm_source_id.h"
+#include "services/resource_coordinator/public/cpp/frame_resource_coordinator.h"
 #include "url/gurl.h"
 
+namespace service_manager {
+class Connector;
+}  // namespace service_manager
+
 namespace resource_coordinator {
 
 class PageResourceCoordinator;
@@ -33,7 +40,10 @@
     return page_resource_coordinator_.get();
   }
 
-  // WebContentsObserver implementation.
+  // WebContentsObserver overrides.
+  void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override;
+  void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override;
+
   void DidStartLoading() override;
   void DidReceiveResponse() override;
   void DidStopLoading() override;
@@ -49,6 +59,10 @@
   void TitleWasSet(content::NavigationEntry* entry) override;
   void DidUpdateFaviconURL(
       const std::vector<content::FaviconURL>& candidates) override;
+  void OnInterfaceRequestFromFrame(
+      content::RenderFrameHost* render_frame_host,
+      const std::string& interface_name,
+      mojo::ScopedMessagePipeHandle* interface_pipe) override;
 
   void UpdateUkmRecorder(int64_t navigation_id);
   ukm::SourceId ukm_source_id() const { return ukm_source_id_; }
@@ -70,6 +84,9 @@
 
   friend class content::WebContentsUserData<ResourceCoordinatorTabHelper>;
 
+  // The service manager connector for this process, if any.
+  service_manager::Connector* connector_ = nullptr;
+
   std::unique_ptr<resource_coordinator::PageResourceCoordinator>
       page_resource_coordinator_;
   ukm::SourceId ukm_source_id_ = ukm::kInvalidSourceId;
@@ -86,6 +103,10 @@
   bool first_time_favicon_set_ = false;
   bool first_time_title_set_ = false;
 
+  // Maps from RenderFrameHost to the associated RC node.
+  std::map<content::RenderFrameHost*, std::unique_ptr<FrameResourceCoordinator>>
+      frames_;
+
   WEB_CONTENTS_USER_DATA_KEY_DECL();
 
   DISALLOW_COPY_AND_ASSIGN(ResourceCoordinatorTabHelper);
diff --git a/chrome/browser/resource_coordinator/tab_memory_metrics_reporter_unittest.cc b/chrome/browser/resource_coordinator/tab_memory_metrics_reporter_unittest.cc
index 52652fc..a060877 100644
--- a/chrome/browser/resource_coordinator/tab_memory_metrics_reporter_unittest.cc
+++ b/chrome/browser/resource_coordinator/tab_memory_metrics_reporter_unittest.cc
@@ -8,6 +8,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "base/test/test_mock_time_task_runner.h"
+#include "base/timer/timer.h"
 #include "chrome/test/base/testing_profile.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_observer.h"
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn
index 11ecf6b..225195d 100644
--- a/chrome/browser/resources/BUILD.gn
+++ b/chrome/browser/resources/BUILD.gn
@@ -19,9 +19,9 @@
         "bookmarks:closure_compile",
         "discards:closure_compile",
         "downloads:closure_compile",
+        "history:closure_compile",
         "local_state:closure_compile",
         "management:closure_compile",
-        "md_history:closure_compile",
         "md_user_manager:closure_compile",
         "media_router:closure_compile",
         "ntp4:closure_compile",
diff --git a/chrome/browser/resources/md_history/BUILD.gn b/chrome/browser/resources/history/BUILD.gn
similarity index 100%
rename from chrome/browser/resources/md_history/BUILD.gn
rename to chrome/browser/resources/history/BUILD.gn
diff --git a/chrome/browser/resources/md_history/OWNERS b/chrome/browser/resources/history/OWNERS
similarity index 100%
rename from chrome/browser/resources/md_history/OWNERS
rename to chrome/browser/resources/history/OWNERS
diff --git a/chrome/browser/resources/md_history/app.html b/chrome/browser/resources/history/app.html
similarity index 100%
rename from chrome/browser/resources/md_history/app.html
rename to chrome/browser/resources/history/app.html
diff --git a/chrome/browser/resources/md_history/app.js b/chrome/browser/resources/history/app.js
similarity index 100%
rename from chrome/browser/resources/md_history/app.js
rename to chrome/browser/resources/history/app.js
diff --git a/chrome/browser/resources/md_history/browser_service.html b/chrome/browser/resources/history/browser_service.html
similarity index 100%
rename from chrome/browser/resources/md_history/browser_service.html
rename to chrome/browser/resources/history/browser_service.html
diff --git a/chrome/browser/resources/md_history/browser_service.js b/chrome/browser/resources/history/browser_service.js
similarity index 100%
rename from chrome/browser/resources/md_history/browser_service.js
rename to chrome/browser/resources/history/browser_service.js
diff --git a/chrome/browser/resources/md_history/constants.html b/chrome/browser/resources/history/constants.html
similarity index 100%
rename from chrome/browser/resources/md_history/constants.html
rename to chrome/browser/resources/history/constants.html
diff --git a/chrome/browser/resources/md_history/constants.js b/chrome/browser/resources/history/constants.js
similarity index 100%
rename from chrome/browser/resources/md_history/constants.js
rename to chrome/browser/resources/history/constants.js
diff --git a/chrome/browser/resources/md_history/externs.js b/chrome/browser/resources/history/externs.js
similarity index 100%
rename from chrome/browser/resources/md_history/externs.js
rename to chrome/browser/resources/history/externs.js
diff --git a/chrome/browser/resources/md_history/history.html b/chrome/browser/resources/history/history.html
similarity index 100%
rename from chrome/browser/resources/md_history/history.html
rename to chrome/browser/resources/history/history.html
diff --git a/chrome/browser/resources/md_history/history.js b/chrome/browser/resources/history/history.js
similarity index 100%
rename from chrome/browser/resources/md_history/history.js
rename to chrome/browser/resources/history/history.js
diff --git a/chrome/browser/resources/md_history/history_item.html b/chrome/browser/resources/history/history_item.html
similarity index 100%
rename from chrome/browser/resources/md_history/history_item.html
rename to chrome/browser/resources/history/history_item.html
diff --git a/chrome/browser/resources/md_history/history_item.js b/chrome/browser/resources/history/history_item.js
similarity index 100%
rename from chrome/browser/resources/md_history/history_item.js
rename to chrome/browser/resources/history/history_item.js
diff --git a/chrome/browser/resources/md_history/history_list.html b/chrome/browser/resources/history/history_list.html
similarity index 100%
rename from chrome/browser/resources/md_history/history_list.html
rename to chrome/browser/resources/history/history_list.html
diff --git a/chrome/browser/resources/md_history/history_list.js b/chrome/browser/resources/history/history_list.js
similarity index 100%
rename from chrome/browser/resources/md_history/history_list.js
rename to chrome/browser/resources/history/history_list.js
diff --git a/chrome/browser/resources/md_history/history_toolbar.html b/chrome/browser/resources/history/history_toolbar.html
similarity index 100%
rename from chrome/browser/resources/md_history/history_toolbar.html
rename to chrome/browser/resources/history/history_toolbar.html
diff --git a/chrome/browser/resources/md_history/history_toolbar.js b/chrome/browser/resources/history/history_toolbar.js
similarity index 100%
rename from chrome/browser/resources/md_history/history_toolbar.js
rename to chrome/browser/resources/history/history_toolbar.js
diff --git a/chrome/browser/resources/md_history/icons.html b/chrome/browser/resources/history/icons.html
similarity index 100%
rename from chrome/browser/resources/md_history/icons.html
rename to chrome/browser/resources/history/icons.html
diff --git a/chrome/browser/resources/md_history/images/100/sign_in_promo.jpg b/chrome/browser/resources/history/images/100/sign_in_promo.jpg
similarity index 100%
rename from chrome/browser/resources/md_history/images/100/sign_in_promo.jpg
rename to chrome/browser/resources/history/images/100/sign_in_promo.jpg
Binary files differ
diff --git a/chrome/browser/resources/md_history/images/200/sign_in_promo.jpg b/chrome/browser/resources/history/images/200/sign_in_promo.jpg
similarity index 100%
rename from chrome/browser/resources/md_history/images/200/sign_in_promo.jpg
rename to chrome/browser/resources/history/images/200/sign_in_promo.jpg
Binary files differ
diff --git a/chrome/browser/resources/md_history/lazy_load.html b/chrome/browser/resources/history/lazy_load.html
similarity index 100%
rename from chrome/browser/resources/md_history/lazy_load.html
rename to chrome/browser/resources/history/lazy_load.html
diff --git a/chrome/browser/resources/md_history/query_manager.html b/chrome/browser/resources/history/query_manager.html
similarity index 100%
rename from chrome/browser/resources/md_history/query_manager.html
rename to chrome/browser/resources/history/query_manager.html
diff --git a/chrome/browser/resources/md_history/query_manager.js b/chrome/browser/resources/history/query_manager.js
similarity index 100%
rename from chrome/browser/resources/md_history/query_manager.js
rename to chrome/browser/resources/history/query_manager.js
diff --git a/chrome/browser/resources/md_history/router.html b/chrome/browser/resources/history/router.html
similarity index 100%
rename from chrome/browser/resources/md_history/router.html
rename to chrome/browser/resources/history/router.html
diff --git a/chrome/browser/resources/md_history/router.js b/chrome/browser/resources/history/router.js
similarity index 100%
rename from chrome/browser/resources/md_history/router.js
rename to chrome/browser/resources/history/router.js
diff --git a/chrome/browser/resources/md_history/searched_label.html b/chrome/browser/resources/history/searched_label.html
similarity index 100%
rename from chrome/browser/resources/md_history/searched_label.html
rename to chrome/browser/resources/history/searched_label.html
diff --git a/chrome/browser/resources/md_history/searched_label.js b/chrome/browser/resources/history/searched_label.js
similarity index 100%
rename from chrome/browser/resources/md_history/searched_label.js
rename to chrome/browser/resources/history/searched_label.js
diff --git a/chrome/browser/resources/md_history/shared_style.html b/chrome/browser/resources/history/shared_style.html
similarity index 100%
rename from chrome/browser/resources/md_history/shared_style.html
rename to chrome/browser/resources/history/shared_style.html
diff --git a/chrome/browser/resources/md_history/shared_vars.html b/chrome/browser/resources/history/shared_vars.html
similarity index 100%
rename from chrome/browser/resources/md_history/shared_vars.html
rename to chrome/browser/resources/history/shared_vars.html
diff --git a/chrome/browser/resources/md_history/side_bar.html b/chrome/browser/resources/history/side_bar.html
similarity index 100%
rename from chrome/browser/resources/md_history/side_bar.html
rename to chrome/browser/resources/history/side_bar.html
diff --git a/chrome/browser/resources/md_history/side_bar.js b/chrome/browser/resources/history/side_bar.js
similarity index 100%
rename from chrome/browser/resources/md_history/side_bar.js
rename to chrome/browser/resources/history/side_bar.js
diff --git a/chrome/browser/resources/md_history/strings.html b/chrome/browser/resources/history/strings.html
similarity index 100%
rename from chrome/browser/resources/md_history/strings.html
rename to chrome/browser/resources/history/strings.html
diff --git a/chrome/browser/resources/md_history/synced_device_card.html b/chrome/browser/resources/history/synced_device_card.html
similarity index 100%
rename from chrome/browser/resources/md_history/synced_device_card.html
rename to chrome/browser/resources/history/synced_device_card.html
diff --git a/chrome/browser/resources/md_history/synced_device_card.js b/chrome/browser/resources/history/synced_device_card.js
similarity index 100%
rename from chrome/browser/resources/md_history/synced_device_card.js
rename to chrome/browser/resources/history/synced_device_card.js
diff --git a/chrome/browser/resources/md_history/synced_device_manager.html b/chrome/browser/resources/history/synced_device_manager.html
similarity index 100%
rename from chrome/browser/resources/md_history/synced_device_manager.html
rename to chrome/browser/resources/history/synced_device_manager.html
diff --git a/chrome/browser/resources/md_history/synced_device_manager.js b/chrome/browser/resources/history/synced_device_manager.js
similarity index 100%
rename from chrome/browser/resources/md_history/synced_device_manager.js
rename to chrome/browser/resources/history/synced_device_manager.js
diff --git a/chrome/browser/resources/md_user_manager/user_manager.html b/chrome/browser/resources/md_user_manager/user_manager.html
index 1c306c2..606774f 100644
--- a/chrome/browser/resources/md_user_manager/user_manager.html
+++ b/chrome/browser/resources/md_user_manager/user_manager.html
@@ -360,7 +360,6 @@
     <error-dialog></error-dialog>
     <include src="../../../../ui/login/account_picker/user_pod_template.html">
   </user-manager-pages>
-  <link rel="import" href="chrome://resources/html/i18n_template.html">
   <script src="user_manager.js"></script>
 </body>
 </html>
diff --git a/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.js b/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.js
index f0b6481..138238ac 100644
--- a/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.js
+++ b/chrome/browser/resources/media_router/elements/media_router_header/media_router_header.js
@@ -97,7 +97,7 @@
   },
 
   attached: function() {
-    // isRTL() only works after i18n_template.js runs to set <html dir>.
+    // isRTL() only works after <html dir> is set.
     // Set the back button icon based on text direction.
     this.arrowDropIcon_ = isRTL() ? 'cr:arrow-forward' : 'cr:arrow-back';
   },
diff --git a/chrome/browser/resources/media_router/media_router.html b/chrome/browser/resources/media_router/media_router.html
index 30c6046..f40477a 100644
--- a/chrome/browser/resources/media_router/media_router.html
+++ b/chrome/browser/resources/media_router/media_router.html
@@ -16,6 +16,5 @@
 </head>
 <body>
   <media-router-container id="media-router-container"></media-router-container>
-  <link rel="import" href="chrome://resources/html/i18n_template.html">
 </body>
 </html>
diff --git a/chrome/browser/resources/print_preview/new/destination_settings.js b/chrome/browser/resources/print_preview/new/destination_settings.js
index 9f7b60c..907a64f6 100644
--- a/chrome/browser/resources/print_preview/new/destination_settings.js
+++ b/chrome/browser/resources/print_preview/new/destination_settings.js
@@ -107,12 +107,6 @@
 
     const recentDestinations = [];
     let update = false;
-    let filterAccount = this.activeUser;
-    // Fallback to the account for the current destination, in case activeUser
-    // is not known yet from cloudprint.
-    if (!filterAccount) {
-      filterAccount = this.destination ? this.destination.account : '';
-    }
     const existingKeys = this.recentDestinationList_ ?
         this.recentDestinationList_.map(listItem => listItem.key) :
         [];
@@ -120,7 +114,7 @@
       const key = print_preview.createRecentDestinationKey(recentDestination);
       const destination = this.destinationStore.getDestinationByKey(key);
       if (destination && !this.destinationIsDriveOrPdf_(recentDestination) &&
-          (!destination.account || destination.account == filterAccount)) {
+          (!destination.account || destination.account == this.activeUser)) {
         recentDestinations.push(destination);
         update = update || !existingKeys.includes(key);
       }
diff --git a/chrome/browser/safe_browsing/certificate_reporting_service_factory.cc b/chrome/browser/safe_browsing/certificate_reporting_service_factory.cc
index 5a4607e..8272b90 100644
--- a/chrome/browser/safe_browsing/certificate_reporting_service_factory.cc
+++ b/chrome/browser/safe_browsing/certificate_reporting_service_factory.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/safe_browsing/certificate_reporting_service_factory.h"
 
+#include "base/bind_helpers.h"
 #include "base/time/default_clock.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/srt_delete_extension_win_unittest.cc b/chrome/browser/safe_browsing/chrome_cleaner/srt_delete_extension_win_unittest.cc
index 74efd594..b3cbde5 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/srt_delete_extension_win_unittest.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/srt_delete_extension_win_unittest.cc
@@ -7,6 +7,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/feature_list.h"
 #include "base/location.h"
 #include "base/macros.h"
diff --git a/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc b/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc
index 17104b6..873a0c26 100644
--- a/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc
+++ b/chrome/browser/safe_browsing/chrome_cleaner/srt_field_trial_win.cc
@@ -39,19 +39,19 @@
 
 constexpr char kSRTPromptTrial[] = "SRTPromptFieldTrial";
 
-constexpr base::Feature kRebootPromptDialogFeature{
+const base::Feature kRebootPromptDialogFeature{
     "RebootPromptDialog", base::FEATURE_DISABLED_BY_DEFAULT};
 
-constexpr base::Feature kUserInitiatedChromeCleanupsFeature{
+const base::Feature kUserInitiatedChromeCleanupsFeature{
     "UserInitiatedChromeCleanups", base::FEATURE_ENABLED_BY_DEFAULT};
 
-constexpr base::Feature kChromeCleanupDistributionFeature{
+const base::Feature kChromeCleanupDistributionFeature{
     "ChromeCleanupDistribution", base::FEATURE_DISABLED_BY_DEFAULT};
 
-constexpr base::Feature kChromeCleanupQuarantineFeature{
+const base::Feature kChromeCleanupQuarantineFeature{
     "ChromeCleanupQuarantine", base::FEATURE_DISABLED_BY_DEFAULT};
 
-constexpr base::Feature kChromeCleanupExtensionsFeature{
+const base::Feature kChromeCleanupExtensionsFeature{
     "ChromeCleanupExtensions", base::FEATURE_DISABLED_BY_DEFAULT};
 
 bool IsInSRTPromptFieldTrialGroups() {
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.h b/chrome/browser/safe_browsing/chrome_password_protection_service.h
index e3892a7..a8ffe8e9 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service.h
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service.h
@@ -8,6 +8,7 @@
 #include <map>
 
 #include "base/observer_list.h"
+#include "base/timer/timer.h"
 #include "build/build_config.h"
 #include "components/safe_browsing/password_protection/password_protection_service.h"
 #include "components/safe_browsing/triggers/trigger_manager.h"
diff --git a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
index b87c98e..ca3e4043 100644
--- a/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
+++ b/chrome/browser/safe_browsing/client_side_detection_host_unittest.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
diff --git a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h
index d38e96b..9cecb26 100644
--- a/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h
+++ b/chrome/browser/safe_browsing/safe_browsing_navigation_observer_manager.h
@@ -8,6 +8,7 @@
 #include "base/containers/circular_deque.h"
 #include "base/feature_list.h"
 #include "base/supports_user_data.h"
+#include "base/timer/timer.h"
 #include "components/safe_browsing/browser/referrer_chain_provider.h"
 #include "components/safe_browsing/proto/csd.pb.h"
 #include "components/sessions/core/session_id.h"
diff --git a/chrome/browser/sessions/better_session_restore_browsertest.cc b/chrome/browser/sessions/better_session_restore_browsertest.cc
index 6fc01b5..67d5f776 100644
--- a/chrome/browser/sessions/better_session_restore_browsertest.cc
+++ b/chrome/browser/sessions/better_session_restore_browsertest.cc
@@ -34,7 +34,6 @@
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/startup/startup_browser_creator.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/webui/md_history_ui.h"
 #include "chrome/common/buildflags.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/common/url_constants.h"
diff --git a/chrome/browser/sessions/session_data_deleter.cc b/chrome/browser/sessions/session_data_deleter.cc
index 7edc8a5f..3670587 100644
--- a/chrome/browser/sessions/session_data_deleter.cc
+++ b/chrome/browser/sessions/session_data_deleter.cc
@@ -6,6 +6,7 @@
 #include <stdint.h>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
diff --git a/chrome/browser/sessions/tab_loader_tester.h b/chrome/browser/sessions/tab_loader_tester.h
index ed6a950..6aeca249 100644
--- a/chrome/browser/sessions/tab_loader_tester.h
+++ b/chrome/browser/sessions/tab_loader_tester.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_SESSIONS_TAB_LOADER_TESTER_H_
 #define CHROME_BROWSER_SESSIONS_TAB_LOADER_TESTER_H_
 
+#include "base/timer/timer.h"
 #include "chrome/browser/sessions/tab_loader.h"
 
 // Wraps a TabLoader and exposes helper functions for testing. See tab_loader.h
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc
index 32d3edf9..623f33d7 100644
--- a/chrome/browser/signin/chrome_signin_client.cc
+++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -284,18 +284,18 @@
   if (type == network::mojom::ConnectionType::CONNECTION_NONE)
     return;
 
-  for (const base::Closure& callback : delayed_callbacks_)
-    callback.Run();
+  for (base::OnceClosure& callback : delayed_callbacks_)
+    std::move(callback).Run();
 
   delayed_callbacks_.clear();
 }
 #endif
 
-void ChromeSigninClient::DelayNetworkCall(const base::Closure& callback) {
+void ChromeSigninClient::DelayNetworkCall(base::OnceClosure callback) {
 #if defined(OS_CHROMEOS)
   chromeos::DelayNetworkCall(
       base::TimeDelta::FromMilliseconds(chromeos::kDefaultNetworkRetryDelayMS),
-      callback);
+      std::move(callback));
   return;
 #else
   // Don't bother if we don't have any kind of network connection.
@@ -305,9 +305,9 @@
                             weak_ptr_factory_.GetWeakPtr()));
   if (!sync || type == network::mojom::ConnectionType::CONNECTION_NONE) {
     // Connection type cannot be retrieved synchronously so delay the callback.
-    delayed_callbacks_.push_back(callback);
+    delayed_callbacks_.push_back(std::move(callback));
   } else {
-    callback.Run();
+    std::move(callback).Run();
   }
 #endif
 }
diff --git a/chrome/browser/signin/chrome_signin_client.h b/chrome/browser/signin/chrome_signin_client.h
index b9de346..eda1659 100644
--- a/chrome/browser/signin/chrome_signin_client.h
+++ b/chrome/browser/signin/chrome_signin_client.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_SIGNIN_CHROME_SIGNIN_CLIENT_H_
 #define CHROME_BROWSER_SIGNIN_CHROME_SIGNIN_CLIENT_H_
 
+#include <list>
+
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
@@ -55,7 +57,7 @@
       content_settings::Observer* observer) override;
   void RemoveContentSettingsObserver(
       content_settings::Observer* observer) override;
-  void DelayNetworkCall(const base::Closure& callback) override;
+  void DelayNetworkCall(base::OnceClosure callback) override;
   std::unique_ptr<GaiaAuthFetcher> CreateGaiaAuthFetcher(
       GaiaAuthConsumer* consumer,
       gaia::GaiaSource source,
@@ -115,7 +117,7 @@
   base::OnceCallback<void(SignoutDecision)> on_signout_decision_reached_;
 
 #if !defined(OS_CHROMEOS)
-  std::list<base::Closure> delayed_callbacks_;
+  std::list<base::OnceClosure> delayed_callbacks_;
 #endif
 
   bool should_display_user_manager_ = true;
diff --git a/chrome/browser/signin/chrome_signin_client_unittest.cc b/chrome/browser/signin/chrome_signin_client_unittest.cc
index 814daf2a..aa25805 100644
--- a/chrome/browser/signin/chrome_signin_client_unittest.cc
+++ b/chrome/browser/signin/chrome_signin_client_unittest.cc
@@ -95,7 +95,7 @@
   SetUpNetworkConnection(true, network::mojom::ConnectionType::CONNECTION_3G);
   CallbackTester tester;
   signin_client()->DelayNetworkCall(
-      base::Bind(&CallbackTester::Increment, base::Unretained(&tester)));
+      base::BindOnce(&CallbackTester::Increment, base::Unretained(&tester)));
   ASSERT_TRUE(tester.WasCalledExactlyOnce());
 }
 
@@ -105,8 +105,8 @@
   base::RunLoop run_loop;
   CallbackTester tester;
   signin_client()->DelayNetworkCall(
-      base::Bind(&CallbackTester::IncrementAndUnblock,
-                 base::Unretained(&tester), &run_loop));
+      base::BindOnce(&CallbackTester::IncrementAndUnblock,
+                     base::Unretained(&tester), &run_loop));
   ASSERT_FALSE(tester.WasCalledExactlyOnce());
   run_loop.Run();  // Wait for IncrementAndUnblock().
   ASSERT_TRUE(tester.WasCalledExactlyOnce());
@@ -118,8 +118,8 @@
   base::RunLoop run_loop;
   CallbackTester tester;
   signin_client()->DelayNetworkCall(
-      base::Bind(&CallbackTester::IncrementAndUnblock,
-                 base::Unretained(&tester), &run_loop));
+      base::BindOnce(&CallbackTester::IncrementAndUnblock,
+                     base::Unretained(&tester), &run_loop));
 
   ASSERT_FALSE(tester.WasCalledExactlyOnce());
   SetConnectionType(network::mojom::ConnectionType::CONNECTION_3G);
diff --git a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory_unittest.cc b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory_unittest.cc
index f4070974..1e9cfd84 100644
--- a/chrome/browser/signin/chrome_signin_proxying_url_loader_factory_unittest.cc
+++ b/chrome/browser/signin/chrome_signin_proxying_url_loader_factory_unittest.cc
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/test/mock_callback.h"
diff --git a/chrome/browser/spellchecker/spellcheck_service_browsertest.cc b/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
index 2156d411..638fe31 100644
--- a/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
+++ b/chrome/browser/spellchecker/spellcheck_service_browsertest.cc
@@ -38,6 +38,7 @@
 #include "content/public/test/mock_render_process_host.h"
 #include "content/public/test/test_utils.h"
 #include "mojo/public/cpp/bindings/binding.h"
+#include "services/service_manager/public/cpp/connector.h"
 
 using content::BrowserContext;
 using content::RenderProcessHost;
diff --git a/chrome/browser/storage/durable_storage_permission_context_unittest.cc b/chrome/browser/storage/durable_storage_permission_context_unittest.cc
index 62641cb..188b8fa 100644
--- a/chrome/browser/storage/durable_storage_permission_context_unittest.cc
+++ b/chrome/browser/storage/durable_storage_permission_context_unittest.cc
@@ -7,6 +7,7 @@
 #include <string>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
diff --git a/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc b/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc
index e6e2b8f..89404d3 100644
--- a/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_directory_sync_test.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/bind_helpers.h"
 #include "base/files/file_enumerator.h"
 #include "base/files/file_path.h"
 #include "base/location.h"
diff --git a/chrome/browser/sync/test/integration/typed_urls_helper.cc b/chrome/browser/sync/test/integration/typed_urls_helper.cc
index 734d7838..7e0f5d3 100644
--- a/chrome/browser/sync/test/integration/typed_urls_helper.cc
+++ b/chrome/browser/sync/test/integration/typed_urls_helper.cc
@@ -10,6 +10,7 @@
 #include <sstream>
 
 #include "base/big_endian.h"
+#include "base/bind_helpers.h"
 #include "base/compiler_specific.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_worker.cc b/chrome/browser/sync_file_system/drive_backend/sync_worker.cc
index a2a93bc..a36b9b3 100644
--- a/chrome/browser/sync_file_system/drive_backend/sync_worker.cc
+++ b/chrome/browser/sync_file_system/drive_backend/sync_worker.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "chrome/browser/extensions/extension_service.h"
 #include "chrome/browser/sync_file_system/drive_backend/callback_helper.h"
 #include "chrome/browser/sync_file_system/drive_backend/conflict_resolver.h"
diff --git a/chrome/browser/sync_file_system/local/local_file_sync_context.cc b/chrome/browser/sync_file_system/local/local_file_sync_context.cc
index 3933454..660d8554 100644
--- a/chrome/browser/sync_file_system/local/local_file_sync_context.cc
+++ b/chrome/browser/sync_file_system/local/local_file_sync_context.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_util.h"
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
diff --git a/chrome/browser/task_manager/providers/crostini/crostini_process_task.cc b/chrome/browser/task_manager/providers/crostini/crostini_process_task.cc
index 1163f7f..11c737b 100644
--- a/chrome/browser/task_manager/providers/crostini/crostini_process_task.cc
+++ b/chrome/browser/task_manager/providers/crostini/crostini_process_task.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/task_manager/providers/crostini/crostini_process_task.h"
 
+#include "base/bind_helpers.h"
 #include "base/i18n/rtl.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/chromeos/crostini/crostini_manager.h"
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index b6e78e6..4430a22e 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1116,6 +1116,8 @@
       "webui/help/version_updater.h",
       "webui/history_login_handler.cc",
       "webui/history_login_handler.h",
+      "webui/history_ui.cc",
+      "webui/history_ui.h",
       "webui/identity_internals_ui.cc",
       "webui/identity_internals_ui.h",
       "webui/inspect_ui.cc",
@@ -1126,8 +1128,6 @@
       "webui/management_ui.h",
       "webui/management_ui_handler.cc",
       "webui/management_ui_handler.h",
-      "webui/md_history_ui.cc",
-      "webui/md_history_ui.h",
       "webui/media_router/media_router_dialog_controller_webui_impl.cc",
       "webui/media_router/media_router_dialog_controller_webui_impl.h",
       "webui/media_router/media_router_internals_ui.cc",
diff --git a/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc b/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc
index 8b53762..8ef7969d 100644
--- a/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc
+++ b/chrome/browser/ui/app_list/app_list_client_impl_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include <stddef.h>
 
+#include "ash/public/cpp/app_list/app_list_features.h"
 #include "ash/public/cpp/app_list/app_list_switches.h"
 #include "base/command_line.h"
 #include "base/macros.h"
@@ -11,6 +12,7 @@
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind_test_util.h"
+#include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
 #include "chrome/browser/browser_process.h"
@@ -200,6 +202,14 @@
 // Test showing search results, and uninstalling one of them while displayed.
 IN_PROC_BROWSER_TEST_F(AppListClientSearchResultsBrowserTest,
                        UninstallSearchResult) {
+  // Zero state changes UI behavior. This test case tests the expected UI
+  // behavior with zero state being disabled.
+  // TODO(jennyz): write new test case for zero state, crbug.com/925195.
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndDisableFeature(
+      app_list_features::kEnableZeroStateSuggestions);
+  ASSERT_FALSE(app_list_features::IsZeroStateSuggestionsEnabled());
+
   base::FilePath test_extension_path;
   ASSERT_TRUE(
       base::PathService::Get(chrome::DIR_TEST_DATA, &test_extension_path));
diff --git a/chrome/browser/ui/app_list/crostini/crostini_app_context_menu.cc b/chrome/browser/ui/app_list/crostini/crostini_app_context_menu.cc
index ef73e52d..0155ddf 100644
--- a/chrome/browser/ui/app_list/crostini/crostini_app_context_menu.cc
+++ b/chrome/browser/ui/app_list/crostini/crostini_app_context_menu.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/ui/app_list/crostini/crostini_app_context_menu.h"
 
 #include "ash/public/cpp/app_menu_constants.h"
+#include "base/bind_helpers.h"
 #include "chrome/browser/chromeos/crostini/crostini_manager.h"
 #include "chrome/browser/chromeos/crostini/crostini_registry_service.h"
 #include "chrome/browser/chromeos/crostini/crostini_registry_service_factory.h"
diff --git a/chrome/browser/ui/app_list/search/dictionary_data_store.cc b/chrome/browser/ui/app_list/search/dictionary_data_store.cc
index bf59b590..c57a92b 100644
--- a/chrome/browser/ui/app_list/search/dictionary_data_store.cc
+++ b/chrome/browser/ui/app_list/search/dictionary_data_store.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/json/json_file_value_serializer.h"
 #include "base/json/json_string_value_serializer.h"
 #include "base/lazy_instance.h"
diff --git a/chrome/browser/ui/ash/cast_config_client_media_router.cc b/chrome/browser/ui/ash/cast_config_client_media_router.cc
index 29f8b852..6311742 100644
--- a/chrome/browser/ui/ash/cast_config_client_media_router.cc
+++ b/chrome/browser/ui/ash/cast_config_client_media_router.cc
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "ash/public/interfaces/constants.mojom.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/optional.h"
 #include "base/strings/string_util.h"
diff --git a/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui_unittest.cc b/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui_unittest.cc
index 7b07324..d04a165 100644
--- a/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui_unittest.cc
+++ b/chrome/browser/ui/ash/keyboard/chrome_keyboard_ui_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "base/bind_helpers.h"
 #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "chrome/test/base/test_chrome_web_ui_controller_factory.h"
diff --git a/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc b/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc
index 4e2f4b9..5743d7d 100644
--- a/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc
+++ b/chrome/browser/ui/ash/keyboard/keyboard_controller_browsertest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
index fd11337..33064285 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
@@ -16,6 +16,7 @@
 #include "ash/public/cpp/window_animation_types.h"
 #include "ash/public/interfaces/constants.mojom.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/strings/pattern.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
index b6da61e..06f3204 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_unittest.cc
@@ -25,6 +25,7 @@
 #include "ash/public/cpp/window_properties.h"
 #include "ash/shelf/shelf_application_menu_model.h"
 #include "ash/shelf/shelf_controller.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
 #include "base/files/file_path.h"
diff --git a/chrome/browser/ui/ash/launcher/crostini_shelf_context_menu.cc b/chrome/browser/ui/ash/launcher/crostini_shelf_context_menu.cc
index 188bdd9..999bee63 100644
--- a/chrome/browser/ui/ash/launcher/crostini_shelf_context_menu.cc
+++ b/chrome/browser/ui/ash/launcher/crostini_shelf_context_menu.cc
@@ -9,6 +9,7 @@
 
 #include "ash/public/cpp/app_menu_constants.h"
 #include "ash/public/cpp/shelf_item.h"
+#include "base/bind_helpers.h"
 #include "chrome/browser/chromeos/crostini/crostini_registry_service.h"
 #include "chrome/browser/chromeos/crostini/crostini_registry_service_factory.h"
 #include "chrome/browser/chromeos/crostini/crostini_util.h"
diff --git a/chrome/browser/ui/autofill/save_card_bubble_controller_impl_browsertest.cc b/chrome/browser/ui/autofill/save_card_bubble_controller_impl_browsertest.cc
index 44740e6..c0faa56 100644
--- a/chrome/browser/ui/autofill/save_card_bubble_controller_impl_browsertest.cc
+++ b/chrome/browser/ui/autofill/save_card_bubble_controller_impl_browsertest.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "base/bind_helpers.h"
 #include "base/json/json_reader.h"
 #include "base/macros.h"
 #include "base/test/scoped_feature_list.h"
diff --git a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
index 3cde2e7..ac9ec63d 100644
--- a/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
+++ b/chrome/browser/ui/blocked_content/popup_blocker_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include <stdint.h>
 
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
diff --git a/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc b/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
index 8a0f983..8d4afa7 100644
--- a/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
+++ b/chrome/browser/ui/find_bar/find_bar_host_browsertest.cc
@@ -27,7 +27,6 @@
 #include "chrome/browser/ui/find_bar/find_tab_helper.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/views_mode_controller.h"
-#include "chrome/browser/ui/webui/md_history_ui.h"
 #include "chrome/common/url_constants.h"
 #include "chrome/test/base/find_in_page_observer.h"
 #include "chrome/test/base/in_process_browser_test.h"
diff --git a/chrome/browser/ui/global_error/global_error_browsertest.cc b/chrome/browser/ui/global_error/global_error_browsertest.cc
index d1f3710..ff0b184 100644
--- a/chrome/browser/ui/global_error/global_error_browsertest.cc
+++ b/chrome/browser/ui/global_error/global_error_browsertest.cc
@@ -5,6 +5,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/task/post_task.h"
diff --git a/chrome/browser/ui/login/login_handler.cc b/chrome/browser/ui/login/login_handler.cc
index c5b8fb7..d3c1ea3 100644
--- a/chrome/browser/ui/login/login_handler.cc
+++ b/chrome/browser/ui/login/login_handler.cc
@@ -531,21 +531,19 @@
   }
 }
 
-// static
 void LoginHandler::ShowLoginPrompt(const GURL& request_url,
-                                   net::AuthChallengeInfo* auth_info,
-                                   LoginHandler* handler) {
+                                   net::AuthChallengeInfo* auth_info) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  WebContents* parent_contents = handler->GetWebContentsForLogin();
+  WebContents* parent_contents = GetWebContentsForLogin();
   if (!parent_contents) {
-    handler->CancelAuth();
+    CancelAuth();
     return;
   }
   prerender::PrerenderContents* prerender_contents =
       prerender::PrerenderContents::FromWebContents(parent_contents);
   if (prerender_contents) {
     prerender_contents->Destroy(prerender::FINAL_STATUS_AUTH_NEEDED);
-    handler->CancelAuth();
+    CancelAuth();
     return;
   }
 
@@ -554,7 +552,7 @@
   GetDialogStrings(request_url, *auth_info, &authority, &explanation);
 
   password_manager::PasswordManager* password_manager =
-      handler->GetPasswordManagerForLogin();
+      GetPasswordManagerForLogin();
 
   if (!password_manager) {
 #if BUILDFLAG(ENABLE_EXTENSIONS)
@@ -565,11 +563,11 @@
     if (guest &&
         extensions::GetViewType(guest->owner_web_contents()) !=
             extensions::VIEW_TYPE_EXTENSION_BACKGROUND_PAGE) {
-      handler->BuildViewWithoutPasswordManager(authority, explanation);
+      BuildViewWithoutPasswordManager(authority, explanation);
       return;
     }
 #endif
-    handler->CancelAuth();
+    CancelAuth();
     return;
   }
 
@@ -582,26 +580,24 @@
   }
 
   PasswordForm observed_form(
-      LoginHandler::MakeInputForPasswordManager(request_url, *auth_info));
-  handler->BuildViewWithPasswordManager(authority, explanation,
-                                        password_manager, observed_form);
+      MakeInputForPasswordManager(request_url, *auth_info));
+  BuildViewWithPasswordManager(authority, explanation, password_manager,
+                               observed_form);
 }
 
-// static
 void LoginHandler::LoginDialogCallback(
     const GURL& request_url,
     const content::GlobalRequestID& request_id,
     net::AuthChallengeInfo* auth_info,
     scoped_refptr<net::HttpResponseHeaders> response_headers,
-    LoginHandler* handler,
     bool is_main_frame) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  WebContents* parent_contents = handler->GetWebContentsForLogin();
-  if (!parent_contents || handler->WasAuthHandled()) {
+  WebContents* parent_contents = GetWebContentsForLogin();
+  if (!parent_contents || WasAuthHandled()) {
     // The request may have been canceled, or it may be for a renderer not
     // hosted by a tab (e.g. an extension). Cancel just in case (canceling twice
     // is a no-op).
-    handler->CancelAuth();
+    CancelAuth();
     return;
   }
 
@@ -612,9 +608,9 @@
   auto* api =
       extensions::BrowserContextKeyedAPIFactory<extensions::WebRequestAPI>::Get(
           parent_contents->GetBrowserContext());
-  auto continuation = base::BindOnce(&LoginHandler::MaybeSetUpLoginPrompt,
-                                     request_url, base::RetainedRef(auth_info),
-                                     base::RetainedRef(handler), is_main_frame);
+  auto continuation =
+      base::BindOnce(&LoginHandler::MaybeSetUpLoginPrompt, this, request_url,
+                     base::RetainedRef(auth_info), is_main_frame);
   if (api->MaybeProxyAuthRequest(auth_info, std::move(response_headers),
                                  request_id, is_main_frame,
                                  std::move(continuation))) {
@@ -622,36 +618,34 @@
   }
 #endif
 
-  MaybeSetUpLoginPrompt(request_url, auth_info, handler, is_main_frame,
-                        base::nullopt, false /* should_cancel */);
+  MaybeSetUpLoginPrompt(request_url, auth_info, is_main_frame, base::nullopt,
+                        false /* should_cancel */);
 }
 
-// static
 void LoginHandler::MaybeSetUpLoginPrompt(
     const GURL& request_url,
     net::AuthChallengeInfo* auth_info,
-    LoginHandler* handler,
     bool is_request_for_main_frame,
     const base::Optional<net::AuthCredentials>& credentials,
     bool should_cancel) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
-  WebContents* parent_contents = handler->GetWebContentsForLogin();
-  if (!parent_contents || handler->WasAuthHandled()) {
+  WebContents* parent_contents = GetWebContentsForLogin();
+  if (!parent_contents || WasAuthHandled()) {
     // The request may have been canceled, or it may be for a renderer not
     // hosted by a tab (e.g. an extension). Cancel just in case (canceling twice
     // is a no-op).
-    handler->CancelAuth();
+    CancelAuth();
     return;
   }
 
   if (should_cancel) {
-    handler->CancelAuth();
+    CancelAuth();
     return;
   }
 
   if (credentials) {
-    handler->SetAuth(credentials->username(), credentials->password());
+    SetAuth(credentials->username(), credentials->password());
     return;
   }
 
@@ -693,15 +687,15 @@
 
     // Show a blank interstitial for main-frame, cross origin requests
     // so that the correct URL is shown in the omnibox.
-    base::Closure callback =
-        base::Bind(&LoginHandler::ShowLoginPrompt, request_url,
-                   base::RetainedRef(auth_info), base::RetainedRef(handler));
+    base::OnceClosure callback =
+        base::BindOnce(&LoginHandler::ShowLoginPrompt, this, request_url,
+                       base::RetainedRef(auth_info));
     // The interstitial delegate is owned by the interstitial that it creates.
     // This cancels any existing interstitial.
-    handler->SetInterstitialDelegate(
+    SetInterstitialDelegate(
         (new LoginInterstitialDelegate(
              parent_contents, auth_info->is_proxy ? GURL() : request_url,
-             callback))
+             std::move(callback)))
             ->GetWeakPtr());
 
   } else {
@@ -712,7 +706,7 @@
                                    ? AUTH_PROMPT_TYPE_SUBRESOURCE_CROSS_ORIGIN
                                    : AUTH_PROMPT_TYPE_SUBRESOURCE_SAME_ORIGIN);
     }
-    ShowLoginPrompt(request_url, auth_info, handler);
+    ShowLoginPrompt(request_url, auth_info);
   }
 }
 
@@ -730,8 +724,8 @@
       auth_info, web_contents_getter, std::move(auth_required_callback));
   base::PostTaskWithTraits(
       FROM_HERE, {BrowserThread::UI},
-      base::BindOnce(&LoginHandler::LoginDialogCallback, url, request_id,
-                     base::RetainedRef(auth_info), std::move(response_headers),
-                     base::RetainedRef(handler), is_request_for_main_frame));
+      base::BindOnce(&LoginHandler::LoginDialogCallback, handler, url,
+                     request_id, base::RetainedRef(auth_info),
+                     std::move(response_headers), is_request_for_main_frame));
   return handler;
 }
diff --git a/chrome/browser/ui/login/login_handler.h b/chrome/browser/ui/login/login_handler.h
index 107e052..d5b4feae 100644
--- a/chrome/browser/ui/login/login_handler.h
+++ b/chrome/browser/ui/login/login_handler.h
@@ -200,9 +200,8 @@
                                base::string16* authority,
                                base::string16* explanation);
 
-  static void ShowLoginPrompt(const GURL& request_url,
-                              net::AuthChallengeInfo* auth_info,
-                              LoginHandler* handler);
+  void ShowLoginPrompt(const GURL& request_url,
+                       net::AuthChallengeInfo* auth_info);
 
   // This callback is run on the UI thread and creates a constrained window with
   // a LoginView to prompt the user. If the prompt is triggered because of a
@@ -211,12 +210,11 @@
   // created directly in this callback. In both cases, the response will be sent
   // to LoginHandler, which then routes it to the net::URLRequest on the I/O
   // thread.
-  static void LoginDialogCallback(
+  void LoginDialogCallback(
       const GURL& request_url,
       const content::GlobalRequestID& request_id,
       net::AuthChallengeInfo* auth_info,
       scoped_refptr<net::HttpResponseHeaders> response_headers,
-      LoginHandler* handler,
       bool is_main_frame);
 
   // Continuation from |LoginDialogCallback()| after any potential interception
@@ -224,10 +222,9 @@
   // request is cancelled. Otherwise |credentials| are used if supplied. Finally
   // if the request is NOT cancelled AND |credentials| is empty, then we'll
   // actually show a login prompt.
-  static void MaybeSetUpLoginPrompt(
+  void MaybeSetUpLoginPrompt(
       const GURL& request_url,
       net::AuthChallengeInfo* auth_info,
-      LoginHandler* handler,
       bool is_main_frame,
       const base::Optional<net::AuthCredentials>& credentials,
       bool should_cancel);
diff --git a/chrome/browser/ui/login/login_interstitial_delegate.cc b/chrome/browser/ui/login/login_interstitial_delegate.cc
index e114774..e98c39c6 100644
--- a/chrome/browser/ui/login/login_interstitial_delegate.cc
+++ b/chrome/browser/ui/login/login_interstitial_delegate.cc
@@ -4,6 +4,8 @@
 
 #include "chrome/browser/ui/login/login_interstitial_delegate.h"
 
+#include <utility>
+
 const content::InterstitialPageDelegate::TypeID
     LoginInterstitialDelegate::kTypeForTesting =
         &LoginInterstitialDelegate::kTypeForTesting;
@@ -11,8 +13,8 @@
 LoginInterstitialDelegate::LoginInterstitialDelegate(
     content::WebContents* web_contents,
     const GURL& request_url,
-    base::Closure& callback)
-    : callback_(callback),
+    base::OnceClosure callback)
+    : callback_(std::move(callback)),
       interstitial_page_(content::InterstitialPage::Create(web_contents,
                                                            true,
                                                            request_url,
@@ -39,7 +41,7 @@
 }
 
 void LoginInterstitialDelegate::CommandReceived(const std::string& command) {
-  callback_.Run();
+  std::move(callback_).Run();
 }
 
 content::InterstitialPageDelegate::TypeID
diff --git a/chrome/browser/ui/login/login_interstitial_delegate.h b/chrome/browser/ui/login/login_interstitial_delegate.h
index 73af4f24..c63bd0e4 100644
--- a/chrome/browser/ui/login/login_interstitial_delegate.h
+++ b/chrome/browser/ui/login/login_interstitial_delegate.h
@@ -27,7 +27,7 @@
 
   LoginInterstitialDelegate(content::WebContents* web_contents,
                             const GURL& request_url,
-                            base::Closure& callback);
+                            base::OnceClosure callback);
 
   ~LoginInterstitialDelegate() override;
 
@@ -43,7 +43,7 @@
   std::string GetHTMLContents() override;
 
  private:
-  base::Closure callback_;
+  base::OnceClosure callback_;
   content::InterstitialPage* interstitial_page_;
   base::WeakPtrFactory<LoginInterstitialDelegate> weak_ptr_factory_;
 
diff --git a/chrome/browser/ui/media_router/media_router_ui_base.cc b/chrome/browser/ui/media_router/media_router_ui_base.cc
index c7b8301..14a91ef 100644
--- a/chrome/browser/ui/media_router/media_router_ui_base.cc
+++ b/chrome/browser/ui/media_router/media_router_ui_base.cc
@@ -15,6 +15,7 @@
 #include "base/macros.h"
 #include "base/stl_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/timer/timer.h"
 #include "build/build_config.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/media/router/issue_manager.h"
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.h b/chrome/browser/ui/passwords/manage_passwords_ui_controller.h
index aecc71a..f3630591 100644
--- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.h
+++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.h
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/passwords/manage_passwords_state.h"
 #include "chrome/browser/ui/passwords/passwords_client_ui_delegate.h"
 #include "chrome/browser/ui/passwords/passwords_model_delegate.h"
diff --git a/chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.cc b/chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.cc
index 518ef94..5142dbd2 100644
--- a/chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.cc
+++ b/chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.cc
@@ -5,8 +5,6 @@
 #include "chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.h"
 
 #include "chrome/browser/download/download_stats.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
 
@@ -18,18 +16,14 @@
   // WebContents.
   auto* guest_view =
       extensions::MimeHandlerViewGuest::FromWebContents(web_contents);
-  if (guest_view)
-    return guest_view->embedder_web_contents();
-  return web_contents;
+  return guest_view ? guest_view->embedder_web_contents() : web_contents;
 }
 
 }  // namespace
 
-ChromePDFWebContentsHelperClient::ChromePDFWebContentsHelperClient() {
-}
+ChromePDFWebContentsHelperClient::ChromePDFWebContentsHelperClient() = default;
 
-ChromePDFWebContentsHelperClient::~ChromePDFWebContentsHelperClient() {
-}
+ChromePDFWebContentsHelperClient::~ChromePDFWebContentsHelperClient() = default;
 
 void ChromePDFWebContentsHelperClient::UpdateContentRestrictions(
     content::WebContents* contents,
@@ -49,7 +43,7 @@
 
 void ChromePDFWebContentsHelperClient::OnPDFHasUnsupportedFeature(
     content::WebContents* contents) {
-  // There is no more Adobe pluging for PDF so there is not much we can do in
+  // There is no more Adobe plugin for PDF so there is not much we can do in
   // this case. Maybe simply download the file.
 }
 
diff --git a/chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.h b/chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.h
index 96192cf..ca84997 100644
--- a/chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.h
+++ b/chrome/browser/ui/pdf/chrome_pdf_web_contents_helper_client.h
@@ -18,9 +18,7 @@
   // pdf::PDFWebContentsHelperClient:
   void UpdateContentRestrictions(content::WebContents* contents,
                                  int content_restrictions) override;
-
   void OnPDFHasUnsupportedFeature(content::WebContents* contents) override;
-
   void OnSaveURL(content::WebContents* contents) override;
 
   DISALLOW_COPY_AND_ASSIGN(ChromePDFWebContentsHelperClient);
diff --git a/chrome/browser/ui/tab_helpers.cc b/chrome/browser/ui/tab_helpers.cc
index 1d92544..6aafa39a 100644
--- a/chrome/browser/ui/tab_helpers.cc
+++ b/chrome/browser/ui/tab_helpers.cc
@@ -295,8 +295,7 @@
   LookalikeUrlNavigationObserver::CreateForWebContents(web_contents);
   ManagePasswordsUIController::CreateForWebContents(web_contents);
   pdf::PDFWebContentsHelper::CreateForWebContentsWithClient(
-      web_contents, std::unique_ptr<pdf::PDFWebContentsHelperClient>(
-                        new ChromePDFWebContentsHelperClient()));
+      web_contents, std::make_unique<ChromePDFWebContentsHelperClient>());
   PluginObserver::CreateForWebContents(web_contents);
   SadTabHelper::CreateForWebContents(web_contents);
   safe_browsing::SafeBrowsingTabObserver::CreateForWebContents(web_contents);
diff --git a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc
index 498bdc0..98dac6d 100644
--- a/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc
+++ b/chrome/browser/ui/toolbar/recent_tabs_sub_menu_model_unittest.cc
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
diff --git a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_browsertest.cc b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_browsertest.cc
index c2bbe01..d8891a2 100644
--- a/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_browsertest.cc
+++ b/chrome/browser/ui/views/apps/app_info_dialog/app_info_dialog_views_browsertest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <string>
 
+#include "base/bind_helpers.h"
 #include "build/build_config.h"
 #include "chrome/browser/extensions/test_extension_environment.h"
 #include "chrome/browser/ui/browser.h"
diff --git a/chrome/browser/ui/views/crostini/crostini_upgrade_container_view_browsertest.cc b/chrome/browser/ui/views/crostini/crostini_upgrade_container_view_browsertest.cc
index 54afc14..6783b90a 100644
--- a/chrome/browser/ui/views/crostini/crostini_upgrade_container_view_browsertest.cc
+++ b/chrome/browser/ui/views/crostini/crostini_upgrade_container_view_browsertest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/views/crostini/crostini_upgrade_container_view.h"
 
+#include "base/bind_helpers.h"
 #include "base/metrics/histogram_base.h"
 #include "base/run_loop.h"
 #include "base/test/metrics/histogram_tester.h"
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.h b/chrome/browser/ui/views/extensions/extension_install_dialog_view.h
index 8eea22c..b1ab63d0 100644
--- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.h
+++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.h
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "base/macros.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/extensions/extension_install_prompt.h"
 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
 #include "ui/views/controls/button/button.h"
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
index 1edc3db..65fceee 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash_browsertest.cc
@@ -19,10 +19,11 @@
 #include "ash/public/interfaces/shelf_test_api.test-mojom.h"
 #include "ash/public/interfaces/shell_test_api.test-mojom-test-utils.h"
 #include "ash/public/interfaces/window_pin_type.mojom.h"
-#include "ash/shell.h"                                   // mash-ok
-#include "ash/wm/overview/overview_controller.h"         // mash-ok
-#include "ash/wm/splitview/split_view_controller.h"      // mash-ok
-#include "ash/wm/tablet_mode/tablet_mode_controller.h"   // mash-ok
+#include "ash/shell.h"                                  // mash-ok
+#include "ash/wm/overview/overview_controller.h"        // mash-ok
+#include "ash/wm/splitview/split_view_controller.h"     // mash-ok
+#include "ash/wm/tablet_mode/tablet_mode_controller.h"  // mash-ok
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/scoped_observer.h"
 #include "base/test/metrics/histogram_tester.h"
diff --git a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
index 1ce55ab..368ee50 100644
--- a/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
+++ b/chrome/browser/ui/views/frame/immersive_mode_controller_ash.cc
@@ -53,18 +53,24 @@
   LocatedEventRetargeter() {}
   ~LocatedEventRetargeter() override {}
 
-  ui::EventDispatchDetails RewriteEvent(
+  ui::EventRewriteStatus RewriteEvent(
       const ui::Event& event,
-      const base::WeakPtr<Continuation> continuation) override {
+      std::unique_ptr<ui::Event>* rewritten_event) override {
     if (!event.IsLocatedEvent())
-      return SendEvent(continuation, &event);
+      return ui::EVENT_REWRITE_CONTINUE;
 
-    std::unique_ptr<ui::Event> replacement_event = ui::Event::Clone(event);
+    *rewritten_event = ui::Event::Clone(event);
     // Cloning strips the EventTarget. The only goal of this EventRewriter is to
     // null the target, so there's no need to do anything extra here.
-    DCHECK(!replacement_event->target());
+    DCHECK(!(*rewritten_event)->target());
 
-    return SendEventFinally(continuation, replacement_event.get());
+    return ui::EVENT_REWRITE_REWRITTEN;
+  }
+
+  ui::EventRewriteStatus NextDispatchEvent(
+      const ui::Event& last_event,
+      std::unique_ptr<ui::Event>* new_event) override {
+    return ui::EVENT_REWRITE_CONTINUE;
   }
 
  private:
@@ -112,7 +118,7 @@
 void ImmersiveModeControllerAsh::Init(BrowserView* browser_view) {
   browser_view_ = browser_view;
   controller_->Init(this, browser_view_->frame(),
-                    browser_view_->top_container());
+      browser_view_->top_container());
 
   observed_windows_.Add(
       !features::IsUsingWindowService()
@@ -267,15 +273,15 @@
   browser_view_->frame()->GetFrameView()->UpdateClientArea();
 }
 
-std::vector<gfx::Rect> ImmersiveModeControllerAsh::GetVisibleBoundsInScreen()
-    const {
+std::vector<gfx::Rect>
+ImmersiveModeControllerAsh::GetVisibleBoundsInScreen() const {
   views::View* top_container_view = browser_view_->top_container();
   gfx::Rect top_container_view_bounds = top_container_view->GetVisibleBounds();
   // TODO(tdanderson): Implement View::ConvertRectToScreen().
   gfx::Point top_container_view_bounds_in_screen_origin(
       top_container_view_bounds.origin());
-  views::View::ConvertPointToScreen(
-      top_container_view, &top_container_view_bounds_in_screen_origin);
+  views::View::ConvertPointToScreen(top_container_view,
+      &top_container_view_bounds_in_screen_origin);
   gfx::Rect top_container_view_bounds_in_screen(
       top_container_view_bounds_in_screen_origin,
       top_container_view_bounds.size());
@@ -295,8 +301,8 @@
     return;
 
   // Auto hide the shelf in immersive browser fullscreen.
-  bool in_tab_fullscreen = content::Source<FullscreenController>(source)
-                               ->IsWindowFullscreenForTabOrPending();
+  bool in_tab_fullscreen = content::Source<FullscreenController>(source)->
+      IsWindowFullscreenForTabOrPending();
   browser_view_->GetNativeWindow()->SetProperty(
       ash::kHideShelfWhenFullscreenKey, in_tab_fullscreen);
 }
diff --git a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc
index b69d459..78422d1 100644
--- a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc
+++ b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc
@@ -13,6 +13,7 @@
 #include "ash/public/interfaces/cros_display_config.mojom-test-utils.h"
 #include "ash/public/interfaces/cros_display_config.mojom.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/path_service.h"
 #include "base/strings/safe_sprintf.h"
diff --git a/chrome/browser/ui/views/login_handler_views.cc b/chrome/browser/ui/views/login_handler_views.cc
index fc05cfc..ca3d909 100644
--- a/chrome/browser/ui/views/login_handler_views.cc
+++ b/chrome/browser/ui/views/login_handler_views.cc
@@ -18,14 +18,15 @@
 #include "ui/views/widget/widget.h"
 #include "ui/views/window/dialog_delegate.h"
 
-// ----------------------------------------------------------------------------
-// LoginHandlerViews
+namespace chrome {
+
+namespace {
 
 // This class simply forwards the authentication from the LoginView (on
 // the UI thread) to the net::URLRequest (on the I/O thread).
 // This class uses ref counting to ensure that it lives until all InvokeLaters
 // have been called.
-class LoginHandlerViews : public LoginHandler, public views::DialogDelegate {
+class LoginHandlerViews : public LoginHandler {
  public:
   LoginHandlerViews(
       net::AuthChallengeInfo* auth_info,
@@ -33,67 +34,8 @@
       LoginAuthRequiredCallback auth_required_callback)
       : LoginHandler(auth_info,
                      web_contents_getter,
-                     std::move(auth_required_callback)),
-        login_view_(nullptr),
-        dialog_(nullptr) {
-    chrome::RecordDialogCreation(chrome::DialogIdentifier::LOGIN_HANDLER);
-  }
-
-  // views::DialogDelegate:
-  bool ShouldShowCloseButton() const override { return false; }
-
-  base::string16 GetDialogButtonLabel(ui::DialogButton button) const override {
-    if (button == ui::DIALOG_BUTTON_OK)
-      return l10n_util::GetStringUTF16(IDS_LOGIN_DIALOG_OK_BUTTON_LABEL);
-    return DialogDelegate::GetDialogButtonLabel(button);
-  }
-
-  base::string16 GetWindowTitle() const override {
-    return l10n_util::GetStringUTF16(IDS_LOGIN_DIALOG_TITLE);
-  }
-
-  void WindowClosing() override {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-    // Reference is no longer valid.
-    dialog_ = NULL;
-    CancelAuth();
-  }
-
-  void DeleteDelegate() override {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-
-    // The widget is going to delete itself; clear our pointer.
-    dialog_ = NULL;
-
-    // This Release is the counter-point to the AddRef() in BuildViewImpl().
-    Release();
-
-    ReleaseSoon();
-  }
-
-  ui::ModalType GetModalType() const override { return ui::MODAL_TYPE_CHILD; }
-
-  bool Cancel() override {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-    CancelAuth();
-    return true;
-  }
-
-  bool Accept() override {
-    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-    SetAuth(login_view_->GetUsername(), login_view_->GetPassword());
-    return true;
-  }
-
-  views::View* GetInitiallyFocusedView() override {
-    return login_view_->GetInitiallyFocusedView();
-  }
-
-  views::View* GetContentsView() override { return login_view_; }
-  views::Widget* GetWidget() override { return login_view_->GetWidget(); }
-  const views::Widget* GetWidget() const override {
-    return login_view_->GetWidget();
+                     std::move(auth_required_callback)) {
+    RecordDialogCreation(DialogIdentifier::LOGIN_HANDLER);
   }
 
   // LoginHandler:
@@ -101,50 +43,134 @@
                      const base::string16& explanation,
                      LoginModelData* login_model_data) override {
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+    DCHECK(!dialog_);
 
-    // Create a new LoginView and set the model for it.  The model (password
-    // manager) is owned by the WebContents, but the view is parented to the
-    // browser window, so the view may be destroyed after the password
-    // manager. The view listens for model destruction and unobserves
-    // accordingly.
-    login_view_ = new LoginView(authority, explanation, login_model_data);
-
-    // Views requires the WidgetDelegate [this instance] live longer than the
-    // Widget. To enforce this, we AddRef() here and Release() in
-    // DeleteDelegate().
-    AddRef();
-
-    // Scary thread safety note: This can potentially be called *after* SetAuth
-    // or CancelAuth (say, if the request was cancelled before the UI thread got
-    // control).  However, that's OK since any UI interaction in those functions
-    // will occur via an InvokeLater on the UI thread, which is guaranteed
-    // to happen after this is called (since this was InvokeLater'd first).
-    dialog_ = constrained_window::ShowWebModalDialogViews(
-        this, GetWebContentsForLogin());
+    dialog_ = new Dialog(this, GetWebContentsForLogin(), authority, explanation,
+                         login_model_data);
     NotifyAuthNeeded();
   }
 
   void CloseDialog() override {
     // The hosting widget may have been freed.
-    if (dialog_)
-      dialog_->Close();
+    if (dialog_) {
+      dialog_->CloseDialog();
+      dialog_ = nullptr;
+    }
   }
 
  private:
   friend class base::RefCountedThreadSafe<LoginHandlerViews>;
-  friend class LoginPrompt;
 
-  ~LoginHandlerViews() override {}
+  ~LoginHandlerViews() override = default;
 
-  // The LoginView that contains the user's login information.
-  LoginView* login_view_;
+  void OnDialogDestroyed() { dialog_ = nullptr; }
 
-  views::Widget* dialog_;
+  // The DialogDelegate is a separate object from LoginHandlerViews so it can be
+  // owned by the views hierarchy (see DeleteDelegate).
+  class Dialog : public views::DialogDelegate {
+   public:
+    // Creates a Dialog which reports the results back to |handler|. Note the
+    // Dialog is responsible for its own lifetime, which may be independent of
+    // |handler|. |handler| may decide to close the Dialog, by calling
+    // CloseDialog, or the Dialog may have been destroyed by the views
+    // hierarchy, in which case it will call handler->OnDialogDestroyed. When
+    // one of these methods is called, whichever comes first, each object must
+    // release pointers to the other.
+    Dialog(LoginHandlerViews* handler,
+           content::WebContents* web_contents,
+           const base::string16& authority,
+           const base::string16& explanation,
+           LoginHandler::LoginModelData* login_model_data)
+        : handler_(handler), login_view_(nullptr), widget_(nullptr) {
+      // Create a new LoginView and set the model for it.  The model (password
+      // manager) is owned by the WebContents, but the view is parented to the
+      // browser window, so the view may be destroyed after the password
+      // manager. The view listens for model destruction and unobserves
+      // accordingly.
+      login_view_ = new LoginView(authority, explanation, login_model_data);
+
+      // ShowWebModalDialogViews takes ownership of this, by way of the
+      // DeleteDelegate method.
+      widget_ = constrained_window::ShowWebModalDialogViews(this, web_contents);
+    }
+
+    void CloseDialog() {
+      handler_ = nullptr;
+      // The hosting widget may have been freed.
+      if (widget_)
+        widget_->Close();
+    }
+
+    // views::DialogDelegate:
+    bool ShouldShowCloseButton() const override { return false; }
+
+    base::string16 GetDialogButtonLabel(
+        ui::DialogButton button) const override {
+      if (button == ui::DIALOG_BUTTON_OK)
+        return l10n_util::GetStringUTF16(IDS_LOGIN_DIALOG_OK_BUTTON_LABEL);
+      return DialogDelegate::GetDialogButtonLabel(button);
+    }
+
+    base::string16 GetWindowTitle() const override {
+      return l10n_util::GetStringUTF16(IDS_LOGIN_DIALOG_TITLE);
+    }
+
+    void WindowClosing() override {
+      // Reference is no longer valid.
+      widget_ = nullptr;
+      if (handler_)
+        handler_->CancelAuth();
+    }
+
+    void DeleteDelegate() override { delete this; }
+
+    ui::ModalType GetModalType() const override { return ui::MODAL_TYPE_CHILD; }
+
+    bool Cancel() override {
+      DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+      if (handler_)
+        handler_->CancelAuth();
+      return true;
+    }
+
+    bool Accept() override {
+      DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+      if (handler_)
+        handler_->SetAuth(login_view_->GetUsername(),
+                          login_view_->GetPassword());
+      return true;
+    }
+
+    views::View* GetInitiallyFocusedView() override {
+      return login_view_->GetInitiallyFocusedView();
+    }
+
+    views::View* GetContentsView() override { return login_view_; }
+    views::Widget* GetWidget() override { return login_view_->GetWidget(); }
+    const views::Widget* GetWidget() const override {
+      return login_view_->GetWidget();
+    }
+
+   private:
+    ~Dialog() override {
+      if (handler_)
+        handler_->OnDialogDestroyed();
+    }
+
+    LoginHandlerViews* handler_;
+    // The LoginView that contains the user's login information.
+    LoginView* login_view_;
+    views::Widget* widget_;
+
+    DISALLOW_COPY_AND_ASSIGN(Dialog);
+  };
+
+  Dialog* dialog_ = nullptr;
 
   DISALLOW_COPY_AND_ASSIGN(LoginHandlerViews);
 };
 
-namespace chrome {
+}  // namespace
 
 scoped_refptr<LoginHandler> CreateLoginHandlerViews(
     net::AuthChallengeInfo* auth_info,
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.h b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
index 84feecc..8114922 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.h
@@ -96,6 +96,13 @@
   bool SelectionAtBeginning() const;
   bool SelectionAtEnd() const;
 
+  // Returns the width in pixels needed to display the current text. The
+  // returned value includes margins.
+  int GetTextWidth() const;
+
+  // Returns the omnibox's width in pixels.
+  int GetWidth() const;
+
   // OmniboxView:
   void EmphasizeURLComponents() override;
   void Update() override;
@@ -114,7 +121,6 @@
   void SelectAll(bool reversed) override;
   void RevertAll() override;
   void SetFocus() override;
-  int GetTextWidth() const override;
   bool IsImeComposing() const override;
 
   // views::Textfield:
@@ -211,7 +217,6 @@
   bool OnAfterPossibleChange(bool allow_keyword_ui_change) override;
   gfx::NativeView GetNativeView() const override;
   gfx::NativeView GetRelativeWindowForPopup() const override;
-  int GetWidth() const override;
   bool IsImeShowingPopup() const override;
   void ShowVirtualKeyboardIfEnabled() override;
   void HideImeIfNeeded() override;
diff --git a/chrome/browser/ui/views/overlay/overlay_window_views.h b/chrome/browser/ui/views/overlay/overlay_window_views.h
index 2f1e974c..3dc6d17 100644
--- a/chrome/browser/ui/views/overlay/overlay_window_views.h
+++ b/chrome/browser/ui/views/overlay/overlay_window_views.h
@@ -7,6 +7,7 @@
 
 #include "content/public/browser/overlay_window.h"
 
+#include "base/timer/timer.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/widget/widget.h"
diff --git a/chrome/browser/ui/views/passwords/password_auto_sign_in_view.h b/chrome/browser/ui/views/passwords/password_auto_sign_in_view.h
index a514f421..8b603dd7 100644
--- a/chrome/browser/ui/views/passwords/password_auto_sign_in_view.h
+++ b/chrome/browser/ui/views/passwords/password_auto_sign_in_view.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_UI_VIEWS_PASSWORDS_PASSWORD_AUTO_SIGN_IN_VIEW_H_
 
 #include "base/scoped_observer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/views/passwords/password_bubble_view_base.h"
 #include "ui/views/controls/button/button.h"
 #include "ui/views/widget/widget.h"
diff --git a/chrome/browser/ui/views/profiles/incognito_window_count_view.cc b/chrome/browser/ui/views/profiles/incognito_window_count_view.cc
index 9002105..40759a9a 100644
--- a/chrome/browser/ui/views/profiles/incognito_window_count_view.cc
+++ b/chrome/browser/ui/views/profiles/incognito_window_count_view.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/views/profiles/incognito_window_count_view.h"
 
+#include "base/bind_helpers.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/platform_util.h"
 #include "chrome/browser/ui/browser.h"
diff --git a/chrome/browser/ui/views/ssl_client_certificate_selector_mac_browsertest.mm b/chrome/browser/ui/views/ssl_client_certificate_selector_mac_browsertest.mm
index 065f6c9f..6e7c86a 100644
--- a/chrome/browser/ui/views/ssl_client_certificate_selector_mac_browsertest.mm
+++ b/chrome/browser/ui/views/ssl_client_certificate_selector_mac_browsertest.mm
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #import "base/mac/mac_util.h"
 #include "base/macros.h"
 #include "chrome/browser/ssl/ssl_client_certificate_selector.h"
diff --git a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
index 5446f84..e04dde33 100644
--- a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/bind.h"
 #include "base/macros.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/layout_constants.h"
 #include "chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h"
 #include "chrome/browser/ui/views/tabs/new_tab_button.h"
diff --git a/chrome/browser/ui/webui/OWNERS b/chrome/browser/ui/webui/OWNERS
index 85a2e866..5e97af03 100644
--- a/chrome/browser/ui/webui/OWNERS
+++ b/chrome/browser/ui/webui/OWNERS
@@ -8,7 +8,7 @@
 per-file inspect_ui*=dgozman@chromium.org
 per-file inspect_ui*=pfeldman@chromium.org
 
-per-file md_history_ui*=calamity@chromium.org
+per-file history_ui*=calamity@chromium.org
 
 per-file memory_internals_ui*=erikchen@chromium.org
 
diff --git a/chrome/browser/ui/webui/browsing_history_handler_unittest.cc b/chrome/browser/ui/webui/browsing_history_handler_unittest.cc
index cdc2311..b0310cb 100644
--- a/chrome/browser/ui/webui/browsing_history_handler_unittest.cc
+++ b/chrome/browser/ui/webui/browsing_history_handler_unittest.cc
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
index 668bf06f..9e0f8a5 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -130,7 +130,7 @@
 #include "chrome/browser/ui/webui/inspect_ui.h"
 #include "chrome/browser/ui/webui/bookmarks/bookmarks_ui.h"
 #include "chrome/browser/ui/webui/downloads/downloads_ui.h"
-#include "chrome/browser/ui/webui/md_history_ui.h"
+#include "chrome/browser/ui/webui/history_ui.h"
 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
 #include "chrome/browser/ui/webui/page_not_available_for_guest/page_not_available_for_guest_ui.h"
 #include "chrome/browser/ui/webui/sync_file_system_internals/sync_file_system_internals_ui.h"
diff --git a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h
index 99cf45c..07836e09 100644
--- a/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h
+++ b/chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "ash/public/interfaces/assistant_controller.mojom.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/macros.h"
 #include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_utils.h"
diff --git a/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc b/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
index e391082..46e535b 100644
--- a/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
+++ b/chrome/browser/ui/webui/chromeos/drive_internals_ui.cc
@@ -12,6 +12,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_enumerator.h"
 #include "base/files/file_util.h"
 #include "base/format_macros.h"
diff --git a/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc b/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc
index b8b8f19..6920cd8 100644
--- a/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/emulator/device_emulator_message_handler.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/values.h"
diff --git a/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc
index 55f85c3c..408d98c 100644
--- a/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/assistant_optin_flow_screen_handler.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/metrics/histogram_macros.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/chromeos/login/oobe_screen.h"
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc b/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc
index f9b37cc..095fab6 100644
--- a/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc
+++ b/chrome/browser/ui/webui/chromeos/login/oobe_display_chooser.cc
@@ -8,6 +8,7 @@
 
 #include "ash/public/interfaces/constants.mojom.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/task/post_task.h"
 #include "chrome/browser/ui/ash/ash_util.h"
diff --git a/chrome/browser/ui/webui/md_history_ui.cc b/chrome/browser/ui/webui/history_ui.cc
similarity index 99%
rename from chrome/browser/ui/webui/md_history_ui.cc
rename to chrome/browser/ui/webui/history_ui.cc
index aeb6d5b..e1ba4983 100644
--- a/chrome/browser/ui/webui/md_history_ui.cc
+++ b/chrome/browser/ui/webui/history_ui.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 "chrome/browser/ui/webui/md_history_ui.h"
+#include "chrome/browser/ui/webui/history_ui.h"
 
 #include <memory>
 #include <string>
diff --git a/chrome/browser/ui/webui/md_history_ui.h b/chrome/browser/ui/webui/history_ui.h
similarity index 85%
rename from chrome/browser/ui/webui/md_history_ui.h
rename to chrome/browser/ui/webui/history_ui.h
index 709cef0..71b2e1bb 100644
--- a/chrome/browser/ui/webui/md_history_ui.h
+++ b/chrome/browser/ui/webui/history_ui.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_BROWSER_UI_WEBUI_MD_HISTORY_UI_H_
-#define CHROME_BROWSER_UI_WEBUI_MD_HISTORY_UI_H_
+#ifndef CHROME_BROWSER_UI_WEBUI_HISTORY_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_HISTORY_UI_H_
 
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
@@ -37,4 +37,4 @@
   DISALLOW_COPY_AND_ASSIGN(MdHistoryUI);
 };
 
-#endif  // CHROME_BROWSER_UI_WEBUI_MD_HISTORY_UI_H_
+#endif  // CHROME_BROWSER_UI_WEBUI_HISTORY_UI_H_
diff --git a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
index 0999b24..00d7313 100644
--- a/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/local_discovery/local_discovery_ui_browsertest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/compiler_specific.h"
diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
index ff1c8c4b..c900de6 100644
--- a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
+++ b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/memory/weak_ptr.h"
diff --git a/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc b/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc
index b951b85..a2d092d 100644
--- a/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc
+++ b/chrome/browser/ui/webui/print_preview/pdf_printer_handler_win_unittest.cc
@@ -9,6 +9,7 @@
 #include <commdlg.h>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/run_loop.h"
diff --git a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
index 7efa92b6..95320dd 100644
--- a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.cc
@@ -247,14 +247,6 @@
   RefreshUI();
 }
 
-void AccountManagerUIHandler::OnAccountUpdateFailed(
-    const std::string& account_id) {
-  // An account fetch failed for |account_id|, but we must display the account
-  // anyways (if it was not being displayed already) so that users do not think
-  // that their account has suddenly disappeared.
-  RefreshUI();
-}
-
 void AccountManagerUIHandler::OnAccountRemoved(const AccountInfo& account_key) {
 }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h
index 2b2a1918..e97cfdb9 100644
--- a/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/account_manager_handler.h
@@ -44,7 +44,6 @@
 
   // |AccountTrackerService::Observer| overrides.
   void OnAccountUpdated(const AccountInfo& info) override;
-  void OnAccountUpdateFailed(const std::string& account_id) override;
   void OnAccountRemoved(const AccountInfo& account_key) override;
 
  private:
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
index 7932d706..759c07ed 100644
--- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -103,7 +103,7 @@
   // Behavior for querying a non-IPP uri is undefined and disallowed.
   if (!IsIppUri(printer_uri) || !optional.has_value()) {
     PRINTER_LOG(ERROR) << "Printer uri is invalid: " << printer_uri;
-    callback.Run(false, "", "", "", false);
+    callback.Run(false, "", "", "", {}, false);
     return;
   }
 
@@ -423,7 +423,7 @@
 
   if (printer_address.empty()) {
     // Run the failure callback.
-    OnAutoconfQueried(callback_id, false, "", "", "", false);
+    OnAutoconfQueried(callback_id, false, "", "", "", {}, false);
     return;
   }
 
@@ -452,6 +452,7 @@
     const std::string& make,
     const std::string& model,
     const std::string& make_and_model,
+    const std::vector<std::string>& document_formats,
     bool ipp_everywhere) {
   RecordIppQuerySuccess(success);
 
@@ -488,12 +489,14 @@
   FireManuallyAddDiscoveredPrinter(*printer);
 }
 
-void CupsPrintersHandler::OnAutoconfQueried(const std::string& callback_id,
-                                            bool success,
-                                            const std::string& make,
-                                            const std::string& model,
-                                            const std::string& make_and_model,
-                                            bool ipp_everywhere) {
+void CupsPrintersHandler::OnAutoconfQueried(
+    const std::string& callback_id,
+    bool success,
+    const std::string& make,
+    const std::string& model,
+    const std::string& make_and_model,
+    const std::vector<std::string>& document_formats,
+    bool ipp_everywhere) {
   RecordIppQuerySuccess(success);
 
   if (!success) {
@@ -521,8 +524,11 @@
     return;
   }
 
-  PpdProvider::PrinterSearchData ppd_search_data;
+  PrinterSearchData ppd_search_data;
+  ppd_search_data.discovery_type =
+      PrinterSearchData::PrinterDiscoveryType::kManual;
   ppd_search_data.make_and_model.push_back(make_and_model);
+  ppd_search_data.supported_document_formats = document_formats;
 
   // Try to resolve the PPD matching.
   ppd_provider_->ResolvePpdReference(
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
index f6b4aa1..0362548 100644
--- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
+++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.h
@@ -68,15 +68,18 @@
                          const std::string& make,
                          const std::string& model,
                          const std::string& make_and_model,
+                         const std::vector<std::string>& document_formats,
                          bool ipp_everywhere);
 
   // Handles the callback for HandleGetPrinterInfo for a discovered printer.
-  void OnAutoconfQueriedDiscovered(std::unique_ptr<Printer> printer,
-                                   bool success,
-                                   const std::string& make,
-                                   const std::string& model,
-                                   const std::string& make_and_model,
-                                   bool ipp_everywhere);
+  void OnAutoconfQueriedDiscovered(
+      std::unique_ptr<Printer> printer,
+      bool success,
+      const std::string& make,
+      const std::string& model,
+      const std::string& make_and_model,
+      const std::vector<std::string>& document_formats,
+      bool ipp_everywhere);
 
   // Callback for PPD matching attempts;
   void OnPpdResolved(const std::string& callback_id,
diff --git a/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc b/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc
index 3f42503..af5e73cd 100644
--- a/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/google_assistant_handler.cc
@@ -9,6 +9,7 @@
 #include "ash/public/interfaces/assistant_controller.mojom.h"
 #include "ash/public/interfaces/constants.mojom.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/values.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/chromeos/assistant_optin/assistant_optin_ui.h"
diff --git a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
index ba8af47a..b0234504 100644
--- a/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
+++ b/chrome/browser/ui/webui/settings/site_settings_handler_unittest.cc
@@ -8,6 +8,7 @@
 #include <string>
 #include <utility>
 
+#include "base/bind_helpers.h"
 #include "base/json/json_reader.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/simple_test_clock.h"
diff --git a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
index 91b4e01..2bfcee6c 100644
--- a/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
+++ b/chrome/browser/ui/webui/signin/user_manager_screen_handler.cc
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
diff --git a/chrome/browser/ui/webui/site_settings_helper_unittest.cc b/chrome/browser/ui/webui/site_settings_helper_unittest.cc
index 197fef1..f8bab84 100644
--- a/chrome/browser/ui/webui/site_settings_helper_unittest.cc
+++ b/chrome/browser/ui/webui/site_settings_helper_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/webui/site_settings_helper.h"
 
+#include "base/bind_helpers.h"
 #include "base/guid.h"
 #include "base/json/json_reader.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
diff --git a/chrome/browser/ui/webui/snippets_internals/snippets_internals_page_handler.h b/chrome/browser/ui/webui/snippets_internals/snippets_internals_page_handler.h
index 7922e21..b134684 100644
--- a/chrome/browser/ui/webui/snippets_internals/snippets_internals_page_handler.h
+++ b/chrome/browser/ui/webui/snippets_internals/snippets_internals_page_handler.h
@@ -7,6 +7,7 @@
 
 #include "base/macros.h"
 #include "base/scoped_observer.h"
+#include "base/timer/timer.h"
 #include "chrome/browser/ui/webui/snippets_internals/snippets_internals.mojom.h"
 #include "components/ntp_snippets/content_suggestions_service.h"
 #include "components/ntp_snippets/remote/remote_suggestions_provider.h"
diff --git a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_browsertest.cc b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_browsertest.cc
index 3ed5690..253a37da 100644
--- a/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_browsertest.cc
+++ b/chrome/browser/web_applications/extensions/pending_bookmark_app_manager_browsertest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/web_applications/extensions/pending_bookmark_app_manager.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/optional.h"
 #include "base/run_loop.h"
diff --git a/chrome/browser/web_applications/web_app_icon_manager_unittest.cc b/chrome/browser/web_applications/web_app_icon_manager_unittest.cc
index 961e45a..a1b610cb 100644
--- a/chrome/browser/web_applications/web_app_icon_manager_unittest.cc
+++ b/chrome/browser/web_applications/web_app_icon_manager_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/web_applications/web_app_icon_manager.h"
 
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/test/bind_test_util.h"
 #include "chrome/browser/web_applications/components/web_app_icon_generator.h"
diff --git a/chrome/chrome_cleaner/parsers/json_parser/json_splicer_unittest.cc b/chrome/chrome_cleaner/parsers/json_parser/json_splicer_unittest.cc
index ac081b1..45abdf1 100644
--- a/chrome/chrome_cleaner/parsers/json_parser/json_splicer_unittest.cc
+++ b/chrome/chrome_cleaner/parsers/json_parser/json_splicer_unittest.cc
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/test/test_timeouts.h"
 #include "base/values.h"
diff --git a/chrome/chrome_cleaner/parsers/target/parser_impl_unittest.cc b/chrome/chrome_cleaner/parsers/target/parser_impl_unittest.cc
index 7b6f92e..d3ae8c1 100644
--- a/chrome/chrome_cleaner/parsers/target/parser_impl_unittest.cc
+++ b/chrome/chrome_cleaner/parsers/target/parser_impl_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/chrome_cleaner/parsers/target/parser_impl.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/memory/scoped_refptr.h"
diff --git a/chrome/renderer/net/net_error_helper.cc b/chrome/renderer/net/net_error_helper.cc
index 66f1ca9..0450253 100644
--- a/chrome/renderer/net/net_error_helper.cc
+++ b/chrome/renderer/net/net_error_helper.cc
@@ -562,8 +562,7 @@
 
 void NetErrorHelper::LoadPageFromCache(const GURL& page_url) {
   blink::WebLocalFrame* web_frame = render_frame()->GetWebFrame();
-  DCHECK_NE("POST",
-            web_frame->GetDocumentLoader()->GetRequest().HttpMethod().Ascii());
+  DCHECK_NE("POST", web_frame->GetDocumentLoader()->HttpMethod().Ascii());
 
   blink::WebURLRequest request(page_url);
   request.SetCacheMode(blink::mojom::FetchCacheMode::kOnlyIfCached);
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 101b6f3..f5536df 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -727,6 +727,7 @@
       "../browser/page_load_metrics/observers/ads_page_load_metrics_observer_browsertest.cc",
       "../browser/page_load_metrics/observers/data_saver_site_breakdown_metrics_observer_browsertest.cc",
       "../browser/page_load_metrics/observers/data_use_metrics_observer_browsertest.cc",
+      "../browser/page_load_metrics/observers/foreground_duration_ukm_observer_browsertest.cc",
       "../browser/page_load_metrics/observers/https_engagement_metrics/https_engagement_page_load_metrics_observer_browsertest.cc",
       "../browser/page_load_metrics/observers/live_tab_count_page_load_metrics_observer_browsertest.cc",
       "../browser/page_load_metrics/observers/multi_tab_loading_page_load_metrics_observer_browsertest.cc",
diff --git a/chrome/test/chromedriver/DEPS b/chrome/test/chromedriver/DEPS
index 3b194022..29d14bd 100644
--- a/chrome/test/chromedriver/DEPS
+++ b/chrome/test/chromedriver/DEPS
@@ -5,6 +5,7 @@
 
   # Except for constants which it links in directly.
   "+chrome/common/chrome_constants.h",
+  "+chrome/common/chrome_version.h",
 
   "+chrome/test/chromedriver",
 
diff --git a/chrome/test/chromedriver/chrome/version.cc b/chrome/test/chromedriver/chrome/version.cc
index 69ebe42..93c492fb 100644
--- a/chrome/test/chromedriver/chrome/version.cc
+++ b/chrome/test/chromedriver/chrome/version.cc
@@ -13,6 +13,8 @@
 
 }  // namespace
 
+const int kMinimumSupportedChromeMajorVersion =
+    kMinimumSupportedChromeVersion[0];
 const int kMinimumSupportedChromeBuildNo = kMinimumSupportedChromeVersion[2];
 
 std::string GetMinimumSupportedChromeVersion() {
diff --git a/chrome/test/chromedriver/chrome/version.h b/chrome/test/chromedriver/chrome/version.h
index 1618b97..1b4113e 100644
--- a/chrome/test/chromedriver/chrome/version.h
+++ b/chrome/test/chromedriver/chrome/version.h
@@ -8,6 +8,7 @@
 #include <string>
 
 extern const int kMinimumSupportedChromeBuildNo;
+extern const int kMinimumSupportedChromeMajorVersion;
 
 std::string GetMinimumSupportedChromeVersion();
 
diff --git a/chrome/test/chromedriver/chrome_launcher.cc b/chrome/test/chromedriver/chrome_launcher.cc
index d0ae29f..5bddfa3 100644
--- a/chrome/test/chromedriver/chrome_launcher.cc
+++ b/chrome/test/chromedriver/chrome_launcher.cc
@@ -35,6 +35,7 @@
 #include "base/values.h"
 #include "build/build_config.h"
 #include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_version.h"
 #include "chrome/test/chromedriver/chrome/chrome_android_impl.h"
 #include "chrome/test/chromedriver/chrome/chrome_desktop_impl.h"
 #include "chrome/test/chromedriver/chrome/chrome_finder.h"
@@ -99,6 +100,7 @@
 const char* const kAndroidSwitches[] = {
     "disable-fre", "enable-remote-debugging",
 };
+const int chrome_version[] = {CHROME_VERSION};
 
 #if defined(OS_LINUX)
 const char kEnableCrashReport[] = "enable-crash-reporter-for-testing";
@@ -209,7 +211,8 @@
     const SyncWebSocketFactory& socket_factory,
     const Capabilities* capabilities,
     int wait_time,
-    std::unique_ptr<DevToolsHttpClient>* user_client) {
+    std::unique_ptr<DevToolsHttpClient>* user_client,
+    bool* retry) {
   std::unique_ptr<DeviceMetrics> device_metrics;
   if (capabilities && capabilities->device_metrics)
     device_metrics.reset(new DeviceMetrics(*capabilities->device_metrics));
@@ -253,14 +256,19 @@
                           browser_info->android_package.c_str()));
   }
 
+  *retry = true;
   if (cmd_line->HasSwitch("disable-build-check")) {
     LOG(WARNING) << "You are using an unsupported command-line switch: "
                     "--disable-build-check. Please don't report bugs that "
                     "cannot be reproduced with this switch removed.";
-  } else if (browser_info->build_no < kMinimumSupportedChromeBuildNo) {
-    return Status(
-        kSessionNotCreated,
-        "Chrome version must be >= " + GetMinimumSupportedChromeVersion());
+  } else if (browser_info->major_version <
+                 kMinimumSupportedChromeMajorVersion ||
+             browser_info->major_version > (chrome_version[0] + 1)) {
+    *retry = false;
+    return Status(kSessionNotCreated,
+                  base::StringPrintf("Chrome version must be between %d and %d",
+                                     kMinimumSupportedChromeMajorVersion,
+                                     chrome_version[0] + 1));
   }
 
   while (base::TimeTicks::Now() < deadline) {
@@ -322,9 +330,10 @@
     std::unique_ptr<Chrome>* chrome) {
   Status status(kOk);
   std::unique_ptr<DevToolsHttpClient> devtools_http_client;
+  bool retry = true;
   status = WaitForDevToolsAndCheckVersion(
       capabilities.debugger_address, factory, socket_factory, &capabilities, 60,
-      &devtools_http_client);
+      &devtools_http_client, &retry);
   if (status.IsError()) {
     return Status(kUnknownError, "cannot connect to chrome at " +
                       capabilities.debugger_address.ToString(),
@@ -362,6 +371,7 @@
   Status status = Status(kOk);
   std::vector<std::string> extension_bg_pages;
   int devtools_port = 0;
+  bool retry = true;
 
   if (capabilities.switches.HasSwitch("remote-debugging-port")) {
     std::string port_switch =
@@ -460,7 +470,10 @@
     if (status.IsOk()) {
       status = WaitForDevToolsAndCheckVersion(
           NetAddress(devtools_port), factory, socket_factory, &capabilities, 1,
-          &devtools_http_client);
+          &devtools_http_client, &retry);
+      if (!retry) {
+        break;
+      }
     }
     if (status.IsOk()) {
       break;
@@ -579,9 +592,10 @@
   }
 
   std::unique_ptr<DevToolsHttpClient> devtools_http_client;
+  bool retry = true;
   status = WaitForDevToolsAndCheckVersion(NetAddress(devtools_port), factory,
                                           socket_factory, &capabilities, 60,
-                                          &devtools_http_client);
+                                          &devtools_http_client, &retry);
   if (status.IsError()) {
     device->TearDown();
     return status;
@@ -633,10 +647,10 @@
 #endif
 
   std::unique_ptr<DevToolsHttpClient> devtools_http_client;
-  status =
-      WaitForDevToolsAndCheckVersion(NetAddress(0), factory, socket_factory,
-                                     &capabilities, 1, &devtools_http_client);
-
+  bool retry = true;
+  status = WaitForDevToolsAndCheckVersion(NetAddress(0), factory,
+                                          socket_factory, &capabilities, 1,
+                                          &devtools_http_client, &retry);
   std::unique_ptr<DevToolsClient> devtools_websocket_client;
   status = CreateBrowserwideDevToolsClientAndConnect(
       NetAddress(0), capabilities.perf_logging_prefs, socket_factory,
diff --git a/chrome/test/data/ads_observer/blank_with_adiframe_writer.html b/chrome/test/data/ads_observer/blank_with_adiframe_writer.html
new file mode 100644
index 0000000..8a3dc06
--- /dev/null
+++ b/chrome/test/data/ads_observer/blank_with_adiframe_writer.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+<script src="ad_iframe_writer.js"></script>
+</body>
+</html>
diff --git a/chrome/test/data/ads_observer/display_block_adframe.html b/chrome/test/data/ads_observer/display_block_adframe.html
new file mode 100644
index 0000000..cd536992
--- /dev/null
+++ b/chrome/test/data/ads_observer/display_block_adframe.html
@@ -0,0 +1,13 @@
+<html>
+<body>
+<script src="ad_iframe_writer.js"></script>
+<script>
+  let adIframe = createAdIframe();
+  adIframe.style.display = "block";
+  adIframe.src = "pixel.png";
+  adIframe.width = 100;
+  adIframe.height = 100;
+</script>
+
+</body>
+</html>
diff --git a/chrome/test/data/ads_observer/display_none_adframe.html b/chrome/test/data/ads_observer/display_none_adframe.html
new file mode 100644
index 0000000..9386af59
--- /dev/null
+++ b/chrome/test/data/ads_observer/display_none_adframe.html
@@ -0,0 +1,11 @@
+<html>
+<body>
+<script src="ad_iframe_writer.js"></script>
+<script>
+  let adIframe = createAdIframe();
+  adIframe.style.display = "none";
+  adIframe.srcdoc = "<img src=pixel.png></img>";
+</script>
+
+</body>
+</html>
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index c99bca1c..a32d494 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -12,7 +12,7 @@
     "bookmarks/bookmarks_focus_test.js",
     "cr_elements/cr_elements_focus_test.js",
     "cr_focus_row_behavior_interactive_test.js",
-    "md_history/md_history_focus_test.js",
+    "history/history_focus_test.js",
     "print_preview/print_preview_interactive_ui_tests.js",
     "settings/cr_settings_interactive_ui_tests.js",
     "settings/settings_ui_browsertest.js",
@@ -54,8 +54,8 @@
     "cr_components/cr_components_browsertest.js",
     "cr_elements/cr_elements_browsertest.js",
     "find_shortcut_behavior_browsertest.js",
+    "history/history_browsertest.js",
     "load_time_data_browsertest.js",
-    "md_history/md_history_browsertest.js",
     "media_router/media_router_elements_browsertest.js",
     "mock4js_browsertest.js",
     "net_internals/chromeos_view.js",
diff --git a/chrome/test/data/webui/md_history/.eslintrc.js b/chrome/test/data/webui/history/.eslintrc.js
similarity index 100%
rename from chrome/test/data/webui/md_history/.eslintrc.js
rename to chrome/test/data/webui/history/.eslintrc.js
diff --git a/chrome/test/data/webui/md_history/browser_service_test.js b/chrome/test/data/webui/history/browser_service_test.js
similarity index 100%
rename from chrome/test/data/webui/md_history/browser_service_test.js
rename to chrome/test/data/webui/history/browser_service_test.js
diff --git a/chrome/test/data/webui/md_history/md_history_browsertest.js b/chrome/test/data/webui/history/history_browsertest.js
similarity index 100%
rename from chrome/test/data/webui/md_history/md_history_browsertest.js
rename to chrome/test/data/webui/history/history_browsertest.js
diff --git a/chrome/test/data/webui/md_history/history_drawer_test.js b/chrome/test/data/webui/history/history_drawer_test.js
similarity index 100%
rename from chrome/test/data/webui/md_history/history_drawer_test.js
rename to chrome/test/data/webui/history/history_drawer_test.js
diff --git a/chrome/test/data/webui/md_history/md_history_focus_test.js b/chrome/test/data/webui/history/history_focus_test.js
similarity index 100%
rename from chrome/test/data/webui/md_history/md_history_focus_test.js
rename to chrome/test/data/webui/history/history_focus_test.js
diff --git a/chrome/test/data/webui/md_history/history_item_test.js b/chrome/test/data/webui/history/history_item_test.js
similarity index 100%
rename from chrome/test/data/webui/md_history/history_item_test.js
rename to chrome/test/data/webui/history/history_item_test.js
diff --git a/chrome/test/data/webui/md_history/history_list_test.js b/chrome/test/data/webui/history/history_list_test.js
similarity index 100%
rename from chrome/test/data/webui/md_history/history_list_test.js
rename to chrome/test/data/webui/history/history_list_test.js
diff --git a/chrome/test/data/webui/md_history/history_metrics_test.js b/chrome/test/data/webui/history/history_metrics_test.js
similarity index 100%
rename from chrome/test/data/webui/md_history/history_metrics_test.js
rename to chrome/test/data/webui/history/history_metrics_test.js
diff --git a/chrome/test/data/webui/md_history/history_overflow_menu_test.js b/chrome/test/data/webui/history/history_overflow_menu_test.js
similarity index 100%
rename from chrome/test/data/webui/md_history/history_overflow_menu_test.js
rename to chrome/test/data/webui/history/history_overflow_menu_test.js
diff --git a/chrome/test/data/webui/md_history/history_routing_test.js b/chrome/test/data/webui/history/history_routing_test.js
similarity index 100%
rename from chrome/test/data/webui/md_history/history_routing_test.js
rename to chrome/test/data/webui/history/history_routing_test.js
diff --git a/chrome/test/data/webui/md_history/history_supervised_user_test.js b/chrome/test/data/webui/history/history_supervised_user_test.js
similarity index 100%
rename from chrome/test/data/webui/md_history/history_supervised_user_test.js
rename to chrome/test/data/webui/history/history_supervised_user_test.js
diff --git a/chrome/test/data/webui/md_history/history_synced_tabs_test.js b/chrome/test/data/webui/history/history_synced_tabs_test.js
similarity index 100%
rename from chrome/test/data/webui/md_history/history_synced_tabs_test.js
rename to chrome/test/data/webui/history/history_synced_tabs_test.js
diff --git a/chrome/test/data/webui/md_history/history_toolbar_test.js b/chrome/test/data/webui/history/history_toolbar_test.js
similarity index 100%
rename from chrome/test/data/webui/md_history/history_toolbar_test.js
rename to chrome/test/data/webui/history/history_toolbar_test.js
diff --git a/chrome/test/data/webui/md_history/searched_label_test.js b/chrome/test/data/webui/history/searched_label_test.js
similarity index 100%
rename from chrome/test/data/webui/md_history/searched_label_test.js
rename to chrome/test/data/webui/history/searched_label_test.js
diff --git a/chrome/test/data/webui/md_history/test_util.js b/chrome/test/data/webui/history/test_util.js
similarity index 100%
rename from chrome/test/data/webui/md_history/test_util.js
rename to chrome/test/data/webui/history/test_util.js
diff --git a/chrome/test/data/xr/e2e_test_files/html/test_webxr_capabilities.html b/chrome/test/data/xr/e2e_test_files/html/test_webxr_capabilities.html
index f5bda52..b6331710 100644
--- a/chrome/test/data/xr/e2e_test_files/html/test_webxr_capabilities.html
+++ b/chrome/test/data/xr/e2e_test_files/html/test_webxr_capabilities.html
@@ -30,13 +30,12 @@
         var supportsNonImmersive;
         var supportsImmersive;
         var ctx = webglCanvas.getContext("xrpresent");
-        xrDevice.supportsSession(
-            {immersive: false, outputContext: ctx}).then( () => {
+        navigator.xr.supportsSessionMode('inline').then( () => {
           supportsNonImmersive = true;
         }, () => {
           supportsNonImmersive = false;
         }).then( () => {
-          xrDevice.supportsSession({immersive: true}).then( () => {
+          navigator.xr.supportsSessionMode('immersive-vr').then( () => {
             supportsImmersive = true;
           }, () => {
             supportsImmersive = false;
diff --git a/chrome/test/data/xr/e2e_test_files/html/test_webxr_does_not_return_device.html b/chrome/test/data/xr/e2e_test_files/html/test_webxr_does_not_return_device.html
index 631c1bf..c8ade39f 100644
--- a/chrome/test/data/xr/e2e_test_files/html/test_webxr_does_not_return_device.html
+++ b/chrome/test/data/xr/e2e_test_files/html/test_webxr_does_not_return_device.html
@@ -1,6 +1,6 @@
 <!doctype html>
 <!--
-Tests that WebXR returns no devices when OpenVR is disabled.
+Tests that WebXR does not report immersive-vr support when OpenVR is disabled.
 -->
 <html>
   <head>
@@ -11,8 +11,8 @@
     <script src="../../../../../../third_party/blink/web_tests/resources/testharness.js"></script>
     <script src="../resources/webxr_e2e.js"></script>
     <script>
-      navigator.xr.requestDevice().then( () => {
-        assert_unreached("WebXR returned a device");
+      navigator.xr.supportsSessionMode('immersive-vr').then( () => {
+        assert_unreached("WebXR indicated support for 'immersive-vr'");
       }, () => {
         done();
       });
diff --git a/chrome/test/data/xr/e2e_test_files/html/webxr_test_presentation_promise_rejected_if_don_canceled.html b/chrome/test/data/xr/e2e_test_files/html/webxr_test_presentation_promise_rejected_if_don_canceled.html
index 9f63024a..9b061e9 100644
--- a/chrome/test/data/xr/e2e_test_files/html/webxr_test_presentation_promise_rejected_if_don_canceled.html
+++ b/chrome/test/data/xr/e2e_test_files/html/webxr_test_presentation_promise_rejected_if_don_canceled.html
@@ -14,7 +14,7 @@
     <script src="../resources/webxr_boilerplate.js"></script>
     <script>
       function onImmersiveRequestWithDon() {
-        xrDevice.requestSession({immersive: true}).then( (session) => {
+        navigator.xr.requestSession({mode: 'immersive-vr'}).then( (session) => {
           assert_unreached("requestPresent promise resolved");
         }, () => {
           // Do nothing when the promise is rejected
diff --git a/chrome/test/data/xr/e2e_test_files/html/webxr_test_presentation_promise_unresolved_during_don.html b/chrome/test/data/xr/e2e_test_files/html/webxr_test_presentation_promise_unresolved_during_don.html
index da7de7f..58b0882 100644
--- a/chrome/test/data/xr/e2e_test_files/html/webxr_test_presentation_promise_unresolved_during_don.html
+++ b/chrome/test/data/xr/e2e_test_files/html/webxr_test_presentation_promise_unresolved_during_don.html
@@ -14,7 +14,7 @@
     <script src="../resources/webxr_boilerplate.js"></script>
     <script>
       function onImmersiveRequestWithDon() {
-        xrDevice.requestSession({immersive: true}).then( (session) => {
+        navigator.xr.requestSession({mode: 'immersive-vr'}).then( (session) => {
           assert_unreached("requestSession promise resolved");
         }, () => {
           assert_unreached("requestSession promise rejected");
diff --git a/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js b/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js
index 4b39f58..2f2c17b 100644
--- a/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js
+++ b/chrome/test/data/xr/e2e_test_files/resources/webxr_boilerplate.js
@@ -4,7 +4,6 @@
 
 // Add additional setup steps to the object from webvr_e2e.js if it exists.
 if (typeof initializationSteps !== 'undefined') {
-  initializationSteps['getXRDevice'] = false;
   initializationSteps['magicWindowStarted'] = false;
 } else {
   // Create here if it doesn't exist so we can access it later without checking
@@ -18,7 +17,6 @@
   xrCompatible: true,
 };
 var gl = null;
-var xrDevice = null;
 var onMagicWindowXRFrameCallback = null;
 var onImmersiveXRFrameCallback = null;
 var onPoseCallback = null;
@@ -67,11 +65,10 @@
 sessionInfos[sessionTypes.MAGIC_WINDOW] = new SessionInfo();
 
 function getSessionType(session) {
-  if (session.immersive) {
+  if (session.mode == 'immersive-vr') {
     return sessionTypes.IMMERSIVE;
-  } else if (sessionInfos[sessionTypes.AR].currentSession == session) {
-    // TODO(bsheedy): Replace this check if there's ever something like
-    // session.ar for checking if the session is AR-capable.
+  } else if (session.mode == 'immersive-ar' ||
+             session.mode == 'legacy-inline-ar') {
     return sessionTypes.AR;
   } else {
     return sessionTypes.MAGIC_WINDOW;
@@ -82,7 +79,7 @@
   switch (sessionTypeToRequest) {
     case sessionTypes.IMMERSIVE:
       console.info('Requesting immersive session');
-      xrDevice.requestSession({immersive: true}).then( (session) => {
+      navigator.xr.requestSession({mode: 'immersive-vr'}).then( (session) => {
         console.info('Immersive session request succeeded');
         sessionInfos[sessionTypes.IMMERSIVE].currentSession = session;
         onSessionStarted(session);
@@ -92,11 +89,7 @@
       break;
     case sessionTypes.AR:
       console.info('Requesting AR session');
-      let sessionOptions = {
-        environmentIntegration: true,
-        outputContext: webglCanvas.getContext('xrpresent'),
-      };
-      xrDevice.requestSession(sessionOptions).then((session) => {
+      navigator.xr.requestSession({mode: 'immersive-ar'}).then((session) => {
         console.info('AR session request succeeded');
         sessionInfos[sessionTypes.AR].currentSession = session;
         onSessionStarted(session);
@@ -180,37 +173,30 @@
   hasPresentedFrame = true;
 }
 
-// Try to get an XRDevice and set up a non-immersive session with it
 if (navigator.xr) {
-  navigator.xr.requestDevice().then( (device) => {
-    xrDevice = device;
-    if (!device)
-      return;
 
-    // Set up the device to have a non-immersive session (magic window) drawing
-    // into the full screen canvas on the page
-    let ctx = webglCanvas.getContext('xrpresent');
-    // WebXR for VR tests want a non-immersive session to be automatically
-    // created on page load to reduce the amount of boilerplate code necessary.
-    // However, doing so during AR tests currently fails due to AR sessions
-    // always requiring a user gesture. So, allow a page to set a variable
-    // before loading this JavaScript file if they wish to skip the automatic
-    // non-immersive session creation.
-    if (typeof shouldAutoCreateNonImmersiveSession === 'undefined'
-        || shouldAutoCreateNonImmersiveSession === true) {
-      device.requestSession({outputContext: ctx}).then( (session) => {
-        onSessionStarted(session);
-      }).then( () => {
-        initializationSteps['magicWindowStarted'] = true;
-      });
-    } else {
-      initializationSteps['magicWindowStarted'] = true;
-    }
-  }).then( () => {
-    initializationSteps['getXRDevice'] = true;
-  });
+  // Set up an inline session (magic window) drawing into the full screen canvas
+  // on the page
+  let ctx = webglCanvas.getContext('xrpresent');
+  // WebXR for VR tests want an inline session to be automatically
+  // created on page load to reduce the amount of boilerplate code necessary.
+  // However, doing so during AR tests currently fails due to AR sessions
+  // always requiring a user gesture. So, allow a page to set a variable
+  // before loading this JavaScript file if they wish to skip the automatic
+  // inline session creation.
+  if (typeof shouldAutoCreateNonImmersiveSession === 'undefined'
+      || shouldAutoCreateNonImmersiveSession === true) {
+    navigator.xr.requestSession({outputContext: ctx})
+        .then((session) => {
+          onSessionStarted(session);
+        }).then( () => {
+          initializationSteps['magicWindowStarted'] = true;
+        });
+  } else {
+    initializationSteps['magicWindowStarted'] = true;
+  }
+
 } else {
-  initializationSteps['getXRDevice'] = true;
   initializationSteps['magicWindowStarted'] = true;
 }
 
diff --git a/chromecast/browser/cast_overlay_manifests.cc b/chromecast/browser/cast_overlay_manifests.cc
index 74d6768..93b8d5e6 100644
--- a/chromecast/browser/cast_overlay_manifests.cc
+++ b/chromecast/browser/cast_overlay_manifests.cc
@@ -61,7 +61,7 @@
 GetCastContentPackagedServicesOverlayManifest() {
   static base::NoDestructor<service_manager::Manifest> manifest {
     service_manager::ManifestBuilder()
-        .PackageService(::media::GetManifest())
+        .PackageService(::media::GetMediaManifest())
         .Build()
 #if defined(USE_INTERNAL_OVERLAY_MANIFESTS)
         .Amend(cast_content_packaged_services_internal_manifest_overlay::
diff --git a/chromecast/device/bluetooth/le/remote_device_impl.cc b/chromecast/device/bluetooth/le/remote_device_impl.cc
index 1b1ab78..74eec537 100644
--- a/chromecast/device/bluetooth/le/remote_device_impl.cc
+++ b/chromecast/device/bluetooth/le/remote_device_impl.cc
@@ -5,6 +5,7 @@
 #include "chromecast/device/bluetooth/le/remote_device_impl.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "chromecast/base/bind_to_task_runner.h"
 #include "chromecast/device/bluetooth/bluetooth_util.h"
 #include "chromecast/device/bluetooth/le/gatt_client_manager_impl.h"
diff --git a/chromecast/graphics/gestures/side_swipe_detector_test.cc b/chromecast/graphics/gestures/side_swipe_detector_test.cc
index 2195e6b..f3c3584 100644
--- a/chromecast/graphics/gestures/side_swipe_detector_test.cc
+++ b/chromecast/graphics/gestures/side_swipe_detector_test.cc
@@ -9,6 +9,7 @@
 #include "base/run_loop.h"
 #include "base/test/simple_test_tick_clock.h"
 #include "base/test/test_mock_time_task_runner.h"
+#include "base/timer/timer.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/test/aura_test_base.h"
diff --git a/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc b/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc
index d14bf00..3d2e992 100644
--- a/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc
+++ b/chromecast/media/cma/backend/android/audio_sink_android_audiotrack_impl.cc
@@ -360,7 +360,7 @@
     state_ = kStateNormalPlayback;
     Java_AudioSinkAudioTrackImpl_play(base::android::AttachCurrentThread(),
                                       j_audio_sink_audiotrack_impl_);
-    if (pending_data_bytes_already_fed_) {
+    if (pending_data_ && pending_data_bytes_already_fed_) {
       // The last data buffer was partially fed, complete it now.
       FeedDataContinue();
     }
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn
index 1032121..5eaae8a 100644
--- a/chromeos/BUILD.gn
+++ b/chromeos/BUILD.gn
@@ -53,6 +53,8 @@
     "policy/weekly_time/weekly_time.h",
     "policy/weekly_time/weekly_time_interval.cc",
     "policy/weekly_time/weekly_time_interval.h",
+    "printing/epson_driver_matching.cc",
+    "printing/epson_driver_matching.h",
     "printing/ppd_cache.cc",
     "printing/ppd_cache.h",
     "printing/ppd_line_reader.cc",
@@ -217,6 +219,7 @@
     "policy/weekly_time/time_utils_unittest.cc",
     "policy/weekly_time/weekly_time_interval_unittest.cc",
     "policy/weekly_time/weekly_time_unittest.cc",
+    "printing/epson_driver_matching_unittest.cc",
     "printing/ppd_cache_unittest.cc",
     "printing/ppd_line_reader_unittest.cc",
     "printing/ppd_provider_unittest.cc",
diff --git a/chromeos/account_manager/account_manager.cc b/chromeos/account_manager/account_manager.cc
index c1aca23..92c0accf 100644
--- a/chromeos/account_manager/account_manager.cc
+++ b/chromeos/account_manager/account_manager.cc
@@ -123,9 +123,9 @@
     DCHECK(!refresh_token_.empty());
     gaia_auth_fetcher_ = std::make_unique<GaiaAuthFetcher>(
         this, gaia::GaiaSource::kChromeOS, url_loader_factory);
-    base::RepeatingClosure start_revoke_token = base::BindRepeating(
+    base::OnceClosure start_revoke_token = base::BindOnce(
         &GaiaTokenRevocationRequest::Start, weak_factory_.GetWeakPtr());
-    delay_network_call_runner.Run(start_revoke_token);
+    delay_network_call_runner.Run(std::move(start_revoke_token));
   }
 
   ~GaiaTokenRevocationRequest() override = default;
diff --git a/chromeos/account_manager/account_manager.h b/chromeos/account_manager/account_manager.h
index 6c00309..d2d1829 100644
--- a/chromeos/account_manager/account_manager.h
+++ b/chromeos/account_manager/account_manager.h
@@ -80,7 +80,7 @@
   using AccountListCallback = base::OnceCallback<void(std::vector<AccountKey>)>;
 
   using DelayNetworkCallRunner =
-      base::RepeatingCallback<void(const base::RepeatingClosure&)>;
+      base::RepeatingCallback<void(base::OnceClosure)>;
 
   class Observer {
    public:
diff --git a/chromeos/account_manager/account_manager_unittest.cc b/chromeos/account_manager/account_manager_unittest.cc
index 79d45b7..aeacdd8f 100644
--- a/chromeos/account_manager/account_manager_unittest.cc
+++ b/chromeos/account_manager/account_manager_unittest.cc
@@ -104,7 +104,7 @@
       account_manager::AccountType::ACCOUNT_TYPE_ACTIVE_DIRECTORY};
   AccountManager::DelayNetworkCallRunner immediate_callback_runner_ =
       base::BindRepeating(
-          [](const base::RepeatingClosure& closure) -> void { closure.Run(); });
+          [](base::OnceClosure closure) -> void { std::move(closure).Run(); });
 
  private:
   DISALLOW_COPY_AND_ASSIGN(AccountManagerTest);
diff --git a/chromeos/components/tether/tether_component_impl.cc b/chromeos/components/tether/tether_component_impl.cc
index 3b463440..6df9305 100644
--- a/chromeos/components/tether/tether_component_impl.cc
+++ b/chromeos/components/tether/tether_component_impl.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/memory/ptr_util.h"
 #include "chromeos/components/multidevice/logging/logging.h"
 #include "chromeos/components/tether/active_host.h"
diff --git a/chromeos/components/tether/tether_connector_impl.cc b/chromeos/components/tether/tether_connector_impl.cc
index aadf4d3b..00b3339 100644
--- a/chromeos/components/tether/tether_connector_impl.cc
+++ b/chromeos/components/tether/tether_connector_impl.cc
@@ -5,6 +5,7 @@
 #include "chromeos/components/tether/tether_connector_impl.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/metrics/histogram_macros.h"
 #include "chromeos/components/multidevice/logging/logging.h"
 #include "chromeos/components/tether/active_host.h"
diff --git a/chromeos/dbus/power_manager_client.cc b/chromeos/dbus/power_manager_client.cc
index d4574c6..b5c82e7 100644
--- a/chromeos/dbus/power_manager_client.cc
+++ b/chromeos/dbus/power_manager_client.cc
@@ -11,6 +11,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/format_macros.h"
 #include "base/logging.h"
diff --git a/chromeos/network/network_state.cc b/chromeos/network/network_state.cc
index cd20d92..8ec94aa2 100644
--- a/chromeos/network/network_state.cc
+++ b/chromeos/network/network_state.cc
@@ -320,7 +320,7 @@
                        base::Value(network_technology()));
     dictionary->SetKey(shill::kActivationStateProperty,
                        base::Value(activation_state()));
-    dictionary->SetKey(shill::kRoamingStateProperty, base::Value(roaming()));
+    dictionary->SetKey(shill::kRoamingStateProperty, base::Value(roaming_));
     dictionary->SetKey(shill::kOutOfCreditsProperty,
                        base::Value(cellular_out_of_credits()));
   }
@@ -405,6 +405,11 @@
          tethering_state() == shill::kTetheringConfirmedState;
 }
 
+bool NetworkState::IndicateRoaming() const {
+  return type() == shill::kTypeCellular &&
+         roaming_ == shill::kRoamingStateRoaming && !provider_requires_roaming_;
+}
+
 bool NetworkState::IsDynamicWep() const {
   return security_class_ == shill::kSecurityWep &&
          eap_key_mgmt_ == shill::kKeyManagementIEEE8021X;
diff --git a/chromeos/network/network_state.h b/chromeos/network/network_state.h
index 9b2d54f5..ae9fa3d 100644
--- a/chromeos/network/network_state.h
+++ b/chromeos/network/network_state.h
@@ -116,7 +116,6 @@
   const std::string& network_technology() const { return network_technology_; }
   const std::string& activation_type() const { return activation_type_; }
   const std::string& activation_state() const { return activation_state_; }
-  const std::string& roaming() const { return roaming_; }
   const std::string& payment_url() const { return payment_url_; }
   const std::string& payment_post_data() const { return payment_post_data_; }
   bool cellular_out_of_credits() const { return cellular_out_of_credits_; }
@@ -146,7 +145,11 @@
   // |onc_source_|).
   bool IsManagedByPolicy() const;
 
-  // Returns true if current connection is using mobile data.
+  // Returns true if the network is romaing and the provider does not require
+  // roaming.
+  bool IndicateRoaming() const;
+
+  // Returns true if the current connection is using mobile data.
   bool IsUsingMobileData() const;
 
   // Returns true if the network securty is WEP_8021x (Dynamic WEP)
@@ -265,6 +268,7 @@
   std::string activation_type_;
   std::string activation_state_;
   std::string roaming_;
+  bool provider_requires_roaming_ = false;
   std::string payment_url_;
   std::string payment_post_data_;
   bool cellular_out_of_credits_ = false;
diff --git a/chromeos/network/network_state_handler.cc b/chromeos/network/network_state_handler.cc
index 4f6c888..ce2a088 100644
--- a/chromeos/network/network_state_handler.cc
+++ b/chromeos/network/network_state_handler.cc
@@ -1257,6 +1257,8 @@
 
   UpdateGuid(network);
   UpdateCaptivePortalProvider(network);
+  if (network->Matches(NetworkTypePattern::Cellular()))
+    UpdateCellularStateFromDevice(network);
 
   network_list_sorted_ = false;
 
@@ -1634,6 +1636,13 @@
                                     portal_iter->second.name);
 }
 
+void NetworkStateHandler::UpdateCellularStateFromDevice(NetworkState* network) {
+  const DeviceState* device = GetDeviceState(network->device_path());
+  if (!device)
+    return;
+  network->provider_requires_roaming_ = device->provider_requires_roaming();
+}
+
 std::unique_ptr<NetworkState>
 NetworkStateHandler::MaybeCreateDefaultCellularNetwork() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/chromeos/network/network_state_handler.h b/chromeos/network/network_state_handler.h
index 915dd9d..db4b931 100644
--- a/chromeos/network/network_state_handler.h
+++ b/chromeos/network/network_state_handler.h
@@ -478,6 +478,9 @@
   // |hex_ssid_to_captive_portal_provider_map_|.
   void UpdateCaptivePortalProvider(NetworkState* network);
 
+  // Update networkState properties from the associated DeviceState.
+  void UpdateCellularStateFromDevice(NetworkState* network);
+
   // Cellular networks may not have an associated Shill Service (e.g. when the
   // SIM is locked or a mobile network is not available). This returns a new
   // default cellular network if necessary.
diff --git a/chromeos/network/network_state_handler_unittest.cc b/chromeos/network/network_state_handler_unittest.cc
index a747531..7583eb9 100644
--- a/chromeos/network/network_state_handler_unittest.cc
+++ b/chromeos/network/network_state_handler_unittest.cc
@@ -13,6 +13,7 @@
 #include <string>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
diff --git a/chromeos/printing/epson_driver_matching.cc b/chromeos/printing/epson_driver_matching.cc
new file mode 100644
index 0000000..cddbb69
--- /dev/null
+++ b/chromeos/printing/epson_driver_matching.cc
@@ -0,0 +1,51 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/printing/epson_driver_matching.h"
+
+#include <algorithm>
+
+#include "chromeos/printing/ppd_provider.h"
+
+namespace chromeos {
+
+bool CanUseEpsonGenericPPD(const PrinterSearchData& sd) {
+  // Needed to check if its an Epson printer.
+  if (sd.make_and_model.empty()) {
+    return false;
+  }
+
+  // Fail if this isn't an Epson printer.
+  // Note: Assumes make and model strings are already lowercase.
+  auto it = std::find_if(sd.make_and_model.begin(), sd.make_and_model.end(),
+                         [](base::StringPiece emm) {
+                           return emm.find("epson") != base::StringPiece::npos;
+                         });
+  if (it == sd.make_and_model.end()) {
+    return false;
+  }
+
+  switch (sd.discovery_type) {
+    case PrinterSearchData::PrinterDiscoveryType::kManual:
+      // For manually discovered printers, supported_document_formats is
+      // retrieved via an ippGetAttributes query to the printer.
+      return base::ContainsValue(sd.supported_document_formats,
+                                 "application/octet-stream");
+
+    case PrinterSearchData::PrinterDiscoveryType::kUsb:
+      return base::ContainsValue(sd.usb_command_set, "ESC/P-R");
+
+    case PrinterSearchData::PrinterDiscoveryType::kZeroconf:
+      // For printers found through mDNS/DNS-SD discovery,
+      // supported_document_formats is retrieved via the Printer Description TXT
+      // Record(from the key 'pdl').
+      return base::ContainsValue(sd.supported_document_formats,
+                                 "application/vnd.epson.escpr");
+
+    default:
+      return false;
+  }
+}
+
+}  // namespace chromeos
diff --git a/chromeos/printing/epson_driver_matching.h b/chromeos/printing/epson_driver_matching.h
new file mode 100644
index 0000000..f87aa5a
--- /dev/null
+++ b/chromeos/printing/epson_driver_matching.h
@@ -0,0 +1,20 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_PRINTING_EPSON_DRIVER_MATCHING_H_
+#define CHROMEOS_PRINTING_EPSON_DRIVER_MATCHING_H_
+
+#include "chromeos/chromeos_export.h"
+
+namespace chromeos {
+
+struct PrinterSearchData;
+
+// Implements PPD matching rules obtained from Epson. Returns true when this
+// printer can be saftely setup using the generic Epson PPD.
+bool CHROMEOS_EXPORT CanUseEpsonGenericPPD(const PrinterSearchData& sd);
+
+}  // namespace chromeos
+
+#endif  // CHROMEOS_PRINTING_EPSON_DRIVER_MATCHING_H_
diff --git a/chromeos/printing/epson_driver_matching_unittest.cc b/chromeos/printing/epson_driver_matching_unittest.cc
new file mode 100644
index 0000000..42d274a
--- /dev/null
+++ b/chromeos/printing/epson_driver_matching_unittest.cc
@@ -0,0 +1,143 @@
+// 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.
+
+#include "chromeos/printing/epson_driver_matching.h"
+
+#include <string>
+
+#include "chromeos/printing/ppd_provider.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+namespace {
+
+const char kOctetStream[] = "application/octet-stream";
+const char kEscPr[] = "ESC/P-R";
+const char kEpsonEscpr[] = "application/vnd.epson.escpr";
+
+using PrinterDiscoveryType = PrinterSearchData::PrinterDiscoveryType;
+
+PrinterSearchData GetTestPrinterSearchData(
+    PrinterDiscoveryType type = PrinterDiscoveryType::kManual) {
+  PrinterSearchData sd;
+  sd.make_and_model.push_back("epson");
+
+  switch (type) {
+    case PrinterDiscoveryType::kManual:
+      sd.discovery_type = PrinterDiscoveryType::kManual;
+      sd.supported_document_formats.push_back(kOctetStream);
+      break;
+
+    case PrinterDiscoveryType::kUsb:
+      sd.discovery_type = PrinterDiscoveryType::kUsb;
+      sd.usb_command_set.push_back(kEscPr);
+      break;
+
+    case PrinterDiscoveryType::kZeroconf:
+      sd.discovery_type = PrinterDiscoveryType::kZeroconf;
+      sd.supported_document_formats.push_back(kEpsonEscpr);
+      break;
+
+    default:
+      sd.discovery_type = type;
+      break;
+  }
+
+  return sd;
+}
+
+// Ensuring simple good cases generated above pass.
+TEST(EpsonDriverMatchingTest, SimpleSanityTest) {
+  EXPECT_TRUE(CanUseEpsonGenericPPD(
+      GetTestPrinterSearchData(PrinterDiscoveryType::kManual)));
+  EXPECT_TRUE(CanUseEpsonGenericPPD(
+      GetTestPrinterSearchData(PrinterDiscoveryType::kUsb)));
+  EXPECT_TRUE(CanUseEpsonGenericPPD(
+      GetTestPrinterSearchData(PrinterDiscoveryType::kZeroconf)));
+}
+
+// Always fails printers missing make and model information.
+TEST(EpsonDriverMatchingTest, EmptyMakeAndModels) {
+  EXPECT_FALSE(CanUseEpsonGenericPPD(PrinterSearchData()));
+}
+
+// Always fails printers with invalid discovery types.
+TEST(EpsonDriverMatchingTest, InvalidPrinterDiscoveryType) {
+  EXPECT_FALSE(CanUseEpsonGenericPPD(
+      GetTestPrinterSearchData(PrinterDiscoveryType::kUnknown)));
+  EXPECT_FALSE(CanUseEpsonGenericPPD(
+      GetTestPrinterSearchData(PrinterDiscoveryType::kDiscoveryTypeMax)));
+}
+
+// Confirms an Epson printer if any make and models have 'epson'.
+TEST(EpsonDriverMatchingTest, ChecksAllMakeAndModels) {
+  PrinterSearchData sd(GetTestPrinterSearchData());
+  sd.make_and_model.clear();
+
+  sd.make_and_model.push_back("kodak fdasf");
+  EXPECT_FALSE(CanUseEpsonGenericPPD(sd));
+
+  sd.make_and_model.push_back("epso nomega x301");
+  EXPECT_FALSE(CanUseEpsonGenericPPD(sd));
+
+  sd.make_and_model.push_back("epson xp5100");
+  EXPECT_TRUE(CanUseEpsonGenericPPD(sd));
+}
+
+// Simple PrinterDiscoveryType::kManual checks.
+TEST(EpsonDriverMatchingTest, ManualDiscovery) {
+  PrinterSearchData sd(GetTestPrinterSearchData(PrinterDiscoveryType::kManual));
+  sd.supported_document_formats.clear();
+
+  sd.supported_document_formats.push_back("application/");
+  EXPECT_FALSE(CanUseEpsonGenericPPD(sd));
+
+  sd.supported_document_formats.push_back(std::string(kOctetStream) + "afds");
+  EXPECT_FALSE(CanUseEpsonGenericPPD(sd));
+
+  sd.usb_command_set.push_back(kOctetStream);
+  EXPECT_FALSE(CanUseEpsonGenericPPD(sd));
+
+  sd.supported_document_formats.push_back(kOctetStream);
+  EXPECT_TRUE(CanUseEpsonGenericPPD(sd));
+}
+
+// Simple PrinterDiscoveryType::kUsb checks.
+TEST(EpsonDriverMatchingTest, UsbDiscovery) {
+  PrinterSearchData sd(GetTestPrinterSearchData(PrinterDiscoveryType::kUsb));
+  sd.usb_command_set.clear();
+
+  sd.usb_command_set.push_back("ESC");
+  EXPECT_FALSE(CanUseEpsonGenericPPD(sd));
+
+  sd.usb_command_set.push_back(std::string(kEscPr) + ":asfd");
+  EXPECT_FALSE(CanUseEpsonGenericPPD(sd));
+
+  sd.supported_document_formats.push_back(kEscPr);
+  EXPECT_FALSE(CanUseEpsonGenericPPD(sd));
+
+  sd.usb_command_set.push_back(kEscPr);
+  EXPECT_TRUE(CanUseEpsonGenericPPD(sd));
+}
+
+TEST(EpsonDriverMatchingTest, ZerconfDiscovery) {
+  PrinterSearchData sd(
+      GetTestPrinterSearchData(PrinterDiscoveryType::kZeroconf));
+  sd.supported_document_formats.clear();
+
+  sd.supported_document_formats.push_back("application/");
+  EXPECT_FALSE(CanUseEpsonGenericPPD(sd));
+
+  sd.supported_document_formats.push_back(std::string(kEpsonEscpr) + ":asfd");
+  EXPECT_FALSE(CanUseEpsonGenericPPD(sd));
+
+  sd.usb_command_set.push_back(kEpsonEscpr);
+  EXPECT_FALSE(CanUseEpsonGenericPPD(sd));
+
+  sd.supported_document_formats.push_back(kEpsonEscpr);
+  EXPECT_TRUE(CanUseEpsonGenericPPD(sd));
+}
+
+}  // namespace
+}  // namespace chromeos
diff --git a/chromeos/printing/ppd_provider.cc b/chromeos/printing/ppd_provider.cc
index 1860f916..09df3a1 100644
--- a/chromeos/printing/ppd_provider.cc
+++ b/chromeos/printing/ppd_provider.cc
@@ -32,6 +32,7 @@
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/time/time.h"
 #include "base/values.h"
+#include "chromeos/printing/epson_driver_matching.h"
 #include "chromeos/printing/ppd_cache.h"
 #include "chromeos/printing/ppd_line_reader.h"
 #include "chromeos/printing/printing_constants.h"
@@ -48,6 +49,8 @@
 namespace chromeos {
 namespace {
 
+const char kEpsonGenericPPD[] = "epson generic escpr printer";
+
 // Holds a metadata_v2 reverse-index response
 struct ReverseIndexJSON {
   // Canonical name of printer
@@ -173,7 +176,7 @@
   ~PpdReferenceResolutionQueueEntry() = default;
 
   // Metadata used to resolve to a unique PpdReference object.
-  PpdProvider::PrinterSearchData search_data;
+  PrinterSearchData search_data;
 
   // If true, we have failed usb_index_resolution already.
   bool usb_resolution_attempted = false;
@@ -452,11 +455,24 @@
         StartFetch(GetUsbURL(search_data.usb_vendor_id), FT_USB_DEVICES);
         return true;
       }
-      // We don't have anything else left to try.  NOT_FOUND it is.
-      base::SequencedTaskRunnerHandle::Get()->PostTask(
-          FROM_HERE, base::BindOnce(std::move(next.cb), PpdProvider::NOT_FOUND,
-                                    Printer::PpdReference()));
-      ppd_reference_resolution_queue_.pop_front();
+
+      // If possible, here we fall back to OEM designated generic PPDs.
+      if (CanUseEpsonGenericPPD(search_data)) {
+        // Found a hit, satisfy this resolution.
+        Printer::PpdReference ret;
+        ret.effective_make_and_model = kEpsonGenericPPD;
+        base::SequencedTaskRunnerHandle::Get()->PostTask(
+            FROM_HERE,
+            base::BindOnce(std::move(next.cb), PpdProvider::SUCCESS, ret));
+        ppd_reference_resolution_queue_.pop_front();
+      } else {
+        // We don't have anything else left to try.  NOT_FOUND it is.
+        base::SequencedTaskRunnerHandle::Get()->PostTask(
+            FROM_HERE,
+            base::BindOnce(std::move(next.cb), PpdProvider::NOT_FOUND,
+                           Printer::PpdReference()));
+        ppd_reference_resolution_queue_.pop_front();
+      }
     }
     // Didn't start any fetches.
     return false;
@@ -1066,13 +1082,13 @@
         }
       }
     }
-    Printer::PpdReference ret;
     if (result == PpdProvider::SUCCESS) {
+      Printer::PpdReference ret;
       ret.effective_make_and_model = contents;
       base::SequencedTaskRunnerHandle::Get()->PostTask(
           FROM_HERE,
           base::BindOnce(std::move(ppd_reference_resolution_queue_.front().cb),
-                         result, ret));
+                         result, std::move(ret)));
       ppd_reference_resolution_queue_.pop_front();
     } else {
       ppd_reference_resolution_queue_.front().usb_resolution_attempted = true;
@@ -1558,10 +1574,9 @@
   }
 }
 
-PpdProvider::PrinterSearchData::PrinterSearchData() = default;
-PpdProvider::PrinterSearchData::PrinterSearchData(
-    const PrinterSearchData& other) = default;
-PpdProvider::PrinterSearchData::~PrinterSearchData() = default;
+PrinterSearchData::PrinterSearchData() = default;
+PrinterSearchData::PrinterSearchData(const PrinterSearchData& other) = default;
+PrinterSearchData::~PrinterSearchData() = default;
 
 // static
 scoped_refptr<PpdProvider> PpdProvider::Create(
diff --git a/chromeos/printing/ppd_provider.h b/chromeos/printing/ppd_provider.h
index 31a236e..b868579 100644
--- a/chromeos/printing/ppd_provider.h
+++ b/chromeos/printing/ppd_provider.h
@@ -27,6 +27,42 @@
 
 class PpdCache;
 
+// Everything we might know about a printer when looking for a
+// driver for it.  All of the default values for fields in this struct
+// mean we *don't* have that piece of information.
+//
+// Fields are listed in search order preference -- we use earlier
+// fields first to attempt to find a match.
+struct CHROMEOS_EXPORT PrinterSearchData {
+  PrinterSearchData();
+  PrinterSearchData(const PrinterSearchData& other);
+  ~PrinterSearchData();
+
+  // Make-and-model string guesses.
+  std::vector<std::string> make_and_model;
+
+  // 16-bit usb identifiers.
+  int usb_vendor_id = 0;
+  int usb_product_id = 0;
+
+  // Method of printer discovery.
+  enum PrinterDiscoveryType {
+    kUnknown = 0,
+    kManual = 1,
+    kUsb = 2,
+    kZeroconf = 3,
+    kDiscoveryTypeMax
+  };
+  PrinterDiscoveryType discovery_type;
+
+  // Set of MIME types supported by this printer.
+  std::vector<std::string> supported_document_formats;
+
+  // Stripped from IEEE1284 signaling method(from the device ID key 'CMD').
+  // Details a set of languages this printer understands.
+  std::vector<std::string> usb_command_set;
+};
+
 // PpdProvider is responsible for mapping printer descriptions to
 // CUPS-PostScript Printer Description (PPD) files.  It provides PPDs that a
 // user previously identified for use, and falls back to querying quirksserver
@@ -68,25 +104,6 @@
     std::string ppd_server_root = "https://www.gstatic.com/chromeos_printing";
   };
 
-  // Everything we might know about a printer when looking for a
-  // driver for it.  All of the default values for fields in this struct
-  // mean we *don't* have that piece of information.
-  //
-  // Fields are listed in search order preference -- we use earlier
-  // fields first to attempt to find a match.
-  struct PrinterSearchData {
-    PrinterSearchData();
-    PrinterSearchData(const PrinterSearchData& other);
-    ~PrinterSearchData();
-
-    // Make-and-model string guesses.
-    std::vector<std::string> make_and_model;
-
-    // 16-bit usb identifiers.
-    int usb_vendor_id = 0;
-    int usb_product_id = 0;
-  };
-
   // Defines the limitations on when we show a particular PPD
   struct Restrictions {
     // Minimum milestone for ChromeOS build
diff --git a/chromeos/printing/ppd_provider_unittest.cc b/chromeos/printing/ppd_provider_unittest.cc
index 4f0e942..98458214 100644
--- a/chromeos/printing/ppd_provider_unittest.cc
+++ b/chromeos/printing/ppd_provider_unittest.cc
@@ -392,13 +392,13 @@
   StartFakePpdServer();
   auto provider = CreateProvider("en", false);
 
-  PpdProvider::PrinterSearchData unrecognized_printer;
+  PrinterSearchData unrecognized_printer;
   unrecognized_printer.make_and_model = {"Printer Printer"};
 
-  PpdProvider::PrinterSearchData recognized_printer;
+  PrinterSearchData recognized_printer;
   recognized_printer.make_and_model = {"printer_a_ref"};
 
-  PpdProvider::PrinterSearchData mixed;
+  PrinterSearchData mixed;
   mixed.make_and_model = {"printer_a_ref", "Printer Printer"};
 
   // Resolve the same thing repeatedly.
@@ -432,7 +432,7 @@
   StartFakePpdServer();
   auto provider = CreateProvider("en", false);
 
-  PpdProvider::PrinterSearchData search_data;
+  PrinterSearchData search_data;
 
   // Should get back "Some canonical reference"
   search_data.usb_vendor_id = 0x031f;
@@ -728,7 +728,7 @@
   provider->ReverseLookup(ref,
                           base::BindOnce(&PpdProviderTest::CaptureReverseLookup,
                                          base::Unretained(this)));
-  PpdProvider::PrinterSearchData printer_info;
+  PrinterSearchData printer_info;
   printer_info.make_and_model = {ref};
   provider->ResolvePpdReference(
       printer_info, base::BindOnce(&PpdProviderTest::CaptureResolvePpdReference,
diff --git a/chromeos/services/assistant/assistant_settings_manager_impl.cc b/chromeos/services/assistant/assistant_settings_manager_impl.cc
index 31811cd5..4f596dd 100644
--- a/chromeos/services/assistant/assistant_settings_manager_impl.cc
+++ b/chromeos/services/assistant/assistant_settings_manager_impl.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "chromeos/dbus/util/version_loader.h"
 #include "chromeos/services/assistant/assistant_manager_service_impl.h"
 #include "chromeos/services/assistant/constants.h"
diff --git a/chromeos/services/assistant/platform/audio_input_impl.cc b/chromeos/services/assistant/platform/audio_input_impl.cc
index 030f04e..4f79c164 100644
--- a/chromeos/services/assistant/platform/audio_input_impl.cc
+++ b/chromeos/services/assistant/platform/audio_input_impl.cc
@@ -7,6 +7,7 @@
 #include "base/bind.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
+#include "base/timer/timer.h"
 #include "chromeos/services/assistant/public/features.h"
 #include "libassistant/shared/public/platform_audio_buffer.h"
 #include "media/audio/audio_device_description.h"
diff --git a/chromeos/services/assistant/service_unittest.cc b/chromeos/services/assistant/service_unittest.cc
index dac17a9..07d27ac 100644
--- a/chromeos/services/assistant/service_unittest.cc
+++ b/chromeos/services/assistant/service_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/time/tick_clock.h"
 #include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "chromeos/dbus/fake_power_manager_client.h"
 #include "chromeos/services/assistant/fake_assistant_manager_service_impl.h"
diff --git a/chromeos/services/multidevice_setup/host_backend_delegate_impl.h b/chromeos/services/multidevice_setup/host_backend_delegate_impl.h
index 6ecf969..7bdb335 100644
--- a/chromeos/services/multidevice_setup/host_backend_delegate_impl.h
+++ b/chromeos/services/multidevice_setup/host_backend_delegate_impl.h
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
+#include "base/timer/timer.h"
 #include "chromeos/components/multidevice/remote_device_ref.h"
 #include "chromeos/services/device_sync/public/cpp/device_sync_client.h"
 #include "chromeos/services/multidevice_setup/host_backend_delegate.h"
diff --git a/chromeos/services/multidevice_setup/host_verifier_impl.cc b/chromeos/services/multidevice_setup/host_verifier_impl.cc
index 35c9981..caee511 100644
--- a/chromeos/services/multidevice_setup/host_verifier_impl.cc
+++ b/chromeos/services/multidevice_setup/host_verifier_impl.cc
@@ -5,6 +5,7 @@
 #include "chromeos/services/multidevice_setup/host_verifier_impl.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
 #include "base/no_destructor.h"
diff --git a/chromeos/services/multidevice_setup/multidevice_setup_service_unittest.cc b/chromeos/services/multidevice_setup/multidevice_setup_service_unittest.cc
index f871340..d28c7f64 100644
--- a/chromeos/services/multidevice_setup/multidevice_setup_service_unittest.cc
+++ b/chromeos/services/multidevice_setup/multidevice_setup_service_unittest.cc
@@ -5,6 +5,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
 #include "chromeos/components/multidevice/remote_device_test_util.h"
diff --git a/chromeos/services/secure_channel/public/cpp/client/client_channel_impl_unittest.cc b/chromeos/services/secure_channel/public/cpp/client/client_channel_impl_unittest.cc
index 6d2493f..2119605 100644
--- a/chromeos/services/secure_channel/public/cpp/client/client_channel_impl_unittest.cc
+++ b/chromeos/services/secure_channel/public/cpp/client/client_channel_impl_unittest.cc
@@ -5,6 +5,7 @@
 #include "chromeos/services/secure_channel/public/cpp/client/client_channel_impl.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/no_destructor.h"
diff --git a/chromeos/timezone/timezone_resolver.cc b/chromeos/timezone/timezone_resolver.cc
index a57f12ed..ac6774596 100644
--- a/chromeos/timezone/timezone_resolver.cc
+++ b/chromeos/timezone/timezone_resolver.cc
@@ -18,6 +18,7 @@
 #include "base/rand_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "chromeos/geolocation/geoposition.h"
 #include "chromeos/geolocation/simple_geolocation_provider.h"
 #include "chromeos/timezone/timezone_provider.h"
diff --git a/chromeos/timezone/timezone_resolver.h b/chromeos/timezone/timezone_resolver.h
index d31c384..04160ecf 100644
--- a/chromeos/timezone/timezone_resolver.h
+++ b/chromeos/timezone/timezone_resolver.h
@@ -35,7 +35,8 @@
 
   // chromeos::DelayNetworkCall cannot be used directly due to link
   // restrictions.
-  using DelayNetworkCallClosure = base::Callback<void(const base::Closure&)>;
+  using DelayNetworkCallClosure =
+      base::RepeatingCallback<void(base::OnceClosure)>;
 
   class Delegate {
    public:
diff --git a/components/arc/power/arc_power_bridge.h b/components/arc/power/arc_power_bridge.h
index 5697d7c..34df4abe 100644
--- a/components/arc/power/arc_power_bridge.h
+++ b/components/arc/power/arc_power_bridge.h
@@ -10,6 +10,7 @@
 
 #include "base/macros.h"
 #include "base/optional.h"
+#include "base/timer/timer.h"
 #include "chromeos/dbus/power_manager_client.h"
 #include "components/arc/common/power.mojom.h"
 #include "components/arc/connection_observer.h"
diff --git a/components/arc/test/fake_clipboard_instance.cc b/components/arc/test/fake_clipboard_instance.cc
index c372584..1ab61d0b 100644
--- a/components/arc/test/fake_clipboard_instance.cc
+++ b/components/arc/test/fake_clipboard_instance.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "components/arc/test/fake_clipboard_instance.h"
+#include "base/bind_helpers.h"
 
 namespace arc {
 
diff --git a/components/autofill/core/browser/credit_card_save_manager.cc b/components/autofill/core/browser/credit_card_save_manager.cc
index cef57c0..8461702 100644
--- a/components/autofill/core/browser/credit_card_save_manager.cc
+++ b/components/autofill/core/browser/credit_card_save_manager.cc
@@ -15,6 +15,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/feature_list.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
diff --git a/components/autofill_assistant/browser/batch_element_checker_unittest.cc b/components/autofill_assistant/browser/batch_element_checker_unittest.cc
index 1dabee2..8a5d239b 100644
--- a/components/autofill_assistant/browser/batch_element_checker_unittest.cc
+++ b/components/autofill_assistant/browser/batch_element_checker_unittest.cc
@@ -8,6 +8,7 @@
 #include <set>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/test/mock_callback.h"
 #include "base/test/scoped_task_environment.h"
 #include "components/autofill_assistant/browser/mock_run_once_callback.h"
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc
index cc77d1dd..5a82a20 100644
--- a/components/autofill_assistant/browser/controller.cc
+++ b/components/autofill_assistant/browser/controller.cc
@@ -56,18 +56,9 @@
 
 }  // namespace
 
-Controller::Controller(content::WebContents* web_contents,
-                       Client* client,
-                       std::unique_ptr<WebController> web_controller,
-                       std::unique_ptr<Service> service)
+Controller::Controller(content::WebContents* web_contents, Client* client)
     : content::WebContentsObserver(web_contents),
       client_(client),
-      web_controller_(std::move(web_controller)),
-      service_(std::move(service)),
-      memory_(std::make_unique<ClientMemory>()),
-      touchable_element_area_(web_controller_.get()),
-      script_tracker_(std::make_unique<ScriptTracker>(/* delegate= */ this,
-                                                      /* listener= */ this)),
       weak_ptr_factory_(this) {
   // Only set the controller as the delegate if web_contents does not yet have
   // one.
@@ -87,6 +78,9 @@
 }
 
 Service* Controller::GetService() {
+  if (!service_) {
+    service_ = Service::Create(web_contents()->GetBrowserContext(), client_);
+  }
   return service_.get();
 }
 
@@ -95,10 +89,16 @@
 }
 
 WebController* Controller::GetWebController() {
+  if (!web_controller_) {
+    web_controller_ = WebController::CreateForWebContents(web_contents());
+  }
   return web_controller_.get();
 }
 
 ClientMemory* Controller::GetClientMemory() {
+  if (!memory_) {
+    memory_ = std::make_unique<ClientMemory>();
+  }
   return memory_.get();
 }
 
@@ -115,7 +115,7 @@
 }
 
 void Controller::SetTouchableElementArea(const ElementAreaProto& area) {
-  touchable_element_area_.SetFromProto(area);
+  touchable_element_area()->SetFromProto(area);
 }
 
 void Controller::SetStatusMessage(const std::string& message) {
@@ -152,19 +152,26 @@
   GetUiController()->OnStateChanged(state);
 }
 
+void Controller::SetWebControllerAndServiceForTest(
+    std::unique_ptr<WebController> web_controller,
+    std::unique_ptr<Service> service) {
+  web_controller_ = std::move(web_controller);
+  service_ = std::move(service);
+}
+
 void Controller::GetOrCheckScripts(const GURL& url) {
-  if (!started_ || script_tracker_->running()) {
+  if (!started_ || script_tracker()->running()) {
     return;
   }
 
   if (script_domain_ != url.host()) {
     StopPeriodicScriptChecks();
     script_domain_ = url.host();
-    service_->GetScriptsForUrl(
+    GetService()->GetScriptsForUrl(
         url, parameters_,
         base::BindOnce(&Controller::OnGetScripts, base::Unretained(this), url));
   } else {
-    script_tracker_->CheckScripts(kPeriodicScriptCheckInterval);
+    script_tracker()->CheckScripts(kPeriodicScriptCheckInterval);
     StartPeriodicScriptChecks();
   }
 }
@@ -204,7 +211,7 @@
   }
 
   periodic_script_check_count_--;
-  script_tracker_->CheckScripts(kPeriodicScriptCheckInterval);
+  script_tracker()->CheckScripts(kPeriodicScriptCheckInterval);
   base::PostDelayedTaskWithTraits(
       FROM_HERE, {content::BrowserThread::UI},
       base::BindOnce(&Controller::OnPeriodicScriptCheck,
@@ -229,25 +236,25 @@
   std::vector<std::unique_ptr<Script>> scripts;
   bool parse_result = ProtocolUtils::ParseScripts(response, &scripts);
   DCHECK(parse_result);
-  script_tracker_->SetScripts(std::move(scripts));
-  script_tracker_->CheckScripts(kPeriodicScriptCheckInterval);
+  script_tracker()->SetScripts(std::move(scripts));
+  script_tracker()->CheckScripts(kPeriodicScriptCheckInterval);
   StartPeriodicScriptChecks();
 }
 
 void Controller::ExecuteScript(const std::string& script_path) {
-  DCHECK(!script_tracker_->running());
+  DCHECK(!script_tracker()->running());
   EnterState(AutofillAssistantState::RUNNING);
 
-  touchable_element_area_.Clear();
+  touchable_element_area()->Clear();
 
   StopPeriodicScriptChecks();
   // Runnable scripts will be checked and reported if necessary after executing
   // the script.
-  script_tracker_->ClearRunnableScripts();
+  script_tracker()->ClearRunnableScripts();
   GetUiController()->ClearChips();
   // TODO(crbug.com/806868): Consider making ClearRunnableScripts part of
   // ExecuteScripts to simplify the controller.
-  script_tracker_->ExecuteScript(
+  script_tracker()->ExecuteScript(
       script_path, base::BindOnce(&Controller::OnScriptExecuted,
                                   // script_tracker_ is owned by Controller.
                                   base::Unretained(this), script_path));
@@ -262,12 +269,13 @@
     EnterState(AutofillAssistantState::STOPPED);
     return;
   }
+
   if (result.touchable_element_area) {
-    touchable_element_area_.SetFromProto(*result.touchable_element_area);
+    touchable_element_area()->SetFromProto(*result.touchable_element_area);
   } else {
     // For backward-compatibility, if no touchable elements are defined, the
     // whole screen is available instead of nothing being available.
-    touchable_element_area_.CoverViewport();
+    touchable_element_area()->CoverViewport();
   }
 
   switch (result.at_end) {
@@ -289,9 +297,8 @@
       return;
 
     case ScriptExecutor::RESTART:
-      script_tracker_ = std::make_unique<ScriptTracker>(/* delegate= */ this,
-                                                        /* listener= */ this);
-      memory_ = std::make_unique<ClientMemory>();
+      script_tracker_.reset();
+      memory_.reset();
       script_domain_ = "";
       break;
 
@@ -378,12 +385,6 @@
         IDS_AUTOFILL_ASSISTANT_LOADING, base::UTF8ToUTF16(initial_url.host())));
     GetUiController()->ShowProgressBar(kAutostartInitialProgress);
   }
-
-  touchable_element_area_.SetOnUpdate(base::BindRepeating(
-      &UiController::UpdateTouchableArea,
-      // Unretained is safe, since touchable_element_area_ is guaranteed to be
-      // deleted before the UI controller.
-      base::Unretained(GetUiController())));
 }
 
 void Controller::MaybeSetInitialDetails() {
@@ -416,7 +417,9 @@
 
 bool Controller::Terminate() {
   StopPeriodicScriptChecks();
-  return script_tracker_->Terminate();
+  if (script_tracker_)
+    return script_tracker_->Terminate();
+  return true;
 }
 
 void Controller::OnScriptSelected(const std::string& script_path) {
@@ -429,11 +432,11 @@
 }
 
 void Controller::UpdateTouchableArea() {
-  touchable_element_area_.UpdatePositions();
+  touchable_element_area()->UpdatePositions();
 }
 
 void Controller::OnUserInteractionInsideTouchableArea() {
-  script_tracker_->CheckScripts(kPeriodicScriptCheckInterval);
+  script_tracker()->CheckScripts(kPeriodicScriptCheckInterval);
   StartPeriodicScriptChecks();
 }
 
@@ -448,7 +451,7 @@
     parameters_js.push_back(std::move(parameter_js));
   }
   dict.SetKey("parameters", base::Value(parameters_js));
-  dict.SetKey("scripts", script_tracker_->GetDebugContext());
+  dict.SetKey("scripts", script_tracker()->GetDebugContext());
 
   if (details_)
     dict.SetKey("details", details_->GetDebugContext());
@@ -459,7 +462,7 @@
 }
 
 void Controller::OnNoRunnableScriptsAnymore() {
-  if (script_tracker_->running())
+  if (script_tracker()->running())
     return;
 
   // We're navigated to a page that has no scripts or the scripts have reached a
@@ -472,7 +475,7 @@
     const std::vector<ScriptHandle>& runnable_scripts) {
   // Script selection is disabled when a script is already running. We will
   // check again and maybe update when the current script has finished.
-  if (script_tracker_->running())
+  if (script_tracker()->running())
     return;
 
   if (!runnable_scripts.empty()) {
@@ -520,7 +523,7 @@
     // If there's no script to autostart, allow access to the whole screen
     // during the first prompt. In normal operations, touchable_element_area_ is
     // set at the end of a successful script.
-    touchable_element_area_.CoverViewport();
+    touchable_element_area()->CoverViewport();
   }
   EnterState(AutofillAssistantState::PROMPT);
   GetUiController()->SetChips(std::move(chips));
@@ -541,6 +544,9 @@
 
 void Controller::DidStartNavigation(
     content::NavigationHandle* navigation_handle) {
+  if (!started_)
+    return;
+
   // The following types of navigations are allowed for the main frame:
   //  - first-time URL load
   //  - script-directed navigation, while a script is running unless
@@ -558,22 +564,12 @@
   if (navigation_handle->IsInMainFrame() &&
       web_contents()->GetLastCommittedURL().is_valid() &&
       !navigation_handle->WasServerRedirect() &&
-      !navigation_handle->IsSameDocument()) {
-    if (!script_tracker_->running() &&
-        !navigation_handle->IsRendererInitiated()) {
+      !navigation_handle->IsSameDocument() &&
+      !navigation_handle->IsRendererInitiated()) {
+    // The action can define a touchable element area that prevents navigation.
+    if (!script_tracker_ || !script_tracker()->running() ||
+        touchable_element_area()->HasElements()) {
       GiveUp();
-      return;
-    }
-
-    // Special case: during a prompt, only forbid non-render-initiated
-    // navigation for the main frame, such as going back to the previous page or
-    // refreshing the page using the UI. This allows clicking on links and
-    // Javascript-initiated navigation; it's up to the action to define a
-    // touchable element area that prevents these from happening.
-    if (script_tracker_->running() && touchable_element_area_.HasElements() &&
-        !navigation_handle->IsRendererInitiated()) {
-      GiveUp();
-      return;
     }
   }
 }
@@ -608,4 +604,24 @@
   return iter != parameters_.end() && iter->second == "1";
 }
 
+ElementArea* Controller::touchable_element_area() {
+  if (!touchable_element_area_) {
+    touchable_element_area_ = std::make_unique<ElementArea>(this);
+    touchable_element_area_->SetOnUpdate(base::BindRepeating(
+        &UiController::UpdateTouchableArea,
+        // Unretained is safe, since touchable_element_area_ is guaranteed to be
+        // deleted before the UI controller.
+        base::Unretained(GetUiController())));
+  }
+  return touchable_element_area_.get();
+}
+
+ScriptTracker* Controller::script_tracker() {
+  if (!script_tracker_) {
+    script_tracker_ = std::make_unique<ScriptTracker>(/* delegate= */ this,
+                                                      /* listener= */ this);
+  }
+  return script_tracker_.get();
+}
+
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/controller.h b/components/autofill_assistant/browser/controller.h
index d18ebfb2..36fa10e 100644
--- a/components/autofill_assistant/browser/controller.h
+++ b/components/autofill_assistant/browser/controller.h
@@ -43,10 +43,7 @@
  public:
   // |web_contents| and |client| must remain valid for the lifetime of the
   // instance.
-  Controller(content::WebContents* web_contents,
-             Client* client,
-             std::unique_ptr<WebController> web_controller,
-             std::unique_ptr<Service> service);
+  Controller(content::WebContents* web_contents, Client* client);
   ~Controller() override;
 
   // Called when autofill assistant can start executing scripts.
@@ -87,6 +84,10 @@
  private:
   friend ControllerTest;
 
+  void SetWebControllerAndServiceForTest(
+      std::unique_ptr<WebController> web_controller,
+      std::unique_ptr<Service> service);
+
   void GetOrCheckScripts(const GURL& url);
   void OnGetScripts(const GURL& url, bool result, const std::string& response);
   void ExecuteScript(const std::string& script_path);
@@ -146,10 +147,19 @@
   void LoadProgressChanged(content::WebContents* source,
                            double progress) override;
 
+  ElementArea* touchable_element_area();
+  ScriptTracker* script_tracker();
+
   Client* const client_;
+
+  // Lazily instantiate in GetWebController().
   std::unique_ptr<WebController> web_controller_;
+
+  // Lazily instantiate in GetService().
   std::unique_ptr<Service> service_;
   std::map<std::string, std::string> parameters_;
+
+  // Lazily instantiate in GetClientMemory().
   std::unique_ptr<ClientMemory> memory_;
 
   AutofillAssistantState state_ = AutofillAssistantState::INACTIVE;
@@ -175,7 +185,8 @@
 
   // Area of the screen that corresponds to the current set of touchable
   // elements.
-  ElementArea touchable_element_area_;
+  // Lazily instantiate in touchable_element_area().
+  std::unique_ptr<ElementArea> touchable_element_area_;
 
   // Current status message, may be empty.
   std::string status_message_;
@@ -189,6 +200,7 @@
   // Tracks scripts and script execution. It's kept at the end, as it tend to
   // depend on everything the controller support, through script and script
   // actions.
+  // Lazily instantiate in script_tracker().
   std::unique_ptr<ScriptTracker> script_tracker_;
 
   base::WeakPtrFactory<Controller> weak_ptr_factory_;
diff --git a/components/autofill_assistant/browser/controller_unittest.cc b/components/autofill_assistant/browser/controller_unittest.cc
index af110d9..82a6d9d6 100644
--- a/components/autofill_assistant/browser/controller_unittest.cc
+++ b/components/autofill_assistant/browser/controller_unittest.cc
@@ -76,9 +76,9 @@
     auto service = std::make_unique<NiceMock<MockService>>();
     mock_service_ = service.get();
 
-    controller_ = std::make_unique<Controller>(web_contents(), &fake_client_,
-                                               std::move(web_controller),
-                                               std::move(service));
+    controller_ = std::make_unique<Controller>(web_contents(), &fake_client_);
+    controller_->SetWebControllerAndServiceForTest(std::move(web_controller),
+                                                   std::move(service));
 
     // Fetching scripts succeeds for all URLs, but return nothing.
     ON_CALL(*mock_service_, OnGetScriptsForUrl(_, _, _))
diff --git a/components/autofill_assistant/browser/element_area.cc b/components/autofill_assistant/browser/element_area.cc
index dc10edac..33046ff 100644
--- a/components/autofill_assistant/browser/element_area.cc
+++ b/components/autofill_assistant/browser/element_area.cc
@@ -11,6 +11,7 @@
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "components/autofill_assistant/browser/script_executor_delegate.h"
 #include "components/autofill_assistant/browser/web_controller.h"
 
 namespace autofill_assistant {
@@ -21,11 +22,9 @@
     base::TimeDelta::FromMilliseconds(100);
 }  // namespace
 
-ElementArea::ElementArea(WebController* web_controller)
-    : web_controller_(web_controller),
-      scheduled_update_(false),
-      weak_ptr_factory_(this) {
-  DCHECK(web_controller_);
+ElementArea::ElementArea(ScriptExecutorDelegate* delegate)
+    : delegate_(delegate), scheduled_update_(false), weak_ptr_factory_(this) {
+  DCHECK(delegate_);
 }
 
 ElementArea::~ElementArea() = default;
@@ -82,7 +81,7 @@
       position.pending_update = true;
     }
     for (auto& position : rectangle.positions) {
-      web_controller_->GetElementPosition(
+      delegate_->GetWebController()->GetElementPosition(
           position.selector,
           base::BindOnce(&ElementArea::OnGetElementPosition,
                          weak_ptr_factory_.GetWeakPtr(), position.selector));
diff --git a/components/autofill_assistant/browser/element_area.h b/components/autofill_assistant/browser/element_area.h
index 1eef6fa0..7b4e996 100644
--- a/components/autofill_assistant/browser/element_area.h
+++ b/components/autofill_assistant/browser/element_area.h
@@ -15,14 +15,14 @@
 #include "components/autofill_assistant/browser/selector.h"
 
 namespace autofill_assistant {
-class WebController;
+class ScriptExecutorDelegate;
 
 // A helper that keeps track of the area on the screen that correspond to an
 // changeable set of elements.
 class ElementArea {
  public:
-  // |web_controller| must remain valid for the lifetime of this instance.
-  explicit ElementArea(WebController* web_controller);
+  // |delegate| must remain valid for the lifetime of this instance.
+  explicit ElementArea(ScriptExecutorDelegate* delegate);
   ~ElementArea();
 
   // Clears the area. Stops scheduled updates.
@@ -107,7 +107,7 @@
                             const RectF& rect);
   void ReportUpdate();
 
-  WebController* const web_controller_;
+  ScriptExecutorDelegate* const delegate_;
   std::vector<Rectangle> rectangles_;
   bool cover_viewport_ = false;
 
diff --git a/components/autofill_assistant/browser/element_area_unittest.cc b/components/autofill_assistant/browser/element_area_unittest.cc
index 1ee2e6c..c258735 100644
--- a/components/autofill_assistant/browser/element_area_unittest.cc
+++ b/components/autofill_assistant/browser/element_area_unittest.cc
@@ -5,6 +5,7 @@
 #include "components/autofill_assistant/browser/element_area.h"
 
 #include <algorithm>
+#include <map>
 
 #include "base/bind.h"
 #include "base/strings/stringprintf.h"
@@ -12,6 +13,7 @@
 #include "base/test/scoped_task_environment.h"
 #include "components/autofill_assistant/browser/mock_run_once_callback.h"
 #include "components/autofill_assistant/browser/mock_web_controller.h"
+#include "components/autofill_assistant/browser/script_executor_delegate.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 using ::testing::_;
@@ -39,18 +41,48 @@
 
 ACTION(DoNothing) {}
 
-class ElementAreaTest : public testing::Test {
+class ElementAreaTest : public testing::Test, public ScriptExecutorDelegate {
  protected:
   ElementAreaTest()
       : scoped_task_environment_(
             base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
-        element_area_(&mock_web_controller_) {
+        element_area_(this) {
     ON_CALL(mock_web_controller_, OnGetElementPosition(_, _))
         .WillByDefault(RunOnceCallback<1>(false, RectF()));
     element_area_.SetOnUpdate(base::BindRepeating(&ElementAreaTest::OnUpdate,
                                                   base::Unretained(this)));
   }
 
+  // Overrides ScriptTrackerDelegate
+  Service* GetService() override { return nullptr; }
+
+  UiController* GetUiController() override { return nullptr; }
+
+  WebController* GetWebController() override { return &mock_web_controller_; }
+
+  ClientMemory* GetClientMemory() override { return nullptr; }
+
+  void EnterState(AutofillAssistantState state) override {}
+
+  const std::map<std::string, std::string>& GetParameters() override {
+    return parameters_;
+  }
+
+  autofill::PersonalDataManager* GetPersonalDataManager() override {
+    return nullptr;
+  }
+
+  content::WebContents* GetWebContents() override { return nullptr; }
+
+  void SetTouchableElementArea(const ElementAreaProto& element_area) override {}
+
+  void SetStatusMessage(const std::string& status_message) override {}
+  std::string GetStatusMessage() const override { return std::string(); }
+
+  void SetDetails(const Details& details) override {}
+
+  void ClearDetails() override {}
+
   void SetElement(const std::string& selector) {
     ElementAreaProto area;
     area.add_rectangles()->add_elements()->add_selectors(selector);
@@ -66,6 +98,7 @@
   base::test::ScopedTaskEnvironment scoped_task_environment_;
 
   MockWebController mock_web_controller_;
+  std::map<std::string, std::string> parameters_;
   ElementArea element_area_;
   std::vector<RectF> highlighted_area_;
 };
diff --git a/components/autofill_assistant/browser/script_executor.cc b/components/autofill_assistant/browser/script_executor.cc
index 9e47d898..18f6828 100644
--- a/components/autofill_assistant/browser/script_executor.cc
+++ b/components/autofill_assistant/browser/script_executor.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerExternalUma.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerExternalUma.java
index 5fc778b..43e350f 100644
--- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerExternalUma.java
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerExternalUma.java
@@ -18,4 +18,21 @@
     public static void reportTaskStartedNative(int taskId) {
         BackgroundTaskSchedulerUma.getInstance().reportTaskStartedNative(taskId);
     }
+
+    /**
+     * Report metrics for starting a NativeBackgroundTask. This does not consider tasks that are
+     * short-circuited before any work is done.
+     */
+    public static void reportNativeTaskStarted(int taskId) {
+        BackgroundTaskSchedulerUma.getInstance().reportNativeTaskStarted(taskId);
+    }
+
+    /**
+     * Reports metrics that a NativeBackgroundTask has been finished cleanly (i.e., no unexpected
+     * exits because of chrome crash or OOM). This includes tasks that have been stopped due to
+     * timeout.
+     */
+    public static void reportNativeTaskFinished(int taskId) {
+        BackgroundTaskSchedulerUma.getInstance().reportNativeTaskFinished(taskId);
+    }
 }
\ No newline at end of file
diff --git a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java
index d1ca29e..41efef4e 100644
--- a/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java
+++ b/components/background_task_scheduler/android/java/src/org/chromium/components/background_task_scheduler/BackgroundTaskSchedulerUma.java
@@ -157,6 +157,23 @@
                 toUmaEnumValueFromTaskId(taskId));
     }
 
+    /**
+     * Report metrics for starting a NativeBackgroundTask. This does not consider tasks that are
+     * short-circuited before any work is done.
+     */
+    public void reportNativeTaskStarted(int taskId) {
+        cacheEvent("Android.NativeBackgroundTask.TaskStarted", toUmaEnumValueFromTaskId(taskId));
+    }
+
+    /**
+     * Reports metrics that a NativeBackgroundTask has been finished cleanly (i.e., no unexpected
+     * exits because of chrome crash or OOM). This includes tasks that have been stopped due to
+     * timeout.
+     */
+    public void reportNativeTaskFinished(int taskId) {
+        cacheEvent("Android.NativeBackgroundTask.TaskFinished", toUmaEnumValueFromTaskId(taskId));
+    }
+
     /** Method that actually invokes histogram recording. Extracted for testing. */
     @VisibleForTesting
     void recordEnumeratedHistogram(String histogram, int value, int maxCount) {
diff --git a/components/browser_sync/profile_sync_test_util.cc b/components/browser_sync/profile_sync_test_util.cc
index 5fa7ecb..b26ad96 100644
--- a/components/browser_sync/profile_sync_test_util.cc
+++ b/components/browser_sync/profile_sync_test_util.cc
@@ -7,6 +7,7 @@
 #include <string>
 #include <utility>
 
+#include "base/bind_helpers.h"
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/sequenced_task_runner_handle.h"
diff --git a/components/browsing_data/core/browsing_data_utils_unittest.cc b/components/browsing_data/core/browsing_data_utils_unittest.cc
index aa2f1369..f494e540 100644
--- a/components/browsing_data/core/browsing_data_utils_unittest.cc
+++ b/components/browsing_data/core/browsing_data_utils_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <string>
 
+#include "base/bind_helpers.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/scoped_task_environment.h"
@@ -167,4 +168,4 @@
   }
 }
 
-}  // namespace browsing_data
\ No newline at end of file
+}  // namespace browsing_data
diff --git a/components/cast_channel/cast_message_handler.h b/components/cast_channel/cast_message_handler.h
index 3a7b48e..e6049ad 100644
--- a/components/cast_channel/cast_message_handler.h
+++ b/components/cast_channel/cast_message_handler.h
@@ -13,6 +13,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
 #include "base/time/tick_clock.h"
+#include "base/timer/timer.h"
 #include "base/token.h"
 #include "base/values.h"
 #include "components/cast_channel/cast_message_util.h"
diff --git a/components/cast_channel/cast_message_handler_unittest.cc b/components/cast_channel/cast_message_handler_unittest.cc
index c754859..4b91ae48 100644
--- a/components/cast_channel/cast_message_handler_unittest.cc
+++ b/components/cast_channel/cast_message_handler_unittest.cc
@@ -5,6 +5,7 @@
 #include "components/cast_channel/cast_message_handler.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/json/json_reader.h"
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
diff --git a/components/cast_channel/keep_alive_delegate_unittest.cc b/components/cast_channel/keep_alive_delegate_unittest.cc
index 087e0339..7b4c25cb 100644
--- a/components/cast_channel/keep_alive_delegate_unittest.cc
+++ b/components/cast_channel/keep_alive_delegate_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/time/tick_clock.h"
 #include "base/timer/mock_timer.h"
+#include "base/timer/timer.h"
 #include "base/values.h"
 #include "components/cast_channel/cast_test_util.h"
 #include "net/base/net_errors.h"
diff --git a/components/component_updater/component_installer_unittest.cc b/components/component_updater/component_installer_unittest.cc
index afebb3d..638591a27 100644
--- a/components/component_updater/component_installer_unittest.cc
+++ b/components/component_updater/component_installer_unittest.cc
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
diff --git a/components/component_updater/component_updater_service.cc b/components/component_updater/component_updater_service.cc
index 2c11f11..a98f186 100644
--- a/components/component_updater/component_updater_service.cc
+++ b/components/component_updater/component_updater_service.cc
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
diff --git a/components/component_updater/timer_update_scheduler.cc b/components/component_updater/timer_update_scheduler.cc
index 36d694a..9035af2 100644
--- a/components/component_updater/timer_update_scheduler.cc
+++ b/components/component_updater/timer_update_scheduler.cc
@@ -4,6 +4,7 @@
 
 #include "components/component_updater/timer_update_scheduler.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 
 namespace component_updater {
 
diff --git a/components/download/internal/common/download_file_impl.cc b/components/download/internal/common/download_file_impl.cc
index f24872f2..d200eaf 100644
--- a/components/download/internal/common/download_file_impl.cc
+++ b/components/download/internal/common/download_file_impl.cc
@@ -13,6 +13,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "base/values.h"
 #include "components/download/internal/common/parallel_download_utils.h"
 #include "components/download/public/common/download_create_info.h"
diff --git a/components/drive/chromeos/change_list_loader.cc b/components/drive/chromeos/change_list_loader.cc
index 3c01c91..e7d495be 100644
--- a/components/drive/chromeos/change_list_loader.cc
+++ b/components/drive/chromeos/change_list_loader.cc
@@ -11,6 +11,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/callback_helpers.h"
 #include "base/macros.h"
diff --git a/components/drive/chromeos/default_corpus_change_list_loader.cc b/components/drive/chromeos/default_corpus_change_list_loader.cc
index 2bab6d44..2ecb6ce 100644
--- a/components/drive/chromeos/default_corpus_change_list_loader.cc
+++ b/components/drive/chromeos/default_corpus_change_list_loader.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/time/clock.h"
 #include "components/drive/chromeos/about_resource_root_folder_id_loader.h"
 #include "components/drive/file_system_core_util.h"
diff --git a/components/drive/chromeos/dummy_file_system.cc b/components/drive/chromeos/dummy_file_system.cc
index ff8c14df..b284bcb38 100644
--- a/components/drive/chromeos/dummy_file_system.cc
+++ b/components/drive/chromeos/dummy_file_system.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "components/drive/chromeos/dummy_file_system.h"
+#include "base/bind_helpers.h"
 
 namespace drive {
 
diff --git a/components/drive/chromeos/file_system.cc b/components/drive/chromeos/file_system.cc
index 64699bb..39a57ed 100644
--- a/components/drive/chromeos/file_system.cc
+++ b/components/drive/chromeos/file_system.cc
@@ -12,6 +12,7 @@
 
 #include "base/barrier_closure.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_util.h"
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
diff --git a/components/drive/chromeos/sync_client.cc b/components/drive/chromeos/sync_client.cc
index 5d59647c..262a971 100644
--- a/components/drive/chromeos/sync_client.cc
+++ b/components/drive/chromeos/sync_client.cc
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "components/drive/chromeos/file_cache.h"
 #include "components/drive/chromeos/file_system/download_operation.h"
diff --git a/components/feed/core/feed_image_manager_unittest.cc b/components/feed/core/feed_image_manager_unittest.cc
index 81ea896..418724a 100644
--- a/components/feed/core/feed_image_manager_unittest.cc
+++ b/components/feed/core/feed_image_manager_unittest.cc
@@ -15,6 +15,7 @@
 #include "base/test/mock_callback.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/sequenced_task_runner_handle.h"
+#include "base/timer/timer.h"
 #include "components/image_fetcher/core/image_decoder.h"
 #include "components/image_fetcher/core/image_fetcher_impl.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
diff --git a/components/gcm_driver/fake_gcm_client.h b/components/gcm_driver/fake_gcm_client.h
index d3bd6f6..4dea554 100644
--- a/components/gcm_driver/fake_gcm_client.h
+++ b/components/gcm_driver/fake_gcm_client.h
@@ -10,6 +10,7 @@
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/timer/timer.h"
 #include "components/gcm_driver/gcm_client.h"
 #include "components/gcm_driver/gcm_stats_recorder_impl.h"
 
diff --git a/components/gcm_driver/gcm_client_impl.h b/components/gcm_driver/gcm_client_impl.h
index d58742d9..18feb80 100644
--- a/components/gcm_driver/gcm_client_impl.h
+++ b/components/gcm_driver/gcm_client_impl.h
@@ -18,6 +18,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
+#include "base/timer/timer.h"
 #include "components/gcm_driver/gcm_client.h"
 #include "components/gcm_driver/gcm_stats_recorder_impl.h"
 #include "google_apis/gcm/base/mcs_message.h"
diff --git a/components/gcm_driver/gcm_driver_desktop.cc b/components/gcm_driver/gcm_driver_desktop.cc
index 804a367d..4d005c5 100644
--- a/components/gcm_driver/gcm_driver_desktop.cc
+++ b/components/gcm_driver/gcm_driver_desktop.cc
@@ -16,6 +16,7 @@
 #include "base/sequenced_task_runner.h"
 #include "base/task_runner_util.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/timer/timer.h"
 #include "build/build_config.h"
 #include "components/gcm_driver/gcm_account_mapper.h"
 #include "components/gcm_driver/gcm_app_handler.h"
@@ -473,8 +474,12 @@
 
   std::unique_ptr<base::RetainingOneShotTimer> timer;
   if (wake)
-    timer = std::make_unique<timers::SimpleAlarmTimer>();
-  else
+    timer = timers::SimpleAlarmTimer::Create();
+
+  // If not |wake|, or SimpleAlarmTimer is not supported on the running
+  // platform (please see SimpleAlarmTimer for the details), fall back to
+  // RetainingOneShotTimer.
+  if (!timer)
     timer = std::make_unique<base::RetainingOneShotTimer>();
 
   gcm_client_->UpdateHeartbeatTimer(std::move(timer));
diff --git a/components/history/core/browser/browsing_history_service_unittest.cc b/components/history/core/browser/browsing_history_service_unittest.cc
index c7724c9..c2bd57ea 100644
--- a/components/history/core/browser/browsing_history_service_unittest.cc
+++ b/components/history/core/browser/browsing_history_service_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/bind_helpers.h"
 #include "base/callback_forward.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
diff --git a/components/image_fetcher/core/cache/image_cache.cc b/components/image_fetcher/core/cache/image_cache.cc
index 7a880a9..1f61efb8 100644
--- a/components/image_fetcher/core/cache/image_cache.cc
+++ b/components/image_fetcher/core/cache/image_cache.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/sha1.h"
 #include "base/task/post_task.h"
 #include "base/task/task_traits.h"
diff --git a/components/invalidation/impl/fcm_network_handler_unittests.cc b/components/invalidation/impl/fcm_network_handler_unittests.cc
index 666bb0d3..8da013c5 100644
--- a/components/invalidation/impl/fcm_network_handler_unittests.cc
+++ b/components/invalidation/impl/fcm_network_handler_unittests.cc
@@ -14,6 +14,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/mock_callback.h"
 #include "base/test/test_mock_time_task_runner.h"
+#include "base/timer/timer.h"
 #include "build/build_config.h"
 #include "components/gcm_driver/gcm_driver.h"
 #include "components/gcm_driver/instance_id/instance_id.h"
diff --git a/components/mirroring/service/message_dispatcher.cc b/components/mirroring/service/message_dispatcher.cc
index 1f8d7b9..ebc0fcc2 100644
--- a/components/mirroring/service/message_dispatcher.cc
+++ b/components/mirroring/service/message_dispatcher.cc
@@ -8,6 +8,7 @@
 #include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "base/rand_util.h"
+#include "base/timer/timer.h"
 
 namespace mirroring {
 
diff --git a/components/net_log/net_export_file_writer.cc b/components/net_log/net_export_file_writer.cc
index e727d4fb..6f26a179 100644
--- a/components/net_log/net_export_file_writer.cc
+++ b/components/net_log/net_export_file_writer.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
diff --git a/components/offline_pages/core/background/request_coordinator.cc b/components/offline_pages/core/background/request_coordinator.cc
index 60a4087..eaab693 100644
--- a/components/offline_pages/core/background/request_coordinator.cc
+++ b/components/offline_pages/core/background/request_coordinator.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
diff --git a/components/offline_pages/core/background/request_coordinator_unittest.cc b/components/offline_pages/core/background/request_coordinator_unittest.cc
index c12f7a2..ef477c2b 100644
--- a/components/offline_pages/core/background/request_coordinator_unittest.cc
+++ b/components/offline_pages/core/background/request_coordinator_unittest.cc
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/containers/circular_deque.h"
 #include "base/location.h"
 #include "base/logging.h"
diff --git a/components/offline_pages/core/downloads/download_ui_adapter_unittest.cc b/components/offline_pages/core/downloads/download_ui_adapter_unittest.cc
index 007bcc05..c8dc249 100644
--- a/components/offline_pages/core/downloads/download_ui_adapter_unittest.cc
+++ b/components/offline_pages/core/downloads/download_ui_adapter_unittest.cc
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/run_loop.h"
diff --git a/components/offline_pages/core/model/cleanup_thumbnails_task_unittest.cc b/components/offline_pages/core/model/cleanup_thumbnails_task_unittest.cc
index 0dd76f87..68c618c1 100644
--- a/components/offline_pages/core/model/cleanup_thumbnails_task_unittest.cc
+++ b/components/offline_pages/core/model/cleanup_thumbnails_task_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <memory>
 
+#include "base/bind_helpers.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/mock_callback.h"
diff --git a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc
index cc756ce0..79b82b3e 100644
--- a/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc
+++ b/components/offline_pages/core/prefetch/prefetch_dispatcher_impl_unittest.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
diff --git a/components/omnibox/browser/omnibox_view.h b/components/omnibox/browser/omnibox_view.h
index 6c59a0e..d5b3cd41 100644
--- a/components/omnibox/browser/omnibox_view.h
+++ b/components/omnibox/browser/omnibox_view.h
@@ -194,13 +194,6 @@
   // the top-most window is the relative window.
   virtual gfx::NativeView GetRelativeWindowForPopup() const = 0;
 
-  // Returns the width in pixels needed to display the current text. The
-  // returned value includes margins.
-  virtual int GetTextWidth() const = 0;
-
-  // Returns the omnibox's width in pixels.
-  virtual int GetWidth() const = 0;
-
   // Returns true if the user is composing something in an IME.
   virtual bool IsImeComposing() const = 0;
 
diff --git a/components/omnibox/browser/omnibox_view_unittest.cc b/components/omnibox/browser/omnibox_view_unittest.cc
index b56abfe3..1d3c68d 100644
--- a/components/omnibox/browser/omnibox_view_unittest.cc
+++ b/components/omnibox/browser/omnibox_view_unittest.cc
@@ -5,6 +5,7 @@
 #include <stddef.h>
 #include <utility>
 
+#include "base/bind_helpers.h"
 #include "base/stl_util.h"
 #include "base/strings/string16.h"
 #include "base/strings/string_util.h"
diff --git a/components/omnibox/browser/test_omnibox_view.cc b/components/omnibox/browser/test_omnibox_view.cc
index 6250397..958b2fa 100644
--- a/components/omnibox/browser/test_omnibox_view.cc
+++ b/components/omnibox/browser/test_omnibox_view.cc
@@ -79,14 +79,6 @@
   return nullptr;
 }
 
-int TestOmniboxView::GetTextWidth() const {
-  return 0;
-}
-
-int TestOmniboxView::GetWidth() const {
-  return 0;
-}
-
 bool TestOmniboxView::IsImeComposing() const {
   return false;
 }
diff --git a/components/omnibox/browser/test_omnibox_view.h b/components/omnibox/browser/test_omnibox_view.h
index 530e90d2..b32bb74 100644
--- a/components/omnibox/browser/test_omnibox_view.h
+++ b/components/omnibox/browser/test_omnibox_view.h
@@ -62,8 +62,6 @@
   bool OnAfterPossibleChange(bool allow_keyword_ui_change) override;
   gfx::NativeView GetNativeView() const override;
   gfx::NativeView GetRelativeWindowForPopup() const override;
-  int GetTextWidth() const override;
-  int GetWidth() const override;
   bool IsImeComposing() const override;
   int GetOmniboxTextLength() const override;
   void EmphasizeURLComponents() override {}
diff --git a/components/pairing/bluetooth_host_pairing_controller.cc b/components/pairing/bluetooth_host_pairing_controller.cc
index b5755924..12e76ad6 100644
--- a/components/pairing/bluetooth_host_pairing_controller.cc
+++ b/components/pairing/bluetooth_host_pairing_controller.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/hash.h"
 #include "base/location.h"
 #include "base/logging.h"
diff --git a/components/password_manager/core/browser/password_store.cc b/components/password_manager/core/browser/password_store.cc
index f7bcf27..2cc35f3 100644
--- a/components/password_manager/core/browser/password_store.cc
+++ b/components/password_manager/core/browser/password_store.cc
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/debug/dump_without_crashing.h"
 #include "base/location.h"
 #include "base/macros.h"
diff --git a/components/pdf/browser/pdf_web_contents_helper.cc b/components/pdf/browser/pdf_web_contents_helper.cc
index 02d00b8..ed336f1c 100644
--- a/components/pdf/browser/pdf_web_contents_helper.cc
+++ b/components/pdf/browser/pdf_web_contents_helper.cc
@@ -6,9 +6,7 @@
 
 #include <utility>
 
-#include "base/bind.h"
 #include "base/memory/ptr_util.h"
-#include "base/strings/utf_string_conversions.h"
 #include "components/pdf/browser/pdf_web_contents_helper_client.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/common/referrer_type_converters.h"
@@ -149,7 +147,7 @@
 
 void PDFWebContentsHelper::OnManagerWillDestroy(
     content::TouchSelectionControllerClientManager* manager) {
-  DCHECK(manager == touch_selection_controller_client_manager_);
+  DCHECK_EQ(touch_selection_controller_client_manager_, manager);
   manager->RemoveObserver(this);
   touch_selection_controller_client_manager_ = nullptr;
 }
diff --git a/components/pdf/browser/pdf_web_contents_helper.h b/components/pdf/browser/pdf_web_contents_helper.h
index 2150fc0..2acb21d 100644
--- a/components/pdf/browser/pdf_web_contents_helper.h
+++ b/components/pdf/browser/pdf_web_contents_helper.h
@@ -6,9 +6,7 @@
 #define COMPONENTS_PDF_BROWSER_PDF_WEB_CONTENTS_HELPER_H_
 
 #include <memory>
-#include <string>
 
-#include "base/callback.h"
 #include "base/macros.h"
 #include "components/pdf/common/pdf.mojom.h"
 #include "content/public/browser/touch_selection_controller_client_manager.h"
@@ -67,6 +65,7 @@
 
  private:
   friend class content::WebContentsUserData<PDFWebContentsHelper>;
+
   PDFWebContentsHelper(content::WebContents* web_contents,
                        std::unique_ptr<PDFWebContentsHelperClient> client);
 
diff --git a/components/pdf/browser/pdf_web_contents_helper_client.h b/components/pdf/browser/pdf_web_contents_helper_client.h
index 9a6ae89..cc2ae23 100644
--- a/components/pdf/browser/pdf_web_contents_helper_client.h
+++ b/components/pdf/browser/pdf_web_contents_helper_client.h
@@ -5,10 +5,6 @@
 #ifndef COMPONENTS_PDF_BROWSER_PDF_WEB_CONTENTS_HELPER_CLIENT_H_
 #define COMPONENTS_PDF_BROWSER_PDF_WEB_CONTENTS_HELPER_CLIENT_H_
 
-#include "base/callback.h"
-#include "base/strings/string16.h"
-#include "ipc/ipc_message.h"
-
 namespace content {
 class WebContents;
 }
diff --git a/components/prefs/pref_service_factory.cc b/components/prefs/pref_service_factory.cc
index ef39b03..cc8e52d8 100644
--- a/components/prefs/pref_service_factory.cc
+++ b/components/prefs/pref_service_factory.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/sequenced_task_runner.h"
 #include "components/prefs/default_pref_store.h"
 #include "components/prefs/json_pref_store.h"
diff --git a/components/prefs/pref_service_unittest.cc b/components/prefs/pref_service_unittest.cc
index dfc51f6..3e6c1916 100644
--- a/components/prefs/pref_service_unittest.cc
+++ b/components/prefs/pref_service_unittest.cc
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "base/bind_helpers.h"
 #include "base/stl_util.h"
 #include "base/time/time.h"
 #include "base/values.h"
diff --git a/components/search_engines/util.cc b/components/search_engines/util.cc
index 324409b..db4770b 100644
--- a/components/search_engines/util.cc
+++ b/components/search_engines/util.cc
@@ -55,77 +55,100 @@
     const SearchTermsData& search_terms_data,
     std::set<std::string>* removed_keyword_guids) {
   DCHECK(template_urls);
+  TemplateURLService::OwnedTemplateURLVector checked_urls;
 
   // For convenience construct an ID->TemplateURL* map from |prepopulated_urls|.
   std::map<int, TemplateURLData*> prepopulated_url_map;
   for (const auto& url : prepopulated_urls)
     prepopulated_url_map[url->prepopulate_id] = url.get();
 
-  // Separate |template_urls| into prepopulated and non-prepopulated groups.
-  std::multimap<int, std::unique_ptr<TemplateURL>> unchecked_urls;
-  TemplateURLService::OwnedTemplateURLVector checked_urls;
+  constexpr size_t invalid_index = std::numeric_limits<size_t>::max();
+  // A helper structure for deduplicating elements with the same prepopulate_id.
+  struct DuplicationData {
+    DuplicationData() : index_representative(invalid_index) {}
+
+    // The index into checked_urls at which the best representative is stored.
+    size_t index_representative;
+
+    // Proper duplicates for consideration during selection phase.  This
+    // does not include the representative stored in checked_urls.
+    TemplateURLService::OwnedTemplateURLVector duplicates;
+  };
+  // Map from prepopulate_id to data for deduplication and selection.
+  std::unordered_map<int, DuplicationData> duplication_map;
+
+  const auto has_default_search_keyword = [&](const auto& turl) {
+    return default_search_provider &&
+           (default_search_provider->prepopulate_id() ==
+            turl->prepopulate_id()) &&
+           default_search_provider->HasSameKeywordAs(turl->data(),
+                                                     search_terms_data);
+  };
+
+  // Deduplication phase: move elements into new vector, preserving order while
+  // gathering duplicates into separate container for selection.
   for (auto& turl : *template_urls) {
-    int prepopulate_id = turl->prepopulate_id();
-    if (prepopulate_id)
-      unchecked_urls.insert(std::make_pair(prepopulate_id, std::move(turl)));
-    else
+    const int prepopulate_id = turl->prepopulate_id();
+    if (prepopulate_id) {
+      auto& duplication_data = duplication_map[prepopulate_id];
+      if (duplication_data.index_representative == invalid_index) {
+        // This is the first found.
+        duplication_data.index_representative = checked_urls.size();
+        checked_urls.push_back(std::move(turl));
+      } else {
+        // This is a duplicate.
+        duplication_data.duplicates.push_back(std::move(turl));
+      }
+    } else {
       checked_urls.push_back(std::move(turl));
+    }
   }
 
-  // For each group of prepopulated URLs with one ID, find the best URL to use
-  // and add it to the (initially all non-prepopulated) URLs we've already OKed.
-  // Delete the others from the service and from memory.
-  while (!unchecked_urls.empty()) {
-    // Find the best URL.
-    int prepopulate_id = unchecked_urls.begin()->first;
-    auto prepopulated_url = prepopulated_url_map.find(prepopulate_id);
-    auto end = unchecked_urls.upper_bound(prepopulate_id);
-    auto best = unchecked_urls.begin();
-    bool matched_keyword = false;
-    for (auto i = unchecked_urls.begin(); i != end; ++i) {
-      // If the user-selected DSE is a prepopulated engine its properties will
-      // either come from the prepopulation origin or from the user preferences
-      // file (see DefaultSearchManager). Those properties will end up
-      // overwriting whatever we load now anyway. If we are eliminating
-      // duplicates, then, we err on the side of keeping the thing that looks
-      // more like the value we will end up with in the end.
-      if (default_search_provider &&
-          (default_search_provider->prepopulate_id() ==
-              i->second->prepopulate_id()) &&
-          default_search_provider->HasSameKeywordAs(i->second->data(),
-                                                    search_terms_data)) {
-        best = i;
-        break;
-      }
+  // Selection and cleanup phase: swap out elements if necessary to ensure new
+  // vector contains only the best representative for each prepopulate_id.
+  // Then delete the remaining duplicates.
+  for (auto& id_data : duplication_map) {
+    const auto prepopulated_url = prepopulated_url_map.find(id_data.first);
+    const auto has_prepopulated_keyword = [&](const auto& turl) {
+      return (prepopulated_url != prepopulated_url_map.end()) &&
+             turl->HasSameKeywordAs(*prepopulated_url->second,
+                                    search_terms_data);
+    };
 
-      // Otherwise, a URL is best if it matches the prepopulated data's keyword;
-      // if none match, just fall back to using the one with the lowest ID.
-      if (matched_keyword)
-        continue;
-      if ((prepopulated_url != prepopulated_url_map.end()) &&
-          i->second->HasSameKeywordAs(*prepopulated_url->second,
-                                      search_terms_data)) {
-        best = i;
-        matched_keyword = true;
-      } else if (i->second->id() < best->second->id()) {
-        best = i;
+    // If the user-selected DSE is a prepopulated engine its properties will
+    // either come from the prepopulation origin or from the user preferences
+    // file (see DefaultSearchManager). Those properties will end up
+    // overwriting whatever we load now anyway. If we are eliminating
+    // duplicates, then, we err on the side of keeping the thing that looks
+    // more like the value we will end up with in the end.
+    // Otherwise, a URL is best if it matches the prepopulated data's keyword;
+    // if none match, just fall back to using the one with the lowest ID.
+    auto& best = checked_urls[id_data.second.index_representative];
+    if (!has_default_search_keyword(best)) {
+      bool matched_keyword = has_prepopulated_keyword(best);
+      for (auto& duplicate : id_data.second.duplicates) {
+        if (has_default_search_keyword(duplicate)) {
+          best.swap(duplicate);
+          break;
+        } else if (matched_keyword) {
+          continue;
+        } else if (has_prepopulated_keyword(duplicate)) {
+          best.swap(duplicate);
+          matched_keyword = true;
+        } else if (duplicate->id() < best->id()) {
+          best.swap(duplicate);
+        }
       }
     }
 
-    // Add the best URL to the checked group and delete the rest.
-    checked_urls.push_back(std::move(best->second));
-    for (auto i = unchecked_urls.begin(); i != end; ++i) {
-      if (i == best)
-        continue;
+    // Clean up what's left.
+    for (const auto& duplicate : id_data.second.duplicates) {
       if (service) {
-        service->RemoveKeyword(i->second->id());
+        service->RemoveKeyword(duplicate->id());
         if (removed_keyword_guids)
-          removed_keyword_guids->insert(i->second->sync_guid());
+          removed_keyword_guids->insert(duplicate->sync_guid());
       }
     }
-
-    // Done with this group.
-    unchecked_urls.erase(unchecked_urls.begin(), end);
   }
 
   // Return the checked URLs.
diff --git a/components/search_engines/util.h b/components/search_engines/util.h
index 39034e5..d3790c9 100644
--- a/components/search_engines/util.h
+++ b/components/search_engines/util.h
@@ -127,6 +127,9 @@
 // Sync GUID of each item removed from the DB will be added to it. This is a
 // helper used by GetSearchProvidersUsingKeywordResult(), but is declared here
 // so it's accessible by unittests.
+// The order of template_urls is preserved (except for duplicates) because it
+// affects order of presentation in settings web-ui.
+// See https://crbug.com/924268 for details.
 void RemoveDuplicatePrepopulateIDs(
     KeywordWebDataService* service,
     const std::vector<std::unique_ptr<TemplateURLData>>& prepopulated_urls,
diff --git a/components/services/heap_profiling/connection_manager.h b/components/services/heap_profiling/connection_manager.h
index 97dd66d..6c746b3 100644
--- a/components/services/heap_profiling/connection_manager.h
+++ b/components/services/heap_profiling/connection_manager.h
@@ -15,6 +15,7 @@
 #include "base/process/process_handle.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/thread.h"
+#include "base/timer/timer.h"
 #include "base/values.h"
 #include "build/build_config.h"
 #include "components/services/heap_profiling/allocation_event.h"
diff --git a/components/signin/core/browser/gaia_cookie_manager_service.cc b/components/signin/core/browser/gaia_cookie_manager_service.cc
index 7112b50..2ea9a77 100644
--- a/components/signin/core/browser/gaia_cookie_manager_service.cc
+++ b/components/signin/core/browser/gaia_cookie_manager_service.cc
@@ -487,7 +487,7 @@
       GaiaCookieRequest::CreateSetAccountsRequest(account_ids, source));
   if (requests_.size() == 1) {
     fetcher_retries_ = 0;
-    signin_client_->DelayNetworkCall(base::Bind(
+    signin_client_->DelayNetworkCall(base::BindOnce(
         &GaiaCookieManagerService::StartFetchingAccessTokensForMultilogin,
         base::Unretained(this)));
   }
@@ -528,8 +528,8 @@
       GaiaCookieRequest::CreateAddAccountRequest(account_id, source));
   if (requests_.size() == 1) {
     signin_client_->DelayNetworkCall(
-        base::Bind(&GaiaCookieManagerService::StartFetchingUbertoken,
-                   base::Unretained(this)));
+        base::BindOnce(&GaiaCookieManagerService::StartFetchingUbertoken,
+                       base::Unretained(this)));
   }
 }
 
@@ -575,8 +575,8 @@
     fetcher_retries_ = 0;
     requests_.push_back(GaiaCookieRequest::CreateListAccountsRequest());
     signin_client_->DelayNetworkCall(
-        base::Bind(&GaiaCookieManagerService::StartFetchingListAccounts,
-                   base::Unretained(this)));
+        base::BindOnce(&GaiaCookieManagerService::StartFetchingListAccounts,
+                       base::Unretained(this)));
   } else if (std::find_if(requests_.begin(), requests_.end(),
                           [](const GaiaCookieRequest& request) {
                             return request.request_type() == LIST_ACCOUNTS;
@@ -637,7 +637,7 @@
     requests_.push_back(GaiaCookieRequest::CreateLogOutRequest(source));
     if (requests_.size() == 1) {
       fetcher_retries_ = 0;
-      signin_client_->DelayNetworkCall(base::Bind(
+      signin_client_->DelayNetworkCall(base::BindOnce(
           &GaiaCookieManagerService::StartGaiaLogOut, base::Unretained(this)));
     }
   }
@@ -687,8 +687,8 @@
     requests_.push_back(GaiaCookieRequest::CreateListAccountsRequest());
     fetcher_retries_ = 0;
     signin_client_->DelayNetworkCall(
-        base::Bind(&GaiaCookieManagerService::StartFetchingListAccounts,
-                   base::Unretained(this)));
+        base::BindOnce(&GaiaCookieManagerService::StartFetchingListAccounts,
+                       base::Unretained(this)));
   }
 }
 
@@ -742,8 +742,8 @@
   }
 
   signin_client_->DelayNetworkCall(
-      base::Bind(&GaiaCookieManagerService::StartFetchingMergeSession,
-                 base::Unretained(this)));
+      base::BindOnce(&GaiaCookieManagerService::StartFetchingMergeSession,
+                     base::Unretained(this)));
 }
 
 void GaiaCookieManagerService::OnTokenFetched(const std::string& account_id,
@@ -753,8 +753,8 @@
     fetcher_retries_ = 0;
     token_requests_.clear();
     signin_client_->DelayNetworkCall(
-        base::Bind(&GaiaCookieManagerService::SetAccountsInCookieWithTokens,
-                   base::Unretained(this)));
+        base::BindOnce(&GaiaCookieManagerService::SetAccountsInCookieWithTokens,
+                       base::Unretained(this)));
   }
 }
 
@@ -784,9 +784,9 @@
         FROM_HERE, fetcher_backoff_.GetTimeUntilRelease(),
         base::BindOnce(
             &SigninClient::DelayNetworkCall, base::Unretained(signin_client_),
-            base::Bind(&GaiaCookieManagerService::
-                           StartFetchingAccessTokenForMultilogin,
-                       base::Unretained(this), request->GetAccountId())));
+            base::BindOnce(&GaiaCookieManagerService::
+                               StartFetchingAccessTokenForMultilogin,
+                           base::Unretained(this), request->GetAccountId())));
     return;
   }
   RecordGetAccessTokenFinished(error);
@@ -824,8 +824,8 @@
         FROM_HERE, fetcher_backoff_.GetTimeUntilRelease(),
         base::BindOnce(
             &SigninClient::DelayNetworkCall, base::Unretained(signin_client_),
-            base::Bind(&GaiaCookieManagerService::StartFetchingMergeSession,
-                       base::Unretained(this))));
+            base::BindOnce(&GaiaCookieManagerService::StartFetchingMergeSession,
+                           base::Unretained(this))));
     return;
   }
 
@@ -860,8 +860,9 @@
         FROM_HERE, fetcher_backoff_.GetTimeUntilRelease(),
         base::BindOnce(
             &SigninClient::DelayNetworkCall, base::Unretained(signin_client_),
-            base::Bind(&GaiaCookieManagerService::SetAccountsInCookieWithTokens,
-                       base::Unretained(this))));
+            base::BindOnce(
+                &GaiaCookieManagerService::SetAccountsInCookieWithTokens,
+                base::Unretained(this))));
     return;
   }
   // If Gaia responded with status: "INVALID_TOKENS", we have to mark tokens as
@@ -939,8 +940,8 @@
         FROM_HERE, fetcher_backoff_.GetTimeUntilRelease(),
         base::BindOnce(
             &SigninClient::DelayNetworkCall, base::Unretained(signin_client_),
-            base::Bind(&GaiaCookieManagerService::StartFetchingListAccounts,
-                       base::Unretained(this))));
+            base::BindOnce(&GaiaCookieManagerService::StartFetchingListAccounts,
+                           base::Unretained(this))));
     return;
   }
 
@@ -1142,27 +1143,27 @@
       case GaiaCookieRequestType::ADD_ACCOUNT:
         DCHECK_EQ(1u, requests_.front().account_ids().size());
         signin_client_->DelayNetworkCall(
-            base::Bind(&GaiaCookieManagerService::StartFetchingUbertoken,
-                       base::Unretained(this)));
+            base::BindOnce(&GaiaCookieManagerService::StartFetchingUbertoken,
+                           base::Unretained(this)));
         break;
       case GaiaCookieRequestType::SET_ACCOUNTS:
         DCHECK(!requests_.front().account_ids().empty());
-        signin_client_->DelayNetworkCall(base::Bind(
+        signin_client_->DelayNetworkCall(base::BindOnce(
             &GaiaCookieManagerService::StartFetchingAccessTokensForMultilogin,
             base::Unretained(this)));
         break;
       case GaiaCookieRequestType::LOG_OUT:
         DCHECK(requests_.front().account_ids().empty());
         signin_client_->DelayNetworkCall(
-            base::Bind(&GaiaCookieManagerService::StartGaiaLogOut,
-                       base::Unretained(this)));
+            base::BindOnce(&GaiaCookieManagerService::StartGaiaLogOut,
+                           base::Unretained(this)));
         break;
       case GaiaCookieRequestType::LIST_ACCOUNTS:
         DCHECK(requests_.front().account_ids().empty());
         uber_token_fetcher_.reset();
         signin_client_->DelayNetworkCall(
-            base::Bind(&GaiaCookieManagerService::StartFetchingListAccounts,
-                       base::Unretained(this)));
+            base::BindOnce(&GaiaCookieManagerService::StartFetchingListAccounts,
+                           base::Unretained(this)));
         break;
     }
   }
diff --git a/components/signin/core/browser/signin_client.h b/components/signin/core/browser/signin_client.h
index 6b43910..8aaa8c2 100644
--- a/components/signin/core/browser/signin_client.h
+++ b/components/signin/core/browser/signin_client.h
@@ -92,7 +92,7 @@
       content_settings::Observer* observer) = 0;
 
   // Execute |callback| if and when there is a network connection.
-  virtual void DelayNetworkCall(const base::Closure& callback) = 0;
+  virtual void DelayNetworkCall(base::OnceClosure callback) = 0;
 
   // Creates a new platform-specific GaiaAuthFetcher.
   virtual std::unique_ptr<GaiaAuthFetcher> CreateGaiaAuthFetcher(
diff --git a/components/signin/core/browser/test_signin_client.cc b/components/signin/core/browser/test_signin_client.cc
index c137b2f..889365f9 100644
--- a/components/signin/core/browser/test_signin_client.cc
+++ b/components/signin/core/browser/test_signin_client.cc
@@ -124,11 +124,11 @@
     content_settings::Observer* observer) {
 }
 
-void TestSigninClient::DelayNetworkCall(const base::Closure& callback) {
+void TestSigninClient::DelayNetworkCall(base::OnceClosure callback) {
   if (network_calls_delayed_) {
-    delayed_network_calls_.push_back(callback);
+    delayed_network_calls_.push_back(std::move(callback));
   } else {
-    callback.Run();
+    std::move(callback).Run();
   }
 }
 
diff --git a/components/signin/core/browser/test_signin_client.h b/components/signin/core/browser/test_signin_client.h
index d401d8540..3b0e39f4 100644
--- a/components/signin/core/browser/test_signin_client.h
+++ b/components/signin/core/browser/test_signin_client.h
@@ -84,7 +84,7 @@
       content_settings::Observer* observer) override;
   void RemoveContentSettingsObserver(
       content_settings::Observer* observer) override;
-  void DelayNetworkCall(const base::Closure& callback) override;
+  void DelayNetworkCall(base::OnceClosure callback) override;
   std::unique_ptr<GaiaAuthFetcher> CreateGaiaAuthFetcher(
       GaiaAuthConsumer* consumer,
       gaia::GaiaSource source,
diff --git a/components/signin/ios/browser/wait_for_network_callback_helper.cc b/components/signin/ios/browser/wait_for_network_callback_helper.cc
index fcec9a5f..f1f4637 100644
--- a/components/signin/ios/browser/wait_for_network_callback_helper.cc
+++ b/components/signin/ios/browser/wait_for_network_callback_helper.cc
@@ -4,6 +4,8 @@
 
 #include "components/signin/ios/browser/wait_for_network_callback_helper.h"
 
+#include <utility>
+
 WaitForNetworkCallbackHelper::WaitForNetworkCallbackHelper() {
   net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
 }
@@ -17,17 +19,16 @@
   if (net::NetworkChangeNotifier::IsOffline())
     return;
 
-  for (const base::Closure& callback : delayed_callbacks_)
-    callback.Run();
+  for (base::OnceClosure& callback : delayed_callbacks_)
+    std::move(callback).Run();
 
   delayed_callbacks_.clear();
 }
 
-void WaitForNetworkCallbackHelper::HandleCallback(
-    const base::Closure& callback) {
+void WaitForNetworkCallbackHelper::HandleCallback(base::OnceClosure callback) {
   if (net::NetworkChangeNotifier::IsOffline()) {
-    delayed_callbacks_.push_back(callback);
+    delayed_callbacks_.push_back(std::move(callback));
   } else {
-    callback.Run();
+    std::move(callback).Run();
   }
 }
diff --git a/components/signin/ios/browser/wait_for_network_callback_helper.h b/components/signin/ios/browser/wait_for_network_callback_helper.h
index 6e77513..08d1fa1 100644
--- a/components/signin/ios/browser/wait_for_network_callback_helper.h
+++ b/components/signin/ios/browser/wait_for_network_callback_helper.h
@@ -25,10 +25,10 @@
 
   // If offline, saves the |callback| to be called later when online. Otherwise,
   // invokes immediately.
-  void HandleCallback(const base::Closure& callback);
+  void HandleCallback(base::OnceClosure callback);
 
  private:
-  std::list<base::Closure> delayed_callbacks_;
+  std::list<base::OnceClosure> delayed_callbacks_;
 
   DISALLOW_COPY_AND_ASSIGN(WaitForNetworkCallbackHelper);
 };
diff --git a/components/storage_monitor/storage_monitor_chromeos.cc b/components/storage_monitor/storage_monitor_chromeos.cc
index 38e4afb..9bcee56 100644
--- a/components/storage_monitor/storage_monitor_chromeos.cc
+++ b/components/storage_monitor/storage_monitor_chromeos.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/sequenced_task_runner.h"
diff --git a/components/storage_monitor/storage_monitor_linux.cc b/components/storage_monitor/storage_monitor_linux.cc
index 4a07af2..0ade339 100644
--- a/components/storage_monitor/storage_monitor_linux.cc
+++ b/components/storage_monitor/storage_monitor_linux.cc
@@ -18,6 +18,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/process/kill.h"
diff --git a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc
index f0e2ffb..60eb509 100644
--- a/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc
+++ b/components/subresource_filter/content/browser/activation_state_computing_navigation_throttle_unittest.cc
@@ -8,6 +8,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc
index b1c83a1..e147fec 100644
--- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc
+++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager_unittest.cc
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/message_loop/message_loop_current.h"
diff --git a/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle_unittest.cc b/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle_unittest.cc
index 3dd4c72..d9a5e92a 100644
--- a/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle_unittest.cc
+++ b/components/subresource_filter/content/browser/subframe_navigation_filtering_throttle_unittest.cc
@@ -8,6 +8,7 @@
 #include <sstream>
 #include <string>
 
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/message_loop/message_loop_current.h"
 #include "base/run_loop.h"
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
index ceaae5a..8828d086 100644
--- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
+++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_activation_throttle_unittest.cc
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/message_loop/message_loop_current.h"
 #include "base/metrics/field_trial.h"
 #include "base/run_loop.h"
diff --git a/components/sync/device_info/device_info_sync_bridge_unittest.cc b/components/sync/device_info/device_info_sync_bridge_unittest.cc
index 175d2f3c..79a3900 100644
--- a/components/sync/device_info/device_info_sync_bridge_unittest.cc
+++ b/components/sync/device_info/device_info_sync_bridge_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/scoped_task_environment.h"
+#include "base/timer/timer.h"
 #include "components/sync/base/time.h"
 #include "components/sync/device_info/local_device_info_provider_mock.h"
 #include "components/sync/model/data_batch.h"
diff --git a/components/sync/driver/model_association_manager.cc b/components/sync/driver/model_association_manager.cc
index b60ad619..f8101dd 100644
--- a/components/sync/driver/model_association_manager.cc
+++ b/components/sync/driver/model_association_manager.cc
@@ -13,6 +13,7 @@
 
 #include "base/barrier_closure.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/stl_util.h"
diff --git a/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
index 6bb9b2f4..45617bb 100644
--- a/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
+++ b/components/sync_bookmarks/bookmark_model_type_processor_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <string>
 
+#include "base/bind_helpers.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/mock_callback.h"
diff --git a/components/timers/alarm_timer_chromeos.cc b/components/timers/alarm_timer_chromeos.cc
index 94a9294..371eb670 100644
--- a/components/timers/alarm_timer_chromeos.cc
+++ b/components/timers/alarm_timer_chromeos.cc
@@ -15,14 +15,40 @@
 #include "base/debug/task_annotator.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
+#include "base/memory/ptr_util.h"
 #include "base/pending_task.h"
 #include "base/trace_event/trace_event.h"
 
 namespace timers {
 
-SimpleAlarmTimer::SimpleAlarmTimer()
-    : alarm_fd_(timerfd_create(CLOCK_REALTIME_ALARM, TFD_CLOEXEC)),
-      weak_factory_(this) {}
+// static
+std::unique_ptr<SimpleAlarmTimer> SimpleAlarmTimer::Create() {
+  return CreateInternal(CLOCK_REALTIME_ALARM);
+}
+
+// static
+std::unique_ptr<SimpleAlarmTimer> SimpleAlarmTimer::CreateForTesting() {
+  // For unittest, use CLOCK_REALTIME in order to run the tests without
+  // CAP_WAKE_ALARM.
+  return CreateInternal(CLOCK_REALTIME);
+}
+
+// static
+std::unique_ptr<SimpleAlarmTimer> SimpleAlarmTimer::CreateInternal(
+    int clockid) {
+  base::ScopedFD alarm_fd(timerfd_create(clockid, TFD_CLOEXEC));
+  if (!alarm_fd.is_valid()) {
+    PLOG(ERROR) << "Failed to create timer fd";
+    return nullptr;
+  }
+
+  // Note: std::make_unique<> cannot be used because the constructor is
+  // private.
+  return base::WrapUnique(new SimpleAlarmTimer(std::move(alarm_fd)));
+}
+
+SimpleAlarmTimer::SimpleAlarmTimer(base::ScopedFD alarm_fd)
+    : alarm_fd_(std::move(alarm_fd)), weak_factory_(this) {}
 
 SimpleAlarmTimer::~SimpleAlarmTimer() {
   DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
@@ -35,11 +61,6 @@
   if (!IsRunning())
     return;
 
-  if (!CanWakeFromSuspend()) {
-    base::RetainingOneShotTimer::Stop();
-    return;
-  }
-
   // Cancel any previous callbacks.
   weak_factory_.InvalidateWeakPtrs();
 
@@ -52,11 +73,6 @@
   DCHECK(origin_task_runner_->RunsTasksInCurrentSequence());
   DCHECK(!base::RetainingOneShotTimer::user_task().is_null());
 
-  if (!CanWakeFromSuspend()) {
-    base::RetainingOneShotTimer::Reset();
-    return;
-  }
-
   // Cancel any previous callbacks and stop watching |alarm_fd_|.
   weak_factory_.InvalidateWeakPtrs();
   alarm_fd_watcher_.reset();
@@ -81,7 +97,7 @@
   alarm_time.it_value.tv_nsec =
       (delay.InMicroseconds() % base::Time::kMicrosecondsPerSecond) *
       base::Time::kNanosecondsPerMicrosecond;
-  if (timerfd_settime(alarm_fd_, 0, &alarm_time, NULL) < 0)
+  if (timerfd_settime(alarm_fd_.get(), 0, &alarm_time, NULL) < 0)
     PLOG(ERROR) << "Error while setting alarm time.  Timer will not fire";
 
   // The timer is running.
@@ -98,7 +114,7 @@
     base::debug::TaskAnnotator().WillQueueTask("SimpleAlarmTimer::Reset",
                                                pending_task_.get());
     alarm_fd_watcher_ = base::FileDescriptorWatcher::WatchReadable(
-        alarm_fd_,
+        alarm_fd_.get(),
         base::BindRepeating(&SimpleAlarmTimer::OnAlarmFdReadableWithoutBlocking,
                             weak_factory_.GetWeakPtr()));
   }
@@ -110,7 +126,7 @@
 
   // Read from |alarm_fd_| to ack the event.
   char val[sizeof(uint64_t)];
-  if (!base::ReadFromFD(alarm_fd_, val, sizeof(uint64_t)))
+  if (!base::ReadFromFD(alarm_fd_.get(), val, sizeof(uint64_t)))
     PLOG(DFATAL) << "Unable to read from timer file descriptor.";
 
   OnTimerFired();
@@ -137,8 +153,4 @@
     Stop();
 }
 
-bool SimpleAlarmTimer::CanWakeFromSuspend() const {
-  return alarm_fd_ != -1;
-}
-
 }  // namespace timers
diff --git a/components/timers/alarm_timer_chromeos.h b/components/timers/alarm_timer_chromeos.h
index 1ff689e..e1301e9e 100644
--- a/components/timers/alarm_timer_chromeos.h
+++ b/components/timers/alarm_timer_chromeos.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "base/files/file_descriptor_watcher_posix.h"
+#include "base/files/scoped_file.h"
 #include "base/macros.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
@@ -24,8 +25,7 @@
 // suspended state. For example, this is useful for running tasks that are
 // needed for maintaining network connectivity, like sending heartbeat messages.
 // Currently, this feature is only available on Chrome OS systems running linux
-// version 3.11 or higher. On all other platforms, the SimpleAlarmTimer behaves
-// exactly the same way as a regular Timer.
+// version 3.11 or higher.
 //
 // A SimpleAlarmTimer instance can only be used from the sequence on which it
 // was instantiated. Start() and Stop() must be called from a thread that
@@ -36,7 +36,15 @@
 // times but not at a regular interval.
 class SimpleAlarmTimer : public base::RetainingOneShotTimer {
  public:
-  SimpleAlarmTimer();
+  // Creates the SimpleAlarmTimer instance, or returns null on failure, e.g.,
+  // on a platform without timerfd_* system calls support, or missing
+  // capability (CAP_WAKE_ALARM).
+  static std::unique_ptr<SimpleAlarmTimer> Create();
+
+  // Similar to Create(), but for unittests without capability.
+  // Specifically, uses CLOCK_REALTIME instead of CLOCK_REALTIME_ALARM.
+  static std::unique_ptr<SimpleAlarmTimer> CreateForTesting();
+
   ~SimpleAlarmTimer() override;
 
   // Timer overrides.
@@ -44,6 +52,11 @@
   void Reset() override;
 
  private:
+  // Shared implementation of Create and CreateForTesting.
+  static std::unique_ptr<SimpleAlarmTimer> CreateInternal(int clockid);
+
+  explicit SimpleAlarmTimer(base::ScopedFD alarm_fd);
+
   // Called when |alarm_fd_| is readable without blocking. Reads data from
   // |alarm_fd_| and calls OnTimerFired().
   void OnAlarmFdReadableWithoutBlocking();
@@ -51,14 +64,8 @@
   // Called when the timer fires. Runs the callback.
   void OnTimerFired();
 
-  // Tracks whether the timer has the ability to wake the system up from
-  // suspend. This is a runtime check because we won't know if the system
-  // supports being woken up from suspend until the constructor actually tries
-  // to set it up.
-  bool CanWakeFromSuspend() const;
-
   // Timer file descriptor.
-  const int alarm_fd_;
+  const base::ScopedFD alarm_fd_;
 
   // Watches |alarm_fd_|.
   std::unique_ptr<base::FileDescriptorWatcher::Controller> alarm_fd_watcher_;
diff --git a/components/timers/alarm_timer_unittest.cc b/components/timers/alarm_timer_unittest.cc
index 7863d77..166144e 100644
--- a/components/timers/alarm_timer_unittest.cc
+++ b/components/timers/alarm_timer_unittest.cc
@@ -24,7 +24,9 @@
 // regular Timer so it should pass the same tests as the Timer class.
 namespace timers {
 namespace {
-const base::TimeDelta kTenMilliseconds = base::TimeDelta::FromMilliseconds(10);
+
+constexpr base::TimeDelta kTenMilliseconds =
+    base::TimeDelta::FromMilliseconds(10);
 
 class AlarmTimerTester {
  public:
@@ -34,7 +36,7 @@
       : did_run_(did_run),
         quit_closure_(std::move(quit_closure)),
         delay_(delay),
-        timer_(new timers::SimpleAlarmTimer()) {}
+        timer_(SimpleAlarmTimer::CreateForTesting()) {}
   void Start() {
     timer_->Start(
         FROM_HERE, delay_,
@@ -51,7 +53,7 @@
   bool* did_run_;
   base::OnceClosure quit_closure_;
   const base::TimeDelta delay_;
-  std::unique_ptr<timers::SimpleAlarmTimer> timer_;
+  std::unique_ptr<SimpleAlarmTimer> timer_;
 
   DISALLOW_COPY_AND_ASSIGN(AlarmTimerTester);
 };
@@ -64,7 +66,7 @@
       : did_run_(did_run),
         quit_closure_(std::move(quit_closure)),
         delay_(delay),
-        timer_(new timers::SimpleAlarmTimer()) {}
+        timer_(SimpleAlarmTimer::CreateForTesting()) {}
   void Start() {
     timer_->Start(FROM_HERE, delay_,
                   base::BindRepeating(&SelfDeletingAlarmTimerTester::Run,
@@ -83,7 +85,7 @@
   bool* did_run_;
   base::OnceClosure quit_closure_;
   const base::TimeDelta delay_;
-  std::unique_ptr<timers::SimpleAlarmTimer> timer_;
+  std::unique_ptr<SimpleAlarmTimer> timer_;
 
   DISALLOW_COPY_AND_ASSIGN(SelfDeletingAlarmTimerTester);
 };
@@ -221,49 +223,47 @@
 }
 
 TEST(AlarmTimerTest, NonRepeatIsRunning) {
-  {
-    base::test::ScopedTaskEnvironment task_environment(
-        base::test::ScopedTaskEnvironment::MainThreadType::IO);
+  base::test::ScopedTaskEnvironment task_environment(
+      base::test::ScopedTaskEnvironment::MainThreadType::IO);
 
-    timers::SimpleAlarmTimer timer;
-    EXPECT_FALSE(timer.IsRunning());
-    timer.Start(FROM_HERE, base::TimeDelta::FromDays(1), base::DoNothing());
+  auto timer = SimpleAlarmTimer::CreateForTesting();
+  EXPECT_FALSE(timer->IsRunning());
+  timer->Start(FROM_HERE, base::TimeDelta::FromDays(1), base::DoNothing());
 
-    // Allow FileDescriptorWatcher to start watching the timer. Without this, a
-    // task posted by FileDescriptorWatcher::WatchReadable() is leaked.
-    base::RunLoop().RunUntilIdle();
+  // Allow FileDescriptorWatcher to start watching the timer. Without this, a
+  // task posted by FileDescriptorWatcher::WatchReadable() is leaked.
+  base::RunLoop().RunUntilIdle();
 
-    EXPECT_TRUE(timer.IsRunning());
-    timer.Stop();
-    EXPECT_FALSE(timer.IsRunning());
-    ASSERT_FALSE(timer.user_task().is_null());
-    timer.Reset();
-    base::RunLoop().RunUntilIdle();
-    EXPECT_TRUE(timer.IsRunning());
-  }
+  EXPECT_TRUE(timer->IsRunning());
+  timer->Stop();
+  EXPECT_FALSE(timer->IsRunning());
+  ASSERT_FALSE(timer->user_task().is_null());
+  timer->Reset();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(timer->IsRunning());
 }
 
 TEST(AlarmTimerTest, RetainNonRepeatIsRunning) {
   base::test::ScopedTaskEnvironment task_environment(
       base::test::ScopedTaskEnvironment::MainThreadType::IO);
 
-  timers::SimpleAlarmTimer timer;
-  EXPECT_FALSE(timer.IsRunning());
-  timer.Start(FROM_HERE, base::TimeDelta::FromDays(1), base::DoNothing());
+  auto timer = SimpleAlarmTimer::CreateForTesting();
+  EXPECT_FALSE(timer->IsRunning());
+  timer->Start(FROM_HERE, base::TimeDelta::FromDays(1), base::DoNothing());
 
   // Allow FileDescriptorWatcher to start watching the timer. Without this, a
   // task posted by FileDescriptorWatcher::WatchReadable() is leaked.
   base::RunLoop().RunUntilIdle();
 
-  EXPECT_TRUE(timer.IsRunning());
-  timer.Reset();
+  EXPECT_TRUE(timer->IsRunning());
+  timer->Reset();
   base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(timer.IsRunning());
-  timer.Stop();
-  EXPECT_FALSE(timer.IsRunning());
-  timer.Reset();
+  EXPECT_TRUE(timer->IsRunning());
+  timer->Stop();
+  EXPECT_FALSE(timer->IsRunning());
+  timer->Reset();
   base::RunLoop().RunUntilIdle();
-  EXPECT_TRUE(timer.IsRunning());
+  EXPECT_TRUE(timer->IsRunning());
 }
 
 namespace {
@@ -293,16 +293,16 @@
   base::test::ScopedTaskEnvironment task_environment(
       base::test::ScopedTaskEnvironment::MainThreadType::IO);
 
-  timers::SimpleAlarmTimer timer;
-  timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(10),
-              base::BindRepeating(&SetCallbackHappened1,
-                                  base::DoNothing().Repeatedly()));
-  timer.Stop();
+  auto timer = SimpleAlarmTimer::CreateForTesting();
+  timer->Start(FROM_HERE, base::TimeDelta::FromMilliseconds(10),
+               base::BindRepeating(&SetCallbackHappened1,
+                                   base::DoNothing().Repeatedly()));
+  timer->Stop();
 
   base::RunLoop run_loop;
-  timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(40),
-              base::BindRepeating(&SetCallbackHappened2,
-                                  run_loop.QuitWhenIdleClosure()));
+  timer->Start(FROM_HERE, base::TimeDelta::FromMilliseconds(40),
+               base::BindRepeating(&SetCallbackHappened2,
+                                   run_loop.QuitWhenIdleClosure()));
   run_loop.Run();
 
   EXPECT_FALSE(g_callback_happened1);
@@ -315,12 +315,12 @@
       base::test::ScopedTaskEnvironment::MainThreadType::IO);
 
   base::RunLoop run_loop;
-  timers::SimpleAlarmTimer timer;
-  timer.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(10),
-              base::BindRepeating(&SetCallbackHappened1,
-                                  run_loop.QuitWhenIdleClosure()));
-  timer.Reset();
-  ASSERT_FALSE(timer.user_task().is_null());
+  auto timer = SimpleAlarmTimer::CreateForTesting();
+  timer->Start(FROM_HERE, base::TimeDelta::FromMilliseconds(10),
+               base::BindRepeating(&SetCallbackHappened1,
+                                   run_loop.QuitWhenIdleClosure()));
+  timer->Reset();
+  ASSERT_FALSE(timer->user_task().is_null());
   run_loop.Run();
   EXPECT_TRUE(g_callback_happened1);
 }
@@ -334,16 +334,13 @@
   base::RunLoop run_loop;
 
   // Will be deleted by the callback.
-  timers::SimpleAlarmTimer* timer = new timers::SimpleAlarmTimer;
-
-  timer->Start(
+  auto timer = SimpleAlarmTimer::CreateForTesting();
+  auto* timer_ptr = timer.get();
+  timer_ptr->Start(
       FROM_HERE, base::TimeDelta::FromMilliseconds(10),
-      base::BindRepeating(
-          [](timers::SimpleAlarmTimer* timer, base::RunLoop* run_loop) {
-            delete timer;
-            run_loop->Quit();
-          },
-          timer, &run_loop));
+      base::BindRepeating([](std::unique_ptr<SimpleAlarmTimer> timer,
+                             base::RunLoop* run_loop) { run_loop->Quit(); },
+                          base::Passed(std::move(timer)), &run_loop));
   run_loop.Run();
 }
 
@@ -355,16 +352,13 @@
   base::RunLoop run_loop;
 
   // Will be deleted by the callback.
-  timers::SimpleAlarmTimer* timer = new timers::SimpleAlarmTimer;
-
-  timer->Start(
+  auto timer = SimpleAlarmTimer::CreateForTesting();
+  auto* timer_ptr = timer.get();
+  timer_ptr->Start(
       FROM_HERE, base::TimeDelta(),
-      base::BindRepeating(
-          [](timers::SimpleAlarmTimer* timer, base::RunLoop* run_loop) {
-            delete timer;
-            run_loop->Quit();
-          },
-          timer, &run_loop));
+      base::BindRepeating([](std::unique_ptr<SimpleAlarmTimer> timer,
+                             base::RunLoop* run_loop) { run_loop->Quit(); },
+                          base::Passed(std::move(timer)), &run_loop));
   run_loop.Run();
 }
 
diff --git a/components/tracing/common/native_stack_sampler_android.cc b/components/tracing/common/native_stack_sampler_android.cc
index 15d5b41..fe45d16b 100644
--- a/components/tracing/common/native_stack_sampler_android.cc
+++ b/components/tracing/common/native_stack_sampler_android.cc
@@ -25,7 +25,8 @@
   if (!unwinder_.is_initialized()) {
     // May block on disk access. This function is executed on the profiler
     // thread, so this will only block profiling execution.
-    TRACE_EVENT0("cpu_profiler", "StackUnwinderAndroid::Initialize");
+    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cpu_profiler"),
+                 "StackUnwinderAndroid::Initialize");
     unwinder_.Initialize();
   }
   const void* pcs[kMaxFrameDepth];
diff --git a/components/variations/variations_request_scheduler_mobile.h b/components/variations/variations_request_scheduler_mobile.h
index 5b46f1f..838373f 100644
--- a/components/variations/variations_request_scheduler_mobile.h
+++ b/components/variations/variations_request_scheduler_mobile.h
@@ -8,6 +8,7 @@
 #include "base/bind.h"
 #include "base/gtest_prod_util.h"
 #include "base/macros.h"
+#include "base/timer/timer.h"
 #include "components/variations/variations_request_scheduler.h"
 
 class PrefService;
diff --git a/components/viz/common/display/renderer_settings.h b/components/viz/common/display/renderer_settings.h
index 2b8cd27..e34c338 100644
--- a/components/viz/common/display/renderer_settings.h
+++ b/components/viz/common/display/renderer_settings.h
@@ -29,7 +29,6 @@
   bool release_overlay_resources_after_gpu_query = false;
   bool tint_gl_composited_content = false;
   bool show_overdraw_feedback = false;
-  bool enable_draw_occlusion = false;
   bool use_skia_renderer = false;
   bool allow_overlays = true;
   bool dont_round_texture_sizes_for_pixel_tests = false;
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc
index f0c077d..184c013 100644
--- a/components/viz/common/features.cc
+++ b/components/viz/common/features.cc
@@ -10,11 +10,6 @@
 
 namespace features {
 
-// Enables running draw occlusion algorithm to remove Draw Quads that are not
-// shown on screen from CompositorFrame.
-const base::Feature kEnableDrawOcclusion{"DrawOcclusion",
-                                         base::FEATURE_ENABLED_BY_DEFAULT};
-
 #if defined(USE_AURA) || defined(OS_MACOSX)
 const base::Feature kEnableSurfaceSynchronization{
     "SurfaceSynchronization", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -82,10 +77,6 @@
          base::FeatureList::IsEnabled(kEnableVizHitTestSurfaceLayer);
 }
 
-bool IsDrawOcclusionEnabled() {
-  return base::FeatureList::IsEnabled(kEnableDrawOcclusion);
-}
-
 bool IsUsingSkiaRenderer() {
   return base::FeatureList::IsEnabled(kUseSkiaRenderer);
 }
diff --git a/components/viz/common/features.h b/components/viz/common/features.h
index 2d76f38..69d8285 100644
--- a/components/viz/common/features.h
+++ b/components/viz/common/features.h
@@ -11,7 +11,6 @@
 
 namespace features {
 
-VIZ_COMMON_EXPORT extern const base::Feature kEnableDrawOcclusion;
 VIZ_COMMON_EXPORT extern const base::Feature kEnableSurfaceSynchronization;
 VIZ_COMMON_EXPORT extern const base::Feature kEnableVizHitTestDrawQuad;
 VIZ_COMMON_EXPORT extern const base::Feature kEnableVizHitTestSurfaceLayer;
@@ -19,7 +18,6 @@
 VIZ_COMMON_EXPORT extern const base::Feature kRecordSkPicture;
 VIZ_COMMON_EXPORT extern const base::Feature kVizDisplayCompositor;
 
-VIZ_COMMON_EXPORT bool IsDrawOcclusionEnabled();
 VIZ_COMMON_EXPORT bool IsSurfaceSynchronizationEnabled();
 VIZ_COMMON_EXPORT bool IsVizHitTestingDebugEnabled();
 VIZ_COMMON_EXPORT bool IsVizHitTestingDrawQuadEnabled();
diff --git a/components/viz/common/gl_helper.cc b/components/viz/common/gl_helper.cc
index 29bfd28..cbd11c7 100644
--- a/components/viz/common/gl_helper.cc
+++ b/components/viz/common/gl_helper.cc
@@ -11,6 +11,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/containers/queue.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
diff --git a/components/viz/host/host_frame_sink_manager.cc b/components/viz/host/host_frame_sink_manager.cc
index 741a2b4..abb030f 100644
--- a/components/viz/host/host_frame_sink_manager.cc
+++ b/components/viz/host/host_frame_sink_manager.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
diff --git a/components/viz/host/host_gpu_memory_buffer_manager_unittest.cc b/components/viz/host/host_gpu_memory_buffer_manager_unittest.cc
index 836c167..d91186c 100644
--- a/components/viz/host/host_gpu_memory_buffer_manager_unittest.cc
+++ b/components/viz/host/host_gpu_memory_buffer_manager_unittest.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/threading/thread.h"
 #include "build/build_config.h"
diff --git a/components/viz/host/renderer_settings_creation.cc b/components/viz/host/renderer_settings_creation.cc
index e63d2019..a235580 100644
--- a/components/viz/host/renderer_settings_creation.cc
+++ b/components/viz/host/renderer_settings_creation.cc
@@ -57,7 +57,6 @@
       command_line->HasSwitch(switches::kTintGlCompositedContent);
   renderer_settings.show_overdraw_feedback =
       command_line->HasSwitch(switches::kShowOverdrawFeedback);
-  renderer_settings.enable_draw_occlusion = features::IsDrawOcclusionEnabled();
   renderer_settings.allow_antialiasing =
       !command_line->HasSwitch(switches::kDisableCompositedAntialiasing);
   renderer_settings.use_skia_renderer = features::IsUsingSkiaRenderer();
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc
index 236611f..f9f821b3 100644
--- a/components/viz/service/display/display.cc
+++ b/components/viz/service/display/display.cc
@@ -427,13 +427,11 @@
     TRACE_EVENT_ASYNC_STEP_INTO0("viz,benchmark",
                                  "Graphics.Pipeline.DrawAndSwap",
                                  swapped_trace_id_, "Draw");
-    if (settings_.enable_draw_occlusion) {
-      base::ElapsedTimer draw_occlusion_timer;
-      RemoveOverdrawQuads(&frame);
-      UMA_HISTOGRAM_COUNTS_1000(
-          "Compositing.Display.Draw.Occlusion.Calculation.Time",
-          draw_occlusion_timer.Elapsed().InMicroseconds());
-    }
+    base::ElapsedTimer draw_occlusion_timer;
+    RemoveOverdrawQuads(&frame);
+    UMA_HISTOGRAM_COUNTS_1000(
+        "Compositing.Display.Draw.Occlusion.Calculation.Time",
+        draw_occlusion_timer.Elapsed().InMicroseconds());
 
     bool disable_image_filtering =
         frame.metadata.is_resourceless_software_draw_with_scroll_or_animation;
diff --git a/components/viz/service/display/gl_renderer_unittest.cc b/components/viz/service/display/gl_renderer_unittest.cc
index fa37f784..91d4ca5f4 100644
--- a/components/viz/service/display/gl_renderer_unittest.cc
+++ b/components/viz/service/display/gl_renderer_unittest.cc
@@ -13,6 +13,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/scoped_feature_list.h"
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc
index 162d473..cf994fa9 100644
--- a/components/viz/service/display/renderer_pixeltest.cc
+++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -8,6 +8,7 @@
 #include <tuple>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/memory/aligned_memory.h"
 #include "build/build_config.h"
 #include "cc/base/math_util.h"
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc b/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc
index 26d77db..d2345bc 100644
--- a/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc
+++ b/components/viz/service/display_embedder/skia_output_surface_impl_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "base/base64.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/test/scoped_feature_list.h"
 #include "cc/test/fake_output_surface_client.h"
 #include "cc/test/pixel_test_utils.h"
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_impl.cc b/components/viz/service/frame_sinks/compositor_frame_sink_impl.cc
index 5bc1e9b..c9d6235 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_impl.cc
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_impl.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
 
 namespace viz {
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
index c962e3d..b91a3e3b 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.cc
@@ -592,6 +592,7 @@
     last_frame_time_ = args.frame_time;
     client_->OnBeginFrame(copy_args, std::move(presentation_feedbacks_));
     presentation_feedbacks_.clear();
+    UpdateNeedsBeginFramesInternal();
   }
 }
 
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support.h b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
index 88a7d5f3..26af0a7b 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support.h
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support.h
@@ -181,6 +181,7 @@
   }
 
  private:
+  friend class CompositorFrameSinkSupportTest;
   friend class DisplayTest;
   friend class FrameSinkManagerTest;
 
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
index 21c3e6ff..8e03bfb 100644
--- a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
+++ b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
@@ -62,6 +62,12 @@
   return token;
 }
 
+bool BeginFrameArgsAreEquivalent(const BeginFrameArgs& first,
+                                 const BeginFrameArgs& second) {
+  return first.source_id == second.source_id &&
+         first.sequence_number == second.sequence_number;
+}
+
 }  // namespace
 
 class MockFrameSinkManagerClient : public mojom::FrameSinkManagerClient {
@@ -207,6 +213,20 @@
     manager_.surface_manager()->ExpireOldTemporaryReferences();
   }
 
+  const BeginFrameArgs& GetLastUsedBeginFrameArgs(
+      const CompositorFrameSinkSupport* support) const {
+    return support->LastUsedBeginFrameArgs();
+  }
+
+  void SendPresentationFeedback(CompositorFrameSinkSupport* support,
+                                uint32_t frame_token) {
+    support->DidPresentCompositorFrame(
+        frame_token,
+        gfx::PresentationFeedback(base::TimeTicks::Now(),
+                                  base::TimeDelta::FromMilliseconds(16),
+                                  /*flags=*/0));
+  }
+
  protected:
   ServerSharedBitmapManager shared_bitmap_manager_;
   FrameSinkManagerImpl manager_;
@@ -965,6 +985,57 @@
   support_->SetNeedsBeginFrame(false);
 }
 
+// Validates that if a client asked to stop receiving begin-frames, then it
+// stops receiving begin-frames after receiving the presentation-feedback from
+// the last submitted frame.
+TEST_F(CompositorFrameSinkSupportTest,
+       NeedsBeginFrameResetAfterPresentationFeedback) {
+  // Request BeginFrames.
+  support_->SetNeedsBeginFrame(true);
+
+  // Issue a BeginFrame. Validate that the client receives the begin-frame.
+  BeginFrameArgs args =
+      CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 0, 1);
+  begin_frame_source_.TestOnBeginFrame(args);
+  BeginFrameArgs received_args = GetLastUsedBeginFrameArgs(support_.get());
+  EXPECT_TRUE(BeginFrameArgsAreEquivalent(args, received_args));
+  EXPECT_EQ(received_args.type, BeginFrameArgs::NORMAL);
+
+  // Client submits a compositor frame in response.
+  BeginFrameAck ack(args, true);
+  CompositorFrame frame = CompositorFrameBuilder()
+                              .AddDefaultRenderPass()
+                              .SetBeginFrameAck(ack)
+                              .Build();
+  auto token = frame.metadata.frame_token;
+  support_->SubmitCompositorFrame(local_surface_id_, std::move(frame));
+
+  // Client stops asking for begin-frames.
+  support_->SetNeedsBeginFrame(false);
+
+  // Issue a new BeginFrame. This time, the client should not receive it since
+  // it has stopped asking for begin-frames.
+  args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 1, 2);
+  begin_frame_source_.TestOnBeginFrame(args);
+  received_args = GetLastUsedBeginFrameArgs(support_.get());
+  EXPECT_FALSE(BeginFrameArgsAreEquivalent(args, received_args));
+
+  // The presentation-feedback from the last submitted frame arrives. This
+  // results in the client immediately receiving a MISSED begin-frame.
+  SendPresentationFeedback(support_.get(), token);
+  received_args = GetLastUsedBeginFrameArgs(support_.get());
+  EXPECT_TRUE(BeginFrameArgsAreEquivalent(args, received_args));
+  EXPECT_EQ(received_args.type, BeginFrameArgs::MISSED);
+
+  // Issue another begin-frame. This time, the client should not receive it
+  // anymore since it has stopped asking for begin-frames, and it has already
+  // received the last presentation-feedback.
+  args = CreateBeginFrameArgsForTesting(BEGINFRAME_FROM_HERE, 2, 3);
+  begin_frame_source_.TestOnBeginFrame(args);
+  received_args = GetLastUsedBeginFrameArgs(support_.get());
+  EXPECT_FALSE(BeginFrameArgsAreEquivalent(args, received_args));
+}
+
 TEST_F(CompositorFrameSinkSupportTest, FrameIndexCarriedOverToNewSurface) {
   LocalSurfaceId local_surface_id1(1, kArbitraryToken);
   LocalSurfaceId local_surface_id2(2, kArbitraryToken);
diff --git a/components/viz/service/gl/gpu_service_impl_unittest.cc b/components/viz/service/gl/gpu_service_impl_unittest.cc
index 3475096..399eaaa0 100644
--- a/components/viz/service/gl/gpu_service_impl_unittest.cc
+++ b/components/viz/service/gl/gpu_service_impl_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index 2ececf6..c4d780c 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -868,6 +868,8 @@
     "frame_host/interstitial_page_impl.h",
     "frame_host/interstitial_page_navigator_impl.cc",
     "frame_host/interstitial_page_navigator_impl.h",
+    "frame_host/ipc_utils.cc",
+    "frame_host/ipc_utils.h",
     "frame_host/keep_alive_handle_factory.cc",
     "frame_host/keep_alive_handle_factory.h",
     "frame_host/mixed_content_navigation_throttle.cc",
diff --git a/content/browser/appcache/README.md b/content/browser/appcache/README.md
new file mode 100644
index 0000000..dde134d3
--- /dev/null
+++ b/content/browser/appcache/README.md
@@ -0,0 +1,183 @@
+# AppCache
+
+AppCache is the well-known shorthand for `Application Cache`, the key mechanism
+in the
+[Offline Web applications specification](https://html.spec.whatwg.org/multipage/offline.html#offline).
+
+*** promo
+AppCache is deprecated and slated for removal from the Web Platform. Chrome's
+implementation is in maintenance mode. We're only tacking critical bugs and code
+health improvements that allow us to reason about bugs easier. Long-term efforts
+should be focused on Service Workers.
+***
+
+
+## Overview
+
+AppCache is aimed at SPAs (single-page Web applications).
+
+The application's HTML page (Document) points to a **manifest** in an `<html
+manifest=...>` attribute. The manifest lists all the sub-resources (style
+sheets, scripts, images, etc.) that the page needs to work offline. When a
+user navigates to the HTML page for the first time, the browser caches all
+the resources in the manifest. Future navigations use the cached resources,
+so the application still works even if the network is down.
+
+The simplified model above misses two critical pieces, which are responsible for
+the bulk of AppCache's complexity. The sections below can be skimmed on a first
+reading.
+
+### Updates (Why AppCache is Hard, Part 1)
+
+The ease of deploying updates is a key strength of Web applications. Browsers
+automatically (barring misconfigured HTTP caching) load the latest version of
+an application's resources when a user navigates to one of the application's
+pages.
+
+AppCache aims for comparable ease by automatically updating its locally cached
+copy of the manifest and its resources whenever a page is visited. This comes
+with some significant caveats.
+
+1. AppCache bails early in the update process if the manifest hasn't changed
+   (byte for byte). This behavior is intended to save network bandwidth.
+   The downside is that developers must change their manifest whenever any of
+   the sub-resources change.
+2. The manifest does not have any versioning information in it. So, when a
+   manifest changes, the browser must reload all the resources referenced by
+   it.
+3. The manifest is only checked for updates when a page is visited, to keep the
+   Web ephemeral. The update check is performed concurrently with page loading,
+   for performance reasons. If the manifest changed, all the resources used
+   by the page are served from the outdated cache. This is necessary, because by
+   the time the browser can detect a manifest update, the page has been
+   partially loaded using the (now known to be outdated) cached resources.
+   It's not reasonable to ask Web developers to support mixing resources from
+   different application versions.
+4. While the browser is downloading a page's cache (the manifest and its
+   resources), the user could navigate a different tab to the same page. The
+   second tab uses the result of the ongoing cache download, rather than
+   updating the cache on its own. This removes many race conditions from the
+   cache update process, at the cost of having the browser coordinate between
+   all instances of a page that uses AppCache.
+5. AppCache also supports application-driven updates. The support is aimed at
+   applications that may be left open in the same tab for a long time, like
+   e-mail and chat clients. This means browsers must support both
+   navigation-driven cache updates and application-driven updates.
+
+### Multi-Page Applications (Why AppCache is Hard, Part 2)
+
+AppCache supports multi-page applications by allowing multiple pages to share
+the same manifest, and therefore use the same cached resources.
+
+Manifest sharing is particularly complex when combined with implicit caching.
+An AppCache manifest is not required to list the HTML pages that refer to it
+via an `<html manifest>` attribute. (Listing the pages is however recommended.)
+This allowance introduces the following complexities.
+
+1. When a browser encounters an HTML page that refers to a manifest it hasn't
+   seen before, the browser creates an implicit resource entry for the HTML
+   page. The HTML page is cached together with the other resources listed in
+   the manifest, so it can be available for offline browsing.
+2. When a browser encounters an HTML page that refers to a manifest it has
+   already cached, the browser also creates an implicit resource entry for
+   the HTML page. The existing cache must be changed to include the new
+   implicit resource.
+3. When a manifest changes, the browser must update all the implicit resources
+   (HTML pages that refer to the manifest) as well as the resources explicitly
+   mentioned in the manifest. If any of the HTML pages using the manifest are
+   opened, they must be notified that a manifest update is available.
+4. When a browser encounters an HTML page that refers to a manifest whose
+   resources are still being downloaded, it needs to ensure that the page's
+   implicit resource eventually gets associated with the manifest. To avoid race
+   conditions, the browser must add the HTML page to a list of pages that need
+   updating. The manifest update logic must also process this list, after
+   downloading the resources already associated with the manifest.
+
+While the pages in multi-page applications can share a manifest, they are not
+required to do so. In other words, an application's pages can use different
+manifests. However, each manifest conceptually spawns its own resource cache,
+which is updated independently from other manifests' caches. So, different pages
+from the same application may use different versions of the same sub-resource,
+if they are associated with different manifests.
+
+A particularly complex case is loading an HTML page that is associated with a
+cached manifest, discovering that the manifest has changed and requires an
+update, updating the HTML page, and obtaining a new version of the HTML page
+that refers to a different manifest. In this case, loading a single page ends up
+downloading two manifests and all the resources associated with them.
+
+
+## Data Model
+
+AppCache uses the following terms.
+
+* A **manifest** is a list of URLs to resources. The listed resources should be
+  be sufficient for the page to be used while offline.
+* An **application cache** contains one version of a manifest and all the
+  resources associated with it. This includes the resources explicitly listed in
+  the manifest, and the implicitly cached HTML pages that refer to the manifest.
+* An **application cache group** is a collection of all the application caches
+  that have the same manifest.
+* A **cache host** is a name used to refer to a Document (HTML page) when the
+  emphasis is on the connection between the page, the manifest it references,
+  and the application cache / cache group associated with that manifest.
+
+### Application Cache
+
+An application cache has the following components.
+
+1. **Entries** that identify resources to be cached.
+2. **Namespaces** that direct the loading of sub-resource URLs for a page
+   associated with the cache.
+3. **Flags** that influence the cache's behavior.
+
+Entries have the following types.
+
+* **manifest** - the AppCache manifest; the absolute URL of this entry is used
+  to identify the group that this application cache belongs to
+* **master** - documents (HTML pages) whose `<html manifest>` attribute points
+  to the cache's manifest; these are added to an application cache as they are
+  discovered during user navigations
+* **explicit** - listed in the manifest's explicit section (`CACHE:`)
+* **fallback** - listed in the manifest's fallback section (`FALLBACK:`)
+
+Explicit and fallback entries can also be marked as **foreign**. A foreign entry
+indicates a document whose `<html manifest>` attribute does not point to this
+cache's manifest.
+
+Namespaces are conceptually patterns that match resource URLs. AppCache supports
+the following namespaces.
+
+* **fallback** - URLs matching the namespace are first fetched from the network.
+  If the fetch fails, a cached fallback resource is used instead. Fallback
+  namespaces are listed in the `FALLBACK:` manifest section.
+* **online safelist** -- URLs matching the namespace are always fetched from the
+  network. Online safelist namespaces are listed in the `NETWORK:` manifest
+  section.
+
+*** promo
+Chrome's AppCache implementation also supports **intercept** namespaces, listed
+in the `CHROMIUM-INTERCEPT:` manifest section. URLs matching an intercept
+namespace are loaded as if the fetch request encountered an HTTP redirect.
+***
+
+The AppCache specification supports specifying namespaces as URL prefixes. Given
+a list of namespaces in an application cache, a resource URL matches the longest
+namespace that is a prefix of the URL.
+
+*** promo
+Our AppCache implementation also supports specifying namespaces as regular
+expressions that match URLs. This extension is invoked by adding the `isPattern`
+keyword after the namespace in the manifest.
+***
+
+An application cache has the following flags.
+
+* **completeness** - the application cache is *complete* when all the resources
+  in the manifest have been fetched and cached, and *incomplete* otherwise
+* **online safelist wildcard** - *blocking* by default, which means that all
+  resources not listed in the manifest are considered unavailable; can be set
+  to *open* by adding an `*` entry in the `NETWORK:` manifest section, causing
+  all unlisted resources to be fetched from the network
+* **cache mode** - not supported by Chrome, which does not implement the
+  `SETTINGS:` manifest section
diff --git a/content/browser/appcache/appcache_fuzzer.cc b/content/browser/appcache/appcache_fuzzer.cc
index c7bd343..2e902e5 100644
--- a/content/browser/appcache/appcache_fuzzer.cc
+++ b/content/browser/appcache/appcache_fuzzer.cc
@@ -4,6 +4,7 @@
 
 #include "base/at_exit.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/i18n/icu_util.h"
 #include "base/no_destructor.h"
 #include "base/task/post_task.h"
diff --git a/content/browser/appcache/appcache_request_handler.cc b/content/browser/appcache/appcache_request_handler.cc
index c1dbf56..b5c8cff 100644
--- a/content/browser/appcache/appcache_request_handler.cc
+++ b/content/browser/appcache/appcache_request_handler.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "content/browser/appcache/appcache.h"
 #include "content/browser/appcache/appcache_backend_impl.h"
diff --git a/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc b/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
index 3793328..ea14e02992 100644
--- a/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
+++ b/content/browser/background_fetch/background_fetch_delegate_proxy_unittest.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/memory/weak_ptr.h"
 #include "base/run_loop.h"
 #include "base/task/post_task.h"
diff --git a/content/browser/background_fetch/background_fetch_job_controller.cc b/content/browser/background_fetch/background_fetch_job_controller.cc
index eb62fd5a..d3176d7a 100644
--- a/content/browser/background_fetch/background_fetch_job_controller.cc
+++ b/content/browser/background_fetch/background_fetch_job_controller.cc
@@ -13,6 +13,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "content/public/browser/browser_thread.h"
 
 namespace content {
diff --git a/content/browser/background_fetch/background_fetch_job_controller_unittest.cc b/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
index e99566c..9e944d8 100644
--- a/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
+++ b/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
@@ -13,6 +13,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/guid.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
diff --git a/content/browser/background_fetch/background_fetch_scheduler.cc b/content/browser/background_fetch/background_fetch_scheduler.cc
index 94dc386..23b75d4 100644
--- a/content/browser/background_fetch/background_fetch_scheduler.cc
+++ b/content/browser/background_fetch/background_fetch_scheduler.cc
@@ -5,6 +5,7 @@
 #include "content/browser/background_fetch/background_fetch_scheduler.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/guid.h"
 #include "base/stl_util.h"
 #include "content/browser/background_fetch/background_fetch_data_manager.h"
diff --git a/content/browser/background_fetch/background_fetch_scheduler_unittest.cc b/content/browser/background_fetch/background_fetch_scheduler_unittest.cc
index f7549a12..eefbd0f 100644
--- a/content/browser/background_fetch/background_fetch_scheduler_unittest.cc
+++ b/content/browser/background_fetch/background_fetch_scheduler_unittest.cc
@@ -7,6 +7,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/guid.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/task/post_task.h"
diff --git a/content/browser/background_fetch/background_fetch_service_impl.cc b/content/browser/background_fetch/background_fetch_service_impl.cc
index c03ee465..718f19c 100644
--- a/content/browser/background_fetch/background_fetch_service_impl.cc
+++ b/content/browser/background_fetch/background_fetch_service_impl.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/guid.h"
 #include "base/optional.h"
 #include "base/task/post_task.h"
diff --git a/content/browser/background_fetch/storage/create_metadata_task.cc b/content/browser/background_fetch/storage/create_metadata_task.cc
index b6bc42d..fdf6fae2 100644
--- a/content/browser/background_fetch/storage/create_metadata_task.cc
+++ b/content/browser/background_fetch/storage/create_metadata_task.cc
@@ -10,6 +10,7 @@
 
 #include "base/barrier_closure.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
 #include "content/browser/background_fetch/background_fetch_data_manager.h"
diff --git a/content/browser/background_fetch/storage/get_initialization_data_task.cc b/content/browser/background_fetch/storage/get_initialization_data_task.cc
index f690b850..7360a21 100644
--- a/content/browser/background_fetch/storage/get_initialization_data_task.cc
+++ b/content/browser/background_fetch/storage/get_initialization_data_task.cc
@@ -6,6 +6,7 @@
 
 #include "base/barrier_closure.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/post_task.h"
 #include "base/task/task_traits.h"
diff --git a/content/browser/background_sync/background_sync_manager.cc b/content/browser/background_sync/background_sync_manager.cc
index 1d56e5f6..e9df600 100644
--- a/content/browser/background_sync/background_sync_manager.cc
+++ b/content/browser/background_sync/background_sync_manager.cc
@@ -8,6 +8,7 @@
 
 #include "base/barrier_closure.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/location.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_macros.h"
diff --git a/content/browser/bad_message.h b/content/browser/bad_message.h
index 5dcf68ec..03b16dde 100644
--- a/content/browser/bad_message.h
+++ b/content/browser/bad_message.h
@@ -195,9 +195,9 @@
   RWH_INVALID_FRAME_TOKEN = 167,
   RWH_BAD_FRAME_SINK_REQUEST = 168,
   RWH_SURFACE_INVARIANTS_VIOLATION = 169,
-  RFH_ILLEGAL_UPLOAD_PARAMS = 170,
+  ILLEGAL_UPLOAD_PARAMS = 170,
   RFH_BASE_URL_FOR_DATA_URL_SPECIFIED = 171,
-  RFPH_ILLEGAL_UPLOAD_PARAMS = 172,
+  OBSOLETE_RFPH_ILLEGAL_UPLOAD_PARAMS = 172,
   OBSOLETE_SWDH_PROVIDER_CREATED_ILLEGAL_TYPE = 173,
   OBSOLETE_SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_NOT_WINDOW = 174,
   OBSOLETE_SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_SERVICE_WORKER = 175,
@@ -226,10 +226,10 @@
   SYNC_COMPOSITOR_NO_FUTURE_FRAME = 198,
   SYNC_COMPOSITOR_NO_BEGIN_FRAME = 199,
   WEBUI_BAD_HOST_ACCESS = 200,
-  RFMF_BLOB_URL_TOKEN_FOR_NON_BLOB_URL = 201,
+  OBSOLETE_RFMF_BLOB_URL_TOKEN_FOR_NON_BLOB_URL = 201,
   PERMISSION_SERVICE_BAD_PERMISSION_DESCRIPTOR = 202,
-  RFH_BLOB_URL_TOKEN_FOR_NON_BLOB_URL = 203,
-  RFPH_BLOB_URL_TOKEN_FOR_NON_BLOB_URL = 204,
+  BLOB_URL_TOKEN_FOR_NON_BLOB_URL = 203,
+  OBSOLETE_RFPH_BLOB_URL_TOKEN_FOR_NON_BLOB_URL = 204,
   RFH_ERROR_PROCESS_NON_ERROR_COMMIT = 205,
   RFH_ERROR_PROCESS_NON_UNIQUE_ORIGIN_COMMIT = 206,
   RFH_CANNOT_RENDER_FALLBACK_CONTENT = 207,
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.cc b/content/browser/bluetooth/web_bluetooth_service_impl.cc
index ff1479dc..8e975e9 100644
--- a/content/browser/bluetooth/web_bluetooth_service_impl.cc
+++ b/content/browser/bluetooth/web_bluetooth_service_impl.cc
@@ -13,6 +13,7 @@
 #include <algorithm>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/content/browser/cache_storage/cache_storage.cc b/content/browser/cache_storage/cache_storage.cc
index 37d70be..6a9ff84 100644
--- a/content/browser/cache_storage/cache_storage.cc
+++ b/content/browser/cache_storage/cache_storage.cc
@@ -12,6 +12,7 @@
 
 #include "base/barrier_closure.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_util.h"
 #include "base/files/memory_mapped_file.h"
 #include "base/guid.h"
diff --git a/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc b/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc
index ebd4909..ddea197 100644
--- a/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc
+++ b/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
diff --git a/content/browser/cache_storage/cache_storage_manager.cc b/content/browser/cache_storage/cache_storage_manager.cc
index df00535..16dba58 100644
--- a/content/browser/cache_storage/cache_storage_manager.cc
+++ b/content/browser/cache_storage/cache_storage_manager.cc
@@ -13,6 +13,7 @@
 
 #include "base/barrier_closure.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/containers/id_map.h"
 #include "base/files/file_enumerator.h"
 #include "base/files/file_util.h"
diff --git a/content/browser/child_process_security_policy_unittest.cc b/content/browser/child_process_security_policy_unittest.cc
index 5dd2f94..fbba808b 100644
--- a/content/browser/child_process_security_policy_unittest.cc
+++ b/content/browser/child_process_security_policy_unittest.cc
@@ -5,6 +5,7 @@
 #include <set>
 #include <string>
 
+#include "base/bind_helpers.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/synchronization/waitable_event.h"
diff --git a/content/browser/cookie_store/cookie_store_manager.cc b/content/browser/cookie_store/cookie_store_manager.cc
index 8a2db200..9dc3ac79 100644
--- a/content/browser/cookie_store/cookie_store_manager.cc
+++ b/content/browser/cookie_store/cookie_store_manager.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/optional.h"
 #include "content/browser/cookie_store/cookie_change_subscriptions.pb.h"
 #include "content/browser/service_worker/embedded_worker_status.h"
diff --git a/content/browser/cross_site_transfer_browsertest.cc b/content/browser/cross_site_transfer_browsertest.cc
index 2bb9bfdd..62bcf49 100644
--- a/content/browser/cross_site_transfer_browsertest.cc
+++ b/content/browser/cross_site_transfer_browsertest.cc
@@ -418,7 +418,7 @@
       "setTimeout(\n"
       "  function() { document.getElementById('file-form').submit(); },\n"
       "  0);"));
-  EXPECT_EQ(bad_message::RFPH_ILLEGAL_UPLOAD_PARAMS, kill_waiter.Wait());
+  EXPECT_EQ(bad_message::ILLEGAL_UPLOAD_PARAMS, kill_waiter.Wait());
 
   // The target frame should still be at the original location - the malicious
   // navigation should have been stopped.
diff --git a/content/browser/devtools/devtools_renderer_channel.cc b/content/browser/devtools/devtools_renderer_channel.cc
index 66cb507..6c627aad 100644
--- a/content/browser/devtools/devtools_renderer_channel.cc
+++ b/content/browser/devtools/devtools_renderer_channel.cc
@@ -5,6 +5,7 @@
 #include "content/browser/devtools/devtools_renderer_channel.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "content/browser/devtools/devtools_agent_host_impl.h"
 #include "content/browser/devtools/devtools_session.h"
 #include "content/browser/devtools/protocol/devtools_domain_handler.h"
diff --git a/content/browser/devtools/protocol/service_worker_handler.cc b/content/browser/devtools/protocol/service_worker_handler.cc
index 37edf0b..19b4801 100644
--- a/content/browser/devtools/protocol/service_worker_handler.cc
+++ b/content/browser/devtools/protocol/service_worker_handler.cc
@@ -5,6 +5,7 @@
 #include "content/browser/devtools/protocol/service_worker_handler.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/containers/flat_set.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/content/browser/devtools/protocol/target_handler.cc b/content/browser/devtools/protocol/target_handler.cc
index 098c426..509a7c9 100644
--- a/content/browser/devtools/protocol/target_handler.cc
+++ b/content/browser/devtools/protocol/target_handler.cc
@@ -6,6 +6,7 @@
 
 #include "base/base64.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/containers/flat_map.h"
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
diff --git a/content/browser/devtools/service_worker_devtools_agent_host.cc b/content/browser/devtools/service_worker_devtools_agent_host.cc
index f2c9811..5759e8da 100644
--- a/content/browser/devtools/service_worker_devtools_agent_host.cc
+++ b/content/browser/devtools/service_worker_devtools_agent_host.cc
@@ -5,6 +5,7 @@
 #include "content/browser/devtools/service_worker_devtools_agent_host.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/strings/stringprintf.h"
 #include "base/task/post_task.h"
 #include "content/browser/devtools/devtools_renderer_channel.h"
diff --git a/content/browser/dom_storage/local_storage_context_mojo_unittest.cc b/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
index 638ce4c..fee17f17 100644
--- a/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
+++ b/content/browser/dom_storage/local_storage_context_mojo_unittest.cc
@@ -5,6 +5,7 @@
 #include "content/browser/dom_storage/local_storage_context_mojo.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_enumerator.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
diff --git a/content/browser/dom_storage/session_storage_context_mojo.cc b/content/browser/dom_storage/session_storage_context_mojo.cc
index 443d902..5439973 100644
--- a/content/browser/dom_storage/session_storage_context_mojo.cc
+++ b/content/browser/dom_storage/session_storage_context_mojo.cc
@@ -11,6 +11,7 @@
 
 #include "base/barrier_closure.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/debug/stack_trace.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_functions.h"
diff --git a/content/browser/dom_storage/session_storage_context_mojo_unittest.cc b/content/browser/dom_storage/session_storage_context_mojo_unittest.cc
index 26a67849..fa416ff 100644
--- a/content/browser/dom_storage/session_storage_context_mojo_unittest.cc
+++ b/content/browser/dom_storage/session_storage_context_mojo_unittest.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_enumerator.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
diff --git a/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc b/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc
index cde6cd633..c04d727 100644
--- a/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc
+++ b/content/browser/dom_storage/session_storage_namespace_impl_mojo_unittest.cc
@@ -5,6 +5,7 @@
 #include "content/browser/dom_storage/session_storage_namespace_impl_mojo.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/guid.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
diff --git a/content/browser/dom_storage/storage_area_impl_unittest.cc b/content/browser/dom_storage/storage_area_impl_unittest.cc
index b858637c..b1e8918 100644
--- a/content/browser/dom_storage/storage_area_impl_unittest.cc
+++ b/content/browser/dom_storage/storage_area_impl_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/atomic_ref_count.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
diff --git a/content/browser/frame_host/frame_tree_node.h b/content/browser/frame_host/frame_tree_node.h
index 5c4ad3e5..23b67f8 100644
--- a/content/browser/frame_host/frame_tree_node.h
+++ b/content/browser/frame_host/frame_tree_node.h
@@ -408,6 +408,10 @@
   // will never be reused - this saves memory.
   void PruneChildFrameNavigationEntries(NavigationEntryImpl* entry);
 
+  blink::FrameOwnerElementType frame_owner_element_type() const {
+    return replication_state_.frame_owner_element_type;
+  }
+
  private:
   FRIEND_TEST_ALL_PREFIXES(SitePerProcessFeaturePolicyBrowserTest,
                            ContainerPolicyDynamic);
diff --git a/content/browser/frame_host/ipc_utils.cc b/content/browser/frame_host/ipc_utils.cc
new file mode 100644
index 0000000..1530444
--- /dev/null
+++ b/content/browser/frame_host/ipc_utils.cc
@@ -0,0 +1,114 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/frame_host/ipc_utils.h"
+
+#include <utility>
+
+#include "content/browser/bad_message.h"
+#include "content/browser/blob_storage/chrome_blob_storage_context.h"
+#include "content/browser/child_process_security_policy_impl.h"
+#include "content/common/frame.mojom.h"
+#include "content/common/frame_messages.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/site_instance.h"
+#include "content/public/common/child_process_host.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+
+namespace content {
+
+namespace {
+
+bool VerifyBlobToken(
+    int process_id,
+    mojo::MessagePipeHandle received_token,
+    const GURL& received_url,
+    blink::mojom::BlobURLTokenPtrInfo* out_blob_url_token_info) {
+  DCHECK_NE(ChildProcessHost::kInvalidUniqueID, process_id);
+  DCHECK(out_blob_url_token_info);
+
+  mojo::ScopedMessagePipeHandle blob_url_token_handle(
+      std::move(received_token));
+  blink::mojom::BlobURLTokenPtrInfo blob_url_token_info(
+      std::move(blob_url_token_handle), blink::mojom::BlobURLToken::Version_);
+  if (blob_url_token_info) {
+    if (!received_url.SchemeIsBlob()) {
+      bad_message::ReceivedBadMessage(
+          process_id, bad_message::BLOB_URL_TOKEN_FOR_NON_BLOB_URL);
+      return false;
+    }
+  }
+
+  *out_blob_url_token_info = std::move(blob_url_token_info);
+  return true;
+}
+
+}  // namespace
+
+bool VerifyDownloadUrlParams(
+    int process_id,
+    const FrameHostMsg_DownloadUrl_Params& params,
+    blink::mojom::BlobURLTokenPtrInfo* out_blob_url_token_info) {
+  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO) ||
+         BrowserThread::CurrentlyOn(BrowserThread::UI));
+  DCHECK_NE(ChildProcessHost::kInvalidUniqueID, process_id);
+  DCHECK(out_blob_url_token_info);
+
+  // Verify |params.blob_url_token| and populate |out_blob_url_token_info|.
+  if (!VerifyBlobToken(process_id, params.blob_url_token, params.url,
+                       out_blob_url_token_info)) {
+    return false;
+  }
+
+  // TODO(lukasza): Verify |params.initiator_origin|.
+
+  return true;
+}
+
+bool VerifyOpenURLParams(SiteInstance* site_instance,
+                         const FrameHostMsg_OpenURL_Params& params,
+                         GURL* out_validated_url,
+                         scoped_refptr<network::SharedURLLoaderFactory>*
+                             out_blob_url_loader_factory) {
+  DCHECK_CURRENTLY_ON(BrowserThread::UI);
+  DCHECK(site_instance);
+  DCHECK(out_validated_url);
+  DCHECK(out_blob_url_loader_factory);
+  RenderProcessHost* process = site_instance->GetProcess();
+  int process_id = process->GetID();
+
+  // Verify |params.url| and populate |out_validated_url|.
+  *out_validated_url = params.url;
+  process->FilterURL(false, out_validated_url);
+
+  // Verify |params.blob_url_token| and populate |out_blob_url_loader_factory|.
+  blink::mojom::BlobURLTokenPtrInfo blob_url_token_info;
+  if (!VerifyBlobToken(process_id, params.blob_url_token, params.url,
+                       &blob_url_token_info)) {
+    return false;
+  }
+  if (blob_url_token_info) {
+    blink::mojom::BlobURLTokenPtr blob_url_token(
+        std::move(blob_url_token_info));
+    *out_blob_url_loader_factory =
+        ChromeBlobStorageContext::URLLoaderFactoryForToken(
+            process->GetBrowserContext(), std::move(blob_url_token));
+  }
+
+  // Verify |params.resource_request_body|.
+  auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+  if (!policy->CanReadRequestBody(site_instance,
+                                  params.resource_request_body)) {
+    bad_message::ReceivedBadMessage(process,
+                                    bad_message::ILLEGAL_UPLOAD_PARAMS);
+    return false;
+  }
+
+  // TODO(lukasza): Verify |params.initiator_origin|.
+
+  return true;
+}
+
+}  // namespace content
diff --git a/content/browser/frame_host/ipc_utils.h b/content/browser/frame_host/ipc_utils.h
new file mode 100644
index 0000000..5263264
--- /dev/null
+++ b/content/browser/frame_host/ipc_utils.h
@@ -0,0 +1,53 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_FRAME_HOST_IPC_UTILS_H_
+#define CONTENT_BROWSER_FRAME_HOST_IPC_UTILS_H_
+
+#include "base/memory/ref_counted.h"
+#include "content/common/frame.mojom.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
+#include "url/gurl.h"
+
+struct FrameHostMsg_DownloadUrl_Params;
+struct FrameHostMsg_OpenURL_Params;
+
+namespace content {
+
+class SiteInstance;
+
+// Verifies that |params| are valid and can be accessed by |process_id|.
+//
+// Returns true if the |params| are valid.  As a side-effect of the verification
+// |out_blob_url_token_info| will be populated.
+//
+// Terminates the renderer with the given |process_id| and returns false if the
+// |params| are invalid.
+//
+// This function may be called on either the IO thread or the UI thread
+// (but not on other threads).
+bool VerifyDownloadUrlParams(
+    int process_id,
+    const FrameHostMsg_DownloadUrl_Params& params,
+    blink::mojom::BlobURLTokenPtrInfo* out_blob_url_token_info);
+
+// Verifies that |params| are valid and can be accessed by the renderer process
+// associated with |site_instance|.
+//
+// Returns true if the |params| are valid.  As a side-effect of the verification
+// |out_validated_url| and |out_blob_url_loader_factory| will be populated.
+//
+// Terminates the renderer the process associated with |site_instance| and
+// returns false if the |params| are invalid.
+//
+// This function has to be called on the UI thread.
+bool VerifyOpenURLParams(SiteInstance* site_instance,
+                         const FrameHostMsg_OpenURL_Params& params,
+                         GURL* out_validated_url,
+                         scoped_refptr<network::SharedURLLoaderFactory>*
+                             out_blob_url_loader_factory);
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_FRAME_HOST_IPC_UTILS_H_
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc
index 5ce90476..2cace5e 100644
--- a/content/browser/frame_host/navigation_request.cc
+++ b/content/browser/frame_host/navigation_request.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/debug/alias.h"
 #include "base/debug/dump_without_crashing.h"
 #include "base/metrics/field_trial_params.h"
@@ -221,9 +222,26 @@
         site_value = "same-site";
       }
     }
-    headers->SetHeaderIfMissing("Sec-Fetch-Dest", frame_tree_node->IsMainFrame()
-                                                      ? "document"
-                                                      : "nested-document");
+    std::string destination;
+    switch (frame_tree_node->frame_owner_element_type()) {
+      case blink::FrameOwnerElementType::kNone:
+        destination = "document";
+        break;
+      case blink::FrameOwnerElementType::kObject:
+        destination = "object";
+        break;
+      case blink::FrameOwnerElementType::kEmbed:
+        destination = "embed";
+        break;
+      case blink::FrameOwnerElementType::kIframe:
+      case blink::FrameOwnerElementType::kFrame:
+      case blink::FrameOwnerElementType::kPortal:
+        // TODO(mkwst): "Portal"'s destination isn't actually defined at the
+        // moment. Let's assume it'll be similar to a frame until we decide
+        // otherwise.
+        destination = "nested-document";
+    }
+    headers->SetHeaderIfMissing("Sec-Fetch-Dest", destination.c_str());
     headers->SetHeaderIfMissing("Sec-Fetch-Site", site_value.c_str());
     headers->SetHeaderIfMissing("Sec-Fetch-User",
                                 has_user_gesture ? "?T" : "?F");
diff --git a/content/browser/frame_host/render_frame_host_delegate.h b/content/browser/frame_host/render_frame_host_delegate.h
index b8e7958..37c8d6e9 100644
--- a/content/browser/frame_host/render_frame_host_delegate.h
+++ b/content/browser/frame_host/render_frame_host_delegate.h
@@ -176,6 +176,14 @@
   virtual void DidReceiveFirstUserActivation(
       RenderFrameHost* render_frame_host) {}
 
+  // The display style of the frame has changed.
+  virtual void DidChangeDisplayState(RenderFrameHost* render_frame_host,
+                                     bool is_display_none) {}
+
+  // The size of the frame has changed.
+  virtual void FrameSizeChanged(RenderFrameHost* render_frame_host,
+                                const gfx::Size& frame_size) {}
+
   // The onload handler in the frame has completed. Only called for the top-
   // level frame.
   virtual void DocumentOnLoadCompleted(RenderFrameHost* render_frame_host) {}
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index a6c9e15b2..0a92476 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -47,6 +47,7 @@
 #include "content/browser/frame_host/frame_tree.h"
 #include "content/browser/frame_host/frame_tree_node.h"
 #include "content/browser/frame_host/input/input_injector_impl.h"
+#include "content/browser/frame_host/ipc_utils.h"
 #include "content/browser/frame_host/keep_alive_handle_factory.h"
 #include "content/browser/frame_host/navigation_entry_impl.h"
 #include "content/browser/frame_host/navigation_handle_impl.h"
@@ -169,7 +170,6 @@
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
 #include "services/network/public/mojom/network_service.mojom.h"
-#include "services/resource_coordinator/public/cpp/resource_coordinator_features.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "storage/browser/blob/blob_storage_context.h"
@@ -324,13 +324,6 @@
 };
 #endif  // BUILDFLAG(ENABLE_MEDIA_REMOTING)
 
-void CreateFrameResourceCoordinator(
-    RenderFrameHostImpl* render_frame_host,
-    resource_coordinator::mojom::FrameCoordinationUnitRequest request) {
-  render_frame_host->GetFrameResourceCoordinator()->AddBinding(
-      std::move(request));
-}
-
 using FrameNotifyCallback =
     base::RepeatingCallback<void(ResourceDispatcherHostImpl*,
                                  const GlobalFrameRoutingId&)>;
@@ -445,14 +438,6 @@
   return url::Origin::Create(target_url);
 }
 
-service_manager::Connector* MaybeGetFrameResourceCoordinator() {
-  auto* connection = ServiceManagerConnection::GetForProcess();
-  if (!connection)
-    return nullptr;
-
-  return connection->GetConnector();
-}
-
 std::unique_ptr<blink::URLLoaderFactoryBundleInfo> CloneFactoryBundle(
     scoped_refptr<blink::URLLoaderFactoryBundle> bundle) {
   return base::WrapUnique(static_cast<blink::URLLoaderFactoryBundleInfo*>(
@@ -777,7 +762,6 @@
       accessibility_reset_count_(0),
       browser_plugin_embedder_ax_tree_id_(ui::AXTreeIDUnknown()),
       no_create_browser_accessibility_manager_for_testing_(false),
-      frame_resource_coordinator_(MaybeGetFrameResourceCoordinator()),
       web_ui_type_(WebUI::kNoWebUI),
       pending_web_ui_type_(WebUI::kNoWebUI),
       should_reuse_web_ui_(false),
@@ -879,15 +863,6 @@
                                    : frame_tree_node_->opener();
   if (frame_owner)
     CSPContext::SetSelf(frame_owner->current_origin());
-
-  // Hook up the Resource Coordinator edges to the associated process and
-  // parent frame, if any.
-  frame_resource_coordinator_.SetProcess(
-      *GetProcess()->GetProcessResourceCoordinator());
-  if (parent_) {
-    parent_->GetFrameResourceCoordinator()->AddChildFrame(
-        frame_resource_coordinator_);
-  }
 }
 
 RenderFrameHostImpl::~RenderFrameHostImpl() {
@@ -1104,6 +1079,14 @@
   return frame_tree_node_->frame_name();
 }
 
+bool RenderFrameHostImpl::IsFrameDisplayNone() {
+  return frame_tree_node()->frame_owner_properties().is_display_none;
+}
+
+const base::Optional<gfx::Size>& RenderFrameHostImpl::GetFrameSize() {
+  return frame_size_;
+}
+
 bool RenderFrameHostImpl::IsCrossProcessSubframe() {
   if (!parent_)
     return false;
@@ -2079,29 +2062,11 @@
 }
 
 void RenderFrameHostImpl::OnOpenURL(const FrameHostMsg_OpenURL_Params& params) {
-  GURL validated_url(params.url);
-  GetProcess()->FilterURL(false, &validated_url);
-
-  mojo::ScopedMessagePipeHandle blob_url_token_handle(params.blob_url_token);
-  blink::mojom::BlobURLTokenPtr blob_url_token(
-      blink::mojom::BlobURLTokenPtrInfo(std::move(blob_url_token_handle),
-                                        blink::mojom::BlobURLToken::Version_));
+  // Verify and unpack IPC payload.
+  GURL validated_url;
   scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
-  if (blob_url_token) {
-    if (!params.url.SchemeIsBlob()) {
-      bad_message::ReceivedBadMessage(
-          GetProcess(), bad_message::RFH_BLOB_URL_TOKEN_FOR_NON_BLOB_URL);
-      return;
-    }
-    blob_url_loader_factory =
-        ChromeBlobStorageContext::URLLoaderFactoryForToken(
-            GetSiteInstance()->GetBrowserContext(), std::move(blob_url_token));
-  }
-
-  if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanReadRequestBody(
-          GetSiteInstance(), params.resource_request_body)) {
-    bad_message::ReceivedBadMessage(GetProcess(),
-                                    bad_message::RFH_ILLEGAL_UPLOAD_PARAMS);
+  if (!VerifyOpenURLParams(GetSiteInstance(), params, &validated_url,
+                           &blob_url_loader_factory)) {
     return;
   }
 
@@ -3097,9 +3062,18 @@
   if (!child)
     return;
 
+  bool has_display_none_property_changed =
+      properties.is_display_none !=
+      child->frame_owner_properties().is_display_none;
+
   child->set_frame_owner_properties(properties);
 
   child->render_manager()->OnDidUpdateFrameOwnerProperties(properties);
+  if (has_display_none_property_changed) {
+    delegate_->DidChangeDisplayState(
+        child->current_frame_host(),
+        properties.is_display_none /* is_display_none */);
+  }
 }
 
 void RenderFrameHostImpl::OnUpdateTitle(
@@ -3126,6 +3100,7 @@
 
 void RenderFrameHostImpl::FrameSizeChanged(const gfx::Size& frame_size) {
   frame_size_ = frame_size;
+  delegate_->FrameSizeChanged(this, frame_size);
 }
 
 void RenderFrameHostImpl::FullscreenStateChanged(bool is_fullscreen) {
@@ -3918,7 +3893,7 @@
   if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanReadRequestBody(
           GetSiteInstance(), validated_params.post_data)) {
     bad_message::ReceivedBadMessage(GetProcess(),
-                                    bad_message::RFH_ILLEGAL_UPLOAD_PARAMS);
+                                    bad_message::ILLEGAL_UPLOAD_PARAMS);
     return;
   }
 
@@ -4076,9 +4051,6 @@
       base::BindRepeating(&RenderFrameHostImpl::CreateAudioOutputStreamFactory,
                           base::Unretained(this)));
 
-  registry_->AddInterface(
-      base::Bind(&CreateFrameResourceCoordinator, base::Unretained(this)));
-
   // BrowserMainLoop::GetInstance() may be null on unit tests.
   if (BrowserMainLoop::GetInstance()) {
     // BrowserMainLoop, which owns MediaStreamManager, is alive for the lifetime
@@ -5003,9 +4975,6 @@
   // Disconnect with ImageDownloader Mojo service in RenderFrame.
   mojo_image_downloader_.reset();
 
-  // Make sure the renderer cannot add new bindings.
-  frame_resource_coordinator_.reset();
-
   // The geolocation service and sensor provider proxy may attempt to cancel
   // permission requests so they must be reset before the routing_id mapping is
   // removed.
@@ -5133,11 +5102,6 @@
   return find_in_page_;
 }
 
-resource_coordinator::FrameResourceCoordinator*
-RenderFrameHostImpl::GetFrameResourceCoordinator() {
-  return &frame_resource_coordinator_;
-}
-
 void RenderFrameHostImpl::ResetLoadingState() {
   if (is_loading()) {
     // When pending deletion, just set the loading state to not loading.
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 27e1ecf..dfedd09 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -59,7 +59,6 @@
 #include "mojo/public/cpp/system/data_pipe.h"
 #include "net/http/http_response_headers.h"
 #include "services/device/public/mojom/wake_lock_context.mojom.h"
-#include "services/resource_coordinator/public/cpp/frame_resource_coordinator.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "services/service_manager/public/mojom/interface_provider.mojom.h"
 #include "services/viz/public/interfaces/hit_test/input_target_client.mojom.h"
@@ -211,6 +210,8 @@
   int GetFrameTreeNodeId() override;
   base::UnguessableToken GetDevToolsFrameToken() override;
   const std::string& GetFrameName() override;
+  bool IsFrameDisplayNone() override;
+  const base::Optional<gfx::Size>& GetFrameSize() override;
   bool IsCrossProcessSubframe() override;
   const GURL& GetLastCommittedURL() override;
   const url::Origin& GetLastCommittedOrigin() override;
@@ -706,9 +707,6 @@
   // Returns pointer to renderer side FindInPage associated with this frame.
   const blink::mojom::FindInPageAssociatedPtr& GetFindInPage();
 
-  resource_coordinator::FrameResourceCoordinator* GetFrameResourceCoordinator()
-      override;
-
   // Resets the loading state. Following this call, the RenderFrameHost will be
   // in a non-loading state.
   void ResetLoadingState();
@@ -1666,9 +1664,6 @@
   // Holder of Mojo connection with FindInPage service in Blink.
   blink::mojom::FindInPageAssociatedPtr find_in_page_;
 
-  // Holds the interface wrapper to the Global Resource Coordinator service.
-  resource_coordinator::FrameResourceCoordinator frame_resource_coordinator_;
-
   // Holds a NavigationRequest when it's about to commit, ie. after
   // OnCrossDocumentCommitProcessed has returned a positive answer for this
   // NavigationRequest but before receiving DidCommitProvisionalLoad. This
diff --git a/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
index fbc648de..e9768e0 100644
--- a/content/browser/frame_host/render_frame_host_manager_browsertest.cc
+++ b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -9,6 +9,7 @@
 #include <set>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/json/json_reader.h"
 #include "base/location.h"
diff --git a/content/browser/frame_host/render_frame_message_filter.cc b/content/browser/frame_host/render_frame_message_filter.cc
index 15cd7e5a..e17622d6 100644
--- a/content/browser/frame_host/render_frame_message_filter.cc
+++ b/content/browser/frame_host/render_frame_message_filter.cc
@@ -22,6 +22,7 @@
 #include "content/browser/bad_message.h"
 #include "content/browser/blob_storage/chrome_blob_storage_context.h"
 #include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/frame_host/ipc_utils.h"
 #include "content/browser/frame_host/render_frame_host_impl.h"
 #include "content/browser/gpu/gpu_data_manager_impl.h"
 #include "content/browser/renderer_host/render_widget_helper.h"
@@ -518,14 +519,9 @@
 
 void RenderFrameMessageFilter::OnDownloadUrl(
     const FrameHostMsg_DownloadUrl_Params& params) {
-  mojo::ScopedMessagePipeHandle blob_url_token_handle(params.blob_url_token);
-  blink::mojom::BlobURLTokenPtrInfo blob_url_token(
-      std::move(blob_url_token_handle), blink::mojom::BlobURLToken::Version_);
-  if (blob_url_token && !params.url.SchemeIsBlob()) {
-    bad_message::ReceivedBadMessage(
-        this, bad_message::RFMF_BLOB_URL_TOKEN_FOR_NON_BLOB_URL);
+  blink::mojom::BlobURLTokenPtrInfo blob_url_token;
+  if (!VerifyDownloadUrlParams(render_process_id_, params, &blob_url_token))
     return;
-  }
 
   DownloadUrl(params.render_view_id, params.render_frame_id, params.url,
               params.referrer, params.initiator_origin, params.suggested_name,
diff --git a/content/browser/frame_host/render_frame_proxy_host.cc b/content/browser/frame_host/render_frame_proxy_host.cc
index f075640d..e70b7e4 100644
--- a/content/browser/frame_host/render_frame_proxy_host.cc
+++ b/content/browser/frame_host/render_frame_proxy_host.cc
@@ -17,6 +17,7 @@
 #include "content/browser/frame_host/cross_process_frame_connector.h"
 #include "content/browser/frame_host/frame_tree.h"
 #include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/frame_host/ipc_utils.h"
 #include "content/browser/frame_host/navigator.h"
 #include "content/browser/frame_host/render_frame_host_delegate.h"
 #include "content/browser/renderer_host/render_view_host_impl.h"
@@ -283,23 +284,12 @@
 
 void RenderFrameProxyHost::OnOpenURL(
     const FrameHostMsg_OpenURL_Params& params) {
-  GURL validated_url(params.url);
-  GetProcess()->FilterURL(false, &validated_url);
-
-  mojo::ScopedMessagePipeHandle blob_url_token_handle(params.blob_url_token);
-  blink::mojom::BlobURLTokenPtr blob_url_token(
-      blink::mojom::BlobURLTokenPtrInfo(std::move(blob_url_token_handle),
-                                        blink::mojom::BlobURLToken::Version_));
+  // Verify and unpack IPC payload.
+  GURL validated_url;
   scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
-  if (blob_url_token) {
-    if (!params.url.SchemeIsBlob()) {
-      bad_message::ReceivedBadMessage(
-          GetProcess(), bad_message::RFPH_BLOB_URL_TOKEN_FOR_NON_BLOB_URL);
-      return;
-    }
-    blob_url_loader_factory =
-        ChromeBlobStorageContext::URLLoaderFactoryForToken(
-            GetSiteInstance()->GetBrowserContext(), std::move(blob_url_token));
+  if (!VerifyOpenURLParams(GetSiteInstance(), params, &validated_url,
+                           &blob_url_loader_factory)) {
+    return;
   }
 
   // Verify that we are in the same BrowsingInstance as the current
@@ -308,15 +298,6 @@
   if (!site_instance_->IsRelatedSiteInstance(current_rfh->GetSiteInstance()))
     return;
 
-  // Verify if the request originator (*not* |current_rfh|) has access to the
-  // contents of the POST body.
-  if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanReadRequestBody(
-          GetSiteInstance(), params.resource_request_body)) {
-    bad_message::ReceivedBadMessage(GetProcess(),
-                                    bad_message::RFPH_ILLEGAL_UPLOAD_PARAMS);
-    return;
-  }
-
   // Since this navigation targeted a specific RenderFrameProxy, it should stay
   // in the current tab.
   DCHECK_EQ(WindowOpenDisposition::CURRENT_TAB, params.disposition);
diff --git a/content/browser/gpu/browser_gpu_channel_host_factory.h b/content/browser/gpu/browser_gpu_channel_host_factory.h
index c620a09..552afc8 100644
--- a/content/browser/gpu/browser_gpu_channel_host_factory.h
+++ b/content/browser/gpu/browser_gpu_channel_host_factory.h
@@ -15,6 +15,7 @@
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/single_thread_task_runner.h"
+#include "base/timer/timer.h"
 #include "build/build_config.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/browser_thread.h"
diff --git a/content/browser/indexed_db/indexed_db_factory_impl.cc b/content/browser/indexed_db/indexed_db_factory_impl.cc
index 8dd39826..70e3107f 100644
--- a/content/browser/indexed_db/indexed_db_factory_impl.cc
+++ b/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -19,6 +19,7 @@
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/timer/timer.h"
 #include "content/browser/indexed_db/indexed_db_backing_store.h"
 #include "content/browser/indexed_db/indexed_db_class_factory.h"
 #include "content/browser/indexed_db/indexed_db_context_impl.h"
diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc
index d06ee90f..cb6179d 100644
--- a/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -22,6 +22,7 @@
 #include "base/task/task_traits.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/timer/timer.h"
 #include "base/unguessable_token.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/download/download_manager_impl.h"
diff --git a/content/browser/media/flinging_renderer.cc b/content/browser/media/flinging_renderer.cc
index 89ead420..59c0d42 100644
--- a/content/browser/media/flinging_renderer.cc
+++ b/content/browser/media/flinging_renderer.cc
@@ -98,10 +98,13 @@
 
 void FlingingRenderer::SetPlaybackRate(double playback_rate) {
   DVLOG(2) << __func__;
-  if (playback_rate == 0)
+  if (playback_rate == 0) {
+    SetTargetPlayState(PlayState::PAUSED);
     controller_->GetMediaController()->Pause();
-  else
+  } else {
+    SetTargetPlayState(PlayState::PLAYING);
     controller_->GetMediaController()->Play();
+  }
 }
 
 void FlingingRenderer::SetVolume(float volume) {
@@ -113,8 +116,49 @@
   return controller_->GetApproximateCurrentTime();
 }
 
+void FlingingRenderer::SetTargetPlayState(PlayState state) {
+  DVLOG(3) << __func__ << " : state " << static_cast<int>(state);
+  DCHECK(state == PlayState::PLAYING || state == PlayState::PAUSED);
+  reached_target_play_state_ = false;
+  target_play_state_ = state;
+}
+
 void FlingingRenderer::OnMediaStatusUpdated(const media::MediaStatus& status) {
-  // TODO(tguilbert): propagate important changes to RendererClient.
+  const auto& current_state = status.state;
+
+  if (current_state == target_play_state_)
+    reached_target_play_state_ = true;
+
+  // Because we can get a MediaStatus update at any time from the device, only
+  // handle state updates after we have reached the target state.
+  // If we do not, we can encounter the following scenario:
+  // - A user pauses the video.
+  // - While the PAUSE command is in flight, an unrelated MediaStatus with a
+  //   PLAYING state is sent from the cast device.
+  // - We call OnRemotePlaybackStateChange(PLAYING).
+  // - As the PAUSE command completes and we receive a PlayState::PAUSE, we
+  //   queue a new PLAYING.
+  // - The local device enters a tick/tock feedback loop of constantly
+  //   requesting the wrong state of PLAYING/PAUSED.
+  if (!reached_target_play_state_)
+    return;
+
+  // Ignore all non PLAYING/PAUSED states.
+  // UNKNOWN and BUFFERING states are uninteresting and can be safely ignored.
+  // STOPPED normally causes the session to teardown, and |this| is destroyed
+  // shortly after.
+  if (current_state != PlayState::PLAYING &&
+      current_state != PlayState::PAUSED) {
+    DVLOG(3) << __func__ << " : external state ignored: "
+             << static_cast<int>(current_state);
+    return;
+  }
+
+  // We previously reached a stable target PlayState, and the cast device has
+  // reached a new stable PlayState without WMPI having asked for it.
+  // Let WMPI know it should update itself.
+  if (current_state != target_play_state_)
+    client_->OnRemotePlayStateChange(current_state);
 }
 
 }  // namespace content
diff --git a/content/browser/media/flinging_renderer.h b/content/browser/media/flinging_renderer.h
index 023c216d..5279b14e 100644
--- a/content/browser/media/flinging_renderer.h
+++ b/content/browser/media/flinging_renderer.h
@@ -54,10 +54,19 @@
 
  private:
   friend class FlingingRendererTest;
+  using PlayState = media::MediaStatus::State;
 
   explicit FlingingRenderer(
       std::unique_ptr<media::FlingingController> controller);
 
+  void SetTargetPlayState(PlayState state);
+
+  // The state that we expect the remotely playing video to transition into.
+  // This is used to differentiate between state changes that originated from
+  // this device versus external devices.
+  PlayState target_play_state_ = PlayState::UNKNOWN;
+  bool reached_target_play_state_ = false;
+
   media::RendererClient* client_;
 
   std::unique_ptr<media::FlingingController> controller_;
diff --git a/content/browser/media/media_internals_unittest.cc b/content/browser/media/media_internals_unittest.cc
index 2f8365aa..632cd03 100644
--- a/content/browser/media/media_internals_unittest.cc
+++ b/content/browser/media/media_internals_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "content/browser/media/session/media_session_impl.h"
+#include "content/public/common/service_manager_connection.h"
 #include "content/public/test/test_browser_thread_bundle.h"
 #include "content/public/test/test_renderer_host.h"
 #include "content/public/test/test_service_manager_context.h"
@@ -27,6 +28,7 @@
 #include "services/media_session/public/cpp/features.h"
 #include "services/media_session/public/mojom/audio_focus.mojom.h"
 #include "services/media_session/public/mojom/constants.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
 #include "ui/gfx/geometry/size.h"
 
 namespace {
diff --git a/content/browser/media/session/media_session_impl.cc b/content/browser/media/session/media_session_impl.cc
index 7a4a7bd..14870f1 100644
--- a/content/browser/media/session/media_session_impl.cc
+++ b/content/browser/media/session/media_session_impl.cc
@@ -11,6 +11,7 @@
 #include "base/numerics/ranges.h"
 #include "base/stl_util.h"
 #include "base/strings/string_util.h"
+#include "base/timer/timer.h"
 #include "build/build_config.h"
 #include "components/url_formatter/elide_url.h"
 #include "content/browser/media/session/audio_focus_delegate.h"
diff --git a/content/browser/navigation_browsertest.cc b/content/browser/navigation_browsertest.cc
index 513ab44..0dadf66 100644
--- a/content/browser/navigation_browsertest.cc
+++ b/content/browser/navigation_browsertest.cc
@@ -565,7 +565,7 @@
       "document.getElementById('file-form').submit();",
       &result));
   EXPECT_TRUE(result);
-  EXPECT_EQ(bad_message::RFH_ILLEGAL_UPLOAD_PARAMS, process_kill_waiter.Wait());
+  EXPECT_EQ(bad_message::ILLEGAL_UPLOAD_PARAMS, process_kill_waiter.Wait());
 }
 
 // Test case to verify that redirects to data: URLs are properly disallowed,
diff --git a/content/browser/notifications/notification_event_dispatcher_impl_unittest.cc b/content/browser/notifications/notification_event_dispatcher_impl_unittest.cc
index ab6bf58..cbc8b8b 100644
--- a/content/browser/notifications/notification_event_dispatcher_impl_unittest.cc
+++ b/content/browser/notifications/notification_event_dispatcher_impl_unittest.cc
@@ -8,6 +8,7 @@
 #include <memory>
 #include <vector>
 
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/test/test_simple_task_runner.h"
diff --git a/content/browser/payments/payment_app_provider_impl.cc b/content/browser/payments/payment_app_provider_impl.cc
index f10b36b..9d3bee7 100644
--- a/content/browser/payments/payment_app_provider_impl.cc
+++ b/content/browser/payments/payment_app_provider_impl.cc
@@ -6,6 +6,7 @@
 
 #include "base/base64.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/strings/string_util.h"
 #include "base/task/post_task.h"
 #include "content/browser/payments/payment_app_context_impl.h"
diff --git a/content/browser/presentation/presentation_service_impl_unittest.cc b/content/browser/presentation/presentation_service_impl_unittest.cc
index 391083a..863e15e 100644
--- a/content/browser/presentation/presentation_service_impl_unittest.cc
+++ b/content/browser/presentation/presentation_service_impl_unittest.cc
@@ -14,6 +14,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "content/public/browser/presentation_request.h"
 #include "content/public/browser/presentation_service_delegate.h"
diff --git a/content/browser/renderer_host/clipboard_host_impl_unittest.cc b/content/browser/renderer_host/clipboard_host_impl_unittest.cc
index 128e01e..05cb4a12 100644
--- a/content/browser/renderer_host/clipboard_host_impl_unittest.cc
+++ b/content/browser/renderer_host/clipboard_host_impl_unittest.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include "base/bind_helpers.h"
 #include "base/callback_helpers.h"
 #include "base/run_loop.h"
 #include "base/strings/string16.h"
diff --git a/content/browser/renderer_host/compositor_impl_android_browsertest.cc b/content/browser/renderer_host/compositor_impl_android_browsertest.cc
index ec8138a2d..285ba9709 100644
--- a/content/browser/renderer_host/compositor_impl_android_browsertest.cc
+++ b/content/browser/renderer_host/compositor_impl_android_browsertest.cc
@@ -6,6 +6,7 @@
 #include "base/android/build_info.h"
 #include "base/base_switches.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/test/scoped_feature_list.h"
 #include "components/viz/common/features.h"
 #include "content/browser/browser_main_loop.h"
diff --git a/content/browser/renderer_host/direct_manipulation_browsertest.cc b/content/browser/renderer_host/direct_manipulation_browsertest.cc
index 5ed43cc5..9a266c8 100644
--- a/content/browser/renderer_host/direct_manipulation_browsertest.cc
+++ b/content/browser/renderer_host/direct_manipulation_browsertest.cc
@@ -119,7 +119,7 @@
   shell2->Close();
 }
 
-// EventLogger is to observe the events sent from WindowEventTarget (the root
+// EventLogger is to obserser the events sent from WindowEventTarget (the root
 // window).
 class EventLogger : public ui::EventRewriter {
  public:
@@ -132,12 +132,19 @@
 
  private:
   // ui::EventRewriter
-  ui::EventDispatchDetails RewriteEvent(
+  ui::EventRewriteStatus RewriteEvent(
       const ui::Event& event,
-      const base::WeakPtr<Continuation> continuation) override {
+      std::unique_ptr<ui::Event>* new_event) override {
     DCHECK(!last_event_);
     last_event_ = ui::Event::Clone(event);
-    return SendEvent(continuation, &event);
+    return ui::EVENT_REWRITE_CONTINUE;
+  }
+
+  // ui::EventRewriter
+  ui::EventRewriteStatus NextDispatchEvent(
+      const ui::Event& last_event,
+      std::unique_ptr<ui::Event>* new_event) override {
+    return ui::EVENT_REWRITE_CONTINUE;
   }
 
   std::unique_ptr<ui::Event> last_event_ = nullptr;
diff --git a/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc b/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
index e51c009..9d0183f 100644
--- a/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
+++ b/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
@@ -11,6 +11,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/test/scoped_task_environment.h"
 #include "base/time/time.h"
 #include "content/browser/renderer_host/input/synthetic_gesture.h"
diff --git a/content/browser/renderer_host/media/audio_output_delegate_impl.h b/content/browser/renderer_host/media/audio_output_delegate_impl.h
index 824a99ce..f5d3a02 100644
--- a/content/browser/renderer_host/media/audio_output_delegate_impl.h
+++ b/content/browser/renderer_host/media/audio_output_delegate_impl.h
@@ -10,6 +10,7 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/timer/timer.h"
 #include "content/common/content_export.h"
 #include "media/audio/audio_output_delegate.h"
 #include "media/mojo/interfaces/audio_logging.mojom.h"
diff --git a/content/browser/renderer_host/media/service_video_capture_device_launcher.cc b/content/browser/renderer_host/media/service_video_capture_device_launcher.cc
index 4ec69bb..a37f0b2 100644
--- a/content/browser/renderer_host/media/service_video_capture_device_launcher.cc
+++ b/content/browser/renderer_host/media/service_video_capture_device_launcher.cc
@@ -5,6 +5,7 @@
 #include "content/browser/renderer_host/media/service_video_capture_device_launcher.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/task/post_task.h"
 #include "content/browser/renderer_host/media/service_launched_video_capture_device.h"
 #include "content/public/browser/browser_task_traits.h"
diff --git a/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc b/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc
index 1353c17..93cdd6d 100644
--- a/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc
+++ b/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc
@@ -5,6 +5,7 @@
 #include "content/browser/renderer_host/media/service_video_capture_provider.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/test/mock_callback.h"
 #include "base/threading/thread.h"
diff --git a/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc b/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc
index f847487..3e9d849 100644
--- a/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc
+++ b/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/task/post_task.h"
 #include "base/task_runner_util.h"
 #include "content/browser/renderer_host/pepper/browser_ppapi_host_impl.h"
diff --git a/content/browser/renderer_host/render_process_host_browsertest.cc b/content/browser/renderer_host/render_process_host_browsertest.cc
index 4ae24e5..4caf7d5 100644
--- a/content/browser/renderer_host/render_process_host_browsertest.cc
+++ b/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/run_loop.h"
 #include "base/synchronization/waitable_event.h"
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 2841e44..740e73b6 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -791,13 +791,6 @@
   RenderProcessHost* host_ = nullptr;
 };
 
-void CreateProcessResourceCoordinator(
-    RenderProcessHostImpl* render_process_host,
-    resource_coordinator::mojom::ProcessCoordinationUnitRequest request) {
-  render_process_host->GetProcessResourceCoordinator()->AddBinding(
-      std::move(request));
-}
-
 // Forwards service requests to Service Manager since the renderer cannot launch
 // out-of-process services on is own.
 template <typename Interface>
@@ -1321,14 +1314,6 @@
       base::BindOnce(&AddCorbExceptionForPluginOnUIThread, process_id));
 }
 
-service_manager::Connector* MaybeGetProcessResourceCoordinator() {
-  auto* connection = ServiceManagerConnection::GetForProcess();
-  if (!connection)
-    return nullptr;
-
-  return connection->GetConnector();
-}
-
 }  // namespace
 
 // Held by the RPH and used to control an (unowned) ConnectionFilterImpl from
@@ -1617,7 +1602,6 @@
       channel_connected_(false),
       sent_render_process_ready_(false),
       renderer_host_binding_(this),
-      process_resource_coordinator_(MaybeGetProcessResourceCoordinator()),
       instance_weak_factory_(
           new base::WeakPtrFactory<RenderProcessHostImpl>(this)),
       frame_sink_provider_(id_),
@@ -2180,10 +2164,6 @@
           base::Unretained(this)));
 
   AddUIThreadInterface(registry.get(),
-                       base::BindRepeating(&CreateProcessResourceCoordinator,
-                                           base::Unretained(this)));
-
-  AddUIThreadInterface(registry.get(),
                        base::BindRepeating(&ClipboardHostImpl::Create));
 
   media::VideoDecodePerfHistory* video_perf_history =
@@ -2578,11 +2558,6 @@
   return renderer_interface_.get();
 }
 
-resource_coordinator::ProcessResourceCoordinator*
-RenderProcessHostImpl::GetProcessResourceCoordinator() {
-  return &process_resource_coordinator_;
-}
-
 void RenderProcessHostImpl::CreateURLLoaderFactoryForRendererProcess(
     network::mojom::URLLoaderFactoryRequest request) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -4251,8 +4226,6 @@
   // it has died.
   ResetIPC();
 
-  process_resource_coordinator_.SetProcessExitStatus(info.exit_code);
-
   UpdateProcessPriority();
 
   within_process_died_observer_ = true;
@@ -4583,8 +4556,6 @@
       observer.RenderProcessReady(this);
   }
 
-  GetProcessResourceCoordinator()->OnProcessLaunched(GetProcess());
-
   WebRTCInternals* webrtc_internals = WebRTCInternals::GetInstance();
   if (webrtc_internals->IsAudioDebugRecordingsEnabled()) {
     EnableAudioDebugRecordings(
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h
index c428b68..83933c1 100644
--- a/content/browser/renderer_host/render_process_host_impl.h
+++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -54,7 +54,6 @@
 #include "mojo/public/cpp/system/invitation.h"
 #include "services/network/public/mojom/mdns_responder.mojom.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
-#include "services/resource_coordinator/public/cpp/process_resource_coordinator.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "services/service_manager/public/mojom/service.mojom.h"
 #include "services/viz/public/interfaces/compositing/compositing_mode_watcher.mojom.h"
@@ -221,8 +220,6 @@
   void PurgeAndSuspend() override;
   void Resume() override;
   mojom::Renderer* GetRendererInterface() override;
-  resource_coordinator::ProcessResourceCoordinator*
-  GetProcessResourceCoordinator() override;
   void CreateURLLoaderFactory(
       const base::Optional<url::Origin>& origin,
       network::mojom::TrustedURLLoaderHeaderClientPtrInfo header_client,
@@ -896,9 +893,6 @@
   // determine if if a process should be backgrounded.
   int media_stream_count_ = 0;
 
-  resource_coordinator::ProcessResourceCoordinator
-      process_resource_coordinator_;
-
   // A WeakPtrFactory which is reset every time Cleanup() runs. Used to vend
   // WeakPtrs which are invalidated any time the RPHI is recycled.
   std::unique_ptr<base::WeakPtrFactory<RenderProcessHostImpl>>
diff --git a/content/browser/scheduler/browser_task_executor_unittest.cc b/content/browser/scheduler/browser_task_executor_unittest.cc
index a8429ab..a70626b 100644
--- a/content/browser/scheduler/browser_task_executor_unittest.cc
+++ b/content/browser/scheduler/browser_task_executor_unittest.cc
@@ -7,6 +7,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/task/post_task.h"
 #include "base/test/scoped_task_environment.h"
 #include "content/public/browser/browser_task_traits.h"
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index 71247da..c6a41c4 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -744,7 +744,7 @@
   EXPECT_EQ(start_url, root->current_frame_host()->GetLastCommittedURL());
 
   // Verify that the malicious renderer got killed.
-  EXPECT_EQ(bad_message::RFH_ILLEGAL_UPLOAD_PARAMS, kill_waiter.Wait());
+  EXPECT_EQ(bad_message::ILLEGAL_UPLOAD_PARAMS, kill_waiter.Wait());
 }
 
 // Test that forging a frame's unique name and commit won't allow changing the
diff --git a/content/browser/service_worker/embedded_worker_instance_unittest.cc b/content/browser/service_worker/embedded_worker_instance_unittest.cc
index 47d39524..9ff0c68 100644
--- a/content/browser/service_worker/embedded_worker_instance_unittest.cc
+++ b/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index dc93883e..d1fe774 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/json/json_reader.h"
diff --git a/content/browser/service_worker/service_worker_clients_api_browsertest.cc b/content/browser/service_worker/service_worker_clients_api_browsertest.cc
index 9710079..02029fe 100644
--- a/content/browser/service_worker/service_worker_clients_api_browsertest.cc
+++ b/content/browser/service_worker/service_worker_clients_api_browsertest.cc
@@ -5,6 +5,7 @@
 #include <string>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/callback_forward.h"
 #include "base/logging.h"
diff --git a/content/browser/service_worker/service_worker_context_request_handler_unittest.cc b/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
index 1005271..e29ac51 100644
--- a/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
+++ b/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/bind_helpers.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
 #include "base/run_loop.h"
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc
index 4c25e9d..21f41e0 100644
--- a/content/browser/service_worker/service_worker_context_wrapper.cc
+++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -12,6 +12,7 @@
 
 #include "base/barrier_closure.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/feature_list.h"
 #include "base/files/file_path.h"
 #include "base/guid.h"
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
index fc23d881..6d8341bd 100644
--- a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
+++ b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
@@ -7,6 +7,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/bind_helpers.h"
 #include "base/callback_helpers.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
diff --git a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
index 4b4a1f7..80b1acda 100644
--- a/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/run_loop.h"
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
index 33369d6..99401257 100644
--- a/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/containers/queue.h"
 #include "base/feature_list.h"
 #include "base/task/post_task.h"
diff --git a/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc b/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
index 7a31637c..6446d112 100644
--- a/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
+++ b/content/browser/service_worker/service_worker_installed_scripts_sender_unittest.cc
@@ -5,6 +5,7 @@
 #include "content/browser/service_worker/service_worker_installed_scripts_sender.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/stl_util.h"
diff --git a/content/browser/service_worker/service_worker_job_unittest.cc b/content/browser/service_worker/service_worker_job_unittest.cc
index 28708ba5..fb9753cb 100644
--- a/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_job_unittest.cc
@@ -6,6 +6,7 @@
 #include <tuple>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
 #include "base/optional.h"
diff --git a/content/browser/service_worker/service_worker_navigation_loader.cc b/content/browser/service_worker/service_worker_navigation_loader.cc
index 59fe9876..4011411 100644
--- a/content/browser/service_worker/service_worker_navigation_loader.cc
+++ b/content/browser/service_worker/service_worker_navigation_loader.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/optional.h"
diff --git a/content/browser/service_worker/service_worker_navigation_loader_unittest.cc b/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
index 53813f0..d6709e1 100644
--- a/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
+++ b/content/browser/service_worker/service_worker_navigation_loader_unittest.cc
@@ -7,6 +7,7 @@
 #include <string>
 #include <utility>
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/test/metrics/histogram_tester.h"
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 1016c4f..1a6ff0d 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
@@ -8,6 +8,7 @@
 #include <memory>
 #include <string>
 #include <utility>
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
 #include "base/test/metrics/histogram_tester.h"
diff --git a/content/browser/service_worker/service_worker_object_host.cc b/content/browser/service_worker/service_worker_object_host.cc
index b75bcc2f..82dfd5a 100644
--- a/content/browser/service_worker/service_worker_object_host.cc
+++ b/content/browser/service_worker/service_worker_object_host.cc
@@ -5,6 +5,7 @@
 #include "content/browser/service_worker/service_worker_object_host.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "content/browser/service_worker/service_worker_client_utils.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
 #include "content/browser/service_worker/service_worker_provider_host.h"
diff --git a/content/browser/service_worker/service_worker_object_host_unittest.cc b/content/browser/service_worker/service_worker_object_host_unittest.cc
index 8404741..7dcbd52 100644
--- a/content/browser/service_worker/service_worker_object_host_unittest.cc
+++ b/content/browser/service_worker/service_worker_object_host_unittest.cc
@@ -6,6 +6,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/test/simple_test_tick_clock.h"
diff --git a/content/browser/service_worker/service_worker_register_job.cc b/content/browser/service_worker/service_worker_register_job.cc
index 9f56124..c129323 100644
--- a/content/browser/service_worker/service_worker_register_job.cc
+++ b/content/browser/service_worker/service_worker_register_job.cc
@@ -7,6 +7,7 @@
 #include <stdint.h>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/location.h"
 #include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/content/browser/service_worker/service_worker_registration.cc b/content/browser/service_worker/service_worker_registration.cc
index b9e93324..24e7506 100644
--- a/content/browser/service_worker/service_worker_registration.cc
+++ b/content/browser/service_worker/service_worker_registration.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "content/browser/service_worker/embedded_worker_status.h"
 #include "content/browser/service_worker/service_worker_context_core.h"
diff --git a/content/browser/service_worker/service_worker_registration.h b/content/browser/service_worker/service_worker_registration.h
index 994a773..12b6452 100644
--- a/content/browser/service_worker/service_worker_registration.h
+++ b/content/browser/service_worker/service_worker_registration.h
@@ -16,6 +16,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/single_thread_task_runner.h"
 #include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "content/browser/service_worker/service_worker_version.h"
 #include "content/common/content_export.h"
 #include "content/common/service_worker/service_worker_types.h"
diff --git a/content/browser/service_worker/service_worker_registration_unittest.cc b/content/browser/service_worker/service_worker_registration_unittest.cc
index 44b8fa9..0b57d33 100644
--- a/content/browser/service_worker/service_worker_registration_unittest.cc
+++ b/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback_helpers.h"
 #include "base/compiler_specific.h"
 #include "base/files/scoped_temp_dir.h"
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 09a0579..587eda2 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
@@ -4,6 +4,7 @@
 
 #include "content/browser/service_worker/service_worker_script_loader_factory.h"
 
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
 #include "content/browser/service_worker/embedded_worker_test_helper.h"
diff --git a/content/browser/service_worker/service_worker_storage_unittest.cc b/content/browser/service_worker/service_worker_storage_unittest.cc
index df04778..a0dc1b7f 100644
--- a/content/browser/service_worker/service_worker_storage_unittest.cc
+++ b/content/browser/service_worker/service_worker_storage_unittest.cc
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/logging.h"
diff --git a/content/browser/service_worker/service_worker_url_request_job_unittest.cc b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
index 069954f..91d62dc 100644
--- a/content/browser/service_worker/service_worker_url_request_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_url_request_job_unittest.cc
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
diff --git a/content/browser/service_worker/service_worker_version_unittest.cc b/content/browser/service_worker/service_worker_version_unittest.cc
index 9bf76ba..6843f66 100644
--- a/content/browser/service_worker/service_worker_version_unittest.cc
+++ b/content/browser/service_worker/service_worker_version_unittest.cc
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/run_loop.h"
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc
index 2c6b3cd..141c4190 100644
--- a/content/browser/site_per_process_hit_test_browsertest.cc
+++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -705,11 +705,18 @@
   ~SystemEventRewriter() override = default;
 
  private:
-  ui::EventDispatchDetails RewriteEvent(
+  ui::EventRewriteStatus RewriteEvent(
       const ui::Event& event,
-      const base::WeakPtr<Continuation> continuation) override {
-    return num_of_scoped_allows_ ? continuation->SendEvent(&event)
-                                 : continuation->DiscardEvent();
+      std::unique_ptr<ui::Event>* new_event) override {
+    return num_of_scoped_allows_ ? ui::EVENT_REWRITE_CONTINUE
+                                 : ui::EVENT_REWRITE_DISCARD;
+  }
+
+  ui::EventRewriteStatus NextDispatchEvent(
+      const ui::Event& event,
+      std::unique_ptr<ui::Event>* new_event) override {
+    NOTREACHED();
+    return ui::EVENT_REWRITE_CONTINUE;
   }
 
   // Count of ScopedAllow objects. When it is greater than 0, events are allowed
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index a7c589c..a1c24ebd 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -13,6 +13,7 @@
 
 #include "base/barrier_closure.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback_helpers.h"
 #include "base/command_line.h"
 #include "base/location.h"
diff --git a/content/browser/storage_partition_impl_map.cc b/content/browser/storage_partition_impl_map.cc
index 430e8d0c..ac79b6f 100644
--- a/content/browser/storage_partition_impl_map.cc
+++ b/content/browser/storage_partition_impl_map.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/files/file_enumerator.h"
diff --git a/content/browser/tracing/background_tracing_manager_impl.cc b/content/browser/tracing/background_tracing_manager_impl.cc
index 54b630c..cad21e1a 100644
--- a/content/browser/tracing/background_tracing_manager_impl.cc
+++ b/content/browser/tracing/background_tracing_manager_impl.cc
@@ -726,7 +726,7 @@
     case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_NAVIGATION: {
       auto config = TraceConfig(
           "benchmark,toplevel,ipc,base,browser,navigation,omnibox,ui,shutdown,"
-          "safe_browsing,Java,EarlyJava,loading,startup,"
+          "safe_browsing,Java,EarlyJava,loading,startup,mojom,"
           "disabled-by-default-system_stats,disabled-by-default-cpu_profiler",
           record_mode);
       // Filter only browser process events.
@@ -737,7 +737,7 @@
     }
     case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_RENDERERS:
       return TraceConfig(
-          "benchmark,toplevel,ipc,base,ui,v8,renderer,blink,blink_gc,"
+          "benchmark,toplevel,ipc,base,ui,v8,renderer,blink,blink_gc,mojom,"
           "disabled-by-default-v8.gc,"
           "disabled-by-default-blink_gc,"
           "disabled-by-default-renderer.scheduler,"
diff --git a/content/browser/tracing/background_tracing_rule.cc b/content/browser/tracing/background_tracing_rule.cc
index a262e90..341ca54 100644
--- a/content/browser/tracing/background_tracing_rule.cc
+++ b/content/browser/tracing/background_tracing_rule.cc
@@ -12,6 +12,7 @@
 #include "base/rand_util.h"
 #include "base/strings/safe_sprintf.h"
 #include "base/task/post_task.h"
+#include "base/timer/timer.h"
 #include "base/values.h"
 #include "components/tracing/common/tracing_messages.h"
 #include "content/browser/tracing/background_tracing_manager_impl.h"
diff --git a/content/browser/url_loader_factory_getter.cc b/content/browser/url_loader_factory_getter.cc
index 4716569..51ea65b7 100644
--- a/content/browser/url_loader_factory_getter.cc
+++ b/content/browser/url_loader_factory_getter.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/lazy_instance.h"
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 30f9e40..1b5b226 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -5819,6 +5819,18 @@
     observer.FrameReceivedFirstUserActivation(render_frame_host);
 }
 
+void WebContentsImpl::DidChangeDisplayState(RenderFrameHost* render_frame_host,
+                                            bool is_display_none) {
+  for (auto& observer : observers_)
+    observer.FrameDisplayStateChanged(render_frame_host, is_display_none);
+}
+
+void WebContentsImpl::FrameSizeChanged(RenderFrameHost* render_frame_host,
+                                       const gfx::Size& frame_size) {
+  for (auto& observer : observers_)
+    observer.FrameSizeChanged(render_frame_host, frame_size);
+}
+
 void WebContentsImpl::DocumentOnLoadCompleted(
     RenderFrameHost* render_frame_host) {
   ShowInsecureLocalhostWarningIfNeeded();
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index f69574d..c048fe9b 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -514,6 +514,10 @@
                      const std::string& name) override;
   void DidReceiveFirstUserActivation(
       RenderFrameHost* render_frame_host) override;
+  void DidChangeDisplayState(RenderFrameHost* render_frame_host,
+                             bool is_display_none) override;
+  void FrameSizeChanged(RenderFrameHost* render_frame_host,
+                        const gfx::Size& frame_size) override;
   void DocumentOnLoadCompleted(RenderFrameHost* render_frame_host) override;
   void UpdateStateForFrame(RenderFrameHost* render_frame_host,
                            const PageState& page_state) override;
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index db4155847..ac50c6c9 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -1237,10 +1237,12 @@
   // Load that same page inside an iframe.
   GURL data_url("data:text/html,<iframe src='" + url.spec() + "'></iframe>");
   NavigateToURL(shell(), data_url);
-  ASSERT_EQ(2U, observer.resource_load_infos().size());
-  EXPECT_EQ(url, observer.resource_load_infos()[0]->url);
-  EXPECT_FALSE(observer.resource_is_associated_with_main_frame()[0]);
+  ASSERT_EQ(3U, observer.resource_load_infos().size());
+  EXPECT_EQ(data_url, observer.resource_load_infos()[0]->url);
+  EXPECT_EQ(url, observer.resource_load_infos()[1]->url);
+  EXPECT_TRUE(observer.resource_is_associated_with_main_frame()[0]);
   EXPECT_FALSE(observer.resource_is_associated_with_main_frame()[1]);
+  EXPECT_FALSE(observer.resource_is_associated_with_main_frame()[2]);
 }
 
 struct LoadProgressDelegateAndObserver : public WebContentsDelegate,
diff --git a/content/browser/web_contents/web_contents_ns_view_bridge.h b/content/browser/web_contents/web_contents_ns_view_bridge.h
index 1d1c5e1..09b460fe6 100644
--- a/content/browser/web_contents/web_contents_ns_view_bridge.h
+++ b/content/browser/web_contents/web_contents_ns_view_bridge.h
@@ -14,7 +14,6 @@
 #include "content/common/content_export.h"
 #include "content/public/common/web_contents_ns_view_bridge.mojom.h"
 #include "ui/base/cocoa/ns_view_ids.h"
-#include "ui/base/cocoa/remote_accessibility_api.h"
 
 @class WebContentsViewCocoa;
 
@@ -51,8 +50,6 @@
 
  private:
   base::scoped_nsobject<WebContentsViewCocoa> cocoa_view_;
-  base::scoped_nsobject<NSAccessibilityRemoteUIElement>
-      parent_accessibility_element_;
   mojom::WebContentsNSViewClientAssociatedPtr client_;
 
   std::unique_ptr<ui::ScopedNSViewIdMapping> view_id_;
diff --git a/content/browser/web_contents/web_contents_ns_view_bridge.mm b/content/browser/web_contents/web_contents_ns_view_bridge.mm
index 44204e22b..af7ead00 100644
--- a/content/browser/web_contents/web_contents_ns_view_bridge.mm
+++ b/content/browser/web_contents/web_contents_ns_view_bridge.mm
@@ -46,15 +46,12 @@
   CHECK(parent_ns_view);
   [parent_ns_view addSubview:cocoa_view_];
 
-  parent_accessibility_element_ =
-      ui::RemoteAccessibility::GetRemoteElementFromToken(parent_token);
-  [cocoa_view_ setAccessibilityParentElement:parent_accessibility_element_];
+  // TODO(https://crbug.com/924955): Ignore the accessibility token because
+  // using it causes crashes.
 }
 
 void WebContentsNSViewBridge::ResetParentNSView() {
   [cocoa_view_ removeFromSuperview];
-  [cocoa_view_ setAccessibilityParentElement:nil];
-  parent_accessibility_element_.reset();
 }
 
 void WebContentsNSViewBridge::SetBounds(const gfx::Rect& bounds_in_window) {
diff --git a/content/browser/web_contents/web_contents_view_mac.mm b/content/browser/web_contents/web_contents_view_mac.mm
index d4f6a36d..7f4308b 100644
--- a/content/browser/web_contents/web_contents_view_mac.mm
+++ b/content/browser/web_contents/web_contents_view_mac.mm
@@ -30,7 +30,6 @@
 #include "mojo/public/cpp/bindings/interface_request.h"
 #include "ui/base/cocoa/cocoa_base_utils.h"
 #include "ui/base/cocoa/ns_view_ids.h"
-#include "ui/base/cocoa/remote_accessibility_api.h"
 #include "ui/gfx/image/image_skia_util_mac.h"
 #include "ui/gfx/mac/coordinate_conversion.h"
 
@@ -533,8 +532,12 @@
 
 void WebContentsViewMac::ViewsHostableAttach(ViewsHostableView::Host* host) {
   views_host_ = host;
-  std::vector<uint8_t> token = ui::RemoteAccessibility::GetTokenForLocalElement(
-      views_host_->GetAccessibilityElement());
+  // TODO(https://crbug.com/924955): Using the remote accessibility to set
+  // the parent accessibility element here causes crashes, so just set it
+  // directly on the in-process WebContentsViewCocoa only.
+  std::vector<uint8_t> token;
+  [cocoa_view()
+      setAccessibilityParentElement:views_host_->GetAccessibilityElement()];
 
   // Create an NSView in the target process, if one exists.
   uint64_t factory_host_id = views_host_->GetViewsFactoryHostId();
@@ -578,6 +581,7 @@
     // Permit the in-process NSView to call back into |this| again.
     [cocoa_view() setClient:this];
   }
+  [cocoa_view() setAccessibilityParentElement:nil];
   ns_view_bridge_local_->SetVisible(false);
   ns_view_bridge_local_->ResetParentNSView();
   views_host_ = nullptr;
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc
index 4e6e3ec..538ca8b 100644
--- a/content/browser/webauth/authenticator_impl_unittest.cc
+++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -19,6 +19,7 @@
 #include "base/test/test_mock_time_task_runner.h"
 #include "base/time/tick_clock.h"
 #include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "build/build_config.h"
 #include "components/cbor/reader.h"
 #include "components/cbor/values.h"
@@ -42,6 +43,7 @@
 #include "device/fido/test_callback_receiver.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "services/device/public/mojom/constants.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
diff --git a/content/common/service_manager/service_manager_connection_impl_unittest.cc b/content/common/service_manager/service_manager_connection_impl_unittest.cc
index 57dff5c..f5e49fb5 100644
--- a/content/common/service_manager/service_manager_connection_impl_unittest.cc
+++ b/content/common/service_manager/service_manager_connection_impl_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "content/common/service_manager/service_manager_connection_impl.h"
 
+#include "base/bind_helpers.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/scoped_task_environment.h"
diff --git a/content/gpu/gpu_child_thread.cc b/content/gpu/gpu_child_thread.cc
index e4e714b..cf502b4 100644
--- a/content/gpu/gpu_child_thread.cc
+++ b/content/gpu/gpu_child_thread.cc
@@ -9,6 +9,7 @@
 
 #include "base/allocator/allocator_extension.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback_helpers.h"
 #include "base/command_line.h"
 #include "base/memory/weak_ptr.h"
diff --git a/content/public/app/content_packaged_services_manifest.cc b/content/public/app/content_packaged_services_manifest.cc
index bbad965..68a5db3 100644
--- a/content/public/app/content_packaged_services_manifest.cc
+++ b/content/public/app/content_packaged_services_manifest.cc
@@ -54,8 +54,8 @@
         .RequireCapability(mojom::kBrowserServiceName, "")
         .RequireCapability("*", "app")
         .PackageService(heap_profiling::GetManifest())
-        .PackageService(cdm::GetManifest())
-        .PackageService(media::GetManifest())
+        .PackageService(media::GetCdmManifest())
+        .PackageService(media::GetMediaManifest())
         .PackageService(audio::GetManifest())
         .PackageService(data_decoder::GetManifest())
         .PackageService(device::GetManifest())
diff --git a/content/public/browser/DEPS b/content/public/browser/DEPS
index 13d34fe..49fd1ed 100644
--- a/content/public/browser/DEPS
+++ b/content/public/browser/DEPS
@@ -10,7 +10,6 @@
   "+services/media_session/public",
   "+services/network/public/cpp",
   "+services/service_manager/sandbox",
-  "+services/resource_coordinator/public",
   "+services/video_capture/public/mojom",
   "+services/ws/public/cpp/host",
   "+services/ws/public/mojom",
diff --git a/content/public/browser/render_frame_host.h b/content/public/browser/render_frame_host.h
index aaa1d2e..4ab1bc5 100644
--- a/content/public/browser/render_frame_host.h
+++ b/content/public/browser/render_frame_host.h
@@ -11,6 +11,7 @@
 #include "base/callback_forward.h"
 #include "base/containers/flat_set.h"
 #include "base/feature_list.h"
+#include "base/optional.h"
 #include "build/build_config.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/page_visibility_state.h"
@@ -44,10 +45,6 @@
 CONTENT_EXPORT extern const base::Feature kCrashReporting;
 }  // namespace features
 
-namespace resource_coordinator {
-class FrameResourceCoordinator;
-}
-
 namespace service_manager {
 class InterfaceProvider;
 }
@@ -110,11 +107,6 @@
   // process.
   virtual SiteInstance* GetSiteInstance() = 0;
 
-  // Returns the interface for the Global Resource Coordinator
-  // for this frame.
-  virtual resource_coordinator::FrameResourceCoordinator*
-  GetFrameResourceCoordinator() = 0;
-
   // Returns the process for this frame.
   virtual RenderProcessHost* GetProcess() = 0;
 
@@ -159,6 +151,13 @@
   // return an empty string.
   virtual const std::string& GetFrameName() = 0;
 
+  // Returns true if the frame is display: none.
+  virtual bool IsFrameDisplayNone() = 0;
+
+  // Returns the size of the frame in the viewport. The frame may not be aware
+  // of its size.
+  virtual const base::Optional<gfx::Size>& GetFrameSize() = 0;
+
   // Returns true if the frame is out of process.
   virtual bool IsCrossProcessSubframe() = 0;
 
diff --git a/content/public/browser/render_process_host.h b/content/public/browser/render_process_host.h
index 0077970..b87e12e 100644
--- a/content/public/browser/render_process_host.h
+++ b/content/public/browser/render_process_host.h
@@ -46,10 +46,6 @@
 class Identity;
 }
 
-namespace resource_coordinator {
-class ProcessResourceCoordinator;
-}
-
 namespace content {
 class BrowserContext;
 class BrowserMessageFilter;
@@ -403,10 +399,6 @@
   // MockRenderProcessHost usage in tests.
   virtual mojom::Renderer* GetRendererInterface() = 0;
 
-  // Acquires the interface to the Global Resource Coordinator for this process.
-  virtual resource_coordinator::ProcessResourceCoordinator*
-  GetProcessResourceCoordinator() = 0;
-
   // Create an URLLoaderFactory that can be used by |origin| being hosted in
   // |this| process.
   //
diff --git a/content/public/browser/web_contents_observer.h b/content/public/browser/web_contents_observer.h
index 8d2239b..ac34050 100644
--- a/content/public/browser/web_contents_observer.h
+++ b/content/public/browser/web_contents_observer.h
@@ -360,6 +360,14 @@
   virtual void FrameReceivedFirstUserActivation(
       RenderFrameHost* render_frame_host) {}
 
+  // Invoked when the display state of the frame changes.
+  virtual void FrameDisplayStateChanged(RenderFrameHost* render_frame_host,
+                                        bool is_display_none) {}
+
+  // Invoked when a frame changes size.
+  virtual void FrameSizeChanged(RenderFrameHost* render_frame_host,
+                                const gfx::Size& frame_size) {}
+
   // This method is invoked when the title of the WebContents is set. Note that
   // |entry| may be null if the web page whose title changed has not yet had a
   // NavigationEntry assigned to it.
diff --git a/content/public/test/DEPS b/content/public/test/DEPS
index f6429a9..19439ae 100644
--- a/content/public/test/DEPS
+++ b/content/public/test/DEPS
@@ -9,7 +9,6 @@
   "+components/viz/test",
   "+services/audio/public/mojom",
   "+services/network",
-  "+services/resource_coordinator",
   "+services/service_manager",
   "+ui/ozone/public",
   "+ui/views/test",
diff --git a/content/public/test/content_browser_test.cc b/content/public/test/content_browser_test.cc
index 36cdbc0..2ab346c2 100644
--- a/content/public/test/content_browser_test.cc
+++ b/content/public/test/content_browser_test.cc
@@ -140,9 +140,16 @@
 #if defined(OS_MACOSX)
   pool_->Recycle();
 #endif
+
+  pre_run_test_executed_ = true;
 }
 
 void ContentBrowserTest::PostRunTestOnMainThread() {
+  // This code is failing when the test is overriding PreRunTestOnMainThread()
+  // without the required call to ContentBrowserTest::PreRunTestOnMainThread().
+  // This is a common error causing a crash on MAC.
+  DCHECK(pre_run_test_executed_);
+
 #if defined(OS_MACOSX)
   pool_->Recycle();
 #endif
diff --git a/content/public/test/content_browser_test.h b/content/public/test/content_browser_test.h
index 8232fa5..6373513 100644
--- a/content/public/test/content_browser_test.h
+++ b/content/public/test/content_browser_test.h
@@ -48,7 +48,7 @@
   base::FilePath GetTestDataFilePath();
 
  private:
-  Shell* shell_;
+  Shell* shell_ = nullptr;
 
 #if defined(OS_MACOSX)
   // On Mac, without the following autorelease pool, code which is directly
@@ -66,6 +66,10 @@
   // ContentMain. For Android we set things up manually.
   std::unique_ptr<ShellMainDelegate> shell_main_delegate_;
 #endif
+
+  // Used to detect incorrect overriding of PreRunTestOnMainThread() with
+  // missung call to base implementation.
+  bool pre_run_test_executed_ = false;
 };
 
 }  // namespace content
diff --git a/content/public/test/mock_render_process_host.cc b/content/public/test/mock_render_process_host.cc
index 2e4f713..4be6589 100644
--- a/content/public/test/mock_render_process_host.cc
+++ b/content/public/test/mock_render_process_host.cc
@@ -396,21 +396,6 @@
   return renderer_interface_->get();
 }
 
-resource_coordinator::ProcessResourceCoordinator*
-MockRenderProcessHost::GetProcessResourceCoordinator() {
-  if (!process_resource_coordinator_) {
-    content::ServiceManagerConnection* connection =
-        content::ServiceManagerConnection::GetForProcess();
-    // Tests may not set up a connection.
-    service_manager::Connector* connector =
-        connection ? connection->GetConnector() : nullptr;
-    process_resource_coordinator_ =
-        std::make_unique<resource_coordinator::ProcessResourceCoordinator>(
-            connector);
-  }
-  return process_resource_coordinator_.get();
-}
-
 void MockRenderProcessHost::CreateURLLoaderFactory(
     const base::Optional<url::Origin>& origin,
     network::mojom::TrustedURLLoaderHeaderClientPtrInfo header_client,
diff --git a/content/public/test/mock_render_process_host.h b/content/public/test/mock_render_process_host.h
index 60ebad7..8a5f877 100644
--- a/content/public/test/mock_render_process_host.h
+++ b/content/public/test/mock_render_process_host.h
@@ -26,7 +26,6 @@
 #include "ipc/ipc_test_sink.h"
 #include "media/media_buildflags.h"
 #include "mojo/public/cpp/bindings/associated_interface_ptr.h"
-#include "services/resource_coordinator/public/cpp/process_resource_coordinator.h"
 #include "services/service_manager/public/cpp/identity.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 
@@ -144,8 +143,6 @@
   void PurgeAndSuspend() override;
   void Resume() override;
   mojom::Renderer* GetRendererInterface() override;
-  resource_coordinator::ProcessResourceCoordinator*
-  GetProcessResourceCoordinator() override;
   void CreateURLLoaderFactory(
       const base::Optional<url::Origin>& origin,
       network::mojom::TrustedURLLoaderHeaderClientPtrInfo header_client,
@@ -227,8 +224,6 @@
   std::unique_ptr<mojo::AssociatedInterfacePtr<mojom::Renderer>>
       renderer_interface_;
   std::map<std::string, InterfaceBinder> binder_overrides_;
-  std::unique_ptr<resource_coordinator::ProcessResourceCoordinator>
-      process_resource_coordinator_;
   service_manager::Identity child_identity_;
   bool is_renderer_locked_to_site_ = false;
   network::mojom::URLLoaderFactory* url_loader_factory_;
diff --git a/content/public/test/network_service_test_helper.cc b/content/public/test/network_service_test_helper.cc
index a048c5fd..978ea4d 100644
--- a/content/public/test/network_service_test_helper.cc
+++ b/content/public/test/network_service_test_helper.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/logging.h"
diff --git a/content/public/test/web_test_support.h b/content/public/test/web_test_support.h
index 1183f55..0a644b93 100644
--- a/content/public/test/web_test_support.h
+++ b/content/public/test/web_test_support.h
@@ -22,7 +22,6 @@
 class WebLocalFrame;
 struct WebSize;
 class WebURL;
-class WebURLRequest;
 class WebView;
 }  // namespace blink
 
@@ -146,11 +145,6 @@
 // TextInputState.
 void ForceTextInputStateUpdateForRenderFrame(RenderFrame* render_frame);
 
-// PlzNavigate
-// Returns true if the navigation identified by the |request| was initiated by
-// the browser or renderer.
-bool IsNavigationInitiatedByRenderer(const blink::WebURLRequest& request);
-
 // RewriteURLFunction must be safe to call from any thread in the renderer
 // process.
 using RewriteURLFunction = blink::WebURL (*)(const std::string&,
diff --git a/content/renderer/frame_owner_properties.cc b/content/renderer/frame_owner_properties.cc
index 66df968..26f18963 100644
--- a/content/renderer/frame_owner_properties.cc
+++ b/content/renderer/frame_owner_properties.cc
@@ -23,6 +23,7 @@
   result.allow_fullscreen = web_frame_owner_properties.allow_fullscreen;
   result.allow_payment_request =
       web_frame_owner_properties.allow_payment_request;
+  result.is_display_none = web_frame_owner_properties.is_display_none;
   result.required_csp = web_frame_owner_properties.required_csp.Utf8();
 
   return result;
@@ -39,6 +40,7 @@
   result.margin_height = frame_owner_properties.margin_height;
   result.allow_fullscreen = frame_owner_properties.allow_fullscreen;
   result.allow_payment_request = frame_owner_properties.allow_payment_request;
+  result.is_display_none = frame_owner_properties.is_display_none;
   result.required_csp =
       blink::WebString::FromUTF8(frame_owner_properties.required_csp);
 
diff --git a/content/renderer/internal_document_state_data.cc b/content/renderer/internal_document_state_data.cc
index c0324abc..26f1cb41 100644
--- a/content/renderer/internal_document_state_data.cc
+++ b/content/renderer/internal_document_state_data.cc
@@ -58,6 +58,7 @@
   cache_policy_override_ = other->cache_policy_override_;
   effective_connection_type_ = other->effective_connection_type_;
   previews_state_ = other->previews_state_;
+  request_id_ = other->request_id_;
 }
 
 void InternalDocumentStateData::set_navigation_state(
diff --git a/content/renderer/internal_document_state_data.h b/content/renderer/internal_document_state_data.h
index 068a848..1a71890a 100644
--- a/content/renderer/internal_document_state_data.h
+++ b/content/renderer/internal_document_state_data.h
@@ -87,6 +87,13 @@
     previews_state_ = previews_state;
   }
 
+  // This is a fake navigation request id, which we send to the browser process
+  // together with metrics. Note that renderer does not actually issue a request
+  // for navigation (browser does it instead), but still reports metrics for it.
+  // See content::mojom::ResourceLoadInfo.
+  int request_id() const { return request_id_; }
+  void set_request_id(int request_id) { request_id_ = request_id; }
+
   NavigationState* navigation_state() { return navigation_state_.get(); }
   void set_navigation_state(std::unique_ptr<NavigationState> navigation_state);
 
@@ -99,6 +106,7 @@
   net::EffectiveConnectionType effective_connection_type_ =
       net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
   PreviewsState previews_state_ = PREVIEWS_UNSPECIFIED;
+  int request_id_ = -1;
   std::unique_ptr<NavigationState> navigation_state_;
 
   DISALLOW_COPY_AND_ASSIGN(InternalDocumentStateData);
diff --git a/content/renderer/loader/navigation_body_loader.cc b/content/renderer/loader/navigation_body_loader.cc
index 094e1cb..16b063e 100644
--- a/content/renderer/loader/navigation_body_loader.cc
+++ b/content/renderer/loader/navigation_body_loader.cc
@@ -11,43 +11,88 @@
 #include "content/renderer/loader/url_response_body_consumer.h"
 #include "content/renderer/loader/web_url_loader_impl.h"
 #include "services/network/public/cpp/url_loader_completion_status.h"
+#include "third_party/blink/public/web/web_navigation_params.h"
 
 namespace content {
 
-NavigationBodyLoader::NavigationBodyLoader(
+// static
+void NavigationBodyLoader::FillNavigationParamsResponseAndBodyLoader(
     const CommonNavigationParams& common_params,
     const CommitNavigationParams& commit_params,
     int request_id,
     const network::ResourceResponseHead& head,
-    network::mojom::URLLoaderClientEndpointsPtr endpoints,
+    network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
     scoped_refptr<base::SingleThreadTaskRunner> task_runner,
     int render_frame_id,
-    bool is_main_frame)
-    : render_frame_id_(render_frame_id),
-      head_(head),
-      endpoints_(std::move(endpoints)),
-      task_runner_(task_runner),
-      url_loader_client_binding_(this),
-      handle_watcher_(FROM_HERE,
-                      mojo::SimpleWatcher::ArmingPolicy::MANUAL,
-                      task_runner),
-      weak_factory_(this) {
-  resource_load_info_ = NotifyResourceLoadInitiated(
-      render_frame_id_, request_id,
-      !commit_params.original_url.is_empty() ? commit_params.original_url
-                                             : common_params.url,
+    bool is_main_frame,
+    blink::WebNavigationParams* navigation_params) {
+  // Use the original navigation url to start with. We'll replay the redirects
+  // afterwards and will eventually arrive to the final url.
+  GURL url = !commit_params.original_url.is_empty() ? commit_params.original_url
+                                                    : common_params.url;
+  auto resource_load_info = NotifyResourceLoadInitiated(
+      render_frame_id, request_id, url,
       !commit_params.original_method.empty() ? commit_params.original_method
                                              : common_params.method,
       common_params.referrer.url,
       is_main_frame ? RESOURCE_TYPE_MAIN_FRAME : RESOURCE_TYPE_SUB_FRAME);
+
   size_t redirect_count = commit_params.redirect_response.size();
+  navigation_params->redirects.reserve(redirect_count);
+  navigation_params->redirects.resize(redirect_count);
   for (size_t i = 0; i < redirect_count; ++i) {
-    NotifyResourceRedirectReceived(render_frame_id_, resource_load_info_.get(),
-                                   commit_params.redirect_infos[i],
-                                   commit_params.redirect_response[i]);
+    blink::WebNavigationParams::RedirectInfo& redirect =
+        navigation_params->redirects[i];
+    auto& redirect_info = commit_params.redirect_infos[i];
+    auto& redirect_response = commit_params.redirect_response[i];
+    NotifyResourceRedirectReceived(render_frame_id, resource_load_info.get(),
+                                   redirect_info, redirect_response);
+    WebURLLoaderImpl::PopulateURLResponse(
+        url, redirect_response, &redirect.redirect_response,
+        false /* report_security_info */, request_id);
+    if (url.SchemeIs(url::kDataScheme))
+      redirect.redirect_response.SetHTTPStatusCode(200);
+    redirect.new_url = redirect_info.new_url;
+    redirect.new_referrer =
+        blink::WebString::FromUTF8(redirect_info.new_referrer);
+    redirect.new_referrer_policy =
+        Referrer::NetReferrerPolicyToBlinkReferrerPolicy(
+            redirect_info.new_referrer_policy);
+    redirect.new_http_method =
+        blink::WebString::FromLatin1(redirect_info.new_method);
+    url = redirect_info.new_url;
+  }
+
+  WebURLLoaderImpl::PopulateURLResponse(url, head, &navigation_params->response,
+                                        false /* report_security_info */,
+                                        request_id);
+  if (url.SchemeIs(url::kDataScheme))
+    navigation_params->response.SetHTTPStatusCode(200);
+
+  if (url_loader_client_endpoints) {
+    navigation_params->body_loader.reset(new NavigationBodyLoader(
+        head, std::move(url_loader_client_endpoints), task_runner,
+        render_frame_id, std::move(resource_load_info)));
   }
 }
 
+NavigationBodyLoader::NavigationBodyLoader(
+    const network::ResourceResponseHead& head,
+    network::mojom::URLLoaderClientEndpointsPtr endpoints,
+    scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+    int render_frame_id,
+    mojom::ResourceLoadInfoPtr resource_load_info)
+    : render_frame_id_(render_frame_id),
+      head_(head),
+      endpoints_(std::move(endpoints)),
+      task_runner_(std::move(task_runner)),
+      resource_load_info_(std::move(resource_load_info)),
+      url_loader_client_binding_(this),
+      handle_watcher_(FROM_HERE,
+                      mojo::SimpleWatcher::ArmingPolicy::MANUAL,
+                      task_runner_),
+      weak_factory_(this) {}
+
 NavigationBodyLoader::~NavigationBodyLoader() {
   if (!has_received_completion_ || !has_seen_end_of_data_) {
     NotifyResourceLoadCanceled(render_frame_id_, std::move(resource_load_info_),
diff --git a/content/renderer/loader/navigation_body_loader.h b/content/renderer/loader/navigation_body_loader.h
index fab86018..ac871a5 100644
--- a/content/renderer/loader/navigation_body_loader.h
+++ b/content/renderer/loader/navigation_body_loader.h
@@ -23,6 +23,10 @@
 #include "services/network/public/mojom/url_loader.mojom.h"
 #include "third_party/blink/public/platform/web_navigation_body_loader.h"
 
+namespace blink {
+struct WebNavigationParams;
+}  // namespace blink
+
 namespace network {
 struct URLLoaderCompletionStatus;
 }  // namespace network
@@ -42,7 +46,9 @@
     : public blink::WebNavigationBodyLoader,
       public network::mojom::URLLoaderClient {
  public:
-  NavigationBodyLoader(
+  // This method fills navigation params related to the navigation request,
+  // redirects and response, and also creates a body loader if needed.
+  static void FillNavigationParamsResponseAndBodyLoader(
       const CommonNavigationParams& common_params,
       const CommitNavigationParams& commit_params,
       int request_id,
@@ -50,7 +56,8 @@
       network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
       scoped_refptr<base::SingleThreadTaskRunner> task_runner,
       int render_frame_id,
-      bool is_main_frame);
+      bool is_main_frame,
+      blink::WebNavigationParams* navigation_params);
   ~NavigationBodyLoader() override;
 
  private:
@@ -76,6 +83,13 @@
   // NotifyCompletionIfAppropriate
   //   notify client about completion
 
+  NavigationBodyLoader(
+      const network::ResourceResponseHead& head,
+      network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
+      scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+      int render_frame_id,
+      mojom::ResourceLoadInfoPtr resource_load_info);
+
   // blink::WebNavigationBodyLoader
   void SetDefersLoading(bool defers) override;
   void StartLoadingBody(WebNavigationBodyLoader::Client* client,
diff --git a/content/renderer/loader/navigation_body_loader_unittest.cc b/content/renderer/loader/navigation_body_loader_unittest.cc
index adc2379..a6fc8c7 100644
--- a/content/renderer/loader/navigation_body_loader_unittest.cc
+++ b/content/renderer/loader/navigation_body_loader_unittest.cc
@@ -13,6 +13,7 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
 #include "third_party/blink/public/platform/web_navigation_body_loader.h"
+#include "third_party/blink/public/web/web_navigation_params.h"
 
 namespace content {
 
@@ -39,11 +40,13 @@
     writer_ = std::move(data_pipe_->producer_handle);
     auto endpoints = network::mojom::URLLoaderClientEndpoints::New();
     endpoints->url_loader_client = mojo::MakeRequest(&client_ptr_);
-    loader_ = std::make_unique<NavigationBodyLoader>(
+    blink::WebNavigationParams navigation_params;
+    NavigationBodyLoader::FillNavigationParamsResponseAndBodyLoader(
         CommonNavigationParams(), CommitNavigationParams(), 1 /* request_id */,
         network::ResourceResponseHead(), std::move(endpoints),
         blink::scheduler::GetSingleThreadTaskRunnerForTesting(),
-        2 /* render_frame_id */, true /* is_main_frame */);
+        2 /* render_frame_id */, true /* is_main_frame */, &navigation_params);
+    loader_ = std::move(navigation_params.body_loader);
   }
 
   void StartLoading() {
diff --git a/content/renderer/loader/request_extra_data.h b/content/renderer/loader/request_extra_data.h
index 72c12dfa..38c20dd 100644
--- a/content/renderer/loader/request_extra_data.h
+++ b/content/renderer/loader/request_extra_data.h
@@ -104,14 +104,6 @@
     block_mixed_plugin_content_ = block_mixed_plugin_content;
   }
 
-  // Indicates whether a navigation was initiated by the browser or renderer.
-  bool navigation_initiated_by_renderer() const {
-    return navigation_initiated_by_renderer_;
-  }
-  void set_navigation_initiated_by_renderer(bool navigation_by_renderer) {
-    navigation_initiated_by_renderer_ = navigation_by_renderer;
-  }
-
   // Determines whether SameSite cookies will be attached to the request
   // even when the request looks cross-site.
   bool attach_same_site_cookies() const { return attach_same_site_cookies_; }
@@ -152,7 +144,6 @@
   bool initiated_in_secure_context_ = false;
   bool is_for_no_state_prefetch_ = false;
   bool block_mixed_plugin_content_ = false;
-  bool navigation_initiated_by_renderer_ = false;
   bool attach_same_site_cookies_ = false;
   std::vector<std::unique_ptr<URLLoaderThrottle>> url_loader_throttles_;
   scoped_refptr<FrameRequestBlocker> frame_request_blocker_;
diff --git a/content/renderer/loader/resource_dispatcher.cc b/content/renderer/loader/resource_dispatcher.cc
index 64dd4b3..f395301 100644
--- a/content/renderer/loader/resource_dispatcher.cc
+++ b/content/renderer/loader/resource_dispatcher.cc
@@ -504,8 +504,7 @@
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
     std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
     std::unique_ptr<NavigationResponseOverrideParameters>
-        response_override_params,
-    base::OnceClosure* continue_navigation_function) {
+        response_override_params) {
   CheckSchemeForReferrerPolicy(*request);
 
 #if defined(OS_ANDROID)
@@ -538,23 +537,11 @@
         request_id, this, loading_task_runner,
         true /* bypass_redirect_checks */, request->url);
 
-    if (request->resource_type == RESOURCE_TYPE_SHARED_WORKER) {
-      // For shared workers, immediately post a task for continuing loading
-      // because shared workers don't have the concept of the navigation commit
-      // and |continue_navigation_function| is never called.
-      // TODO(nhiroki): Unify this case with the navigation case for code
-      // health.
-      loading_task_runner->PostTask(
-          FROM_HERE, base::BindOnce(&ResourceDispatcher::ContinueForNavigation,
-                                    weak_factory_.GetWeakPtr(), request_id));
-    } else {
-      // For navigations, |continue_navigation_function| is called after the
-      // navigation commit.
-      DCHECK(continue_navigation_function);
-      *continue_navigation_function =
-          base::BindOnce(&ResourceDispatcher::ContinueForNavigation,
-                         weak_factory_.GetWeakPtr(), request_id);
-    }
+    DCHECK_EQ(RESOURCE_TYPE_SHARED_WORKER, request->resource_type);
+    // TODO(nhiroki): it would be nice to get rid of response override.
+    loading_task_runner->PostTask(
+        FROM_HERE, base::BindOnce(&ResourceDispatcher::ContinueForNavigation,
+                                  weak_factory_.GetWeakPtr(), request_id));
     return request_id;
   }
 
@@ -631,6 +618,8 @@
   RemoteToLocalTimeTicks(converter, &renderer_info->service_worker_ready_time);
 }
 
+// TODO(dgozman): this is not used for navigation anymore, only for worker
+// main script. Rename all related entities accordingly.
 void ResourceDispatcher::ContinueForNavigation(int request_id) {
   PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
   if (!request_info)
diff --git a/content/renderer/loader/resource_dispatcher.h b/content/renderer/loader/resource_dispatcher.h
index 7f910ab0..e961ec1 100644
--- a/content/renderer/loader/resource_dispatcher.h
+++ b/content/renderer/loader/resource_dispatcher.h
@@ -127,8 +127,7 @@
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
       std::unique_ptr<NavigationResponseOverrideParameters>
-          response_override_params,
-      base::OnceClosure* continue_navigation_function);
+          response_override_params);
 
   // Removes a request from the |pending_requests_| list, returning true if the
   // request was found and removed.
diff --git a/content/renderer/loader/resource_dispatcher_unittest.cc b/content/renderer/loader/resource_dispatcher_unittest.cc
index df1a50e8..de35e851 100644
--- a/content/renderer/loader/resource_dispatcher_unittest.cc
+++ b/content/renderer/loader/resource_dispatcher_unittest.cc
@@ -148,8 +148,7 @@
         TRAFFIC_ANNOTATION_FOR_TESTS, false, false, std::move(peer),
         base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(this),
         std::vector<std::unique_ptr<URLLoaderThrottle>>(),
-        nullptr /* navigation_response_override_params */,
-        nullptr /* continue_navigation_function */);
+        nullptr /* navigation_response_override_params */);
     peer_context->request_id = request_id;
     return request_id;
   }
diff --git a/content/renderer/loader/sync_load_context.cc b/content/renderer/loader/sync_load_context.cc
index f67665a..bab4de7 100644
--- a/content/renderer/loader/sync_load_context.cc
+++ b/content/renderer/loader/sync_load_context.cc
@@ -108,8 +108,7 @@
       traffic_annotation, true /* is_sync */,
       download_to_blob /* pass_response_pipe_to_peer */,
       base::WrapUnique(context), context->url_loader_factory_,
-      std::move(throttles), nullptr /* navigation_response_override_params */,
-      nullptr /* continue_for_navigation */);
+      std::move(throttles), nullptr /* navigation_response_override_params */);
 }
 
 SyncLoadContext::SyncLoadContext(
diff --git a/content/renderer/loader/url_loader_client_impl_unittest.cc b/content/renderer/loader/url_loader_client_impl_unittest.cc
index 4b9cc2b..6e8905a 100644
--- a/content/renderer/loader/url_loader_client_impl_unittest.cc
+++ b/content/renderer/loader/url_loader_client_impl_unittest.cc
@@ -69,8 +69,7 @@
                                           &request_peer_context_),
         base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(this),
         std::vector<std::unique_ptr<URLLoaderThrottle>>(),
-        nullptr /* navigation_response_override_params */,
-        nullptr /* continue_navigation_function */);
+        nullptr /* navigation_response_override_params */);
     request_peer_context_.request_id = request_id_;
 
     base::RunLoop().RunUntilIdle();
diff --git a/content/renderer/loader/url_response_body_consumer_unittest.cc b/content/renderer/loader/url_response_body_consumer_unittest.cc
index 95954e1..5a63af0 100644
--- a/content/renderer/loader/url_response_body_consumer_unittest.cc
+++ b/content/renderer/loader/url_response_body_consumer_unittest.cc
@@ -162,8 +162,7 @@
         base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
             &factory_),
         std::vector<std::unique_ptr<URLLoaderThrottle>>(),
-        nullptr /* navigation_response_override_params */,
-        nullptr /* continue_navigation_function */);
+        nullptr /* navigation_response_override_params */);
   }
 
   void Run(TestRequestPeer::Context* context) {
diff --git a/content/renderer/loader/web_url_loader_impl.cc b/content/renderer/loader/web_url_loader_impl.cc
index 0120f9b..99521d6e 100644
--- a/content/renderer/loader/web_url_loader_impl.cc
+++ b/content/renderer/loader/web_url_loader_impl.cc
@@ -833,17 +833,11 @@
 
   TRACE_EVENT_WITH_FLOW0("loading", "WebURLLoaderImpl::Context::Start", this,
                          TRACE_EVENT_FLAG_FLOW_OUT);
-  base::OnceClosure continue_navigation_function;
   request_id_ = resource_dispatcher_->StartAsync(
       std::move(resource_request), request.RequestorID(), task_runner_,
       GetTrafficAnnotationTag(request), false /* is_sync */,
       request.PassResponsePipeToClient(), std::move(peer), url_loader_factory_,
-      std::move(throttles), std::move(response_override),
-      &continue_navigation_function);
-  if (client_) {
-    client_->SetContinueNavigationRequestCallback(
-        std::move(continue_navigation_function));
-  }
+      std::move(throttles), std::move(response_override));
 
   if (defers_loading_ != NOT_DEFERRING)
     resource_dispatcher_->SetDefersLoading(request_id_, true);
diff --git a/content/renderer/loader/web_url_loader_impl_unittest.cc b/content/renderer/loader/web_url_loader_impl_unittest.cc
index b0733a4..57ae955 100644
--- a/content/renderer/loader/web_url_loader_impl_unittest.cc
+++ b/content/renderer/loader/web_url_loader_impl_unittest.cc
@@ -90,8 +90,7 @@
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
       std::vector<std::unique_ptr<URLLoaderThrottle>> throttles,
       std::unique_ptr<NavigationResponseOverrideParameters>
-          navigation_response_override_params,
-      base::OnceClosure* continue_navigation_function) override {
+          navigation_response_override_params) override {
     EXPECT_FALSE(peer_);
     if (sync_load_response_.info.encoded_body_length != -1)
       EXPECT_TRUE(is_sync);
diff --git a/content/renderer/media/stream/audio_service_audio_processor_proxy.h b/content/renderer/media/stream/audio_service_audio_processor_proxy.h
index 374d0b3..b83007e 100644
--- a/content/renderer/media/stream/audio_service_audio_processor_proxy.h
+++ b/content/renderer/media/stream/audio_service_audio_processor_proxy.h
@@ -12,6 +12,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/synchronization/lock.h"
 #include "base/threading/thread_checker.h"
+#include "base/timer/timer.h"
 #include "content/common/content_export.h"
 #include "content/renderer/media/stream/aec_dump_message_filter.h"
 #include "media/audio/audio_processing.h"
diff --git a/content/renderer/media/stream/webmediaplayer_ms_unittest.cc b/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
index 0f21d64..22bbca9c2 100644
--- a/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
+++ b/content/renderer/media/stream/webmediaplayer_ms_unittest.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/containers/circular_deque.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
diff --git a/content/renderer/media/webrtc/webrtc_video_track_source.cc b/content/renderer/media/webrtc/webrtc_video_track_source.cc
index 7a76dac..47c2fdc 100644
--- a/content/renderer/media/webrtc/webrtc_video_track_source.cc
+++ b/content/renderer/media/webrtc/webrtc_video_track_source.cc
@@ -5,6 +5,7 @@
 #include "content/renderer/media/webrtc/webrtc_video_track_source.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/trace_event/trace_event.h"
 #include "content/renderer/media/webrtc/webrtc_video_frame_adapter.h"
 #include "third_party/libyuv/include/libyuv/scale.h"
diff --git a/content/renderer/navigation_client.cc b/content/renderer/navigation_client.cc
index 971bf1a..ee0747e 100644
--- a/content/renderer/navigation_client.cc
+++ b/content/renderer/navigation_client.cc
@@ -4,6 +4,7 @@
 
 #include "content/renderer/navigation_client.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "content/renderer/render_frame_impl.h"
 #include "third_party/blink/public/platform/task_type.h"
 
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 9c046fa..b939a926 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -111,7 +111,9 @@
 #include "content/renderer/input/widget_input_handler_manager.h"
 #include "content/renderer/installedapp/related_apps_fetcher.h"
 #include "content/renderer/internal_document_state_data.h"
+#include "content/renderer/loader/navigation_body_loader.h"
 #include "content/renderer/loader/request_extra_data.h"
+#include "content/renderer/loader/resource_dispatcher.h"
 #include "content/renderer/loader/tracked_child_url_loader_factory_bundle.h"
 #include "content/renderer/loader/web_url_loader_impl.h"
 #include "content/renderer/loader/web_url_request_util.h"
@@ -423,73 +425,63 @@
   return frame->Parent() == nullptr;
 }
 
-WebURLRequest CreateURLRequestForNavigation(
+void FillNavigationParamsRequest(
     const CommonNavigationParams& common_params,
     const CommitNavigationParams& commit_params,
-    std::unique_ptr<NavigationResponseOverrideParameters> response_override,
-    bool is_view_source_mode_enabled) {
-  // Use the original navigation url to construct the WebURLRequest. The
-  // WebURLloaderImpl will replay the redirects afterwards and will eventually
-  // commit the final url.
-  const GURL navigation_url = !commit_params.original_url.is_empty()
-                                  ? commit_params.original_url
-                                  : common_params.url;
-  const std::string navigation_method = !commit_params.original_method.empty()
-                                            ? commit_params.original_method
-                                            : common_params.method;
-  WebURLRequest request(navigation_url);
-  request.SetHTTPMethod(WebString::FromUTF8(navigation_method));
+    bool is_view_source_mode_enabled,
+    blink::WebNavigationParams* navigation_params) {
+  // Use the original navigation url to start with. We'll replay the redirects
+  // afterwards and will eventually arrive to the final url.
+  navigation_params->url = !commit_params.original_url.is_empty()
+                               ? commit_params.original_url
+                               : common_params.url;
+  navigation_params->http_method = WebString::FromLatin1(
+      !commit_params.original_method.empty() ? commit_params.original_method
+                                             : common_params.method);
 
   if (is_view_source_mode_enabled)
-    request.SetCacheMode(blink::mojom::FetchCacheMode::kForceCache);
+    navigation_params->cache_mode = blink::mojom::FetchCacheMode::kForceCache;
 
-  WebString web_referrer;
   if (common_params.referrer.url.is_valid()) {
-    web_referrer = WebSecurityPolicy::GenerateReferrerHeader(
+    WebString referrer = WebSecurityPolicy::GenerateReferrerHeader(
         common_params.referrer.policy, common_params.url,
         WebString::FromUTF8(common_params.referrer.url.spec()));
-    request.SetHTTPReferrer(web_referrer, common_params.referrer.policy);
-    if (!web_referrer.IsEmpty()) {
-      request.SetHTTPOriginIfNeeded(
-          WebSecurityOrigin(url::Origin::Create(common_params.referrer.url)));
-    }
+    navigation_params->referrer = referrer;
+    navigation_params->referrer_policy = common_params.referrer.policy;
+  }
+  if (common_params.referrer.policy !=
+      network::mojom::ReferrerPolicy::kDefault) {
+    navigation_params->referrer_policy = common_params.referrer.policy;
   }
 
   if (common_params.post_data) {
-    request.SetHTTPBody(GetWebHTTPBodyForRequestBody(*common_params.post_data));
+    navigation_params->http_body =
+        GetWebHTTPBodyForRequestBody(*common_params.post_data);
     if (!commit_params.post_content_type.empty()) {
-      request.AddHTTPHeaderField(
-          WebString::FromASCII(net::HttpRequestHeaders::kContentType),
-          WebString::FromASCII(commit_params.post_content_type));
+      navigation_params->http_content_type =
+          WebString::FromASCII(commit_params.post_content_type);
     }
   }
 
-  if (!web_referrer.IsEmpty() || common_params.referrer.policy !=
-                                     network::mojom::ReferrerPolicy::kDefault) {
-    request.SetHTTPReferrer(web_referrer, common_params.referrer.policy);
-  }
-
-  request.SetPreviewsState(
-      static_cast<WebURLRequest::PreviewsState>(common_params.previews_state));
-
-  request.SetOriginPolicy(WebString::FromUTF8(common_params.origin_policy));
+  navigation_params->previews_state =
+      static_cast<WebURLRequest::PreviewsState>(common_params.previews_state);
+  navigation_params->origin_policy =
+      WebString::FromUTF8(common_params.origin_policy);
 
   // Set the request initiator origin, which is supplied by the browser
   // process. It is present in cases such as navigating a frame in a different
   // process, which is routed through RenderFrameProxy and the origin is
   // required to correctly compute the effective origin in which the
   // navigation will commit.
-  if (common_params.initiator_origin)
-    request.SetRequestorOrigin(common_params.initiator_origin.value());
+  if (common_params.initiator_origin) {
+    navigation_params->requestor_origin =
+        common_params.initiator_origin.value();
+  }
 
-  auto extra_data = std::make_unique<RequestExtraData>();
-  extra_data->set_navigation_response_override(std::move(response_override));
-  extra_data->set_navigation_initiated_by_renderer(commit_params.nav_entry_id ==
-                                                   0);
-  request.SetExtraData(std::move(extra_data));
-  request.SetWasDiscarded(commit_params.was_discarded);
-
-  return request;
+  navigation_params->was_discarded = commit_params.was_discarded;
+#if defined(OS_ANDROID)
+  navigation_params->had_transient_activation = common_params.has_user_gesture;
+#endif
 }
 
 CommonNavigationParams MakeCommonNavigationParams(
@@ -857,6 +849,7 @@
       common_params.navigation_type ==
       FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL);
   internal_data->set_previews_state(common_params.previews_state);
+  internal_data->set_request_id(ResourceDispatcher::MakeRequestID());
   document_state->set_can_load_local_resources(
       commit_params.can_load_local_resources);
 
@@ -959,9 +952,9 @@
 
 // Fills navigation data sent by the browser to a blink understandable
 // format, blink::WebNavigationParams.
-void FillNavigationParams(const CommonNavigationParams& common_params,
-                          const CommitNavigationParams& commit_params,
-                          blink::WebNavigationParams* navigation_params) {
+void FillMiscNavigationParams(const CommonNavigationParams& common_params,
+                              const CommitNavigationParams& commit_params,
+                              blink::WebNavigationParams* navigation_params) {
   navigation_params->navigation_timings = BuildNavigationTimings(
       common_params.navigation_start, commit_params.navigation_timing,
       common_params.input_start);
@@ -2836,7 +2829,8 @@
   // Make sure we never show errors in view source mode.
   frame_->EnableViewSourceMode(false);
 
-  auto navigation_params = std::make_unique<WebNavigationParams>();
+  auto navigation_params = WebNavigationParams::CreateForErrorPage(
+      document_loader, error_html, GURL(kUnreachableWebDataURL), error.url());
   std::unique_ptr<DocumentState> document_state;
 
   if (inherit_document_state) {
@@ -2846,27 +2840,15 @@
         navigation_state->common_params(), navigation_state->commit_params(),
         base::TimeTicks(),  // Not used for failed navigation.
         CommitNavigationCallback(), nullptr, nullptr);
-    FillNavigationParams(navigation_state->common_params(),
-                         navigation_state->commit_params(),
-                         navigation_params.get());
+    FillMiscNavigationParams(navigation_state->common_params(),
+                             navigation_state->commit_params(),
+                             navigation_params.get());
   } else {
     document_state = BuildDocumentState();
   }
 
-  // Locally generated error pages should not be cached.
-  navigation_params->request = document_loader->GetRequest();
-  navigation_params->request.SetCacheMode(
-      blink::mojom::FetchCacheMode::kNoStore);
-  navigation_params->request.SetURL(GURL(kUnreachableWebDataURL));
-
   if (replace_current_item)
     navigation_params->frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
-
-  navigation_params->data = WebData(error_html.data(), error_html.length());
-  navigation_params->mime_type = "text/html";
-  navigation_params->text_encoding = "UTF-8";
-  navigation_params->unreachable_url = error.url();
-
   navigation_params->service_worker_network_provider =
       BuildServiceWorkerNetworkProviderForNavigation(nullptr, nullptr);
 
@@ -3310,7 +3292,8 @@
   navigation_params->service_worker_network_provider =
       BuildServiceWorkerNetworkProviderForNavigation(
           &commit_params, std::move(controller_service_worker_info));
-  FillNavigationParams(common_params, commit_params, navigation_params.get());
+  FillMiscNavigationParams(common_params, commit_params,
+                           navigation_params.get());
 
   // Perform a navigation to a data url if needed (for main frames).
   // Note: the base URL might be invalid, so also check the data URL string.
@@ -3323,21 +3306,23 @@
     GURL base_url;
     DecodeDataURL(common_params, commit_params, &mime_type, &charset, &data,
                   &base_url);
-    navigation_params->request = WebURLRequest(base_url);
+    navigation_params->url = base_url;
     navigation_params->data = WebData(data.c_str(), data.length());
     navigation_params->mime_type = WebString::FromUTF8(mime_type);
     navigation_params->text_encoding = WebString::FromUTF8(charset);
     // Needed so that history-url-only changes don't become reloads.
     navigation_params->unreachable_url = common_params.history_url_for_data_url;
   } else {
-    // TODO(arthursonzogni): Pass the data needed to continue the navigation
-    // directly to CommitNavigation instead of storing it in the
-    // NavigationResponseOverrideParameters. The architecture of committing the
-    // navigation in the renderer process should be simplified and avoid going
-    // through the ResourceFetcher for the main resource.
-    navigation_params->request =
-        CreateURLRequestForCommit(common_params, commit_params,
-                                  std::move(url_loader_client_endpoints), head);
+    InternalDocumentStateData* internal_data =
+        InternalDocumentStateData::FromDocumentState(document_state.get());
+    FillNavigationParamsRequest(common_params, commit_params,
+                                frame_->IsViewSourceModeEnabled(),
+                                navigation_params.get());
+    NavigationBodyLoader::FillNavigationParamsResponseAndBodyLoader(
+        common_params, commit_params, internal_data->request_id(), head,
+        std::move(url_loader_client_endpoints),
+        GetTaskRunner(blink::TaskType::kInternalLoading), GetRoutingID(),
+        !frame_->Parent(), navigation_params.get());
   }
 
   // Note: we cannot use base::AutoReset here, since |this| can be deleted
@@ -3393,9 +3378,13 @@
       has_stale_copy_in_cache ? WebURLError::HasCopyInCache::kTrue
                               : WebURLError::HasCopyInCache::kFalse,
       WebURLError::IsWebSecurityViolation::kFalse, common_params.url);
-  WebURLRequest failed_request = CreateURLRequestForNavigation(
-      common_params, commit_params,
-      /*response_override=*/nullptr, frame_->IsViewSourceModeEnabled());
+
+  auto navigation_params = std::make_unique<WebNavigationParams>();
+  FillNavigationParamsRequest(common_params, commit_params,
+                              frame_->IsViewSourceModeEnabled(),
+                              navigation_params.get());
+  navigation_params->url = GURL(kUnreachableWebDataURL);
+  navigation_params->cache_mode = blink::mojom::FetchCacheMode::kNoStore;
 
   if (!ShouldDisplayErrorPageForFailedLoad(error_code, common_params.url)) {
     // The browser expects this frame to be loading an error page. Inform it
@@ -3453,7 +3442,7 @@
     if (frame_->GetProvisionalDocumentLoader()) {
       // TODO(dgozman): why do we need to notify browser in response
       // to it's own request?
-      SendFailedProvisionalLoad(failed_request.HttpMethod().Ascii(), error,
+      SendFailedProvisionalLoad(navigation_params->http_method.Ascii(), error,
                                 frame_);
     }
   }
@@ -3464,22 +3453,17 @@
     // We don't need the actual error page content, but still call this
     // for any possible side effects.
     GetContentClient()->renderer()->PrepareErrorPage(
-        this, error, failed_request.HttpMethod().Ascii(),
-        failed_request.GetCacheMode() ==
-            blink::mojom::FetchCacheMode::kBypassCache,
-        nullptr);
+        this, error, navigation_params->http_method.Ascii(),
+        false /* ignoring_cache */, nullptr);
   } else {
     GetContentClient()->renderer()->PrepareErrorPage(
-        this, error, failed_request.HttpMethod().Ascii(),
-        failed_request.GetCacheMode() ==
-            blink::mojom::FetchCacheMode::kBypassCache,
-        &error_html);
+        this, error, navigation_params->http_method.Ascii(),
+        false /* ignoring_cache */, &error_html);
   }
 
   // Make sure we never show errors in view source mode.
   frame_->EnableViewSourceMode(false);
 
-  auto navigation_params = std::make_unique<WebNavigationParams>();
   if (history_entry) {
     navigation_params->frame_load_type = WebFrameLoadType::kBackForward;
     navigation_params->history_item = history_entry->root();
@@ -3488,11 +3472,8 @@
   }
   navigation_params->service_worker_network_provider =
       BuildServiceWorkerNetworkProviderForNavigation(&commit_params, nullptr);
-  FillNavigationParams(common_params, commit_params, navigation_params.get());
-
-  failed_request.SetURL(GURL(kUnreachableWebDataURL));
-  failed_request.SetCacheMode(blink::mojom::FetchCacheMode::kNoStore);
-  navigation_params->request = failed_request;
+  FillMiscNavigationParams(common_params, commit_params,
+                           navigation_params.get());
 
   navigation_params->data = WebData(error_html.data(), error_html.length());
   navigation_params->mime_type = "text/html";
@@ -5665,7 +5646,7 @@
           << " url:" << params->url << " origin:" << params->origin;
     }
   }
-  params->request_id = response.RequestId();
+  params->request_id = internal_data->request_id();
 
   return params;
 }
@@ -6510,38 +6491,6 @@
   Send(new FrameHostMsg_OpenURL(routing_id_, params));
 }
 
-WebURLRequest RenderFrameImpl::CreateURLRequestForCommit(
-    const CommonNavigationParams& common_params,
-    const CommitNavigationParams& commit_params,
-    network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
-    const network::ResourceResponseHead& head) {
-  // This will override the url requested by the WebURLLoader, as well as
-  // provide it with the response to the request.
-  std::unique_ptr<NavigationResponseOverrideParameters> response_override(
-      new NavigationResponseOverrideParameters());
-  response_override->url_loader_client_endpoints =
-      std::move(url_loader_client_endpoints);
-  response_override->response = head;
-  response_override->redirect_responses = commit_params.redirect_response;
-  response_override->redirect_infos = commit_params.redirect_infos;
-
-  WebURLRequest request = CreateURLRequestForNavigation(
-      common_params, commit_params, std::move(response_override),
-      frame_->IsViewSourceModeEnabled());
-  request.SetFrameType(IsTopLevelNavigation(frame_)
-                           ? network::mojom::RequestContextFrameType::kTopLevel
-                           : network::mojom::RequestContextFrameType::kNested);
-  request.SetRequestorID(render_view_->GetRoutingID());
-  static_cast<RequestExtraData*>(request.GetExtraData())
-      ->set_render_frame_id(routing_id_);
-
-#if defined(OS_ANDROID)
-  request.SetHasUserGesture(common_params.has_user_gesture);
-#endif
-
-  return request;
-}
-
 ChildURLLoaderFactoryBundle* RenderFrameImpl::GetLoaderFactoryBundle() {
   if (!loader_factories_) {
     RenderFrameImpl* creator = RenderFrameImpl::FromWebFrame(
@@ -7109,7 +7058,7 @@
                                      const GURL& unreachable_url,
                                      bool replace_current_item) {
   auto navigation_params = std::make_unique<WebNavigationParams>();
-  navigation_params->request = WebURLRequest(base_url);
+  navigation_params->url = base_url;
   navigation_params->data = WebData(html.data(), html.length());
   navigation_params->mime_type = "text/html";
   navigation_params->text_encoding = WebString::FromUTF8(text_encoding);
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index cded661..770d61e8 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -1121,13 +1121,6 @@
   void OpenURL(std::unique_ptr<blink::WebNavigationInfo> info,
                bool is_history_navigation_in_new_child);
 
-  // Creates a WebURLRequest to use fo the commit of a navigation.
-  blink::WebURLRequest CreateURLRequestForCommit(
-      const CommonNavigationParams& common_params,
-      const CommitNavigationParams& commit_params,
-      network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
-      const network::ResourceResponseHead& head);
-
   // Returns a ChildURLLoaderFactoryBundle which can be used to request
   // subresources for this frame.
   // For frames with committed navigations, this bundle is created with the
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 56a50baa..ad1fa7d 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -13,6 +13,7 @@
 #include "base/allocator/allocator_extension.h"
 #include "base/at_exit.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/lazy_instance.h"
 #include "base/logging.h"
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index b3082416..c6c5d9c 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -12,6 +12,7 @@
 #include "base/auto_reset.h"
 #include "base/base_switches.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/logging.h"
diff --git a/content/renderer/render_widget_unittest.cc b/content/renderer/render_widget_unittest.cc
index 0c4238f..07dc9b1 100644
--- a/content/renderer/render_widget_unittest.cc
+++ b/content/renderer/render_widget_unittest.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/optional.h"
 #include "base/run_loop.h"
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
index 7ddfb2a..b5694510 100644
--- a/content/renderer/service_worker/service_worker_context_client.cc
+++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/debug/alias.h"
 #include "base/feature_list.h"
 #include "base/lazy_instance.h"
diff --git a/content/renderer/service_worker/service_worker_timeout_timer_unittest.cc b/content/renderer/service_worker/service_worker_timeout_timer_unittest.cc
index e734fed..30ae57e 100644
--- a/content/renderer/service_worker/service_worker_timeout_timer_unittest.cc
+++ b/content/renderer/service_worker/service_worker_timeout_timer_unittest.cc
@@ -5,6 +5,7 @@
 #include "content/renderer/service_worker/service_worker_timeout_timer.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/memory/ref_counted.h"
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
diff --git a/content/shell/renderer/web_test/blink_test_runner.cc b/content/shell/renderer/web_test/blink_test_runner.cc
index 3f38c221..a643e986 100644
--- a/content/shell/renderer/web_test/blink_test_runner.cc
+++ b/content/shell/renderer/web_test/blink_test_runner.cc
@@ -679,11 +679,6 @@
   ForceTextInputStateUpdateForRenderFrame(RenderFrame::FromWebFrame(frame));
 }
 
-bool BlinkTestRunner::IsNavigationInitiatedByRenderer(
-    const WebURLRequest& request) {
-  return content::IsNavigationInitiatedByRenderer(request);
-}
-
 bool BlinkTestRunner::AddMediaStreamVideoSourceAndTrack(
     blink::WebMediaStream* stream) {
   DCHECK(stream);
diff --git a/content/shell/renderer/web_test/blink_test_runner.h b/content/shell/renderer/web_test/blink_test_runner.h
index 02127d2e..392ca7b1 100644
--- a/content/shell/renderer/web_test/blink_test_runner.h
+++ b/content/shell/renderer/web_test/blink_test_runner.h
@@ -30,7 +30,6 @@
 }
 
 namespace blink {
-class WebURLRequest;
 class WebView;
 }  // namespace blink
 
@@ -147,8 +146,6 @@
   float GetDeviceScaleFactor() const override;
   void RunIdleTasks(base::OnceClosure callback) override;
   void ForceTextInputStateUpdate(blink::WebLocalFrame* frame) override;
-  bool IsNavigationInitiatedByRenderer(
-      const blink::WebURLRequest& request) override;
 
   // Resets a RenderView to a known state for web tests. It is used both when
   // a RenderView is created and when reusing an existing RenderView for the
diff --git a/content/shell/test_runner/web_frame_test_client.cc b/content/shell/test_runner/web_frame_test_client.cc
index 5d43e24..4da5a48 100644
--- a/content/shell/test_runner/web_frame_test_client.cc
+++ b/content/shell/test_runner/web_frame_test_client.cc
@@ -421,12 +421,6 @@
 }
 
 void WebFrameTestClient::WillSendRequest(blink::WebURLRequest& request) {
-  // PlzNavigate
-  // Navigation requests initiated by the renderer will have been logged when
-  // the navigation was sent to the browser. Please see
-  // the RenderFrameImpl::BeginNavigation() function.
-  if (delegate_->IsNavigationInitiatedByRenderer(request))
-    return;
   // Need to use GURL for host() and SchemeIs()
   GURL url = request.Url();
   std::string request_url = url.possibly_invalid_spec();
@@ -551,8 +545,6 @@
 
 bool WebFrameTestClient::ShouldContinueNavigation(
     const blink::WebNavigationInfo& info) {
-  DCHECK(!delegate_->IsNavigationInitiatedByRenderer(info.url_request));
-
   if (test_runner()->shouldDumpNavigationPolicy()) {
     delegate_->PrintMessage(
         "Default policy for navigation to '" +
diff --git a/content/shell/test_runner/web_test_delegate.h b/content/shell/test_runner/web_test_delegate.h
index 656027e..8b6457b 100644
--- a/content/shell/test_runner/web_test_delegate.h
+++ b/content/shell/test_runner/web_test_delegate.h
@@ -32,7 +32,6 @@
 class WebPlugin;
 struct WebPluginParams;
 struct WebSize;
-class WebURLRequest;
 class WebView;
 }
 
@@ -262,11 +261,6 @@
   // associated with |frame|.
   virtual void ForceTextInputStateUpdate(blink::WebLocalFrame* frame) = 0;
 
-  // PlzNavigate
-  // Indicates if the navigation was initiated by the browser or renderer.
-  virtual bool IsNavigationInitiatedByRenderer(
-      const blink::WebURLRequest& request) = 0;
-
  protected:
   virtual ~WebTestDelegate() {}
 };
diff --git a/content/test/gpu/gpu_tests/pixel_expectations.py b/content/test/gpu/gpu_tests/pixel_expectations.py
index f6bdf1a3..1c9600e5 100644
--- a/content/test/gpu/gpu_tests/pixel_expectations.py
+++ b/content/test/gpu/gpu_tests/pixel_expectations.py
@@ -27,7 +27,8 @@
     self.Skip('Pixel_OffscreenCanvasWebGLSoftwareCompositingWorker',
               ['android'])
     self.Skip('Pixel_CanvasDisplayLinearRGBUnaccelerated2D', ['android'])
-    self.Skip('Pixel_CanvasUnacceleratedLowLatency2D', ['android'])
+    # Disable temporarily to avoid a collision, https://crbug.com/922218
+    #self.Skip('Pixel_CanvasUnacceleratedLowLatency2D', ['android'])
     self.Skip('Pixel_RepeatedWebGLTo2D_SoftwareCompositing', ['android'])
 
     # Tests running with SwiftShader are skipped on platforms where SwiftShader
@@ -137,5 +138,5 @@
         ['mac', ('amd', 0x679e)], bug=911413)
 
     # TODO(mcasas): re-enable after rebaselining, https://crbug.com/922218
-    self.Fail('Pixel_CanvasLowLatency2D', ['mac'], bug=922218)
-    self.Fail('Pixel_CanvasUnacceleratedLowLatency2D', ['mac'], bug=922218)
+    self.Fail('Pixel_CanvasLowLatency2D', bug=922218)
+    self.Fail('Pixel_CanvasUnacceleratedLowLatency2D', bug=922218)
diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py
index a89697c8..78a4d67c 100644
--- a/content/test/gpu/gpu_tests/pixel_test_pages.py
+++ b/content/test/gpu/gpu_tests/pixel_test_pages.py
@@ -857,14 +857,14 @@
       'pixel_canvas_low_latency_2d.html',
       base_name + '_CanvasLowLatency2D',
       test_rect=[0, 0, 100, 100],
-      revision=5,
+      revision=6,
       browser_args=browser_args),
 
     PixelTestPage(
       'pixel_canvas_low_latency_2d.html',
       base_name + '_CanvasUnacceleratedLowLatency2D',
       test_rect=[0, 0, 100, 100],
-      revision=2,
+      revision=3,
       browser_args=browser_args + unaccelerated_args),
 
     PixelTestPage(
diff --git a/content/test/navigation_simulator_unittest.cc b/content/test/navigation_simulator_unittest.cc
index 6b9f576..1699394 100644
--- a/content/test/navigation_simulator_unittest.cc
+++ b/content/test/navigation_simulator_unittest.cc
@@ -10,6 +10,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/memory/scoped_refptr.h"
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc
index f86ccce..72791325 100644
--- a/content/test/test_render_frame.cc
+++ b/content/test/test_render_frame.cc
@@ -8,6 +8,7 @@
 #include <utility>
 #include <vector>
 
+#include "base/bind_helpers.h"
 #include "base/debug/stack_trace.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
@@ -269,7 +270,7 @@
     // going through browser process in this case.
     GURL url = info->url_request.Url();
     auto navigation_params = std::make_unique<blink::WebNavigationParams>();
-    navigation_params->request = blink::WebURLRequest(url);
+    navigation_params->url = url;
     if (!url.IsAboutBlank() && url != content::kAboutSrcDocURL) {
       std::string mime_type, charset, data;
       bool success = net::DataURL::Parse(url, &mime_type, &charset, &data);
diff --git a/content/test/web_test_support.cc b/content/test/web_test_support.cc
index 451a022..cbc43d75 100644
--- a/content/test/web_test_support.cc
+++ b/content/test/web_test_support.cc
@@ -560,10 +560,4 @@
   render_widget->ShowVirtualKeyboard();
 }
 
-bool IsNavigationInitiatedByRenderer(const blink::WebURLRequest& request) {
-  RequestExtraData* extra_data =
-      static_cast<RequestExtraData*>(request.GetExtraData());
-  return extra_data && extra_data->navigation_initiated_by_renderer();
-}
-
 }  // namespace content
diff --git a/content/utility/utility_thread_impl.cc b/content/utility/utility_thread_impl.cc
index 8e0eea1..80b9da23 100644
--- a/content/utility/utility_thread_impl.cc
+++ b/content/utility/utility_thread_impl.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "build/build_config.h"
 #include "content/child/child_process.h"
diff --git a/device/fido/ble/fido_ble_device.cc b/device/fido/ble/fido_ble_device.cc
index da6a3a1..46b5681 100644
--- a/device/fido/ble/fido_ble_device.cc
+++ b/device/fido/ble/fido_ble_device.cc
@@ -7,6 +7,7 @@
 #include <bitset>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/strings/string_piece.h"
 #include "components/apdu/apdu_response.h"
 #include "device/bluetooth/bluetooth_uuid.h"
diff --git a/device/usb/usb_device_handle_impl.cc b/device/usb/usb_device_handle_impl.cc
index b870832..f55bdde9 100644
--- a/device/usb/usb_device_handle_impl.cc
+++ b/device/usb/usb_device_handle_impl.cc
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/location.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted_memory.h"
diff --git a/device/usb/usb_service_impl.cc b/device/usb/usb_service_impl.cc
index e302052..3b826ca 100644
--- a/device/usb/usb_service_impl.cc
+++ b/device/usb/usb_service_impl.cc
@@ -13,6 +13,7 @@
 
 #include "base/barrier_closure.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/location.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/memory/weak_ptr.h"
diff --git a/device/vr/vr_device_base_unittest.cc b/device/vr/vr_device_base_unittest.cc
index 339505d..5b1f696 100644
--- a/device/vr/vr_device_base_unittest.cc
+++ b/device/vr/vr_device_base_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "device/vr/public/mojom/vr_service.mojom.h"
diff --git a/docs/security/mojo.md b/docs/security/mojo.md
index 8dd1010..c6d2cd4 100644
--- a/docs/security/mojo.md
+++ b/docs/security/mojo.md
@@ -192,6 +192,27 @@
 > performs the appropriate sanitizations and recommend its usage directly here.
 
 
+### Validate privilege-presuming data received over IPC
+
+If it is not possible to avoid sending privilege-presuming data over IPC (see
+the previous section), then such data should be verified before being used.
+
+* Browser process:
+    - Use `ChildProcessSecurityPolicy`'s methods like
+      `CanAccessDataForOrigin` or `CanReadFile` to verify IPC messages
+      received from less privileged processes.
+    - When verification fails, ignore the IPC and terminate the renderer process
+      using `mojo::ReportBadMessage` (or using `mojo::GetBadMessageCallback` for
+      messages handled asynchronously).  For legacy IPC, the renderer process
+      may be terminated by calling the `ReceivedBadMessage` function (separate
+      implementations exist for `//content`, `//chrome` and other layers).
+
+* NetworkService process:
+    - Do not trust `network::ResourceRequest::request_initiator` - verify it
+      using `VerifyRequestInitiatorLock` and fall back to a fail-safe origin
+      (e.g. an opaque origin) when verification fails.
+
+
 ### Do not define unused or unimplemented things
 
 Mojo interfaces often cross privilege boundaries. Having well-defined interfaces
@@ -779,4 +800,4 @@
 [security-tips-for-ipc]: https://www.chromium.org/Home/chromium-security/education/security-tips-for-ipc
 [NfcTypeConverter.java]: https://chromium.googlesource.com/chromium/src/+/e97442ee6e8c4cf6bcf7f5623c6fb2cc8cce92ac/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcTypeConverter.java
 [mojo-doc-process-crashes]: https://chromium.googlesource.com/chromium/src/+/master/mojo/public/cpp/bindings#Best-practices-for-dealing-with-process-crashes-and-callbacks
-[serialize-struct-tm-safely]: https://chromium-review.googlesource.com/c/chromium/src/+/679441
\ No newline at end of file
+[serialize-struct-tm-safely]: https://chromium-review.googlesource.com/c/chromium/src/+/679441
diff --git a/docs/vscode.md b/docs/vscode.md
index 13708e82..3d6f588 100644
--- a/docs/vscode.md
+++ b/docs/vscode.md
@@ -55,19 +55,40 @@
 Code does not require project or solution files. However, it does store
 workspace settings in a `.vscode` folder in your base directory.
 
-### Git on Windows
+
+### Fixes for Known Issues
+
+#### Git on Windows
 
 If you only have the `depot_tools` Git installed on your machine, even though it
 is in your PATH, VS Code will ignore it as it seems to be looking for `git.exe`.
 You will have to add the following to your settings in order for the Git
 integration to work:
 
-```
+```json
 {
   "git.path": "C:\\src\\depot_tools\\git.bat"
 }
 ```
 
+#### Rendering of underscore on Linux
+
+As mentioned in [#35901](https://github.com/Microsoft/vscode/issues/35901), VS
+Code will not show underscore (`_`) properly on Linux by default. You can work
+around this issue by forcing another font such as the default `monospace` or
+changing the font size in your settings:
+
+```json
+{
+  // If you want to use the default "monospace" font:
+  //"terminal.integrated.fontFamily": "monospace"
+  // If you would rather just increase the size of the font:
+  //"terminal.integrated.fontSize": 15
+  // If you would rather decrease the size of the font:
+  //"terminal.integrated.fontSize": 15
+}
+```
+
 ### Useful Extensions
 
 Up to now, you have a basic version of VS Code without much language support.
diff --git a/extensions/browser/api/bluetooth/bluetooth_event_router_unittest.cc b/extensions/browser/api/bluetooth/bluetooth_event_router_unittest.cc
index 144e8c6..4664505 100644
--- a/extensions/browser/api/bluetooth/bluetooth_event_router_unittest.cc
+++ b/extensions/browser/api/bluetooth/bluetooth_event_router_unittest.cc
@@ -8,6 +8,7 @@
 #include <string>
 #include <utility>
 
+#include "base/bind_helpers.h"
 #include "base/memory/ref_counted.h"
 #include "base/run_loop.h"
 #include "content/public/test/test_browser_context.h"
diff --git a/extensions/browser/api/device_permissions_prompt.cc b/extensions/browser/api/device_permissions_prompt.cc
index eee0f08..a8c2b12 100644
--- a/extensions/browser/api/device_permissions_prompt.cc
+++ b/extensions/browser/api/device_permissions_prompt.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/i18n/message_formatter.h"
 #include "base/scoped_observer.h"
 #include "base/strings/stringprintf.h"
diff --git a/extensions/browser/api/lock_screen_data/lock_screen_value_store_migrator_impl_unittest.cc b/extensions/browser/api/lock_screen_data/lock_screen_value_store_migrator_impl_unittest.cc
index a42299b..157cd97f0 100644
--- a/extensions/browser/api/lock_screen_data/lock_screen_value_store_migrator_impl_unittest.cc
+++ b/extensions/browser/api/lock_screen_data/lock_screen_value_store_migrator_impl_unittest.cc
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ref_counted.h"
diff --git a/extensions/browser/api/power/power_api.cc b/extensions/browser/api/power/power_api.cc
index f756b43..264aa906 100644
--- a/extensions/browser/api/power/power_api.cc
+++ b/extensions/browser/api/power/power_api.cc
@@ -5,6 +5,7 @@
 #include "extensions/browser/api/power/power_api.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/lazy_instance.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/service_manager_connection.h"
diff --git a/extensions/browser/api/system_network/system_network_api.cc b/extensions/browser/api/system_network/system_network_api.cc
index d9ab819..d32585d2 100644
--- a/extensions/browser/api/system_network/system_network_api.cc
+++ b/extensions/browser/api/system_network/system_network_api.cc
@@ -7,20 +7,13 @@
 #include "base/bind.h"
 #include "base/task/post_task.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/network_service_instance.h"
+#include "services/network/public/mojom/network_service.mojom.h"
 
 namespace {
+
 const char kNetworkListError[] = "Network lookup failed or unsupported";
 
-std::unique_ptr<net::NetworkInterfaceList> GetListOnBlockingTaskRunner() {
-  auto interface_list = std::make_unique<net::NetworkInterfaceList>();
-  if (net::GetNetworkList(interface_list.get(),
-                          net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES)) {
-    return interface_list;
-  }
-
-  return nullptr;
-}
-
 }  // namespace
 
 namespace extensions {
@@ -37,20 +30,18 @@
 ExtensionFunction::ResponseAction
 SystemNetworkGetNetworkInterfacesFunction::Run() {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  constexpr base::TaskTraits kTraits = {
-      base::MayBlock(), base::TaskPriority::USER_VISIBLE,
-      base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN};
-  using Self = SystemNetworkGetNetworkInterfacesFunction;
-  base::PostTaskWithTraitsAndReplyWithResult(
-      FROM_HERE, kTraits, base::BindOnce(&GetListOnBlockingTaskRunner),
-      base::BindOnce(&Self::SendResponseOnUIThread, this));
+  content::GetNetworkService()->GetNetworkList(
+      net::INCLUDE_HOST_SCOPE_VIRTUAL_INTERFACES,
+      base::BindOnce(
+          &SystemNetworkGetNetworkInterfacesFunction::SendResponseOnUIThread,
+          this));
   return RespondLater();
 }
 
 void SystemNetworkGetNetworkInterfacesFunction::SendResponseOnUIThread(
-    std::unique_ptr<net::NetworkInterfaceList> interface_list) {
+    const base::Optional<net::NetworkInterfaceList>& interface_list) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-  if (!interface_list) {
+  if (!interface_list.has_value()) {
     Respond(Error(kNetworkListError));
     return;
   }
diff --git a/extensions/browser/api/system_network/system_network_api.h b/extensions/browser/api/system_network/system_network_api.h
index 385fed4..15ddabb 100644
--- a/extensions/browser/api/system_network/system_network_api.h
+++ b/extensions/browser/api/system_network/system_network_api.h
@@ -30,7 +30,7 @@
 
  private:
   void SendResponseOnUIThread(
-      std::unique_ptr<net::NetworkInterfaceList> interface_list);
+      const base::Optional<net::NetworkInterfaceList>& interface_list);
 };
 
 }  // namespace api
diff --git a/extensions/browser/content_verifier.cc b/extensions/browser/content_verifier.cc
index 9accb2f..36fc369 100644
--- a/extensions/browser/content_verifier.cc
+++ b/extensions/browser/content_verifier.cc
@@ -9,6 +9,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_path.h"
 #include "base/memory/weak_ptr.h"
 #include "base/metrics/histogram_macros.h"
diff --git a/extensions/browser/content_verify_job_unittest.cc b/extensions/browser/content_verify_job_unittest.cc
index fc3e0da2..2162fda 100644
--- a/extensions/browser/content_verify_job_unittest.cc
+++ b/extensions/browser/content_verify_job_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
diff --git a/extensions/browser/extension_registrar.cc b/extensions/browser/extension_registrar.cc
index 8eb3870..1f7782a 100644
--- a/extensions/browser/extension_registrar.cc
+++ b/extensions/browser/extension_registrar.cc
@@ -5,6 +5,7 @@
 #include "extensions/browser/extension_registrar.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/stl_util.h"
diff --git a/extensions/browser/service_worker_manager.cc b/extensions/browser/service_worker_manager.cc
index f8cf87ee..9fa18be 100644
--- a/extensions/browser/service_worker_manager.cc
+++ b/extensions/browser/service_worker_manager.cc
@@ -5,6 +5,7 @@
 #include "extensions/browser/service_worker_manager.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/service_worker_context.h"
 #include "content/public/browser/storage_partition.h"
diff --git a/extensions/common/image_util.cc b/extensions/common/image_util.cc
index 7e5ab41..841950fc 100644
--- a/extensions/common/image_util.cc
+++ b/extensions/common/image_util.cc
@@ -233,7 +233,7 @@
   constexpr unsigned int kThreshold = 7;
   // The minimum "percent" of pixels that must be visible for the icon to be
   // considered OK.
-  constexpr double kMinPercentVisiblePixels = 0.05;
+  constexpr double kMinPercentVisiblePixels = 0.03;
   const int total_pixels = icon.height() * icon.width();
   // Pre-calculate the minimum number of visible pixels so we can exit early.
   // Since we expect most icons to be visible, this will perform better for
@@ -246,11 +246,8 @@
   // values against the threshold. Any pixel with a value greater than the
   // threshold is considered visible.
   SkBitmap bitmap;
-  bitmap.allocN32Pixels(icon.width(), icon.height());
-  bitmap.eraseColor(background_color);
-  SkCanvas offscreen(bitmap);
-  offscreen.drawImage(SkImage::MakeFromBitmap(icon), 0, 0);
-  offscreen.drawColor(background_color, SkBlendMode::kDifference);
+  RenderIconForVisibilityAnalysis(icon, background_color, &bitmap);
+
   int visible_pixels = 0;
   for (int x = 0; x < icon.width(); ++x) {
     for (int y = 0; y < icon.height(); ++y) {
@@ -266,6 +263,18 @@
   return false;
 }
 
+void RenderIconForVisibilityAnalysis(const SkBitmap& icon,
+                                     SkColor background_color,
+                                     SkBitmap* rendered_icon) {
+  DCHECK(rendered_icon);
+  DCHECK(rendered_icon->empty());
+  rendered_icon->allocN32Pixels(icon.width(), icon.height());
+  rendered_icon->eraseColor(background_color);
+  SkCanvas offscreen(*rendered_icon);
+  offscreen.drawImage(SkImage::MakeFromBitmap(icon), 0, 0);
+  offscreen.drawColor(background_color, SkBlendMode::kDifference);
+}
+
 bool IsRenderedIconAtPathSufficientlyVisible(const base::FilePath& path,
                                              SkColor background_color) {
   SkBitmap icon;
diff --git a/extensions/common/image_util.h b/extensions/common/image_util.h
index 7501780..31bc54b 100644
--- a/extensions/common/image_util.h
+++ b/extensions/common/image_util.h
@@ -59,6 +59,12 @@
 bool IsRenderedIconAtPathSufficientlyVisible(const base::FilePath& path,
                                              SkColor background_color);
 
+// Renders the icon bitmap onto another bitmap, combining it with the specified
+// background color. The output bitmap must be empty.
+void RenderIconForVisibilityAnalysis(const SkBitmap& icon,
+                                     SkColor background_color,
+                                     SkBitmap* rendered_icon);
+
 // Load a PNG image from a file into the destination bitmap.
 bool LoadPngFromFile(const base::FilePath& path, SkBitmap* dst);
 
diff --git a/fuchsia/BUILD.gn b/fuchsia/BUILD.gn
index e681ba0a..43194bc 100644
--- a/fuchsia/BUILD.gn
+++ b/fuchsia/BUILD.gn
@@ -336,7 +336,7 @@
     "license_file",
     rebase_path(_license_path, root_build_dir),
     "--gn-target",
-    "//fuchsia:webrunner_pkg",
+    "//fuchsia/runners:web_runner_pkg",
     "--gn-out-dir",
     ".",
   ]
diff --git a/google_apis/drive/drive_api_requests_unittest.cc b/google_apis/drive/drive_api_requests_unittest.cc
index c40f6ca5..486e92c 100644
--- a/google_apis/drive/drive_api_requests_unittest.cc
+++ b/google_apis/drive/drive_api_requests_unittest.cc
@@ -11,6 +11,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
index f952b5d..82a959d 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
@@ -20,6 +20,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/callback_helpers.h"
 #include "base/containers/flat_set.h"
diff --git a/gpu/command_buffer/service/gpu_command_buffer_memory_tracker.h b/gpu/command_buffer/service/gpu_command_buffer_memory_tracker.h
index d40df9d..aa85412 100644
--- a/gpu/command_buffer/service/gpu_command_buffer_memory_tracker.h
+++ b/gpu/command_buffer/service/gpu_command_buffer_memory_tracker.h
@@ -8,6 +8,7 @@
 #include "base/macros.h"
 #include "base/memory/memory_pressure_listener.h"
 #include "base/single_thread_task_runner.h"
+#include "base/timer/timer.h"
 #include "gpu/command_buffer/common/command_buffer_id.h"
 #include "gpu/command_buffer/common/context_creation_attribs.h"
 #include "gpu/command_buffer/service/memory_tracking.h"
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index a2c1c321..c000932 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -1210,6 +1210,14 @@
       process_pos += size;
       cmd_data += size;
     }
+
+#if defined(OS_MACOSX)
+    if (!flush_workaround_disabled_for_test_) {
+      if (gr_context())
+        gr_context()->flush();
+      api()->glFlushFn();
+    }
+#endif
   }
 
   *entries_processed = process_pos;
diff --git a/gpu/command_buffer/service/raster_decoder_unittest_base.cc b/gpu/command_buffer/service/raster_decoder_unittest_base.cc
index 7c953e1c..d8a4c8e 100644
--- a/gpu/command_buffer/service/raster_decoder_unittest_base.cc
+++ b/gpu/command_buffer/service/raster_decoder_unittest_base.cc
@@ -12,6 +12,7 @@
 #include <string>
 #include <vector>
 
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
diff --git a/gpu/ipc/service/image_transport_surface_overlay_mac.mm b/gpu/ipc/service/image_transport_surface_overlay_mac.mm
index 3884df87..54e8912 100644
--- a/gpu/ipc/service/image_transport_surface_overlay_mac.mm
+++ b/gpu/ipc/service/image_transport_surface_overlay_mac.mm
@@ -7,6 +7,7 @@
 #include <sstream>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm
index f54fd4196..54809b26 100644
--- a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm
+++ b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_io_data.mm
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/stl_util.h"
diff --git a/ios/chrome/browser/browser_state/test_chrome_browser_state.mm b/ios/chrome/browser/browser_state/test_chrome_browser_state.mm
index febb1e0..3de87eb 100644
--- a/ios/chrome/browser/browser_state/test_chrome_browser_state.mm
+++ b/ios/chrome/browser/browser_state/test_chrome_browser_state.mm
@@ -6,6 +6,7 @@
 
 #include "base/base_paths.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_util.h"
 #include "base/location.h"
 #include "base/logging.h"
diff --git a/ios/chrome/browser/net/cookie_util.mm b/ios/chrome/browser/net/cookie_util.mm
index 7582d21..3192182 100644
--- a/ios/chrome/browser/net/cookie_util.mm
+++ b/ios/chrome/browser/net/cookie_util.mm
@@ -10,6 +10,7 @@
 #include <sys/sysctl.h>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "base/memory/ref_counted.h"
 #include "base/task/post_task.h"
diff --git a/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory_util.cc b/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory_util.cc
index a255edf..55e3b6c 100644
--- a/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory_util.cc
+++ b/ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory_util.cc
@@ -15,6 +15,7 @@
 #include "base/task/post_task.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/default_clock.h"
+#include "base/timer/timer.h"
 #include "base/values.h"
 #include "components/image_fetcher/core/image_decoder.h"
 #include "components/image_fetcher/core/image_fetcher.h"
diff --git a/ios/chrome/browser/signin/ios_chrome_signin_client.h b/ios/chrome/browser/signin/ios_chrome_signin_client.h
index b19165df..d358d63 100644
--- a/ios/chrome/browser/signin/ios_chrome_signin_client.h
+++ b/ios/chrome/browser/signin/ios_chrome_signin_client.h
@@ -49,7 +49,7 @@
       content_settings::Observer* observer) override;
   void RemoveContentSettingsObserver(
       content_settings::Observer* observer) override;
-  void DelayNetworkCall(const base::Closure& callback) override;
+  void DelayNetworkCall(base::OnceClosure callback) override;
 
  private:
 
diff --git a/ios/chrome/browser/signin/ios_chrome_signin_client.mm b/ios/chrome/browser/signin/ios_chrome_signin_client.mm
index 1ea733a..b685e3f7 100644
--- a/ios/chrome/browser/signin/ios_chrome_signin_client.mm
+++ b/ios/chrome/browser/signin/ios_chrome_signin_client.mm
@@ -86,8 +86,8 @@
   host_content_settings_map_->RemoveObserver(observer);
 }
 
-void IOSChromeSigninClient::DelayNetworkCall(const base::Closure& callback) {
-  network_callback_helper_->HandleCallback(callback);
+void IOSChromeSigninClient::DelayNetworkCall(base::OnceClosure callback) {
+  network_callback_helper_->HandleCallback(std::move(callback));
 }
 
 std::unique_ptr<GaiaAuthFetcher> IOSChromeSigninClient::CreateGaiaAuthFetcher(
diff --git a/ios/chrome/browser/sync/ios_chrome_profile_sync_test_util.cc b/ios/chrome/browser/sync/ios_chrome_profile_sync_test_util.cc
index b6f1852..82c3390d 100644
--- a/ios/chrome/browser/sync/ios_chrome_profile_sync_test_util.cc
+++ b/ios/chrome/browser/sync/ios_chrome_profile_sync_test_util.cc
@@ -7,6 +7,7 @@
 #include <string>
 #include <utility>
 
+#include "base/bind_helpers.h"
 #include "components/browser_sync/profile_sync_service_mock.h"
 #include "components/browser_sync/profile_sync_test_util.h"
 #include "ios/chrome/browser/browser_state/chrome_browser_state.h"
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h
index a310f787..352c908 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h
+++ b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.h
@@ -91,8 +91,6 @@
   void OnRevertTemporaryText() override {}
   gfx::NativeView GetNativeView() const override;
   gfx::NativeView GetRelativeWindowForPopup() const override;
-  int GetTextWidth() const override;
-  int GetWidth() const override;
 
   // AutocompleteTextFieldDelegate methods
   void OnDidBeginEditing();
diff --git a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm
index e39d75fc..0f79493 100644
--- a/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm
+++ b/ios/chrome/browser/ui/omnibox/omnibox_view_ios.mm
@@ -392,15 +392,6 @@
   return nullptr;
 }
 
-int OmniboxViewIOS::GetTextWidth() const {
-  return 0;
-}
-
-// TODO(crbug.com/329527): [Merge r241107] implement OmniboxViewIOS::GetWidth().
-int OmniboxViewIOS::GetWidth() const {
-  return 0;
-}
-
 void OmniboxViewIOS::OnDidBeginEditing() {
   // Reset the changed flag.
   omnibox_interacted_while_focused_ = NO;
diff --git a/ios/chrome/browser/ui/webui/inspect/inspect_ui.mm b/ios/chrome/browser/ui/webui/inspect/inspect_ui.mm
index 5433edb0..8923dbd 100644
--- a/ios/chrome/browser/ui/webui/inspect/inspect_ui.mm
+++ b/ios/chrome/browser/ui/webui/inspect/inspect_ui.mm
@@ -186,6 +186,15 @@
     web::WebState* web_state,
     web::WebFrame* sender_frame,
     const JavaScriptConsoleMessage& message) {
+  web::WebFrame* inspect_ui_main_frame =
+      web::GetMainWebFrame(web_ui()->GetWebState());
+  if (!inspect_ui_main_frame) {
+    // Disable logging and drop this message because the main frame no longer
+    // exists.
+    SetLoggingEnabled(false);
+    return;
+  }
+
   std::vector<base::Value> params;
   web::WebFrame* main_web_frame = web::GetMainWebFrame(web_state);
   params.push_back(base::Value(main_web_frame->GetFrameId()));
@@ -194,8 +203,8 @@
   params.push_back(base::Value(message.level));
   params.push_back(message.message->Clone());
 
-  web::GetMainWebFrame(web_ui()->GetWebState())
-      ->CallJavaScriptFunction("inspectWebUI.logMessageReceived", params);
+  inspect_ui_main_frame->CallJavaScriptFunction(
+      "inspectWebUI.logMessageReceived", params);
 }
 
 void InspectDOMHandler::SetDelegateForWebStatesInTabModel(
diff --git a/ios/chrome/browser/web_data_service_factory.cc b/ios/chrome/browser/web_data_service_factory.cc
index 2132d4b..98eddb5c 100644
--- a/ios/chrome/browser/web_data_service_factory.cc
+++ b/ios/chrome/browser/web_data_service_factory.cc
@@ -5,6 +5,7 @@
 #include "ios/chrome/browser/web_data_service_factory.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
 #include "base/no_destructor.h"
diff --git a/ios/net/crn_http_protocol_handler.mm b/ios/net/crn_http_protocol_handler.mm
index de41dc8..d3936a8 100644
--- a/ios/net/crn_http_protocol_handler.mm
+++ b/ios/net/crn_http_protocol_handler.mm
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/mac/foundation_util.h"
diff --git a/ios/web/net/request_tracker_impl.mm b/ios/web/net/request_tracker_impl.mm
index 92e71ac6..726a64c7 100644
--- a/ios/web/net/request_tracker_impl.mm
+++ b/ios/web/net/request_tracker_impl.mm
@@ -9,6 +9,7 @@
 #include <stdint.h>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "base/macros.h"
 #include "base/strings/sys_string_conversions.h"
diff --git a/ios/web/service_manager_connection_impl_unittest.cc b/ios/web/service_manager_connection_impl_unittest.cc
index 8935073..3711a1f3 100644
--- a/ios/web/service_manager_connection_impl_unittest.cc
+++ b/ios/web/service_manager_connection_impl_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "ios/web/service_manager_connection_impl.h"
 
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/task/post_task.h"
 #include "base/test/bind_test_util.h"
diff --git a/ios/web_view/internal/cwv_web_view.mm b/ios/web_view/internal/cwv_web_view.mm
index 1c4e270..3c2ddbf 100644
--- a/ios/web_view/internal/cwv_web_view.mm
+++ b/ios/web_view/internal/cwv_web_view.mm
@@ -20,6 +20,7 @@
 #import "ios/web/public/navigation_manager.h"
 #include "ios/web/public/referrer.h"
 #include "ios/web/public/reload_type.h"
+#import "ios/web/public/web_client.h"
 #import "ios/web/public/web_state/context_menu_params.h"
 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h"
 #import "ios/web/public/web_state/navigation_context.h"
@@ -660,6 +661,12 @@
   [self updateVisibleSSLStatus];
   self.loading = NO;
   self.estimatedProgress = 0.0;
+
+  // TODO(crbug.com/873729): The session will not be restored until
+  // LoadIfNecessary call. Fix the bug and remove extra call.
+  if (web::GetWebClient()->IsSlimNavigationManagerEnabled() && sessionStorage) {
+    _webState->GetNavigationManager()->LoadIfNecessary();
+  }
 }
 
 // Adds the web view provided by |_webState| as a subview unless it has already.
diff --git a/ios/web_view/internal/signin/ios_web_view_signin_client.h b/ios/web_view/internal/signin/ios_web_view_signin_client.h
index 7d3e63c7..1e683fce 100644
--- a/ios/web_view/internal/signin/ios_web_view_signin_client.h
+++ b/ios/web_view/internal/signin/ios_web_view_signin_client.h
@@ -48,7 +48,7 @@
   void PreSignOut(
       base::OnceCallback<void(SignoutDecision)> on_signout_decision_reached,
       signin_metrics::ProfileSignout signout_source_metric) override;
-  void DelayNetworkCall(const base::Closure& callback) override;
+  void DelayNetworkCall(base::OnceClosure callback) override;
   std::unique_ptr<GaiaAuthFetcher> CreateGaiaAuthFetcher(
       GaiaAuthConsumer* consumer,
       gaia::GaiaSource source,
diff --git a/ios/web_view/internal/signin/ios_web_view_signin_client.mm b/ios/web_view/internal/signin/ios_web_view_signin_client.mm
index 6c4200d..b4ad7dc 100644
--- a/ios/web_view/internal/signin/ios_web_view_signin_client.mm
+++ b/ios/web_view/internal/signin/ios_web_view_signin_client.mm
@@ -86,8 +86,8 @@
   [sync_controller_ didSignoutWithSourceMetric:signout_source_metric];
 }
 
-void IOSWebViewSigninClient::DelayNetworkCall(const base::Closure& callback) {
-  network_callback_helper_->HandleCallback(callback);
+void IOSWebViewSigninClient::DelayNetworkCall(base::OnceClosure callback) {
+  network_callback_helper_->HandleCallback(std::move(callback));
 }
 
 std::unique_ptr<GaiaAuthFetcher> IOSWebViewSigninClient::CreateGaiaAuthFetcher(
diff --git a/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm b/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm
index 85544e1..b635afe 100644
--- a/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm
+++ b/ios/web_view/internal/sync/cwv_sync_controller_unittest.mm
@@ -7,6 +7,7 @@
 #include <memory>
 #include <set>
 
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/test/bind_test_util.h"
diff --git a/ios/web_view/internal/sync/web_view_profile_sync_service_factory.mm b/ios/web_view/internal/sync/web_view_profile_sync_service_factory.mm
index 507ef405..430ced8 100644
--- a/ios/web_view/internal/sync/web_view_profile_sync_service_factory.mm
+++ b/ios/web_view/internal/sync/web_view_profile_sync_service_factory.mm
@@ -6,6 +6,7 @@
 
 #include <utility>
 
+#include "base/bind_helpers.h"
 #include "base/no_destructor.h"
 #include "base/time/time.h"
 #include "components/browser_sync/profile_sync_service.h"
diff --git a/ios/web_view/internal/webdata_services/web_view_web_data_service_wrapper_factory.mm b/ios/web_view/internal/webdata_services/web_view_web_data_service_wrapper_factory.mm
index d173e18..3a6aa61 100644
--- a/ios/web_view/internal/webdata_services/web_view_web_data_service_wrapper_factory.mm
+++ b/ios/web_view/internal/webdata_services/web_view_web_data_service_wrapper_factory.mm
@@ -5,6 +5,7 @@
 #include "ios/web_view/internal/webdata_services/web_view_web_data_service_wrapper_factory.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/logging.h"
diff --git a/ios/web_view/test/web_view_restorable_state_inttest.mm b/ios/web_view/test/web_view_restorable_state_inttest.mm
index c38c645..c8b655b 100644
--- a/ios/web_view/test/web_view_restorable_state_inttest.mm
+++ b/ios/web_view/test/web_view_restorable_state_inttest.mm
@@ -4,6 +4,7 @@
 
 #import <ChromeWebView/ChromeWebView.h>
 
+#import "base/test/ios/wait_util.h"
 #import "ios/web_view/test/web_view_inttest_base.h"
 #import "ios/web_view/test/web_view_test_util.h"
 #include "testing/gtest_mac.h"
@@ -12,6 +13,9 @@
 #error "This file requires ARC support."
 #endif
 
+using base::test::ios::WaitUntilConditionOrTimeout;
+using base::test::ios::kWaitForPageLoadTimeout;
+
 namespace ios_web_view {
 
 // Tests encodeRestorableStateWithCoder: and decodeRestorableStateWithCoder:
@@ -36,6 +40,11 @@
   CWVWebView* restored_web_view = test::CreateWebView();
   test::CopyWebViewState(web_view_, restored_web_view);
 
+  // Wait for restore to finish.
+  ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^bool {
+    return [restored_web_view canGoBack];
+  }));
+
   // Verify that the state has been restored correctly.
   EXPECT_NSEQ(@"about:blank",
               [restored_web_view lastCommittedURL].absoluteString);
diff --git a/media/audio/alive_checker.cc b/media/audio/alive_checker.cc
index 7a65c87..eae96c70 100644
--- a/media/audio/alive_checker.cc
+++ b/media/audio/alive_checker.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/message_loop/message_loop_current.h"
 
 namespace media {
diff --git a/media/audio/audio_input_controller_unittest.cc b/media/audio/audio_input_controller_unittest.cc
index d01713f..3b3802c 100644
--- a/media/audio/audio_input_controller_unittest.cc
+++ b/media/audio/audio_input_controller_unittest.cc
@@ -9,6 +9,7 @@
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
+#include "base/timer/timer.h"
 #include "media/audio/audio_manager.h"
 #include "media/audio/fake_audio_input_stream.h"
 #include "media/audio/test_audio_thread.h"
diff --git a/media/blink/webmediaplayer_impl.cc b/media/blink/webmediaplayer_impl.cc
index ca97cfa9..a25744a 100644
--- a/media/blink/webmediaplayer_impl.cc
+++ b/media/blink/webmediaplayer_impl.cc
@@ -2228,7 +2228,15 @@
 }
 
 void WebMediaPlayerImpl::OnRemotePlayStateChange(MediaStatus::State state) {
-  // TODO(tguilbert): request play/pause appropriately.
+  DCHECK(is_flinging_);
+
+  if (state == MediaStatus::State::PLAYING && Paused()) {
+    DVLOG(1) << __func__ << " requesting PLAY.";
+    client_->RequestPlay();
+  } else if (state == MediaStatus::State::PAUSED && !Paused()) {
+    DVLOG(1) << __func__ << " requesting PAUSE.";
+    client_->RequestPause();
+  }
 }
 
 void WebMediaPlayerImpl::OnFrameHidden() {
diff --git a/media/blink/webmediaplayer_impl_unittest.cc b/media/blink/webmediaplayer_impl_unittest.cc
index a3a7f8d3..dbd1d5a 100644
--- a/media/blink/webmediaplayer_impl_unittest.cc
+++ b/media/blink/webmediaplayer_impl_unittest.cc
@@ -9,6 +9,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback_helpers.h"
 #include "base/command_line.h"
 #include "base/memory/ref_counted.h"
diff --git a/media/capture/video/chromeos/camera_device_delegate.cc b/media/capture/video/chromeos/camera_device_delegate.cc
index 86d4a1f..9ef046e 100644
--- a/media/capture/video/chromeos/camera_device_delegate.cc
+++ b/media/capture/video/chromeos/camera_device_delegate.cc
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/numerics/ranges.h"
 #include "base/posix/safe_strerror.h"
 #include "base/trace_event/trace_event.h"
diff --git a/media/filters/android/media_codec_audio_decoder.cc b/media/filters/android/media_codec_audio_decoder.cc
index 8f08efa..b6e6635 100644
--- a/media/filters/android/media_codec_audio_decoder.cc
+++ b/media/filters/android/media_codec_audio_decoder.cc
@@ -8,6 +8,7 @@
 
 #include "base/android/build_info.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback_helpers.h"
 #include "base/logging.h"
 #include "base/single_thread_task_runner.h"
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn
index 8cde0b7..e9c8a959 100644
--- a/media/gpu/BUILD.gn
+++ b/media/gpu/BUILD.gn
@@ -564,7 +564,7 @@
       "//media/test/data/peach_pi-41x23.jpg",
     ]
     if (use_vaapi) {
-      deps += [ "//media/gpu/vaapi:jpeg_decode_accelerator_unit_test" ]
+      deps += [ "//media/gpu/vaapi:jpeg_decoder_unit_test" ]
       data += [ "//media/test/data/pixel-1280x720.jpg" ]
     }
     if (use_x11) {
diff --git a/media/gpu/android/codec_allocator.cc b/media/gpu/android/codec_allocator.cc
index 16f0b8a..ef5f3c3 100644
--- a/media/gpu/android/codec_allocator.cc
+++ b/media/gpu/android/codec_allocator.cc
@@ -8,6 +8,7 @@
 
 #include <memory>
 
+#include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "base/single_thread_task_runner.h"
 #include "base/system/sys_info.h"
diff --git a/media/gpu/android/media_codec_video_decoder.h b/media/gpu/android/media_codec_video_decoder.h
index f24de99..ecb467c 100644
--- a/media/gpu/android/media_codec_video_decoder.h
+++ b/media/gpu/android/media_codec_video_decoder.h
@@ -11,6 +11,7 @@
 #include "base/optional.h"
 #include "base/threading/thread_checker.h"
 #include "base/timer/elapsed_timer.h"
+#include "base/timer/timer.h"
 #include "gpu/config/gpu_feature_info.h"
 #include "gpu/config/gpu_preferences.h"
 #include "media/base/android_overlay_mojo_factory.h"
diff --git a/media/gpu/android/video_frame_factory_impl.cc b/media/gpu/android/video_frame_factory_impl.cc
index cd242863..da41d9c 100644
--- a/media/gpu/android/video_frame_factory_impl.cc
+++ b/media/gpu/android/video_frame_factory_impl.cc
@@ -5,6 +5,7 @@
 #include "media/gpu/android/video_frame_factory_impl.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/memory/ref_counted.h"
 #include "base/single_thread_task_runner.h"
diff --git a/media/gpu/vaapi/BUILD.gn b/media/gpu/vaapi/BUILD.gn
index cf471b7..9d5f96bb 100644
--- a/media/gpu/vaapi/BUILD.gn
+++ b/media/gpu/vaapi/BUILD.gn
@@ -41,6 +41,8 @@
     "vaapi_h264_accelerator.h",
     "vaapi_jpeg_decode_accelerator.cc",
     "vaapi_jpeg_decode_accelerator.h",
+    "vaapi_jpeg_decoder.cc",
+    "vaapi_jpeg_decoder.h",
     "vaapi_jpeg_encode_accelerator.cc",
     "vaapi_jpeg_encode_accelerator.h",
     "vaapi_jpeg_encoder.cc",
@@ -69,10 +71,12 @@
 
   deps = [
     ":libva_stubs",
+    "//base",
     "//gpu/ipc/service",
     "//media",
     "//media/gpu:common",
     "//third_party/libyuv",
+    "//ui/gfx/geometry",
   ]
 
   if (is_linux) {
@@ -127,19 +131,18 @@
   ]
 }
 
-source_set("jpeg_decode_accelerator_unit_test") {
+source_set("jpeg_decoder_unit_test") {
   testonly = true
   sources = [
-    "vaapi_jpeg_decode_accelerator_unittest.cc",
+    "vaapi_jpeg_decoder_unittest.cc",
   ]
   deps = [
     ":vaapi",
+    "//base",
     "//base/test:test_support",
-    "//gpu:test_support",
+    "//media",
     "//media:test_support",
-    "//media/gpu:common",
-    "//testing/gmock",
     "//testing/gtest",
-    "//ui/gfx:test_support",
+    "//ui/gfx/geometry",
   ]
 }
diff --git a/media/gpu/vaapi/vaapi_jpeg_decode_accelerator.cc b/media/gpu/vaapi/vaapi_jpeg_decode_accelerator.cc
index ed242ee..9e6cec77 100644
--- a/media/gpu/vaapi/vaapi_jpeg_decode_accelerator.cc
+++ b/media/gpu/vaapi/vaapi_jpeg_decode_accelerator.cc
@@ -5,16 +5,18 @@
 #include "media/gpu/vaapi/vaapi_jpeg_decode_accelerator.h"
 
 #include <stddef.h>
-#include <string.h>
 
-#include <memory>
+#include <iostream>
 #include <utility>
+#include <vector>
 
 #include <va/va.h>
 
 #include "base/bind.h"
+#include "base/location.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/single_thread_task_runner.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
 #include "media/base/bitstream_buffer.h"
@@ -22,7 +24,7 @@
 #include "media/base/video_frame.h"
 #include "media/filters/jpeg_parser.h"
 #include "media/gpu/macros.h"
-#include "media/gpu/vaapi/vaapi_picture.h"
+#include "media/gpu/vaapi/vaapi_jpeg_decoder.h"
 #include "media/gpu/vaapi/vaapi_utils.h"
 #include "media/gpu/vaapi/vaapi_wrapper.h"
 #include "third_party/libyuv/include/libyuv.h"
@@ -30,6 +32,15 @@
 namespace media {
 
 namespace {
+
+// TODO(andrescj): remove this once VaapiJpegDecoder is responsible for
+// obtaining the VAImage.
+constexpr VAImageFormat kImageFormatI420 = {
+    .fourcc = VA_FOURCC_I420,
+    .byte_order = VA_LSB_FIRST,
+    .bits_per_pixel = 12,
+};
+
 // UMA errors that the VaapiJpegDecodeAccelerator class reports.
 enum VAJDADecoderFailure {
   VAAPI_ERROR = 0,
@@ -41,235 +52,6 @@
                             VAJDA_DECODER_FAILURES_MAX + 1);
 }
 
-// Check the value of VA_FOURCC_YUYV, as we don't have access to the VA_FOURCC
-// macro in the header file without pulling in the entire <va/va.h>.
-static_assert(VA_FOURCC_YUYV == VA_FOURCC('Y', 'U', 'Y', 'V'),
-              "VA_FOURCC_YUYV must be equal to VA_FOURCC('Y', 'U', 'Y', 'V')");
-constexpr VAImageFormat kImageFormatI420 = {.fourcc = VA_FOURCC_I420,
-                                            .byte_order = VA_LSB_FIRST,
-                                            .bits_per_pixel = 12};
-constexpr VAImageFormat kImageFormatYUYV = {.fourcc = VA_FOURCC_YUYV,
-                                            .byte_order = VA_LSB_FIRST,
-                                            .bits_per_pixel = 16};
-
-// Convert the specified surface format to the associated output image format.
-bool VaSurfaceFormatToImageFormat(uint32_t va_rt_format,
-                                  VAImageFormat* va_image_format) {
-  switch (va_rt_format) {
-    case VA_RT_FORMAT_YUV420:
-      *va_image_format = kImageFormatI420;
-      return true;
-    case VA_RT_FORMAT_YUV422:
-      *va_image_format = kImageFormatYUYV;
-      return true;
-    default:
-      return false;
-  }
-}
-
-static unsigned int VaSurfaceFormatForJpeg(
-    const JpegFrameHeader& frame_header) {
-  // The range of sampling factor is [1, 4]. Pack them into integer to make the
-  // matching code simpler. For example, 0x211 means the sampling factor are 2,
-  // 1, 1 for 3 components.
-  unsigned int h = 0, v = 0;
-  for (int i = 0; i < frame_header.num_components; i++) {
-    DCHECK_LE(frame_header.components[i].horizontal_sampling_factor, 4);
-    DCHECK_LE(frame_header.components[i].vertical_sampling_factor, 4);
-    h = h << 4 | frame_header.components[i].horizontal_sampling_factor;
-    v = v << 4 | frame_header.components[i].vertical_sampling_factor;
-  }
-
-  switch (frame_header.num_components) {
-    case 1:  // Grey image
-      return VA_RT_FORMAT_YUV400;
-
-    case 3:  // Y Cb Cr color image
-      // See https://en.wikipedia.org/wiki/Chroma_subsampling for the
-      // definition of these numbers.
-      if (h == 0x211 && v == 0x211)
-        return VA_RT_FORMAT_YUV420;
-
-      if (h == 0x211 && v == 0x111)
-        return VA_RT_FORMAT_YUV422;
-
-      if (h == 0x111 && v == 0x111)
-        return VA_RT_FORMAT_YUV444;
-
-      if (h == 0x411 && v == 0x111)
-        return VA_RT_FORMAT_YUV411;
-  }
-  VLOGF(1) << "Unsupported sampling factor: num_components="
-           << frame_header.num_components << ", h=" << std::hex << h
-           << ", v=" << v;
-
-  return 0;
-}
-
-// VAAPI only supports a subset of JPEG profiles. This function determines
-// whether a given parsed JPEG result is supported or not.
-static bool IsVaapiSupportedJpeg(const JpegParseResult& jpeg) {
-  if (jpeg.frame_header.visible_width < 1 ||
-      jpeg.frame_header.visible_height < 1) {
-    DLOG(ERROR) << "width(" << jpeg.frame_header.visible_width
-                << ") and height(" << jpeg.frame_header.visible_height
-                << ") should be at least 1";
-    return false;
-  }
-
-  // Size 64k*64k is the maximum in the JPEG standard. VAAPI doesn't support
-  // resolutions larger than 16k*16k.
-  const int kMaxDimension = 16384;
-  if (jpeg.frame_header.coded_width > kMaxDimension ||
-      jpeg.frame_header.coded_height > kMaxDimension) {
-    DLOG(ERROR) << "VAAPI doesn't support size("
-                << jpeg.frame_header.coded_width << "*"
-                << jpeg.frame_header.coded_height << ") larger than "
-                << kMaxDimension << "*" << kMaxDimension;
-    return false;
-  }
-
-  if (jpeg.frame_header.num_components != 3) {
-    DLOG(ERROR) << "VAAPI doesn't support num_components("
-                << static_cast<int>(jpeg.frame_header.num_components)
-                << ") != 3";
-    return false;
-  }
-
-  if (jpeg.frame_header.components[0].horizontal_sampling_factor <
-          jpeg.frame_header.components[1].horizontal_sampling_factor ||
-      jpeg.frame_header.components[0].horizontal_sampling_factor <
-          jpeg.frame_header.components[2].horizontal_sampling_factor) {
-    DLOG(ERROR) << "VAAPI doesn't supports horizontal sampling factor of Y"
-                << " smaller than Cb and Cr";
-    return false;
-  }
-
-  if (jpeg.frame_header.components[0].vertical_sampling_factor <
-          jpeg.frame_header.components[1].vertical_sampling_factor ||
-      jpeg.frame_header.components[0].vertical_sampling_factor <
-          jpeg.frame_header.components[2].vertical_sampling_factor) {
-    DLOG(ERROR) << "VAAPI doesn't supports vertical sampling factor of Y"
-                << " smaller than Cb and Cr";
-    return false;
-  }
-
-  return true;
-}
-
-static void FillPictureParameters(
-    const JpegFrameHeader& frame_header,
-    VAPictureParameterBufferJPEGBaseline* pic_param) {
-  memset(pic_param, 0, sizeof(*pic_param));
-  pic_param->picture_width = frame_header.coded_width;
-  pic_param->picture_height = frame_header.coded_height;
-  pic_param->num_components = frame_header.num_components;
-
-  for (int i = 0; i < pic_param->num_components; i++) {
-    pic_param->components[i].component_id = frame_header.components[i].id;
-    pic_param->components[i].h_sampling_factor =
-        frame_header.components[i].horizontal_sampling_factor;
-    pic_param->components[i].v_sampling_factor =
-        frame_header.components[i].vertical_sampling_factor;
-    pic_param->components[i].quantiser_table_selector =
-        frame_header.components[i].quantization_table_selector;
-  }
-}
-
-static void FillIQMatrix(const JpegQuantizationTable* q_table,
-                         VAIQMatrixBufferJPEGBaseline* iq_matrix) {
-  memset(iq_matrix, 0, sizeof(*iq_matrix));
-  static_assert(kJpegMaxQuantizationTableNum ==
-                    std::extent<decltype(iq_matrix->load_quantiser_table)>(),
-                "max number of quantization table mismatched");
-  static_assert(
-      sizeof(iq_matrix->quantiser_table[0]) == sizeof(q_table[0].value),
-      "number of quantization entries mismatched");
-  for (size_t i = 0; i < kJpegMaxQuantizationTableNum; i++) {
-    if (!q_table[i].valid)
-      continue;
-    iq_matrix->load_quantiser_table[i] = 1;
-    for (size_t j = 0; j < base::size(q_table[i].value); j++)
-      iq_matrix->quantiser_table[i][j] = q_table[i].value[j];
-  }
-}
-
-static void FillHuffmanTable(const JpegHuffmanTable* dc_table,
-                             const JpegHuffmanTable* ac_table,
-                             VAHuffmanTableBufferJPEGBaseline* huffman_table) {
-  memset(huffman_table, 0, sizeof(*huffman_table));
-  // Use default huffman tables if not specified in header.
-  bool has_huffman_table = false;
-  for (size_t i = 0; i < kJpegMaxHuffmanTableNumBaseline; i++) {
-    if (dc_table[i].valid || ac_table[i].valid) {
-      has_huffman_table = true;
-      break;
-    }
-  }
-  if (!has_huffman_table) {
-    dc_table = kDefaultDcTable;
-    ac_table = kDefaultAcTable;
-  }
-
-  static_assert(kJpegMaxHuffmanTableNumBaseline ==
-                    std::extent<decltype(huffman_table->load_huffman_table)>(),
-                "max number of huffman table mismatched");
-  static_assert(sizeof(huffman_table->huffman_table[0].num_dc_codes) ==
-                    sizeof(dc_table[0].code_length),
-                "size of huffman table code length mismatch");
-  static_assert(sizeof(huffman_table->huffman_table[0].dc_values[0]) ==
-                    sizeof(dc_table[0].code_value[0]),
-                "size of huffman table code value mismatch");
-  for (size_t i = 0; i < kJpegMaxHuffmanTableNumBaseline; i++) {
-    if (!dc_table[i].valid || !ac_table[i].valid)
-      continue;
-    huffman_table->load_huffman_table[i] = 1;
-
-    memcpy(huffman_table->huffman_table[i].num_dc_codes,
-           dc_table[i].code_length,
-           sizeof(huffman_table->huffman_table[i].num_dc_codes));
-    memcpy(huffman_table->huffman_table[i].dc_values, dc_table[i].code_value,
-           sizeof(huffman_table->huffman_table[i].dc_values));
-    memcpy(huffman_table->huffman_table[i].num_ac_codes,
-           ac_table[i].code_length,
-           sizeof(huffman_table->huffman_table[i].num_ac_codes));
-    memcpy(huffman_table->huffman_table[i].ac_values, ac_table[i].code_value,
-           sizeof(huffman_table->huffman_table[i].ac_values));
-  }
-}
-
-static void FillSliceParameters(
-    const JpegParseResult& parse_result,
-    VASliceParameterBufferJPEGBaseline* slice_param) {
-  memset(slice_param, 0, sizeof(*slice_param));
-  slice_param->slice_data_size = parse_result.data_size;
-  slice_param->slice_data_offset = 0;
-  slice_param->slice_data_flag = VA_SLICE_DATA_FLAG_ALL;
-  slice_param->slice_horizontal_position = 0;
-  slice_param->slice_vertical_position = 0;
-  slice_param->num_components = parse_result.scan.num_components;
-  for (int i = 0; i < slice_param->num_components; i++) {
-    slice_param->components[i].component_selector =
-        parse_result.scan.components[i].component_selector;
-    slice_param->components[i].dc_table_selector =
-        parse_result.scan.components[i].dc_selector;
-    slice_param->components[i].ac_table_selector =
-        parse_result.scan.components[i].ac_selector;
-  }
-  slice_param->restart_interval = parse_result.restart_interval;
-
-  // Cast to int to prevent overflow.
-  int max_h_factor =
-      parse_result.frame_header.components[0].horizontal_sampling_factor;
-  int max_v_factor =
-      parse_result.frame_header.components[0].vertical_sampling_factor;
-  int mcu_cols = parse_result.frame_header.coded_width / (max_h_factor * 8);
-  DCHECK_GT(mcu_cols, 0);
-  int mcu_rows = parse_result.frame_header.coded_height / (max_v_factor * 8);
-  DCHECK_GT(mcu_rows, 0);
-  slice_param->num_mcus = mcu_rows * mcu_cols;
-}
-
 }  // namespace
 
 void VaapiJpegDecodeAccelerator::NotifyError(int32_t bitstream_buffer_id,
@@ -399,7 +181,7 @@
       break;
     }
     case VA_FOURCC_YUY2:
-    case VA_FOURCC_YUYV: {
+    case VA_FOURCC('Y', 'U', 'Y', 'V'): {
       DCHECK_EQ(image->num_planes, 1u);
       const uint8_t* src_yuy2 = mem + image->offsets[0];
       const size_t src_yuy2_stride = image->pitches[0];
@@ -469,7 +251,8 @@
     coded_size_ = new_coded_size;
   }
 
-  if (!DoDecode(vaapi_wrapper_.get(), parse_result, va_surface_id_)) {
+  if (!VaapiJpegDecoder::DoDecode(vaapi_wrapper_.get(), parse_result,
+                                  va_surface_id_)) {
     VLOGF(1) << "Decode JPEG failed";
     NotifyError(bitstream_buffer_id, PLATFORM_FAILURE);
     return;
@@ -520,51 +303,4 @@
   return VaapiWrapper::IsJpegDecodeSupported();
 }
 
-// static
-bool VaapiJpegDecodeAccelerator::DoDecode(VaapiWrapper* vaapi_wrapper,
-                                          const JpegParseResult& parse_result,
-                                          VASurfaceID va_surface) {
-  DCHECK_NE(va_surface, VA_INVALID_SURFACE);
-  if (!IsVaapiSupportedJpeg(parse_result))
-    return false;
-
-  // Set picture parameters.
-  VAPictureParameterBufferJPEGBaseline pic_param;
-  FillPictureParameters(parse_result.frame_header, &pic_param);
-  if (!vaapi_wrapper->SubmitBuffer(VAPictureParameterBufferType, &pic_param)) {
-    return false;
-  }
-
-  // Set quantization table.
-  VAIQMatrixBufferJPEGBaseline iq_matrix;
-  FillIQMatrix(parse_result.q_table, &iq_matrix);
-  if (!vaapi_wrapper->SubmitBuffer(VAIQMatrixBufferType, &iq_matrix)) {
-    return false;
-  }
-
-  // Set huffman table.
-  VAHuffmanTableBufferJPEGBaseline huffman_table;
-  FillHuffmanTable(parse_result.dc_table, parse_result.ac_table,
-                   &huffman_table);
-  if (!vaapi_wrapper->SubmitBuffer(VAHuffmanTableBufferType, &huffman_table)) {
-    return false;
-  }
-
-  // Set slice parameters.
-  VASliceParameterBufferJPEGBaseline slice_param;
-  FillSliceParameters(parse_result, &slice_param);
-  if (!vaapi_wrapper->SubmitBuffer(VASliceParameterBufferType, &slice_param)) {
-    return false;
-  }
-
-  // Set scan data.
-  if (!vaapi_wrapper->SubmitBuffer(VASliceDataBufferType,
-                                   parse_result.data_size,
-                                   const_cast<char*>(parse_result.data))) {
-    return false;
-  }
-
-  return vaapi_wrapper->ExecuteAndDestroyPendingBuffers(va_surface);
-}
-
 }  // namespace media
diff --git a/media/gpu/vaapi/vaapi_jpeg_decode_accelerator.h b/media/gpu/vaapi/vaapi_jpeg_decode_accelerator.h
index 6b489d2..398ef69 100644
--- a/media/gpu/vaapi/vaapi_jpeg_decode_accelerator.h
+++ b/media/gpu/vaapi/vaapi_jpeg_decode_accelerator.h
@@ -10,27 +10,28 @@
 #include <memory>
 
 #include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
-#include "base/single_thread_task_runner.h"
 #include "base/threading/thread.h"
 #include "media/gpu/media_gpu_export.h"
 #include "media/video/jpeg_decode_accelerator.h"
+#include "ui/gfx/geometry/size.h"
 
-// These data types are defined in va/va.h using typedef, reproduced here.
-typedef struct _VAImageFormat VAImageFormat;
-typedef unsigned int VASurfaceID;
+// This data type is defined in va/va.h using typedef, reproduced here.
+// TODO(andrescj): remove this once VaapiJpegDecoder is responsible for
+// obtaining the VAImage.
+using VASurfaceID = unsigned int;
+
+namespace base {
+class SingleThreadTaskRunner;
+}
 
 namespace media {
 
 class BitstreamBuffer;
-struct JpegParseResult;
 class UnalignedSharedMemory;
 class VaapiWrapper;
-class VaapiJpegDecodeAcceleratorTest;
-
-// Alternative notation for the VA_FOURCC_YUY2 format, <va/va.h> doesn't provide
-// this specific packing/ordering.
-constexpr uint32_t VA_FOURCC_YUYV = 0x56595559;
+class VideoFrame;
 
 // Class to provide JPEG decode acceleration for Intel systems with hardware
 // support for it, and on which libva is available.
@@ -54,8 +55,6 @@
   bool IsSupported() override;
 
  private:
-  friend class VaapiJpegDecodeAcceleratorTest;
-
   // Notifies the client that an error has occurred and decoding cannot
   // continue. The client is notified on the |task_runner_|, i.e., the thread in
   // which |*this| was created.
@@ -78,16 +77,6 @@
                      int32_t input_buffer_id,
                      const scoped_refptr<VideoFrame>& video_frame);
 
-  // Decodes a JPEG picture. It will fill VA-API parameters and call
-  // corresponding VA-API methods according to the JPEG |parse_result|. Decoded
-  // data will be outputted to the given |va_surface|. Returns false on failure.
-  // |vaapi_wrapper| should be initialized in kDecode mode with
-  // VAProfileJPEGBaseline profile. |va_surface| should be created with size at
-  // least as large as the picture size.
-  static bool DoDecode(VaapiWrapper* vaapi_wrapper,
-                       const JpegParseResult& parse_result,
-                       VASurfaceID va_surface);
-
   // ChildThread's task runner.
   const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
 
diff --git a/media/gpu/vaapi/vaapi_jpeg_decoder.cc b/media/gpu/vaapi/vaapi_jpeg_decoder.cc
new file mode 100644
index 0000000..228ed15
--- /dev/null
+++ b/media/gpu/vaapi/vaapi_jpeg_decoder.cc
@@ -0,0 +1,296 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/gpu/vaapi/vaapi_jpeg_decoder.h"
+
+#include <string.h>
+
+#include <iostream>
+#include <type_traits>
+
+#include <va/va.h>
+
+#include "base/logging.h"
+#include "base/stl_util.h"
+#include "media/filters/jpeg_parser.h"
+#include "media/gpu/macros.h"
+#include "media/gpu/vaapi/vaapi_wrapper.h"
+
+namespace media {
+
+namespace {
+
+constexpr VAImageFormat kImageFormatI420 = {
+    .fourcc = VA_FOURCC_I420,
+    .byte_order = VA_LSB_FIRST,
+    .bits_per_pixel = 12,
+};
+
+constexpr VAImageFormat kImageFormatYUYV = {
+    .fourcc = VA_FOURCC('Y', 'U', 'Y', 'V'),
+    .byte_order = VA_LSB_FIRST,
+    .bits_per_pixel = 16,
+};
+
+static void FillPictureParameters(
+    const JpegFrameHeader& frame_header,
+    VAPictureParameterBufferJPEGBaseline* pic_param) {
+  pic_param->picture_width = frame_header.coded_width;
+  pic_param->picture_height = frame_header.coded_height;
+  pic_param->num_components = frame_header.num_components;
+
+  for (int i = 0; i < pic_param->num_components; i++) {
+    pic_param->components[i].component_id = frame_header.components[i].id;
+    pic_param->components[i].h_sampling_factor =
+        frame_header.components[i].horizontal_sampling_factor;
+    pic_param->components[i].v_sampling_factor =
+        frame_header.components[i].vertical_sampling_factor;
+    pic_param->components[i].quantiser_table_selector =
+        frame_header.components[i].quantization_table_selector;
+  }
+}
+
+static void FillIQMatrix(const JpegQuantizationTable* q_table,
+                         VAIQMatrixBufferJPEGBaseline* iq_matrix) {
+  static_assert(kJpegMaxQuantizationTableNum ==
+                    std::extent<decltype(iq_matrix->load_quantiser_table)>(),
+                "max number of quantization table mismatched");
+  static_assert(
+      sizeof(iq_matrix->quantiser_table[0]) == sizeof(q_table[0].value),
+      "number of quantization entries mismatched");
+  for (size_t i = 0; i < kJpegMaxQuantizationTableNum; i++) {
+    if (!q_table[i].valid)
+      continue;
+    iq_matrix->load_quantiser_table[i] = 1;
+    for (size_t j = 0; j < base::size(q_table[i].value); j++)
+      iq_matrix->quantiser_table[i][j] = q_table[i].value[j];
+  }
+}
+
+static void FillHuffmanTable(const JpegHuffmanTable* dc_table,
+                             const JpegHuffmanTable* ac_table,
+                             VAHuffmanTableBufferJPEGBaseline* huffman_table) {
+  // Use default huffman tables if not specified in header.
+  bool has_huffman_table = false;
+  for (size_t i = 0; i < kJpegMaxHuffmanTableNumBaseline; i++) {
+    if (dc_table[i].valid || ac_table[i].valid) {
+      has_huffman_table = true;
+      break;
+    }
+  }
+  if (!has_huffman_table) {
+    dc_table = kDefaultDcTable;
+    ac_table = kDefaultAcTable;
+  }
+
+  static_assert(kJpegMaxHuffmanTableNumBaseline ==
+                    std::extent<decltype(huffman_table->load_huffman_table)>(),
+                "max number of huffman table mismatched");
+  static_assert(sizeof(huffman_table->huffman_table[0].num_dc_codes) ==
+                    sizeof(dc_table[0].code_length),
+                "size of huffman table code length mismatch");
+  static_assert(sizeof(huffman_table->huffman_table[0].dc_values[0]) ==
+                    sizeof(dc_table[0].code_value[0]),
+                "size of huffman table code value mismatch");
+  for (size_t i = 0; i < kJpegMaxHuffmanTableNumBaseline; i++) {
+    if (!dc_table[i].valid || !ac_table[i].valid)
+      continue;
+    huffman_table->load_huffman_table[i] = 1;
+
+    memcpy(huffman_table->huffman_table[i].num_dc_codes,
+           dc_table[i].code_length,
+           sizeof(huffman_table->huffman_table[i].num_dc_codes));
+    memcpy(huffman_table->huffman_table[i].dc_values, dc_table[i].code_value,
+           sizeof(huffman_table->huffman_table[i].dc_values));
+    memcpy(huffman_table->huffman_table[i].num_ac_codes,
+           ac_table[i].code_length,
+           sizeof(huffman_table->huffman_table[i].num_ac_codes));
+    memcpy(huffman_table->huffman_table[i].ac_values, ac_table[i].code_value,
+           sizeof(huffman_table->huffman_table[i].ac_values));
+  }
+}
+
+static void FillSliceParameters(
+    const JpegParseResult& parse_result,
+    VASliceParameterBufferJPEGBaseline* slice_param) {
+  slice_param->slice_data_size = parse_result.data_size;
+  slice_param->slice_data_offset = 0;
+  slice_param->slice_data_flag = VA_SLICE_DATA_FLAG_ALL;
+  slice_param->slice_horizontal_position = 0;
+  slice_param->slice_vertical_position = 0;
+  slice_param->num_components = parse_result.scan.num_components;
+  for (int i = 0; i < slice_param->num_components; i++) {
+    slice_param->components[i].component_selector =
+        parse_result.scan.components[i].component_selector;
+    slice_param->components[i].dc_table_selector =
+        parse_result.scan.components[i].dc_selector;
+    slice_param->components[i].ac_table_selector =
+        parse_result.scan.components[i].ac_selector;
+  }
+  slice_param->restart_interval = parse_result.restart_interval;
+
+  // Cast to int to prevent overflow.
+  int max_h_factor =
+      parse_result.frame_header.components[0].horizontal_sampling_factor;
+  int max_v_factor =
+      parse_result.frame_header.components[0].vertical_sampling_factor;
+  int mcu_cols = parse_result.frame_header.coded_width / (max_h_factor * 8);
+  DCHECK_GT(mcu_cols, 0);
+  int mcu_rows = parse_result.frame_header.coded_height / (max_v_factor * 8);
+  DCHECK_GT(mcu_rows, 0);
+  slice_param->num_mcus = mcu_rows * mcu_cols;
+}
+
+// VAAPI only supports a subset of JPEG profiles. This function determines
+// whether a given parsed JPEG result is supported or not.
+static bool IsVaapiSupportedJpeg(const JpegParseResult& jpeg) {
+  if (jpeg.frame_header.visible_width < 1 ||
+      jpeg.frame_header.visible_height < 1) {
+    DLOG(ERROR) << "width(" << jpeg.frame_header.visible_width
+                << ") and height(" << jpeg.frame_header.visible_height
+                << ") should be at least 1";
+    return false;
+  }
+
+  // Size 64k*64k is the maximum in the JPEG standard. VAAPI doesn't support
+  // resolutions larger than 16k*16k.
+  constexpr int kMaxDimension = 16384;
+  if (jpeg.frame_header.coded_width > kMaxDimension ||
+      jpeg.frame_header.coded_height > kMaxDimension) {
+    DLOG(ERROR) << "VAAPI doesn't support size("
+                << jpeg.frame_header.coded_width << "*"
+                << jpeg.frame_header.coded_height << ") larger than "
+                << kMaxDimension << "*" << kMaxDimension;
+    return false;
+  }
+
+  if (jpeg.frame_header.num_components != 3) {
+    DLOG(ERROR) << "VAAPI doesn't support num_components("
+                << static_cast<int>(jpeg.frame_header.num_components)
+                << ") != 3";
+    return false;
+  }
+
+  if (jpeg.frame_header.components[0].horizontal_sampling_factor <
+          jpeg.frame_header.components[1].horizontal_sampling_factor ||
+      jpeg.frame_header.components[0].horizontal_sampling_factor <
+          jpeg.frame_header.components[2].horizontal_sampling_factor) {
+    DLOG(ERROR) << "VAAPI doesn't supports horizontal sampling factor of Y"
+                << " smaller than Cb and Cr";
+    return false;
+  }
+
+  if (jpeg.frame_header.components[0].vertical_sampling_factor <
+          jpeg.frame_header.components[1].vertical_sampling_factor ||
+      jpeg.frame_header.components[0].vertical_sampling_factor <
+          jpeg.frame_header.components[2].vertical_sampling_factor) {
+    DLOG(ERROR) << "VAAPI doesn't supports vertical sampling factor of Y"
+                << " smaller than Cb and Cr";
+    return false;
+  }
+
+  return true;
+}
+
+}  // namespace
+
+bool VaSurfaceFormatToImageFormat(uint32_t va_rt_format,
+                                  VAImageFormat* va_image_format) {
+  switch (va_rt_format) {
+    case VA_RT_FORMAT_YUV420:
+      *va_image_format = kImageFormatI420;
+      return true;
+    case VA_RT_FORMAT_YUV422:
+      *va_image_format = kImageFormatYUYV;
+      return true;
+    default:
+      return false;
+  }
+}
+
+unsigned int VaSurfaceFormatForJpeg(const JpegFrameHeader& frame_header) {
+  // The range of sampling factor is [1, 4]. Pack them into integer to make the
+  // matching code simpler. For example, 0x211 means the sampling factor are 2,
+  // 1, 1 for 3 components.
+  unsigned int h = 0, v = 0;
+  for (int i = 0; i < frame_header.num_components; i++) {
+    DCHECK_LE(frame_header.components[i].horizontal_sampling_factor, 4);
+    DCHECK_LE(frame_header.components[i].vertical_sampling_factor, 4);
+    h = h << 4 | frame_header.components[i].horizontal_sampling_factor;
+    v = v << 4 | frame_header.components[i].vertical_sampling_factor;
+  }
+
+  switch (frame_header.num_components) {
+    case 1:  // Grey image
+      return VA_RT_FORMAT_YUV400;
+
+    case 3:  // Y Cb Cr color image
+      // See https://en.wikipedia.org/wiki/Chroma_subsampling for the
+      // definition of these numbers.
+      if (h == 0x211 && v == 0x211)
+        return VA_RT_FORMAT_YUV420;
+
+      if (h == 0x211 && v == 0x111)
+        return VA_RT_FORMAT_YUV422;
+
+      if (h == 0x111 && v == 0x111)
+        return VA_RT_FORMAT_YUV444;
+
+      if (h == 0x411 && v == 0x111)
+        return VA_RT_FORMAT_YUV411;
+  }
+  VLOGF(1) << "Unsupported sampling factor: num_components="
+           << frame_header.num_components << ", h=" << std::hex << h
+           << ", v=" << v;
+
+  return 0;
+}
+
+bool VaapiJpegDecoder::DoDecode(VaapiWrapper* vaapi_wrapper,
+                                const JpegParseResult& parse_result,
+                                VASurfaceID va_surface) {
+  DCHECK_NE(va_surface, VA_INVALID_SURFACE);
+  if (!IsVaapiSupportedJpeg(parse_result))
+    return false;
+
+  // Set picture parameters.
+  VAPictureParameterBufferJPEGBaseline pic_param{};
+  FillPictureParameters(parse_result.frame_header, &pic_param);
+  if (!vaapi_wrapper->SubmitBuffer(VAPictureParameterBufferType, &pic_param)) {
+    return false;
+  }
+
+  // Set quantization table.
+  VAIQMatrixBufferJPEGBaseline iq_matrix{};
+  FillIQMatrix(parse_result.q_table, &iq_matrix);
+  if (!vaapi_wrapper->SubmitBuffer(VAIQMatrixBufferType, &iq_matrix)) {
+    return false;
+  }
+
+  // Set huffman table.
+  VAHuffmanTableBufferJPEGBaseline huffman_table{};
+  FillHuffmanTable(parse_result.dc_table, parse_result.ac_table,
+                   &huffman_table);
+  if (!vaapi_wrapper->SubmitBuffer(VAHuffmanTableBufferType, &huffman_table)) {
+    return false;
+  }
+
+  // Set slice parameters.
+  VASliceParameterBufferJPEGBaseline slice_param{};
+  FillSliceParameters(parse_result, &slice_param);
+  if (!vaapi_wrapper->SubmitBuffer(VASliceParameterBufferType, &slice_param)) {
+    return false;
+  }
+
+  // Set scan data.
+  if (!vaapi_wrapper->SubmitBuffer(VASliceDataBufferType,
+                                   parse_result.data_size,
+                                   const_cast<char*>(parse_result.data))) {
+    return false;
+  }
+
+  return vaapi_wrapper->ExecuteAndDestroyPendingBuffers(va_surface);
+}
+
+}  // namespace media
diff --git a/media/gpu/vaapi/vaapi_jpeg_decoder.h b/media/gpu/vaapi/vaapi_jpeg_decoder.h
new file mode 100644
index 0000000..ccbe54d
--- /dev/null
+++ b/media/gpu/vaapi/vaapi_jpeg_decoder.h
@@ -0,0 +1,47 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_GPU_VAAPI_VAAPI_JPEG_DECODER_H_
+#define MEDIA_GPU_VAAPI_VAAPI_JPEG_DECODER_H_
+
+#include <stdint.h>
+
+// These data types are defined in va/va.h using typedef, reproduced here.
+// TODO(andrescj): revisit this once VaSurfaceFormatToImageFormat() and
+// VaSurfaceFormatForJpeg() are moved to the anonymous namespace in the .cc
+// file.
+using VAImageFormat = struct _VAImageFormat;
+using VASurfaceID = unsigned int;
+
+namespace media {
+
+struct JpegFrameHeader;
+struct JpegParseResult;
+class VaapiWrapper;
+
+// Convert the specified surface format to the associated output image format.
+bool VaSurfaceFormatToImageFormat(uint32_t va_rt_format,
+                                  VAImageFormat* va_image_format);
+
+unsigned int VaSurfaceFormatForJpeg(const JpegFrameHeader& frame_header);
+
+class VaapiJpegDecoder {
+ public:
+  VaapiJpegDecoder() = default;
+  virtual ~VaapiJpegDecoder() = default;
+
+  // Decodes a JPEG picture. It will fill VA-API parameters and call
+  // corresponding VA-API methods according to the JPEG |parse_result|. Decoded
+  // data will be outputted to the given |va_surface|. Returns false on failure.
+  // |vaapi_wrapper| should be initialized in kDecode mode with
+  // VAProfileJPEGBaseline profile. |va_surface| should be created with size at
+  // least as large as the picture size.
+  static bool DoDecode(VaapiWrapper* vaapi_wrapper,
+                       const JpegParseResult& parse_result,
+                       VASurfaceID va_surface);
+};
+
+}  // namespace media
+
+#endif  // MEDIA_GPU_VAAPI_VAAPI_JPEG_DECODER_H_
diff --git a/media/gpu/vaapi/vaapi_jpeg_decode_accelerator_unittest.cc b/media/gpu/vaapi/vaapi_jpeg_decoder_unittest.cc
similarity index 85%
rename from media/gpu/vaapi/vaapi_jpeg_decode_accelerator_unittest.cc
rename to media/gpu/vaapi/vaapi_jpeg_decoder_unittest.cc
index e29ee63..1cdd1c9 100644
--- a/media/gpu/vaapi/vaapi_jpeg_decode_accelerator_unittest.cc
+++ b/media/gpu/vaapi/vaapi_jpeg_decoder_unittest.cc
@@ -3,7 +3,10 @@
 // found in the LICENSE file.
 
 #include <stdint.h>
-#include <string.h>
+
+#include <memory>
+#include <string>
+#include <vector>
 
 #include <va/va.h>
 
@@ -11,21 +14,26 @@
 // See http://code.google.com/p/googletest/issues/detail?id=371
 #include "testing/gtest/include/gtest/gtest.h"
 
-#include "base/at_exit.h"
 #include "base/bind.h"
+#include "base/callback.h"
 #include "base/command_line.h"
+#include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/logging.h"
 #include "base/md5.h"
-#include "base/path_service.h"
+#include "base/memory/scoped_refptr.h"
 #include "base/strings/string_piece.h"
+#include "base/synchronization/lock.h"
 #include "base/test/gtest_util.h"
+#include "base/thread_annotations.h"
 #include "media/base/test_data_util.h"
 #include "media/base/video_frame.h"
+#include "media/base/video_types.h"
 #include "media/filters/jpeg_parser.h"
-#include "media/gpu/vaapi/vaapi_jpeg_decode_accelerator.h"
+#include "media/gpu/vaapi/vaapi_jpeg_decoder.h"
 #include "media/gpu/vaapi/vaapi_utils.h"
 #include "media/gpu/vaapi/vaapi_wrapper.h"
+#include "ui/gfx/geometry/size.h"
 
 namespace media {
 namespace {
@@ -34,12 +42,17 @@
 constexpr const char* kExpectedMd5SumI420 = "6e9e1716073c9a9a1282e3f0e0dab743";
 constexpr const char* kExpectedMd5SumYUYV = "ff313a6aedbc4e157561e5c2d5c2e079";
 
-constexpr VAImageFormat kImageFormatI420 = {.fourcc = VA_FOURCC_I420,
-                                            .byte_order = VA_LSB_FIRST,
-                                            .bits_per_pixel = 12};
-constexpr VAImageFormat kImageFormatYUYV = {.fourcc = VA_FOURCC_YUYV,
-                                            .byte_order = VA_LSB_FIRST,
-                                            .bits_per_pixel = 16};
+constexpr VAImageFormat kImageFormatI420 = {
+    .fourcc = VA_FOURCC_I420,
+    .byte_order = VA_LSB_FIRST,
+    .bits_per_pixel = 12,
+};
+
+constexpr VAImageFormat kImageFormatYUYV = {
+    .fourcc = VA_FOURCC('Y', 'U', 'Y', 'V'),
+    .byte_order = VA_LSB_FIRST,
+    .bits_per_pixel = 16,
+};
 
 void LogOnError() {
   LOG(FATAL) << "Oh noes! Decoder failed";
@@ -67,13 +80,12 @@
 
 }  // namespace
 
-class VaapiJpegDecodeAcceleratorTest : public ::testing::Test {
+class VaapiJpegDecoderTest : public ::testing::Test {
  protected:
-  VaapiJpegDecodeAcceleratorTest() {
+  VaapiJpegDecoderTest() {
     const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
-    if (cmd_line && cmd_line->HasSwitch("test_data_path")) {
+    if (cmd_line && cmd_line->HasSwitch("test_data_path"))
       test_data_path_ = cmd_line->GetSwitchValueASCII("test_data_path");
-    }
   }
 
   void SetUp() override {
@@ -118,7 +130,7 @@
 // is not found, treat the file as being relative to the test file directory.
 // This is either a custom test data path provided by --test_data_path, or the
 // default test data path (//media/test/data).
-base::FilePath VaapiJpegDecodeAcceleratorTest::FindTestDataFilePath(
+base::FilePath VaapiJpegDecoderTest::FindTestDataFilePath(
     const std::string& file_name) {
   const base::FilePath file_path = base::FilePath(file_name);
   if (base::PathExists(file_path))
@@ -128,7 +140,7 @@
   return GetTestDataFilePath(file_name);
 }
 
-bool VaapiJpegDecodeAcceleratorTest::VerifyDecode(
+bool VaapiJpegDecoderTest::VerifyDecode(
     const JpegParseResult& parse_result) const {
   gfx::Size size(parse_result.frame_header.coded_width,
                  parse_result.frame_header.coded_height);
@@ -179,14 +191,13 @@
   return true;
 }
 
-bool VaapiJpegDecodeAcceleratorTest::Decode(VaapiWrapper* vaapi_wrapper,
-                                            const JpegParseResult& parse_result,
-                                            VASurfaceID va_surface) const {
-  return VaapiJpegDecodeAccelerator::DoDecode(vaapi_wrapper, parse_result,
-                                              va_surface);
+bool VaapiJpegDecoderTest::Decode(VaapiWrapper* vaapi_wrapper,
+                                  const JpegParseResult& parse_result,
+                                  VASurfaceID va_surface) const {
+  return VaapiJpegDecoder::DoDecode(vaapi_wrapper, parse_result, va_surface);
 }
 
-TEST_F(VaapiJpegDecodeAcceleratorTest, DecodeSuccess) {
+TEST_F(VaapiJpegDecoderTest, DecodeSuccess) {
   JpegParseResult parse_result;
   ASSERT_TRUE(
       ParseJpegPicture(reinterpret_cast<const uint8_t*>(jpeg_data_.data()),
@@ -195,7 +206,7 @@
   EXPECT_TRUE(VerifyDecode(parse_result));
 }
 
-TEST_F(VaapiJpegDecodeAcceleratorTest, DecodeFail) {
+TEST_F(VaapiJpegDecoderTest, DecodeFail) {
   JpegParseResult parse_result;
   ASSERT_TRUE(
       ParseJpegPicture(reinterpret_cast<const uint8_t*>(jpeg_data_.data()),
@@ -216,7 +227,7 @@
 }
 
 // This test exercises the usual ScopedVAImage lifetime.
-TEST_F(VaapiJpegDecodeAcceleratorTest, ScopedVAImage) {
+TEST_F(VaapiJpegDecoderTest, ScopedVAImage) {
   std::vector<VASurfaceID> va_surfaces;
   const gfx::Size coded_size(64, 64);
   ASSERT_TRUE(wrapper_->CreateContextAndSurfaces(VA_RT_FORMAT_YUV420,
@@ -242,7 +253,7 @@
 }
 
 // This test exercises creation of a ScopedVAImage with a bad VASurfaceID.
-TEST_F(VaapiJpegDecodeAcceleratorTest, BadScopedVAImage) {
+TEST_F(VaapiJpegDecoderTest, BadScopedVAImage) {
   const std::vector<VASurfaceID> va_surfaces = {VA_INVALID_ID};
   const gfx::Size coded_size(64, 64);
 
@@ -265,7 +276,7 @@
 }
 
 // This test exercises creation of a ScopedVABufferMapping with bad VABufferIDs.
-TEST_F(VaapiJpegDecodeAcceleratorTest, BadScopedVABufferMapping) {
+TEST_F(VaapiJpegDecoderTest, BadScopedVABufferMapping) {
   base::AutoLock auto_lock(*GetVaapiWrapperLock());
 
   // A ScopedVABufferMapping with a VA_INVALID_ID VABufferID is DCHECK()ed.
diff --git a/media/gpu/vaapi/vaapi_video_encode_accelerator.cc b/media/gpu/vaapi/vaapi_video_encode_accelerator.cc
index 3c9e636..eea55c6 100644
--- a/media/gpu/vaapi/vaapi_video_encode_accelerator.cc
+++ b/media/gpu/vaapi/vaapi_video_encode_accelerator.cc
@@ -16,6 +16,7 @@
 #include <va/va_enc_vp8.h>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
diff --git a/media/gpu/vaapi/vaapi_wrapper.h b/media/gpu/vaapi/vaapi_wrapper.h
index 07bf1a7..9a0b45a6 100644
--- a/media/gpu/vaapi/vaapi_wrapper.h
+++ b/media/gpu/vaapi/vaapi_wrapper.h
@@ -223,7 +223,7 @@
 
  private:
   friend class base::RefCountedThreadSafe<VaapiWrapper>;
-  friend class VaapiJpegDecodeAcceleratorTest;
+  friend class VaapiJpegDecoderTest;
 
   bool Initialize(CodecMode mode, VAProfile va_profile);
   void Deinitialize();
diff --git a/media/mojo/clients/mojo_renderer.cc b/media/mojo/clients/mojo_renderer.cc
index 717de96..08a4ee0 100644
--- a/media/mojo/clients/mojo_renderer.cc
+++ b/media/mojo/clients/mojo_renderer.cc
@@ -283,7 +283,7 @@
 }
 
 void MojoRenderer::OnRemotePlayStateChange(media::MediaStatus::State state) {
-  DVLOG(2) << __func__ << ": state" << (int)state;
+  DVLOG(2) << __func__ << ": state [" << static_cast<int>(state) << "]";
   client_->OnRemotePlayStateChange(state);
 }
 
diff --git a/media/mojo/services/BUILD.gn b/media/mojo/services/BUILD.gn
index 4e6b4a3..622582d 100644
--- a/media/mojo/services/BUILD.gn
+++ b/media/mojo/services/BUILD.gn
@@ -2,11 +2,10 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chromecast_build.gni")
 import("//build/config/jumbo.gni")
 import("//media/media_options.gni")
-import("//services/catalog/public/tools/catalog.gni")
 import("//services/service_manager/public/cpp/service_executable.gni")
-import("//services/service_manager/public/service_manifest.gni")
 import("//testing/test.gni")
 
 jumbo_component("services") {
@@ -147,14 +146,34 @@
   }
 }
 
-service_manifest("cdm_manifest") {
-  name = "cdm"
-  source = "cdm_manifest.json"
+source_set("cdm_manifest") {
+  sources = [
+    "cdm_manifest.cc",
+    "cdm_manifest.h",
+  ]
+  deps = [
+    "//base",
+    "//media/mojo/interfaces",
+    "//media/mojo/interfaces:constants",
+    "//services/service_manager/public/cpp",
+  ]
 }
 
-service_manifest("media_manifest") {
-  name = "media"
-  source = "media_manifest.json"
+source_set("media_manifest") {
+  sources = [
+    "media_manifest.cc",
+    "media_manifest.h",
+  ]
+  deps = [
+    "//base",
+    "//media/mojo/interfaces",
+    "//media/mojo/interfaces:constants",
+    "//services/service_manager/public/cpp",
+  ]
+  if (is_chromecast) {
+    defines = [ "IS_CHROMECAST" ]
+    deps += [ "//chromecast/common/mojom" ]
+  }
 }
 
 # Unit Tests
@@ -236,7 +255,7 @@
   }
 
   deps = [
-    ":service_tests_catalog_source",
+    ":media_manifest",
     ":services",
     "//base",
     "//base/test:test_support",
@@ -247,6 +266,7 @@
     "//media/mojo/interfaces",
     "//media/mojo/interfaces:constants",
     "//mojo/core/test:run_all_unittests",
+    "//services/service_manager/public/cpp",
     "//services/service_manager/public/cpp/test:test_support",
     "//testing/gmock",
     "//testing/gtest",
@@ -257,23 +277,6 @@
   ]
 }
 
-service_manifest("media_service_unittest_manifest") {
-  name = "media_service_unittests"
-  source = "test_manifest.json"
-}
-
-catalog("service_tests_catalog") {
-  testonly = true
-  embedded_services = [ ":media_service_unittest_manifest" ]
-  standalone_services = [ ":media_manifest" ]
-}
-
-catalog_cpp_source("service_tests_catalog_source") {
-  testonly = true
-  catalog = ":service_tests_catalog"
-  generated_function_name = "media::test::CreateServiceTestCatalog"
-}
-
 # media_pipeline_integration_unittests is out of date and disabled by default.
 test("media_pipeline_integration_unittests") {
   testonly = true
@@ -287,19 +290,3 @@
     ":media",
   ]
 }
-
-service_manifest("pipeline_test_manifest") {
-  name = "media_pipeline_integration_unittests"
-  source = "pipeline_test_manifest.json"
-}
-
-catalog("media_pipeline_integration_unittests_catalog") {
-  embedded_services = [ ":pipeline_test_manifest" ]
-  standalone_services = [ ":media_manifest" ]
-}
-
-catalog_cpp_source("media_pipeline_integration_unittests_catalog_source") {
-  testonly = true
-  catalog = ":media_pipeline_integration_unittests_catalog"
-  generated_function_name = "media::test::CreatePipelineIntegrationTestCatalog"
-}
diff --git a/media/mojo/services/DEPS b/media/mojo/services/DEPS
new file mode 100644
index 0000000..c57f39ec
--- /dev/null
+++ b/media/mojo/services/DEPS
@@ -0,0 +1,6 @@
+specific_include_rules = {
+  "media_manifest\.cc": [
+    "+chromecast/common/mojom",
+  ]
+}
+
diff --git a/media/mojo/services/OWNERS b/media/mojo/services/OWNERS
index 5faebda..228f247 100644
--- a/media/mojo/services/OWNERS
+++ b/media/mojo/services/OWNERS
@@ -1,17 +1,12 @@
-per-file cdm_manifest.json=set noparent
-per-file cdm_manifest.json=file://ipc/SECURITY_OWNERS
+per-file cdm_manifest.cc=set noparent
+per-file cdm_manifest.cc=file://ipc/SECURITY_OWNERS
+per-file cdm_manifest.h=set noparent
+per-file cdm_manifest.h=file://ipc/SECURITY_OWNERS
 
-per-file media_manifest.json=set noparent
-per-file media_manifest.json=file://ipc/SECURITY_OWNERS
-
-per-file pipeline_test_manifest.json=set noparent
-per-file pipeline_test_manifest.json=file://ipc/SECURITY_OWNERS
-
-per-file test_manifest.json=set noparent
-per-file test_manifest.json=file://ipc/SECURITY_OWNERS
-
-per-file pipeline_apptest_manifest.json=set noparent
-per-file pipeline_apptest_manifest.json=file://ipc/SECURITY_OWNERS
+per-file media_manifest.cc=set noparent
+per-file media_manifest.cc=file://ipc/SECURITY_OWNERS
+per-file media_manifest.h=set noparent
+per-file media_manifest.h=file://ipc/SECURITY_OWNERS
 
 per-file mojo_audio_output*=file://media/audio/OWNERS
 per-file mojo_audio_input*=file://media/audio/OWNERS
diff --git a/media/mojo/services/cdm_manifest.cc b/media/mojo/services/cdm_manifest.cc
new file mode 100644
index 0000000..91a0f28
--- /dev/null
+++ b/media/mojo/services/cdm_manifest.cc
@@ -0,0 +1,29 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/mojo/services/cdm_manifest.h"
+
+#include "base/no_destructor.h"
+#include "media/mojo/interfaces/cdm_service.mojom.h"
+#include "media/mojo/interfaces/constants.mojom.h"
+#include "services/service_manager/public/cpp/manifest_builder.h"
+
+namespace media {
+
+const service_manager::Manifest& GetCdmManifest() {
+  static base::NoDestructor<service_manager::Manifest> manifest{
+      service_manager::ManifestBuilder()
+          .WithServiceName(mojom::kCdmServiceName)
+          .WithDisplayName("Content Decryption Module Service")
+          .WithOptions(service_manager::ManifestOptionsBuilder()
+                           .WithSandboxType("cdm")
+                           .Build())
+          .ExposeCapability(
+              "media:cdm",
+              service_manager::Manifest::InterfaceList<mojom::CdmService>())
+          .Build()};
+  return *manifest;
+}
+
+}  // namespace media
diff --git a/media/mojo/services/cdm_manifest.h b/media/mojo/services/cdm_manifest.h
new file mode 100644
index 0000000..b3f02c4
--- /dev/null
+++ b/media/mojo/services/cdm_manifest.h
@@ -0,0 +1,16 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_MOJO_SERVICES_CDM_MANIFEST_H_
+#define MEDIA_MOJO_SERVICES_CDM_MANIFEST_H_
+
+#include "services/service_manager/public/cpp/manifest.h"
+
+namespace media {
+
+const service_manager::Manifest& GetCdmManifest();
+
+}  // namespace media
+
+#endif  // MEDIA_MOJO_SERVICES_CDM_MANIFEST_H_
diff --git a/media/mojo/services/cdm_manifest.json b/media/mojo/services/cdm_manifest.json
deleted file mode 100644
index 78ea3fcc..0000000
--- a/media/mojo/services/cdm_manifest.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-  "name": "cdm",
-  "display_name": "Content Decryption Module Service",
-  "sandbox_type": "cdm",
-  "interface_provider_specs": {
-    "service_manager:connector": {
-      "provides": {
-        "media:cdm": [ "media.mojom.CdmService" ]
-      },
-      "requires": {
-        "*": [ "app" ]
-      }
-    }
-  }
-}
diff --git a/media/mojo/services/media_manifest.cc b/media/mojo/services/media_manifest.cc
new file mode 100644
index 0000000..7fa40040
--- /dev/null
+++ b/media/mojo/services/media_manifest.cc
@@ -0,0 +1,35 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "media/mojo/services/media_manifest.h"
+
+#include "base/no_destructor.h"
+#include "media/mojo/interfaces/constants.mojom.h"
+#include "media/mojo/interfaces/media_service.mojom.h"
+#include "services/service_manager/public/cpp/manifest_builder.h"
+
+#if defined(IS_CHROMECAST)
+#include "chromecast/common/mojom/constants.mojom.h"
+#endif
+
+namespace media {
+
+const service_manager::Manifest& GetMediaManifest() {
+  static base::NoDestructor<service_manager::Manifest> manifest {
+    service_manager::ManifestBuilder()
+        .WithServiceName(mojom::kMediaServiceName)
+        .WithDisplayName("Media Service")
+        .ExposeCapability(
+            "media:media",
+            service_manager::Manifest::InterfaceList<mojom::MediaService>())
+#if defined(IS_CHROMECAST)
+        .RequireCapability(chromecast::mojom::kChromecastServiceName,
+                           "multizone")
+#endif
+        .Build()
+  };
+  return *manifest;
+}
+
+}  // namespace media
diff --git a/media/mojo/services/media_manifest.h b/media/mojo/services/media_manifest.h
new file mode 100644
index 0000000..95c810b
--- /dev/null
+++ b/media/mojo/services/media_manifest.h
@@ -0,0 +1,16 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef MEDIA_MOJO_SERVICES_MEDIA_MANIFEST_H_
+#define MEDIA_MOJO_SERVICES_MEDIA_MANIFEST_H_
+
+#include "services/service_manager/public/cpp/manifest.h"
+
+namespace media {
+
+const service_manager::Manifest& GetMediaManifest();
+
+}  // namespace media
+
+#endif  // MEDIA_MOJO_SERVICES_MEDIA_MANIFEST_H_
diff --git a/media/mojo/services/media_manifest.json b/media/mojo/services/media_manifest.json
deleted file mode 100644
index 3e34a787..0000000
--- a/media/mojo/services/media_manifest.json
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-  "name": "media",
-  "display_name": "Media Service",
-  "interface_provider_specs": {
-    "service_manager:connector": {
-      "provides": {
-        "media:media": [ "media.mojom.MediaService" ]
-      },
-      "requires": {
-        "*": [ "app" ],
-        "chromecast": [ "multizone" ]
-      }
-    }
-  }
-}
diff --git a/media/mojo/services/media_service_unittest.cc b/media/mojo/services/media_service_unittest.cc
index b48c9f8..2a05263 100644
--- a/media/mojo/services/media_service_unittest.cc
+++ b/media/mojo/services/media_service_unittest.cc
@@ -28,9 +28,10 @@
 #include "media/mojo/interfaces/media_service.mojom.h"
 #include "media/mojo/interfaces/renderer.mojom.h"
 #include "media/mojo/services/media_interface_provider.h"
-#include "media/mojo/services/service_tests_catalog_source.h"
+#include "media/mojo/services/media_manifest.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
+#include "services/service_manager/public/cpp/manifest_builder.h"
 #include "services/service_manager/public/cpp/test/test_service.h"
 #include "services/service_manager/public/cpp/test/test_service_manager.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -118,6 +119,8 @@
   base::PostTask(FROM_HERE, run_loop->QuitClosure());
 }
 
+const char kTestServiceName[] = "media_service_unittests";
+
 // Tests MediaService built into a standalone mojo service binary (see
 // ServiceMain() in main.cc) where MediaService uses TestMojoMediaClient.
 // TestMojoMediaClient supports CDM creation using DefaultCdmFactory (only
@@ -126,9 +129,14 @@
 class MediaServiceTest : public testing::Test {
  public:
   MediaServiceTest()
-      : test_service_manager_(test::CreateServiceTestCatalog()),
-        test_service_(test_service_manager_.RegisterTestInstance(
-            "media_service_unittests")),
+      : test_service_manager_(
+            {GetMediaManifest(),
+             service_manager::ManifestBuilder()
+                 .WithServiceName(kTestServiceName)
+                 .RequireCapability(mojom::kMediaServiceName, "media:media")
+                 .Build()}),
+        test_service_(
+            test_service_manager_.RegisterTestInstance(kTestServiceName)),
         cdm_proxy_client_binding_(&cdm_proxy_client_),
         renderer_client_binding_(&renderer_client_),
         video_stream_(DemuxerStream::VIDEO) {}
diff --git a/media/mojo/services/mojo_video_encode_accelerator_service_unittest.cc b/media/mojo/services/mojo_video_encode_accelerator_service_unittest.cc
index ba61772..592feda 100644
--- a/media/mojo/services/mojo_video_encode_accelerator_service_unittest.cc
+++ b/media/mojo/services/mojo_video_encode_accelerator_service_unittest.cc
@@ -5,6 +5,7 @@
 #include <stddef.h>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
 #include "gpu/config/gpu_preferences.h"
diff --git a/media/mojo/services/pipeline_apptest_manifest.json b/media/mojo/services/pipeline_apptest_manifest.json
deleted file mode 100644
index 29db9c4..0000000
--- a/media/mojo/services/pipeline_apptest_manifest.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "name": "media_pipeline_integration_apptests",
-  "display_name": "Media Pipeline Integration Apptests",
-  "interface_provider_specs": {
-    "service_manager:connector": {
-      "requires": {
-        "*": [ "app" ]
-      }
-    }
-  }
-}
diff --git a/media/mojo/services/pipeline_test_manifest.json b/media/mojo/services/pipeline_test_manifest.json
deleted file mode 100644
index 86b0441..0000000
--- a/media/mojo/services/pipeline_test_manifest.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "name": "media_pipeline_integration_unittests",
-  "display_name": "Media Pipeline Integration Unittests",
-  "interface_provider_specs": {
-    "service_manager:connector": {
-      "requires": {
-        "*": [ "app" ]
-      }
-    }
-  }
-}
diff --git a/media/mojo/services/test_manifest.json b/media/mojo/services/test_manifest.json
deleted file mode 100644
index 1ff56985..0000000
--- a/media/mojo/services/test_manifest.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "name": "media_service_unittests",
-  "display_name": "Media Service Unittests",
-  "interface_provider_specs": {
-    "service_manager:connector": {
-      "requires": {
-        "*": [ "app" ],
-        "media": [ "media:media" ]
-      }
-    }
-  }
-}
diff --git a/media/remoting/integration_test.cc b/media/remoting/integration_test.cc
index 45d80f9..6086d81 100644
--- a/media/remoting/integration_test.cc
+++ b/media/remoting/integration_test.cc
@@ -6,8 +6,8 @@
 
 #include "media/base/test_data_util.h"
 #include "media/remoting/end2end_test_renderer.h"
-#include "media/test/mock_media_source.h"
 #include "media/test/pipeline_integration_test_base.h"
+#include "media/test/test_media_source.h"
 
 namespace media {
 namespace remoting {
@@ -64,7 +64,7 @@
 }
 
 TEST_F(MediaRemotingIntegrationTest, BasicPlayback_MediaSource) {
-  MockMediaSource source("bear-320x240.webm", 219229);
+  TestMediaSource source("bear-320x240.webm", 219229);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
   source.EndOfStream();
 
@@ -75,7 +75,7 @@
 }
 
 TEST_F(MediaRemotingIntegrationTest, MediaSource_ConfigChange_WebM) {
-  MockMediaSource source("bear-320x240-16x9-aspect.webm", kAppendWholeFile);
+  TestMediaSource source("bear-320x240-16x9-aspect.webm", kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
 
   EXPECT_CALL(*this, OnVideoNaturalSizeChange(gfx::Size(640, 360))).Times(1);
diff --git a/media/test/BUILD.gn b/media/test/BUILD.gn
index 5bd9de49..e5b8361 100644
--- a/media/test/BUILD.gn
+++ b/media/test/BUILD.gn
@@ -31,10 +31,10 @@
     sources = [
       "fake_encrypted_media.cc",
       "fake_encrypted_media.h",
-      "mock_media_source.cc",
-      "mock_media_source.h",
       "pipeline_integration_test_base.cc",
       "pipeline_integration_test_base.h",
+      "test_media_source.cc",
+      "test_media_source.h",
     ]
 
     configs += [ "//media:media_config" ]
@@ -124,8 +124,10 @@
       "//media:test_support",
       "//media/mojo/clients",
       "//media/mojo/interfaces",
+      "//media/mojo/interfaces:constants",
       "//media/mojo/services",
-      "//media/mojo/services:media_pipeline_integration_unittests_catalog_source",
+      "//media/mojo/services:media_manifest",
+      "//services/service_manager/public/cpp",
       "//services/service_manager/public/cpp/test:test_support",
       "//testing/gtest",
       "//third_party/libaom:av1_buildflags",
diff --git a/media/test/pipeline_integration_fuzzertest.cc b/media/test/pipeline_integration_fuzzertest.cc
index d960185e..843b55f 100644
--- a/media/test/pipeline_integration_fuzzertest.cc
+++ b/media/test/pipeline_integration_fuzzertest.cc
@@ -19,8 +19,8 @@
 #include "media/base/media.h"
 #include "media/base/media_switches.h"
 #include "media/base/pipeline_status.h"
-#include "media/test/mock_media_source.h"
 #include "media/test/pipeline_integration_test_base.h"
+#include "media/test/test_media_source.h"
 #include "third_party/libaom/av1_buildflags.h"
 
 namespace {
@@ -191,7 +191,7 @@
     scoped_refptr<media::DecoderBuffer> buffer(
         DecoderBuffer::CopyFrom(data, size));
 
-    MockMediaSource source(buffer, mimetype, kAppendWholeFile);
+    TestMediaSource source(buffer, mimetype, kAppendWholeFile);
 
     // Prevent timeout in the case of not enough media appended to complete
     // demuxer initialization, yet no error in the media appended.  The
@@ -203,9 +203,9 @@
         base::Bind(&OnEncryptedMediaInitData, this));
 
     // Allow parsing to either pass or fail without emitting a gtest failure
-    // from MockMediaSource.
+    // from TestMediaSource.
     source.set_expected_append_result(
-        MockMediaSource::ExpectedAppendResult::kSuccessOrFailure);
+        TestMediaSource::ExpectedAppendResult::kSuccessOrFailure);
 
     // TODO(wolenetz): Vary the behavior (abort/remove/seek/endOfStream/Append
     // in pieces/append near play-head/vary append mode/etc), perhaps using
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc
index ca905fdb..a8e58c7 100644
--- a/media/test/pipeline_integration_test.cc
+++ b/media/test/pipeline_integration_test.cc
@@ -32,17 +32,19 @@
 #include "media/media_buildflags.h"
 #include "media/renderers/renderer_impl.h"
 #include "media/test/fake_encrypted_media.h"
-#include "media/test/mock_media_source.h"
 #include "media/test/pipeline_integration_test_base.h"
+#include "media/test/test_media_source.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "third_party/libaom/av1_buildflags.h"
 #include "url/gurl.h"
 
 #if defined(MOJO_RENDERER)
 #include "media/mojo/clients/mojo_renderer.h"
+#include "media/mojo/interfaces/constants.mojom.h"  // nogncheck
 #include "media/mojo/interfaces/interface_factory.mojom.h"
 #include "media/mojo/interfaces/renderer.mojom.h"
-#include "media/mojo/services/media_pipeline_integration_unittests_catalog_source.h"  // nogncheck
+#include "media/mojo/services/media_manifest.h"                    // nogncheck
+#include "services/service_manager/public/cpp/manifest_builder.h"  // nogncheck
 #include "services/service_manager/public/cpp/test/test_service.h"  // nogncheck
 #include "services/service_manager/public/cpp/test/test_service_manager.h"  // nogncheck
 
@@ -411,13 +413,20 @@
 //               preferably by eliminating multiple inheritance here which is
 //               banned by Google C++ style.
 #if defined(MOJO_RENDERER) && defined(ENABLE_MOJO_PIPELINE_INTEGRATION_TEST)
+const char kTestServiceName[] = "media_pipeline_integration_unittests";
+
 class PipelineIntegrationTest : public testing::Testing,
                                 public PipelineIntegrationTestBase {
  public:
   PipelineIntegrationTest()
-      : test_service_manager_(test::CreatePipelineIntegrationTestCatalog()),
-        test_service_(test_service_manager_.RegisterTestInstance(
-            "media_pipeline_integration_shelltests")) {}
+      : test_service_manager_(
+            {GetMediaManifest(),
+             service_manager::ManifestBuilder()
+                 .WithServiceName(kTestServiceName)
+                 .RequireCapability(mojom::kMediaServiceName, "media:media")
+                 .Build()}),
+        test_service_(
+            test_service_manager_.RegisterTestInstance(kTestServiceName)) {}
 
   void SetUp() override {
     InitializeMediaLibrary();
@@ -427,7 +436,7 @@
   std::unique_ptr<Renderer> CreateRenderer(
       CreateVideoDecodersCB prepend_video_decoders_cb,
       CreateAudioDecodersCB prepend_audio_decoders_cb) override {
-    test_service_.connector()->BindInterface("media",
+    test_service_.connector()->BindInterface(mojom::kMediaServiceName,
                                              &media_interface_factory_);
 
     mojom::RendererPtr mojo_renderer;
@@ -456,7 +465,7 @@
                           base::TimeDelta seek_time,
                           int seek_file_position,
                           int seek_append_size) {
-    MockMediaSource source(filename, initial_append_size);
+    TestMediaSource source(filename, initial_append_size);
 
     if (StartPipelineWithMediaSource(&source, kNoClockless, nullptr) !=
         PIPELINE_OK) {
@@ -528,7 +537,7 @@
   void PlayToEnd() {
     MSEPlaybackTestData data = GetParam();
 
-    MockMediaSource source(data.filename, data.append_bytes);
+    TestMediaSource source(data.filename, data.append_bytes);
     ASSERT_EQ(PIPELINE_OK,
               StartPipelineWithMediaSource(&source, kNormal, nullptr));
     source.EndOfStream();
@@ -648,7 +657,7 @@
     // TODO(wolenetz): Switch back to 'segments' mode once we have some
     // incubation of a way to flexibly allow playback through unbuffered
     // regions. Known test media requiring sequence mode: MP3-in-MP2T
-    MockMediaSource source(file_one.filename, file_one.append_bytes, true);
+    TestMediaSource source(file_one.filename, file_one.append_bytes, true);
     ASSERT_EQ(PIPELINE_OK,
               StartPipelineWithMediaSource(&source, kNormal, nullptr));
     source.EndOfStream();
@@ -1158,7 +1167,7 @@
 }
 
 TEST_P(MSEPipelineIntegrationTest, BasicPlaybackOpusWebmTrimmingHashed) {
-  MockMediaSource source("opus-trimming-test.webm", kAppendWholeFile);
+  TestMediaSource source("opus-trimming-test.webm", kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK,
             StartPipelineWithMediaSource(&source, kHashed, nullptr));
   source.EndOfStream();
@@ -1187,7 +1196,7 @@
 }
 
 TEST_P(MSEPipelineIntegrationTest, BasicPlaybackOpusMp4TrimmingHashed) {
-  MockMediaSource source("opus-trimming-test.mp4", kAppendWholeFile);
+  TestMediaSource source("opus-trimming-test.mp4", kAppendWholeFile);
 
   // TODO(dalecurtis): The test clip currently does not have the edit list
   // entries required to achieve correctness here, so we're manually specifying
@@ -1297,7 +1306,7 @@
 }
 
 TEST_P(MSEPipelineIntegrationTest, BasicPlaybackOpusPrerollExceedsCodecDelay) {
-  MockMediaSource source("bear-opus.webm", kAppendWholeFile);
+  TestMediaSource source("bear-opus.webm", kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK,
             StartPipelineWithMediaSource(&source, kHashed, nullptr));
   source.EndOfStream();
@@ -1326,7 +1335,7 @@
 
 TEST_P(MSEPipelineIntegrationTest,
        BasicPlaybackOpusMp4PrerollExceedsCodecDelay) {
-  MockMediaSource source("bear-opus.mp4", kAppendWholeFile);
+  TestMediaSource source("bear-opus.mp4", kAppendWholeFile);
 
   // TODO(dalecurtis): The test clip currently does not have the edit list
   // entries required to achieve correctness here, so we're manually specifying
@@ -1420,7 +1429,7 @@
 }
 
 TEST_P(MSEPipelineIntegrationTest, BasicPlayback) {
-  MockMediaSource source("bear-320x240.webm", 219229);
+  TestMediaSource source("bear-320x240.webm", 219229);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
   source.EndOfStream();
 
@@ -1443,7 +1452,7 @@
   // stream should let the test complete with error indicating failure to open
   // demuxer. Here we append only the first 10 bytes of a test WebM, definitely
   // less than the ~4400 bytes needed to parse its full initialization segment.
-  MockMediaSource source("bear-320x240.webm", 10);
+  TestMediaSource source("bear-320x240.webm", 10);
   source.set_do_eos_after_next_append(true);
   EXPECT_EQ(
       DEMUXER_ERROR_COULD_NOT_OPEN,
@@ -1454,16 +1463,16 @@
   // After successful initialization segment append completing demuxer opening,
   // immediately append a corrupted media segment to trigger parse error while
   // pipeline is still completing renderer setup.
-  MockMediaSource source("bear-320x240_corrupted_after_init_segment.webm",
+  TestMediaSource source("bear-320x240_corrupted_after_init_segment.webm",
                          4380);
   source.set_expected_append_result(
-      MockMediaSource::ExpectedAppendResult::kFailure);
+      TestMediaSource::ExpectedAppendResult::kFailure);
   EXPECT_EQ(CHUNK_DEMUXER_ERROR_APPEND_FAILED,
             StartPipelineWithMediaSource(&source));
 }
 
 TEST_P(MSEPipelineIntegrationTest, BasicPlayback_Live) {
-  MockMediaSource source("bear-320x240-live.webm", 219221);
+  TestMediaSource source("bear-320x240-live.webm", 219221);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
   source.EndOfStream();
 
@@ -1483,7 +1492,7 @@
 
 #if BUILDFLAG(ENABLE_AV1_DECODER)
 TEST_P(MSEPipelineIntegrationTest, BasicPlayback_AV1_WebM) {
-  MockMediaSource source("bear-av1.webm", 18898);
+  TestMediaSource source("bear-av1.webm", 18898);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
   source.EndOfStream();
 
@@ -1500,7 +1509,7 @@
 }
 
 TEST_P(MSEPipelineIntegrationTest, BasicPlayback_AV1_10bit_WebM) {
-  MockMediaSource source("bear-av1-320x180-10bit.webm", 19076);
+  TestMediaSource source("bear-av1-320x180-10bit.webm", 19076);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
   source.EndOfStream();
 
@@ -1520,7 +1529,7 @@
 #endif
 
 TEST_P(MSEPipelineIntegrationTest, BasicPlayback_VP9_WebM) {
-  MockMediaSource source("bear-vp9.webm", 67504);
+  TestMediaSource source("bear-vp9.webm", 67504);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
   source.EndOfStream();
 
@@ -1537,7 +1546,7 @@
 }
 
 TEST_P(MSEPipelineIntegrationTest, BasicPlayback_VP9_BlockGroup_WebM) {
-  MockMediaSource source("bear-vp9-blockgroup.webm", 67871);
+  TestMediaSource source("bear-vp9-blockgroup.webm", 67871);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
   source.EndOfStream();
 
@@ -1554,7 +1563,7 @@
 }
 
 TEST_P(MSEPipelineIntegrationTest, BasicPlayback_VP8A_WebM) {
-  MockMediaSource source("bear-vp8a.webm", kAppendWholeFile);
+  TestMediaSource source("bear-vp8a.webm", kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
   source.EndOfStream();
 
@@ -1572,7 +1581,7 @@
 
 #if BUILDFLAG(ENABLE_AV1_DECODER)
 TEST_P(MSEPipelineIntegrationTest, ConfigChange_AV1_WebM) {
-  MockMediaSource source("bear-av1-480x360.webm", kAppendWholeFile);
+  TestMediaSource source("bear-av1-480x360.webm", kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
 
   const gfx::Size kNewSize(640, 480);
@@ -1600,7 +1609,7 @@
 #endif  // BUILDFLAG(ENABLE_AV1_DECODER)
 
 TEST_P(MSEPipelineIntegrationTest, ConfigChange_WebM) {
-  MockMediaSource source("bear-320x240-16x9-aspect.webm", kAppendWholeFile);
+  TestMediaSource source("bear-320x240-16x9-aspect.webm", kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
 
   const gfx::Size kNewSize(640, 360);
@@ -1627,7 +1636,7 @@
 }
 
 TEST_P(MSEPipelineIntegrationTest, AudioConfigChange_WebM) {
-  MockMediaSource source("bear-320x240-audio-only.webm", kAppendWholeFile);
+  TestMediaSource source("bear-320x240-audio-only.webm", kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
 
   const int kNewSampleRate = 48000;
@@ -1661,7 +1670,7 @@
 }
 
 TEST_P(MSEPipelineIntegrationTest, Remove_Updates_BufferedRanges) {
-  MockMediaSource source("bear-320x240.webm", kAppendWholeFile);
+  TestMediaSource source("bear-320x240.webm", kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
 
   auto buffered_ranges = pipeline_->GetBufferedTimeRanges();
@@ -1690,7 +1699,7 @@
 // will no longer start at 0.
 TEST_P(MSEPipelineIntegrationTest, FillUp_Buffer) {
   const char* input_filename = "bear-320x240.webm";
-  MockMediaSource source(input_filename, kAppendWholeFile);
+  TestMediaSource source(input_filename, kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
   source.SetMemoryLimits(1048576);
 
@@ -1719,7 +1728,7 @@
 
 TEST_P(MSEPipelineIntegrationTest, GCWithDisabledVideoStream) {
   const char* input_filename = "bear-320x240.webm";
-  MockMediaSource source(input_filename, kAppendWholeFile);
+  TestMediaSource source(input_filename, kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
   scoped_refptr<DecoderBuffer> file = ReadTestDataFile(input_filename);
   // The input file contains audio + video data. Assuming video data size is
@@ -1749,7 +1758,7 @@
 
 MAYBE_EME_TEST_P(MSEPipelineIntegrationTest,
                  MAYBE_EME(ConfigChange_Encrypted_WebM)) {
-  MockMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm",
+  TestMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm",
                          kAppendWholeFile);
   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   EXPECT_EQ(PIPELINE_OK,
@@ -1781,7 +1790,7 @@
 
 MAYBE_EME_TEST_P(MSEPipelineIntegrationTest,
                  MAYBE_EME(ConfigChange_ClearThenEncrypted_WebM)) {
-  MockMediaSource source("bear-320x240-16x9-aspect.webm", kAppendWholeFile);
+  TestMediaSource source("bear-320x240-16x9-aspect.webm", kAppendWholeFile);
   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   EXPECT_EQ(PIPELINE_OK,
             StartPipelineWithEncryptedMedia(&source, &encrypted_media));
@@ -1814,7 +1823,7 @@
 // supported by the Renderer.
 MAYBE_EME_TEST_P(MSEPipelineIntegrationTest,
                  MAYBE_EME(ConfigChange_EncryptedThenClear_WebM)) {
-  MockMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm",
+  TestMediaSource source("bear-320x240-16x9-aspect-av_enc-av.webm",
                          kAppendWholeFile);
   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   EXPECT_EQ(PIPELINE_OK,
@@ -1864,7 +1873,7 @@
 
 #if BUILDFLAG(ENABLE_AV1_DECODER)
 TEST_P(MSEPipelineIntegrationTest, BasicPlayback_AV1_MP4) {
-  MockMediaSource source("bear-av1.mp4", 24355);
+  TestMediaSource source("bear-av1.mp4", 24355);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
   source.EndOfStream();
 
@@ -1881,7 +1890,7 @@
 }
 
 TEST_P(MSEPipelineIntegrationTest, BasicPlayback_AV1_10bit_MP4) {
-  MockMediaSource source("bear-av1-320x180-10bit.mp4", 19658);
+  TestMediaSource source("bear-av1-320x180-10bit.mp4", 19658);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
   source.EndOfStream();
 
@@ -1900,7 +1909,7 @@
 #endif
 
 TEST_P(MSEPipelineIntegrationTest, FlacInMp4_Hashed) {
-  MockMediaSource source("sfx-flac_frag.mp4", kAppendWholeFile);
+  TestMediaSource source("sfx-flac_frag.mp4", kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK,
             StartPipelineWithMediaSource(&source, kHashed, nullptr));
   source.EndOfStream();
@@ -2010,7 +2019,7 @@
                                         "-0.22,0.80,1.19,0.73,-0.31,-1.12,")));
 
 TEST_P(MSEPipelineIntegrationTest, MP3) {
-  MockMediaSource source("sfx.mp3", kAppendWholeFile);
+  TestMediaSource source("sfx.mp3", kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK,
             StartPipelineWithMediaSource(&source, kHashed, nullptr));
   source.EndOfStream();
@@ -2028,7 +2037,7 @@
 }
 
 TEST_P(MSEPipelineIntegrationTest, MP3_TimestampOffset) {
-  MockMediaSource source("sfx.mp3", kAppendWholeFile);
+  TestMediaSource source("sfx.mp3", kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
   EXPECT_EQ(313, source.last_timestamp_offset().InMilliseconds());
 
@@ -2055,7 +2064,7 @@
 }
 
 TEST_P(MSEPipelineIntegrationTest, MP3_Icecast) {
-  MockMediaSource source("icy_sfx.mp3", kAppendWholeFile);
+  TestMediaSource source("icy_sfx.mp3", kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
   source.EndOfStream();
 
@@ -2067,7 +2076,7 @@
 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
 
 TEST_P(MSEPipelineIntegrationTest, ADTS) {
-  MockMediaSource source("sfx.adts", kAppendWholeFile);
+  TestMediaSource source("sfx.adts", kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK,
             StartPipelineWithMediaSource(&source, kHashed, nullptr));
   source.EndOfStream();
@@ -2085,7 +2094,7 @@
 }
 
 TEST_P(MSEPipelineIntegrationTest, ADTS_TimestampOffset) {
-  MockMediaSource source("sfx.adts", kAppendWholeFile);
+  TestMediaSource source("sfx.adts", kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK,
             StartPipelineWithMediaSource(&source, kHashed, nullptr));
   EXPECT_EQ(325, source.last_timestamp_offset().InMilliseconds());
@@ -2172,7 +2181,7 @@
 };
 
 TEST_P(MSEPipelineIntegrationTest, ConfigChange_MP4) {
-  MockMediaSource source("bear-640x360-av_frag.mp4", kAppendWholeFile);
+  TestMediaSource source("bear-640x360-av_frag.mp4", kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
 
   const gfx::Size kNewSize(1280, 720);
@@ -2205,7 +2214,7 @@
 
 MAYBE_EME_TEST_P(MSEPipelineIntegrationTest,
                  MAYBE_EME(ConfigChange_Encrypted_MP4_CENC_VideoOnly)) {
-  MockMediaSource source("bear-640x360-v_frag-cenc-mdat.mp4", kAppendWholeFile);
+  TestMediaSource source("bear-640x360-v_frag-cenc-mdat.mp4", kAppendWholeFile);
   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   EXPECT_EQ(PIPELINE_OK,
             StartPipelineWithEncryptedMedia(&source, &encrypted_media));
@@ -2239,7 +2248,7 @@
 MAYBE_EME_TEST_P(
     MSEPipelineIntegrationTest,
     MAYBE_EME(ConfigChange_Encrypted_MP4_CENC_KeyRotation_VideoOnly)) {
-  MockMediaSource source("bear-640x360-v_frag-cenc-key_rotation.mp4",
+  TestMediaSource source("bear-640x360-v_frag-cenc-key_rotation.mp4",
                          kAppendWholeFile);
   FakeEncryptedMedia encrypted_media(new RotatingKeyProvidingApp());
   EXPECT_EQ(PIPELINE_OK,
@@ -2269,7 +2278,7 @@
 
 TEST_P(MSEPipelineIntegrationTest,
        MAYBE_EME(ConfigChange_ClearThenEncrypted_MP4_CENC)) {
-  MockMediaSource source("bear-640x360-v_frag.mp4", kAppendWholeFile);
+  TestMediaSource source("bear-640x360-v_frag.mp4", kAppendWholeFile);
   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   EXPECT_EQ(PIPELINE_OK,
             StartPipelineWithEncryptedMedia(&source, &encrypted_media));
@@ -2278,7 +2287,7 @@
   scoped_refptr<DecoderBuffer> second_file =
       ReadTestDataFile("bear-1280x720-v_frag-cenc.mp4");
   source.set_expected_append_result(
-      MockMediaSource::ExpectedAppendResult::kFailure);
+      TestMediaSource::ExpectedAppendResult::kFailure);
   source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
                       second_file->data(), second_file->data_size());
 
@@ -2302,7 +2311,7 @@
 // Config changes from encrypted to clear are not currently supported.
 MAYBE_EME_TEST_P(MSEPipelineIntegrationTest,
                  MAYBE_EME(ConfigChange_EncryptedThenClear_MP4_CENC)) {
-  MockMediaSource source("bear-640x360-v_frag-cenc-mdat.mp4", kAppendWholeFile);
+  TestMediaSource source("bear-640x360-v_frag-cenc-mdat.mp4", kAppendWholeFile);
   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   EXPECT_EQ(PIPELINE_OK,
             StartPipelineWithEncryptedMedia(&source, &encrypted_media));
@@ -2311,7 +2320,7 @@
       ReadTestDataFile("bear-1280x720-av_frag.mp4");
 
   source.set_expected_append_result(
-      MockMediaSource::ExpectedAppendResult::kFailure);
+      TestMediaSource::ExpectedAppendResult::kFailure);
   source.AppendAtTime(base::TimeDelta::FromSeconds(kAppendTimeSec),
                       second_file->data(), second_file->data_size());
 
@@ -2354,7 +2363,7 @@
 
 MAYBE_EME_TEST_P(MSEPipelineIntegrationTest,
                  MAYBE_EME(EncryptedPlayback_WebM)) {
-  MockMediaSource source("bear-320x240-av_enc-av.webm", 219816);
+  TestMediaSource source("bear-320x240-av_enc-av.webm", 219816);
   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   EXPECT_EQ(PIPELINE_OK,
             StartPipelineWithEncryptedMedia(&source, &encrypted_media));
@@ -2371,7 +2380,7 @@
 
 MAYBE_EME_TEST_P(MSEPipelineIntegrationTest,
                  MAYBE_EME(EncryptedPlayback_ClearStart_WebM)) {
-  MockMediaSource source("bear-320x240-av_enc-av_clear-1s.webm",
+  TestMediaSource source("bear-320x240-av_enc-av_clear-1s.webm",
                          kAppendWholeFile);
   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   EXPECT_EQ(PIPELINE_OK,
@@ -2389,7 +2398,7 @@
 
 MAYBE_EME_TEST_P(MSEPipelineIntegrationTest,
                  MAYBE_EME(EncryptedPlayback_NoEncryptedFrames_WebM)) {
-  MockMediaSource source("bear-320x240-av_enc-av_clear-all.webm",
+  TestMediaSource source("bear-320x240-av_enc-av_clear-all.webm",
                          kAppendWholeFile);
   FakeEncryptedMedia encrypted_media(new NoResponseApp());
   EXPECT_EQ(PIPELINE_OK,
@@ -2407,7 +2416,7 @@
 
 MAYBE_EME_TEST_P(MSEPipelineIntegrationTest,
                  MAYBE_EME(EncryptedPlayback_MP4_VP9_CENC_VideoOnly)) {
-  MockMediaSource source("bear-320x240-v_frag-vp9-cenc.mp4", kAppendWholeFile);
+  TestMediaSource source("bear-320x240-v_frag-vp9-cenc.mp4", kAppendWholeFile);
   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   EXPECT_EQ(PIPELINE_OK,
             StartPipelineWithEncryptedMedia(&source, &encrypted_media));
@@ -2422,7 +2431,7 @@
 }
 
 TEST_P(MSEPipelineIntegrationTest, BasicPlayback_VideoOnly_MP4_VP9) {
-  MockMediaSource source("bear-320x240-v_frag-vp9.mp4", kAppendWholeFile);
+  TestMediaSource source("bear-320x240-v_frag-vp9.mp4", kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
   source.EndOfStream();
   ASSERT_EQ(PIPELINE_OK, pipeline_status_);
@@ -2437,7 +2446,7 @@
 #if BUILDFLAG(USE_PROPRIETARY_CODECS)
 MAYBE_EME_TEST_P(MSEPipelineIntegrationTest,
                  MAYBE_EME(EncryptedPlayback_MP4_CENC_VideoOnly)) {
-  MockMediaSource source("bear-1280x720-v_frag-cenc.mp4", kAppendWholeFile);
+  TestMediaSource source("bear-1280x720-v_frag-cenc.mp4", kAppendWholeFile);
   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   EXPECT_EQ(PIPELINE_OK,
             StartPipelineWithEncryptedMedia(&source, &encrypted_media));
@@ -2454,7 +2463,7 @@
 
 MAYBE_EME_TEST_P(MSEPipelineIntegrationTest,
                  MAYBE_EME(EncryptedPlayback_MP4_CENC_AudioOnly)) {
-  MockMediaSource source("bear-1280x720-a_frag-cenc.mp4", kAppendWholeFile);
+  TestMediaSource source("bear-1280x720-a_frag-cenc.mp4", kAppendWholeFile);
   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   EXPECT_EQ(PIPELINE_OK,
             StartPipelineWithEncryptedMedia(&source, &encrypted_media));
@@ -2472,7 +2481,7 @@
 MAYBE_EME_TEST_P(
     MSEPipelineIntegrationTest,
     MAYBE_EME(EncryptedPlayback_NoEncryptedFrames_MP4_CENC_VideoOnly)) {
-  MockMediaSource source("bear-1280x720-v_frag-cenc_clear-all.mp4",
+  TestMediaSource source("bear-1280x720-v_frag-cenc_clear-all.mp4",
                          kAppendWholeFile);
   FakeEncryptedMedia encrypted_media(new NoResponseApp());
   EXPECT_EQ(PIPELINE_OK,
@@ -2488,7 +2497,7 @@
 }
 
 TEST_P(MSEPipelineIntegrationTest, Mp2ts_AAC_HE_SBR_Audio) {
-  MockMediaSource source("bear-1280x720-aac_he.ts", kAppendWholeFile);
+  TestMediaSource source("bear-1280x720-aac_he.ts", kAppendWholeFile);
 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
   source.EndOfStream();
@@ -2507,7 +2516,7 @@
 }
 
 TEST_P(MSEPipelineIntegrationTest, Mpeg2ts_MP3Audio_Mp4a_6B) {
-  MockMediaSource source("bear-audio-mp4a.6B.ts",
+  TestMediaSource source("bear-audio-mp4a.6B.ts",
                          "video/mp2t; codecs=\"mp4a.6B\"", kAppendWholeFile);
 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
@@ -2521,7 +2530,7 @@
 }
 
 TEST_P(MSEPipelineIntegrationTest, Mpeg2ts_MP3Audio_Mp4a_69) {
-  MockMediaSource source("bear-audio-mp4a.69.ts",
+  TestMediaSource source("bear-audio-mp4a.69.ts",
                          "video/mp2t; codecs=\"mp4a.69\"", kAppendWholeFile);
 #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER)
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
@@ -2537,7 +2546,7 @@
 MAYBE_EME_TEST_P(
     MSEPipelineIntegrationTest,
     MAYBE_EME(EncryptedPlayback_NoEncryptedFrames_MP4_CENC_AudioOnly)) {
-  MockMediaSource source("bear-1280x720-a_frag-cenc_clear-all.mp4",
+  TestMediaSource source("bear-1280x720-a_frag-cenc_clear-all.mp4",
                          kAppendWholeFile);
   FakeEncryptedMedia encrypted_media(new NoResponseApp());
   EXPECT_EQ(PIPELINE_OK,
@@ -2556,7 +2565,7 @@
 // beginning of mdat box.
 MAYBE_EME_TEST_P(MSEPipelineIntegrationTest,
                  MAYBE_EME(EncryptedPlayback_MP4_CENC_MDAT_Video)) {
-  MockMediaSource source("bear-640x360-v_frag-cenc-mdat.mp4", kAppendWholeFile);
+  TestMediaSource source("bear-640x360-v_frag-cenc-mdat.mp4", kAppendWholeFile);
   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   EXPECT_EQ(PIPELINE_OK,
             StartPipelineWithEncryptedMedia(&source, &encrypted_media));
@@ -2572,7 +2581,7 @@
 
 MAYBE_EME_TEST_P(MSEPipelineIntegrationTest,
                  MAYBE_EME(EncryptedPlayback_MP4_CENC_SENC_Video)) {
-  MockMediaSource source("bear-640x360-v_frag-cenc-senc.mp4", kAppendWholeFile);
+  TestMediaSource source("bear-640x360-v_frag-cenc-senc.mp4", kAppendWholeFile);
   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   EXPECT_EQ(PIPELINE_OK,
             StartPipelineWithEncryptedMedia(&source, &encrypted_media));
@@ -2594,7 +2603,7 @@
 MAYBE_EME_TEST_P(
     MSEPipelineIntegrationTest,
     MAYBE_EME(EncryptedPlayback_MP4_CENC_SENC_NO_SAIZ_SAIO_Video)) {
-  MockMediaSource source("bear-640x360-v_frag-cenc-senc-no-saiz-saio.mp4",
+  TestMediaSource source("bear-640x360-v_frag-cenc-senc-no-saiz-saio.mp4",
                          kAppendWholeFile);
   FakeEncryptedMedia encrypted_media(new KeyProvidingApp());
   EXPECT_EQ(PIPELINE_OK,
@@ -2611,7 +2620,7 @@
 
 MAYBE_EME_TEST_P(MSEPipelineIntegrationTest,
                  MAYBE_EME(EncryptedPlayback_MP4_CENC_KeyRotation_Video)) {
-  MockMediaSource source("bear-1280x720-v_frag-cenc-key_rotation.mp4",
+  TestMediaSource source("bear-1280x720-v_frag-cenc-key_rotation.mp4",
                          kAppendWholeFile);
   FakeEncryptedMedia encrypted_media(new RotatingKeyProvidingApp());
   EXPECT_EQ(PIPELINE_OK,
@@ -2628,7 +2637,7 @@
 
 MAYBE_EME_TEST_P(MSEPipelineIntegrationTest,
                  MAYBE_EME(EncryptedPlayback_MP4_CENC_KeyRotation_Audio)) {
-  MockMediaSource source("bear-1280x720-a_frag-cenc-key_rotation.mp4",
+  TestMediaSource source("bear-1280x720-a_frag-cenc-key_rotation.mp4",
                          kAppendWholeFile);
   FakeEncryptedMedia encrypted_media(new RotatingKeyProvidingApp());
   EXPECT_EQ(PIPELINE_OK,
@@ -2644,7 +2653,7 @@
 }
 
 TEST_P(MSEPipelineIntegrationTest, BasicPlayback_VideoOnly_MP4_AVC3) {
-  MockMediaSource source("bear-1280x720-v_frag-avc3.mp4", kAppendWholeFile);
+  TestMediaSource source("bear-1280x720-v_frag-avc3.mp4", kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
   source.EndOfStream();
 
@@ -2667,7 +2676,7 @@
   // to actually demux and decode the stream. On platforms that support both
   // demuxing and decoding we'll get PIPELINE_OK.
   const char kMp4HevcVideoOnly[] = "video/mp4; codecs=\"hvc1.1.6.L93.B0\"";
-  MockMediaSource source("bear-320x240-v_frag-hevc.mp4", kMp4HevcVideoOnly,
+  TestMediaSource source("bear-320x240-v_frag-hevc.mp4", kMp4HevcVideoOnly,
                          kAppendWholeFile);
 #if BUILDFLAG(ENABLE_HEVC_DEMUXING)
   PipelineStatus status = StartPipelineWithMediaSource(&source);
@@ -2682,7 +2691,7 @@
 // Same test as above but using a different mime type.
 TEST_P(MSEPipelineIntegrationTest, BasicPlayback_VideoOnly_MP4_HEV1) {
   const char kMp4Hev1VideoOnly[] = "video/mp4; codecs=\"hev1.1.6.L93.B0\"";
-  MockMediaSource source("bear-320x240-v_frag-hevc.mp4", kMp4Hev1VideoOnly,
+  TestMediaSource source("bear-320x240-v_frag-hevc.mp4", kMp4Hev1VideoOnly,
                          kAppendWholeFile);
 #if BUILDFLAG(ENABLE_HEVC_DEMUXING)
   PipelineStatus status = StartPipelineWithMediaSource(&source);
@@ -2970,7 +2979,7 @@
 
 // Same as above but using MediaSource.
 TEST_P(MSEPipelineIntegrationTest, BasicPlayback_Opus441kHz) {
-  MockMediaSource source("sfx-opus-441.webm", kAppendWholeFile);
+  TestMediaSource source("sfx-opus-441.webm", kAppendWholeFile);
   EXPECT_EQ(PIPELINE_OK, StartPipelineWithMediaSource(&source));
   source.EndOfStream();
   Play();
diff --git a/media/test/pipeline_integration_test_base.cc b/media/test/pipeline_integration_test_base.cc
index 146207e..59fa650 100644
--- a/media/test/pipeline_integration_test_base.cc
+++ b/media/test/pipeline_integration_test_base.cc
@@ -12,6 +12,7 @@
 #include "base/memory/ref_counted.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/time/time.h"
 #include "media/base/media_log.h"
 #include "media/base/media_switches.h"
 #include "media/base/media_tracks.h"
@@ -22,7 +23,7 @@
 #include "media/renderers/audio_renderer_impl.h"
 #include "media/renderers/renderer_impl.h"
 #include "media/test/fake_encrypted_media.h"
-#include "media/test/mock_media_source.h"
+#include "media/test/test_media_source.h"
 #include "third_party/libaom/av1_buildflags.h"
 
 #if BUILDFLAG(ENABLE_AV1_DECODER)
@@ -125,6 +126,9 @@
       webaudio_attached_(false),
       mono_output_(false),
       fuzzing_(false),
+#if defined(ADDRESS_SANITIZER)
+      disable_run_timeout_(base::TimeDelta()),
+#endif
       pipeline_(
           new PipelineImpl(scoped_task_environment_.GetMainThreadTaskRunner(),
                            scoped_task_environment_.GetMainThreadTaskRunner(),
@@ -577,18 +581,18 @@
 }
 
 PipelineStatus PipelineIntegrationTestBase::StartPipelineWithMediaSource(
-    MockMediaSource* source) {
+    TestMediaSource* source) {
   return StartPipelineWithMediaSource(source, kNormal, nullptr);
 }
 
 PipelineStatus PipelineIntegrationTestBase::StartPipelineWithEncryptedMedia(
-    MockMediaSource* source,
+    TestMediaSource* source,
     FakeEncryptedMedia* encrypted_media) {
   return StartPipelineWithMediaSource(source, kNormal, encrypted_media);
 }
 
 PipelineStatus PipelineIntegrationTestBase::StartPipelineWithMediaSource(
-    MockMediaSource* source,
+    TestMediaSource* source,
     uint8_t test_type,
     FakeEncryptedMedia* encrypted_media) {
   ParseTestTypeFlags(test_type);
diff --git a/media/test/pipeline_integration_test_base.h b/media/test/pipeline_integration_test_base.h
index af5e34e..e52aac5f 100644
--- a/media/test/pipeline_integration_test_base.h
+++ b/media/test/pipeline_integration_test_base.h
@@ -10,6 +10,7 @@
 
 #include "base/callback_forward.h"
 #include "base/md5.h"
+#include "base/run_loop.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/scoped_task_environment.h"
 #include "media/audio/clockless_audio_sink.h"
@@ -35,7 +36,7 @@
 namespace media {
 
 class FakeEncryptedMedia;
-class MockMediaSource;
+class TestMediaSource;
 
 // Empty MD5 hash string.  Used to verify empty video tracks.
 extern const char kNullVideoHash[];
@@ -158,6 +159,10 @@
   bool webaudio_attached_;
   bool mono_output_;
   bool fuzzing_;
+#if defined(ADDRESS_SANITIZER)
+  // TODO(https://crbug.com/924030): ASAN causes Run() timeouts to be reached.
+  base::RunLoop::ScopedRunTimeoutForTest disable_run_timeout_;
+#endif
   std::unique_ptr<Demuxer> demuxer_;
   std::unique_ptr<DataSource> data_source_;
   std::unique_ptr<PipelineImpl> pipeline_;
@@ -191,12 +196,12 @@
       CreateAudioDecodersCB prepend_audio_decoders_cb =
           CreateAudioDecodersCB());
 
-  PipelineStatus StartPipelineWithMediaSource(MockMediaSource* source);
+  PipelineStatus StartPipelineWithMediaSource(TestMediaSource* source);
   PipelineStatus StartPipelineWithEncryptedMedia(
-      MockMediaSource* source,
+      TestMediaSource* source,
       FakeEncryptedMedia* encrypted_media);
   PipelineStatus StartPipelineWithMediaSource(
-      MockMediaSource* source,
+      TestMediaSource* source,
       uint8_t test_type,
       FakeEncryptedMedia* encrypted_media);
 
diff --git a/media/test/mock_media_source.cc b/media/test/test_media_source.cc
similarity index 81%
rename from media/test/mock_media_source.cc
rename to media/test/test_media_source.cc
index 373ebdfea..4385951 100644
--- a/media/test/mock_media_source.cc
+++ b/media/test/test_media_source.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 "media/test/mock_media_source.h"
+#include "media/test/test_media_source.h"
 
 #include "base/bind.h"
 #include "base/bind_helpers.h"
@@ -44,7 +44,7 @@
 
 constexpr char kSourceId[] = "SourceId";
 
-MockMediaSource::MockMediaSource(const std::string& filename,
+TestMediaSource::TestMediaSource(const std::string& filename,
                                  const std::string& mimetype,
                                  size_t initial_append_size,
                                  bool initial_sequence_mode)
@@ -53,9 +53,9 @@
       initial_sequence_mode_(initial_sequence_mode),
       mimetype_(mimetype),
       chunk_demuxer_(new ChunkDemuxer(
-          base::Bind(&MockMediaSource::DemuxerOpened, base::Unretained(this)),
+          base::Bind(&TestMediaSource::DemuxerOpened, base::Unretained(this)),
           base::DoNothing(),
-          base::BindRepeating(&MockMediaSource::OnEncryptedMediaInitData,
+          base::BindRepeating(&TestMediaSource::OnEncryptedMediaInitData,
                               base::Unretained(this)),
           &media_log_)),
       owned_chunk_demuxer_(chunk_demuxer_) {
@@ -68,15 +68,15 @@
   CHECK_LE(initial_append_size_, file_data_->data_size());
 }
 
-MockMediaSource::MockMediaSource(const std::string& filename,
+TestMediaSource::TestMediaSource(const std::string& filename,
                                  size_t initial_append_size,
                                  bool initial_sequence_mode)
-    : MockMediaSource(filename,
+    : TestMediaSource(filename,
                       GetMimeTypeForFile(filename),
                       initial_append_size,
                       initial_sequence_mode) {}
 
-MockMediaSource::MockMediaSource(scoped_refptr<DecoderBuffer> data,
+TestMediaSource::TestMediaSource(scoped_refptr<DecoderBuffer> data,
                                  const std::string& mimetype,
                                  size_t initial_append_size,
                                  bool initial_sequence_mode)
@@ -86,9 +86,9 @@
       initial_sequence_mode_(initial_sequence_mode),
       mimetype_(mimetype),
       chunk_demuxer_(new ChunkDemuxer(
-          base::Bind(&MockMediaSource::DemuxerOpened, base::Unretained(this)),
+          base::Bind(&TestMediaSource::DemuxerOpened, base::Unretained(this)),
           base::DoNothing(),
-          base::BindRepeating(&MockMediaSource::OnEncryptedMediaInitData,
+          base::BindRepeating(&TestMediaSource::OnEncryptedMediaInitData,
                               base::Unretained(this)),
           &media_log_)),
       owned_chunk_demuxer_(chunk_demuxer_) {
@@ -99,13 +99,13 @@
   CHECK_LE(initial_append_size_, file_data_->data_size());
 }
 
-MockMediaSource::~MockMediaSource() = default;
+TestMediaSource::~TestMediaSource() = default;
 
-std::unique_ptr<Demuxer> MockMediaSource::GetDemuxer() {
+std::unique_ptr<Demuxer> TestMediaSource::GetDemuxer() {
   return std::move(owned_chunk_demuxer_);
 }
 
-void MockMediaSource::SetAppendWindow(base::TimeDelta timestamp_offset,
+void TestMediaSource::SetAppendWindow(base::TimeDelta timestamp_offset,
                                       base::TimeDelta append_window_start,
                                       base::TimeDelta append_window_end) {
   last_timestamp_offset_ = timestamp_offset;
@@ -113,7 +113,7 @@
   append_window_end_ = append_window_end;
 }
 
-void MockMediaSource::Seek(base::TimeDelta seek_time,
+void TestMediaSource::Seek(base::TimeDelta seek_time,
                            size_t new_position,
                            size_t seek_append_size) {
   chunk_demuxer_->StartWaitingForSeek(seek_time);
@@ -127,16 +127,16 @@
   AppendData(seek_append_size);
 }
 
-void MockMediaSource::Seek(base::TimeDelta seek_time) {
+void TestMediaSource::Seek(base::TimeDelta seek_time) {
   chunk_demuxer_->StartWaitingForSeek(seek_time);
 }
 
-void MockMediaSource::SetSequenceMode(bool sequence_mode) {
+void TestMediaSource::SetSequenceMode(bool sequence_mode) {
   CHECK(!chunk_demuxer_->IsParsingMediaSegment(kSourceId));
   chunk_demuxer_->SetSequenceMode(kSourceId, sequence_mode);
 }
 
-void MockMediaSource::AppendData(size_t size) {
+void TestMediaSource::AppendData(size_t size) {
   CHECK(chunk_demuxer_);
   CHECK_LT(current_position_, file_data_->data_size());
   CHECK_LE(current_position_ + size, file_data_->data_size());
@@ -155,7 +155,7 @@
   }
 }
 
-bool MockMediaSource::AppendAtTime(base::TimeDelta timestamp_offset,
+bool TestMediaSource::AppendAtTime(base::TimeDelta timestamp_offset,
                                    const uint8_t* pData,
                                    int size) {
   CHECK(!chunk_demuxer_->IsParsingMediaSegment(kSourceId));
@@ -166,7 +166,7 @@
   return success;
 }
 
-void MockMediaSource::AppendAtTimeWithWindow(
+void TestMediaSource::AppendAtTimeWithWindow(
     base::TimeDelta timestamp_offset,
     base::TimeDelta append_window_start,
     base::TimeDelta append_window_end,
@@ -179,30 +179,30 @@
   last_timestamp_offset_ = timestamp_offset;
 }
 
-void MockMediaSource::SetMemoryLimits(size_t limit_bytes) {
+void TestMediaSource::SetMemoryLimits(size_t limit_bytes) {
   chunk_demuxer_->SetMemoryLimitsForTest(DemuxerStream::AUDIO, limit_bytes);
   chunk_demuxer_->SetMemoryLimitsForTest(DemuxerStream::VIDEO, limit_bytes);
 }
 
-bool MockMediaSource::EvictCodedFrames(base::TimeDelta currentMediaTime,
+bool TestMediaSource::EvictCodedFrames(base::TimeDelta currentMediaTime,
                                        size_t newDataSize) {
   return chunk_demuxer_->EvictCodedFrames(kSourceId, currentMediaTime,
                                           newDataSize);
 }
 
-void MockMediaSource::RemoveRange(base::TimeDelta start, base::TimeDelta end) {
+void TestMediaSource::RemoveRange(base::TimeDelta start, base::TimeDelta end) {
   chunk_demuxer_->Remove(kSourceId, start, end);
 }
 
-void MockMediaSource::EndOfStream() {
+void TestMediaSource::EndOfStream() {
   chunk_demuxer_->MarkEndOfStream(PIPELINE_OK);
 }
 
-void MockMediaSource::UnmarkEndOfStream() {
+void TestMediaSource::UnmarkEndOfStream() {
   chunk_demuxer_->UnmarkEndOfStream();
 }
 
-void MockMediaSource::Shutdown() {
+void TestMediaSource::Shutdown() {
   if (!chunk_demuxer_)
     return;
   chunk_demuxer_->ResetParserState(kSourceId, base::TimeDelta(),
@@ -211,13 +211,13 @@
   chunk_demuxer_ = NULL;
 }
 
-void MockMediaSource::DemuxerOpened() {
+void TestMediaSource::DemuxerOpened() {
   base::ThreadTaskRunnerHandle::Get()->PostTask(
       FROM_HERE,
-      base::Bind(&MockMediaSource::DemuxerOpenedTask, base::Unretained(this)));
+      base::Bind(&TestMediaSource::DemuxerOpenedTask, base::Unretained(this)));
 }
 
-void MockMediaSource::DemuxerOpenedTask() {
+void TestMediaSource::DemuxerOpenedTask() {
   ChunkDemuxer::Status status = AddId();
   if (status != ChunkDemuxer::kOk) {
     CHECK(demuxer_failure_cb_);
@@ -225,25 +225,25 @@
     return;
   }
   chunk_demuxer_->SetTracksWatcher(
-      kSourceId, base::Bind(&MockMediaSource::InitSegmentReceived,
+      kSourceId, base::Bind(&TestMediaSource::InitSegmentReceived,
                             base::Unretained(this)));
 
   chunk_demuxer_->SetParseWarningCallback(
       kSourceId,
-      base::Bind(&MockMediaSource::OnParseWarningMock, base::Unretained(this)));
+      base::Bind(&TestMediaSource::OnParseWarningMock, base::Unretained(this)));
 
   SetSequenceMode(initial_sequence_mode_);
   AppendData(initial_append_size_);
 }
 
-ChunkDemuxer::Status MockMediaSource::AddId() {
+ChunkDemuxer::Status TestMediaSource::AddId() {
   std::string type;
   std::string codecs;
   SplitMime(mimetype_, &type, &codecs);
   return chunk_demuxer_->AddId(kSourceId, type, codecs);
 }
 
-void MockMediaSource::ChangeType(const std::string& mimetype) {
+void TestMediaSource::ChangeType(const std::string& mimetype) {
   chunk_demuxer_->ResetParserState(kSourceId, base::TimeDelta(),
                                    kInfiniteDuration, &last_timestamp_offset_);
   std::string type;
@@ -253,7 +253,7 @@
   chunk_demuxer_->ChangeType(kSourceId, type, codecs);
 }
 
-void MockMediaSource::OnEncryptedMediaInitData(
+void TestMediaSource::OnEncryptedMediaInitData(
     EmeInitDataType init_data_type,
     const std::vector<uint8_t>& init_data) {
   CHECK(!init_data.empty());
@@ -261,7 +261,7 @@
   encrypted_media_init_data_cb_.Run(init_data_type, init_data);
 }
 
-void MockMediaSource::InitSegmentReceived(std::unique_ptr<MediaTracks> tracks) {
+void TestMediaSource::InitSegmentReceived(std::unique_ptr<MediaTracks> tracks) {
   CHECK(tracks.get());
   EXPECT_GT(tracks->tracks().size(), 0u);
   CHECK(chunk_demuxer_);
@@ -274,7 +274,7 @@
   InitSegmentReceivedMock(tracks);
 }
 
-void MockMediaSource::VerifyExpectedAppendResult(bool append_result) {
+void TestMediaSource::VerifyExpectedAppendResult(bool append_result) {
   if (expected_append_result_ == ExpectedAppendResult::kSuccessOrFailure)
     return;  // |append_result| is ignored in this case.
 
diff --git a/media/test/mock_media_source.h b/media/test/test_media_source.h
similarity index 92%
rename from media/test/mock_media_source.h
rename to media/test/test_media_source.h
index 7b1fad8..3d8e154 100644
--- a/media/test/mock_media_source.h
+++ b/media/test/test_media_source.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 MEDIA_TEST_MOCK_MEDIA_SOURCE_H_
-#define MEDIA_TEST_MOCK_MEDIA_SOURCE_H_
+#ifndef MEDIA_TEST_TEST_MEDIA_SOURCE_H_
+#define MEDIA_TEST_TEST_MEDIA_SOURCE_H_
 
 #include <limits>
 
@@ -21,7 +21,7 @@
 
 // Helper class that emulates calls made on the ChunkDemuxer by the
 // Media Source API.
-class MockMediaSource {
+class TestMediaSource {
  public:
   enum class ExpectedAppendResult {
     kSuccess,
@@ -29,20 +29,20 @@
     kSuccessOrFailure,  // e.g., for fuzzing when parse may pass or fail
   };
 
-  MockMediaSource(const std::string& filename,
+  TestMediaSource(const std::string& filename,
                   const std::string& mimetype,
                   size_t initial_append_size,
                   bool initial_sequence_mode = false);
   // Same as the constructor above, but use GetMimeTypeForFile() to get the mime
   // type.
-  MockMediaSource(const std::string& filename,
+  TestMediaSource(const std::string& filename,
                   size_t initial_append_size,
                   bool initial_sequence_mode = false);
-  MockMediaSource(scoped_refptr<DecoderBuffer> data,
+  TestMediaSource(scoped_refptr<DecoderBuffer> data,
                   const std::string& mimetype,
                   size_t initial_append_size,
                   bool initial_sequence_mode = false);
-  ~MockMediaSource();
+  ~TestMediaSource();
 
   std::unique_ptr<Demuxer> GetDemuxer();
 
@@ -122,9 +122,9 @@
   bool do_eos_after_next_append_ = false;
   ExpectedAppendResult expected_append_result_ = ExpectedAppendResult::kSuccess;
 
-  DISALLOW_COPY_AND_ASSIGN(MockMediaSource);
+  DISALLOW_COPY_AND_ASSIGN(TestMediaSource);
 };
 
 }  // namespace media
 
-#endif  // MEDIA_TEST_MOCK_MEDIA_SOURCE_H_
+#endif  // MEDIA_TEST_TEST_MEDIA_SOURCE_H_
diff --git a/mojo/public/cpp/bindings/tests/associated_interface_unittest.cc b/mojo/public/cpp/bindings/tests/associated_interface_unittest.cc
index 544f032b..221f2c4 100644
--- a/mojo/public/cpp/bindings/tests/associated_interface_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/associated_interface_unittest.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/callback_helpers.h"
 #include "base/memory/ptr_util.h"
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 35012c3..5152acf 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -1043,8 +1043,6 @@
       "socket/socks5_client_socket.h",
       "socket/socks_client_socket.cc",
       "socket/socks_client_socket.h",
-      "socket/socks_client_socket_pool.cc",
-      "socket/socks_client_socket_pool.h",
       "socket/socks_connect_job.cc",
       "socket/socks_connect_job.h",
       "socket/ssl_client_socket_pool.cc",
@@ -5029,7 +5027,6 @@
     "socket/socket_bio_adapter_unittest.cc",
     "socket/socket_tag_unittest.cc",
     "socket/socks5_client_socket_unittest.cc",
-    "socket/socks_client_socket_pool_unittest.cc",
     "socket/socks_client_socket_unittest.cc",
     "socket/socks_connect_job_unittest.cc",
     "socket/ssl_client_socket_pool_unittest.cc",
diff --git a/net/android/network_change_notifier_android.cc b/net/android/network_change_notifier_android.cc
index 6ecf62d..bfcb292 100644
--- a/net/android/network_change_notifier_android.cc
+++ b/net/android/network_change_notifier_android.cc
@@ -63,6 +63,7 @@
 
 #include "base/android/build_info.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
diff --git a/net/base/network_change_notifier_linux.cc b/net/base/network_change_notifier_linux.cc
index 9917306..9621a74 100644
--- a/net/base/network_change_notifier_linux.cc
+++ b/net/base/network_change_notifier_linux.cc
@@ -5,6 +5,7 @@
 #include "net/base/network_change_notifier_linux.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/compiler_specific.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
diff --git a/net/http/bidirectional_stream_unittest.cc b/net/http/bidirectional_stream_unittest.cc
index 1c023ec..7f6387d7 100644
--- a/net/http/bidirectional_stream_unittest.cc
+++ b/net/http/bidirectional_stream_unittest.cc
@@ -17,6 +17,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/time/time.h"
 #include "base/timer/mock_timer.h"
+#include "base/timer/timer.h"
 #include "build/build_config.h"
 #include "net/base/completion_once_callback.h"
 #include "net/base/load_timing_info.h"
diff --git a/net/http/http_cache_writers.cc b/net/http/http_cache_writers.cc
index fccbcb89..e0183bd 100644
--- a/net/http/http_cache_writers.cc
+++ b/net/http/http_cache_writers.cc
@@ -9,6 +9,7 @@
 
 #include "base/auto_reset.h"
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/logging.h"
 
 #include "net/base/net_errors.h"
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index b71a6eb..afa541e9 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -314,7 +314,7 @@
   return GetSocketPoolManager(pool_type)->GetSSLSocketPool();
 }
 
-SOCKSClientSocketPool* HttpNetworkSession::GetSocketPoolForSOCKSProxy(
+TransportClientSocketPool* HttpNetworkSession::GetSocketPoolForSOCKSProxy(
     SocketPoolType pool_type,
     const ProxyServer& socks_proxy) {
   return GetSocketPoolManager(pool_type)->GetSocketPoolForSOCKSProxy(
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index 0c42c754..4310ef4 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -75,7 +75,6 @@
 class ReportingService;
 #endif
 class SocketPerformanceWatcherFactory;
-class SOCKSClientSocketPool;
 class SSLClientSocketPool;
 class SSLConfigService;
 class TransportClientSocketPool;
@@ -294,7 +293,8 @@
 
   TransportClientSocketPool* GetTransportSocketPool(SocketPoolType pool_type);
   SSLClientSocketPool* GetSSLSocketPool(SocketPoolType pool_type);
-  SOCKSClientSocketPool* GetSocketPoolForSOCKSProxy(
+  // Currently only works for SOCKS proxies.
+  TransportClientSocketPool* GetSocketPoolForSOCKSProxy(
       SocketPoolType pool_type,
       const ProxyServer& socks_proxy);
   HttpProxyClientSocketPool* GetSocketPoolForHTTPLikeProxy(
diff --git a/net/http/http_network_session_peer.cc b/net/http/http_network_session_peer.cc
index bfcc592..4841c5e2 100644
--- a/net/http/http_network_session_peer.cc
+++ b/net/http/http_network_session_peer.cc
@@ -7,7 +7,6 @@
 #include "net/http/http_proxy_client_socket_pool.h"
 #include "net/proxy_resolution/proxy_resolution_service.h"
 #include "net/socket/client_socket_pool_manager.h"
-#include "net/socket/socks_client_socket_pool.h"
 #include "net/socket/ssl_client_socket_pool.h"
 #include "net/socket/transport_client_socket_pool.h"
 
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 19631949..2f4759c 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -58,7 +58,6 @@
 #include "net/log/net_log_event_type.h"
 #include "net/socket/client_socket_factory.h"
 #include "net/socket/next_proto.h"
-#include "net/socket/socks_client_socket_pool.h"
 #include "net/socket/transport_client_socket_pool.h"
 #include "net/spdy/spdy_http_stream.h"
 #include "net/spdy/spdy_session.h"
diff --git a/net/http/http_network_transaction_unittest.cc b/net/http/http_network_transaction_unittest.cc
index e8e24f9..fecabc1 100644
--- a/net/http/http_network_transaction_unittest.cc
+++ b/net/http/http_network_transaction_unittest.cc
@@ -84,6 +84,7 @@
 #include "net/socket/next_proto.h"
 #include "net/socket/socket_tag.h"
 #include "net/socket/socket_test_util.h"
+#include "net/socket/socks_connect_job.h"
 #include "net/socket/ssl_client_socket.h"
 #include "net/spdy/spdy_session.h"
 #include "net/spdy/spdy_session_pool.h"
@@ -684,8 +685,6 @@
 CaptureGroupNameTransportSocketPool;
 typedef CaptureGroupNameSocketPool<HttpProxyClientSocketPool>
 CaptureGroupNameHttpProxySocketPool;
-typedef CaptureGroupNameSocketPool<SOCKSClientSocketPool>
-CaptureGroupNameSOCKSSocketPool;
 typedef CaptureGroupNameSocketPool<SSLClientSocketPool>
 CaptureGroupNameSSLSocketPool;
 
@@ -11198,13 +11197,13 @@
     ProxyServer proxy_server(
         ProxyServer::FromURI(tests[i].proxy_server, ProxyServer::SCHEME_HTTP));
     ASSERT_TRUE(proxy_server.is_valid());
-    CaptureGroupNameSOCKSSocketPool* socks_conn_pool =
-        new CaptureGroupNameSOCKSSocketPool(NULL, NULL);
+    CaptureGroupNameTransportSocketPool* socks_conn_pool =
+        new CaptureGroupNameTransportSocketPool(NULL, NULL);
     CaptureGroupNameSSLSocketPool* ssl_conn_pool =
         new CaptureGroupNameSSLSocketPool(NULL, NULL);
     auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
-    mock_pool_manager->SetSocketPoolForSOCKSProxy(
-        proxy_server, base::WrapUnique(socks_conn_pool));
+    mock_pool_manager->SetSocketPoolForProxy(proxy_server,
+                                             base::WrapUnique(socks_conn_pool));
     mock_pool_manager->SetSocketPoolForSSLWithProxy(
         proxy_server, base::WrapUnique(ssl_conn_pool));
     peer.SetClientSocketPoolManager(std::move(mock_pool_manager));
diff --git a/net/http/http_proxy_client_socket_pool_unittest.cc b/net/http/http_proxy_client_socket_pool_unittest.cc
index 4397ae6..8a4bbd7 100644
--- a/net/http/http_proxy_client_socket_pool_unittest.cc
+++ b/net/http/http_proxy_client_socket_pool_unittest.cc
@@ -31,6 +31,7 @@
 #include "net/socket/next_proto.h"
 #include "net/socket/socket_tag.h"
 #include "net/socket/socket_test_util.h"
+#include "net/socket/socks_connect_job.h"
 #include "net/socket/transport_connect_job.h"
 #include "net/spdy/spdy_test_util_common.h"
 #include "net/test/gtest_util.h"
diff --git a/net/http/http_proxy_client_socket_wrapper_unittest.cc b/net/http/http_proxy_client_socket_wrapper_unittest.cc
index d5d3d563..3e3d842 100644
--- a/net/http/http_proxy_client_socket_wrapper_unittest.cc
+++ b/net/http/http_proxy_client_socket_wrapper_unittest.cc
@@ -22,6 +22,7 @@
 #include "net/quic/quic_test_packet_maker.h"
 #include "net/socket/socket_tag.h"
 #include "net/socket/socket_test_util.h"
+#include "net/socket/socks_connect_job.h"
 #include "net/socket/transport_connect_job.h"
 #include "net/ssl/channel_id_service.h"
 #include "net/ssl/default_channel_id_store.h"
diff --git a/net/http/http_stream_factory_job.cc b/net/http/http_stream_factory_job.cc
index 5579cae9..6dbe6287 100644
--- a/net/http/http_stream_factory_job.cc
+++ b/net/http/http_stream_factory_job.cc
@@ -45,7 +45,6 @@
 #include "net/socket/client_socket_handle.h"
 #include "net/socket/client_socket_pool.h"
 #include "net/socket/client_socket_pool_manager.h"
-#include "net/socket/socks_client_socket_pool.h"
 #include "net/socket/ssl_client_socket.h"
 #include "net/socket/ssl_client_socket_pool.h"
 #include "net/socket/stream_socket.h"
diff --git a/net/http/http_stream_factory_unittest.cc b/net/http/http_stream_factory_unittest.cc
index 11667098..5b38579 100644
--- a/net/http/http_stream_factory_unittest.cc
+++ b/net/http/http_stream_factory_unittest.cc
@@ -51,6 +51,7 @@
 #include "net/socket/next_proto.h"
 #include "net/socket/socket_tag.h"
 #include "net/socket/socket_test_util.h"
+#include "net/socket/socks_connect_job.h"
 #include "net/socket/transport_connect_job.h"
 #include "net/spdy/spdy_session.h"
 #include "net/spdy/spdy_session_pool.h"
@@ -447,8 +448,6 @@
     CapturePreconnectsTransportSocketPool;
 typedef CapturePreconnectsSocketPool<HttpProxyClientSocketPool>
     CapturePreconnectsHttpProxySocketPool;
-typedef CapturePreconnectsSocketPool<SOCKSClientSocketPool>
-    CapturePreconnectsSOCKSSocketPool;
 typedef CapturePreconnectsSocketPool<SSLClientSocketPool>
     CapturePreconnectsSSLSocketPool;
 
@@ -579,8 +578,8 @@
     HttpNetworkSessionPeer peer(session.get());
     ProxyServer proxy_server(ProxyServer::SCHEME_SOCKS4,
                              HostPortPair("socks_proxy", 1080));
-    CapturePreconnectsSOCKSSocketPool* socks_proxy_pool =
-        new CapturePreconnectsSOCKSSocketPool(
+    CapturePreconnectsTransportSocketPool* socks_proxy_pool =
+        new CapturePreconnectsTransportSocketPool(
             session_deps.host_resolver.get(), session_deps.cert_verifier.get(),
             session_deps.transport_security_state.get(),
             session_deps.cert_transparency_verifier.get(),
@@ -592,7 +591,7 @@
             session_deps.cert_transparency_verifier.get(),
             session_deps.ct_policy_enforcer.get());
     auto mock_pool_manager = std::make_unique<MockClientSocketPoolManager>();
-    mock_pool_manager->SetSocketPoolForSOCKSProxy(
+    mock_pool_manager->SetSocketPoolForProxy(
         proxy_server, base::WrapUnique(socks_proxy_pool));
     mock_pool_manager->SetSocketPoolForSSLWithProxy(
         proxy_server, base::WrapUnique(ssl_conn_pool));
diff --git a/net/nqe/network_quality_estimator.cc b/net/nqe/network_quality_estimator.cc
index 98c77b3..a46ce25 100644
--- a/net/nqe/network_quality_estimator.cc
+++ b/net/nqe/network_quality_estimator.cc
@@ -727,6 +727,27 @@
 
   network_quality_ = nqe::internal::NetworkQuality(http_rtt, transport_rtt,
                                                    downstream_throughput_kbps);
+  net::EffectiveConnectionType signal_strength_capped_ect =
+      GetCappedECTBasedOnSignalStrength();
+
+  if (signal_strength_capped_ect != effective_connection_type_) {
+    DCHECK_LE(signal_strength_capped_ect, effective_connection_type_);
+    UMA_HISTOGRAM_EXACT_LINEAR(
+        "NQE.CellularSignalStrength.ECTReduction",
+        effective_connection_type_ - signal_strength_capped_ect,
+        static_cast<int>(EFFECTIVE_CONNECTION_TYPE_LAST));
+
+    effective_connection_type_ = signal_strength_capped_ect;
+
+    // Reset |network_quality_| based on the updated effective connection type.
+    network_quality_ = nqe::internal::NetworkQuality(
+        params_->TypicalNetworkQuality(effective_connection_type_).http_rtt(),
+        params_->TypicalNetworkQuality(effective_connection_type_)
+            .transport_rtt(),
+        params_->TypicalNetworkQuality(effective_connection_type_)
+            .downstream_throughput_kbps());
+  }
+
   UMA_HISTOGRAM_ENUMERATION("NQE.EffectiveConnectionType.OnECTComputation",
                             effective_connection_type_,
                             EFFECTIVE_CONNECTION_TYPE_LAST);
@@ -771,6 +792,86 @@
   new_throughput_observations_since_last_ect_computation_ = 0;
 }
 
+EffectiveConnectionType
+NetworkQualityEstimator::GetCappedECTBasedOnSignalStrength() const {
+  if (!params_->cap_ect_based_on_signal_strength())
+    return effective_connection_type_;
+
+  // Check if signal strength is available.
+  if (current_network_id_.signal_strength == INT32_MIN)
+    return effective_connection_type_;
+
+  if (effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_UNKNOWN ||
+      effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_OFFLINE) {
+    return effective_connection_type_;
+  }
+
+  // The maximum signal strength level is 4.
+  UMA_HISTOGRAM_EXACT_LINEAR("NQE.CellularSignalStrength.AtECTComputation",
+                             current_network_id_.signal_strength, 4);
+
+  // Do not cap ECT if the signal strength is high.
+  if (current_network_id_.signal_strength > 2)
+    return effective_connection_type_;
+
+  DCHECK_LE(0, current_network_id_.signal_strength);
+
+  DCHECK_LE(NetworkChangeNotifier::CONNECTION_2G, current_network_id_.type);
+  DCHECK_GE(NetworkChangeNotifier::CONNECTION_4G, current_network_id_.type);
+
+  // When signal strength is 0, the device is almost offline.
+  if (current_network_id_.signal_strength == 0) {
+    switch (current_network_id_.type) {
+      case NetworkChangeNotifier::CONNECTION_2G:
+      case NetworkChangeNotifier::CONNECTION_3G:
+        return std::min(effective_connection_type_,
+                        EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
+      case NetworkChangeNotifier::CONNECTION_4G:
+        return std::min(effective_connection_type_,
+                        EFFECTIVE_CONNECTION_TYPE_2G);
+      default:
+        NOTREACHED();
+        return effective_connection_type_;
+    }
+  }
+
+  if (current_network_id_.signal_strength == 1) {
+    switch (current_network_id_.type) {
+      case NetworkChangeNotifier::CONNECTION_2G:
+        return std::min(effective_connection_type_,
+                        EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
+      case NetworkChangeNotifier::CONNECTION_3G:
+        return std::min(effective_connection_type_,
+                        EFFECTIVE_CONNECTION_TYPE_2G);
+      case NetworkChangeNotifier::CONNECTION_4G:
+        return std::min(effective_connection_type_,
+                        EFFECTIVE_CONNECTION_TYPE_3G);
+      default:
+        NOTREACHED();
+        return effective_connection_type_;
+    }
+  }
+
+  if (current_network_id_.signal_strength == 2) {
+    switch (current_network_id_.type) {
+      case NetworkChangeNotifier::CONNECTION_2G:
+        return std::min(effective_connection_type_,
+                        EFFECTIVE_CONNECTION_TYPE_2G);
+      case NetworkChangeNotifier::CONNECTION_3G:
+        return std::min(effective_connection_type_,
+                        EFFECTIVE_CONNECTION_TYPE_3G);
+      case NetworkChangeNotifier::CONNECTION_4G:
+        return std::min(effective_connection_type_,
+                        EFFECTIVE_CONNECTION_TYPE_4G);
+      default:
+        NOTREACHED();
+        return effective_connection_type_;
+    }
+  }
+  NOTREACHED();
+  return effective_connection_type_;
+}
+
 EffectiveConnectionType NetworkQualityEstimator::GetEffectiveConnectionType()
     const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/net/nqe/network_quality_estimator.h b/net/nqe/network_quality_estimator.h
index bf40a20..02da751 100644
--- a/net/nqe/network_quality_estimator.h
+++ b/net/nqe/network_quality_estimator.h
@@ -516,6 +516,11 @@
   // observations.
   bool ShouldSocketWatcherNotifyRTT(base::TimeTicks now);
 
+  // Caps and returns the current value of effective connection type based on
+  // the current signal strength. If the signal strength is reported as low, a
+  // value lower than |effective_connection_type_| may be returned.
+  EffectiveConnectionType GetCappedECTBasedOnSignalStrength() const;
+
   // Determines if the requests to local host can be used in estimating the
   // network quality. Set to true only for tests.
   bool use_localhost_requests_;
diff --git a/net/nqe/network_quality_estimator_params.cc b/net/nqe/network_quality_estimator_params.cc
index 44999ee..e4c5d1a 100644
--- a/net/nqe/network_quality_estimator_params.cc
+++ b/net/nqe/network_quality_estimator_params.cc
@@ -500,6 +500,11 @@
               "socket_watchers_min_notification_interval_msec",
               200))),
       use_end_to_end_rtt_(true),
+      cap_ect_based_on_signal_strength_(
+          GetStringValueForVariationParamWithDefaultValue(
+              params_,
+              "cap_ect_based_on_signal_strength",
+              "false") == "true"),
       use_small_responses_(false) {
   DCHECK(hanging_request_http_rtt_upper_bound_transport_rtt_multiplier_ == -1 ||
          hanging_request_http_rtt_upper_bound_transport_rtt_multiplier_ > 0);
diff --git a/net/nqe/network_quality_estimator_params.h b/net/nqe/network_quality_estimator_params.h
index ff99cd8..f5f53ff 100644
--- a/net/nqe/network_quality_estimator_params.h
+++ b/net/nqe/network_quality_estimator_params.h
@@ -240,6 +240,12 @@
   // quality estimate.
   bool use_end_to_end_rtt() const { return use_end_to_end_rtt_; }
 
+  // Return true if ECT value should be capped based on the current signal
+  // strength.
+  bool cap_ect_based_on_signal_strength() const {
+    return cap_ect_based_on_signal_strength_;
+  }
+
   // Sets the forced effective connection type as |type|.
   void SetForcedEffectiveConnectionTypeForTesting(EffectiveConnectionType type);
 
@@ -271,6 +277,7 @@
   const bool add_default_platform_observations_;
   const base::TimeDelta socket_watchers_min_notification_interval_;
   const bool use_end_to_end_rtt_;
+  const bool cap_ect_based_on_signal_strength_;
 
   bool use_small_responses_;
 
diff --git a/net/nqe/network_quality_estimator_test_util.cc b/net/nqe/network_quality_estimator_test_util.cc
index 2ceaab0..4ee7b4fb 100644
--- a/net/nqe/network_quality_estimator_test_util.cc
+++ b/net/nqe/network_quality_estimator_test_util.cc
@@ -335,7 +335,12 @@
 }
 
 int32_t TestNetworkQualityEstimator::GetCurrentSignalStrength() const {
-  return INT32_MIN;
+  return current_cellular_signal_strength_;
+}
+
+void TestNetworkQualityEstimator::SetCurrentSignalStrength(
+    int32_t signal_strength) {
+  current_cellular_signal_strength_ = signal_strength;
 }
 
 TestNetworkQualityEstimator::LocalHttpTestServer::LocalHttpTestServer(
diff --git a/net/nqe/network_quality_estimator_test_util.h b/net/nqe/network_quality_estimator_test_util.h
index bf614c3..5786f91 100644
--- a/net/nqe/network_quality_estimator_test_util.h
+++ b/net/nqe/network_quality_estimator_test_util.h
@@ -213,6 +213,8 @@
     transport_rtt_observation_count_last_ect_computation_ = count;
   }
 
+  void SetCurrentSignalStrength(int32_t signal_strength);
+
   // Returns count of ping RTTs received from H2/spdy connections.
   size_t ping_rtt_received_count() const { return ping_rtt_received_count_; }
 
@@ -279,6 +281,8 @@
   // If set, GetRTTEstimateInternal() would return the set value.
   base::Optional<base::TimeDelta> start_time_null_end_to_end_rtt_;
 
+  int32_t current_cellular_signal_strength_ = INT32_MIN;
+
   LocalHttpTestServer embedded_test_server_;
 
   // If true, notifications are not sent to any of the observers.
diff --git a/net/nqe/network_quality_estimator_unittest.cc b/net/nqe/network_quality_estimator_unittest.cc
index 9263799..b92ee2b5 100644
--- a/net/nqe/network_quality_estimator_unittest.cc
+++ b/net/nqe/network_quality_estimator_unittest.cc
@@ -942,7 +942,7 @@
 
   const struct {
     int32_t rtt_msec;
-    EffectiveConnectionType expected_conn_type;
+    EffectiveConnectionType expected_ect;
   } tests[] = {
       {5000, EFFECTIVE_CONNECTION_TYPE_OFFLINE},
       {4000, EFFECTIVE_CONNECTION_TYPE_OFFLINE},
@@ -966,7 +966,7 @@
     estimator.set_recent_downlink_throughput_kbps(INT32_MAX);
     estimator.SetStartTimeNullHttpRtt(
         base::TimeDelta::FromMilliseconds(test.rtt_msec));
-    EXPECT_EQ(test.expected_conn_type, estimator.GetEffectiveConnectionType());
+    EXPECT_EQ(test.expected_ect, estimator.GetEffectiveConnectionType());
   }
 }
 
@@ -976,7 +976,7 @@
   const struct {
     bool override_defaults_using_variation_params;
     int32_t http_rtt_msec;
-    EffectiveConnectionType expected_conn_type;
+    EffectiveConnectionType expected_ect;
   } tests[] = {
       // When the variation params do not override connection thresholds,
       // default values should be used.
@@ -1019,7 +1019,74 @@
         base::TimeDelta::FromMilliseconds(test.http_rtt_msec));
     estimator.set_start_time_null_downlink_throughput_kbps(INT32_MAX);
     estimator.set_recent_downlink_throughput_kbps(INT32_MAX);
-    EXPECT_EQ(test.expected_conn_type, estimator.GetEffectiveConnectionType());
+    EXPECT_EQ(test.expected_ect, estimator.GetEffectiveConnectionType());
+  }
+}
+
+// Tests that the ECT and other network quality metrics are capped based on
+// signal strength.
+TEST_F(NetworkQualityEstimatorTest, SignalStrengthBasedCapping) {
+  const struct {
+    bool enable_signal_strength_capping_experiment;
+    int32_t signal_strength_level;
+    int32_t http_rtt_msec;
+    EffectiveConnectionType expected_ect;
+    bool expected_http_rtt_overridden;
+  } tests[] = {
+      // Signal strength is unavailable.
+      {true, INT32_MIN, 20, EFFECTIVE_CONNECTION_TYPE_4G, false},
+
+      // Signal strength is too low. Even though RTT is reported as low,
+      // ECT is expected to be capped to 2G.
+      {true, 0, 20, EFFECTIVE_CONNECTION_TYPE_2G, true},
+
+      // When the signal strength based capping experiment is not enabled,
+      // ECT should be computed only on the based of |http_rtt_msec|.
+      {false, INT32_MIN, 20, EFFECTIVE_CONNECTION_TYPE_4G, false},
+      {false, 0, 20, EFFECTIVE_CONNECTION_TYPE_4G, false},
+  };
+
+  for (const auto& test : tests) {
+    base::HistogramTester histogram_tester;
+    std::map<std::string, std::string> variation_params;
+    variation_params["cap_ect_based_on_signal_strength"] =
+        test.enable_signal_strength_capping_experiment ? "true" : "false";
+
+    TestNetworkQualityEstimator estimator(variation_params);
+
+    // Simulate the connection type so that GetEffectiveConnectionType
+    // does not return Offline if the device is offline.
+    estimator.SetCurrentSignalStrength(test.signal_strength_level);
+
+    estimator.SimulateNetworkChange(NetworkChangeNotifier::CONNECTION_4G,
+                                    "test");
+
+    estimator.SetStartTimeNullHttpRtt(
+        base::TimeDelta::FromMilliseconds(test.http_rtt_msec));
+    estimator.set_recent_http_rtt(
+        base::TimeDelta::FromMilliseconds(test.http_rtt_msec));
+    estimator.set_start_time_null_downlink_throughput_kbps(INT32_MAX);
+    estimator.set_recent_downlink_throughput_kbps(INT32_MAX);
+    estimator.RunOneRequest();
+    EXPECT_EQ(test.expected_ect, estimator.GetEffectiveConnectionType());
+
+    if (!test.expected_http_rtt_overridden) {
+      EXPECT_EQ(base::TimeDelta::FromMilliseconds(test.http_rtt_msec),
+                estimator.GetHttpRTT());
+    } else {
+      EXPECT_EQ(estimator.params()
+                    ->TypicalNetworkQuality(EFFECTIVE_CONNECTION_TYPE_2G)
+                    .http_rtt(),
+                estimator.GetHttpRTT());
+    }
+
+    if (!test.expected_http_rtt_overridden) {
+      histogram_tester.ExpectTotalCount(
+          "NQE.CellularSignalStrength.ECTReduction", 0);
+    } else {
+      ExpectBucketCountAtLeast(&histogram_tester,
+                               "NQE.CellularSignalStrength.ECTReduction", 2, 1);
+    }
   }
 }
 
@@ -1049,7 +1116,7 @@
   const struct {
     int32_t rtt_msec;
     int32_t downlink_throughput_kbps;
-    EffectiveConnectionType expected_conn_type;
+    EffectiveConnectionType expected_ect;
   } tests[] = {
       // Set RTT to a very low value to observe the effect of throughput.
       // Throughput is the bottleneck.
@@ -1082,7 +1149,7 @@
     // Run one main frame request to force recomputation of effective connection
     // type.
     estimator.RunOneRequest();
-    EXPECT_EQ(test.expected_conn_type, estimator.GetEffectiveConnectionType());
+    EXPECT_EQ(test.expected_ect, estimator.GetEffectiveConnectionType());
   }
 }
 
diff --git a/net/proxy_resolution/dhcp_pac_file_fetcher_win_unittest.cc b/net/proxy_resolution/dhcp_pac_file_fetcher_win_unittest.cc
index f8e3278..7ea2182 100644
--- a/net/proxy_resolution/dhcp_pac_file_fetcher_win_unittest.cc
+++ b/net/proxy_resolution/dhcp_pac_file_fetcher_win_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/test/test_timeouts.h"
 #include "base/threading/platform_thread.h"
 #include "base/timer/elapsed_timer.h"
+#include "base/timer/timer.h"
 #include "net/proxy_resolution/dhcp_pac_file_adapter_fetcher_win.h"
 #include "net/test/gtest_util.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
diff --git a/net/proxy_resolution/proxy_config_service_android_unittest.cc b/net/proxy_resolution/proxy_config_service_android_unittest.cc
index 33c45cb..d222bbe 100644
--- a/net/proxy_resolution/proxy_config_service_android_unittest.cc
+++ b/net/proxy_resolution/proxy_config_service_android_unittest.cc
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/compiler_specific.h"
 #include "base/run_loop.h"
 #include "base/threading/thread_task_runner_handle.h"
diff --git a/net/quic/bidirectional_stream_quic_impl_unittest.cc b/net/quic/bidirectional_stream_quic_impl_unittest.cc
index 90079c9b..42b2940a 100644
--- a/net/quic/bidirectional_stream_quic_impl_unittest.cc
+++ b/net/quic/bidirectional_stream_quic_impl_unittest.cc
@@ -12,6 +12,7 @@
 #include "base/strings/string_number_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "net/base/completion_once_callback.h"
 #include "net/base/ip_address.h"
 #include "net/base/load_timing_info.h"
diff --git a/net/quic/quic_chromium_client_session.h b/net/quic/quic_chromium_client_session.h
index 7ddacd8..65020a6 100644
--- a/net/quic/quic_chromium_client_session.h
+++ b/net/quic/quic_chromium_client_session.h
@@ -21,6 +21,7 @@
 #include "base/containers/mru_cache.h"
 #include "base/macros.h"
 #include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "net/base/completion_once_callback.h"
 #include "net/base/load_timing_info.h"
 #include "net/base/net_error_details.h"
diff --git a/net/quic/quic_connectivity_probing_manager.h b/net/quic/quic_connectivity_probing_manager.h
index 9931a37..8a4795e0 100644
--- a/net/quic/quic_connectivity_probing_manager.h
+++ b/net/quic/quic_connectivity_probing_manager.h
@@ -6,6 +6,7 @@
 #define NET_QUIC_QUIC_CONNECTIVITY_PROBING_MANAGER_H_
 
 #include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "net/base/net_export.h"
 #include "net/log/net_log_with_source.h"
 #include "net/quic/quic_chromium_packet_reader.h"
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index 04f2559..3f06cab 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -1070,8 +1070,6 @@
       ssl_config_service_(ssl_config_service),
       enable_socket_recv_optimization_(enable_socket_recv_optimization),
       weak_factory_(this) {
-  if (ssl_config_service_)
-    ssl_config_service_->AddObserver(this);
   DCHECK(transport_security_state_);
   DCHECK(http_server_properties_);
   crypto_config_.set_user_agent_id(user_agent_id);
@@ -1114,8 +1112,6 @@
   active_jobs_.clear();
   while (!active_cert_verifier_jobs_.empty())
     active_cert_verifier_jobs_.erase(active_cert_verifier_jobs_.begin());
-  if (ssl_config_service_)
-    ssl_config_service_->RemoveObserver(this);
   if (close_sessions_on_ip_change_ || goaway_sessions_on_ip_change_) {
     NetworkChangeNotifier::RemoveIPAddressObserver(this);
   }
@@ -1612,10 +1608,6 @@
   return socket;
 }
 
-void QuicStreamFactory::OnSSLConfigChanged() {
-  CloseAllSessions(ERR_CERT_DATABASE_CHANGED, quic::QUIC_CONNECTION_CANCELLED);
-}
-
 void QuicStreamFactory::OnCertDBChanged() {
   // We should flush the sessions if we removed trust from a
   // cert, because a previously trusted server may have become
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h
index 6dcb932..53703e9 100644
--- a/net/quic/quic_stream_factory.h
+++ b/net/quic/quic_stream_factory.h
@@ -191,7 +191,6 @@
 class NET_EXPORT_PRIVATE QuicStreamFactory
     : public NetworkChangeNotifier::IPAddressObserver,
       public NetworkChangeNotifier::NetworkObserver,
-      public SSLConfigService::Observer,
       public CertDatabase::Observer {
  public:
   // This class encompasses |destination| and |server_id|.
@@ -350,11 +349,6 @@
   void OnNetworkMadeDefault(
       NetworkChangeNotifier::NetworkHandle network) override;
 
-  // SSLConfigService::Observer methods:
-
-  // We perform the same flushing as described above when SSL settings change.
-  void OnSSLConfigChanged() override;
-
   // CertDatabase::Observer methods:
 
   // We close all sessions when certificate database is changed.
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
index 1a3719d..82d34af 100644
--- a/net/quic/quic_stream_factory_test.cc
+++ b/net/quic/quic_stream_factory_test.cc
@@ -7387,70 +7387,6 @@
   EXPECT_TRUE(socket_data1.AllWriteDataConsumed());
 }
 
-TEST_P(QuicStreamFactoryTest, OnSSLConfigChanged) {
-  Initialize();
-  ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
-  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
-  crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
-
-  MockQuicData socket_data;
-  socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
-  socket_data.AddWrite(
-      SYNCHRONOUS, ConstructClientRstPacket(2, quic::QUIC_RST_ACKNOWLEDGEMENT));
-  socket_data.AddWrite(
-      SYNCHRONOUS, client_maker_.MakeConnectionClosePacket(
-                       3, true, quic::QUIC_CONNECTION_CANCELLED, "net error"));
-  socket_data.AddSocketDataToFactory(socket_factory_.get());
-
-  MockQuicData socket_data2;
-  socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-  socket_data2.AddWrite(SYNCHRONOUS,
-                        ConstructInitialSettingsPacket(1, nullptr));
-  socket_data2.AddSocketDataToFactory(socket_factory_.get());
-
-  QuicStreamRequest request(factory_.get());
-  EXPECT_EQ(ERR_IO_PENDING,
-            request.Request(
-                host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
-                SocketTag(),
-                /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
-                failed_on_default_network_callback_, callback_.callback()));
-
-  EXPECT_THAT(callback_.WaitForResult(), IsOk());
-  std::unique_ptr<HttpStream> stream = CreateStream(&request);
-  HttpRequestInfo request_info;
-  request_info.traffic_annotation =
-      MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS);
-  EXPECT_EQ(OK, stream->InitializeStream(&request_info, false, DEFAULT_PRIORITY,
-                                         net_log_, CompletionOnceCallback()));
-
-  ssl_config_service_->NotifySSLConfigChange();
-  EXPECT_EQ(ERR_CERT_DATABASE_CHANGED,
-            stream->ReadResponseHeaders(callback_.callback()));
-  EXPECT_FALSE(factory_->require_confirmation());
-
-  // Now attempting to request a stream to the same origin should create
-  // a new session.
-
-  QuicStreamRequest request2(factory_.get());
-  EXPECT_EQ(ERR_IO_PENDING,
-            request2.Request(
-                host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
-                SocketTag(),
-                /*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
-                failed_on_default_network_callback_, callback_.callback()));
-
-  EXPECT_THAT(callback_.WaitForResult(), IsOk());
-  stream = CreateStream(&request2);
-  stream.reset();  // Will reset stream 3.
-
-  EXPECT_TRUE(socket_data.AllReadDataConsumed());
-  EXPECT_TRUE(socket_data.AllWriteDataConsumed());
-  EXPECT_TRUE(socket_data2.AllReadDataConsumed());
-  EXPECT_TRUE(socket_data2.AllWriteDataConsumed());
-}
-
 TEST_P(QuicStreamFactoryTest, OnCertDBChanged) {
   Initialize();
   ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
diff --git a/net/socket/client_socket_pool_manager.cc b/net/socket/client_socket_pool_manager.cc
index 894c0e20..f3d7c48 100644
--- a/net/socket/client_socket_pool_manager.cc
+++ b/net/socket/client_socket_pool_manager.cc
@@ -17,7 +17,6 @@
 #include "net/proxy_resolution/proxy_info.h"
 #include "net/socket/client_socket_handle.h"
 #include "net/socket/client_socket_pool.h"
-#include "net/socket/socks_client_socket_pool.h"
 #include "net/socket/socks_connect_job.h"
 #include "net/socket/ssl_client_socket_pool.h"
 #include "net/socket/transport_client_socket_pool.h"
@@ -234,17 +233,23 @@
   }
 
   if (proxy_info.is_socks()) {
-    SOCKSClientSocketPool* pool = session->GetSocketPoolForSOCKSProxy(
+    TransportClientSocketPool* pool = session->GetSocketPoolForSOCKSProxy(
         socket_pool_type, proxy_info.proxy_server());
     if (num_preconnect_streams) {
-      RequestSocketsForPool(pool, connection_group, socks_params,
-                            num_preconnect_streams, net_log);
+      RequestSocketsForPool(
+          pool, connection_group,
+          TransportClientSocketPool::SocketParams::CreateFromSOCKSSocketParams(
+              socks_params),
+          num_preconnect_streams, net_log);
       return OK;
     }
 
-    return socket_handle->Init(connection_group, socks_params, request_priority,
-                               socket_tag, respect_limits, std::move(callback),
-                               pool, net_log);
+    return socket_handle->Init(
+        connection_group,
+        TransportClientSocketPool::SocketParams::CreateFromSOCKSSocketParams(
+            socks_params),
+        request_priority, socket_tag, respect_limits, std::move(callback), pool,
+        net_log);
   }
 
   DCHECK(proxy_info.is_direct());
diff --git a/net/socket/client_socket_pool_manager.h b/net/socket/client_socket_pool_manager.h
index 167225f..23c9f88c 100644
--- a/net/socket/client_socket_pool_manager.h
+++ b/net/socket/client_socket_pool_manager.h
@@ -37,7 +37,6 @@
 class ProxyInfo;
 class ProxyServer;
 class TransportClientSocketPool;
-class SOCKSClientSocketPool;
 class SSLClientSocketPool;
 
 struct SSLConfig;
@@ -81,7 +80,7 @@
   virtual void CloseIdleSockets() = 0;
   virtual TransportClientSocketPool* GetTransportSocketPool() = 0;
   virtual SSLClientSocketPool* GetSSLSocketPool() = 0;
-  virtual SOCKSClientSocketPool* GetSocketPoolForSOCKSProxy(
+  virtual TransportClientSocketPool* GetSocketPoolForSOCKSProxy(
       const ProxyServer& socks_proxy) = 0;
   // Returns the HttpProxyClientSocketPool for a ProxyServer that uses an
   // "HTTP-like" scheme, as defined by ProxyServer::is_http_like().
diff --git a/net/socket/client_socket_pool_manager_impl.cc b/net/socket/client_socket_pool_manager_impl.cc
index 11b2821..2afd7d9 100644
--- a/net/socket/client_socket_pool_manager_impl.cc
+++ b/net/socket/client_socket_pool_manager_impl.cc
@@ -12,9 +12,10 @@
 #include "net/base/proxy_server.h"
 #include "net/http/http_network_session.h"
 #include "net/http/http_proxy_client_socket_pool.h"
-#include "net/socket/socks_client_socket_pool.h"
+#include "net/socket/socks_connect_job.h"
 #include "net/socket/ssl_client_socket_pool.h"
 #include "net/socket/transport_client_socket_pool.h"
+#include "net/socket/transport_connect_job.h"
 #include "net/socket/websocket_transport_client_socket_pool.h"
 #include "net/ssl/ssl_config_service.h"
 
@@ -111,47 +112,29 @@
   // Flush the highest level pools first, since higher level pools may release
   // stuff to the lower level pools.
 
-  for (SSLSocketPoolMap::const_iterator it =
-       ssl_socket_pools_for_proxies_.begin();
-       it != ssl_socket_pools_for_proxies_.end();
-       ++it)
-    it->second->FlushWithError(error);
+  for (const auto& it : ssl_socket_pools_for_proxies_) {
+    it.second->FlushWithError(error);
+  }
 
-  for (HTTPProxySocketPoolMap::const_iterator it =
-       http_proxy_socket_pools_.begin();
-       it != http_proxy_socket_pools_.end();
-       ++it)
-    it->second->FlushWithError(error);
+  for (const auto& it : http_proxy_socket_pools_) {
+    it.second->FlushWithError(error);
+  }
 
-  for (SSLSocketPoolMap::const_iterator it =
-       ssl_socket_pools_for_https_proxies_.begin();
-       it != ssl_socket_pools_for_https_proxies_.end();
-       ++it)
-    it->second->FlushWithError(error);
+  for (const auto& it : ssl_socket_pools_for_https_proxies_) {
+    it.second->FlushWithError(error);
+  }
 
-  for (TransportSocketPoolMap::const_iterator it =
-       transport_socket_pools_for_https_proxies_.begin();
-       it != transport_socket_pools_for_https_proxies_.end();
-       ++it)
-    it->second->FlushWithError(error);
+  for (const auto& it : transport_socket_pools_for_https_proxies_) {
+    it.second->FlushWithError(error);
+  }
 
-  for (TransportSocketPoolMap::const_iterator it =
-       transport_socket_pools_for_http_proxies_.begin();
-       it != transport_socket_pools_for_http_proxies_.end();
-       ++it)
-    it->second->FlushWithError(error);
+  for (const auto& it : transport_socket_pools_for_http_proxies_) {
+    it.second->FlushWithError(error);
+  }
 
-  for (SOCKSSocketPoolMap::const_iterator it =
-       socks_socket_pools_.begin();
-       it != socks_socket_pools_.end();
-       ++it)
-    it->second->FlushWithError(error);
-
-  for (TransportSocketPoolMap::const_iterator it =
-       transport_socket_pools_for_socks_proxies_.begin();
-       it != transport_socket_pools_for_socks_proxies_.end();
-       ++it)
-    it->second->FlushWithError(error);
+  for (const auto& it : proxy_socket_pools_) {
+    it.second->FlushWithError(error);
+  }
 
   ssl_socket_pool_->FlushWithError(error);
   transport_socket_pool_->FlushWithError(error);
@@ -160,47 +143,29 @@
 void ClientSocketPoolManagerImpl::CloseIdleSockets() {
   // Close sockets in the highest level pools first, since higher level pools'
   // sockets may release stuff to the lower level pools.
-  for (SSLSocketPoolMap::const_iterator it =
-       ssl_socket_pools_for_proxies_.begin();
-       it != ssl_socket_pools_for_proxies_.end();
-       ++it)
-    it->second->CloseIdleSockets();
+  for (const auto& it : ssl_socket_pools_for_proxies_) {
+    it.second->CloseIdleSockets();
+  }
 
-  for (HTTPProxySocketPoolMap::const_iterator it =
-       http_proxy_socket_pools_.begin();
-       it != http_proxy_socket_pools_.end();
-       ++it)
-    it->second->CloseIdleSockets();
+  for (const auto& it : http_proxy_socket_pools_) {
+    it.second->CloseIdleSockets();
+  }
 
-  for (SSLSocketPoolMap::const_iterator it =
-       ssl_socket_pools_for_https_proxies_.begin();
-       it != ssl_socket_pools_for_https_proxies_.end();
-       ++it)
-    it->second->CloseIdleSockets();
+  for (const auto& it : ssl_socket_pools_for_https_proxies_) {
+    it.second->CloseIdleSockets();
+  }
 
-  for (TransportSocketPoolMap::const_iterator it =
-       transport_socket_pools_for_https_proxies_.begin();
-       it != transport_socket_pools_for_https_proxies_.end();
-       ++it)
-    it->second->CloseIdleSockets();
+  for (const auto& it : transport_socket_pools_for_https_proxies_) {
+    it.second->CloseIdleSockets();
+  }
 
-  for (TransportSocketPoolMap::const_iterator it =
-       transport_socket_pools_for_http_proxies_.begin();
-       it != transport_socket_pools_for_http_proxies_.end();
-       ++it)
-    it->second->CloseIdleSockets();
+  for (const auto& it : transport_socket_pools_for_http_proxies_) {
+    it.second->CloseIdleSockets();
+  }
 
-  for (SOCKSSocketPoolMap::const_iterator it =
-       socks_socket_pools_.begin();
-       it != socks_socket_pools_.end();
-       ++it)
-    it->second->CloseIdleSockets();
-
-  for (TransportSocketPoolMap::const_iterator it =
-       transport_socket_pools_for_socks_proxies_.begin();
-       it != transport_socket_pools_for_socks_proxies_.end();
-       ++it)
-    it->second->CloseIdleSockets();
+  for (const auto& it : proxy_socket_pools_) {
+    it.second->CloseIdleSockets();
+  }
 
   ssl_socket_pool_->CloseIdleSockets();
   transport_socket_pool_->CloseIdleSockets();
@@ -215,37 +180,27 @@
   return ssl_socket_pool_.get();
 }
 
-SOCKSClientSocketPool* ClientSocketPoolManagerImpl::GetSocketPoolForSOCKSProxy(
-    const ProxyServer& socks_proxy) {
-  DCHECK(socks_proxy.is_socks());
+TransportClientSocketPool*
+ClientSocketPoolManagerImpl::GetSocketPoolForSOCKSProxy(
+    const ProxyServer& proxy_server) {
+  DCHECK(proxy_server.is_socks());
 
-  SOCKSSocketPoolMap::const_iterator it = socks_socket_pools_.find(socks_proxy);
-  if (it != socks_socket_pools_.end()) {
-    DCHECK(base::ContainsKey(transport_socket_pools_for_socks_proxies_,
-                             socks_proxy));
+  TransportSocketPoolMap::const_iterator it =
+      proxy_socket_pools_.find(proxy_server);
+  if (it != proxy_socket_pools_.end())
     return it->second.get();
-  }
 
-  DCHECK(!base::ContainsKey(transport_socket_pools_for_socks_proxies_,
-                            socks_proxy));
   int sockets_per_proxy_server = max_sockets_per_proxy_server(pool_type_);
   int sockets_per_group = std::min(sockets_per_proxy_server,
                                    max_sockets_per_group(pool_type_));
 
-  std::pair<TransportSocketPoolMap::iterator, bool> tcp_ret =
-      transport_socket_pools_for_socks_proxies_.insert(std::make_pair(
-          socks_proxy,
+  std::pair<TransportSocketPoolMap::iterator, bool> ret =
+      proxy_socket_pools_.insert(std::make_pair(
+          proxy_server,
           std::make_unique<TransportClientSocketPool>(
               sockets_per_proxy_server, sockets_per_group, host_resolver_,
-              socket_factory_, nullptr, net_log_)));
-  DCHECK(tcp_ret.second);
-
-  std::pair<SOCKSSocketPoolMap::iterator, bool> ret =
-      socks_socket_pools_.insert(std::make_pair(
-          socks_proxy,
-          std::make_unique<SOCKSClientSocketPool>(
-              sockets_per_proxy_server, sockets_per_group, host_resolver_,
-              tcp_ret.first->second.get(), nullptr, net_log_)));
+              socket_factory_, nullptr /* socket_performance_watcher */,
+              net_log_)));
 
   return ret.first->second.get();
 }
@@ -360,7 +315,7 @@
                                                 false));
   AddSocketPoolsToList(list.get(), http_proxy_socket_pools_,
                        "http_proxy_socket_pool", true);
-  AddSocketPoolsToList(list.get(), socks_socket_pools_, "socks_socket_pool",
+  AddSocketPoolsToList(list.get(), proxy_socket_pools_, "proxy_socket_pools",
                        true);
 
   // Third parameter is false because |ssl_socket_pools_for_proxies_| use
diff --git a/net/socket/client_socket_pool_manager_impl.h b/net/socket/client_socket_pool_manager_impl.h
index 5f500dd..e8f3fa2 100644
--- a/net/socket/client_socket_pool_manager_impl.h
+++ b/net/socket/client_socket_pool_manager_impl.h
@@ -38,7 +38,6 @@
 class ProxyDelegate;
 class ProxyServer;
 class SocketPerformanceWatcherFactory;
-class SOCKSClientSocketPool;
 class SSLClientSocketPool;
 class SSLConfigService;
 class TransportClientSocketPool;
@@ -74,8 +73,8 @@
 
   SSLClientSocketPool* GetSSLSocketPool() override;
 
-  SOCKSClientSocketPool* GetSocketPoolForSOCKSProxy(
-      const ProxyServer& socks_proxy) override;
+  TransportClientSocketPool* GetSocketPoolForSOCKSProxy(
+      const ProxyServer& proxy_server) override;
 
   HttpProxyClientSocketPool* GetSocketPoolForHTTPLikeProxy(
       const ProxyServer& http_proxy) override;
@@ -96,8 +95,6 @@
  private:
   using TransportSocketPoolMap =
       std::map<ProxyServer, std::unique_ptr<TransportClientSocketPool>>;
-  using SOCKSSocketPoolMap =
-      std::map<ProxyServer, std::unique_ptr<SOCKSClientSocketPool>>;
   using HTTPProxySocketPoolMap =
       std::map<ProxyServer, std::unique_ptr<HttpProxyClientSocketPool>>;
   using SSLSocketPoolMap =
@@ -122,8 +119,13 @@
 
   std::unique_ptr<TransportClientSocketPool> transport_socket_pool_;
   std::unique_ptr<SSLClientSocketPool> ssl_socket_pool_;
-  TransportSocketPoolMap transport_socket_pools_for_socks_proxies_;
-  SOCKSSocketPoolMap socks_socket_pools_;
+
+  // Currently only contains socket pools for SOCKS proxies (With SSL over SOCKS
+  // connections layered on top of it, and appearing in
+  // |ssl_socket_pools_for_proxies_|), but will eventually contain all pools for
+  // proxies that use TCP connections.
+  TransportSocketPoolMap proxy_socket_pools_;
+
   TransportSocketPoolMap transport_socket_pools_for_http_proxies_;
   TransportSocketPoolMap transport_socket_pools_for_https_proxies_;
   SSLSocketPoolMap ssl_socket_pools_for_https_proxies_;
diff --git a/net/socket/mock_client_socket_pool_manager.cc b/net/socket/mock_client_socket_pool_manager.cc
index 28a5d4c..b9776561 100644
--- a/net/socket/mock_client_socket_pool_manager.cc
+++ b/net/socket/mock_client_socket_pool_manager.cc
@@ -6,7 +6,6 @@
 
 #include "base/values.h"
 #include "net/http/http_proxy_client_socket_pool.h"
-#include "net/socket/socks_client_socket_pool.h"
 #include "net/socket/ssl_client_socket_pool.h"
 #include "net/socket/transport_client_socket_pool.h"
 
@@ -25,10 +24,11 @@
   ssl_socket_pool_.reset(pool);
 }
 
-void MockClientSocketPoolManager::SetSocketPoolForSOCKSProxy(
-    const ProxyServer& socks_proxy,
-    std::unique_ptr<SOCKSClientSocketPool> pool) {
-  socks_socket_pools_[socks_proxy] = std::move(pool);
+void MockClientSocketPoolManager::SetSocketPoolForProxy(
+    const ProxyServer& proxy_server,
+    std::unique_ptr<TransportClientSocketPool> pool) {
+  DCHECK(proxy_server.is_socks());
+  proxy_socket_pools_[proxy_server] = std::move(pool);
 }
 
 void MockClientSocketPoolManager::SetSocketPoolForHTTPProxy(
@@ -60,10 +60,13 @@
   return ssl_socket_pool_.get();
 }
 
-SOCKSClientSocketPool* MockClientSocketPoolManager::GetSocketPoolForSOCKSProxy(
-    const ProxyServer& socks_proxy) {
-  SOCKSSocketPoolMap::const_iterator it = socks_socket_pools_.find(socks_proxy);
-  if (it != socks_socket_pools_.end())
+TransportClientSocketPool*
+MockClientSocketPoolManager::GetSocketPoolForSOCKSProxy(
+    const ProxyServer& proxy_server) {
+  DCHECK(proxy_server.is_socks());
+  TransportClientSocketPoolMap::const_iterator it =
+      proxy_socket_pools_.find(proxy_server);
+  if (it != proxy_socket_pools_.end())
     return it->second.get();
   return nullptr;
 }
diff --git a/net/socket/mock_client_socket_pool_manager.h b/net/socket/mock_client_socket_pool_manager.h
index bf46e4475..8e97cd6b 100644
--- a/net/socket/mock_client_socket_pool_manager.h
+++ b/net/socket/mock_client_socket_pool_manager.h
@@ -24,8 +24,9 @@
   // Sets "override" socket pools that get used instead.
   void SetTransportSocketPool(TransportClientSocketPool* pool);
   void SetSSLSocketPool(SSLClientSocketPool* pool);
-  void SetSocketPoolForSOCKSProxy(const ProxyServer& socks_proxy,
-                                  std::unique_ptr<SOCKSClientSocketPool> pool);
+  // Currently only works for SOCKS proxies.
+  void SetSocketPoolForProxy(const ProxyServer& proxy_server,
+                             std::unique_ptr<TransportClientSocketPool> pool);
   void SetSocketPoolForHTTPProxy(
       const ProxyServer& http_proxy,
       std::unique_ptr<HttpProxyClientSocketPool> pool);
@@ -37,7 +38,7 @@
   void CloseIdleSockets() override;
   TransportClientSocketPool* GetTransportSocketPool() override;
   SSLClientSocketPool* GetSSLSocketPool() override;
-  SOCKSClientSocketPool* GetSocketPoolForSOCKSProxy(
+  TransportClientSocketPool* GetSocketPoolForSOCKSProxy(
       const ProxyServer& socks_proxy) override;
   HttpProxyClientSocketPool* GetSocketPoolForHTTPLikeProxy(
       const ProxyServer& http_proxy) override;
@@ -49,8 +50,8 @@
       const std::string& parent_dump_absolute_name) const override;
 
  private:
-  using SOCKSSocketPoolMap =
-      std::map<ProxyServer, std::unique_ptr<SOCKSClientSocketPool>>;
+  using TransportClientSocketPoolMap =
+      std::map<ProxyServer, std::unique_ptr<TransportClientSocketPool>>;
   using HTTPProxySocketPoolMap =
       std::map<ProxyServer, std::unique_ptr<HttpProxyClientSocketPool>>;
   using SSLSocketPoolMap =
@@ -58,7 +59,7 @@
 
   std::unique_ptr<TransportClientSocketPool> transport_socket_pool_;
   std::unique_ptr<SSLClientSocketPool> ssl_socket_pool_;
-  SOCKSSocketPoolMap socks_socket_pools_;
+  TransportClientSocketPoolMap proxy_socket_pools_;
   HTTPProxySocketPoolMap http_proxy_socket_pools_;
   SSLSocketPoolMap ssl_socket_pools_for_proxies_;
 
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index 14d7608..2d1db66 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -2138,52 +2138,6 @@
   release_count_++;
 }
 
-MockSOCKSClientSocketPool::MockSOCKSClientSocketPool(
-    int max_sockets,
-    int max_sockets_per_group,
-    TransportClientSocketPool* transport_pool)
-    : SOCKSClientSocketPool(max_sockets,
-                            max_sockets_per_group,
-                            NULL,
-                            transport_pool,
-                            NULL,
-                            NULL),
-      transport_pool_(transport_pool) {}
-
-MockSOCKSClientSocketPool::~MockSOCKSClientSocketPool() = default;
-
-int MockSOCKSClientSocketPool::RequestSocket(const std::string& group_name,
-                                             const void* socket_params,
-                                             RequestPriority priority,
-                                             const SocketTag& socket_tag,
-                                             RespectLimits respect_limits,
-                                             ClientSocketHandle* handle,
-                                             CompletionOnceCallback callback,
-                                             const NetLogWithSource& net_log) {
-  return transport_pool_->RequestSocket(group_name, socket_params, priority,
-                                        socket_tag, respect_limits, handle,
-                                        std::move(callback), net_log);
-}
-
-void MockSOCKSClientSocketPool::SetPriority(const std::string& group_name,
-                                            ClientSocketHandle* handle,
-                                            RequestPriority priority) {
-  transport_pool_->SetPriority(group_name, handle, priority);
-}
-
-void MockSOCKSClientSocketPool::CancelRequest(
-    const std::string& group_name,
-    ClientSocketHandle* handle) {
-  return transport_pool_->CancelRequest(group_name, handle);
-}
-
-void MockSOCKSClientSocketPool::ReleaseSocket(
-    const std::string& group_name,
-    std::unique_ptr<StreamSocket> socket,
-    int id) {
-  return transport_pool_->ReleaseSocket(group_name, std::move(socket), id);
-}
-
 WrappedStreamSocket::WrappedStreamSocket(
     std::unique_ptr<StreamSocket> transport)
     : transport_(std::move(transport)) {}
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h
index 1e001e1..f9d53ce 100644
--- a/net/socket/socket_test_util.h
+++ b/net/socket/socket_test_util.h
@@ -40,7 +40,6 @@
 #include "net/socket/datagram_client_socket.h"
 #include "net/socket/socket_performance_watcher.h"
 #include "net/socket/socket_tag.h"
-#include "net/socket/socks_client_socket_pool.h"
 #include "net/socket/ssl_client_socket.h"
 #include "net/socket/ssl_client_socket_pool.h"
 #include "net/socket/transport_client_socket.h"
@@ -1243,38 +1242,6 @@
   DISALLOW_COPY_AND_ASSIGN(MockTransportClientSocketPool);
 };
 
-class MockSOCKSClientSocketPool : public SOCKSClientSocketPool {
- public:
-  MockSOCKSClientSocketPool(int max_sockets,
-                            int max_sockets_per_group,
-                            TransportClientSocketPool* transport_pool);
-
-  ~MockSOCKSClientSocketPool() override;
-
-  // SOCKSClientSocketPool implementation.
-  int RequestSocket(const std::string& group_name,
-                    const void* socket_params,
-                    RequestPriority priority,
-                    const SocketTag& socket_tag,
-                    RespectLimits respect_limits,
-                    ClientSocketHandle* handle,
-                    CompletionOnceCallback callback,
-                    const NetLogWithSource& net_log) override;
-  void SetPriority(const std::string& group_name,
-                   ClientSocketHandle* handle,
-                   RequestPriority priority) override;
-  void CancelRequest(const std::string& group_name,
-                     ClientSocketHandle* handle) override;
-  void ReleaseSocket(const std::string& group_name,
-                     std::unique_ptr<StreamSocket> socket,
-                     int id) override;
-
- private:
-  TransportClientSocketPool* const transport_pool_;
-
-  DISALLOW_COPY_AND_ASSIGN(MockSOCKSClientSocketPool);
-};
-
 // WrappedStreamSocket is a base class that wraps an existing StreamSocket,
 // forwarding the Socket and StreamSocket interfaces to the underlying
 // transport.
diff --git a/net/socket/socks5_client_socket.cc b/net/socket/socks5_client_socket.cc
index 6c2eec9..fe00fc8 100644
--- a/net/socket/socks5_client_socket.cc
+++ b/net/socket/socks5_client_socket.cc
@@ -17,7 +17,6 @@
 #include "net/base/io_buffer.h"
 #include "net/log/net_log.h"
 #include "net/log/net_log_event_type.h"
-#include "net/socket/client_socket_handle.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 
 namespace net {
@@ -33,12 +32,12 @@
 static_assert(sizeof(struct in6_addr) == 16, "incorrect system size of IPv6");
 
 SOCKS5ClientSocket::SOCKS5ClientSocket(
-    std::unique_ptr<ClientSocketHandle> transport_socket,
+    std::unique_ptr<StreamSocket> transport_socket,
     const HostResolver::RequestInfo& req_info,
     const NetworkTrafficAnnotationTag& traffic_annotation)
     : io_callback_(base::BindRepeating(&SOCKS5ClientSocket::OnIOComplete,
                                        base::Unretained(this))),
-      transport_(std::move(transport_socket)),
+      transport_socket_(std::move(transport_socket)),
       next_state_(STATE_NONE),
       completed_handshake_(false),
       bytes_sent_(0),
@@ -46,7 +45,7 @@
       read_header_size(kReadHeaderSize),
       was_ever_used_(false),
       host_request_info_(req_info),
-      net_log_(transport_->socket()->NetLog()),
+      net_log_(transport_socket_->NetLog()),
       traffic_annotation_(traffic_annotation) {}
 
 SOCKS5ClientSocket::~SOCKS5ClientSocket() {
@@ -54,8 +53,7 @@
 }
 
 int SOCKS5ClientSocket::Connect(CompletionOnceCallback callback) {
-  DCHECK(transport_.get());
-  DCHECK(transport_->socket());
+  DCHECK(transport_socket_);
   DCHECK_EQ(STATE_NONE, next_state_);
   DCHECK(user_callback_.is_null());
 
@@ -79,7 +77,7 @@
 
 void SOCKS5ClientSocket::Disconnect() {
   completed_handshake_ = false;
-  transport_->socket()->Disconnect();
+  transport_socket_->Disconnect();
 
   // Reset other states to make sure they aren't mistakenly used later.
   // These are the states initialized by Connect().
@@ -88,11 +86,11 @@
 }
 
 bool SOCKS5ClientSocket::IsConnected() const {
-  return completed_handshake_ && transport_->socket()->IsConnected();
+  return completed_handshake_ && transport_socket_->IsConnected();
 }
 
 bool SOCKS5ClientSocket::IsConnectedAndIdle() const {
-  return completed_handshake_ && transport_->socket()->IsConnectedAndIdle();
+  return completed_handshake_ && transport_socket_->IsConnectedAndIdle();
 }
 
 const NetLogWithSource& SOCKS5ClientSocket::NetLog() const {
@@ -104,25 +102,22 @@
 }
 
 bool SOCKS5ClientSocket::WasAlpnNegotiated() const {
-  if (transport_.get() && transport_->socket()) {
-    return transport_->socket()->WasAlpnNegotiated();
-  }
+  if (transport_socket_)
+    return transport_socket_->WasAlpnNegotiated();
   NOTREACHED();
   return false;
 }
 
 NextProto SOCKS5ClientSocket::GetNegotiatedProtocol() const {
-  if (transport_.get() && transport_->socket()) {
-    return transport_->socket()->GetNegotiatedProtocol();
-  }
+  if (transport_socket_)
+    return transport_socket_->GetNegotiatedProtocol();
   NOTREACHED();
   return kProtoUnknown;
 }
 
 bool SOCKS5ClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
-  if (transport_.get() && transport_->socket()) {
-    return transport_->socket()->GetSSLInfo(ssl_info);
-  }
+  if (transport_socket_)
+    return transport_socket_->GetSSLInfo(ssl_info);
   NOTREACHED();
   return false;
 }
@@ -132,11 +127,11 @@
 }
 
 int64_t SOCKS5ClientSocket::GetTotalReceivedBytes() const {
-  return transport_->socket()->GetTotalReceivedBytes();
+  return transport_socket_->GetTotalReceivedBytes();
 }
 
 void SOCKS5ClientSocket::ApplySocketTag(const SocketTag& tag) {
-  return transport_->socket()->ApplySocketTag(tag);
+  return transport_socket_->ApplySocketTag(tag);
 }
 
 // Read is called by the transport layer above to read. This can only be done
@@ -149,7 +144,7 @@
   DCHECK(user_callback_.is_null());
   DCHECK(!callback.is_null());
 
-  int rv = transport_->socket()->Read(
+  int rv = transport_socket_->Read(
       buf, buf_len,
       base::BindOnce(&SOCKS5ClientSocket::OnReadWriteComplete,
                      base::Unretained(this), std::move(callback)));
@@ -170,7 +165,7 @@
   DCHECK(user_callback_.is_null());
   DCHECK(!callback.is_null());
 
-  int rv = transport_->socket()->Write(
+  int rv = transport_socket_->Write(
       buf, buf_len,
       base::BindOnce(&SOCKS5ClientSocket::OnReadWriteComplete,
                      base::Unretained(this), std::move(callback)),
@@ -181,11 +176,11 @@
 }
 
 int SOCKS5ClientSocket::SetReceiveBufferSize(int32_t size) {
-  return transport_->socket()->SetReceiveBufferSize(size);
+  return transport_socket_->SetReceiveBufferSize(size);
 }
 
 int SOCKS5ClientSocket::SetSendBufferSize(int32_t size) {
-  return transport_->socket()->SetSendBufferSize(size);
+  return transport_socket_->SetSendBufferSize(size);
 }
 
 void SOCKS5ClientSocket::DoCallback(int result) {
@@ -293,8 +288,8 @@
   handshake_buf_ = base::MakeRefCounted<IOBuffer>(handshake_buf_len);
   memcpy(handshake_buf_->data(), &buffer_.data()[bytes_sent_],
          handshake_buf_len);
-  return transport_->socket()->Write(handshake_buf_.get(), handshake_buf_len,
-                                     io_callback_, traffic_annotation_);
+  return transport_socket_->Write(handshake_buf_.get(), handshake_buf_len,
+                                  io_callback_, traffic_annotation_);
 }
 
 int SOCKS5ClientSocket::DoGreetWriteComplete(int result) {
@@ -316,8 +311,8 @@
   next_state_ = STATE_GREET_READ_COMPLETE;
   size_t handshake_buf_len = kGreetReadHeaderSize - bytes_received_;
   handshake_buf_ = base::MakeRefCounted<IOBuffer>(handshake_buf_len);
-  return transport_->socket()
-      ->Read(handshake_buf_.get(), handshake_buf_len, io_callback_);
+  return transport_socket_->Read(handshake_buf_.get(), handshake_buf_len,
+                                 io_callback_);
 }
 
 int SOCKS5ClientSocket::DoGreetReadComplete(int result) {
@@ -392,8 +387,8 @@
   handshake_buf_ = base::MakeRefCounted<IOBuffer>(handshake_buf_len);
   memcpy(handshake_buf_->data(), &buffer_[bytes_sent_],
          handshake_buf_len);
-  return transport_->socket()->Write(handshake_buf_.get(), handshake_buf_len,
-                                     io_callback_, traffic_annotation_);
+  return transport_socket_->Write(handshake_buf_.get(), handshake_buf_len,
+                                  io_callback_, traffic_annotation_);
 }
 
 int SOCKS5ClientSocket::DoHandshakeWriteComplete(int result) {
@@ -426,8 +421,8 @@
 
   int handshake_buf_len = read_header_size - bytes_received_;
   handshake_buf_ = base::MakeRefCounted<IOBuffer>(handshake_buf_len);
-  return transport_->socket()
-      ->Read(handshake_buf_.get(), handshake_buf_len, io_callback_);
+  return transport_socket_->Read(handshake_buf_.get(), handshake_buf_len,
+                                 io_callback_);
 }
 
 int SOCKS5ClientSocket::DoHandshakeReadComplete(int result) {
@@ -497,11 +492,11 @@
 }
 
 int SOCKS5ClientSocket::GetPeerAddress(IPEndPoint* address) const {
-  return transport_->socket()->GetPeerAddress(address);
+  return transport_socket_->GetPeerAddress(address);
 }
 
 int SOCKS5ClientSocket::GetLocalAddress(IPEndPoint* address) const {
-  return transport_->socket()->GetLocalAddress(address);
+  return transport_socket_->GetLocalAddress(address);
 }
 
 }  // namespace net
diff --git a/net/socket/socks5_client_socket.h b/net/socket/socks5_client_socket.h
index b6e59ae..aa8da1c3 100644
--- a/net/socket/socks5_client_socket.h
+++ b/net/socket/socks5_client_socket.h
@@ -26,8 +26,6 @@
 
 namespace net {
 
-class ClientSocketHandle;
-
 // This StreamSocket is used to setup a SOCKSv5 handshake with a socks proxy.
 // Currently no SOCKSv5 authentication is supported.
 class NET_EXPORT_PRIVATE SOCKS5ClientSocket : public StreamSocket {
@@ -38,7 +36,7 @@
   // Although SOCKS 5 supports 3 different modes of addressing, we will
   // always pass it a hostname. This means the DNS resolving is done
   // proxy side.
-  SOCKS5ClientSocket(std::unique_ptr<ClientSocketHandle> transport_socket,
+  SOCKS5ClientSocket(std::unique_ptr<StreamSocket> transport_socket,
                      const HostResolver::RequestInfo& req_info,
                      const NetworkTrafficAnnotationTag& traffic_annotation);
 
@@ -126,7 +124,7 @@
   CompletionRepeatingCallback io_callback_;
 
   // Stores the underlying socket.
-  std::unique_ptr<ClientSocketHandle> transport_;
+  std::unique_ptr<StreamSocket> transport_socket_;
 
   State next_state_;
 
diff --git a/net/socket/socks5_client_socket_fuzzer.cc b/net/socket/socks5_client_socket_fuzzer.cc
index fb9c7b5..783184c 100644
--- a/net/socket/socks5_client_socket_fuzzer.cc
+++ b/net/socket/socks5_client_socket_fuzzer.cc
@@ -13,7 +13,6 @@
 #include "net/base/net_errors.h"
 #include "net/base/test_completion_callback.h"
 #include "net/log/test_net_log.h"
-#include "net/socket/client_socket_handle.h"
 #include "net/socket/fuzzed_socket.h"
 #include "net/socket/socks5_client_socket.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -34,12 +33,8 @@
       new net::FuzzedSocket(&data_provider, &test_net_log));
   CHECK_EQ(net::OK, fuzzed_socket->Connect(callback.callback()));
 
-  std::unique_ptr<net::ClientSocketHandle> socket_handle(
-      new net::ClientSocketHandle());
-  socket_handle->SetSocket(std::move(fuzzed_socket));
-
   net::HostResolver::RequestInfo request_info(net::HostPortPair("foo", 80));
-  net::SOCKS5ClientSocket socket(std::move(socket_handle), request_info,
+  net::SOCKS5ClientSocket socket(std::move(fuzzed_socket), request_info,
                                  TRAFFIC_ANNOTATION_FOR_TESTS);
   int result = socket.Connect(callback.callback());
   callback.GetResult(result);
diff --git a/net/socket/socks5_client_socket_unittest.cc b/net/socket/socks5_client_socket_unittest.cc
index a8052f018..0f42457 100644
--- a/net/socket/socks5_client_socket_unittest.cc
+++ b/net/socket/socks5_client_socket_unittest.cc
@@ -111,14 +111,12 @@
   EXPECT_THAT(rv, IsOk());
   EXPECT_TRUE(tcp_sock_->IsConnected());
 
-  std::unique_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
-  // |connection| takes ownership of |tcp_sock_|, but keep a
+  // The SOCKS5ClientSocket takes ownership of |tcp_sock_|, but keep a
   // non-owning pointer to it.
-  connection->SetSocket(std::unique_ptr<StreamSocket>(tcp_sock_));
-  return std::unique_ptr<SOCKS5ClientSocket>(new SOCKS5ClientSocket(
-      std::move(connection),
+  return std::make_unique<SOCKS5ClientSocket>(
+      base::WrapUnique(tcp_sock_),
       HostResolver::RequestInfo(HostPortPair(hostname, port)),
-      TRAFFIC_ANNOTATION_FOR_TESTS));
+      TRAFFIC_ANNOTATION_FOR_TESTS);
 }
 
 // Tests a complete SOCKS5 handshake and the disconnection.
@@ -384,12 +382,10 @@
       new MockTaggingStreamSocket(std::unique_ptr<StreamSocket>(
           new MockTCPClientSocket(address_list_, &log, &data)));
 
-  std::unique_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
-  // |connection| takes ownership of |tagging_sock|, but keep a
-  // non-owning pointer to it.
-  connection->SetSocket(std::unique_ptr<StreamSocket>(tagging_sock));
+  // |socket| takes ownership of |tagging_sock|, but keep a non-owning pointer
+  // to it.
   SOCKS5ClientSocket socket(
-      std::move(connection),
+      std::unique_ptr<StreamSocket>(tagging_sock),
       HostResolver::RequestInfo(HostPortPair("localhost", 80)),
       TRAFFIC_ANNOTATION_FOR_TESTS);
 
diff --git a/net/socket/socks_client_socket.cc b/net/socket/socks_client_socket.cc
index ede3b356..af298ff 100644
--- a/net/socket/socks_client_socket.cc
+++ b/net/socket/socks_client_socket.cc
@@ -14,7 +14,6 @@
 #include "net/base/io_buffer.h"
 #include "net/log/net_log.h"
 #include "net/log/net_log_event_type.h"
-#include "net/socket/client_socket_handle.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 
 namespace net {
@@ -60,12 +59,12 @@
               "socks4 server response struct has incorrect size");
 
 SOCKSClientSocket::SOCKSClientSocket(
-    std::unique_ptr<ClientSocketHandle> transport_socket,
+    std::unique_ptr<StreamSocket> transport_socket,
     const HostResolver::RequestInfo& req_info,
     RequestPriority priority,
     HostResolver* host_resolver,
     const NetworkTrafficAnnotationTag& traffic_annotation)
-    : transport_(std::move(transport_socket)),
+    : transport_socket_(std::move(transport_socket)),
       next_state_(STATE_NONE),
       completed_handshake_(false),
       bytes_sent_(0),
@@ -74,7 +73,7 @@
       host_resolver_(host_resolver),
       host_request_info_(req_info),
       priority_(priority),
-      net_log_(transport_->socket()->NetLog()),
+      net_log_(transport_socket_->NetLog()),
       traffic_annotation_(traffic_annotation) {}
 
 SOCKSClientSocket::~SOCKSClientSocket() {
@@ -82,8 +81,7 @@
 }
 
 int SOCKSClientSocket::Connect(CompletionOnceCallback callback) {
-  DCHECK(transport_.get());
-  DCHECK(transport_->socket());
+  DCHECK(transport_socket_);
   DCHECK_EQ(STATE_NONE, next_state_);
   DCHECK(user_callback_.is_null());
 
@@ -107,7 +105,7 @@
 void SOCKSClientSocket::Disconnect() {
   completed_handshake_ = false;
   request_.reset();
-  transport_->socket()->Disconnect();
+  transport_socket_->Disconnect();
 
   // Reset other states to make sure they aren't mistakenly used later.
   // These are the states initialized by Connect().
@@ -116,11 +114,11 @@
 }
 
 bool SOCKSClientSocket::IsConnected() const {
-  return completed_handshake_ && transport_->socket()->IsConnected();
+  return completed_handshake_ && transport_socket_->IsConnected();
 }
 
 bool SOCKSClientSocket::IsConnectedAndIdle() const {
-  return completed_handshake_ && transport_->socket()->IsConnectedAndIdle();
+  return completed_handshake_ && transport_socket_->IsConnectedAndIdle();
 }
 
 const NetLogWithSource& SOCKSClientSocket::NetLog() const {
@@ -132,25 +130,22 @@
 }
 
 bool SOCKSClientSocket::WasAlpnNegotiated() const {
-  if (transport_.get() && transport_->socket()) {
-    return transport_->socket()->WasAlpnNegotiated();
-  }
+  if (transport_socket_)
+    return transport_socket_->WasAlpnNegotiated();
   NOTREACHED();
   return false;
 }
 
 NextProto SOCKSClientSocket::GetNegotiatedProtocol() const {
-  if (transport_.get() && transport_->socket()) {
-    return transport_->socket()->GetNegotiatedProtocol();
-  }
+  if (transport_socket_)
+    return transport_socket_->GetNegotiatedProtocol();
   NOTREACHED();
   return kProtoUnknown;
 }
 
 bool SOCKSClientSocket::GetSSLInfo(SSLInfo* ssl_info) {
-  if (transport_.get() && transport_->socket()) {
-    return transport_->socket()->GetSSLInfo(ssl_info);
-  }
+  if (transport_socket_)
+    return transport_socket_->GetSSLInfo(ssl_info);
   NOTREACHED();
   return false;
 }
@@ -160,11 +155,11 @@
 }
 
 int64_t SOCKSClientSocket::GetTotalReceivedBytes() const {
-  return transport_->socket()->GetTotalReceivedBytes();
+  return transport_socket_->GetTotalReceivedBytes();
 }
 
 void SOCKSClientSocket::ApplySocketTag(const SocketTag& tag) {
-  return transport_->socket()->ApplySocketTag(tag);
+  return transport_socket_->ApplySocketTag(tag);
 }
 
 // Read is called by the transport layer above to read. This can only be done
@@ -177,7 +172,7 @@
   DCHECK(user_callback_.is_null());
   DCHECK(!callback.is_null());
 
-  int rv = transport_->socket()->Read(
+  int rv = transport_socket_->Read(
       buf, buf_len,
       base::BindOnce(&SOCKSClientSocket::OnReadWriteComplete,
                      base::Unretained(this), std::move(callback)));
@@ -196,14 +191,14 @@
 
   // Pass |callback| directly instead of wrapping it with OnReadWriteComplete.
   // This is to avoid setting |was_ever_used_| unless data is actually read.
-  int rv = transport_->socket()->ReadIfReady(buf, buf_len, std::move(callback));
+  int rv = transport_socket_->ReadIfReady(buf, buf_len, std::move(callback));
   if (rv > 0)
     was_ever_used_ = true;
   return rv;
 }
 
 int SOCKSClientSocket::CancelReadIfReady() {
-  return transport_->socket()->CancelReadIfReady();
+  return transport_socket_->CancelReadIfReady();
 }
 
 // Write is called by the transport layer. This can only be done if the
@@ -218,7 +213,7 @@
   DCHECK(user_callback_.is_null());
   DCHECK(!callback.is_null());
 
-  int rv = transport_->socket()->Write(
+  int rv = transport_socket_->Write(
       buf, buf_len,
       base::BindOnce(&SOCKSClientSocket::OnReadWriteComplete,
                      base::Unretained(this), std::move(callback)),
@@ -229,11 +224,11 @@
 }
 
 int SOCKSClientSocket::SetReceiveBufferSize(int32_t size) {
-  return transport_->socket()->SetReceiveBufferSize(size);
+  return transport_socket_->SetReceiveBufferSize(size);
 }
 
 int SOCKSClientSocket::SetSendBufferSize(int32_t size) {
-  return transport_->socket()->SetSendBufferSize(size);
+  return transport_socket_->SetSendBufferSize(size);
 }
 
 void SOCKSClientSocket::DoCallback(int result) {
@@ -368,7 +363,7 @@
   handshake_buf_ = base::MakeRefCounted<IOBuffer>(handshake_buf_len);
   memcpy(handshake_buf_->data(), &buffer_[bytes_sent_],
          handshake_buf_len);
-  return transport_->socket()->Write(
+  return transport_socket_->Write(
       handshake_buf_.get(), handshake_buf_len,
       base::Bind(&SOCKSClientSocket::OnIOComplete, base::Unretained(this)),
       traffic_annotation_);
@@ -403,9 +398,8 @@
 
   int handshake_buf_len = kReadHeaderSize - bytes_received_;
   handshake_buf_ = base::MakeRefCounted<IOBuffer>(handshake_buf_len);
-  return transport_->socket()->Read(
-      handshake_buf_.get(),
-      handshake_buf_len,
+  return transport_socket_->Read(
+      handshake_buf_.get(), handshake_buf_len,
       base::Bind(&SOCKSClientSocket::OnIOComplete, base::Unretained(this)));
 }
 
@@ -461,11 +455,11 @@
 }
 
 int SOCKSClientSocket::GetPeerAddress(IPEndPoint* address) const {
-  return transport_->socket()->GetPeerAddress(address);
+  return transport_socket_->GetPeerAddress(address);
 }
 
 int SOCKSClientSocket::GetLocalAddress(IPEndPoint* address) const {
-  return transport_->socket()->GetLocalAddress(address);
+  return transport_socket_->GetLocalAddress(address);
 }
 
 }  // namespace net
diff --git a/net/socket/socks_client_socket.h b/net/socket/socks_client_socket.h
index 8d3f8ff8f..74f1548 100644
--- a/net/socket/socks_client_socket.h
+++ b/net/socket/socks_client_socket.h
@@ -25,14 +25,12 @@
 
 namespace net {
 
-class ClientSocketHandle;
-
 // The SOCKS client socket implementation
 class NET_EXPORT_PRIVATE SOCKSClientSocket : public StreamSocket {
  public:
   // |req_info| contains the hostname and port to which the socket above will
   // communicate to via the socks layer. For testing the referrer is optional.
-  SOCKSClientSocket(std::unique_ptr<ClientSocketHandle> transport_socket,
+  SOCKSClientSocket(std::unique_ptr<StreamSocket> transport_socket,
                     const HostResolver::RequestInfo& req_info,
                     RequestPriority priority,
                     HostResolver* host_resolver,
@@ -108,7 +106,7 @@
   const std::string BuildHandshakeWriteBuffer() const;
 
   // Stores the underlying socket.
-  std::unique_ptr<ClientSocketHandle> transport_;
+  std::unique_ptr<StreamSocket> transport_socket_;
 
   State next_state_;
 
diff --git a/net/socket/socks_client_socket_fuzzer.cc b/net/socket/socks_client_socket_fuzzer.cc
index cd44a023..4a5ce22c 100644
--- a/net/socket/socks_client_socket_fuzzer.cc
+++ b/net/socket/socks_client_socket_fuzzer.cc
@@ -15,7 +15,6 @@
 #include "net/dns/host_resolver.h"
 #include "net/dns/mock_host_resolver.h"
 #include "net/log/test_net_log.h"
-#include "net/socket/client_socket_handle.h"
 #include "net/socket/fuzzed_socket.h"
 #include "net/socket/socks_client_socket.h"
 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -54,13 +53,9 @@
       new net::FuzzedSocket(&data_provider, &test_net_log));
   CHECK_EQ(net::OK, fuzzed_socket->Connect(callback.callback()));
 
-  std::unique_ptr<net::ClientSocketHandle> socket_handle(
-      new net::ClientSocketHandle());
-  socket_handle->SetSocket(std::move(fuzzed_socket));
-
   net::HostResolver::RequestInfo request_info(net::HostPortPair("foo", 80));
 
-  net::SOCKSClientSocket socket(std::move(socket_handle), request_info,
+  net::SOCKSClientSocket socket(std::move(fuzzed_socket), request_info,
                                 net::DEFAULT_PRIORITY, &mock_host_resolver,
                                 TRAFFIC_ANNOTATION_FOR_TESTS);
   int result = socket.Connect(callback.callback());
diff --git a/net/socket/socks_client_socket_pool.cc b/net/socket/socks_client_socket_pool.cc
deleted file mode 100644
index 63de317..0000000
--- a/net/socket/socks_client_socket_pool.cc
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/socket/socks_client_socket_pool.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/values.h"
-#include "net/base/net_errors.h"
-#include "net/log/net_log_source_type.h"
-#include "net/log/net_log_with_source.h"
-#include "net/socket/client_socket_factory.h"
-#include "net/socket/client_socket_handle.h"
-#include "net/socket/transport_client_socket_pool.h"
-
-namespace net {
-
-std::unique_ptr<ConnectJob>
-SOCKSClientSocketPool::SOCKSConnectJobFactory::NewConnectJob(
-    const std::string& group_name,
-    const PoolBase::Request& request,
-    ConnectJob::Delegate* delegate) const {
-  return std::make_unique<SOCKSConnectJob>(
-      group_name, request.priority(), request.socket_tag(),
-      request.respect_limits() == ClientSocketPool::RespectLimits::ENABLED,
-      request.params(), transport_pool_, host_resolver_, delegate, net_log_);
-}
-
-SOCKSClientSocketPool::SOCKSClientSocketPool(
-    int max_sockets,
-    int max_sockets_per_group,
-    HostResolver* host_resolver,
-    TransportClientSocketPool* transport_pool,
-    SocketPerformanceWatcherFactory*,
-    NetLog* net_log)
-    : transport_pool_(transport_pool),
-      base_(
-          this,
-          max_sockets,
-          max_sockets_per_group,
-          ClientSocketPool::unused_idle_socket_timeout(),
-          ClientSocketPool::used_idle_socket_timeout(),
-          new SOCKSConnectJobFactory(transport_pool, host_resolver, net_log)) {
-  // We should always have a |transport_pool_| except in unit tests.
-  if (transport_pool_)
-    base_.AddLowerLayeredPool(transport_pool_);
-}
-
-SOCKSClientSocketPool::~SOCKSClientSocketPool() = default;
-
-int SOCKSClientSocketPool::RequestSocket(const std::string& group_name,
-                                         const void* socket_params,
-                                         RequestPriority priority,
-                                         const SocketTag& socket_tag,
-                                         RespectLimits respect_limits,
-                                         ClientSocketHandle* handle,
-                                         CompletionOnceCallback callback,
-                                         const NetLogWithSource& net_log) {
-  const scoped_refptr<SOCKSSocketParams>* casted_socket_params =
-      static_cast<const scoped_refptr<SOCKSSocketParams>*>(socket_params);
-
-  return base_.RequestSocket(group_name, *casted_socket_params, priority,
-                             socket_tag, respect_limits, handle,
-                             std::move(callback), net_log);
-}
-
-void SOCKSClientSocketPool::RequestSockets(const std::string& group_name,
-                                           const void* params,
-                                           int num_sockets,
-                                           const NetLogWithSource& net_log) {
-  const scoped_refptr<SOCKSSocketParams>* casted_params =
-      static_cast<const scoped_refptr<SOCKSSocketParams>*>(params);
-
-  base_.RequestSockets(group_name, *casted_params, num_sockets, net_log);
-}
-
-void SOCKSClientSocketPool::SetPriority(const std::string& group_name,
-                                        ClientSocketHandle* handle,
-                                        RequestPriority priority) {
-  base_.SetPriority(group_name, handle, priority);
-}
-
-void SOCKSClientSocketPool::CancelRequest(const std::string& group_name,
-                                          ClientSocketHandle* handle) {
-  base_.CancelRequest(group_name, handle);
-}
-
-void SOCKSClientSocketPool::ReleaseSocket(const std::string& group_name,
-                                          std::unique_ptr<StreamSocket> socket,
-                                          int id) {
-  base_.ReleaseSocket(group_name, std::move(socket), id);
-}
-
-void SOCKSClientSocketPool::FlushWithError(int error) {
-  base_.FlushWithError(error);
-}
-
-void SOCKSClientSocketPool::CloseIdleSockets() {
-  base_.CloseIdleSockets();
-}
-
-void SOCKSClientSocketPool::CloseIdleSocketsInGroup(
-    const std::string& group_name) {
-  base_.CloseIdleSocketsInGroup(group_name);
-}
-
-int SOCKSClientSocketPool::IdleSocketCount() const {
-  return base_.idle_socket_count();
-}
-
-int SOCKSClientSocketPool::IdleSocketCountInGroup(
-    const std::string& group_name) const {
-  return base_.IdleSocketCountInGroup(group_name);
-}
-
-LoadState SOCKSClientSocketPool::GetLoadState(
-    const std::string& group_name, const ClientSocketHandle* handle) const {
-  return base_.GetLoadState(group_name, handle);
-}
-
-std::unique_ptr<base::DictionaryValue> SOCKSClientSocketPool::GetInfoAsValue(
-    const std::string& name,
-    const std::string& type,
-    bool include_nested_pools) const {
-  std::unique_ptr<base::DictionaryValue> dict(base_.GetInfoAsValue(name, type));
-  if (include_nested_pools) {
-    std::unique_ptr<base::ListValue> list(new base::ListValue());
-    list->Append(transport_pool_->GetInfoAsValue("transport_socket_pool",
-                                                 "transport_socket_pool",
-                                                 false));
-    dict->Set("nested_pools", std::move(list));
-  }
-  return dict;
-}
-
-bool SOCKSClientSocketPool::IsStalled() const {
-  return base_.IsStalled();
-}
-
-void SOCKSClientSocketPool::AddHigherLayeredPool(
-    HigherLayeredPool* higher_pool) {
-  base_.AddHigherLayeredPool(higher_pool);
-}
-
-void SOCKSClientSocketPool::RemoveHigherLayeredPool(
-    HigherLayeredPool* higher_pool) {
-  base_.RemoveHigherLayeredPool(higher_pool);
-}
-
-bool SOCKSClientSocketPool::CloseOneIdleConnection() {
-  if (base_.CloseOneIdleSocket())
-    return true;
-  return base_.CloseOneIdleConnectionInHigherLayeredPool();
-}
-
-}  // namespace net
diff --git a/net/socket/socks_client_socket_pool.h b/net/socket/socks_client_socket_pool.h
deleted file mode 100644
index 4816b8b5..0000000
--- a/net/socket/socks_client_socket_pool.h
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_SOCKET_SOCKS_CLIENT_SOCKET_POOL_H_
-#define NET_SOCKET_SOCKS_CLIENT_SOCKET_POOL_H_
-
-#include <memory>
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "net/base/completion_once_callback.h"
-#include "net/base/host_port_pair.h"
-#include "net/base/net_export.h"
-#include "net/dns/host_resolver.h"
-#include "net/socket/client_socket_pool.h"
-#include "net/socket/client_socket_pool_base.h"
-#include "net/socket/socks_connect_job.h"
-#include "net/traffic_annotation/network_traffic_annotation.h"
-
-namespace net {
-
-class ConnectJobFactory;
-class NetLog;
-class SocketPerformanceWatcherFactory;
-class TransportClientSocketPool;
-
-class NET_EXPORT_PRIVATE SOCKSClientSocketPool
-    : public ClientSocketPool, public HigherLayeredPool {
- public:
-  typedef SOCKSSocketParams SocketParams;
-
-  SOCKSClientSocketPool(int max_sockets,
-                        int max_sockets_per_group,
-                        HostResolver* host_resolver,
-                        TransportClientSocketPool* transport_pool,
-                        SocketPerformanceWatcherFactory*,
-                        NetLog* net_log);
-
-  ~SOCKSClientSocketPool() override;
-
-  // ClientSocketPool implementation.
-  int RequestSocket(const std::string& group_name,
-                    const void* connect_params,
-                    RequestPriority priority,
-                    const SocketTag& socket_tag,
-                    RespectLimits respect_limits,
-                    ClientSocketHandle* handle,
-                    CompletionOnceCallback callback,
-                    const NetLogWithSource& net_log) override;
-
-  void RequestSockets(const std::string& group_name,
-                      const void* params,
-                      int num_sockets,
-                      const NetLogWithSource& net_log) override;
-
-  void SetPriority(const std::string& group_name,
-                   ClientSocketHandle* handle,
-                   RequestPriority priority) override;
-
-  void CancelRequest(const std::string& group_name,
-                     ClientSocketHandle* handle) override;
-
-  void ReleaseSocket(const std::string& group_name,
-                     std::unique_ptr<StreamSocket> socket,
-                     int id) override;
-
-  void FlushWithError(int error) override;
-
-  void CloseIdleSockets() override;
-
-  void CloseIdleSocketsInGroup(const std::string& group_name) override;
-
-  int IdleSocketCount() const override;
-
-  int IdleSocketCountInGroup(const std::string& group_name) const override;
-
-  LoadState GetLoadState(const std::string& group_name,
-                         const ClientSocketHandle* handle) const override;
-
-  std::unique_ptr<base::DictionaryValue> GetInfoAsValue(
-      const std::string& name,
-      const std::string& type,
-      bool include_nested_pools) const override;
-
-  // LowerLayeredPool implementation.
-  bool IsStalled() const override;
-
-  void AddHigherLayeredPool(HigherLayeredPool* higher_pool) override;
-
-  void RemoveHigherLayeredPool(HigherLayeredPool* higher_pool) override;
-
-  // HigherLayeredPool implementation.
-  bool CloseOneIdleConnection() override;
-
- private:
-  typedef ClientSocketPoolBase<SOCKSSocketParams> PoolBase;
-
-  class SOCKSConnectJobFactory : public PoolBase::ConnectJobFactory {
-   public:
-    SOCKSConnectJobFactory(TransportClientSocketPool* transport_pool,
-                           HostResolver* host_resolver,
-                           NetLog* net_log)
-        : transport_pool_(transport_pool),
-          host_resolver_(host_resolver),
-          net_log_(net_log) {}
-
-    ~SOCKSConnectJobFactory() override {}
-
-    // ClientSocketPoolBase::ConnectJobFactory methods.
-    std::unique_ptr<ConnectJob> NewConnectJob(
-        const std::string& group_name,
-        const PoolBase::Request& request,
-        ConnectJob::Delegate* delegate) const override;
-
-   private:
-    TransportClientSocketPool* const transport_pool_;
-    HostResolver* const host_resolver_;
-    NetLog* net_log_;
-
-    DISALLOW_COPY_AND_ASSIGN(SOCKSConnectJobFactory);
-  };
-
-  TransportClientSocketPool* const transport_pool_;
-  PoolBase base_;
-
-  DISALLOW_COPY_AND_ASSIGN(SOCKSClientSocketPool);
-};
-
-}  // namespace net
-
-#endif  // NET_SOCKET_SOCKS_CLIENT_SOCKET_POOL_H_
diff --git a/net/socket/socks_client_socket_pool_unittest.cc b/net/socket/socks_client_socket_pool_unittest.cc
index 8a921e7..76cf2a8b 100644
--- a/net/socket/socks_client_socket_pool_unittest.cc
+++ b/net/socket/socks_client_socket_pool_unittest.cc
@@ -129,75 +129,6 @@
   EXPECT_TRUE(handle.socket());
 }
 
-TEST_F(SOCKSClientSocketPoolTest, CancelDuringTransportConnect) {
-  SOCKS5MockData data(SYNCHRONOUS);
-  transport_client_socket_factory_.AddSocketDataProvider(data.data_provider());
-  // We need two connections because the pool base lets one cancelled
-  // connect job proceed for potential future use.
-  SOCKS5MockData data2(SYNCHRONOUS);
-  transport_client_socket_factory_.AddSocketDataProvider(data2.data_provider());
-
-  EXPECT_EQ(0, transport_socket_pool_.cancel_count());
-  int rv = StartRequestV5("a", LOW);
-  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
-
-  rv = StartRequestV5("a", LOW);
-  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
-
-  pool_.CancelRequest("a", (*requests())[0]->handle());
-  pool_.CancelRequest("a", (*requests())[1]->handle());
-  // Requests in the connect phase don't actually get cancelled.
-  EXPECT_EQ(0, transport_socket_pool_.cancel_count());
-
-  // Now wait for the TCP sockets to connect.
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_EQ(ClientSocketPoolTest::kRequestNotFound, GetOrderOfRequest(1));
-  EXPECT_EQ(ClientSocketPoolTest::kRequestNotFound, GetOrderOfRequest(2));
-  EXPECT_EQ(0, transport_socket_pool_.cancel_count());
-  EXPECT_EQ(2, pool_.IdleSocketCount());
-
-  (*requests())[0]->handle()->Reset();
-  (*requests())[1]->handle()->Reset();
-}
-
-TEST_F(SOCKSClientSocketPoolTest, CancelDuringSOCKSConnect) {
-  SOCKS5MockData data(ASYNC);
-  data.data_provider()->set_connect_data(MockConnect(SYNCHRONOUS, OK));
-  transport_client_socket_factory_.AddSocketDataProvider(data.data_provider());
-  // We need two connections because the pool base lets one cancelled
-  // connect job proceed for potential future use.
-  SOCKS5MockData data2(ASYNC);
-  data2.data_provider()->set_connect_data(MockConnect(SYNCHRONOUS, OK));
-  transport_client_socket_factory_.AddSocketDataProvider(data2.data_provider());
-
-  EXPECT_EQ(0, transport_socket_pool_.cancel_count());
-  EXPECT_EQ(0, transport_socket_pool_.release_count());
-  int rv = StartRequestV5("a", LOW);
-  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
-
-  rv = StartRequestV5("a", LOW);
-  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
-
-  pool_.CancelRequest("a", (*requests())[0]->handle());
-  pool_.CancelRequest("a", (*requests())[1]->handle());
-  EXPECT_EQ(0, transport_socket_pool_.cancel_count());
-  // Requests in the connect phase don't actually get cancelled.
-  EXPECT_EQ(0, transport_socket_pool_.release_count());
-
-  // Now wait for the async data to reach the SOCKS connect jobs.
-  base::RunLoop().RunUntilIdle();
-
-  EXPECT_EQ(ClientSocketPoolTest::kRequestNotFound, GetOrderOfRequest(1));
-  EXPECT_EQ(ClientSocketPoolTest::kRequestNotFound, GetOrderOfRequest(2));
-  EXPECT_EQ(0, transport_socket_pool_.cancel_count());
-  EXPECT_EQ(0, transport_socket_pool_.release_count());
-  EXPECT_EQ(2, pool_.IdleSocketCount());
-
-  (*requests())[0]->handle()->Reset();
-  (*requests())[1]->handle()->Reset();
-}
-
 // Test that SocketTag passed into SOCKSClientSocketPool is applied to returned
 // sockets.
 #if defined(OS_ANDROID)
diff --git a/net/socket/socks_client_socket_unittest.cc b/net/socket/socks_client_socket_unittest.cc
index b4fc565..346ee80 100644
--- a/net/socket/socks_client_socket_unittest.cc
+++ b/net/socket/socks_client_socket_unittest.cc
@@ -92,13 +92,11 @@
   EXPECT_THAT(rv, IsOk());
   EXPECT_TRUE(socket->IsConnected());
 
-  auto connection = std::make_unique<ClientSocketHandle>();
-  // |connection| takes ownership of |socket|, but |tcp_socket_| keeps a
+  // The SOCKSClientSocket takes ownership of |socket|, but |tcp_sock_| keeps a
   // non-owning pointer to it.
   tcp_sock_ = socket.get();
-  connection->SetSocket(std::move(socket));
   return std::make_unique<SOCKSClientSocket>(
-      std::move(connection),
+      std::move(socket),
       HostResolver::RequestInfo(HostPortPair(hostname, port)), DEFAULT_PRIORITY,
       host_resolver, TRAFFIC_ANNOTATION_FOR_TESTS);
 }
@@ -528,10 +526,9 @@
   std::unique_ptr<ClientSocketHandle> connection(new ClientSocketHandle);
   // |connection| takes ownership of |tagging_sock|, but keep a
   // non-owning pointer to it.
-  connection->SetSocket(std::unique_ptr<StreamSocket>(tagging_sock));
   MockHostResolver host_resolver;
   SOCKSClientSocket socket(
-      std::move(connection),
+      std::unique_ptr<StreamSocket>(tagging_sock),
       HostResolver::RequestInfo(HostPortPair("localhost", 80)),
       DEFAULT_PRIORITY, &host_resolver, TRAFFIC_ANNOTATION_FOR_TESTS);
 
diff --git a/net/socket/socks_connect_job.cc b/net/socket/socks_connect_job.cc
index 169eacc..f5c193d5 100644
--- a/net/socket/socks_connect_job.cc
+++ b/net/socket/socks_connect_job.cc
@@ -13,7 +13,6 @@
 #include "net/socket/client_socket_handle.h"
 #include "net/socket/socks5_client_socket.h"
 #include "net/socket/socks_client_socket.h"
-#include "net/socket/transport_client_socket_pool.h"
 #include "net/socket/transport_connect_job.h"
 
 namespace net {
@@ -35,39 +34,26 @@
 SOCKSSocketParams::~SOCKSSocketParams() = default;
 
 SOCKSConnectJob::SOCKSConnectJob(
-    const std::string& group_name,
     RequestPriority priority,
-    const SocketTag& socket_tag,
-    bool respect_limits,
+    const CommonConnectJobParams& common_connect_job_params,
     const scoped_refptr<SOCKSSocketParams>& socks_params,
-    TransportClientSocketPool* transport_pool,
-    HostResolver* host_resolver,
-    Delegate* delegate,
-    NetLog* net_log)
-    : ConnectJob(
-          group_name,
-          ConnectionTimeout(),
-          priority,
-          socket_tag,
-          respect_limits,
-          delegate,
-          NetLogWithSource::Make(net_log, NetLogSourceType::SOCKS_CONNECT_JOB)),
-      socks_params_(socks_params),
-      transport_pool_(transport_pool),
-      resolver_(host_resolver) {}
+    ConnectJob::Delegate* delegate)
+    : ConnectJob(priority,
+                 ConnectionTimeout(),
+                 common_connect_job_params,
+                 delegate,
+                 NetLogWithSource::Make(common_connect_job_params.net_log,
+                                        NetLogSourceType::SOCKS_CONNECT_JOB)),
+      socks_params_(socks_params) {}
 
-SOCKSConnectJob::~SOCKSConnectJob() {
-  // We don't worry about cancelling the tcp socket since the destructor in
-  // std::unique_ptr<ClientSocketHandle> transport_socket_handle_ will take care
-  // of
-  // it.
-}
+SOCKSConnectJob::~SOCKSConnectJob() {}
 
 LoadState SOCKSConnectJob::GetLoadState() const {
   switch (next_state_) {
     case STATE_TRANSPORT_CONNECT:
+      return LOAD_STATE_IDLE;
     case STATE_TRANSPORT_CONNECT_COMPLETE:
-      return transport_socket_handle_->GetLoadState();
+      return transport_connect_job_->GetLoadState();
     case STATE_SOCKS_CONNECT:
     case STATE_SOCKS_CONNECT_COMPLETE:
       return LOAD_STATE_CONNECTING;
@@ -88,6 +74,12 @@
     NotifyDelegateOfCompletion(rv);  // Deletes |this|
 }
 
+void SOCKSConnectJob::OnConnectJobComplete(int result, ConnectJob* job) {
+  DCHECK(transport_connect_job_);
+  DCHECK_EQ(next_state_, STATE_TRANSPORT_CONNECT_COMPLETE);
+  OnIOComplete(result);
+}
+
 int SOCKSConnectJob::DoLoop(int result) {
   DCHECK_NE(next_state_, STATE_NONE);
 
@@ -121,16 +113,13 @@
 }
 
 int SOCKSConnectJob::DoTransportConnect() {
+  DCHECK(!transport_connect_job_);
+
   next_state_ = STATE_TRANSPORT_CONNECT_COMPLETE;
-  transport_socket_handle_.reset(new ClientSocketHandle());
-  CompletionOnceCallback callback =
-      base::BindOnce(&SOCKSConnectJob::OnIOComplete, base::Unretained(this));
-  return transport_socket_handle_->Init(
-      group_name(),
-      TransportClientSocketPool::SocketParams::CreateFromTransportSocketParams(
-          socks_params_->transport_params()),
-      priority(), socket_tag(), respect_limits(), std::move(callback),
-      transport_pool_, net_log());
+  transport_connect_job_ = TransportConnectJob::CreateTransportConnectJob(
+      socks_params_->transport_params(), priority(),
+      common_connect_job_params(), this);
+  return transport_connect_job_->Connect();
 }
 
 int SOCKSConnectJob::DoTransportConnectComplete(int result) {
@@ -150,14 +139,15 @@
 
   // Add a SOCKS connection on top of the tcp socket.
   if (socks_params_->is_socks_v5()) {
-    socket_.reset(new SOCKS5ClientSocket(std::move(transport_socket_handle_),
+    socket_.reset(new SOCKS5ClientSocket(transport_connect_job_->PassSocket(),
                                          socks_params_->destination(),
                                          socks_params_->traffic_annotation()));
   } else {
     socket_.reset(new SOCKSClientSocket(
-        std::move(transport_socket_handle_), socks_params_->destination(),
-        priority(), resolver_, socks_params_->traffic_annotation()));
+        transport_connect_job_->PassSocket(), socks_params_->destination(),
+        priority(), host_resolver(), socks_params_->traffic_annotation()));
   }
+  transport_connect_job_.reset();
   return socket_->Connect(
       base::BindOnce(&SOCKSConnectJob::OnIOComplete, base::Unretained(this)));
 }
@@ -179,8 +169,8 @@
 
 void SOCKSConnectJob::ChangePriorityInternal(RequestPriority priority) {
   // Currently doesn't change host resolution request priority for SOCKS4 case.
-  if (transport_socket_handle_)
-    transport_socket_handle_->SetPriority(priority);
+  if (transport_connect_job_)
+    transport_connect_job_->ChangePriority(priority);
 }
 
 }  // namespace net
diff --git a/net/socket/socks_connect_job.h b/net/socket/socks_connect_job.h
index 70d2263..b202d34 100644
--- a/net/socket/socks_connect_job.h
+++ b/net/socket/socks_connect_job.h
@@ -20,11 +20,8 @@
 
 namespace net {
 
-class ClientSocketHandle;
 class HostPortPair;
-class NetLog;
 class StreamSocket;
-class TransportClientSocketPool;
 class TransportSocketParams;
 
 class NET_EXPORT_PRIVATE SOCKSSocketParams
@@ -60,19 +57,15 @@
   DISALLOW_COPY_AND_ASSIGN(SOCKSSocketParams);
 };
 
-// SOCKSConnectJob handles the handshake to a socks server after setting up
-// an underlying transport socket.
-class NET_EXPORT_PRIVATE SOCKSConnectJob : public ConnectJob {
+// SOCKSConnectJob handles establishing a connection to a SOCKS4 or SOCKS5 proxy
+// and then sending a handshake to establish a tunnel.
+class NET_EXPORT_PRIVATE SOCKSConnectJob : public ConnectJob,
+                                           public ConnectJob::Delegate {
  public:
-  SOCKSConnectJob(const std::string& group_name,
-                  RequestPriority priority,
-                  const SocketTag& socket_tag,
-                  bool respect_limits,
-                  const scoped_refptr<SOCKSSocketParams>& params,
-                  TransportClientSocketPool* transport_pool,
-                  HostResolver* host_resolver,
-                  Delegate* delegate,
-                  NetLog* net_log);
+  SOCKSConnectJob(RequestPriority priority,
+                  const CommonConnectJobParams& common_connect_job_params,
+                  const scoped_refptr<SOCKSSocketParams>& socks_params,
+                  ConnectJob::Delegate* delegate);
   ~SOCKSConnectJob() override;
 
   // ConnectJob methods.
@@ -92,6 +85,9 @@
 
   void OnIOComplete(int result);
 
+  // ConnectJob::Delegate methods.
+  void OnConnectJobComplete(int result, ConnectJob* job) override;
+
   // Runs the state transition loop.
   int DoLoop(int result);
 
@@ -108,11 +104,9 @@
   void ChangePriorityInternal(RequestPriority priority) override;
 
   scoped_refptr<SOCKSSocketParams> socks_params_;
-  TransportClientSocketPool* const transport_pool_;
-  HostResolver* const resolver_;
 
   State next_state_;
-  std::unique_ptr<ClientSocketHandle> transport_socket_handle_;
+  std::unique_ptr<ConnectJob> transport_connect_job_;
   std::unique_ptr<StreamSocket> socket_;
 
   DISALLOW_COPY_AND_ASSIGN(SOCKSConnectJob);
diff --git a/net/socket/socks_connect_job_unittest.cc b/net/socket/socks_connect_job_unittest.cc
index 713fc55..8ac0d79 100644
--- a/net/socket/socks_connect_job_unittest.cc
+++ b/net/socket/socks_connect_job_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "net/socket/socks_client_socket_pool.h"
+#include "net/socket/socks_connect_job.h"
 
 #include "base/callback.h"
 #include "base/containers/span.h"
@@ -21,7 +21,6 @@
 #include "net/socket/socket_tag.h"
 #include "net/socket/socket_test_util.h"
 #include "net/socket/socks_connect_job.h"
-#include "net/socket/transport_client_socket_pool.h"
 #include "net/socket/transport_connect_job.h"
 #include "net/test/gtest_util.h"
 #include "net/test/test_with_scoped_task_environment.h"
@@ -49,13 +48,7 @@
       : WithScopedTaskEnvironment(
             base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
             base::test::ScopedTaskEnvironment::NowSource::
-                MAIN_THREAD_MOCK_TIME),
-        transport_pool_(2 /* max_sockets */,
-                        2 /* max_sockets_per_group */,
-                        &host_resolver_,
-                        &client_socket_factory_,
-                        nullptr /* socket_performance_watcher_factory */,
-                        &net_log_) {
+                MAIN_THREAD_MOCK_TIME) {
     // Set an initial delay to ensure that the first call to TimeTicks::Now()
     // before incrementing the counter does not return a null value.
     FastForwardBy(base::TimeDelta::FromSeconds(1));
@@ -76,11 +69,19 @@
         TRAFFIC_ANNOTATION_FOR_TESTS);
   }
 
+  CommonConnectJobParams CreateCommonParams() {
+    // Group name doesn't matter.
+    return CommonConnectJobParams(
+        "group_name", SocketTag(), true /* respect_limits */,
+        &client_socket_factory_,
+        nullptr /* socket_performance_watcher_factory */, &host_resolver_,
+        &net_log_, nullptr /* websocket_endpoint_lock_manager */);
+  }
+
  protected:
   NetLog net_log_;
   MockHostResolver host_resolver_;
   MockTaggingClientSocketFactory client_socket_factory_;
-  TransportClientSocketPool transport_pool_;
 };
 
 TEST_F(SOCKSConnectJobTest, HostResolutionFailure) {
@@ -89,10 +90,9 @@
   for (bool failure_synchronous : {false, true}) {
     host_resolver_.set_synchronous_mode(failure_synchronous);
     TestConnectJobDelegate test_delegate;
-    SOCKSConnectJob socks_connect_job(
-        kSOCKS5TestHost /* group_name */, DEFAULT_PRIORITY, SocketTag(),
-        true /* respect_limits */, CreateSOCKSParams(SOCKSVersion::V5),
-        &transport_pool_, &host_resolver_, &test_delegate, &net_log_);
+    SOCKSConnectJob socks_connect_job(DEFAULT_PRIORITY, CreateCommonParams(),
+                                      CreateSOCKSParams(SOCKSVersion::V5),
+                                      &test_delegate);
     test_delegate.StartJobExpectingResult(
         &socks_connect_job, ERR_PROXY_CONNECTION_FAILED, failure_synchronous);
   }
@@ -118,10 +118,9 @@
       client_socket_factory_.AddSocketDataProvider(&sequenced_socket_data);
 
       TestConnectJobDelegate test_delegate;
-      SOCKSConnectJob socks_connect_job(
-          kSOCKS5TestHost /* group_name */, DEFAULT_PRIORITY, SocketTag(),
-          true /* respect_limits */, CreateSOCKSParams(SOCKSVersion::V5),
-          &transport_pool_, &host_resolver_, &test_delegate, &net_log_);
+      SOCKSConnectJob socks_connect_job(DEFAULT_PRIORITY, CreateCommonParams(),
+                                        CreateSOCKSParams(SOCKSVersion::V5),
+                                        &test_delegate);
       test_delegate.StartJobExpectingResult(
           &socks_connect_job, ERR_UNEXPECTED,
           host_resolution_synchronous && write_failure_synchronous);
@@ -152,10 +151,9 @@
       client_socket_factory_.AddSocketDataProvider(&sequenced_socket_data);
 
       TestConnectJobDelegate test_delegate;
-      SOCKSConnectJob socks_connect_job(
-          kSOCKS5TestHost /* group_name */, DEFAULT_PRIORITY, SocketTag(),
-          true /* respect_limits */, CreateSOCKSParams(SOCKSVersion::V4),
-          &transport_pool_, &host_resolver_, &test_delegate, &net_log_);
+      SOCKSConnectJob socks_connect_job(DEFAULT_PRIORITY, CreateCommonParams(),
+                                        CreateSOCKSParams(SOCKSVersion::V4),
+                                        &test_delegate);
       test_delegate.StartJobExpectingResult(
           &socks_connect_job, OK,
           host_resolution_synchronous && read_and_writes_synchronous);
@@ -189,10 +187,9 @@
       client_socket_factory_.AddSocketDataProvider(&sequenced_socket_data);
 
       TestConnectJobDelegate test_delegate;
-      SOCKSConnectJob socks_connect_job(
-          kSOCKS5TestHost /* group_name */, DEFAULT_PRIORITY, SocketTag(),
-          true /* respect_limits */, CreateSOCKSParams(SOCKSVersion::V5),
-          &transport_pool_, &host_resolver_, &test_delegate, &net_log_);
+      SOCKSConnectJob socks_connect_job(DEFAULT_PRIORITY, CreateCommonParams(),
+                                        CreateSOCKSParams(SOCKSVersion::V5),
+                                        &test_delegate);
       test_delegate.StartJobExpectingResult(
           &socks_connect_job, OK,
           host_resolution_synchronous && read_and_writes_synchronous);
@@ -207,10 +204,9 @@
   host_resolver_.set_ondemand_mode(true);
 
   TestConnectJobDelegate test_delegate;
-  SOCKSConnectJob socks_connect_job(
-      kSOCKS5TestHost /* group_name */, DEFAULT_PRIORITY, SocketTag(),
-      true /* respect_limits */, CreateSOCKSParams(SOCKSVersion::V5),
-      &transport_pool_, &host_resolver_, &test_delegate, &net_log_);
+  SOCKSConnectJob socks_connect_job(DEFAULT_PRIORITY, CreateCommonParams(),
+                                    CreateSOCKSParams(SOCKSVersion::V5),
+                                    &test_delegate);
   socks_connect_job.Connect();
 
   // Just before the TransportConnectJob's timeout, nothing should have
@@ -222,7 +218,6 @@
   // Wait for exactly the TransportConnectJob's timeout to have passed. The Job
   // should time out.
   FastForwardBy(kTinyTime);
-  EXPECT_FALSE(host_resolver_.has_pending_requests());
   EXPECT_TRUE(test_delegate.has_result());
   EXPECT_THAT(test_delegate.WaitForResult(),
               test::IsError(ERR_PROXY_CONNECTION_FAILED));
@@ -246,10 +241,9 @@
   client_socket_factory_.AddSocketDataProvider(&sequenced_socket_data);
 
   TestConnectJobDelegate test_delegate;
-  SOCKSConnectJob socks_connect_job(
-      kSOCKS5TestHost /* group_name */, DEFAULT_PRIORITY, SocketTag(),
-      true /* respect_limits */, CreateSOCKSParams(SOCKSVersion::V5),
-      &transport_pool_, &host_resolver_, &test_delegate, &net_log_);
+  SOCKSConnectJob socks_connect_job(DEFAULT_PRIORITY, CreateCommonParams(),
+                                    CreateSOCKSParams(SOCKSVersion::V5),
+                                    &test_delegate);
   socks_connect_job.Connect();
 
   // Just before the TransportConnectJob's timeout, nothing should have
@@ -283,9 +277,6 @@
 // modified.
 TEST_F(SOCKSConnectJobTest, Priority) {
   host_resolver_.set_ondemand_mode(true);
-  // Make resolution eventually fail, so old jobs can easily be removed from the
-  // socket pool.
-  host_resolver_.rules()->AddSimulatedFailure(kProxyHostName);
   for (int initial_priority = MINIMUM_PRIORITY;
        initial_priority <= MAXIMUM_PRIORITY; ++initial_priority) {
     for (int new_priority = MINIMUM_PRIORITY; new_priority <= MAXIMUM_PRIORITY;
@@ -295,10 +286,8 @@
         continue;
       TestConnectJobDelegate test_delegate;
       SOCKSConnectJob socks_connect_job(
-          kSOCKS5TestHost /* group_name */,
-          static_cast<RequestPriority>(initial_priority), SocketTag(),
-          true /* respect_limits */, CreateSOCKSParams(SOCKSVersion::V4),
-          &transport_pool_, &host_resolver_, &test_delegate, &net_log_);
+          static_cast<RequestPriority>(initial_priority), CreateCommonParams(),
+          CreateSOCKSParams(SOCKSVersion::V4), &test_delegate);
       ASSERT_THAT(socks_connect_job.Connect(), test::IsError(ERR_IO_PENDING));
       ASSERT_TRUE(host_resolver_.has_pending_requests());
       int request_id = host_resolver_.num_resolve();
@@ -313,12 +302,6 @@
       socks_connect_job.ChangePriority(
           static_cast<RequestPriority>(initial_priority));
       EXPECT_EQ(initial_priority, host_resolver_.request_priority(request_id));
-
-      // Complete the resolution, which should result in emptying the
-      // TransportSocketPool.
-      host_resolver_.ResolveAllPending();
-      ASSERT_THAT(test_delegate.WaitForResult(),
-                  test::IsError(ERR_PROXY_CONNECTION_FAILED));
     }
   }
 }
@@ -347,10 +330,9 @@
   client_socket_factory_.AddSocketDataProvider(&sequenced_socket_data);
 
   TestConnectJobDelegate test_delegate;
-  SOCKSConnectJob socks_connect_job(
-      kSOCKS5TestHost /* group_name */, DEFAULT_PRIORITY, SocketTag(),
-      true /* respect_limits */, CreateSOCKSParams(SOCKSVersion::V5),
-      &transport_pool_, &host_resolver_, &test_delegate, &net_log_);
+  SOCKSConnectJob socks_connect_job(DEFAULT_PRIORITY, CreateCommonParams(),
+                                    CreateSOCKSParams(SOCKSVersion::V5),
+                                    &test_delegate);
   base::TimeTicks start = base::TimeTicks::Now();
   socks_connect_job.Connect();
 
@@ -381,5 +363,78 @@
   EXPECT_EQ(base::TimeTicks(), socks_connect_job.connect_timing().ssl_end);
 }
 
+TEST_F(SOCKSConnectJobTest, CancelDuringDnsResolution) {
+  // Set HostResolver to hang.
+  host_resolver_.set_ondemand_mode(true);
+
+  TestConnectJobDelegate test_delegate;
+  std::unique_ptr<SOCKSConnectJob> socks_connect_job =
+      std::make_unique<SOCKSConnectJob>(DEFAULT_PRIORITY, CreateCommonParams(),
+                                        CreateSOCKSParams(SOCKSVersion::V5),
+                                        &test_delegate);
+  socks_connect_job->Connect();
+
+  EXPECT_TRUE(host_resolver_.has_pending_requests());
+
+  socks_connect_job.reset();
+  RunUntilIdle();
+  EXPECT_FALSE(host_resolver_.has_pending_requests());
+  EXPECT_FALSE(test_delegate.has_result());
+}
+
+TEST_F(SOCKSConnectJobTest, CancelDuringConnect) {
+  host_resolver_.set_synchronous_mode(true);
+
+  SequencedSocketData sequenced_socket_data{base::span<MockRead>(),
+                                            base::span<MockWrite>()};
+  sequenced_socket_data.set_connect_data(MockConnect(ASYNC, OK));
+  client_socket_factory_.AddSocketDataProvider(&sequenced_socket_data);
+
+  TestConnectJobDelegate test_delegate;
+  std::unique_ptr<SOCKSConnectJob> socks_connect_job =
+      std::make_unique<SOCKSConnectJob>(DEFAULT_PRIORITY, CreateCommonParams(),
+                                        CreateSOCKSParams(SOCKSVersion::V5),
+                                        &test_delegate);
+  socks_connect_job->Connect();
+  // Host resolution should resolve immediately. The ConnectJob should currently
+  // be trying to connect.
+  EXPECT_FALSE(host_resolver_.has_pending_requests());
+
+  socks_connect_job.reset();
+  RunUntilIdle();
+  EXPECT_FALSE(test_delegate.has_result());
+  // Socket should have been destroyed.
+  EXPECT_FALSE(sequenced_socket_data.socket());
+}
+
+TEST_F(SOCKSConnectJobTest, CancelDuringHandshake) {
+  host_resolver_.set_synchronous_mode(true);
+
+  // Hang at start of handshake.
+  MockWrite writes[] = {
+      MockWrite(SYNCHRONOUS, ERR_IO_PENDING, 0),
+  };
+  SequencedSocketData sequenced_socket_data(base::span<MockRead>(), writes);
+  sequenced_socket_data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
+  client_socket_factory_.AddSocketDataProvider(&sequenced_socket_data);
+
+  TestConnectJobDelegate test_delegate;
+  std::unique_ptr<SOCKSConnectJob> socks_connect_job =
+      std::make_unique<SOCKSConnectJob>(DEFAULT_PRIORITY, CreateCommonParams(),
+                                        CreateSOCKSParams(SOCKSVersion::V5),
+                                        &test_delegate);
+  socks_connect_job->Connect();
+  // Host resolution should resolve immediately. The socket connecting, and the
+  // ConnectJob should currently be trying to send the SOCKS handshake.
+  EXPECT_FALSE(host_resolver_.has_pending_requests());
+
+  socks_connect_job.reset();
+  RunUntilIdle();
+  EXPECT_FALSE(test_delegate.has_result());
+  // Socket should have been destroyed.
+  EXPECT_FALSE(sequenced_socket_data.socket());
+  EXPECT_TRUE(sequenced_socket_data.AllWriteDataConsumed());
+}
+
 }  // namespace
 }  // namespace net
diff --git a/net/socket/ssl_client_socket_pool.cc b/net/socket/ssl_client_socket_pool.cc
index 190b096..7eb19c3 100644
--- a/net/socket/ssl_client_socket_pool.cc
+++ b/net/socket/ssl_client_socket_pool.cc
@@ -24,7 +24,6 @@
 #include "net/log/net_log_with_source.h"
 #include "net/socket/client_socket_factory.h"
 #include "net/socket/client_socket_handle.h"
-#include "net/socket/socks_client_socket_pool.h"
 #include "net/socket/socks_connect_job.h"
 #include "net/socket/ssl_client_socket.h"
 #include "net/socket/transport_client_socket_pool.h"
@@ -102,7 +101,7 @@
                              ClientSocketPool::RespectLimits respect_limits,
                              const scoped_refptr<SSLSocketParams>& params,
                              TransportClientSocketPool* transport_pool,
-                             SOCKSClientSocketPool* socks_pool,
+                             TransportClientSocketPool* socks_pool,
                              HttpProxyClientSocketPool* http_proxy_pool,
                              ClientSocketFactory* client_socket_factory,
                              const SSLClientSocketContext& context,
@@ -280,8 +279,11 @@
   scoped_refptr<SOCKSSocketParams> socks_proxy_params =
       params_->GetSocksProxyConnectionParams();
   return transport_socket_handle_->Init(
-      group_name(), socks_proxy_params, priority(), socket_tag(),
-      respect_limits(), callback_, socks_pool_, net_log());
+      group_name(),
+      TransportClientSocketPool::SocketParams::CreateFromSOCKSSocketParams(
+          socks_proxy_params),
+      priority(), socket_tag(), respect_limits(), callback_, socks_pool_,
+      net_log());
 }
 
 int SSLConnectJob::DoSOCKSConnectComplete(int result) {
@@ -458,7 +460,7 @@
 
 SSLClientSocketPool::SSLConnectJobFactory::SSLConnectJobFactory(
     TransportClientSocketPool* transport_pool,
-    SOCKSClientSocketPool* socks_pool,
+    TransportClientSocketPool* socks_pool,
     HttpProxyClientSocketPool* http_proxy_pool,
     ClientSocketFactory* client_socket_factory,
     const SSLClientSocketContext& context,
@@ -485,7 +487,7 @@
     const std::string& ssl_session_cache_shard,
     ClientSocketFactory* client_socket_factory,
     TransportClientSocketPool* transport_pool,
-    SOCKSClientSocketPool* socks_pool,
+    TransportClientSocketPool* socks_pool,
     HttpProxyClientSocketPool* http_proxy_pool,
     SSLConfigService* ssl_config_service,
     NetworkQualityEstimator* network_quality_estimator,
diff --git a/net/socket/ssl_client_socket_pool.h b/net/socket/ssl_client_socket_pool.h
index df6459f..b65726af 100644
--- a/net/socket/ssl_client_socket_pool.h
+++ b/net/socket/ssl_client_socket_pool.h
@@ -33,7 +33,6 @@
 class HttpProxyClientSocketPool;
 class HttpProxySocketParams;
 class NetworkQualityEstimator;
-class SOCKSClientSocketPool;
 class SOCKSSocketParams;
 class SSLClientSocket;
 class TransportClientSocketPool;
@@ -98,7 +97,7 @@
                 ClientSocketPool::RespectLimits respect_limits,
                 const scoped_refptr<SSLSocketParams>& params,
                 TransportClientSocketPool* transport_pool,
-                SOCKSClientSocketPool* socks_pool,
+                TransportClientSocketPool* socks_pool,
                 HttpProxyClientSocketPool* http_proxy_pool,
                 ClientSocketFactory* client_socket_factory,
                 const SSLClientSocketContext& context,
@@ -158,7 +157,7 @@
 
   scoped_refptr<SSLSocketParams> params_;
   TransportClientSocketPool* const transport_pool_;
-  SOCKSClientSocketPool* const socks_pool_;
+  TransportClientSocketPool* const socks_pool_;
   HttpProxyClientSocketPool* const http_proxy_pool_;
   ClientSocketFactory* const client_socket_factory_;
 
@@ -199,7 +198,7 @@
                       const std::string& ssl_session_cache_shard,
                       ClientSocketFactory* client_socket_factory,
                       TransportClientSocketPool* transport_pool,
-                      SOCKSClientSocketPool* socks_pool,
+                      TransportClientSocketPool* socks_pool,
                       HttpProxyClientSocketPool* http_proxy_pool,
                       SSLConfigService* ssl_config_service,
                       NetworkQualityEstimator* network_quality_estimator,
@@ -278,7 +277,7 @@
   class SSLConnectJobFactory : public PoolBase::ConnectJobFactory {
    public:
     SSLConnectJobFactory(TransportClientSocketPool* transport_pool,
-                         SOCKSClientSocketPool* socks_pool,
+                         TransportClientSocketPool* socks_pool,
                          HttpProxyClientSocketPool* http_proxy_pool,
                          ClientSocketFactory* client_socket_factory,
                          const SSLClientSocketContext& context,
@@ -295,7 +294,7 @@
 
    private:
     TransportClientSocketPool* const transport_pool_;
-    SOCKSClientSocketPool* const socks_pool_;
+    TransportClientSocketPool* const socks_pool_;
     HttpProxyClientSocketPool* const http_proxy_pool_;
     ClientSocketFactory* const client_socket_factory_;
     const SSLClientSocketContext context_;
@@ -306,7 +305,7 @@
   };
 
   TransportClientSocketPool* const transport_pool_;
-  SOCKSClientSocketPool* const socks_pool_;
+  TransportClientSocketPool* const socks_pool_;
   HttpProxyClientSocketPool* const http_proxy_pool_;
   PoolBase base_;
   SSLConfigService* const ssl_config_service_;
diff --git a/net/socket/ssl_client_socket_pool_unittest.cc b/net/socket/ssl_client_socket_pool_unittest.cc
index f930b1a..680dc7c 100644
--- a/net/socket/ssl_client_socket_pool_unittest.cc
+++ b/net/socket/ssl_client_socket_pool_unittest.cc
@@ -119,9 +119,7 @@
                                   true,
                                   HostPortPair("sockshost", 443),
                                   TRAFFIC_ANNOTATION_FOR_TESTS)),
-        socks_socket_pool_(kMaxSockets,
-                           kMaxSocketsPerGroup,
-                           &transport_socket_pool_),
+        socks_socket_pool_(kMaxSockets, kMaxSocketsPerGroup, &socket_factory_),
         http_proxy_socket_params_(
             new HttpProxySocketParams(proxy_transport_socket_params_,
                                       NULL,
@@ -215,7 +213,7 @@
   scoped_refptr<TransportSocketParams> proxy_transport_socket_params_;
 
   scoped_refptr<SOCKSSocketParams> socks_socket_params_;
-  MockSOCKSClientSocketPool socks_socket_pool_;
+  MockTransportClientSocketPool socks_socket_pool_;
 
   scoped_refptr<HttpProxySocketParams> http_proxy_socket_params_;
   HttpProxyClientSocketPool http_proxy_socket_pool_;
@@ -559,8 +557,8 @@
             handle.Init(kGroupName, params, HIGHEST, SocketTag(),
                         ClientSocketPool::RespectLimits::ENABLED,
                         callback.callback(), pool_.get(), NetLogWithSource()));
-  EXPECT_EQ(HIGHEST, transport_socket_pool_.last_request_priority());
-  EXPECT_EQ(HIGHEST, transport_socket_pool_.requests()[0]->priority());
+  EXPECT_EQ(HIGHEST, socks_socket_pool_.last_request_priority());
+  EXPECT_EQ(HIGHEST, socks_socket_pool_.requests()[0]->priority());
 }
 
 // Test that the SSLConnectJob passes priority changes down to the transport
@@ -582,10 +580,10 @@
   EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
   EXPECT_FALSE(handle.is_initialized());
   EXPECT_FALSE(handle.socket());
-  EXPECT_EQ(MEDIUM, transport_socket_pool_.requests()[0]->priority());
+  EXPECT_EQ(MEDIUM, socks_socket_pool_.requests()[0]->priority());
 
   pool_->SetPriority(kGroupName, &handle, LOWEST);
-  EXPECT_EQ(LOWEST, transport_socket_pool_.requests()[0]->priority());
+  EXPECT_EQ(LOWEST, socks_socket_pool_.requests()[0]->priority());
 
   EXPECT_THAT(callback.WaitForResult(), IsOk());
   EXPECT_TRUE(handle.is_initialized());
diff --git a/net/socket/transport_client_socket_pool.cc b/net/socket/transport_client_socket_pool.cc
index d3fd078..9622ea5d 100644
--- a/net/socket/transport_client_socket_pool.cc
+++ b/net/socket/transport_client_socket_pool.cc
@@ -20,11 +20,25 @@
 #include "net/socket/client_socket_handle.h"
 #include "net/socket/client_socket_pool_base.h"
 #include "net/socket/socket_net_log_params.h"
+#include "net/socket/socks_connect_job.h"
 #include "net/socket/transport_connect_job.h"
 #include "net/socket/websocket_transport_connect_job.h"
 
 namespace net {
 
+namespace {
+
+std::unique_ptr<ConnectJob> CreateSOCKSConnectJob(
+    scoped_refptr<SOCKSSocketParams> socks_socket_params,
+    RequestPriority priority,
+    const CommonConnectJobParams& common_connect_job_params,
+    ConnectJob::Delegate* delegate) {
+  return std::make_unique<SOCKSConnectJob>(priority, common_connect_job_params,
+                                           socks_socket_params, delegate);
+}
+
+}  // namespace
+
 TransportClientSocketPool::SocketParams::SocketParams(
     const CreateConnectJobCallback& create_connect_job_callback)
     : create_connect_job_callback_(create_connect_job_callback) {}
@@ -38,6 +52,14 @@
   return base::MakeRefCounted<SocketParams>(callback);
 }
 
+scoped_refptr<TransportClientSocketPool::SocketParams>
+TransportClientSocketPool::SocketParams::CreateFromSOCKSSocketParams(
+    scoped_refptr<SOCKSSocketParams> socks_socket_params) {
+  CreateConnectJobCallback callback = base::BindRepeating(
+      &CreateSOCKSConnectJob, std::move(socks_socket_params));
+  return base::MakeRefCounted<SocketParams>(callback);
+}
+
 TransportClientSocketPool::SocketParams::~SocketParams() = default;
 
 std::unique_ptr<ConnectJob>
diff --git a/net/socket/transport_client_socket_pool.h b/net/socket/transport_client_socket_pool.h
index ef9af2c..2cc8e3c 100644
--- a/net/socket/transport_client_socket_pool.h
+++ b/net/socket/transport_client_socket_pool.h
@@ -24,6 +24,7 @@
 class NetLog;
 class NetLogWithSource;
 class SocketPerformanceWatcherFactory;
+class SOCKSSocketParams;
 class TransportSocketParams;
 
 class NET_EXPORT_PRIVATE TransportClientSocketPool : public ClientSocketPool {
@@ -57,6 +58,9 @@
     static scoped_refptr<SocketParams> CreateFromTransportSocketParams(
         scoped_refptr<TransportSocketParams> transport_client_params);
 
+    static scoped_refptr<SocketParams> CreateFromSOCKSSocketParams(
+        scoped_refptr<SOCKSSocketParams> socks_socket_params);
+
    private:
     friend class base::RefCounted<SocketParams>;
     ~SocketParams();
diff --git a/net/socket/transport_client_socket_pool_unittest.cc b/net/socket/transport_client_socket_pool_unittest.cc
index 68f1c533..57169cd 100644
--- a/net/socket/transport_client_socket_pool_unittest.cc
+++ b/net/socket/transport_client_socket_pool_unittest.cc
@@ -23,6 +23,7 @@
 #include "net/socket/client_socket_handle.h"
 #include "net/socket/socket_tag.h"
 #include "net/socket/socket_test_util.h"
+#include "net/socket/socks_connect_job.h"
 #include "net/socket/stream_socket.h"
 #include "net/socket/transport_client_socket_pool_test_util.h"
 #include "net/socket/transport_connect_job.h"
@@ -46,6 +47,31 @@
 const int kMaxSocketsPerGroup = 6;
 const RequestPriority kDefaultPriority = LOW;
 
+class SOCKS5MockData {
+ public:
+  explicit SOCKS5MockData(IoMode mode) {
+    writes_.reset(new MockWrite[2]);
+    writes_[0] =
+        MockWrite(mode, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength);
+    writes_[1] = MockWrite(mode, kSOCKS5OkRequest, kSOCKS5OkRequestLength);
+
+    reads_.reset(new MockRead[2]);
+    reads_[0] =
+        MockRead(mode, kSOCKS5GreetResponse, kSOCKS5GreetResponseLength);
+    reads_[1] = MockRead(mode, kSOCKS5OkResponse, kSOCKS5OkResponseLength);
+
+    data_.reset(new StaticSocketDataProvider(
+        base::make_span(reads_.get(), 2), base::make_span(writes_.get(), 2)));
+  }
+
+  SocketDataProvider* data_provider() { return data_.get(); }
+
+ private:
+  std::unique_ptr<StaticSocketDataProvider> data_;
+  std::unique_ptr<MockWrite[]> writes_;
+  std::unique_ptr<MockRead[]> reads_;
+};
+
 class TransportClientSocketPoolTest : public TestWithScopedTaskEnvironment {
  protected:
   TransportClientSocketPoolTest()
@@ -1042,6 +1068,38 @@
   handle.Reset();
 }
 
+// Test the case that SOCKSSocketParams are provided.
+TEST_F(TransportClientSocketPoolTest, SOCKS) {
+  for (IoMode socket_io_mode : {SYNCHRONOUS, ASYNC}) {
+    MockTaggingClientSocketFactory socket_factory;
+    TransportClientSocketPool pool(
+        kMaxSockets, kMaxSocketsPerGroup, host_resolver_.get(), &socket_factory,
+        nullptr /* socket_performance_watcher_factory */, nullptr /* netlog */);
+
+    scoped_refptr<TransportSocketParams> tcp_params(new TransportSocketParams(
+        HostPortPair("proxy", 80), false, OnHostResolutionCallback()));
+    scoped_refptr<TransportClientSocketPool::SocketParams> socks_params(
+        TransportClientSocketPool::SocketParams::CreateFromSOCKSSocketParams(
+            base::MakeRefCounted<SOCKSSocketParams>(
+                tcp_params, true /* socks_v5 */, HostPortPair("host", 80),
+                TRAFFIC_ANNOTATION_FOR_TESTS)));
+
+    SOCKS5MockData data(socket_io_mode);
+    data.data_provider()->set_connect_data(MockConnect(socket_io_mode, OK));
+    socket_factory.AddSocketDataProvider(data.data_provider());
+    ClientSocketHandle handle;
+    TestCompletionCallback callback;
+    int rv = handle.Init("a", socks_params, LOW, SocketTag(),
+                         ClientSocketPool::RespectLimits::ENABLED,
+                         callback.callback(), &pool, NetLogWithSource());
+    EXPECT_THAT(callback.GetResult(rv), IsOk());
+    EXPECT_TRUE(handle.is_initialized());
+    EXPECT_TRUE(handle.socket());
+    EXPECT_TRUE(data.data_provider()->AllReadDataConsumed());
+    EXPECT_TRUE(data.data_provider()->AllWriteDataConsumed());
+  }
+}
+
 // Test that SocketTag passed into TransportClientSocketPool is applied to
 // returned sockets.
 #if defined(OS_ANDROID)
@@ -1165,6 +1223,81 @@
   EXPECT_EQ(static_cast<int>(strlen(kRequest)), callback.GetResult(rv));
   EXPECT_GT(GetTaggedBytes(tag_val1), old_traffic);
 }
+
+TEST_F(TransportClientSocketPoolTest, TagSOCKSProxy) {
+  host_resolver_->set_synchronous_mode(true);
+  MockTaggingClientSocketFactory socket_factory;
+  TransportClientSocketPool pool(
+      kMaxSockets, kMaxSocketsPerGroup, host_resolver_.get(), &socket_factory,
+      nullptr /* socket_performance_watcher_factory */, nullptr /* netlog */);
+
+  SocketTag tag1(SocketTag::UNSET_UID, 0x12345678);
+  SocketTag tag2(getuid(), 0x87654321);
+  scoped_refptr<TransportSocketParams> tcp_params(new TransportSocketParams(
+      HostPortPair("proxy", 80), false, OnHostResolutionCallback()));
+  scoped_refptr<TransportClientSocketPool::SocketParams> socks_params(
+      TransportClientSocketPool::SocketParams::CreateFromSOCKSSocketParams(
+          base::MakeRefCounted<SOCKSSocketParams>(
+              tcp_params, true /* socks_v5 */, HostPortPair("host", 80),
+              TRAFFIC_ANNOTATION_FOR_TESTS)));
+
+  // Test socket is tagged when created synchronously.
+  SOCKS5MockData data_sync(SYNCHRONOUS);
+  data_sync.data_provider()->set_connect_data(MockConnect(SYNCHRONOUS, OK));
+  socket_factory.AddSocketDataProvider(data_sync.data_provider());
+  ClientSocketHandle handle;
+  int rv = handle.Init("a", socks_params, LOW, tag1,
+                       ClientSocketPool::RespectLimits::ENABLED,
+                       CompletionOnceCallback(), &pool, NetLogWithSource());
+  EXPECT_THAT(rv, IsOk());
+  EXPECT_TRUE(handle.is_initialized());
+  EXPECT_TRUE(handle.socket());
+  EXPECT_EQ(socket_factory.GetLastProducedTCPSocket()->tag(), tag1);
+  EXPECT_TRUE(
+      socket_factory.GetLastProducedTCPSocket()->tagged_before_connected());
+
+  // Test socket is tagged when reused synchronously.
+  StreamSocket* socket = handle.socket();
+  handle.Reset();
+  rv = handle.Init("a", socks_params, LOW, tag2,
+                   ClientSocketPool::RespectLimits::ENABLED,
+                   CompletionOnceCallback(), &pool, NetLogWithSource());
+  EXPECT_THAT(rv, IsOk());
+  EXPECT_TRUE(handle.socket());
+  EXPECT_TRUE(handle.socket()->IsConnected());
+  EXPECT_EQ(handle.socket(), socket);
+  EXPECT_EQ(socket_factory.GetLastProducedTCPSocket()->tag(), tag2);
+  handle.socket()->Disconnect();
+  handle.Reset();
+
+  // Test socket is tagged when created asynchronously.
+  SOCKS5MockData data_async(ASYNC);
+  socket_factory.AddSocketDataProvider(data_async.data_provider());
+  TestCompletionCallback callback;
+  rv = handle.Init("a", socks_params, LOW, tag1,
+                   ClientSocketPool::RespectLimits::ENABLED,
+                   callback.callback(), &pool, NetLogWithSource());
+  EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
+  EXPECT_THAT(callback.WaitForResult(), IsOk());
+  EXPECT_TRUE(handle.is_initialized());
+  EXPECT_TRUE(handle.socket());
+  EXPECT_EQ(socket_factory.GetLastProducedTCPSocket()->tag(), tag1);
+  EXPECT_TRUE(
+      socket_factory.GetLastProducedTCPSocket()->tagged_before_connected());
+
+  // Test socket is tagged when reused after being created asynchronously.
+  socket = handle.socket();
+  handle.Reset();
+  rv = handle.Init("a", socks_params, LOW, tag2,
+                   ClientSocketPool::RespectLimits::ENABLED,
+                   CompletionOnceCallback(), &pool, NetLogWithSource());
+  EXPECT_THAT(rv, IsOk());
+  EXPECT_TRUE(handle.socket());
+  EXPECT_TRUE(handle.socket()->IsConnected());
+  EXPECT_EQ(handle.socket(), socket);
+  EXPECT_EQ(socket_factory.GetLastProducedTCPSocket()->tag(), tag2);
+}
+
 #endif
 
 }  // namespace
diff --git a/net/socket/udp_socket_posix.cc b/net/socket/udp_socket_posix.cc
index f82f722e..558135f 100644
--- a/net/socket/udp_socket_posix.cc
+++ b/net/socket/udp_socket_posix.cc
@@ -951,6 +951,15 @@
 #endif  //  !defined(OS_MACOSX)
         int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF,
                             reinterpret_cast<const char*>(&mreq), sizeof(mreq));
+#if defined(OS_FUCHSIA)
+        // Remove this workaround once IP_MULTICAST_IF is implemented.
+        // See https://crbug.com/924792
+        if (rv && errno == EOPNOTSUPP) {
+          LOG(WARNING)
+              << "IP_MULTICAST_IF is not supported. Proceeding anyway.";
+          rv = 0;
+        }
+#endif  // !defined(OS_FUCHSIA)
         if (rv)
           return MapSystemError(errno);
         break;
diff --git a/net/spdy/bidirectional_stream_spdy_impl_unittest.cc b/net/spdy/bidirectional_stream_spdy_impl_unittest.cc
index 73d0611..1da14a9 100644
--- a/net/spdy/bidirectional_stream_spdy_impl_unittest.cc
+++ b/net/spdy/bidirectional_stream_spdy_impl_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/strings/string_piece.h"
 #include "base/time/time.h"
 #include "base/timer/mock_timer.h"
+#include "base/timer/timer.h"
 #include "net/base/load_timing_info.h"
 #include "net/base/load_timing_info_test_util.h"
 #include "net/base/net_errors.h"
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc
index 776d81e..fb75add 100644
--- a/net/spdy/spdy_test_util_common.cc
+++ b/net/spdy/spdy_test_util_common.cc
@@ -25,6 +25,7 @@
 #include "net/socket/client_socket_handle.h"
 #include "net/socket/next_proto.h"
 #include "net/socket/socket_tag.h"
+#include "net/socket/socks_connect_job.h"
 #include "net/socket/ssl_client_socket.h"
 #include "net/socket/transport_client_socket_pool.h"
 #include "net/socket/transport_connect_job.h"
diff --git a/net/test/embedded_test_server/embedded_test_server_unittest.cc b/net/test/embedded_test_server/embedded_test_server_unittest.cc
index a1c8bdc..912d24f 100644
--- a/net/test/embedded_test_server/embedded_test_server_unittest.cc
+++ b/net/test/embedded_test_server/embedded_test_server_unittest.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/message_loop/message_loop.h"
diff --git a/net/url_request/url_fetcher_core.cc b/net/url_request/url_fetcher_core.cc
index b5a587e..97a7e3c8 100644
--- a/net/url_request/url_fetcher_core.cc
+++ b/net/url_request/url_fetcher_core.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "base/sequenced_task_runner.h"
 #include "base/single_thread_task_runner.h"
diff --git a/net/url_request/url_request_quic_unittest.cc b/net/url_request/url_request_quic_unittest.cc
index 65eca17..1d0d6c2 100644
--- a/net/url_request/url_request_quic_unittest.cc
+++ b/net/url_request/url_request_quic_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_path.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
index 6f7b73b..47c52540 100644
--- a/net/url_request/url_request_unittest.cc
+++ b/net/url_request/url_request_unittest.cc
@@ -6,6 +6,7 @@
 #include <utility>
 
 // This must be before Windows headers
+#include "base/bind_helpers.h"
 #include "build/build_config.h"
 
 #if defined(OS_WIN)
diff --git a/net/websockets/websocket_basic_stream_adapters_test.cc b/net/websockets/websocket_basic_stream_adapters_test.cc
index 61c47be1..747f7b7 100644
--- a/net/websockets/websocket_basic_stream_adapters_test.cc
+++ b/net/websockets/websocket_basic_stream_adapters_test.cc
@@ -24,6 +24,7 @@
 #include "net/socket/client_socket_pool_manager_impl.h"
 #include "net/socket/socket_tag.h"
 #include "net/socket/socket_test_util.h"
+#include "net/socket/socks_connect_job.h"
 #include "net/socket/ssl_client_socket_pool.h"
 #include "net/socket/transport_client_socket_pool.h"
 #include "net/socket/transport_connect_job.h"
diff --git a/remoting/client/plugin/chromoting_instance.h b/remoting/client/plugin/chromoting_instance.h
index f29f7b9..4e370378 100644
--- a/remoting/client/plugin/chromoting_instance.h
+++ b/remoting/client/plugin/chromoting_instance.h
@@ -14,6 +14,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/timer/timer.h"
 #include "ppapi/c/pp_instance.h"
 #include "ppapi/c/pp_rect.h"
 #include "ppapi/c/pp_resource.h"
diff --git a/remoting/host/desktop_session_agent_unittest.cc b/remoting/host/desktop_session_agent_unittest.cc
index 2a736533..1d2f09b1 100644
--- a/remoting/host/desktop_session_agent_unittest.cc
+++ b/remoting/host/desktop_session_agent_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/location.h"
 #include "base/memory/ref_counted.h"
diff --git a/remoting/protocol/connection_unittest.cc b/remoting/protocol/connection_unittest.cc
index 718394a..6496a62 100644
--- a/remoting/protocol/connection_unittest.cc
+++ b/remoting/protocol/connection_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/test/scoped_task_environment.h"
 #include "base/threading/thread.h"
 #include "base/threading/thread_checker.h"
+#include "base/timer/timer.h"
 #include "remoting/base/constants.h"
 #include "remoting/proto/audio.pb.h"
 #include "remoting/protocol/audio_source.h"
diff --git a/remoting/protocol/monitored_video_stub_unittest.cc b/remoting/protocol/monitored_video_stub_unittest.cc
index e66301e..96ed812 100644
--- a/remoting/protocol/monitored_video_stub_unittest.cc
+++ b/remoting/protocol/monitored_video_stub_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/test/test_timeouts.h"
+#include "base/timer/timer.h"
 #include "remoting/protocol/protocol_mock_objects.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/remoting/protocol/webrtc_transport_unittest.cc b/remoting/protocol/webrtc_transport_unittest.cc
index c25618d..fcc6180 100644
--- a/remoting/protocol/webrtc_transport_unittest.cc
+++ b/remoting/protocol/webrtc_transport_unittest.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
diff --git a/remoting/test/test_video_renderer_unittest.cc b/remoting/test/test_video_renderer_unittest.cc
index 0de668b..91a28f8 100644
--- a/remoting/test/test_video_renderer_unittest.cc
+++ b/remoting/test/test_video_renderer_unittest.cc
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/message_loop/message_loop.h"
diff --git a/services/audio/output_stream.cc b/services/audio/output_stream.cc
index 61893c4..2d89c6a4 100644
--- a/services/audio/output_stream.cc
+++ b/services/audio/output_stream.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "base/trace_event/trace_event.h"
 
diff --git a/services/content/public/cpp/navigable_contents_view.cc b/services/content/public/cpp/navigable_contents_view.cc
index 4b5c5e3..502b7a90 100644
--- a/services/content/public/cpp/navigable_contents_view.cc
+++ b/services/content/public/cpp/navigable_contents_view.cc
@@ -6,6 +6,7 @@
 
 #include <map>
 
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/no_destructor.h"
 #include "base/synchronization/atomic_flag.h"
diff --git a/services/content/public/cpp/test/fake_navigable_contents.cc b/services/content/public/cpp/test/fake_navigable_contents.cc
index 3febc31..12dc304 100644
--- a/services/content/public/cpp/test/fake_navigable_contents.cc
+++ b/services/content/public/cpp/test/fake_navigable_contents.cc
@@ -5,6 +5,7 @@
 #include "services/content/public/cpp/test/fake_navigable_contents.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/unguessable_token.h"
 #include "services/content/public/cpp/navigable_contents_view.h"
 #include "services/content/public/cpp/test/fake_navigable_contents_factory.h"
diff --git a/services/device/battery/battery_status_manager_linux.cc b/services/device/battery/battery_status_manager_linux.cc
index 81de99c..59cb814 100644
--- a/services/device/battery/battery_status_manager_linux.cc
+++ b/services/device/battery/battery_status_manager_linux.cc
@@ -14,6 +14,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram_macros.h"
diff --git a/services/device/hid/hid_service_win.cc b/services/device/hid/hid_service_win.cc
index c8d8f4c0..576ed6ec 100644
--- a/services/device/hid/hid_service_win.cc
+++ b/services/device/hid/hid_service_win.cc
@@ -16,6 +16,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file.h"
 #include "base/location.h"
 #include "base/memory/free_deleter.h"
diff --git a/services/device/media_transfer_protocol/mtp_device_manager.cc b/services/device/media_transfer_protocol/mtp_device_manager.cc
index 5c7da76..1bc49be 100644
--- a/services/device/media_transfer_protocol/mtp_device_manager.cc
+++ b/services/device/media_transfer_protocol/mtp_device_manager.cc
@@ -5,6 +5,7 @@
 #include "services/device/media_transfer_protocol/mtp_device_manager.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
 #include "dbus/bus.h"
 #include "third_party/cros_system_api/dbus/service_constants.h"
diff --git a/services/identity/public/cpp/identity_test_environment.cc b/services/identity/public/cpp/identity_test_environment.cc
index 56d9a669..c0e2bfd 100644
--- a/services/identity/public/cpp/identity_test_environment.cc
+++ b/services/identity/public/cpp/identity_test_environment.cc
@@ -452,6 +452,10 @@
   token_service_->LoadCredentials("");
 }
 
+bool IdentityTestEnvironment::IsAccessTokenRequestPending() {
+  return token_service_->GetPendingRequests().size();
+}
+
 void IdentityTestEnvironment::SetFreshnessOfAccountsInGaiaCookie(
     bool accounts_are_fresh) {
   gaia_cookie_manager_service_->set_list_accounts_stale_for_testing(
diff --git a/services/identity/public/cpp/identity_test_environment.h b/services/identity/public/cpp/identity_test_environment.h
index bcb76d8..447d863c 100644
--- a/services/identity/public/cpp/identity_test_environment.h
+++ b/services/identity/public/cpp/identity_test_environment.h
@@ -242,6 +242,9 @@
   // Simulates the reloading of the accounts from disk.
   void ReloadAccountsFromDisk();
 
+  // Returns whether there is a access token request pending.
+  bool IsAccessTokenRequestPending();
+
   // Sets whether the list of accounts in Gaia cookie jar is fresh and does not
   // need to be updated.
   void SetFreshnessOfAccountsInGaiaCookie(bool accounts_are_fresh);
diff --git a/services/network/mdns_responder_unittest.cc b/services/network/mdns_responder_unittest.cc
index e324d07b..e6edb79 100644
--- a/services/network/mdns_responder_unittest.cc
+++ b/services/network/mdns_responder_unittest.cc
@@ -11,6 +11,7 @@
 #include "services/network/mdns_responder.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/logging.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/strings/string_piece.h"
diff --git a/services/network/network_service.cc b/services/network/network_service.cc
index fbe344a..e1dc8dd 100644
--- a/services/network/network_service.cc
+++ b/services/network/network_service.cc
@@ -138,6 +138,16 @@
   return a.load_state > b.load_state;
 }
 
+void OnGetNetworkList(std::unique_ptr<net::NetworkInterfaceList> networks,
+                      mojom::NetworkService::GetNetworkListCallback callback,
+                      bool success) {
+  if (success) {
+    std::move(callback).Run(*networks);
+  } else {
+    std::move(callback).Run(base::nullopt);
+  }
+}
+
 #if defined(OS_ANDROID) && BUILDFLAG(USE_KERBEROS)
 // Used for Negotiate authentication on Android, which needs to generate tokens
 // in the browser process.
@@ -557,12 +567,14 @@
 void NetworkService::GetNetworkList(
     uint32_t policy,
     mojom::NetworkService::GetNetworkListCallback callback) {
-  net::NetworkInterfaceList networks;
-  if (net::GetNetworkList(&networks, policy)) {
-    std::move(callback).Run(networks);
-  } else {
-    std::move(callback).Run(base::nullopt);
-  }
+  auto networks = std::make_unique<net::NetworkInterfaceList>();
+  auto* raw_networks = networks.get();
+  // net::GetNetworkList may block depending on platform.
+  base::PostTaskWithTraitsAndReplyWithResult(
+      FROM_HERE, {base::MayBlock()},
+      base::BindOnce(&net::GetNetworkList, raw_networks, policy),
+      base::BindOnce(&OnGetNetworkList, std::move(networks),
+                     std::move(callback)));
 }
 
 #if BUILDFLAG(IS_CT_SUPPORTED)
diff --git a/services/network/network_service.h b/services/network/network_service.h
index 9e39832..2a63c54 100644
--- a/services/network/network_service.h
+++ b/services/network/network_service.h
@@ -19,6 +19,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/optional.h"
 #include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "build/build_config.h"
 #include "mojo/public/cpp/bindings/binding.h"
 #include "net/http/http_auth_preferences.h"
diff --git a/services/network/public/cpp/network_connection_tracker_unittest.cc b/services/network/public/cpp/network_connection_tracker_unittest.cc
index ecf3882..c834a32 100644
--- a/services/network/public/cpp/network_connection_tracker_unittest.cc
+++ b/services/network/public/cpp/network_connection_tracker_unittest.cc
@@ -5,6 +5,7 @@
 #include "services/network/public/cpp/network_connection_tracker.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
diff --git a/services/network/tcp_socket_unittest.cc b/services/network/tcp_socket_unittest.cc
index bb89a29..22c4b7d 100644
--- a/services/network/tcp_socket_unittest.cc
+++ b/services/network/tcp_socket_unittest.cc
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback_helpers.h"
 #include "base/location.h"
 #include "base/logging.h"
diff --git a/services/network/test/test_network_connection_tracker.cc b/services/network/test/test_network_connection_tracker.cc
index 889ffec..8cd7b75 100644
--- a/services/network/test/test_network_connection_tracker.cc
+++ b/services/network/test/test_network_connection_tracker.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/logging.h"
 #include "base/memory/ptr_util.h"
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
index 86de200..deda168 100644
--- a/services/network/url_loader.cc
+++ b/services/network/url_loader.cc
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/debug/alias.h"
 #include "base/debug/dump_without_crashing.h"
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc
index 445a47fc..ec496847 100644
--- a/services/network/url_loader_unittest.cc
+++ b/services/network/url_loader_unittest.cc
@@ -12,6 +12,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/compiler_specific.h"
 #include "base/files/file.h"
 #include "base/files/file_path.h"
diff --git a/services/preferences/pref_store_consistency_unittest.cc b/services/preferences/pref_store_consistency_unittest.cc
index 2477151..b403bdc 100644
--- a/services/preferences/pref_store_consistency_unittest.cc
+++ b/services/preferences/pref_store_consistency_unittest.cc
@@ -5,6 +5,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/bind_helpers.h"
 #include "base/containers/circular_deque.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
diff --git a/services/preferences/public/cpp/pref_service_factory.cc b/services/preferences/public/cpp/pref_service_factory.cc
index 2c4ddcd..41f017b3 100644
--- a/services/preferences/public/cpp/pref_service_factory.cc
+++ b/services/preferences/public/cpp/pref_service_factory.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/callback_helpers.h"
 #include "components/prefs/overlay_user_pref_store.h"
 #include "components/prefs/persistent_pref_store.h"
diff --git a/services/preferences/public/cpp/tests/persistent_pref_store_client_unittest.cc b/services/preferences/public/cpp/tests/persistent_pref_store_client_unittest.cc
index 5eba62e..02a5393 100644
--- a/services/preferences/public/cpp/tests/persistent_pref_store_client_unittest.cc
+++ b/services/preferences/public/cpp/tests/persistent_pref_store_client_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "base/run_loop.h"
diff --git a/services/service_manager/public/cpp/test/test_connector_factory.cc b/services/service_manager/public/cpp/test/test_connector_factory.cc
index d09847c..5eb34a8 100644
--- a/services/service_manager/public/cpp/test/test_connector_factory.cc
+++ b/services/service_manager/public/cpp/test/test_connector_factory.cc
@@ -7,6 +7,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/guid.h"
 #include "base/macros.h"
 #include "mojo/public/cpp/bindings/associated_binding.h"
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
index ac4149b..0d7d55a 100644
--- a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
+++ b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/json/json_writer.h"
 #include "base/memory/ref_counted_memory.h"
 #include "base/no_destructor.h"
@@ -204,13 +205,6 @@
     // we're behind a flag) is to run the service on its own thread, the longer
     // term fix is most likely to not go via Mojo in that specific case.
 
-    // TODO(oysteine): Temporary workaround for a specific trace event
-    // which is added while a scheduler lock is held, and will deadlock
-    // if Perfetto does a PostTask to commit a finished chunk.
-    if (strcmp(trace_event->name(), "RealTimeDomain::DelayTillNextTask") == 0) {
-      return;
-    }
-
     if (handle && trace_event->phase() == TRACE_EVENT_PHASE_COMPLETE) {
       // 'X' phase events are added through a scoped object and
       // will have its duration updated when said object drops off
diff --git a/services/video_capture/device_media_to_mojo_adapter_unittest.cc b/services/video_capture/device_media_to_mojo_adapter_unittest.cc
index 879667d..c0d1a5b 100644
--- a/services/video_capture/device_media_to_mojo_adapter_unittest.cc
+++ b/services/video_capture/device_media_to_mojo_adapter_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "services/video_capture/device_media_to_mojo_adapter.h"
 
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
 #include "media/capture/video/mock_device.h"
diff --git a/services/video_capture/push_video_stream_subscription_impl.cc b/services/video_capture/push_video_stream_subscription_impl.cc
index e3d488b..2748a6c 100644
--- a/services/video_capture/push_video_stream_subscription_impl.cc
+++ b/services/video_capture/push_video_stream_subscription_impl.cc
@@ -5,6 +5,7 @@
 #include "services/video_capture/push_video_stream_subscription_impl.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "services/video_capture/broadcasting_receiver.h"
 
 namespace video_capture {
diff --git a/services/video_capture/test/device_factory_provider_connectortest.cc b/services/video_capture/test/device_factory_provider_connectortest.cc
index a148a952..638be12 100644
--- a/services/video_capture/test/device_factory_provider_connectortest.cc
+++ b/services/video_capture/test/device_factory_provider_connectortest.cc
@@ -7,6 +7,7 @@
 #include "base/run_loop.h"
 #include "base/test/mock_callback.h"
 #include "base/test/scoped_task_environment.h"
+#include "base/timer/timer.h"
 #include "media/base/media_switches.h"
 #include "services/service_manager/public/cpp/test/test_connector_factory.h"
 #include "services/video_capture/public/cpp/mock_receiver.h"
diff --git a/services/video_capture/test/mock_device_shared_access_unittest.cc b/services/video_capture/test/mock_device_shared_access_unittest.cc
index 6e543b52..31a9ba9 100644
--- a/services/video_capture/test/mock_device_shared_access_unittest.cc
+++ b/services/video_capture/test/mock_device_shared_access_unittest.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/test/mock_callback.h"
 #include "base/test/scoped_task_environment.h"
diff --git a/services/video_capture/video_source_impl.cc b/services/video_capture/video_source_impl.cc
index c627424..000a705 100644
--- a/services/video_capture/video_source_impl.cc
+++ b/services/video_capture/video_source_impl.cc
@@ -5,6 +5,7 @@
 #include "services/video_capture/video_source_impl.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "services/video_capture/push_video_stream_subscription_impl.h"
 
 namespace video_capture {
diff --git a/services/viz/privileged/interfaces/compositing/renderer_settings.mojom b/services/viz/privileged/interfaces/compositing/renderer_settings.mojom
index 8720a42d..1d3aeeb 100644
--- a/services/viz/privileged/interfaces/compositing/renderer_settings.mojom
+++ b/services/viz/privileged/interfaces/compositing/renderer_settings.mojom
@@ -18,7 +18,6 @@
   bool release_overlay_resources_after_gpu_query;
   bool should_clear_root_render_pass;
   bool show_overdraw_feedback;
-  bool enable_draw_occlusion;
   int32 slow_down_compositing_scale_factor;
   bool use_skia_renderer;
   bool record_sk_picture;
diff --git a/services/viz/privileged/interfaces/compositing/renderer_settings_struct_traits.cc b/services/viz/privileged/interfaces/compositing/renderer_settings_struct_traits.cc
index c305238..10726010 100644
--- a/services/viz/privileged/interfaces/compositing/renderer_settings_struct_traits.cc
+++ b/services/viz/privileged/interfaces/compositing/renderer_settings_struct_traits.cc
@@ -23,7 +23,6 @@
       data.release_overlay_resources_after_gpu_query();
   out->tint_gl_composited_content = data.tint_gl_composited_content();
   out->show_overdraw_feedback = data.show_overdraw_feedback();
-  out->enable_draw_occlusion = data.enable_draw_occlusion();
   out->highp_threshold_min = data.highp_threshold_min();
   out->slow_down_compositing_scale_factor =
       data.slow_down_compositing_scale_factor();
diff --git a/services/viz/privileged/interfaces/compositing/renderer_settings_struct_traits.h b/services/viz/privileged/interfaces/compositing/renderer_settings_struct_traits.h
index be705e4..4e9c42a 100644
--- a/services/viz/privileged/interfaces/compositing/renderer_settings_struct_traits.h
+++ b/services/viz/privileged/interfaces/compositing/renderer_settings_struct_traits.h
@@ -53,10 +53,6 @@
     return input.show_overdraw_feedback;
   }
 
-  static bool enable_draw_occlusion(const viz::RendererSettings& input) {
-    return input.enable_draw_occlusion;
-  }
-
   static int highp_threshold_min(const viz::RendererSettings& input) {
     return input.highp_threshold_min;
   }
diff --git a/services/viz/privileged/interfaces/struct_traits_unittest.cc b/services/viz/privileged/interfaces/struct_traits_unittest.cc
index f20d1b2..e80892f 100644
--- a/services/viz/privileged/interfaces/struct_traits_unittest.cc
+++ b/services/viz/privileged/interfaces/struct_traits_unittest.cc
@@ -27,7 +27,6 @@
   input.should_clear_root_render_pass = false;
   input.release_overlay_resources_after_gpu_query = true;
   input.show_overdraw_feedback = true;
-  input.enable_draw_occlusion = true;
   input.highp_threshold_min = -1;
   input.use_skia_renderer = true;
 
@@ -48,7 +47,6 @@
   EXPECT_EQ(input.tint_gl_composited_content,
             output.tint_gl_composited_content);
   EXPECT_EQ(input.show_overdraw_feedback, output.show_overdraw_feedback);
-  EXPECT_EQ(input.enable_draw_occlusion, output.enable_draw_occlusion);
   EXPECT_EQ(input.highp_threshold_min, output.highp_threshold_min);
   EXPECT_EQ(input.use_skia_renderer, output.use_skia_renderer);
 }
diff --git a/services/ws/BUILD.gn b/services/ws/BUILD.gn
index 6a83a25..f3cb09a 100644
--- a/services/ws/BUILD.gn
+++ b/services/ws/BUILD.gn
@@ -4,7 +4,6 @@
 
 import("//build/config/ui.gni")
 import("//mojo/public/tools/bindings/mojom.gni")
-import("//services/catalog/public/tools/catalog.gni")
 import("//services/service_manager/public/service_manifest.gni")
 import("//testing/test.gni")
 
@@ -162,7 +161,6 @@
 
   deps = [
     ":lib",
-    ":tests_catalog_source",
     "//base",
     "//base/test:test_support",
     "//components/viz/test:test_support",
@@ -173,6 +171,7 @@
     "//services/ws/public/cpp",
     "//services/ws/public/cpp/host",
     "//services/ws/public/mojom",
+    "//services/ws/test_ws:manifest",
     "//testing/gtest",
     "//ui/aura",
     "//ui/aura:test_support",
@@ -190,23 +189,6 @@
   ]
 }
 
-service_manifest("unittests_manifest") {
-  name = "ui_ws2_service_unittests"
-  source = "test_manifest.json"
-}
-
-catalog("tests_catalog") {
-  testonly = true
-  embedded_services = [ ":unittests_manifest" ]
-  standalone_services = [ "//services/ws/test_ws:manifest" ]
-}
-
-catalog_cpp_source("tests_catalog_source") {
-  testonly = true
-  catalog = ":tests_catalog"
-  generated_function_name = "ws::test::CreateTestCatalog"
-}
-
 source_set("tests") {
   testonly = true
 
diff --git a/services/ws/OWNERS b/services/ws/OWNERS
index e7b8b83..9315aba 100644
--- a/services/ws/OWNERS
+++ b/services/ws/OWNERS
@@ -12,8 +12,5 @@
 per-file manifest.json=set noparent
 per-file manifest.json=file://ipc/SECURITY_OWNERS
 
-per-file test_manifest.json=set noparent
-per-file test_manifest.json=file://ipc/SECURITY_OWNERS
-
 per-file *.mojom=set noparent
 per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/services/ws/client_root.cc b/services/ws/client_root.cc
index b9772f2a..e78a2dc 100644
--- a/services/ws/client_root.cc
+++ b/services/ws/client_root.cc
@@ -74,7 +74,7 @@
       frame_sink_id, this, viz::ReportFirstSurfaceActivation::kYes);
   window_->SetEmbedFrameSinkId(frame_sink_id);
 
-  UpdatePrimarySurfaceId();
+  UpdateLocalSurfaceIdAndClientSurfaceEmbedder();
 }
 
 bool ClientRoot::ShouldAssignLocalSurfaceId() {
@@ -106,6 +106,19 @@
   }
 }
 
+void ClientRoot::UpdateLocalSurfaceIdAndClientSurfaceEmbedder() {
+  UpdateLocalSurfaceIdIfNecessary();
+  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window_);
+  if (proxy_window->local_surface_id().has_value()) {
+    client_surface_embedder_->SetSurfaceId(viz::SurfaceId(
+        window_->GetFrameSinkId(), *proxy_window->local_surface_id()));
+    if (fallback_surface_info_) {
+      client_surface_embedder_->SetFallbackSurfaceInfo(*fallback_surface_info_);
+      fallback_surface_info_.reset();
+    }
+  }
+}
+
 void ClientRoot::OnLocalSurfaceIdChanged() {
   if (ShouldAssignLocalSurfaceId())
     return;
@@ -165,19 +178,6 @@
   }
 }
 
-void ClientRoot::UpdatePrimarySurfaceId() {
-  UpdateLocalSurfaceIdIfNecessary();
-  ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window_);
-  if (proxy_window->local_surface_id().has_value()) {
-    client_surface_embedder_->SetSurfaceId(viz::SurfaceId(
-        window_->GetFrameSinkId(), *proxy_window->local_surface_id()));
-    if (fallback_surface_info_) {
-      client_surface_embedder_->SetFallbackSurfaceInfo(*fallback_surface_info_);
-      fallback_surface_info_.reset();
-    }
-  }
-}
-
 void ClientRoot::CheckForScaleFactorChange() {
   if (!ShouldAssignLocalSurfaceId() ||
       last_device_scale_factor_ == window_->layer()->device_scale_factor()) {
@@ -189,7 +189,7 @@
 }
 
 void ClientRoot::HandleBoundsOrScaleFactorChange(const gfx::Rect& old_bounds) {
-  UpdatePrimarySurfaceId();
+  UpdateLocalSurfaceIdAndClientSurfaceEmbedder();
   client_surface_embedder_->UpdateSizeAndGutters();
   // See comments in WindowTree::SetWindowBoundsImpl() for details on
   // why this always notifies the client.
@@ -304,7 +304,7 @@
   if (proxy_window->local_surface_id().has_value()) {
     DCHECK(!fallback_surface_info_);
     if (!client_surface_embedder_->HasPrimarySurfaceId())
-      UpdatePrimarySurfaceId();
+      UpdateLocalSurfaceIdAndClientSurfaceEmbedder();
     client_surface_embedder_->SetFallbackSurfaceInfo(surface_info);
   } else {
     fallback_surface_info_ = std::make_unique<viz::SurfaceInfo>(surface_info);
diff --git a/services/ws/client_root.h b/services/ws/client_root.h
index 6d0b1701..c4cb0829 100644
--- a/services/ws/client_root.h
+++ b/services/ws/client_root.h
@@ -80,15 +80,19 @@
  private:
   friend class ClientRootTestHelper;
 
-  void UpdatePrimarySurfaceId();
-
   // Returns true if the WindowService should assign the LocalSurfaceId. A value
   // of false means the client is expected to providate the LocalSurfaceId.
   bool ShouldAssignLocalSurfaceId();
 
-  // If necessary, this updates the LocalSurfaceId.
+  // If necessary, this updates the LocalSurfaceId. Generally you should call
+  // UpdateLocalSurfaceIdAndClientSurfaceEmbedder(), not this. If you call this,
+  // you need to ensure the ClientSurfaceEmbedder is updated at a later time.
   void UpdateLocalSurfaceIdIfNecessary();
 
+  // Calls UpdateLocalSurfaceIdIfNecessary() and if the current LocalSurfaceId
+  // is valid, updates ClientSurfaceEmbedder.
+  void UpdateLocalSurfaceIdAndClientSurfaceEmbedder();
+
   // Calls HandleBoundsOrScaleFactorChange() it the scale factor has changed.
   void CheckForScaleFactorChange();
 
diff --git a/services/ws/drag_drop_delegate.cc b/services/ws/drag_drop_delegate.cc
index 5c1c593..761c2d6 100644
--- a/services/ws/drag_drop_delegate.cc
+++ b/services/ws/drag_drop_delegate.cc
@@ -5,6 +5,7 @@
 #include "services/ws/drag_drop_delegate.h"
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/strings/string16.h"
 #include "mojo/public/cpp/bindings/map.h"
 #include "services/ws/window_tree.h"
diff --git a/services/ws/ime/BUILD.gn b/services/ws/ime/BUILD.gn
index 73e9795..8096264 100644
--- a/services/ws/ime/BUILD.gn
+++ b/services/ws/ime/BUILD.gn
@@ -2,7 +2,6 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
-import("//services/catalog/public/tools/catalog.gni")
 import("//services/service_manager/public/service_manifest.gni")
 import("//testing/test.gni")
 
@@ -30,38 +29,19 @@
   ]
 
   deps = [
-    ":tests_catalog_source",
     "//base",
     "//base/test:test_support",
     "//services/service_manager/public/cpp",
     "//services/service_manager/public/cpp/test:test_support",
+    "//services/ws/ime/test_ime_driver:manifest",
     "//services/ws/ime/test_ime_driver/public/mojom",
     "//services/ws/public/mojom",
+    "//services/ws/test_ws:manifest",
     "//testing/gtest",
   ]
 
   data_deps = [
-    ":lib",
     "//services/ws/ime/test_ime_driver",
+    "//services/ws/test_ws",
   ]
 }
-
-service_manifest("unittest_manifest") {
-  name = "ime_unittests"
-  source = "test_manifest.json"
-}
-
-catalog("tests_catalog") {
-  testonly = true
-  embedded_services = [ ":unittest_manifest" ]
-  standalone_services = [
-    "//services/ws/ime/test_ime_driver:manifest",
-    "//services/ws/test_ws:manifest",
-  ]
-}
-
-catalog_cpp_source("tests_catalog_source") {
-  testonly = true
-  catalog = ":tests_catalog"
-  generated_function_name = "ws::test::CreateImeTestCatalog"
-}
diff --git a/services/ws/ime/OWNERS b/services/ws/ime/OWNERS
deleted file mode 100644
index af9ec9f..0000000
--- a/services/ws/ime/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-per-file test_manifest.json=set noparent
-per-file test_manifest.json=file://ipc/SECURITY_OWNERS
diff --git a/services/ws/ime/ime_unittest.cc b/services/ws/ime/ime_unittest.cc
index 43d3534b..b9031e1 100644
--- a/services/ws/ime/ime_unittest.cc
+++ b/services/ws/ime/ime_unittest.cc
@@ -9,13 +9,15 @@
 #include "base/run_loop.h"
 #include "base/test/scoped_task_environment.h"
 #include "mojo/public/cpp/bindings/interface_request.h"
+#include "services/service_manager/public/cpp/manifest_builder.h"
 #include "services/service_manager/public/cpp/service.h"
 #include "services/service_manager/public/cpp/service_binding.h"
 #include "services/service_manager/public/cpp/test/test_service_manager.h"
+#include "services/ws/ime/test_ime_driver/manifest.h"
 #include "services/ws/ime/test_ime_driver/public/mojom/constants.mojom.h"
-#include "services/ws/ime/tests_catalog_source.h"
 #include "services/ws/public/mojom/constants.mojom.h"
 #include "services/ws/public/mojom/ime/ime.mojom.h"
+#include "services/ws/test_ws/manifest.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/events/event.h"
 #include "ui/events/keycodes/dom/dom_code.h"
@@ -59,13 +61,21 @@
   DISALLOW_COPY_AND_ASSIGN(TestTextInputClient);
 };
 
+const char kTestServiceName[] = "ime_unittests";
+
 class IMEAppTest : public testing::Test {
  public:
   IMEAppTest()
-      : test_service_manager_(ws::test::CreateImeTestCatalog()),
+      : test_service_manager_(
+            {test_ws::GetManifest(), test_ime_driver::GetManifest(),
+             service_manager::ManifestBuilder()
+                 .WithServiceName(kTestServiceName)
+                 .RequireCapability(ws::mojom::kServiceName, "app")
+                 .RequireCapability(test_ime_driver::mojom::kServiceName, "")
+                 .Build()}),
         test_service_binding_(
             &test_service_,
-            test_service_manager_.RegisterTestInstance("ime_unittests")) {
+            test_service_manager_.RegisterTestInstance(kTestServiceName)) {
     // test_ime_driver will register itself as the current IMEDriver.
     // TODO(https://crbug.com/904148): This should not use |WarmService()|.
     connector()->WarmService(service_manager::ServiceFilter::ByName(
diff --git a/services/ws/ime/test_manifest.json b/services/ws/ime/test_manifest.json
deleted file mode 100644
index 9381d28..0000000
--- a/services/ws/ime/test_manifest.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "name": "ime_unittests",
-  "display_name": "IME Service Unittests",
-  "interface_provider_specs": {
-    "service_manager:connector": {
-      "requires": {
-        "ui": [ "app" ],
-        "test_ime_driver": [ ]
-      }
-    }
-  }
-}
diff --git a/services/ws/test_manifest.json b/services/ws/test_manifest.json
deleted file mode 100644
index 4ba1427f..0000000
--- a/services/ws/test_manifest.json
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-  "name": "ui_ws2_service_unittests",
-  "display_name": "Window Service Unittests",
-  "interface_provider_specs": {
-    "service_manager:connector": {
-      "provides": {
-        "ui:window_tree_client": [
-          "ws.mojom.WindowTreeClient"
-        ]
-      },
-      "requires": {
-        "*": [ "app" ],
-        "ui_ws2_service_unittests": [ "ui:window_tree_client" ],
-        "viz": [ "viz_host" ]
-      }
-    }
-  }
-}
diff --git a/services/ws/window_server_service_test_base.cc b/services/ws/window_server_service_test_base.cc
index 3209b1a..c6245b0d 100644
--- a/services/ws/window_server_service_test_base.cc
+++ b/services/ws/window_server_service_test_base.cc
@@ -8,8 +8,11 @@
 
 #include "base/command_line.h"
 #include "base/memory/ptr_util.h"
+#include "services/service_manager/public/cpp/manifest_builder.h"
 #include "services/ws/common/switches.h"
-#include "services/ws/tests_catalog_source.h"
+#include "services/ws/public/mojom/constants.mojom.h"
+#include "services/ws/public/mojom/window_tree.mojom.h"
+#include "services/ws/test_ws/manifest.h"
 #include "ui/gl/gl_switches.h"
 
 namespace ws {
@@ -27,7 +30,17 @@
 }  // namespace
 
 WindowServerServiceTestBase::WindowServerServiceTestBase()
-    : test_service_manager_(test::CreateTestCatalog()),
+    : test_service_manager_(
+          {test_ws::GetManifest(),
+           service_manager::ManifestBuilder()
+               .WithServiceName(kTestAppName)
+               .ExposeCapability("ui:window_tree_client",
+                                 service_manager::Manifest::InterfaceList<
+                                     ws::mojom::WindowTreeClient>())
+               .RequireCapability(kTestAppName, "ui:window_tree_client")
+               .RequireCapability(ws::mojom::kServiceName, "app")
+               .RequireCapability("viz", "viz_host")
+               .Build()}),
       test_service_binding_(
           this,
           test_service_manager_.RegisterTestInstance(kTestAppName)) {
diff --git a/storage/browser/blob/blob_builder_from_stream_unittest.cc b/storage/browser/blob/blob_builder_from_stream_unittest.cc
index 2d8a3235..aacc841c 100644
--- a/storage/browser/blob/blob_builder_from_stream_unittest.cc
+++ b/storage/browser/blob/blob_builder_from_stream_unittest.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/rand_util.h"
diff --git a/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc b/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
index 8f8cd05..8210336 100644
--- a/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
+++ b/storage/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/containers/queue.h"
 #include "base/files/file_util.h"
 #include "base/files/scoped_temp_dir.h"
diff --git a/storage/browser/fileapi/file_writer_impl_unittest.cc b/storage/browser/fileapi/file_writer_impl_unittest.cc
index 6c174f65..e7162cfb5 100644
--- a/storage/browser/fileapi/file_writer_impl_unittest.cc
+++ b/storage/browser/fileapi/file_writer_impl_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <limits>
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/guid.h"
 #include "base/test/bind_test_util.h"
diff --git a/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc b/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc
index 477535a1..d10ccca 100644
--- a/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc
+++ b/storage/browser/fileapi/sandbox_file_system_backend_delegate.cc
@@ -11,6 +11,7 @@
 #include <vector>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/files/file_util.h"
 #include "base/macros.h"
diff --git a/storage/browser/quota/quota_manager.h b/storage/browser/quota/quota_manager.h
index fab72bd..5fb9468e 100644
--- a/storage/browser/quota/quota_manager.h
+++ b/storage/browser/quota/quota_manager.h
@@ -24,6 +24,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
 #include "base/stl_util.h"
+#include "base/timer/timer.h"
 #include "storage/browser/quota/quota_callbacks.h"
 #include "storage/browser/quota/quota_client.h"
 #include "storage/browser/quota/quota_database.h"
diff --git a/testing/android/junit/java/src/org/chromium/testing/local/LocalRobolectricTestRunner.java b/testing/android/junit/java/src/org/chromium/testing/local/LocalRobolectricTestRunner.java
index 598c22d..210a4d56 100644
--- a/testing/android/junit/java/src/org/chromium/testing/local/LocalRobolectricTestRunner.java
+++ b/testing/android/junit/java/src/org/chromium/testing/local/LocalRobolectricTestRunner.java
@@ -16,13 +16,16 @@
     public static final int DEFAULT_SDK = 26;
     private static final String DEFAULT_PACKAGE_NAME = "org.robolectric.default";
 
-    public LocalRobolectricTestRunner(Class<?> testClass) throws InitializationError {
-        super(testClass);
+    static {
         // Setting robolectric.offline which tells Robolectric to look for runtime dependency
         // JARs from a local directory and to not download them from Maven.
         System.setProperty("robolectric.offline", "true");
     }
 
+    public LocalRobolectricTestRunner(Class<?> testClass) throws InitializationError {
+        super(testClass);
+    }
+
     @Override
     protected Config buildGlobalConfig() {
         String packageName =
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 072c2e33..695a26a 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -3937,6 +3937,57 @@
           "script": "//testing/trigger_scripts/chromeos_device_trigger.py"
         }
       }
+    ],
+    "isolated_scripts": [
+      {
+        "args": [
+          "--browser=cros-chrome",
+          "--remote=variable_chromeos_device_hostname",
+          "--xvfb"
+        ],
+        "isolate_name": "telemetry_perf_unittests",
+        "name": "telemetry_perf_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_type": "kevin",
+              "os": "ChromeOS",
+              "pool": "chrome-cros-dut"
+            }
+          ],
+          "idempotent": false,
+          "shards": 6
+        },
+        "trigger_script": {
+          "script": "//testing/trigger_scripts/chromeos_device_trigger.py"
+        }
+      },
+      {
+        "args": [
+          "--browser=cros-chrome",
+          "--remote=variable_chromeos_device_hostname",
+          "--jobs=1",
+          "--retry-limit=1"
+        ],
+        "isolate_name": "telemetry_unittests",
+        "name": "telemetry_unittests",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "device_type": "kevin",
+              "os": "ChromeOS",
+              "pool": "chrome-cros-dut"
+            }
+          ],
+          "idempotent": false,
+          "shards": 12
+        },
+        "trigger_script": {
+          "script": "//testing/trigger_scripts/chromeos_device_trigger.py"
+        }
+      }
     ]
   },
   "fuchsia-fyi-arm64-rel": {
diff --git a/testing/buildbot/chromium.swarm.json b/testing/buildbot/chromium.swarm.json
index 528b87c..b9c08f3 100644
--- a/testing/buildbot/chromium.swarm.json
+++ b/testing/buildbot/chromium.swarm.json
@@ -683,55 +683,6 @@
       }
     ]
   },
-  "ChromeOS Swarm": {
-    "additional_compile_targets": [
-      "chromiumos_preflight"
-    ],
-    "isolated_scripts": [
-      {
-        "args": [
-          "--browser=cros-chrome",
-          "--remote=variable_chromeos_device_hostname",
-          "--xvfb"
-        ],
-        "isolate_name": "telemetry_perf_unittests",
-        "name": "telemetry_perf_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "kevin-signed-mpkeys",
-              "os": "ChromeOS"
-            }
-          ],
-          "hard_timeout": 960,
-          "idempotent": false,
-          "shards": 12
-        }
-      },
-      {
-        "args": [
-          "--browser=cros-chrome",
-          "--remote=variable_chromeos_device_hostname",
-          "--jobs=1",
-          "--extra-browser-args=--disable-gpu"
-        ],
-        "isolate_name": "telemetry_unittests",
-        "name": "telemetry_unittests",
-        "swarming": {
-          "can_use_on_swarming_builders": true,
-          "dimension_sets": [
-            {
-              "device_type": "kevin-signed-mpkeys",
-              "os": "ChromeOS"
-            }
-          ],
-          "idempotent": false,
-          "shards": 4
-        }
-      }
-    ]
-  },
   "Linux Swarm": {
     "gtest_tests": [
       {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 1b150b5..372cf4bc 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -506,27 +506,27 @@
       'telemetry_perf_unittests': {
         'args': [
           '--browser=cros-chrome',
+          # The magic hostname that resolves to a CrOS device in the test lab.
           '--remote=variable_chromeos_device_hostname',
           '--xvfb',
         ],
         'swarming': {
-          'hard_timeout': 960,
           'idempotent': False,  # https://crbug.com/549140
-          'shards': 12,
+          'shards': 6,
         },
       },
       'telemetry_unittests': {
         'args': [
           '--browser=cros-chrome',
+          # The magic hostname that resolves to a CrOS device in the test lab.
           '--remote=variable_chromeos_device_hostname',
           '--jobs=1',
-          # Disable GPU compositing, telemetry_unittests runs on VMs.
-          # https://crbug.com/871955
-          '--extra-browser-args=--disable-gpu',
+          # TODO(crbug.com/866062): Use the default retry limit.
+          '--retry-limit=1',
         ],
         'swarming': {
           'idempotent': False,  # https://crbug.com/549140
-          'shards': 4,
+          'shards': 12,
         },
       },
     },
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 1930dc2..9163f208 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -1419,6 +1419,7 @@
         },
         'test_suites': {
           'gtest_tests': 'chromeos_device_kevin_tests',
+          'isolated_scripts': 'chromeos_remote_device_isolated_tests',
         },
         'os_type': 'chromeos',
       },
@@ -3294,22 +3295,6 @@
         },
         'os_type': 'android',
       },
-      'ChromeOS Swarm': {
-        'additional_compile_targets': [
-          'chromiumos_preflight',
-        ],
-        'test_suites': {
-          'isolated_scripts': 'chromeos_remote_device_isolated_tests',
-        },
-        'swarming': {
-          'dimension_sets': [
-            {
-              'device_type': 'kevin-signed-mpkeys',
-              'os': 'ChromeOS',
-            }
-          ],
-        },
-      },
       'Linux Swarm': {
         'test_suites': {
            'gtest_tests': 'chromium_swarm_linux_gtests',
diff --git a/third_party/blink/public/platform/web_url_loader_client.h b/third_party/blink/public/platform/web_url_loader_client.h
index de1a83b5..8e66379 100644
--- a/third_party/blink/public/platform/web_url_loader_client.h
+++ b/third_party/blink/public/platform/web_url_loader_client.h
@@ -125,14 +125,6 @@
                        int64_t total_encoded_body_length,
                        int64_t total_decoded_body_length) {}
 
-  // This is a callback set for navigation requests, which should be called
-  // to continue the navigation after starting the main resource request.
-  // This is a workaround for using WebURLLoader machinery for navigation
-  // requests which did already happen in the browser process.
-  // TODO(dgozman): remove this once we no longer use WebURLLoader for
-  // the main resource and instead pass the data directly to CommitNavigation.
-  virtual void SetContinueNavigationRequestCallback(base::OnceClosure) {}
-
   // Value passed to DidFinishLoading when total encoded data length isn't
   // known.
   static const int64_t kUnknownEncodedDataLength = -1;
diff --git a/third_party/blink/public/platform/web_url_loader_mock_factory.h b/third_party/blink/public/platform/web_url_loader_mock_factory.h
index 85a0710..839e94c2 100644
--- a/third_party/blink/public/platform/web_url_loader_mock_factory.h
+++ b/third_party/blink/public/platform/web_url_loader_mock_factory.h
@@ -14,6 +14,7 @@
 
 namespace blink {
 
+struct WebNavigationParams;
 class WebURL;
 class WebURLLoader;
 class WebURLResponse;
@@ -76,6 +77,9 @@
   // Set a delegate that allows callbacks for all WebURLLoaderClients to be
   // intercepted.
   virtual void SetLoaderDelegate(WebURLLoaderTestDelegate*) = 0;
+
+  // Fills navigation params by loading a mocked response.
+  virtual void FillNavigationParamsResponse(WebNavigationParams*) = 0;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/platform/web_url_loader_test_delegate.h b/third_party/blink/public/platform/web_url_loader_test_delegate.h
index 5386c63..ea7dd986 100644
--- a/third_party/blink/public/platform/web_url_loader_test_delegate.h
+++ b/third_party/blink/public/platform/web_url_loader_test_delegate.h
@@ -10,6 +10,7 @@
 
 namespace blink {
 
+struct WebNavigationParams;
 class WebURLResponse;
 class WebURLLoaderClient;
 struct WebURLError;
@@ -38,6 +39,14 @@
                                 int64_t total_encoded_data_length,
                                 int64_t total_encoded_body_length,
                                 int64_t total_decoded_body_length);
+  // Default implementation will load mocked url and fill in redirects,
+  // response and body loader.
+  // To override default behavior, fill in response (always), redirects
+  // (if needed) and body loader (if not empty, see WebNavigationParams)
+  // and return true.
+  virtual bool FillNavigationParamsResponse(WebNavigationParams*) {
+    return false;
+  }
 };
 
 }  // namespace blink
diff --git a/third_party/blink/public/platform/web_url_request.h b/third_party/blink/public/platform/web_url_request.h
index 771bfd0..3aba024 100644
--- a/third_party/blink/public/platform/web_url_request.h
+++ b/third_party/blink/public/platform/web_url_request.h
@@ -281,9 +281,6 @@
   BLINK_PLATFORM_EXPORT Priority GetPriority() const;
   BLINK_PLATFORM_EXPORT void SetPriority(Priority);
 
-  BLINK_PLATFORM_EXPORT bool WasDiscarded() const;
-  BLINK_PLATFORM_EXPORT void SetWasDiscarded(bool);
-
   // https://wicg.github.io/cors-rfc1918/#external-request
   BLINK_PLATFORM_EXPORT bool IsExternalRequest() const;
 
@@ -315,10 +312,6 @@
   BLINK_PLATFORM_EXPORT const base::Optional<base::UnguessableToken>&
   GetDevToolsToken() const;
 
-  // Set the applicable Origin Policy.
-  BLINK_PLATFORM_EXPORT const WebString GetOriginPolicy() const;
-  BLINK_PLATFORM_EXPORT void SetOriginPolicy(const WebString& policy);
-
   // Remembers 'X-Requested-With' header value. Blink should not set this header
   // value until CORS checks are done to avoid running checks even against
   // headers that are internally set.
diff --git a/third_party/blink/public/web/web_document_loader.h b/third_party/blink/public/web/web_document_loader.h
index 2cffdc8..15aed73 100644
--- a/third_party/blink/public/web/web_document_loader.h
+++ b/third_party/blink/public/web/web_document_loader.h
@@ -46,7 +46,6 @@
 class WebDocumentSubresourceFilter;
 class WebServiceWorkerNetworkProvider;
 class WebURL;
-class WebURLRequest;
 class WebURLResponse;
 template <typename T>
 class WebVector;
@@ -89,12 +88,6 @@
   // Returns the referrer policy of the request corresponding to this load.
   virtual network::mojom::ReferrerPolicy GetReferrerPolicy() const = 0;
 
-  // Returns the request corresponding to this datasource.  It may
-  // include additional request headers added by WebKit that were not
-  // present in the original request.  This request may also correspond
-  // to a location specified by a redirect that was followed.
-  virtual const WebURLRequest& GetRequest() const = 0;
-
   // Returns the response associated with this datasource.
   virtual const WebURLResponse& GetResponse() const = 0;
 
diff --git a/third_party/blink/public/web/web_navigation_params.h b/third_party/blink/public/web/web_navigation_params.h
index 1f63b1c..ff81092 100644
--- a/third_party/blink/public/web/web_navigation_params.h
+++ b/third_party/blink/public/web/web_navigation_params.h
@@ -12,16 +12,21 @@
 #include "base/time/time.h"
 #include "base/unguessable_token.h"
 #include "mojo/public/cpp/system/message_pipe.h"
+#include "services/network/public/mojom/referrer_policy.mojom-shared.h"
+#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-shared.h"
 #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
 #include "third_party/blink/public/platform/web_common.h"
 #include "third_party/blink/public/platform/web_content_security_policy.h"
 #include "third_party/blink/public/platform/web_content_security_policy_struct.h"
 #include "third_party/blink/public/platform/web_data.h"
+#include "third_party/blink/public/platform/web_http_body.h"
+#include "third_party/blink/public/platform/web_navigation_body_loader.h"
 #include "third_party/blink/public/platform/web_security_origin.h"
 #include "third_party/blink/public/platform/web_source_location.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_url.h"
 #include "third_party/blink/public/platform/web_url_request.h"
+#include "third_party/blink/public/platform/web_url_response.h"
 #include "third_party/blink/public/web/web_form_element.h"
 #include "third_party/blink/public/web/web_frame_load_type.h"
 #include "third_party/blink/public/web/web_history_item.h"
@@ -38,6 +43,7 @@
 
 class KURL;
 class SharedBuffer;
+class WebDocumentLoader;
 
 // This structure holds all information collected by Blink when
 // navigation is being initiated.
@@ -141,6 +147,13 @@
       base::span<const char> html,
       const WebURL& base_url);
 
+  // Shortcut for loading an error page html.
+  static std::unique_ptr<WebNavigationParams> CreateForErrorPage(
+      WebDocumentLoader* failed_document_loader,
+      base::span<const char> html,
+      const WebURL& base_url,
+      const WebURL& unreachable_url);
+
 #if INSIDE_BLINK
   // Shortcut for loading html with "text/html" mime type and "UTF8" encoding.
   static std::unique_ptr<WebNavigationParams> CreateWithHTMLBuffer(
@@ -148,23 +161,85 @@
       const KURL& base_url);
 #endif
 
-  // The request to navigate to. Its URL indicates the security origin
-  // and will be used as a base URL to resolve links in the committed document.
-  // TODO(dgozman): do we actually need a request here? Maybe just a URL?
-  WebURLRequest request;
+  // This block defines the request used to load the main resource
+  // for this navigation.
+
+  // This URL indicates the security origin and will be used as a base URL
+  // to resolve links in the committed document.
+  WebURL url;
+  // The http method (if any) used to load the main resource.
+  WebString http_method;
+  // The cache mode used to load the main resource.
+  // TODO(dgozman): remove this, we are not really using it.
+  mojom::FetchCacheMode cache_mode = mojom::FetchCacheMode::kDefault;
+  // The referrer string and policy used to load the main resource.
+  WebString referrer;
+  network::mojom::ReferrerPolicy referrer_policy =
+      network::mojom::ReferrerPolicy::kDefault;
+  // The http body of the request used to load the main resource, if any.
+  WebHTTPBody http_body;
+  // The http content type of the request used to load the main resource, if
+  // any.
+  WebString http_content_type;
+  // The origin policy for this navigation.
+  WebString origin_policy;
+  // The origin of the request used to load the main resource, specified at
+  // https://fetch.spec.whatwg.org/#concept-request-origin. Can be null.
+  // TODO(dgozman,nasko): we shouldn't need both this and |origin_to_commit|.
+  WebSecurityOrigin requestor_origin;
+  // If non-null, used as a URL which we weren't able to load. For example,
+  // history item will contain this URL instead of request's URL.
+  // This URL can be retrieved through WebDocumentLoader::UnreachableURL.
+  WebURL unreachable_url;
+
+  // This block defines the document content. The alternatives in the order
+  // of precedence are:
+  // 1. If |data| is supplied, it is used as document content.
+  // 2. If url loads as an empty document (according to
+  //    WebDocumentLoader::WillLoadUrlAsEmpty), the document will be empty.
+  // 3. If loading an iframe of mhtml archive, the document will be
+  //    retrieved from the archive.
+  // 4. Otherwise, provided redirects and response are used to construct
+  //    the final response.
+  //   4a. If body loader is present, it will be used to fetch the content.
+  //   4b. If body loader is missing, but url is a data url, it will be
+  //       decoded and used as response and document content.
+  //   4c. If decoding data url fails, or url is not a data url, the
+  //       navigation will fail.
+
+  struct RedirectInfo {
+    // New base url after redirect.
+    WebURL new_url;
+    // Http method used for redirect.
+    WebString new_http_method;
+    // New referrer string and policy used for redirect.
+    WebString new_referrer;
+    network::mojom::ReferrerPolicy new_referrer_policy;
+    // Redirect response itself.
+    // TODO(dgozman): we only use this response for navigation timings.
+    // Perhaps, we can just get rid of it.
+    WebURLResponse redirect_response;
+  };
+  // Redirects which happened while fetching the main resource.
+  // TODO(dgozman): we are only interested in the final values instead of
+  // all information about redirects.
+  WebVector<RedirectInfo> redirects;
+  // The final response for the main resource. This will be used to determine
+  // the type of resulting document.
+  WebURLResponse response;
+  // The body loader which allows to retrieve the response body when available.
+  std::unique_ptr<WebNavigationBodyLoader> body_loader;
 
   // If the data is non null, it will be used as a main resource content
-  // instead of loading the request above.
+  // instead of redirects, response and body loader.
   WebData data;
   // Specifies the mime type of the raw data. Must be set together with the
   // data.
   WebString mime_type;
   // The encoding of the raw data. Must be set together with the data.
   WebString text_encoding;
-  // If non-null, used as a URL which we weren't able to load. For example,
-  // history item will contain this URL instead of request's URL.
-  // This URL can be retrieved through WebDocumentLoader::UnreachableURL.
-  WebURL unreachable_url;
+
+  // This block defines the type of the navigation.
 
   // The load type. See WebFrameLoadType for definition.
   WebFrameLoadType frame_load_type = WebFrameLoadType::kStandard;
@@ -173,20 +248,30 @@
   // Whether this navigation is a result of client redirect.
   bool is_client_redirect = false;
 
+  // Miscellaneous parameters.
+
   // The origin in which a navigation should commit. When provided, Blink
   // should use this origin directly and not compute locally the new document
   // origin.
   WebSecurityOrigin origin_to_commit;
-
   // The devtools token for this navigation. See DocumentLoader
   // for details.
   base::UnguessableToken devtools_navigation_token;
   // Known timings related to navigation. If the navigation has
   // started in another process, timings are propagated from there.
   WebNavigationTimings navigation_timings;
-  // Whether this navigation had a transient user activation.
+  // Indicates that the frame was previously discarded.
+  // was_discarded is exposed on Document after discard, see:
+  // https://github.com/WICG/web-lifecycle
+  bool was_discarded = false;
+  // Whether this navigation had a transient user activation
+  // when inititated.
+  bool had_transient_activation = false;
+  // Whether this navigation has a sticky user activation flag.
   bool is_user_activated = false;
-
+  // The previews state which should be used for this navigation.
+  WebURLRequest::PreviewsState previews_state =
+      WebURLRequest::kPreviewsUnspecified;
   // The service worker network provider to be used in the new
   // document.
   std::unique_ptr<blink::WebServiceWorkerNetworkProvider>
diff --git a/third_party/blink/renderer/DEPS b/third_party/blink/renderer/DEPS
index 5a05977..96e4e17 100644
--- a/third_party/blink/renderer/DEPS
+++ b/third_party/blink/renderer/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
     "+base/auto_reset.h",
     "+base/bind.h",
+    "+base/bind_helpers.h",
     "+base/bit_cast.h",
     "+base/callback.h",
     "+base/callback_forward.h",
diff --git a/third_party/blink/renderer/controller/tests/run_all_tests.cc b/third_party/blink/renderer/controller/tests/run_all_tests.cc
index df0a6bc63..7e8bb56 100644
--- a/third_party/blink/renderer/controller/tests/run_all_tests.cc
+++ b/third_party/blink/renderer/controller/tests/run_all_tests.cc
@@ -29,6 +29,7 @@
  */
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/run_loop.h"
 #include "base/test/launcher/unit_test_launcher.h"
 #include "base/test/test_suite.h"
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 7575b25..9002c20 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1829,6 +1829,7 @@
     "dom/tree_scope_adopter_test.cc",
     "dom/tree_scope_test.cc",
     "dom/user_gesture_indicator_test.cc",
+    "dom/weak_identifier_map_test.cc",
     "dom/whitespace_attacher_test.cc",
     "editing/caret_display_item_client_test.cc",
     "editing/finder/text_finder_test.cc",
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.cc b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
index 0fe7c25..bc4689e7 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context.cc
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context.cc
@@ -163,12 +163,9 @@
   if (state_ == kUnlocked)
     return GetRejectedPromise(script_state);
 
-  // If we have a resolver, we must be committing already, just return the same
-  // promise.
-  if (commit_resolver_) {
-    DCHECK(state_ == kCommitting) << state_;
+  // If we're already committing then return the promise.
+  if (state_ == kCommitting)
     return commit_resolver_->Promise();
-  }
 
   // Now that we've explicitly been requested to commit, we have cancel the
   // timeout task.
@@ -179,12 +176,42 @@
   // together will still wait until the lifecycle is clean before resolving any
   // of the promises.
   DCHECK_NE(state_, kCommitting);
-  commit_resolver_ = ScriptPromiseResolver::Create(script_state);
+  // We might already have a resolver if we called updateAndCommit() before
+  // this.
+  if (!commit_resolver_)
+    commit_resolver_ = ScriptPromiseResolver::Create(script_state);
   auto promise = commit_resolver_->Promise();
   StartCommit();
   return promise;
 }
 
+ScriptPromise DisplayLockContext::updateAndCommit(ScriptState* script_state) {
+  // Reject if we're unlocked.
+  if (state_ == kUnlocked)
+    return GetRejectedPromise(script_state);
+
+  // If we're in a state where a co-operative update doesn't make sense (e.g. we
+  // haven't acquired the lock, or we're already sync committing), then do
+  // whatever commit() would do.
+  if (state_ == kPendingAcquire || state_ == kCommitting ||
+      !element_->isConnected()) {
+    return commit(script_state);
+  }
+
+  // If we have a commit resolver already, return it.
+  if (commit_resolver_) {
+    // We must be in a second call to updateAndCommit(), meaning that we're in
+    // the kUpdating state with a commit_resolver_.
+    DCHECK_EQ(state_, kUpdating);
+    return commit_resolver_->Promise();
+  }
+
+  CancelTimeoutTask();
+  commit_resolver_ = ScriptPromiseResolver::Create(script_state);
+  StartUpdateIfNeeded();
+  return commit_resolver_->Promise();
+}
+
 void DisplayLockContext::FinishUpdateResolver(ResolverState state) {
   FinishResolver(&update_resolver_, state);
 }
@@ -240,10 +267,11 @@
   // unexpected behavior. By rejecting the promise, the behavior can be detected
   // by script.
   if (!ElementSupportsDisplayLocking()) {
+    bool should_stay_locked = state_ == kUpdating && !commit_resolver_;
     FinishUpdateResolver(kReject);
     FinishCommitResolver(kReject);
     FinishAcquireResolver(kReject);
-    state_ = state_ == kUpdating ? kLocked : kUnlocked;
+    state_ = should_stay_locked ? kLocked : kUnlocked;
     return;
   }
 
@@ -300,16 +328,17 @@
 }
 
 void DisplayLockContext::DidAttachLayoutTree() {
-  if (state_ == kUnlocked)
+  if (state_ >= kUnlocked)
     return;
 
   // Note that although we checked at style recalc time that the element has
   // "contain: style layout", it might not actually apply the containment at the
   // layout object level. This confirms that containment should apply.
   if (!ElementSupportsDisplayLocking()) {
+    bool should_stay_locked = state_ == kUpdating && !commit_resolver_;
     FinishUpdateResolver(kReject);
     FinishCommitResolver(kReject);
-    state_ = state_ == kUpdating ? kLocked : kUnlocked;
+    state_ = should_stay_locked ? kLocked : kUnlocked;
   }
 }
 
@@ -546,7 +575,13 @@
   if (!element_ || !element_->isConnected()) {
     FinishUpdateResolver(kReject);
     update_budget_.reset();
-    state_ = kLocked;
+
+    if (commit_resolver_) {
+      FinishCommitResolver(kReject);
+      state_ = kUnlocked;
+    } else {
+      state_ = kLocked;
+    }
     return;
   }
 
@@ -563,6 +598,17 @@
   FinishUpdateResolver(kResolve);
   update_budget_.reset();
   state_ = kLocked;
+
+  if (commit_resolver_) {
+    // Schedule a commit to run. Note that we can't call StartCommit directly
+    // here, since we're in the lifecycle updates right now and the code that
+    // runs after may depend on having clean layout state, which StartCommit
+    // might dirty.
+    GetExecutionContext()
+        ->GetTaskRunner(TaskType::kMiscPlatformAPI)
+        ->PostTask(FROM_HERE, WTF::Bind(&DisplayLockContext::StartCommit,
+                                        WrapWeakPersistent(this)));
+  }
 }
 
 void DisplayLockContext::ScheduleAnimation() {
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.h b/third_party/blink/renderer/core/display_lock/display_lock_context.h
index 3144eda..1a66026 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context.h
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context.h
@@ -46,7 +46,7 @@
     kDoNotYield,
     kStrictYieldBetweenLifecyclePhases,
     kYieldBetweenLifecyclePhases,
-    kDefault = kYieldBetweenLifecyclePhases
+    kDefault = kStrictYieldBetweenLifecyclePhases
   };
 
   // See GetScopedPendingFrameRect() for description.
@@ -95,6 +95,7 @@
   ScriptPromise acquire(ScriptState*, DisplayLockOptions*);
   ScriptPromise update(ScriptState*);
   ScriptPromise commit(ScriptState*);
+  ScriptPromise updateAndCommit(ScriptState*);
 
   // Lifecycle observation / state functions.
   bool ShouldStyle() const;
diff --git a/third_party/blink/renderer/core/display_lock/display_lock_context.idl b/third_party/blink/renderer/core/display_lock/display_lock_context.idl
index 2e34af83b..592208e 100644
--- a/third_party/blink/renderer/core/display_lock/display_lock_context.idl
+++ b/third_party/blink/renderer/core/display_lock/display_lock_context.idl
@@ -16,4 +16,8 @@
   // necessary lifecycle phases.
   // Returns a promise that resolves when the commit is finished.
   [CallWith=ScriptState] Promise<any> commit();
+
+  // Causes co-operative updates to happen, followed by a commit.
+  // Returns a promise that resolves when the commit is finished.
+  [CallWith=ScriptState] Promise<any> updateAndCommit();
 };
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index 9e55b4d9..df5e45e 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -5411,7 +5411,7 @@
 
 const AtomicString& Document::referrer() const {
   if (Loader())
-    return Loader()->Referrer();
+    return Loader()->GetReferrer().referrer;
   return g_null_atom;
 }
 
diff --git a/third_party/blink/renderer/core/dom/weak_identifier_map.h b/third_party/blink/renderer/core/dom/weak_identifier_map.h
index eed341b..41bbeae3 100644
--- a/third_party/blink/renderer/core/dom/weak_identifier_map.h
+++ b/third_party/blink/renderer/core/dom/weak_identifier_map.h
@@ -5,7 +5,9 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_WEAK_IDENTIFIER_MAP_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_WEAK_IDENTIFIER_MAP_H_
 
+#include <limits>
 #include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
 #include "third_party/blink/renderer/platform/wtf/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
 
@@ -14,53 +16,28 @@
 // TODO(sof): WeakIdentifierMap<> belongs (out) in wtf/, but
 // cannot until GarbageCollected<> can be used from WTF.
 
-template <typename T, typename IdentifierType, bool isGarbageCollected>
-class WeakIdentifierMapBase {
-  USING_FAST_MALLOC(WeakIdentifierMapBase);
-
- protected:
-  using ObjectToIdentifier = HashMap<T*, IdentifierType>;
-  using IdentifierToObject = HashMap<IdentifierType, T*>;
-
-  ObjectToIdentifier object_to_identifier_;
-  IdentifierToObject identifier_to_object_;
-};
-
-template <typename T, typename IdentifierType>
-class WeakIdentifierMapBase<T, IdentifierType, true>
-    : public GarbageCollected<WeakIdentifierMapBase<T, IdentifierType, true>> {
+template <typename T, typename IdentifierType = int>
+class WeakIdentifierMap final
+    : public GarbageCollected<WeakIdentifierMap<T, IdentifierType>> {
  public:
+  WeakIdentifierMap() = default;
+
   void Trace(Visitor* visitor) {
     visitor->Trace(object_to_identifier_);
     visitor->Trace(identifier_to_object_);
   }
 
- protected:
-  using ObjectToIdentifier = HeapHashMap<WeakMember<T>, IdentifierType>;
-  using IdentifierToObject = HeapHashMap<IdentifierType, WeakMember<T>>;
-
-  ObjectToIdentifier object_to_identifier_;
-  IdentifierToObject identifier_to_object_;
-};
-
-template <typename T, typename IdentifierType = int>
-class WeakIdentifierMap final
-    : public WeakIdentifierMapBase<T,
-                                   IdentifierType,
-                                   IsGarbageCollectedType<T>::value> {
- public:
   static IdentifierType Identifier(T* object) {
     IdentifierType result = Instance().object_to_identifier_.at(object);
 
     if (WTF::IsHashTraitsEmptyValue<HashTraits<IdentifierType>>(result)) {
-      result = Next();
-      Instance().Put(object, result);
+      do {
+        result = Next();
+      } while (!LIKELY(Instance().Put(object, result)));
     }
     return result;
   }
 
-  WeakIdentifierMap() = default;
-
   static T* Lookup(IdentifierType identifier) {
     return Instance().identifier_to_object_.at(identifier);
   }
@@ -69,25 +46,49 @@
     Instance().ObjectDestroyed(object);
   }
 
+  static void SetLastIdForTesting(IdentifierType i) { LastIdRef() = i; }
+
+  static size_t GetSizeForTesting() {
+    return Instance().object_to_identifier_.size();
+  }
+
  private:
   static WeakIdentifierMap<T, IdentifierType>& Instance();
 
   static IdentifierType Next() {
-    static IdentifierType last_id = 0;
-    return ++last_id;
+    // On overflow, skip negative values for signed IdentifierType, and 0 which
+    // is not a valid key in HashMap by default.
+    if (UNLIKELY(LastIdRef() == std::numeric_limits<IdentifierType>::max()))
+      LastIdRef() = 0;
+    return ++LastIdRef();
   }
 
-  void Put(T* object, IdentifierType identifier) {
-    DCHECK(object && !this->object_to_identifier_.Contains(object));
-    this->object_to_identifier_.Set(object, identifier);
-    this->identifier_to_object_.Set(identifier, object);
+  static IdentifierType& LastIdRef() {
+    static IdentifierType last_id = 0;
+    return last_id;
+  }
+
+  bool Put(T* object, IdentifierType identifier) {
+    if (!LIKELY(identifier_to_object_.insert(identifier, object).is_new_entry))
+      return false;
+    DCHECK(object && !object_to_identifier_.Contains(object));
+    object_to_identifier_.Set(object, identifier);
+    DCHECK_EQ(object_to_identifier_.size(), identifier_to_object_.size());
+    return true;
   }
 
   void ObjectDestroyed(T* object) {
-    IdentifierType identifier = this->object_to_identifier_.Take(object);
+    IdentifierType identifier = object_to_identifier_.Take(object);
     if (!WTF::IsHashTraitsEmptyValue<HashTraits<IdentifierType>>(identifier))
-      this->identifier_to_object_.erase(identifier);
+      identifier_to_object_.erase(identifier);
+    DCHECK_EQ(object_to_identifier_.size(), identifier_to_object_.size());
   }
+
+  using ObjectToIdentifier = HeapHashMap<WeakMember<T>, IdentifierType>;
+  using IdentifierToObject = HeapHashMap<IdentifierType, WeakMember<T>>;
+
+  ObjectToIdentifier object_to_identifier_;
+  IdentifierToObject identifier_to_object_;
 };
 
 #define DECLARE_WEAK_IDENTIFIER_MAP(T, ...)        \
diff --git a/third_party/blink/renderer/core/dom/weak_identifier_map_test.cc b/third_party/blink/renderer/core/dom/weak_identifier_map_test.cc
new file mode 100644
index 0000000..e43421f
--- /dev/null
+++ b/third_party/blink/renderer/core/dom/weak_identifier_map_test.cc
@@ -0,0 +1,107 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/dom/weak_identifier_map.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+
+namespace blink {
+
+class WeakIdentifierMapTest : public ::testing::Test {
+ public:
+  class TestClass final : public GarbageCollectedFinalized<TestClass> {
+   public:
+    virtual void Trace(Visitor*) {}
+  };
+
+  using TestMap = WeakIdentifierMap<TestClass>;
+
+  void SetUp() override;
+  void TearDown() override;
+
+  void CollectGarbage() {
+    ThreadState::Current()->CollectGarbage(
+        BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking,
+        BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC);
+  }
+};
+
+DECLARE_WEAK_IDENTIFIER_MAP(WeakIdentifierMapTest::TestClass);
+DEFINE_WEAK_IDENTIFIER_MAP(WeakIdentifierMapTest::TestClass);
+
+void WeakIdentifierMapTest::SetUp() {
+  EXPECT_EQ(0u, TestMap::GetSizeForTesting());
+}
+
+void WeakIdentifierMapTest::TearDown() {
+  CollectGarbage();
+  EXPECT_EQ(0u, TestMap::GetSizeForTesting());
+}
+
+TEST_F(WeakIdentifierMapTest, Basic) {
+  auto* a = MakeGarbageCollected<TestClass>();
+  auto* b = MakeGarbageCollected<TestClass>();
+
+  auto id_a = TestMap::Identifier(a);
+  EXPECT_NE(0, id_a);
+  EXPECT_EQ(id_a, TestMap::Identifier(a));
+  EXPECT_EQ(a, TestMap::Lookup(id_a));
+
+  auto id_b = TestMap::Identifier(b);
+  EXPECT_NE(0, id_b);
+  EXPECT_NE(id_a, id_b);
+  EXPECT_EQ(id_b, TestMap::Identifier(b));
+  EXPECT_EQ(b, TestMap::Lookup(id_b));
+
+  EXPECT_EQ(id_a, TestMap::Identifier(a));
+  EXPECT_EQ(a, TestMap::Lookup(id_a));
+
+  EXPECT_EQ(2u, TestMap::GetSizeForTesting());
+}
+
+TEST_F(WeakIdentifierMapTest, NotifyObjectDestroyed) {
+  auto* a = MakeGarbageCollected<TestClass>();
+  auto id_a = TestMap::Identifier(a);
+  TestMap::NotifyObjectDestroyed(a);
+  EXPECT_EQ(nullptr, TestMap::Lookup(id_a));
+
+  // Simulate that an object is newly allocated at the same address.
+  EXPECT_NE(id_a, TestMap::Identifier(a));
+}
+
+TEST_F(WeakIdentifierMapTest, GarbageCollected) {
+  auto* a = MakeGarbageCollected<TestClass>();
+  auto id_a = TestMap::Identifier(a);
+
+  a = nullptr;
+  CollectGarbage();
+  EXPECT_EQ(nullptr, TestMap::Lookup(id_a));
+}
+
+TEST_F(WeakIdentifierMapTest, UnusedID) {
+  auto* a = MakeGarbageCollected<TestClass>();
+  auto id_a = TestMap::Identifier(a);
+  EXPECT_EQ(nullptr, TestMap::Lookup(id_a + 1));
+}
+
+TEST_F(WeakIdentifierMapTest, Overflow) {
+  TestMap::SetLastIdForTesting(0);
+  auto* a = MakeGarbageCollected<TestClass>();
+  EXPECT_EQ(1, TestMap::Identifier(a));
+  EXPECT_EQ(a, TestMap::Lookup(1));
+
+  TestMap::SetLastIdForTesting(INT_MAX - 1);
+  auto* b = MakeGarbageCollected<TestClass>();
+  EXPECT_EQ(INT_MAX, TestMap::Identifier(b));
+  EXPECT_EQ(b, TestMap::Lookup(INT_MAX));
+
+  auto* c = MakeGarbageCollected<TestClass>();
+  EXPECT_EQ(2, TestMap::Identifier(c));
+  EXPECT_EQ(c, TestMap::Lookup(2));
+
+  DCHECK_EQ(3u, TestMap::GetSizeForTesting());
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/editing/inline_box_position.cc b/third_party/blink/renderer/core/editing/inline_box_position.cc
index c569a9ed..f792ee28 100644
--- a/third_party/blink/renderer/core/editing/inline_box_position.cc
+++ b/third_party/blink/renderer/core/editing/inline_box_position.cc
@@ -61,10 +61,8 @@
        next = next->NextInPreOrder(container)) {
     if (next->IsLayoutBlock())
       return nullptr;
-    if (next->IsBR()) {
-      if (!RuntimeEnabledFeatures::BidiCaretAffinityEnabled())
-        return nullptr;
-    }
+    if (next->IsBR())
+      return nullptr;
     if (IsNonTextLeafChild(next))
       return nullptr;
     if (next->IsText()) {
@@ -110,8 +108,6 @@
                                                           int caret_offset) {
   DCHECK(caret_offset == inline_box->CaretLeftmostOffset() ||
          caret_offset == inline_box->CaretRightmostOffset());
-  if (RuntimeEnabledFeatures::BidiCaretAffinityEnabled())
-    return InlineBoxPosition(inline_box, caret_offset);
   return BidiAdjustment::AdjustForCaretPositionResolution(
       InlineBoxPosition(inline_box, caret_offset));
 }
@@ -127,8 +123,6 @@
   DCHECK_EQ(caret_offset, box.CaretMaxOffset());
   if (affinity == TextAffinity::kUpstream)
     return true;
-  if (RuntimeEnabledFeatures::BidiCaretAffinityEnabled())
-    return false;
   return box.NextLeafChild() && box.NextLeafChild()->IsLineBreak();
 }
 
@@ -142,37 +136,13 @@
   InlineBox* inline_box = nullptr;
   InlineTextBox* candidate = nullptr;
 
-  // Used only with bidi caret affinity enabled, in which case, we may receive
-  // positions like "foo |   CBA"/downstream, which should be resolved at "|CBA"
-  // instead of "foo |".
-  InlineTextBox* closest_out_of_range_box = nullptr;
-
   for (InlineTextBox* box : text_layout_object->TextBoxes()) {
     int caret_min_offset = box->CaretMinOffset();
     int caret_max_offset = box->CaretMaxOffset();
 
     if (caret_offset < caret_min_offset || caret_offset > caret_max_offset ||
         (caret_offset == caret_max_offset && box->IsLineBreak())) {
-      if (!RuntimeEnabledFeatures::BidiCaretAffinityEnabled())
         continue;
-      // For downstream, find the closest box starting after |caret_offset|.
-      if (affinity == TextAffinity::kDownstream) {
-        if (caret_offset >= caret_min_offset)
-          continue;
-        if (!closest_out_of_range_box ||
-            caret_min_offset < closest_out_of_range_box->CaretMinOffset()) {
-          closest_out_of_range_box = box;
-        }
-        continue;
-      }
-      // For upstream, find the closest box ending before |caret_offset|.
-      if (caret_offset <= caret_max_offset)
-        continue;
-      if (!closest_out_of_range_box ||
-          caret_max_offset > closest_out_of_range_box->CaretMaxOffset()) {
-        closest_out_of_range_box = box;
-      }
-      continue;
     }
 
     if (caret_offset > caret_min_offset && caret_offset < caret_max_offset)
@@ -186,23 +156,6 @@
     candidate = box;
   }
 
-  if (!inline_box && closest_out_of_range_box) {
-    if (caret_offset < closest_out_of_range_box->CaretMinOffset()) {
-      DCHECK_EQ(affinity, TextAffinity::kDownstream);
-      return InlineBoxPosition(closest_out_of_range_box,
-                               closest_out_of_range_box->CaretMinOffset());
-    }
-    DCHECK_GT(caret_offset, closest_out_of_range_box->CaretMaxOffset());
-    // When the input is upstream after a line break, we should try to find a
-    // caret position in the next line instead of resolving here.
-    if (!closest_out_of_range_box->IsLineBreak()) {
-      DCHECK_EQ(affinity, TextAffinity::kUpstream);
-      return InlineBoxPosition(closest_out_of_range_box,
-                               closest_out_of_range_box->CaretMaxOffset());
-    }
-    // No proper out-of-range box to use. Fall through.
-  }
-
   // TODO(editing-dev): The fixup below seems hacky. It may also be incorrect in
   // non-ltr text. Make it saner.
   if (candidate && candidate == text_layout_object->LastTextBox() &&
diff --git a/third_party/blink/renderer/core/editing/inline_box_traversal.cc b/third_party/blink/renderer/core/editing/inline_box_traversal.cc
index 5a69889e..8e7d6bd 100644
--- a/third_party/blink/renderer/core/editing/inline_box_traversal.cc
+++ b/third_party/blink/renderer/core/editing/inline_box_traversal.cc
@@ -607,18 +607,25 @@
     DCHECK(visible_base.IsValid());
     DCHECK(visible_extent.IsValid());
 
-    RenderedPosition base = RenderedPosition::Create(visible_base);
-    RenderedPosition extent = RenderedPosition::Create(visible_extent);
-
     const SelectionInFlatTree& unchanged_selection =
         SelectionInFlatTree::Builder()
             .SetBaseAndExtent(visible_base.DeepEquivalent(),
                               visible_extent.DeepEquivalent())
             .Build();
 
+    if (RuntimeEnabledFeatures::BidiCaretAffinityEnabled()) {
+      if (NGInlineFormattingContextOf(visible_base.DeepEquivalent()) ||
+          NGInlineFormattingContextOf(visible_extent.DeepEquivalent()))
+        return unchanged_selection;
+    }
+
+    RenderedPosition base = RenderedPosition::Create(visible_base);
+    RenderedPosition extent = RenderedPosition::Create(visible_extent);
+
     if (base.IsNull() || extent.IsNull() || base == extent ||
-        (!base.AtBidiBoundary() && !extent.AtBidiBoundary()))
+        (!base.AtBidiBoundary() && !extent.AtBidiBoundary())) {
       return unchanged_selection;
+    }
 
     if (base.AtBidiBoundary()) {
       if (ShouldAdjustBaseAtBidiBoundary(base, extent)) {
@@ -718,6 +725,7 @@
     static BidiBoundaryType GetPotentialBidiBoundaryType(
         const NGCaretPosition& caret_position) {
       DCHECK(!caret_position.IsNull());
+      DCHECK(!RuntimeEnabledFeatures::BidiCaretAffinityEnabled());
       if (!IsAtFragmentStart(caret_position) &&
           !IsAtFragmentEnd(caret_position))
         return BidiBoundaryType::kNotBoundary;
@@ -851,7 +859,6 @@
 
 InlineBoxPosition BidiAdjustment::AdjustForCaretPositionResolution(
     const InlineBoxPosition& caret_position) {
-  DCHECK(!RuntimeEnabledFeatures::BidiCaretAffinityEnabled());
   const AbstractInlineBoxAndSideAffinity unadjusted(caret_position);
   const AbstractInlineBoxAndSideAffinity adjusted =
       unadjusted.AtLeftSide()
@@ -877,7 +884,6 @@
 
 InlineBoxPosition BidiAdjustment::AdjustForHitTest(
     const InlineBoxPosition& caret_position) {
-  DCHECK(!RuntimeEnabledFeatures::BidiCaretAffinityEnabled());
   const AbstractInlineBoxAndSideAffinity unadjusted(caret_position);
   const AbstractInlineBoxAndSideAffinity adjusted =
       unadjusted.AtLeftSide()
@@ -900,7 +906,6 @@
 SelectionInFlatTree BidiAdjustment::AdjustForRangeSelection(
     const VisiblePositionInFlatTree& base,
     const VisiblePositionInFlatTree& extent) {
-  DCHECK(!RuntimeEnabledFeatures::BidiCaretAffinityEnabled());
   return RangeSelectionAdjuster::AdjustFor(base, extent);
 }
 
diff --git a/third_party/blink/renderer/core/editing/selection_controller.cc b/third_party/blink/renderer/core/editing/selection_controller.cc
index a380f8b..bc2d7aff 100644
--- a/third_party/blink/renderer/core/editing/selection_controller.cc
+++ b/third_party/blink/renderer/core/editing/selection_controller.cc
@@ -796,8 +796,7 @@
   const VisiblePositionInFlatTree& extent =
       CreateVisiblePosition(new_selection.Extent());
   const SelectionInFlatTree& adjusted_selection =
-      (!RuntimeEnabledFeatures::BidiCaretAffinityEnabled() &&
-       endpoints_adjustment_mode == kAdjustEndpointsAtBidiBoundary)
+      endpoints_adjustment_mode == kAdjustEndpointsAtBidiBoundary
           ? BidiAdjustment::AdjustForRangeSelection(base, extent)
           : SelectionInFlatTree::Builder()
                 .SetBaseAndExtent(base.DeepEquivalent(),
diff --git a/third_party/blink/renderer/core/editing/selection_modifier_character.cc b/third_party/blink/renderer/core/editing/selection_modifier_character.cc
index 8bf4ba34..9167cd75 100644
--- a/third_party/blink/renderer/core/editing/selection_modifier_character.cc
+++ b/third_party/blink/renderer/core/editing/selection_modifier_character.cc
@@ -33,6 +33,7 @@
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/core/editing/inline_box_position.h"
 #include "third_party/blink/renderer/core/editing/inline_box_traversal.h"
+#include "third_party/blink/renderer/core/editing/ng_flat_tree_shorthands.h"
 #include "third_party/blink/renderer/core/editing/visible_position.h"
 #include "third_party/blink/renderer/core/editing/visible_units.h"
 #include "third_party/blink/renderer/core/layout/api/line_layout_api_shim.h"
@@ -526,11 +527,9 @@
                                                       start_position));
   }
 
-  // TODO(xiaochengh): The double pointer pattern below is confusing and
-  // cumbersome, but necessary for now. Make it easier.
-  std::unique_ptr<NGOffsetMapping> mapping_storage;
+  DCHECK(context->IsLayoutNGBlockFlow());
   const NGOffsetMapping* mapping =
-      NGInlineNode::GetOffsetMapping(context, &mapping_storage);
+      NGInlineNode::GetOffsetMapping(context, nullptr);
   DCHECK(mapping);
 
   const base::Optional<unsigned> start_offset =
@@ -567,7 +566,8 @@
   DCHECK(visible_position.IsValid()) << visible_position;
 
   VisiblePositionTemplate<Strategy> result;
-  if (!RuntimeEnabledFeatures::BidiCaretAffinityEnabled()) {
+  if (!RuntimeEnabledFeatures::BidiCaretAffinityEnabled() ||
+      !NGInlineFormattingContextOf(visible_position.DeepEquivalent())) {
     const PositionTemplate<Strategy> pos =
         TraverseInternalAlgorithm<Strategy, Traversal>(visible_position);
     // TODO(yosin) Why can't we move left from the last position in a tree?
diff --git a/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc b/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc
index 4f406129..24f8140 100644
--- a/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc
+++ b/third_party/blink/renderer/core/editing/spellcheck/spell_checker.cc
@@ -595,10 +595,6 @@
   GetFrame().GetDocument()->Markers().RemoveMarkersInRange(range, marker_types);
 }
 
-void SpellChecker::CancelCheck() {
-  spell_check_requester_->CancelCheck();
-}
-
 void SpellChecker::DidAttachDocument(Document* document) {
   idle_spell_check_controller_->DidAttachDocument(document);
 }
diff --git a/third_party/blink/renderer/core/editing/spellcheck/spell_checker.h b/third_party/blink/renderer/core/editing/spellcheck/spell_checker.h
index a332ac2..80523ac 100644
--- a/third_party/blink/renderer/core/editing/spellcheck/spell_checker.h
+++ b/third_party/blink/renderer/core/editing/spellcheck/spell_checker.h
@@ -81,7 +81,6 @@
   bool SelectionStartHasMarkerFor(DocumentMarker::MarkerType,
                                   int from,
                                   int length) const;
-  void CancelCheck();
 
   // Exposed for testing and idle time spell checker
   SpellCheckRequester& GetSpellCheckRequester() const {
diff --git a/third_party/blink/renderer/core/editing/visible_position.cc b/third_party/blink/renderer/core/editing/visible_position.cc
index eceeae9..46f55324 100644
--- a/third_party/blink/renderer/core/editing/visible_position.cc
+++ b/third_party/blink/renderer/core/editing/visible_position.cc
@@ -31,7 +31,7 @@
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/text.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
-#include "third_party/blink/renderer/core/editing/local_caret_rect.h"
+#include "third_party/blink/renderer/core/editing/ng_flat_tree_shorthands.h"
 #include "third_party/blink/renderer/core/editing/text_affinity.h"
 #include "third_party/blink/renderer/core/editing/visible_units.h"
 #include "third_party/blink/renderer/core/html/html_element.h"
@@ -93,7 +93,8 @@
   if (position_with_affinity.Affinity() == TextAffinity::kDownstream)
     return VisiblePositionTemplate<Strategy>(downstream_position);
 
-  if (RuntimeEnabledFeatures::BidiCaretAffinityEnabled()) {
+  if (RuntimeEnabledFeatures::BidiCaretAffinityEnabled() &&
+      NGInlineFormattingContextOf(deep_position)) {
     // When not at a line wrap or bidi boundary, make sure to end up with
     // |TextAffinity::Downstream| affinity.
     const PositionWithAffinityTemplate<Strategy> upstream_position(
@@ -118,12 +119,10 @@
     LayoutBlockFlow* const context =
         NGOffsetMapping::GetInlineFormattingContextOf(*layout_object);
     DCHECK(context);
+    DCHECK(context->IsLayoutNGBlockFlow());
 
-    // TODO(xiaochengh): The double pointer pattern below is confusing and
-    // cumbersome, but necessary for now. Make it easier.
-    std::unique_ptr<NGOffsetMapping> mapping_storage;
     const NGOffsetMapping* mapping =
-        NGInlineNode::GetOffsetMapping(context, &mapping_storage);
+        NGInlineNode::GetOffsetMapping(context, nullptr);
     DCHECK(mapping);
 
     const base::Optional<unsigned> offset =
diff --git a/third_party/blink/renderer/core/exported/web_document_loader_impl.cc b/third_party/blink/renderer/core/exported/web_document_loader_impl.cc
index a406461..6ec5c3b 100644
--- a/third_party/blink/renderer/core/exported/web_document_loader_impl.cc
+++ b/third_party/blink/renderer/core/exported/web_document_loader_impl.cc
@@ -58,32 +58,28 @@
 }
 
 WebString WebDocumentLoaderImpl::OriginalReferrer() const {
-  return DocumentLoader::OriginalReferrer();
+  return DocumentLoader::OriginalReferrer().referrer;
 }
 
 WebURL WebDocumentLoaderImpl::GetUrl() const {
-  return request_wrapper_.Url();
+  return DocumentLoader::Url();
 }
 
 WebString WebDocumentLoaderImpl::HttpMethod() const {
-  return request_wrapper_.HttpMethod();
+  return DocumentLoader::HttpMethod();
 }
 
 mojom::FetchCacheMode WebDocumentLoaderImpl::GetCacheMode() const {
-  return request_wrapper_.GetCacheMode();
+  return DocumentLoader::CacheMode();
 }
 
 WebString WebDocumentLoaderImpl::Referrer() const {
-  return DocumentLoader::Referrer();
+  return DocumentLoader::GetReferrer().referrer;
 }
 
 network::mojom::ReferrerPolicy WebDocumentLoaderImpl::GetReferrerPolicy()
     const {
-  return request_wrapper_.GetReferrerPolicy();
-}
-
-const WebURLRequest& WebDocumentLoaderImpl::GetRequest() const {
-  return request_wrapper_;
+  return DocumentLoader::GetReferrer().referrer_policy;
 }
 
 const WebURLResponse& WebDocumentLoaderImpl::GetResponse() const {
@@ -132,7 +128,6 @@
     WebNavigationType navigation_type,
     std::unique_ptr<WebNavigationParams> navigation_params)
     : DocumentLoader(frame, navigation_type, std::move(navigation_params)),
-      request_wrapper_(request_),
       response_wrapper_(DocumentLoader::GetResponse()) {}
 
 WebDocumentLoaderImpl::~WebDocumentLoaderImpl() {
diff --git a/third_party/blink/renderer/core/exported/web_document_loader_impl.h b/third_party/blink/renderer/core/exported/web_document_loader_impl.h
index dc6a4afe..5a382e7 100644
--- a/third_party/blink/renderer/core/exported/web_document_loader_impl.h
+++ b/third_party/blink/renderer/core/exported/web_document_loader_impl.h
@@ -65,7 +65,6 @@
   mojom::FetchCacheMode GetCacheMode() const override;
   WebString Referrer() const override;
   network::mojom::ReferrerPolicy GetReferrerPolicy() const override;
-  const WebURLRequest& GetRequest() const override;
   const WebURLResponse& GetResponse() const override;
   bool HasUnreachableURL() const override;
   WebURL UnreachableURL() const override;
@@ -92,11 +91,9 @@
  private:
   ~WebDocumentLoaderImpl() override;
   void DetachFromFrame(bool flush_microtask_queue) override;
-  String DebugName() const override { return "WebDocumentLoaderImpl"; }
 
   // Mutable because the const getters will magically sync these to the
   // latest version from WebKit.
-  mutable WrappedResourceRequest request_wrapper_;
   mutable WrappedResourceResponse response_wrapper_;
 
   std::unique_ptr<ExtraData> extra_data_;
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc
index 4bac8b6..86da39d 100644
--- a/third_party/blink/renderer/core/exported/web_frame_test.cc
+++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -149,6 +149,7 @@
 #include "third_party/blink/renderer/platform/exported/wrapped_resource_request.h"
 #include "third_party/blink/renderer/platform/graphics/graphics_layer.h"
 #include "third_party/blink/renderer/platform/keyboard_codes.h"
+#include "third_party/blink/renderer/platform/loader/fetch/raw_resource.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher_properties.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
@@ -10967,9 +10968,6 @@
   RegisterMockedHttpURLLoad("promote_img_in_viewport_priority.html");
   RegisterMockedHttpURLLoad("image_slow.pl");
   RegisterMockedHttpURLLoad("image_slow_out_of_viewport.pl");
-  client.AddExpectedRequest(
-      ToKURL("http://internal.test/promote_img_in_viewport_priority.html"),
-      WebURLRequest::Priority::kVeryHigh);
   client.AddExpectedRequest(ToKURL("http://internal.test/image_slow.pl"),
                             WebURLRequest::Priority::kLow);
   client.AddExpectedRequest(
@@ -11007,8 +11005,6 @@
   RegisterMockedHttpURLLoad("priorities/injected.js");
   RegisterMockedHttpURLLoad("priorities/injected-async.js");
   RegisterMockedHttpURLLoad("priorities/body.js");
-  client.AddExpectedRequest(ToKURL("http://internal.test/script_priority.html"),
-                            WebURLRequest::Priority::kVeryHigh);
   client.AddExpectedRequest(ToKURL("http://internal.test/priorities/defer.js"),
                             WebURLRequest::Priority::kLow);
   client.AddExpectedRequest(ToKURL("http://internal.test/priorities/async.js"),
diff --git a/third_party/blink/renderer/core/exported/web_navigation_params.cc b/third_party/blink/renderer/core/exported/web_navigation_params.cc
index db8fa31..12d7c67 100644
--- a/third_party/blink/renderer/core/exported/web_navigation_params.cc
+++ b/third_party/blink/renderer/core/exported/web_navigation_params.cc
@@ -3,24 +3,39 @@
 // found in the LICENSE file.
 
 #include "third_party/blink/public/web/web_navigation_params.h"
+
+#include "third_party/blink/renderer/core/exported/web_document_loader_impl.h"
+#include "third_party/blink/renderer/platform/network/encoded_form_data.h"
+#include "third_party/blink/renderer/platform/network/http_names.h"
 #include "third_party/blink/renderer/platform/shared_buffer.h"
 
 namespace blink {
 
 WebNavigationParams::WebNavigationParams()
-    : devtools_navigation_token(base::UnguessableToken::Create()) {}
+    : http_method(http_names::kGET),
+      devtools_navigation_token(base::UnguessableToken::Create()) {}
 
 WebNavigationParams::~WebNavigationParams() = default;
 
 WebNavigationParams::WebNavigationParams(
     const base::UnguessableToken& devtools_navigation_token)
-    : devtools_navigation_token(devtools_navigation_token) {}
+    : http_method(http_names::kGET),
+      devtools_navigation_token(devtools_navigation_token) {}
 
 // static
 std::unique_ptr<WebNavigationParams> WebNavigationParams::CreateFromInfo(
     const WebNavigationInfo& info) {
   auto result = std::make_unique<WebNavigationParams>();
-  result->request = info.url_request;
+  result->url = info.url_request.Url();
+  result->http_method = info.url_request.HttpMethod();
+  result->cache_mode = info.url_request.GetCacheMode();
+  result->referrer = info.url_request.HttpHeaderField(http_names::kReferer);
+  result->referrer_policy = info.url_request.GetReferrerPolicy();
+  result->http_body = info.url_request.HttpBody();
+  result->http_content_type =
+      info.url_request.HttpHeaderField(http_names::kContentType);
+  result->previews_state = info.url_request.GetPreviewsState();
+  result->requestor_origin = info.url_request.RequestorOrigin();
   result->frame_load_type = info.frame_load_type;
   result->is_client_redirect = info.is_client_redirect;
   result->navigation_timings.input_start = info.input_start;
@@ -32,20 +47,35 @@
     base::span<const char> html,
     const WebURL& base_url) {
   auto result = std::make_unique<WebNavigationParams>();
-  result->request = WebURLRequest(base_url);
+  result->url = base_url;
   result->data = WebData(html.data(), html.size());
   result->mime_type = "text/html";
   result->text_encoding = "UTF-8";
   return result;
 }
 
+// static
+std::unique_ptr<WebNavigationParams> WebNavigationParams::CreateForErrorPage(
+    WebDocumentLoader* failed_document_loader,
+    base::span<const char> html,
+    const WebURL& base_url,
+    const WebURL& unreachable_url) {
+  auto result = WebNavigationParams::CreateWithHTMLString(html, base_url);
+  result->unreachable_url = unreachable_url;
+  // Locally generated error pages should not be cached.
+  result->cache_mode = blink::mojom::FetchCacheMode::kNoStore;
+  static_cast<WebDocumentLoaderImpl*>(failed_document_loader)
+      ->FillNavigationParamsForErrorPage(result.get());
+  return result;
+}
+
 #if INSIDE_BLINK
 // static
 std::unique_ptr<WebNavigationParams> WebNavigationParams::CreateWithHTMLBuffer(
     scoped_refptr<SharedBuffer> buffer,
     const KURL& base_url) {
   auto result = std::make_unique<WebNavigationParams>();
-  result->request = WebURLRequest(base_url);
+  result->url = base_url;
   result->data = WebData(std::move(buffer));
   result->mime_type = "text/html";
   result->text_encoding = "UTF-8";
diff --git a/third_party/blink/renderer/core/feature_policy/feature_policy.cc b/third_party/blink/renderer/core/feature_policy/feature_policy.cc
index 6a705510..af6761d 100644
--- a/third_party/blink/renderer/core/feature_policy/feature_policy.cc
+++ b/third_party/blink/renderer/core/feature_policy/feature_policy.cc
@@ -256,8 +256,6 @@
     ASSERT_ORIGIN_TRIAL(WebVR);
     ASSERT_ORIGIN_TRIAL(WebXR);
     default_feature_name_map.Set("vr", mojom::FeaturePolicyFeature::kWebVr);
-    default_feature_name_map.Set("wake-lock",
-                                 mojom::FeaturePolicyFeature::kWakeLock);
     if (RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled()) {
       default_feature_name_map.Set(
           "layout-animations", mojom::FeaturePolicyFeature::kLayoutAnimations);
@@ -303,6 +301,10 @@
       default_feature_name_map.Set("magnetometer",
                                    mojom::FeaturePolicyFeature::kMagnetometer);
     }
+    if (RuntimeEnabledFeatures::WakeLockEnabled()) {
+      default_feature_name_map.Set("wake-lock",
+                                   mojom::FeaturePolicyFeature::kWakeLock);
+    }
     if (RuntimeEnabledFeatures::WebUSBEnabled()) {
       default_feature_name_map.Set("usb", mojom::FeaturePolicyFeature::kUsb);
     }
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
index 4ee3d72c..856dda6 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -112,9 +112,10 @@
     impl->LoadJavaScriptURL(url);
   } else {
     auto params = std::make_unique<WebNavigationParams>();
-    params->request = WebURLRequest(url);
+    params->url = url;
     params->navigation_timings.navigation_start = base::TimeTicks::Now();
     params->navigation_timings.fetch_start = base::TimeTicks::Now();
+    FillNavigationParamsResponse(params.get());
     impl->CommitNavigation(std::move(params), nullptr /* extra_data */);
   }
 }
@@ -140,12 +141,12 @@
   WebLocalFrameImpl* impl = ToWebLocalFrameImpl(frame);
   HistoryItem* history_item = item;
   auto params = std::make_unique<WebNavigationParams>();
-  params->request =
-      WrappedResourceRequest(history_item->GenerateResourceRequest(cache_mode));
+  params->url = history_item->Url();
   params->frame_load_type = WebFrameLoadType::kBackForward;
   params->history_item = item;
   params->navigation_timings.navigation_start = base::TimeTicks::Now();
   params->navigation_timings.fetch_start = base::TimeTicks::Now();
+  FillNavigationParamsResponse(params.get());
   impl->CommitNavigation(std::move(params), nullptr /* extra_data */);
   PumpPendingRequestsForFrameToLoad(frame);
 }
@@ -168,6 +169,17 @@
   test::EnterRunLoop();
 }
 
+void FillNavigationParamsResponse(WebNavigationParams* params) {
+  KURL kurl(params->url);
+  // Empty documents, data urls and srcdoc will be handled by DocumentLoader.
+  if (DocumentLoader::WillLoadUrlAsEmpty(kurl) || kurl.ProtocolIsData() ||
+      kurl.IsAboutSrcdocURL()) {
+    return;
+  }
+  Platform::Current()->GetURLLoaderMockFactory()->FillNavigationParamsResponse(
+      params);
+}
+
 WebMouseEvent CreateMouseEvent(WebInputEvent::Type type,
                                WebMouseEvent::Button button,
                                const IntPoint& point,
@@ -532,6 +544,8 @@
   if (!frame_)
     return;
   auto params = WebNavigationParams::CreateFromInfo(*info);
+  if (info->archive_status != WebNavigationInfo::ArchiveStatus::Present)
+    FillNavigationParamsResponse(params.get());
   frame_->CommitNavigation(std::move(params), nullptr /* extra_data */);
 }
 
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.h b/third_party/blink/renderer/core/frame/frame_test_helpers.h
index bd4aa75..61158071 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.h
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.h
@@ -86,6 +86,7 @@
 
 class WebFrame;
 class WebLocalFrameImpl;
+struct WebNavigationParams;
 class WebRemoteFrameImpl;
 class WebSettings;
 
@@ -114,6 +115,9 @@
 void ReloadFrame(WebLocalFrame*);
 void ReloadFrameBypassingCache(WebLocalFrame*);
 
+// Fills navigation params if needed. Params should have the proper url set up.
+void FillNavigationParamsResponse(WebNavigationParams*);
+
 // Pumps pending resource requests while waiting for a frame to load. Consider
 // using one of the above helper methods whenever possible.
 void PumpPendingRequestsForFrameToLoad(WebLocalFrame*);
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
index 5a9963e8..3d353b2 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -2042,8 +2042,7 @@
     std::unique_ptr<WebNavigationParams> navigation_params,
     std::unique_ptr<WebDocumentLoader::ExtraData> extra_data) {
   DCHECK(GetFrame());
-  DCHECK(!navigation_params->request.IsNull());
-  DCHECK(!navigation_params->request.Url().ProtocolIs("javascript"));
+  DCHECK(!navigation_params->url.ProtocolIs("javascript"));
   if (GetTextFinder())
     GetTextFinder()->ClearActiveFindMatch();
   GetFrame()->Loader().CommitNavigation(
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
index c9a271f..af63c781 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -33,6 +33,7 @@
 #include <memory>
 #include <utility>
 
+#include "base/bind_helpers.h"
 #include "base/location.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/numerics/checked_math.h"
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.cc b/third_party/blink/renderer/core/html/media/html_video_element.cc
index 42975d2..c159cda 100644
--- a/third_party/blink/renderer/core/html/media/html_video_element.cc
+++ b/third_party/blink/renderer/core/html/media/html_video_element.cc
@@ -26,6 +26,7 @@
 #include "third_party/blink/renderer/core/html/media/html_video_element.h"
 
 #include <memory>
+#include "base/bind_helpers.h"
 #include "cc/paint/paint_canvas.h"
 #include "third_party/blink/public/platform/web_fullscreen_video_status.h"
 #include "third_party/blink/renderer/core/css/css_property_names.h"
diff --git a/third_party/blink/renderer/core/inspector/browser_protocol.pdl b/third_party/blink/renderer/core/inspector/browser_protocol.pdl
index 9e2e769..1077a0a 100644
--- a/third_party/blink/renderer/core/inspector/browser_protocol.pdl
+++ b/third_party/blink/renderer/core/inspector/browser_protocol.pdl
@@ -1621,7 +1621,7 @@
     returns
       # Resulting node.
       BackendNodeId backendNodeId
-      # Id of the node at given coordinates, only when enabled.
+      # Id of the node at given coordinates, only when enabled and requested document.
       optional NodeId nodeId
 
   # Returns node's HTML markup.
@@ -1891,7 +1891,7 @@
     returns
       # Resulting node.
       BackendNodeId backendNodeId
-      # Id of the node at given coordinates, only when enabled.
+      # Id of the node at given coordinates, only when enabled and requested document.
       optional NodeId nodeId
 
   # Fired when `Element`'s attribute is modified.
diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
index 76aa2f24..5d1b1d5 100644
--- a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
@@ -1335,10 +1335,8 @@
   if (!node)
     return Response::Error("No node found at given location");
   *backend_node_id = IdentifiersFactory::IntIdForNode(node);
-  if (enabled_.Get()) {
-    Response response = PushDocumentUponHandlelessOperation();
-    if (!response.isSuccess())
-      return response;
+  if (enabled_.Get() && document_ &&
+      document_node_to_id_map_->Contains(document_)) {
     *node_id = PushNodePathToFrontend(node);
   }
   return Response::OK();
@@ -1955,11 +1953,11 @@
 }
 
 void InspectorDOMAgent::CharacterDataModified(CharacterData* character_data) {
-  if (IsWhitespace(character_data)) {
+  int id = document_node_to_id_map_->at(character_data);
+  if (IsWhitespace(character_data) && id) {
     DOMNodeRemoved(character_data);
     return;
   }
-  int id = document_node_to_id_map_->at(character_data);
   if (!id) {
     // Push text node if it is being created.
     DidInsertDOMNode(character_data);
@@ -2152,12 +2150,8 @@
 Response InspectorDOMAgent::pushNodesByBackendIdsToFrontend(
     std::unique_ptr<protocol::Array<int>> backend_node_ids,
     std::unique_ptr<protocol::Array<int>>* result) {
-  if (!enabled_.Get())
-    return Response::Error("DOM agent is not enabled");
-
-  Response response = PushDocumentUponHandlelessOperation();
-  if (!response.isSuccess())
-    return response;
+  if (!document_ || !document_node_to_id_map_->Contains(document_))
+    return Response::Error("Document needs to be requested first");
 
   *result = protocol::Array<int>::create();
   for (size_t index = 0; index < backend_node_ids->length(); ++index) {
@@ -2249,10 +2243,9 @@
     return Response::Error("No iframe owner for given node");
 
   *backend_node_id = IdentifiersFactory::IntIdForNode(frame_owner);
-  if (enabled_.Get()) {
-    Response response = PushDocumentUponHandlelessOperation();
-    if (!response.isSuccess())
-      return response;
+
+  if (enabled_.Get() && document_ &&
+      document_node_to_id_map_->Contains(document_)) {
     *node_id = PushNodePathToFrontend(frame_owner);
   }
   return Response::OK();
@@ -2279,14 +2272,6 @@
   return Response::OK();
 }
 
-Response InspectorDOMAgent::PushDocumentUponHandlelessOperation() {
-  if (!document_node_to_id_map_->Contains(document_)) {
-    std::unique_ptr<protocol::DOM::Node> root;
-    return getDocument(Maybe<int>(), Maybe<bool>(), &root);
-  }
-  return Response::OK();
-}
-
 void InspectorDOMAgent::Trace(blink::Visitor* visitor) {
   visitor->Trace(dom_listener_);
   visitor->Trace(inspected_frames_);
diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_agent.h b/third_party/blink/renderer/core/inspector/inspector_dom_agent.h
index 253b3c1..2832c2b 100644
--- a/third_party/blink/renderer/core/inspector/inspector_dom_agent.h
+++ b/third_party/blink/renderer/core/inspector/inspector_dom_agent.h
@@ -251,7 +251,6 @@
   int BoundNodeId(Node*);
   void SetDOMListener(DOMListener*);
   int PushNodePathToFrontend(Node*);
-  protocol::Response PushDocumentUponHandlelessOperation();
   protocol::Response NodeForRemoteObjectId(const String& remote_object_id,
                                            Node*&);
 
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
index 47db6d2..cbfc3b68 100644
--- a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
@@ -840,7 +840,7 @@
     return;
 
   if (initiator_info.name == fetch_initiator_type_names::kDocument &&
-      loader->GetSubstituteData().IsValid())
+      loader->HasSubstituteData())
     return;
 
   if (!extra_request_headers_.IsEmpty()) {
@@ -919,7 +919,7 @@
     type = saved_type;
   }
   if (type == InspectorPageAgent::kDocumentResource && loader &&
-      loader->GetSubstituteData().IsValid())
+      loader->HasSubstituteData())
     return;
 
   // Resources are added to NetworkResourcesData as a WeakMember here and
diff --git a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
index 4546544c..3712f51 100644
--- a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
@@ -480,13 +480,6 @@
     return Response::Error(
         String("Unknown mode \"" + mode + "\" was provided."));
   }
-
-  if (mode != protocol::Overlay::InspectModeEnum::None) {
-    Response response = dom_agent_->PushDocumentUponHandlelessOperation();
-    if (!response.isSuccess())
-      return response;
-  }
-
   return SetSearchingForNode(mode, std::move(highlight_config));
 }
 
@@ -1335,7 +1328,8 @@
     return;
 
   int node_id = dom_agent_->PushNodePathToFrontend(node);
-  GetFrontend()->nodeHighlightRequested(node_id);
+  if (node_id)
+    GetFrontend()->nodeHighlightRequested(node_id);
 }
 
 Response InspectorOverlayAgent::SetSearchingForNode(
diff --git a/third_party/blink/renderer/core/layout/jank_tracker.cc b/third_party/blink/renderer/core/layout/jank_tracker.cc
index 5a49700..77f916c 100644
--- a/third_party/blink/renderer/core/layout/jank_tracker.cc
+++ b/third_party/blink/renderer/core/layout/jank_tracker.cc
@@ -126,6 +126,11 @@
   if (source.IsFixedPositioned() || source.IsStickyPositioned())
     return;
 
+  // SVG elements don't participate in the normal layout algorithms and are
+  // more likely to be used for animations.
+  if (source.IsSVG())
+    return;
+
   const auto* local_xform = TransformNodeFor(painting_layer.GetLayoutObject());
   const auto* root_xform = TransformNodeFor(*source.View());
 
diff --git a/third_party/blink/renderer/core/layout/jank_tracker_test.cc b/third_party/blink/renderer/core/layout/jank_tracker_test.cc
index aa8e01e2..e9d9e74 100644
--- a/third_party/blink/renderer/core/layout/jank_tracker_test.cc
+++ b/third_party/blink/renderer/core/layout/jank_tracker_test.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/core/layout/jank_tracker.h"
 
 #include "third_party/blink/public/platform/web_mouse_event.h"
+#include "third_party/blink/renderer/core/svg_names.h"
 #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h"
 
 namespace blink {
@@ -233,4 +234,17 @@
   EXPECT_FLOAT_EQ(0, GetJankTracker().Score());
 }
 
+TEST_F(JankTrackerTest, IgnoreSVG) {
+  SetBodyInnerHTML(R"HTML(
+    <svg>
+      <circle cx="50" cy="50" r="40"
+              stroke="black" stroke-width="3" fill="red" />
+    </svg>
+  )HTML");
+  GetDocument().QuerySelector("circle")->setAttribute(svg_names::kCxAttr,
+                                                      AtomicString("100"));
+  UpdateAllLifecyclePhases();
+  EXPECT_FLOAT_EQ(0, GetJankTracker().Score());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc
index a4e7f08..99cf3601 100644
--- a/third_party/blink/renderer/core/layout/layout_block.cc
+++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -1064,9 +1064,19 @@
   if (!StyleRef().HasPseudoStyle(kPseudoIdFirstLine))
     return;
 
+  // ImageChanged() is also called when we add image observers. Don't use
+  // FirstLineStyleRef() here because it will update the first line style cache
+  // too early. We should just access the current cached style and bail out if
+  // it's not ready (and we'll update pending image observer when the cache is
+  // updated).
+  const auto* cached_first_line_style =
+      StyleRef().GetCachedPseudoStyle(kPseudoIdFirstLine);
+  if (!cached_first_line_style)
+    return;
+
   if (auto* first_line_container = NearestInnerBlockWithFirstLine()) {
-    for (const auto* layer = &FirstLineStyleRef().BackgroundLayers(); layer;
-         layer = layer->Next()) {
+    for (const auto* layer = &cached_first_line_style->BackgroundLayers();
+         layer; layer = layer->Next()) {
       if (layer->GetImage() && image == layer->GetImage()->Data()) {
         first_line_container->SetShouldDoFullPaintInvalidationForFirstLine();
         break;
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index e2297e7..161a879 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -179,7 +179,7 @@
   void* pointers[5];
   Member<void*> members[1];
 #if DCHECK_IS_ON()
-  unsigned debug_bitfields_ : 2;
+  unsigned debug_bitfields_;
 #endif
   unsigned bitfields_;
   unsigned bitfields2_;
@@ -293,6 +293,7 @@
 #if DCHECK_IS_ON()
       has_ax_object_(false),
       set_needs_layout_forbidden_(false),
+      as_image_observer_count_(0),
 #endif
       bitfields_(node) {
   InstanceCounters::IncrementCounter(InstanceCounters::kLayoutObjectCounter);
@@ -2508,25 +2509,40 @@
   SetStyleWithWritingModeOf(std::move(style), Parent());
 }
 
+void LayoutObject::AddAsImageObserver(StyleImage* image) {
+  if (!image)
+    return;
+#if DCHECK_IS_ON()
+  ++as_image_observer_count_;
+#endif
+  image->AddClient(this);
+}
+
+void LayoutObject::RemoveAsImageObserver(StyleImage* image) {
+  if (!image)
+    return;
+#if DCHECK_IS_ON()
+  SECURITY_DCHECK(as_image_observer_count_ > 0u);
+  --as_image_observer_count_;
+#endif
+  image->RemoveClient(this);
+}
+
 void LayoutObject::UpdateFillImages(const FillLayer* old_layers,
                                     const FillLayer* new_layers) {
   // Optimize the common case
   if (FillLayer::ImagesIdentical(old_layers, new_layers))
     return;
 
-  // Go through the new layers and addClients first, to avoid removing all
-  // clients of an image.
+  // Go through the new layers and AddAsImageObserver() first, to avoid removing
+  // all clients of an image.
   for (const FillLayer* curr_new = new_layers; curr_new;
-       curr_new = curr_new->Next()) {
-    if (curr_new->GetImage())
-      curr_new->GetImage()->AddClient(this);
-  }
+       curr_new = curr_new->Next())
+    AddAsImageObserver(curr_new->GetImage());
 
   for (const FillLayer* curr_old = old_layers; curr_old;
-       curr_old = curr_old->Next()) {
-    if (curr_old->GetImage())
-      curr_old->GetImage()->RemoveClient(this);
-  }
+       curr_old = curr_old->Next())
+    RemoveAsImageObserver(curr_old->GetImage());
 }
 
 void LayoutObject::UpdateCursorImages(const CursorList* old_cursors,
@@ -2535,20 +2551,20 @@
     return;
 
   if (new_cursors) {
-    for (const CursorData& cursor_new : *new_cursors) {
-      if (cursor_new.GetImage())
-        cursor_new.GetImage()->AddClient(this);
-    }
+    for (const auto& cursor : *new_cursors)
+      AddAsImageObserver(cursor.GetImage());
   }
-  RemoveCursorImageClient(old_cursors);
+  if (old_cursors) {
+    for (const auto& cursor : *old_cursors)
+      RemoveAsImageObserver(cursor.GetImage());
+  }
 }
 
 void LayoutObject::UpdateImage(StyleImage* old_image, StyleImage* new_image) {
   if (old_image != new_image) {
-    if (old_image)
-      old_image->RemoveClient(this);
-    if (new_image)
-      new_image->AddClient(this);
+    // AddAsImageObserver first, to avoid removing all clients of an image.
+    AddAsImageObserver(new_image);
+    RemoveAsImageObserver(old_image);
   }
 }
 
@@ -3207,6 +3223,11 @@
   if (style_ && !IsText())
     UpdateImageObservers(style_.get(), nullptr);
 
+#if DCHECK_IS_ON()
+  // We must have removed all image observers.
+  SECURITY_DCHECK(as_image_observer_count_ == 0u);
+#endif
+
   if (GetFrameView())
     SetIsBackgroundAttachmentFixedObject(false);
 }
@@ -3427,23 +3448,6 @@
   delete this;
 }
 
-DISABLE_CFI_PERF
-void LayoutObject::RemoveShapeImageClient(ShapeValue* shape_value) {
-  if (!shape_value)
-    return;
-  if (StyleImage* shape_image = shape_value->GetImage())
-    shape_image->RemoveClient(this);
-}
-
-void LayoutObject::RemoveCursorImageClient(const CursorList* cursor_list) {
-  if (!cursor_list)
-    return;
-  for (const CursorData& cursor : *cursor_list) {
-    if (cursor.GetImage())
-      cursor.GetImage()->RemoveClient(this);
-  }
-}
-
 PositionWithAffinity LayoutObject::PositionForPoint(const LayoutPoint&) const {
   return CreatePositionWithAffinity(CaretMinOffset());
 }
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index b6cb4d4a..86c9d68 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -2396,15 +2396,18 @@
 
   bool IsInert() const;
 
-  void UpdateImage(StyleImage*, StyleImage*);
-
   void ScheduleRelayout();
 
+  void AddAsImageObserver(StyleImage*);
+  void RemoveAsImageObserver(StyleImage*);
+
+  void UpdateImage(StyleImage*, StyleImage*);
   void UpdateShapeImage(const ShapeValue*, const ShapeValue*);
   void UpdateFillImages(const FillLayer* old_layers,
                         const FillLayer* new_layers);
   void UpdateCursorImages(const CursorList* old_cursors,
                           const CursorList* new_cursors);
+
   void CheckCounterChanges(const ComputedStyle* old_style,
                            const ComputedStyle* new_style);
 
@@ -2426,9 +2429,6 @@
   const ComputedStyle* CachedFirstLineStyle() const;
   StyleDifference AdjustStyleDifference(StyleDifference) const;
 
-  void RemoveShapeImageClient(ShapeValue*);
-  void RemoveCursorImageClient(const CursorList*);
-
   // These are helper functions for AbsoluteBoudingBoxRectHandlingEmptyAnchor()
   // and AbsoluteBoundingBoxRectForScrollIntoView().
   enum class ExpandScrollMargin { kExpand, kIgnore };
@@ -2484,6 +2484,7 @@
 #if DCHECK_IS_ON()
   unsigned has_ax_object_ : 1;
   unsigned set_needs_layout_forbidden_ : 1;
+  unsigned as_image_observer_count_ : 20;
 #endif
 
 #define ADD_BOOLEAN_BITFIELD(field_name_, MethodNameBase) \
diff --git a/third_party/blink/renderer/core/layout/layout_object_test.cc b/third_party/blink/renderer/core/layout/layout_object_test.cc
index a13ffee2..674a5dd 100644
--- a/third_party/blink/renderer/core/layout/layout_object_test.cc
+++ b/third_party/blink/renderer/core/layout/layout_object_test.cc
@@ -1028,4 +1028,21 @@
   UpdateAllLifecyclePhasesForTest();
 }
 
+TEST_F(LayoutObjectTest, FirstLineBackgroundImageAddBlockBackgroundImageCrash) {
+  SetBodyInnerHTML(R"HTML(
+    <style>
+      #target::first-line { background-image: linear-gradient(red, blue); }
+    </style>
+    <div id="target"></div>
+  )HTML");
+
+  // The following code should not crash due to incorrectly paired
+  // StyleImage::AddClient() and RemoveClient().
+  GetDocument().getElementById("target")->setAttribute(
+      html_names::kStyleAttr,
+      "background-image: url(data:image/gif;base64,"
+      "R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==)");
+  UpdateAllLifecyclePhasesForTest();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/layout_text.cc b/third_party/blink/renderer/core/layout/layout_text.cc
index a623bc9..7902101 100644
--- a/third_party/blink/renderer/core/layout/layout_text.cc
+++ b/third_party/blink/renderer/core/layout/layout_text.cc
@@ -802,13 +802,6 @@
                                         should_affinity_be_downstream)) {
           const int offset = box->OffsetForPosition(
               point_line_direction, IncludePartialGlyphs, BreakGlyphs);
-          if (RuntimeEnabledFeatures::BidiCaretAffinityEnabled()) {
-            return CreatePositionWithAffinityForBox(
-                box, offset + box->Start(),
-                static_cast<unsigned>(offset) == box->Len()
-                    ? kAlwaysUpstream
-                    : kAlwaysDownstream);
-          }
           return CreatePositionWithAffinityForBoxAfterAdjustingOffsetForBiDi(
               box, offset, should_affinity_be_downstream);
         }
@@ -820,13 +813,6 @@
   if (last_box) {
     const int offset = last_box->OffsetForPosition(
         point_line_direction, IncludePartialGlyphs, BreakGlyphs);
-    if (RuntimeEnabledFeatures::BidiCaretAffinityEnabled()) {
-      return CreatePositionWithAffinityForBox(
-          last_box, offset + last_box->Start(),
-          static_cast<unsigned>(offset) == last_box->Len() ? kAlwaysUpstream
-                                                           : kAlwaysDownstream);
-    }
-
     ShouldAffinityBeDownstream should_affinity_be_downstream;
     LineDirectionPointFitsInBox(point_line_direction.ToInt(), last_box,
                                 should_affinity_be_downstream);
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator_test.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator_test.cc
index 63dfce3..d7d2c5ea 100644
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_caret_navigator_test.cc
@@ -12,13 +12,9 @@
 namespace blink {
 
 class NGCaretNavigatorTest : public RenderingTest,
-                             public testing::WithParamInterface<bool>,
-                             private ScopedLayoutNGForTest,
                              private ScopedBidiCaretAffinityForTest {
  public:
-  NGCaretNavigatorTest()
-      : ScopedLayoutNGForTest(GetParam()),
-        ScopedBidiCaretAffinityForTest(true) {}
+  NGCaretNavigatorTest() : ScopedBidiCaretAffinityForTest(true) {}
 
   void SetupHtml(const char* id, String html) {
     SetBodyInnerHTML(html);
@@ -26,14 +22,12 @@
     LayoutBlockFlow* layout_block_flow =
         ToLayoutBlockFlow(GetLayoutObjectByElementId(id));
     DCHECK(layout_block_flow);
+    DCHECK(layout_block_flow->IsLayoutNGBlockFlow());
     DCHECK(layout_block_flow->ChildrenInline());
-    DCHECK_EQ(layout_block_flow->IsLayoutNGMixin(), GetParam());
 
     const NGOffsetMapping* mapping =
-        NGInlineNode::GetOffsetMapping(layout_block_flow, &mapping_storage_);
+        NGInlineNode::GetOffsetMapping(layout_block_flow, nullptr);
     DCHECK(mapping);
-    DCHECK_EQ(!mapping_storage_,
-              GetParam());  // |storage| is used only for legacy.
 
     caret_navigator_ = mapping->GetCaretNavigator();
     DCHECK(caret_navigator_);
@@ -72,13 +66,10 @@
   }
 
  protected:
-  std::unique_ptr<NGOffsetMapping> mapping_storage_;
   const NGCaretNavigator* caret_navigator_;
 };
 
-INSTANTIATE_TEST_CASE_P(All, NGCaretNavigatorTest, testing::Bool());
-
-TEST_P(NGCaretNavigatorTest, BidiLevelAtBasic) {
+TEST_F(NGCaretNavigatorTest, BidiLevelAtBasic) {
   SetupHtml("container",
             "<div id=container>abc&#x05D0;&#x05D1;&#x05D2;123</div>");
 
@@ -93,7 +84,7 @@
   EXPECT_EQ(2u, BidiLevelAt(8));
 }
 
-TEST_P(NGCaretNavigatorTest, LeftCharacterOfBasic) {
+TEST_F(NGCaretNavigatorTest, LeftCharacterOfBasic) {
   SetupHtml("container",
             "<div id=container>abc&#x05D0;&#x05D1;&#x05D2;123</div>");
 
@@ -124,7 +115,7 @@
   EXPECT_EQ(7u, *LeftCharacterOf(8).index);
 }
 
-TEST_P(NGCaretNavigatorTest, RightCharacterOfBasic) {
+TEST_F(NGCaretNavigatorTest, RightCharacterOfBasic) {
   SetupHtml("container",
             "<div id=container>abc&#x05D0;&#x05D1;&#x05D2;123</div>");
 
@@ -155,7 +146,7 @@
   EXPECT_EQ(5u, *RightCharacterOf(8).index);
 }
 
-TEST_P(NGCaretNavigatorTest, LeftPositionOfBasic) {
+TEST_F(NGCaretNavigatorTest, LeftPositionOfBasic) {
   SetupHtml("container",
             "<div id=container>abc&#x05D0;&#x05D1;&#x05D2;123</div>");
 
@@ -213,7 +204,7 @@
   EXPECT_EQ(CaretBefore(8), *LeftPositionOf(CaretAfter(8)).position);
 }
 
-TEST_P(NGCaretNavigatorTest, RightPositionOfBasic) {
+TEST_F(NGCaretNavigatorTest, RightPositionOfBasic) {
   SetupHtml("container",
             "<div id=container>abc&#x05D0;&#x05D1;&#x05D2;123</div>");
 
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 4154e5f..3046f385 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
@@ -439,37 +439,21 @@
   CollectInlinesInternal(layout_block_flow, &builder, nullptr, nullptr,
                          update_layout);
 
+  std::unique_ptr<NGCaretNavigator> caret_navigator;
+
   // For non-NG object, we need the text, and also the inline items to resolve
   // bidi levels. Otherwise |data| already has the text from the pre-layout
   // phase, check they match.
   if (data->text_content.IsNull()) {
     DCHECK(!layout_block_flow->IsLayoutNGMixin());
     data->text_content = builder.ToString();
-    if (RuntimeEnabledFeatures::BidiCaretAffinityEnabled()) {
-      // Set |is_bidi_enabled_| for all UTF-16 strings for now, because at this
-      // point the string may or may not contain RTL characters.
-      // |SegmentText()| will analyze the text and reset |is_bidi_enabled_| if
-      // it doesn't contain any RTL characters.
-      data->is_bidi_enabled_ = MayBeBidiEnabled(data->text_content, builder);
-      if (data->is_bidi_enabled_) {
-        // |builder| performs some validity checks with |items|, so we can't
-        // simply move them to |data|, but have to copy.
-        // TODO(xiaochengh): Change it into a move.
-        data->items = items;
-        SegmentBidiRunsInternal(data, layout_block_flow->StyleRef());
-      } else {
-        data->SetBaseDirection(TextDirection::kLtr);
-      }
-    }
   } else {
     DCHECK(layout_block_flow->IsLayoutNGMixin());
     DCHECK_EQ(data->text_content, builder.ToString());
+    if (RuntimeEnabledFeatures::BidiCaretAffinityEnabled())
+      caret_navigator = std::make_unique<NGCaretNavigator>(*data);
   }
 
-  std::unique_ptr<NGCaretNavigator> caret_navigator;
-  if (RuntimeEnabledFeatures::BidiCaretAffinityEnabled())
-    caret_navigator = std::make_unique<NGCaretNavigator>(*data);
-
   // TODO(xiaochengh): This doesn't compute offset mapping correctly when
   // text-transform CSS property changes text length.
   NGOffsetMappingBuilder& mapping_builder = builder.GetOffsetMappingBuilder();
@@ -626,6 +610,8 @@
 // static
 // Segment bidi runs by resolving bidi embedding levels.
 // http://unicode.org/reports/tr9/#Resolving_Embedding_Levels
+// TODO(xiaochengh): Merge it back into SegmentBidiRuns(), as we no longer have
+// any legacy callers.
 void NGInlineNode::SegmentBidiRunsInternal(NGInlineNodeData* data,
                                            const ComputedStyle& style) {
   if (!data->is_bidi_enabled_) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.cc b/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.cc
index 00309e85..1399284 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h"
 
+#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_block_node.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h"
@@ -34,12 +35,11 @@
 }
 
 NGBlockChildIterator::Entry NGBlockChildIterator::NextChild(
-    const NGBreakToken* previous_inline_break_token) {
+    const NGInlineBreakToken* previous_inline_break_token) {
   const NGBreakToken* child_break_token = nullptr;
 
   if (previous_inline_break_token &&
       !previous_inline_break_token->IsFinished()) {
-    DCHECK(previous_inline_break_token->IsInlineType());
     return Entry(previous_inline_break_token->InputNode(),
                  previous_inline_break_token);
   }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h b/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h
index fcda3a4..1bf0648 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_child_iterator.h
@@ -12,6 +12,7 @@
 
 class NGBreakToken;
 class NGBlockBreakToken;
+class NGInlineBreakToken;
 
 // A utility class for block-flow layout which given the first child and a
 // break token will iterate through unfinished children.
@@ -31,7 +32,8 @@
   //    needed as multiple line-boxes can exist within the same parent
   //    fragment, unlike blocks.
   struct Entry;
-  Entry NextChild(const NGBreakToken* previous_inline_break_token = nullptr);
+  Entry NextChild(
+      const NGInlineBreakToken* previous_inline_break_token = nullptr);
 
  private:
   NGLayoutInputNode child_;
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 14c3d8f..6b80a1f 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
@@ -489,7 +489,7 @@
   // Try to reuse line box fragments from cached fragments if possible.
   // When possible, this adds fragments to |container_builder_| and update
   // |previous_inflow_position| and |BreakToken()|.
-  scoped_refptr<const NGBreakToken> previous_inline_break_token;
+  scoped_refptr<const NGInlineBreakToken> previous_inline_break_token;
   NGBlockChildIterator child_iterator(Node().FirstChild(), BreakToken());
   for (auto entry = child_iterator.NextChild();
        NGLayoutInputNode child = entry.node;
@@ -724,7 +724,7 @@
   return paint_fragment;
 }
 
-const NGBreakToken* NGBlockLayoutAlgorithm::TryReuseFragmentsFromCache(
+const NGInlineBreakToken* NGBlockLayoutAlgorithm::TryReuseFragmentsFromCache(
     NGInlineNode inline_node,
     NGPreviousInflowPosition* previous_inflow_position,
     bool* aborted_out) {
@@ -798,7 +798,7 @@
   NGBreakToken* last_break_token = last_fragment.fragment.BreakToken();
   DCHECK(last_break_token);
   DCHECK(!last_break_token->IsFinished());
-  return last_break_token;
+  return ToNGInlineBreakToken(last_break_token);
 }
 
 void NGBlockLayoutAlgorithm::HandleOutOfFlowPositioned(
@@ -1187,7 +1187,7 @@
     NGLayoutInputNode child,
     const NGBreakToken* child_break_token,
     NGPreviousInflowPosition* previous_inflow_position,
-    scoped_refptr<const NGBreakToken>* previous_inline_break_token) {
+    scoped_refptr<const NGInlineBreakToken>* previous_inline_break_token) {
   DCHECK(child);
   DCHECK(!child.IsFloating());
   DCHECK(!child.IsOutOfFlowPositioned());
@@ -1453,7 +1453,8 @@
       empty_block_affected_by_clearance);
 
   *previous_inline_break_token =
-      child.IsInline() ? layout_result->PhysicalFragment()->BreakToken()
+      child.IsInline() ? ToNGInlineBreakToken(
+                             layout_result->PhysicalFragment()->BreakToken())
                        : nullptr;
 
   return true;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
index b1f89e39..dffc9cfe 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
@@ -136,9 +136,10 @@
   // function adds part of cached fragments to |container_builder_|, update
   // |break_token_| to continue layout from the last reused fragment, and
   // returns |true|. Otherwise returns |false|.
-  const NGBreakToken* TryReuseFragmentsFromCache(NGInlineNode child,
-                                                 NGPreviousInflowPosition*,
-                                                 bool* abort_out);
+  const NGInlineBreakToken* TryReuseFragmentsFromCache(
+      NGInlineNode child,
+      NGPreviousInflowPosition*,
+      bool* abort_out);
 
   void HandleOutOfFlowPositioned(const NGPreviousInflowPosition&, NGBlockNode);
   void HandleFloat(const NGPreviousInflowPosition&,
@@ -182,7 +183,7 @@
       NGLayoutInputNode child,
       const NGBreakToken* child_break_token,
       NGPreviousInflowPosition*,
-      scoped_refptr<const NGBreakToken>* previous_inline_break_token);
+      scoped_refptr<const NGInlineBreakToken>* previous_inline_break_token);
 
   // Return the amount of block space available in the current fragmentainer
   // for the node being laid out by this algorithm.
diff --git a/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc b/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc
index 54808bb..1b3f1d2 100644
--- a/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc
+++ b/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc
@@ -79,18 +79,8 @@
 }
 
 void ApplicationCacheHost::WillStartLoading(ResourceRequest& request) {
-  if (!IsApplicationCacheEnabled())
+  if (!IsApplicationCacheEnabled() || !host_)
     return;
-
-  if (request.GetFrameType() ==
-          network::mojom::RequestContextFrameType::kTopLevel ||
-      request.GetFrameType() ==
-          network::mojom::RequestContextFrameType::kNested)
-    WillStartLoadingMainResource(request.Url(), request.HttpMethod());
-
-  if (!host_)
-    return;
-
   int host_id = host_->GetHostID();
   if (host_id != mojom::blink::kAppCacheNoHostId)
     request.SetAppCacheHostID(host_id);
@@ -98,12 +88,12 @@
 
 void ApplicationCacheHost::WillStartLoadingMainResource(const KURL& url,
                                                         const String& method) {
+  if (!IsApplicationCacheEnabled())
+    return;
   // We defer creating the outer host object to avoid spurious
   // creation/destruction around creating empty documents. At this point, we're
   // initiating a main resource load for the document, so its for real.
 
-  DCHECK(IsApplicationCacheEnabled());
-
   DCHECK(document_loader_->GetFrame());
   LocalFrame& frame = *document_loader_->GetFrame();
   host_ = frame.Client()->CreateApplicationCacheHost(this);
diff --git a/third_party/blink/renderer/core/loader/appcache/application_cache_host.h b/third_party/blink/renderer/core/loader/appcache/application_cache_host.h
index 09dcf87..a285a61 100644
--- a/third_party/blink/renderer/core/loader/appcache/application_cache_host.h
+++ b/third_party/blink/renderer/core/loader/appcache/application_cache_host.h
@@ -113,6 +113,7 @@
   // willStartLoadingMainResource if it's for frame resource or
   // willStartLoadingResource for subresource requests.
   void WillStartLoading(ResourceRequest&);
+  void WillStartLoadingMainResource(const KURL&, const String&);
 
   void DidReceiveResponseForMainResource(const ResourceResponse&);
   void MainResourceDataReceived(const char* data, size_t length);
@@ -141,8 +142,6 @@
   void Trace(blink::Visitor*);
 
  private:
-  void WillStartLoadingMainResource(const KURL&, const String&);
-
   // WebApplicationCacheHostClient implementation
   void DidChangeCacheAssociation() final;
   void NotifyEventListener(mojom::AppCacheEventID) final;
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index 456d1bd..ed5bf9f 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -30,6 +30,7 @@
 #include "third_party/blink/renderer/core/loader/document_loader.h"
 
 #include <memory>
+#include <utility>
 #include "base/auto_reset.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "services/metrics/public/cpp/ukm_recorder.h"
@@ -86,8 +87,10 @@
 #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_timing_info.h"
+#include "third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.h"
 #include "third_party/blink/renderer/platform/loader/fetch/unique_identifier.h"
 #include "third_party/blink/renderer/platform/loader/ftp_directory_listing.h"
+#include "third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.h"
 #include "third_party/blink/renderer/platform/mhtml/archive_resource.h"
 #include "third_party/blink/renderer/platform/mhtml/mhtml_archive.h"
 #include "third_party/blink/renderer/platform/network/content_security_policy_response_headers.h"
@@ -110,43 +113,58 @@
     LocalFrame* frame,
     WebNavigationType navigation_type,
     std::unique_ptr<WebNavigationParams> navigation_params)
-    : request_(navigation_params->request.ToResourceRequest()),
+    : params_(std::move(navigation_params)),
       frame_(frame),
       resource_fetcher_properties_(
           MakeGarbageCollected<FrameResourceFetcherProperties>(
               *MakeGarbageCollected<FrameOrImportedDocument>(*this))),
       fetcher_(FrameFetchContext::CreateFetcher(*resource_fetcher_properties_)),
-      original_url_(request_.Url()),
-      original_referrer_(request_.HttpReferrer()),
-      load_type_(navigation_params->frame_load_type),
-      is_client_redirect_(navigation_params->is_client_redirect),
+      load_type_(params_->frame_load_type),
+      is_client_redirect_(params_->is_client_redirect),
       replaces_current_history_item_(false),
       data_received_(false),
       navigation_type_(navigation_type),
       document_load_timing_(*this),
       application_cache_host_(ApplicationCacheHost::Create(this)),
       service_worker_network_provider_(
-          std::move(navigation_params->service_worker_network_provider)),
+          std::move(params_->service_worker_network_provider)),
       was_blocked_after_csp_(false),
       state_(kNotStarted),
       committed_data_buffer_(nullptr),
       in_data_received_(false),
       data_buffer_(SharedBuffer::Create()),
-      devtools_navigation_token_(navigation_params->devtools_navigation_token),
-      had_sticky_activation_(navigation_params->is_user_activated),
-      had_transient_activation_(request_.HasUserGesture()),
+      devtools_navigation_token_(params_->devtools_navigation_token),
+      had_sticky_activation_(params_->is_user_activated),
+      was_discarded_(params_->was_discarded),
       use_counter_(frame_->GetChromeClient().IsSVGImageChromeClient()
                        ? UseCounter::kSVGImageContext
                        : UseCounter::kDefaultContext) {
   DCHECK(frame_);
 
-  if (!navigation_params->data.IsNull()) {
-    substitute_data_ = SubstituteData(
-        navigation_params->data, navigation_params->mime_type,
-        navigation_params->text_encoding, navigation_params->unreachable_url);
+  url_ = params_->url;
+  original_url_ = url_;
+  had_transient_activation_ = LocalFrame::HasTransientUserActivation(frame_) ||
+                              params_->had_transient_activation;
+  http_method_ = params_->http_method;
+  if (params_->referrer.IsEmpty()) {
+    referrer_ = Referrer(Referrer::NoReferrer(), params_->referrer_policy);
+  } else {
+    referrer_ = Referrer(params_->referrer, params_->referrer_policy);
   }
-  if (!substitute_data_.IsValid() && request_.Url().IsAboutSrcdocURL()) {
+
+  original_referrer_ = referrer_;
+  http_body_ = params_->http_body;
+  http_content_type_ = params_->http_content_type;
+  origin_policy_ = params_->origin_policy;
+  requestor_origin_ = params_->requestor_origin;
+  unreachable_url_ = params_->unreachable_url;
+  cache_mode_ = params_->cache_mode;
+  previews_state_ = params_->previews_state;
+
+  if (params_->data.IsNull() && url_.IsAboutSrcdocURL()) {
     loading_srcdoc_ = true;
+    params_->mime_type = "text/html";
+    params_->text_encoding = "UTF-8";
     // TODO(dgozman): instead of reaching to the owner here, we could instead:
     // - grab the "srcdoc" value when starting a navigation right in the owner;
     // - pass it around through BeginNavigation to CommitNavigation as |data|;
@@ -158,19 +176,17 @@
         !owner_element->FastHasAttribute(html_names::kSrcdocAttr)) {
       // Cannot retrieve srcdoc content anymore (perhaps, the attribute was
       // cleared) - load empty instead.
-      substitute_data_ = SubstituteData(SharedBuffer::Create(), "text/html",
-                                        "UTF-8", NullURL());
+      params_->data = SharedBuffer::Create();
     } else {
       String srcdoc = owner_element->FastGetAttribute(html_names::kSrcdocAttr);
       DCHECK(!srcdoc.IsNull());
       CString encoded_srcdoc = srcdoc.Utf8();
-      substitute_data_ = SubstituteData(
-          SharedBuffer::Create(encoded_srcdoc.data(), encoded_srcdoc.length()),
-          "text/html", "UTF-8", NullURL());
+      params_->data =
+          SharedBuffer::Create(encoded_srcdoc.data(), encoded_srcdoc.length());
     }
   }
 
-  WebNavigationTimings& timings = navigation_params->navigation_timings;
+  WebNavigationTimings& timings = params_->navigation_timings;
   if (!timings.input_start.is_null())
     document_load_timing_.SetInputStart(timings.input_start);
   if (timings.navigation_start.is_null()) {
@@ -197,17 +213,15 @@
   // frame load type.
   replaces_current_history_item_ =
       load_type_ == WebFrameLoadType::kReplaceCurrentItem &&
-      (!frame_->Loader().Opener() || !request_.Url().IsEmpty());
+      (!frame_->Loader().Opener() || !url_.IsEmpty());
 
   // The document URL needs to be added to the head of the list as that is
   // where the redirects originated.
   if (is_client_redirect_)
     AppendRedirect(frame_->GetDocument()->Url());
 
-  if (!navigation_params->origin_to_commit.IsNull()) {
-    origin_to_commit_ =
-        navigation_params->origin_to_commit.Get()->IsolatedCopy();
-  }
+  if (!params_->origin_to_commit.IsNull())
+    origin_to_commit_ = params_->origin_to_commit.Get()->IsolatedCopy();
 }
 
 FrameLoader& DocumentLoader::GetFrameLoader() const {
@@ -228,7 +242,6 @@
 
 DocumentLoader::~DocumentLoader() {
   DCHECK(!frame_);
-  DCHECK(!GetResource());
   DCHECK(!application_cache_host_);
   DCHECK_EQ(state_, kSentDidFinishLoad);
 }
@@ -244,8 +257,8 @@
   visitor->Trace(document_load_timing_);
   visitor->Trace(application_cache_host_);
   visitor->Trace(content_security_policy_);
+  visitor->Trace(cached_metadata_handler_);
   visitor->Trace(use_counter_);
-  RawResourceClient::Trace(visitor);
 }
 
 unsigned long DocumentLoader::MainResourceIdentifier() const {
@@ -260,7 +273,7 @@
   return original_url_;
 }
 
-const AtomicString& DocumentLoader::OriginalReferrer() const {
+const Referrer& DocumentLoader::OriginalReferrer() const {
   return original_referrer_;
 }
 
@@ -270,7 +283,19 @@
 }
 
 const KURL& DocumentLoader::Url() const {
-  return request_.Url();
+  return url_;
+}
+
+const AtomicString& DocumentLoader::HttpMethod() const {
+  return http_method_;
+}
+
+mojom::FetchCacheMode DocumentLoader::CacheMode() const {
+  return cache_mode_;
+}
+
+const Referrer& DocumentLoader::GetReferrer() const {
+  return referrer_;
 }
 
 void DocumentLoader::SetServiceWorkerNetworkProvider(
@@ -335,13 +360,13 @@
     type = WebFrameLoadType::kReplaceCurrentItem;
   }
 
-  KURL old_url = request_.Url();
+  KURL old_url = url_;
   original_url_ = new_url;
-  request_.SetURL(new_url);
+  url_ = new_url;
   SetReplacesCurrentHistoryItem(type != WebFrameLoadType::kStandard);
   if (same_document_navigation_source == kSameDocumentNavigationHistoryApi) {
-    request_.SetHTTPMethod(http_names::kGET);
-    request_.SetHTTPBody(nullptr);
+    http_method_ = http_names::kGET;
+    http_body_ = nullptr;
   }
   ClearRedirectChain();
   if (is_client_redirect_)
@@ -372,12 +397,20 @@
   return UnreachableURL().IsEmpty() ? Url() : UnreachableURL();
 }
 
-const AtomicString& DocumentLoader::Referrer() const {
-  return request_.HttpReferrer();
+EncodedFormData* DocumentLoader::HttpBody() const {
+  return http_body_.get();
 }
 
-EncodedFormData* DocumentLoader::HttpBody() const {
-  return request_.HttpBody();
+void DocumentLoader::FillNavigationParamsForErrorPage(
+    WebNavigationParams* params) {
+  params->http_method = http_method_;
+  params->referrer = referrer_.referrer;
+  params->referrer_policy = referrer_.referrer_policy;
+  params->http_body = WebHTTPBody(http_body_.get());
+  params->http_content_type = http_content_type_;
+  params->previews_state = previews_state_;
+  params->requestor_origin = requestor_origin_;
+  params->origin_policy = origin_policy_;
 }
 
 void DocumentLoader::SetHistoryItemStateForCommit(
@@ -389,14 +422,13 @@
 
   history_item_->SetURL(UrlForHistory());
   history_item_->SetReferrer(SecurityPolicy::GenerateReferrer(
-      request_.GetReferrerPolicy(), history_item_->Url(),
-      request_.HttpReferrer()));
-  if (DeprecatedEqualIgnoringCase(request_.HttpMethod(), "POST")) {
+      referrer_.referrer_policy, history_item_->Url(), referrer_.referrer));
+  if (DeprecatedEqualIgnoringCase(http_method_, "POST")) {
     // FIXME: Eventually we have to make this smart enough to handle the case
     // where we have a stream for the body to handle the "data interspersed with
     // files" feature.
-    history_item_->SetFormData(request_.HttpBody());
-    history_item_->SetFormContentType(request_.HttpContentType());
+    history_item_->SetFormData(http_body_);
+    history_item_->SetFormContentType(http_content_type_);
   } else {
     history_item_->SetFormData(nullptr);
     history_item_->SetFormContentType(g_null_atom);
@@ -434,19 +466,41 @@
   }
 }
 
-void DocumentLoader::NotifyFinished(Resource* resource) {
-  DCHECK_EQ(GetResource(), resource);
-  DCHECK(GetResource());
+void DocumentLoader::BodyCodeCacheReceived(
+    base::span<const uint8_t> code_cache) {
+  if (cached_metadata_handler_) {
+    cached_metadata_handler_->SetSerializedCachedMetadata(code_cache.data(),
+                                                          code_cache.size());
+  }
+}
 
-  if (!resource->ErrorOccurred() && !resource->WasCanceled()) {
-    const ResourceResponse& response = resource->GetResponse();
-    if (response.IsHTTP()) {
-      navigation_timing_info_->SetFinalResponse(response);
-      const int64_t encoded_data_length = response.EncodedDataLength();
+void DocumentLoader::BodyDataReceived(base::span<const char> data) {
+  fetcher_->Context().DispatchDidReceiveData(main_resource_identifier_,
+                                             data.data(), data.size());
+  HandleData(data.data(), data.size());
+}
+
+void DocumentLoader::BodyLoadingFinished(
+    TimeTicks completion_time,
+    int64_t total_encoded_data_length,
+    int64_t total_encoded_body_length,
+    int64_t total_decoded_body_length,
+    bool should_report_corb_blocking,
+    const base::Optional<WebURLError>& error) {
+  response_.SetEncodedDataLength(total_encoded_data_length);
+  response_.SetEncodedBodyLength(total_encoded_body_length);
+  response_.SetDecodedBodyLength(total_decoded_body_length);
+
+  if (!error) {
+    fetcher_->Context().DispatchDidFinishLoading(
+        main_resource_identifier_, completion_time, total_encoded_data_length,
+        total_decoded_body_length, should_report_corb_blocking);
+    if (response_.IsHTTP()) {
+      navigation_timing_info_->SetFinalResponse(response_);
       navigation_timing_info_->AddFinalTransferSize(
-          encoded_data_length == -1 ? 0 : encoded_data_length);
-      if (response.HttpStatusCode() < 400 && report_timing_info_to_parent_) {
-        navigation_timing_info_->SetLoadFinishTime(resource->LoadFinishTime());
+          total_encoded_data_length == -1 ? 0 : total_encoded_data_length);
+      if (response_.HttpStatusCode() < 400 && report_timing_info_to_parent_) {
+        navigation_timing_info_->SetLoadFinishTime(completion_time);
         if (state_ >= kCommitted) {
           // Note that we currently lose timing info for empty documents,
           // which will be fixed with synchronous commit.
@@ -457,21 +511,21 @@
         frame_->SetShouldSendResourceTimingInfoToParent(false);
       }
     }
-    FinishedLoading(resource->LoadFinishTime());
+    FinishedLoading(completion_time);
     return;
   }
 
-  if (resource->GetResourceError().WasBlockedByResponse()) {
-    probe::didReceiveResourceResponse(
-        probe::ToCoreProbeSink(frame_->GetDocument()), MainResourceIdentifier(),
-        this, resource->GetResponse(), resource);
-  }
-
-  LoadFailed(resource->GetResourceError());
-  ClearResource();
+  ResourceError resource_error = error.value();
+  fetcher_->Context().DispatchDidFail(url_, main_resource_identifier_,
+                                      resource_error, total_encoded_data_length,
+                                      false /* is_internal_request */);
+  LoadFailed(resource_error);
 }
 
 void DocumentLoader::LoadFailed(const ResourceError& error) {
+  body_loader_.reset();
+  virtual_time_pauser_.UnpauseVirtualTime();
+
   if (!error.IsCancellation() && frame_->Owner())
     frame_->Owner()->RenderFallbackContent(frame_);
 
@@ -501,15 +555,14 @@
   DCHECK_EQ(kSentDidFinishLoad, state_);
 }
 
-void DocumentLoader::SetUserActivated() {
-  had_sticky_activation_ = true;
-}
-
 const AtomicString& DocumentLoader::RequiredCSP() {
   return GetFrameLoader().RequiredCSP();
 }
 
 void DocumentLoader::FinishedLoading(TimeTicks finish_time) {
+  body_loader_.reset();
+  virtual_time_pauser_.UnpauseVirtualTime();
+
   DCHECK(frame_->Loader().StateMachine()->CreatingInitialEmptyDocument() ||
          !frame_->GetPage()->Paused() ||
          MainThreadDebugger::Instance()->IsPaused());
@@ -527,6 +580,7 @@
   if (response_end_time.is_null())
     response_end_time = CurrentTimeTicks();
   GetTiming().SetResponseEnd(response_end_time);
+
   if (!MaybeCreateArchive()) {
     // If this is an empty document, it might not have actually been
     // committed yet. Force a commit so that the Document actually gets created.
@@ -546,28 +600,16 @@
       parser_.Clear();
     }
   }
-  ClearResource();
 }
 
-bool DocumentLoader::RedirectReceived(
-    Resource* resource,
-    const ResourceRequest& request,
-    const ResourceResponse& redirect_response) {
-  DCHECK(frame_);
-  DCHECK_EQ(resource, GetResource());
-  DCHECK(!redirect_response.IsNull());
-  request_ = request;
-  const KURL& request_url = request_.Url();
-  navigation_timing_info_->AddRedirect(redirect_response, request_url);
-
+void DocumentLoader::HandleRedirect(const KURL& current_request_url) {
   // Browser process should have already checked that redirecting url is
   // allowed to display content from the target origin.
-  CHECK(SecurityOrigin::Create(redirect_response.CurrentRequestUrl())
-            ->CanDisplay(request_url));
+  CHECK(SecurityOrigin::Create(current_request_url)->CanDisplay(url_));
 
   DCHECK(!GetTiming().FetchStart().is_null());
-  AppendRedirect(request_url);
-  GetTiming().AddRedirect(redirect_response.CurrentRequestUrl(), request_url);
+  AppendRedirect(url_);
+  GetTiming().AddRedirect(current_request_url, url_);
 
   // If a redirection happens during a back/forward navigation, don't restore
   // any state from the old HistoryItem. There is a provisional history item for
@@ -576,7 +618,6 @@
 
   // TODO(creis): Determine if we need to clear any history state
   // in embedder to fix https://crbug.com/671276.
-  return true;
 }
 
 static bool CanShowMIMEType(const String& mime_type, LocalFrame* frame) {
@@ -588,7 +629,7 @@
 }
 
 bool DocumentLoader::ShouldContinueForResponse() const {
-  if (substitute_data_.IsValid())
+  if (has_substitute_data_)
     return true;
 
   int status_code = response_.HttpStatusCode();
@@ -632,10 +673,6 @@
 
 void DocumentLoader::CancelLoadAfterCSPDenied(
     const ResourceResponse& response) {
-  probe::didReceiveResourceResponse(
-      probe::ToCoreProbeSink(frame_->GetDocument()), MainResourceIdentifier(),
-      this, response, GetResource());
-
   SetWasBlockedAfterCSP();
 
   // Pretend that this was an empty HTTP 200 response.  Don't reuse the original
@@ -643,37 +680,21 @@
   //
   // TODO(mkwst):  Remove this once XFO moves to the browser.
   // https://crbug.com/555418.
-  ClearResource();
   content_security_policy_.Clear();
   KURL blocked_url = SecurityOrigin::UrlWithUniqueOpaqueOrigin();
   original_url_ = blocked_url;
-  request_.SetURL(blocked_url);
+  url_ = blocked_url;
   redirect_chain_.pop_back();
   AppendRedirect(blocked_url);
   response_ = ResourceResponse(blocked_url);
   response_.SetMimeType("text/html");
   FinishedLoading(CurrentTimeTicks());
-
-  return;
 }
 
-void DocumentLoader::ResponseReceived(
-    Resource* resource,
-    const ResourceResponse& response,
-    std::unique_ptr<WebDataConsumerHandle> handle) {
-  DCHECK_EQ(GetResource(), resource);
-  DCHECK(!handle);
+bool DocumentLoader::HandleResponse(const ResourceResponse& response) {
   DCHECK(frame_);
-
   application_cache_host_->DidReceiveResponseForMainResource(response);
 
-  // The memory cache doesn't understand the application cache or its caching
-  // rules. So if a main resource is served from the application cache, ensure
-  // we don't save the result for future use. All responses loaded from appcache
-  // will have a non-zero appCacheID().
-  if (response.AppCacheID())
-    GetMemoryCache()->Remove(resource);
-
   content_security_policy_ = ContentSecurityPolicy::Create();
   content_security_policy_->SetOverrideURLForSelf(response.CurrentRequestUrl());
 
@@ -690,8 +711,8 @@
     // already been passed down.
     if (!content_security_policy_->HasPolicyFromSource(
             kContentSecurityPolicyHeaderSourceOriginPolicy)) {
-      std::unique_ptr<OriginPolicy> origin_policy = OriginPolicy::From(
-          StringUTF8Adaptor(request_.GetOriginPolicy()).AsStringPiece());
+      std::unique_ptr<OriginPolicy> origin_policy =
+          OriginPolicy::From(StringUTF8Adaptor(origin_policy_).AsStringPiece());
       if (origin_policy) {
         for (auto csp : origin_policy->GetContentSecurityPolicies()) {
           content_security_policy_->DidReceiveHeader(
@@ -706,7 +727,7 @@
   if (!content_security_policy_->AllowAncestors(frame_,
                                                 response.CurrentRequestUrl())) {
     CancelLoadAfterCSPDenied(response);
-    return;
+    return false;
   }
 
   if (!frame_->GetSettings()->BypassCSP() &&
@@ -736,7 +757,7 @@
             response.CurrentRequestUrl(), this, MainResourceIdentifier());
         frame_->GetDocument()->AddConsoleMessage(console_message);
         CancelLoadAfterCSPDenied(response);
-        return;
+        return false;
       }
     }
   }
@@ -769,16 +790,14 @@
       DeprecatedEqualIgnoringCase("message/rfc822", response_.MimeType());
 
   if (!ShouldContinueForResponse()) {
-    probe::didReceiveResourceResponse(
-        probe::ToCoreProbeSink(frame_->GetDocument()), resource->Identifier(),
-        this, response_, resource);
-    fetcher_->StopFetching();
-    return;
+    StopLoading();
+    return false;
   }
 
   if (frame_->Owner() && response_.IsHTTP() &&
       !cors::IsOkStatus(response_.HttpStatusCode()))
     frame_->Owner()->RenderFallbackContent(frame_);
+  return true;
 }
 
 void DocumentLoader::CommitNavigation(const AtomicString& mime_type,
@@ -805,8 +824,7 @@
   // Prepare a DocumentInit before clearing the frame, because it may need to
   // inherit an aliased security context.
   Document* owner_document = nullptr;
-  scoped_refptr<const SecurityOrigin> initiator_origin =
-      request_.RequestorOrigin();
+  scoped_refptr<const SecurityOrigin> initiator_origin = requestor_origin_;
 
   // TODO(dcheng): This differs from the behavior of both IE and Firefox: the
   // origin is inherited from the document that loaded the URL.
@@ -833,7 +851,7 @@
       mime_type, encoding, InstallNewDocumentReason::kNavigation,
       parsing_policy, overriding_url);
   parser_->SetDocumentWasLoadedAsPartOfNavigation();
-  if (request_.WasDiscarded())
+  if (was_discarded_)
     frame_->GetDocument()->SetWasDiscarded(true);
   frame_->GetDocument()->MaybeHandleHttpRefresh(
       response_.HttpHeaderField(http_names::kRefresh),
@@ -843,7 +861,7 @@
   // If we did commit MediaDocument, we should stop here.
   if (frame_ && frame_->GetDocument()->IsMediaDocument()) {
     parser_->Finish();
-    fetcher_->StopFetching();
+    StopLoading();
   }
 }
 
@@ -868,13 +886,9 @@
   }
 }
 
-void DocumentLoader::DataReceived(Resource* resource,
-                                  const char* data,
-                                  size_t length) {
+void DocumentLoader::HandleData(const char* data, size_t length) {
   DCHECK(data);
   DCHECK(length);
-  DCHECK_EQ(resource, GetResource());
-  DCHECK(!response_.IsNull());
   DCHECK(!frame_->GetPage()->Paused());
   time_of_last_data_received_ = CurrentTimeTicks();
 
@@ -919,14 +933,20 @@
 
 void DocumentLoader::StopLoading() {
   fetcher_->StopFetching();
-  if (frame_ && !SentDidFinishLoad())
+  body_loader_.reset();
+  if (!SentDidFinishLoad())
     LoadFailed(ResourceError::CancelledError(Url()));
 }
 
 void DocumentLoader::SetDefersLoading(bool defers) {
-  // TODO(dgozman): defer body loader once we don't use Fetcher()
-  // for the main resource.
+  defers_loading_ = defers;
   Fetcher()->SetDefersLoading(defers);
+  if (body_loader_)
+    body_loader_->SetDefersLoading(defers);
+  if (defers_loading_)
+    virtual_time_pauser_.UnpauseVirtualTime();
+  else
+    virtual_time_pauser_.PauseVirtualTime();
 }
 
 void DocumentLoader::DetachFromFrame(bool flush_microtask_queue) {
@@ -958,7 +978,6 @@
   application_cache_host_.Clear();
   service_worker_network_provider_ = nullptr;
   WeakIdentifierMap<DocumentLoader>::NotifyObjectDestroyed(this);
-  ClearResource();
   frame_ = nullptr;
 }
 
@@ -985,7 +1004,7 @@
 }
 
 const KURL& DocumentLoader::UnreachableURL() const {
-  return substitute_data_.FailingURL();
+  return unreachable_url_;
 }
 
 bool DocumentLoader::WillLoadUrlAsEmpty(const KURL& url) {
@@ -1000,60 +1019,186 @@
   return SchemeRegistry::ShouldLoadURLSchemeAsEmptyDocument(url.Protocol());
 }
 
-bool DocumentLoader::MaybeLoadEmpty() {
-  if (substitute_data_.IsValid())
-    return false;
-  if (!WillLoadUrlAsEmpty(request_.Url()))
-    return false;
-
-  if (request_.Url().IsEmpty() &&
-      !GetFrameLoader().StateMachine()->CreatingInitialEmptyDocument())
-    request_.SetURL(BlankURL());
-  response_ = ResourceResponse(request_.Url());
+void DocumentLoader::LoadEmpty() {
+  if (url_.IsEmpty() &&
+      !GetFrameLoader().StateMachine()->CreatingInitialEmptyDocument()) {
+    url_ = BlankURL();
+  }
+  response_ = ResourceResponse(url_);
   response_.SetMimeType("text/html");
   response_.SetTextEncodingName("utf-8");
   FinishedLoading(CurrentTimeTicks());
-  return true;
+}
+
+void DocumentLoader::CreateBodyLoaderFromStaticData(const SharedBuffer& data) {
+  DCHECK(!body_loader_);
+  auto body_loader = std::make_unique<StaticDataNavigationBodyLoader>();
+  body_loader->Write(data);
+  body_loader->Finish();
+  body_loader_ = std::move(body_loader);
 }
 
 void DocumentLoader::StartLoading() {
+  StartLoadingInternal();
+  params_ = nullptr;
+}
+
+void DocumentLoader::StartLoadingInternal() {
   GetTiming().MarkNavigationStart();
-  DCHECK(!GetResource());
   DCHECK_EQ(state_, kNotStarted);
+  DCHECK(params_);
   state_ = kProvisional;
 
-  if (!MaybeLoadEmpty()) {
-    DCHECK(!GetTiming().NavigationStart().is_null());
-    // The fetch has already started in the browser,
-    // so we don't MarkFetchStart here.
-
-    main_resource_identifier_ = CreateUniqueIdentifier();
-
-    // This buffer is created and populated for providing transferSize
-    // and redirect timing opt-in information.
-    navigation_timing_info_ = ResourceTimingInfo::Create(
-        fetch_initiator_type_names::kDocument, GetTiming().NavigationStart(),
-        true /* is_main_resource */);
-    navigation_timing_info_->SetInitialURL(request_.Url());
-    report_timing_info_to_parent_ = ShouldReportTimingInfoToParent();
-
-    ResourceLoaderOptions options;
-    options.data_buffering_policy = kDoNotBufferData;
-    options.initiator_info.name = fetch_initiator_type_names::kDocument;
-    FetchParameters fetch_params(request_, options);
-    RawResource::FetchMainResource(fetch_params, Fetcher(), this,
-                                   substitute_data_, main_resource_identifier_);
-    // A bunch of headers are set when the underlying resource load begins, and
-    // request_ needs to include those. Even when using a cached resource, we
-    // may make some modification to the request, e.g. adding the referer
-    // header.
-    request_ = GetResource()->IsLoading() ? GetResource()->GetResourceRequest()
-                                          : fetch_params.GetResourceRequest();
-    base::OnceClosure continue_navigation =
-        GetResource()->TakeContinueNavigationRequestCallback();
-    if (continue_navigation)
-      std::move(continue_navigation).Run();
+  if (params_->data.IsNull() && WillLoadUrlAsEmpty(url_)) {
+    LoadEmpty();
+    return;
   }
+
+  // See WebNavigationParams for special case explanations.
+  ResourceResponse final_response;
+  if (!params_->data.IsNull()) {
+    // Use provided data instead of loading resource body.
+    params_->redirects.Clear();
+    final_response.SetCurrentRequestUrl(url_);
+    final_response.SetMimeType(params_->mime_type);
+    final_response.SetExpectedContentLength(params_->data.size());
+    final_response.SetTextEncodingName(params_->text_encoding);
+    CreateBodyLoaderFromStaticData(params_->data);
+    has_substitute_data_ = true;
+  } else if (fetcher_->Archive()) {
+    // If we have an archive loaded in some ancestor frame, we should
+    // retrieve document content from that archive. This is different from
+    // loading an archive into this frame, which will be handled separately
+    // once we load the body and parse it as an archive.
+    params_->body_loader.reset();
+    ArchiveResource* archive_resource =
+        fetcher_->Archive()->SubresourceForURL(url_);
+    if (archive_resource) {
+      params_->redirects.Clear();
+      final_response.SetCurrentRequestUrl(url_);
+      final_response.SetMimeType(archive_resource->MimeType());
+      final_response.SetExpectedContentLength(archive_resource->Data()->size());
+      final_response.SetTextEncodingName(archive_resource->TextEncoding());
+      CreateBodyLoaderFromStaticData(*archive_resource->Data());
+    }
+  } else if (!params_->body_loader) {
+    // We can handle data urls in place.
+    // TODO(dgozman): This is currently only used in tests. Perhaps we should
+    // either handle all data urls locally, or rework tests.
+    scoped_refptr<SharedBuffer> data;
+    if (url_.ProtocolIsData()) {
+      data =
+          network_utils::ParseDataURLAndPopulateResponse(url_, final_response);
+    }
+    if (data)
+      CreateBodyLoaderFromStaticData(*data);
+  } else {
+    // The common case - both final response and body loader should be
+    // provided.
+    final_response = params_->response.ToResourceResponse();
+    body_loader_ = std::move(params_->body_loader);
+  }
+
+  if (!body_loader_) {
+    // TODO(dgozman): we should try to get rid of this case.
+    LoadFailed(ResourceError::Failure(url_));
+    return;
+  }
+
+  DCHECK(!GetTiming().NavigationStart().is_null());
+  // The fetch has already started in the browser,
+  // so we don't MarkFetchStart here.
+  main_resource_identifier_ = CreateUniqueIdentifier();
+
+  navigation_timing_info_ = ResourceTimingInfo::Create(
+      fetch_initiator_type_names::kDocument, GetTiming().NavigationStart(),
+      true /* is_main_resource */);
+  navigation_timing_info_->SetInitialURL(url_);
+  report_timing_info_to_parent_ = ShouldReportTimingInfoToParent();
+
+  virtual_time_pauser_ =
+      frame_->GetFrameScheduler()->CreateWebScopedVirtualTimePauser(
+          url_.GetString(),
+          WebScopedVirtualTimePauser::VirtualTaskDuration::kNonInstant);
+  virtual_time_pauser_.PauseVirtualTime();
+
+  if (!fetcher_->Archive())
+    application_cache_host_->WillStartLoadingMainResource(url_, http_method_);
+
+  // Many parties are interested in resource loading, so we will notify
+  // them through various DispatchXXX methods on FrameFetchContext.
+
+  // TODO(dgozman): get rid of fake request and initiator info, we only use them
+  // for DispatchWillSendRequest.
+  ResourceRequest fake_request;
+  fake_request.SetURL(url_);
+  fake_request.SetPriority(WebURLRequest::Priority::kVeryHigh);
+  fake_request.SetHTTPBody(http_body_);
+  fake_request.SetFrameType(
+      frame_->IsMainFrame() ? network::mojom::RequestContextFrameType::kTopLevel
+                            : network::mojom::RequestContextFrameType::kNested);
+  fake_request.SetRequestContext(mojom::RequestContextType::HYPERLINK);
+  FetchInitiatorInfo initiator_info;
+  initiator_info.name = fetch_initiator_type_names::kDocument;
+  fetcher_->Context().RecordLoadingActivity(
+      fake_request, ResourceType::kMainResource,
+      fetch_initiator_type_names::kDocument);
+  fetcher_->Context().DispatchWillSendRequest(
+      main_resource_identifier_, fake_request, ResourceResponse(),
+      ResourceType::kMainResource, initiator_info);
+
+  for (size_t i = 0; i < params_->redirects.size(); ++i) {
+    WebNavigationParams::RedirectInfo& redirect = params_->redirects[i];
+    url_ = redirect.new_url;
+    AtomicString new_http_method = redirect.new_http_method;
+    if (http_method_ != new_http_method) {
+      http_body_ = nullptr;
+      fake_request.SetHTTPBody(nullptr);
+      http_method_ = new_http_method;
+    }
+    if (redirect.new_referrer.IsEmpty()) {
+      referrer_ =
+          Referrer(Referrer::NoReferrer(), redirect.new_referrer_policy);
+    } else {
+      referrer_ = Referrer(redirect.new_referrer, redirect.new_referrer_policy);
+    }
+    http_content_type_ = g_null_atom;
+    // TODO(dgozman): check whether clearing origin policy is intended behavior.
+    origin_policy_ = String();
+    fake_request.SetURL(url_);
+    ResourceResponse redirect_response =
+        redirect.redirect_response.ToResourceResponse();
+    fetcher_->Context().DispatchWillSendRequest(
+        main_resource_identifier_, fake_request, redirect_response,
+        ResourceType::kMainResource, initiator_info);
+    navigation_timing_info_->AddRedirect(redirect_response, url_);
+    HandleRedirect(redirect_response.CurrentRequestUrl());
+  }
+
+  fetcher_->Context().DispatchDidReceiveResponse(
+      main_resource_identifier_, fake_request, final_response, nullptr,
+      FetchContext::ResourceResponseType::kNotFromMemoryCache);
+  if (!HandleResponse(final_response))
+    return;
+
+  if (defers_loading_)
+    body_loader_->SetDefersLoading(true);
+
+  if (!url_.ProtocolIsInHTTPFamily()) {
+    // We only support code cache for http family, and browser insists on not
+    // event asking for code cache with other schemes.
+    body_loader_->StartLoadingBody(this, false /* use_isolated_code_cache */);
+    return;
+  }
+
+  auto cached_metadata_sender = CachedMetadataSender::Create(
+      response_, blink::mojom::CodeCacheType::kJavascript, requestor_origin_);
+  cached_metadata_handler_ =
+      MakeGarbageCollected<SourceKeyedCachedMetadataHandler>(
+          WTF::TextEncoding(), std::move(cached_metadata_sender));
+  body_loader_->StartLoadingBody(
+      this, ShouldUseIsolatedCodeCache(mojom::RequestContextType::HYPERLINK,
+                                       response_));
 }
 
 void DocumentLoader::DidInstallNewDocument(Document* document) {
@@ -1361,17 +1506,15 @@
   // resource's cache handler with the parser.
   ScriptableDocumentParser* scriptable_parser =
       parser_->AsScriptableDocumentParser();
-  if (scriptable_parser && GetResource()) {
-    scriptable_parser->SetInlineScriptCacheHandler(
-        ToRawResource(GetResource())->InlineScriptCacheHandler());
-  }
+  if (scriptable_parser && cached_metadata_handler_)
+    scriptable_parser->SetInlineScriptCacheHandler(cached_metadata_handler_);
 
   // FeaturePolicy is reset in the browser process on commit, so this needs to
   // be initialized and replicated to the browser process after commit messages
   // are sent in didCommitNavigation().
   WTF::String feature_policy(
       response_.HttpHeaderField(http_names::kFeaturePolicy));
-  MergeFeaturesFromOriginPolicy(feature_policy, request_.GetOriginPolicy());
+  MergeFeaturesFromOriginPolicy(feature_policy, origin_policy_);
   document->ApplyFeaturePolicyFromHeader(feature_policy);
 
   WTF::String report_only_feature_policy(
@@ -1452,11 +1595,9 @@
   if (!frame_->IsMainFrame())
     return;
 
-  WebURLRequest::PreviewsState previews_state = request_.GetPreviewsState();
-
   // Verify that certain types are not on main frame requests.
-  DCHECK_NE(WebURLRequest::kClientLoFiAutoReload, previews_state);
-  DCHECK_NE(WebURLRequest::kLazyImageLoadDeferred, previews_state);
+  DCHECK_NE(WebURLRequest::kClientLoFiAutoReload, previews_state_);
+  DCHECK_NE(WebURLRequest::kLazyImageLoadDeferred, previews_state_);
 
   static_assert(WebURLRequest::kPreviewsStateLast ==
                     WebURLRequest::kLazyImageLoadDeferred,
@@ -1465,9 +1606,9 @@
 
   // If the preview type is not unspecified, off, or no transform, it is a
   // preview that needs to be reported.
-  if (previews_state == WebURLRequest::kPreviewsUnspecified ||
-      previews_state & WebURLRequest::kPreviewsOff ||
-      previews_state & WebURLRequest::kPreviewsNoTransform) {
+  if (previews_state_ == WebURLRequest::kPreviewsUnspecified ||
+      previews_state_ & WebURLRequest::kPreviewsOff ||
+      previews_state_ & WebURLRequest::kPreviewsNoTransform) {
     return;
   }
 
diff --git a/third_party/blink/renderer/core/loader/document_loader.h b/third_party/blink/renderer/core/loader/document_loader.h
index 16bcd73..8e5dc48 100644
--- a/third_party/blink/renderer/core/loader/document_loader.h
+++ b/third_party/blink/renderer/core/loader/document_loader.h
@@ -34,6 +34,8 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/unguessable_token.h"
 #include "third_party/blink/public/platform/web_loading_behavior_flag.h"
+#include "third_party/blink/public/platform/web_navigation_body_loader.h"
+#include "third_party/blink/public/platform/web_scoped_virtual_time_pauser.h"
 #include "third_party/blink/public/web/web_frame_load_type.h"
 #include "third_party/blink/public/web/web_global_object_reuse_policy.h"
 #include "third_party/blink/public/web/web_navigation_params.h"
@@ -53,12 +55,12 @@
 #include "third_party/blink/renderer/core/loader/previews_resource_loading_hints.h"
 #include "third_party/blink/renderer/core/page/viewport_description.h"
 #include "third_party/blink/renderer/platform/loader/fetch/client_hints_preferences.h"
-#include "third_party/blink/renderer/platform/loader/fetch/raw_resource.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_error.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource_response.h"
-#include "third_party/blink/renderer/platform/loader/fetch/substitute_data.h"
+#include "third_party/blink/renderer/platform/loader/fetch/source_keyed_cached_metadata_handler.h"
 #include "third_party/blink/renderer/platform/shared_buffer.h"
+#include "third_party/blink/renderer/platform/weborigin/referrer.h"
 #include "third_party/blink/renderer/platform/wtf/hash_set.h"
 
 #include <memory>
@@ -83,9 +85,7 @@
 // The DocumentLoader fetches a main resource and handles the result.
 class CORE_EXPORT DocumentLoader
     : public GarbageCollectedFinalized<DocumentLoader>,
-      private RawResourceClient {
-  USING_GARBAGE_COLLECTED_MIXIN(DocumentLoader);
-
+      public WebNavigationBodyLoader::Client {
  public:
   DocumentLoader(LocalFrame*,
                  WebNavigationType navigation_type,
@@ -110,7 +110,7 @@
   const AtomicString& MimeType() const;
 
   const KURL& OriginalUrl() const;
-  const AtomicString& OriginalReferrer() const;
+  const Referrer& OriginalReferrer() const;
 
   ResourceFetcher* Fetcher() const { return fetcher_.Get(); }
 
@@ -126,12 +126,12 @@
     return resource_loading_hints_;
   }
 
-  const SubstituteData& GetSubstituteData() const { return substitute_data_; }
-
   const KURL& Url() const;
-  const KURL& UnreachableURL() const;
   const KURL& UrlForHistory() const;
-  const AtomicString& Referrer() const;
+  const AtomicString& HttpMethod() const;
+  mojom::FetchCacheMode CacheMode() const;
+  const Referrer& GetReferrer() const;
+  const KURL& UnreachableURL() const;
   EncodedFormData* HttpBody() const;
 
   void DidChangePerformanceTiming();
@@ -158,6 +158,9 @@
     return state_ >= kCommitted && !data_received_;
   }
 
+  bool HasSubstituteData() const { return has_substitute_data_; }
+  void FillNavigationParamsForErrorPage(WebNavigationParams*);
+
   // Without PlzNavigate, this is only false for a narrow window during
   // navigation start. For PlzNavigate, a navigation sent to the browser will
   // leave a dummy DocumentLoader in the NotStarted state until the navigation
@@ -225,11 +228,9 @@
 
   void LoadFailed(const ResourceError&);
 
-  void SetUserActivated();
-
   const AtomicString& RequiredCSP();
 
-  void Trace(blink::Visitor*) override;
+  virtual void Trace(blink::Visitor*);
 
   // For automation driver-initiated navigations over the devtools protocol,
   // |devtools_navigation_token_| is used to tag the navigation. This navigation
@@ -275,11 +276,6 @@
 
   Vector<KURL> redirect_chain_;
 
-  // The 'working' request. It may be mutated
-  // several times from the original request to include additional
-  // headers, cookie information, canonicalization and redirects.
-  ResourceRequest request_;
-
  private:
   // installNewDocument() does the work of creating a Document and
   // DocumentParser, as well as creating a new LocalDOMWindow if needed. It also
@@ -312,6 +308,7 @@
 
   bool MaybeCreateArchive();
 
+  void StartLoadingInternal();
   void FinishedLoading(TimeTicks finish_time);
   void CancelLoadAfterCSPDenied(const ResourceResponse&);
 
@@ -324,20 +321,13 @@
                                     WebFrameLoadType,
                                     HistoryNavigationType);
 
-  // RawResourceClient implementation
-  bool RedirectReceived(Resource*,
-                        const ResourceRequest&,
-                        const ResourceResponse&) final;
-  void ResponseReceived(Resource*,
-                        const ResourceResponse&,
-                        std::unique_ptr<WebDataConsumerHandle>) final;
-  void DataReceived(Resource*, const char* data, size_t length) final;
+  void HandleRedirect(const KURL& current_request_url);
+  // Returns true if we should proceed with navigation.
+  bool HandleResponse(const ResourceResponse&);
+  void HandleData(const char* data, size_t length);
 
-  // ResourceClient implementation
-  void NotifyFinished(Resource*) final;
-  String DebugName() const override { return "DocumentLoader"; }
-
-  bool MaybeLoadEmpty();
+  void LoadEmpty();
+  void CreateBodyLoaderFromStaticData(const SharedBuffer&);
 
   bool IsRedirectAfterPost(const ResourceRequest&, const ResourceResponse&);
 
@@ -351,6 +341,33 @@
   // Sends an intervention report if the page is being served as a preview.
   void ReportPreviewsIntervention() const;
 
+  // WebNavigationBodyLoader::Client
+  void BodyCodeCacheReceived(base::span<const uint8_t>) override;
+  void BodyDataReceived(base::span<const char> data) override;
+  void BodyLoadingFinished(TimeTicks completion_time,
+                           int64_t total_encoded_data_length,
+                           int64_t total_encoded_body_length,
+                           int64_t total_decoded_body_length,
+                           bool should_report_corb_blocking,
+                           const base::Optional<WebURLError>& error) override;
+
+  // These fields are copied from WebNavigationParams, see there for definition.
+  KURL url_;
+  AtomicString http_method_;
+  Referrer referrer_;
+  scoped_refptr<EncodedFormData> http_body_;
+  AtomicString http_content_type_;
+  WebURLRequest::PreviewsState previews_state_;
+  String origin_policy_;
+  scoped_refptr<const SecurityOrigin> requestor_origin_;
+  mojom::FetchCacheMode cache_mode_;
+  KURL unreachable_url_;
+  std::unique_ptr<WebNavigationBodyLoader> body_loader_;
+
+  // Params are saved in constructor and are cleared after StartLoading().
+  // TODO(dgozman): remove once StartLoading is merged with constructor.
+  std::unique_ptr<WebNavigationParams> params_;
+
   Member<LocalFrame> frame_;
   // This member is held so that we can update the document later. Do not use
   // this member outside ProvideDocumentToResourceFetcherProperties.
@@ -370,12 +387,10 @@
   // Stores the resource loading hints for this document.
   Member<PreviewsResourceLoadingHints> resource_loading_hints_;
 
-  SubstituteData substitute_data_;
-
   // A reference to actual request's url and referrer used to
   // inititate this load.
   KURL original_url_;
-  AtomicString original_referrer_;
+  Referrer original_referrer_;
 
   ResourceResponse response_;
 
@@ -416,10 +431,16 @@
   scoped_refptr<SharedBuffer> data_buffer_;
   base::UnguessableToken devtools_navigation_token_;
 
+  bool defers_loading_ = false;
+  bool has_substitute_data_ = false;
+
   // Whether this load request comes with a sitcky user activation.
-  bool had_sticky_activation_;
+  bool had_sticky_activation_ = false;
   // Whether this load request had a user activation when created.
-  bool had_transient_activation_;
+  bool had_transient_activation_ = false;
+
+  // See WebNavigationParams for definition.
+  bool was_discarded_ = false;
 
   bool listing_ftp_directory_ = false;
   bool loading_mhtml_archive_ = false;
@@ -427,6 +448,8 @@
   unsigned long main_resource_identifier_ = 0;
   scoped_refptr<ResourceTimingInfo> navigation_timing_info_;
   bool report_timing_info_to_parent_ = false;
+  WebScopedVirtualTimePauser virtual_time_pauser_;
+  Member<SourceKeyedCachedMetadataHandler> cached_metadata_handler_;
 
   // This UseCounter tracks feature usage associated with the lifetime of the
   // document load. Features recorded prior to commit will be recorded locally.
diff --git a/third_party/blink/renderer/core/loader/document_loader_test.cc b/third_party/blink/renderer/core/loader/document_loader_test.cc
index 681c837..c001d5b 100644
--- a/third_party/blink/renderer/core/loader/document_loader_test.cc
+++ b/third_party/blink/renderer/core/loader/document_loader_test.cc
@@ -5,6 +5,8 @@
 #include "third_party/blink/renderer/core/loader/document_loader.h"
 
 #include <queue>
+#include <string>
+#include <utility>
 #include "base/auto_reset.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/frame/frame_owner_element_type.h"
@@ -14,6 +16,7 @@
 #include "third_party/blink/renderer/core/frame/frame_test_helpers.h"
 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
 #include "third_party/blink/renderer/core/page/page.h"
+#include "third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 #include "third_party/blink/renderer/platform/testing/url_test_helpers.h"
 
@@ -81,27 +84,34 @@
   Platform::Current()->GetURLLoaderMockFactory()->SetLoaderDelegate(nullptr);
 }
 
-// Finally, test reentrant callbacks to DocumentLoader::dataReceived().
+// Finally, test reentrant callbacks to DocumentLoader::BodyDataReceived().
 TEST_F(DocumentLoaderTest, MultiChunkWithReentrancy) {
   // This test delegate chunks the response stage into three distinct stages:
-  // 1. The first dataReceived() callback, which triggers frame detach due to
-  //    commiting a provisional load.
-  // 2.  The middle part of the response, which is dispatched to
-  //    dataReceived() reentrantly.
+  // 1. The first BodyDataReceived() callback, which triggers frame detach
+  //    due to committing a provisional load.
+  // 2. The middle part of the response, which is dispatched to
+  //    BodyDataReceived() reentrantly.
   // 3. The final chunk, which is dispatched normally at the top-level.
   class ChildDelegate : public WebURLLoaderTestDelegate,
                         public frame_test_helpers::TestWebFrameClient {
    public:
     // WebURLLoaderTestDelegate overrides:
-    void DidReceiveData(WebURLLoaderClient* original_client,
-                        const char* data,
-                        int data_length) override {
-      EXPECT_EQ(34, data_length) << "foo.html was not served in a single chunk";
+    bool FillNavigationParamsResponse(WebNavigationParams* params) override {
+      params->response = WebURLResponse(params->url);
+      params->response.SetMIMEType("text/html");
+      params->response.SetHTTPStatusCode(200);
 
-      loader_client_ = original_client;
-      for (int i = 0; i < data_length; ++i)
+      std::string data("<html><body>foo</body></html>");
+      for (size_t i = 0; i < data.size(); i++)
         data_.push(data[i]);
 
+      auto body_loader = std::make_unique<StaticDataNavigationBodyLoader>();
+      body_loader_ = body_loader.get();
+      params->body_loader = std::move(body_loader);
+      return true;
+    }
+
+    void Serve() {
       {
         // Serve the first byte to the real WebURLLoaderCLient, which
         // should trigger frameDetach() due to committing a provisional
@@ -109,10 +119,14 @@
         base::AutoReset<bool> dispatching(&dispatching_did_receive_data_, true);
         DispatchOneByte();
       }
+
       // Serve the remaining bytes to complete the load.
       EXPECT_FALSE(data_.empty());
       while (!data_.empty())
         DispatchOneByte();
+
+      body_loader_->Finish();
+      body_loader_ = nullptr;
     }
 
     // WebLocalFrameClient overrides:
@@ -134,16 +148,16 @@
     void DispatchOneByte() {
       char c = data_.front();
       data_.pop();
-      loader_client_->DidReceiveData(&c, 1);
+      body_loader_->Write(&c, 1);
     }
 
     bool ServedReentrantly() const { return served_reentrantly_; }
 
    private:
-    WebURLLoaderClient* loader_client_ = nullptr;
     std::queue<char> data_;
     bool dispatching_did_receive_data_ = false;
     bool served_reentrantly_ = false;
+    StaticDataNavigationBodyLoader* body_loader_ = nullptr;
   };
 
   class MainFrameClient : public frame_test_helpers::TestWebFrameClient {
@@ -170,13 +184,16 @@
   web_view_helper_.Initialize(&main_frame_client);
 
   // This doesn't go through the mocked URL load path: it's just intended to
-  // setup a situation where didReceiveData() can be invoked reentrantly.
+  // setup a situation where BodyDataReceived() can be invoked reentrantly.
   frame_test_helpers::LoadHTMLString(MainFrame(), "<iframe></iframe>",
                                      url_test_helpers::ToKURL("about:blank"));
 
   Platform::Current()->GetURLLoaderMockFactory()->SetLoaderDelegate(
       &child_delegate);
-  frame_test_helpers::LoadFrame(MainFrame(), "https://example.com/foo.html");
+  frame_test_helpers::LoadFrameDontWait(
+      MainFrame(), url_test_helpers::ToKURL("https://example.com/foo.html"));
+  child_delegate.Serve();
+  frame_test_helpers::PumpPendingRequestsForFrameToLoad(MainFrame());
   Platform::Current()->GetURLLoaderMockFactory()->SetLoaderDelegate(nullptr);
 
   EXPECT_TRUE(child_delegate.ServedReentrantly());
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc
index b6bdefc..e2599e0 100644
--- a/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -224,16 +224,8 @@
 void FrameLoader::Init() {
   ScriptForbiddenScope forbid_scripts;
 
-  ResourceRequest initial_request{KURL(g_empty_string)};
-  initial_request.SetRequestContext(mojom::RequestContextType::INTERNAL);
-  initial_request.SetFrameType(
-      frame_->IsMainFrame() ? network::mojom::RequestContextFrameType::kTopLevel
-                            : network::mojom::RequestContextFrameType::kNested);
-  initial_request.SetHasUserGesture(
-      LocalFrame::HasTransientUserActivation(frame_));
-
   auto navigation_params = std::make_unique<WebNavigationParams>();
-  navigation_params->request = WrappedResourceRequest(initial_request);
+  navigation_params->url = KURL(g_empty_string);
   provisional_document_loader_ = CreateDocumentLoader(
       kWebNavigationTypeOther, std::move(navigation_params),
       nullptr /* extra_data */);
@@ -1005,19 +997,8 @@
   if (HTMLFrameOwnerElement* element = frame_->DeprecatedLocalOwner())
     element->CancelPendingLazyLoad();
 
-  ResourceRequest& resource_request =
-      navigation_params->request.ToMutableResourceRequest();
-  resource_request.SetHasUserGesture(
-      LocalFrame::HasTransientUserActivation(frame_));
-  resource_request.SetFetchRequestMode(
-      network::mojom::FetchRequestMode::kNavigate);
-  resource_request.SetFetchCredentialsMode(
-      network::mojom::FetchCredentialsMode::kInclude);
-  resource_request.SetFetchRedirectMode(
-      network::mojom::FetchRedirectMode::kManual);
-
   navigation_params->frame_load_type = DetermineFrameLoadType(
-      resource_request.Url(), resource_request.HttpMethod(),
+      navigation_params->url, navigation_params->http_method,
       nullptr /* origin_document */, navigation_params->unreachable_url,
       navigation_params->frame_load_type);
 
@@ -1034,8 +1015,7 @@
 
   if (!CancelProvisionalLoaderForNewNavigation(
           false /* cancel_scheduled_navigations */,
-          DocumentLoader::WillLoadUrlAsEmpty(
-              navigation_params->request.Url()))) {
+          DocumentLoader::WillLoadUrlAsEmpty(navigation_params->url))) {
     return;
   }
 
@@ -1043,15 +1023,8 @@
   // It seems incorrect to pass |false| for |have_event| and then use
   // determined navigation type to update resource request.
   WebNavigationType navigation_type = DetermineNavigationType(
-      navigation_params->frame_load_type, resource_request.HttpBody(),
-      false /* have_event */);
-  // TODO(dgozman): should these fields be propagated from StartNavigation
-  // and/or set by the caller instead?
-  resource_request.SetRequestContext(
-      DetermineRequestContextFromNavigationType(navigation_type));
-  resource_request.SetFrameType(
-      frame_->IsMainFrame() ? network::mojom::RequestContextFrameType::kTopLevel
-                            : network::mojom::RequestContextFrameType::kNested);
+      navigation_params->frame_load_type,
+      !navigation_params->http_body.IsNull(), false /* have_event */);
 
   HistoryItem* history_item = nullptr;
   if (IsBackForwardLoadType(navigation_params->frame_load_type)) {
@@ -1135,7 +1108,7 @@
   }
 
   auto navigation_params = std::make_unique<WebNavigationParams>();
-  navigation_params->request = info.url_request;
+  navigation_params->url = info.url_request.Url();
   navigation_params->frame_load_type = info.frame_load_type;
   navigation_params->is_client_redirect = info.is_client_redirect;
   navigation_params->navigation_timings.input_start = info.input_start;
diff --git a/third_party/blink/renderer/core/testing/sim/sim_network.cc b/third_party/blink/renderer/core/testing/sim/sim_network.cc
index 22767b3..69d726a6 100644
--- a/third_party/blink/renderer/core/testing/sim/sim_network.cc
+++ b/third_party/blink/renderer/core/testing/sim/sim_network.cc
@@ -4,13 +4,18 @@
 
 #include "third_party/blink/renderer/core/testing/sim/sim_network.h"
 
+#include <memory>
+#include <utility>
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_url_error.h"
 #include "third_party/blink/public/platform/web_url_loader.h"
 #include "third_party/blink/public/platform/web_url_loader_client.h"
 #include "third_party/blink/public/platform/web_url_loader_mock_factory.h"
 #include "third_party/blink/public/platform/web_url_response.h"
+#include "third_party/blink/public/web/web_navigation_params.h"
+#include "third_party/blink/renderer/core/loader/document_loader.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_request.h"
+#include "third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.h"
 
 namespace blink {
 
@@ -100,4 +105,16 @@
   Platform::Current()->GetURLLoaderMockFactory()->UnregisterURL(request.url_);
 }
 
+bool SimNetwork::FillNavigationParamsResponse(WebNavigationParams* params) {
+  auto it = requests_.find(params->url.GetString());
+  SimRequestBase* request = it->value;
+  params->response = WebURLResponse(params->url);
+  params->response.SetMIMEType(request->mime_type_);
+  params->response.SetHTTPStatusCode(200);
+  auto body_loader = std::make_unique<StaticDataNavigationBodyLoader>();
+  request->UsedForNavigation(body_loader.get());
+  params->body_loader = std::move(body_loader);
+  return true;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/testing/sim/sim_network.h b/third_party/blink/renderer/core/testing/sim/sim_network.h
index bce0ac075..56f424d 100644
--- a/third_party/blink/renderer/core/testing/sim/sim_network.h
+++ b/third_party/blink/renderer/core/testing/sim/sim_network.h
@@ -50,6 +50,7 @@
                         int64_t total_encoded_data_length,
                         int64_t total_encoded_body_length,
                         int64_t total_decoded_body_length) override;
+  bool FillNavigationParamsResponse(WebNavigationParams*) override;
 
   SimRequestBase* current_request_;
   HashMap<String, SimRequestBase*> requests_;
diff --git a/third_party/blink/renderer/core/testing/sim/sim_request.cc b/third_party/blink/renderer/core/testing/sim/sim_request.cc
index 4d71825..4cee44e 100644
--- a/third_party/blink/renderer/core/testing/sim/sim_request.cc
+++ b/third_party/blink/renderer/core/testing/sim/sim_request.cc
@@ -4,8 +4,10 @@
 
 #include "third_party/blink/renderer/core/testing/sim/sim_request.h"
 
+#include <vector>
 #include "third_party/blink/public/platform/web_url_loader_client.h"
 #include "third_party/blink/renderer/core/testing/sim/sim_network.h"
+#include "third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 
 namespace blink {
@@ -24,10 +26,12 @@
 
 SimRequestBase::~SimRequestBase() {
   DCHECK(!client_);
+  DCHECK(!navigation_body_loader_);
 }
 
 void SimRequestBase::DidReceiveResponse(WebURLLoaderClient* client,
                                         const WebURLResponse& response) {
+  DCHECK(!navigation_body_loader_);
   client_ = client;
   response_ = response;
   started_ = false;
@@ -39,6 +43,15 @@
   error_ = error;
 }
 
+void SimRequestBase::UsedForNavigation(
+    StaticDataNavigationBodyLoader* navigation_body_loader) {
+  DCHECK(start_immediately_);
+  DCHECK(!client_);
+  DCHECK(!started_);
+  navigation_body_loader_ = navigation_body_loader;
+  started_ = true;
+}
+
 void SimRequestBase::StartInternal() {
   DCHECK(!started_);
   started_ = true;
@@ -51,7 +64,10 @@
   DCHECK(started_);
   DCHECK(!error_);
   total_encoded_data_length_ += data.length();
-  client_->DidReceiveData(data.Utf8().data(), data.length());
+  if (navigation_body_loader_)
+    navigation_body_loader_->Write(data.Utf8().data(), data.length());
+  else
+    client_->DidReceiveData(data.Utf8().data(), data.length());
 }
 
 void SimRequestBase::Write(const Vector<char>& data) {
@@ -60,7 +76,10 @@
   DCHECK(started_);
   DCHECK(!error_);
   total_encoded_data_length_ += data.size();
-  client_->DidReceiveData(data.data(), data.size());
+  if (navigation_body_loader_)
+    navigation_body_loader_->Write(data.data(), data.size());
+  else
+    client_->DidReceiveData(data.data(), data.size());
 }
 
 void SimRequestBase::Finish() {
@@ -68,14 +87,19 @@
     ServePending();
   DCHECK(started_);
   if (error_) {
+    DCHECK(!navigation_body_loader_);
     client_->DidFail(*error_, total_encoded_data_length_,
                      total_encoded_data_length_, total_encoded_data_length_);
   } else {
-    // TODO(esprehn): Is claiming a request time of 0 okay for tests?
-    client_->DidFinishLoading(
-        TimeTicks(), total_encoded_data_length_, total_encoded_data_length_,
-        total_encoded_data_length_, false,
-        std::vector<network::cors::PreflightTimingInfo>());
+    if (navigation_body_loader_) {
+      navigation_body_loader_->Finish();
+    } else {
+      // TODO(esprehn): Is claiming a request time of 0 okay for tests?
+      client_->DidFinishLoading(
+          TimeTicks(), total_encoded_data_length_, total_encoded_data_length_,
+          total_encoded_data_length_, false,
+          std::vector<network::cors::PreflightTimingInfo>());
+    }
   }
   Reset();
 }
@@ -103,6 +127,7 @@
 void SimRequestBase::Reset() {
   started_ = false;
   client_ = nullptr;
+  navigation_body_loader_ = nullptr;
   SimNetwork::Current().RemoveRequest(*this);
 }
 
diff --git a/third_party/blink/renderer/core/testing/sim/sim_request.h b/third_party/blink/renderer/core/testing/sim/sim_request.h
index e757460..5e897480 100644
--- a/third_party/blink/renderer/core/testing/sim/sim_request.h
+++ b/third_party/blink/renderer/core/testing/sim/sim_request.h
@@ -15,6 +15,7 @@
 namespace blink {
 
 class SimNetwork;
+class StaticDataNavigationBodyLoader;
 class WebURLLoaderClient;
 
 // Simulates a single request for a resource from the server. Requires a
@@ -49,6 +50,7 @@
   // Used by SimNetwork.
   void DidReceiveResponse(WebURLLoaderClient*, const WebURLResponse&);
   void DidFail(const WebURLError&);
+  void UsedForNavigation(StaticDataNavigationBodyLoader*);
 
   KURL url_;
   String mime_type_;
@@ -58,6 +60,7 @@
   base::Optional<WebURLError> error_;
   WebURLLoaderClient* client_;
   unsigned total_encoded_data_length_;
+  StaticDataNavigationBodyLoader* navigation_body_loader_ = nullptr;
 };
 
 // This request can be used as a main resource request for navigation.
diff --git a/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js b/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js
index 7f81b836..045ed1e 100644
--- a/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js
+++ b/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js
@@ -1673,14 +1673,14 @@
         return code < 16 ? '\\u0' + code.toString(16) : '\\u' + code.toString(16);
       }
 
-      if (/[\u0000-\u001f\u007f-\u009f]|\'/.test(str)) {
+      if (/[\u0000-\u001f\u007f-\u009f!]|\'/.test(str)) {
         // Use ANSI-C quoting syntax.
         return '$\'' +
             str.replace(/\\/g, '\\\\')
                 .replace(/\'/g, '\\\'')
                 .replace(/\n/g, '\\n')
                 .replace(/\r/g, '\\r')
-                .replace(/[\u0000-\u001f\u007f-\u009f]/g, escapeCharacter) +
+                .replace(/[\u0000-\u001f\u007f-\u009f!]/g, escapeCharacter) +
             '\'';
       } else {
         // Use single quote syntax.
diff --git a/third_party/blink/renderer/devtools/front_end/protocol/InspectorBackend.js b/third_party/blink/renderer/devtools/front_end/protocol/InspectorBackend.js
index 93c140d0d..b64b517 100644
--- a/third_party/blink/renderer/devtools/front_end/protocol/InspectorBackend.js
+++ b/third_party/blink/renderer/devtools/front_end/protocol/InspectorBackend.js
@@ -408,7 +408,6 @@
             messageObject);
         return;
       }
-
       session.target._dispatchers[domainName].dispatch(method[1], messageObject);
     }
   }
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc b/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc
index 72a1c55..c0c3ffa 100644
--- a/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc
+++ b/third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/modules/gamepad/gamepad_haptic_actuator.h"
 
+#include "base/bind_helpers.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/modules/gamepad/gamepad_dispatcher.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni
index 52889de..54bb218 100644
--- a/third_party/blink/renderer/modules/modules_idl_files.gni
+++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -451,7 +451,6 @@
           "webusb/usb_out_transfer_result.idl",
           "xr/xr.idl",
           "xr/xr_bounded_reference_space.idl",
-          "xr/xr_device.idl",
           "xr/xr_frame.idl",
           "xr/xr_hit_result.idl",
           "xr/xr_input_pose.idl",
diff --git a/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc b/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc
index c6ed468..f5d29f9b 100644
--- a/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc
+++ b/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.h"
 
+#include "base/bind_helpers.h"
 #include "third_party/blink/public/common/manifest/web_display_mode.h"
 #include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
 #include "third_party/blink/renderer/core/dom/document.h"
diff --git a/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc b/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc
index 413cec9e..d61d425 100644
--- a/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc
+++ b/third_party/blink/renderer/modules/service_worker/web_embedded_worker_impl_test.cc
@@ -171,16 +171,13 @@
 }
 
 TEST_F(WebEmbeddedWorkerImplTest, TerminateWhileLoadingScript) {
-  EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
-  worker_->StartWorkerContext(start_data_);
-  testing::Mock::VerifyAndClearExpectations(mock_client_);
-
   // Load the shadow page.
+  EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
   EXPECT_CALL(*mock_installed_scripts_manager_,
               IsScriptInstalled(KURL(start_data_.script_url)))
       .Times(testing::AtLeast(1))
       .WillRepeatedly(testing::Return(false));
-  Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+  worker_->StartWorkerContext(start_data_);
   testing::Mock::VerifyAndClearExpectations(mock_client_);
   testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
 
@@ -191,19 +188,15 @@
 }
 
 TEST_F(WebEmbeddedWorkerImplTest, TerminateWhilePausedAfterDownload) {
-  EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
+  // Load the shadow page.
   start_data_.pause_after_download_mode =
       WebEmbeddedWorkerStartData::kPauseAfterDownload;
-  worker_->StartWorkerContext(start_data_);
-  testing::Mock::VerifyAndClearExpectations(mock_client_);
-
-  // Load the shadow page.
+  EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
   EXPECT_CALL(*mock_installed_scripts_manager_,
               IsScriptInstalled(KURL(start_data_.script_url)))
       .Times(testing::AtLeast(1))
       .WillRepeatedly(testing::Return(false));
-
-  Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+  worker_->StartWorkerContext(start_data_);
   testing::Mock::VerifyAndClearExpectations(mock_client_);
   testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
 
@@ -219,6 +212,7 @@
 }
 
 TEST_F(WebEmbeddedWorkerImplTest, ScriptNotFound) {
+  // Load the shadow page.
   WebURL script_url =
       url_test_helpers::ToKURL("https://www.example.com/sw-404.js");
   WebURLResponse response;
@@ -228,18 +222,12 @@
   Platform::Current()->GetURLLoaderMockFactory()->RegisterErrorURL(
       script_url, response, error);
   start_data_.script_url = script_url;
-
   EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
-  worker_->StartWorkerContext(start_data_);
-  testing::Mock::VerifyAndClearExpectations(mock_client_);
-
-  // Load the shadow page.
   EXPECT_CALL(*mock_installed_scripts_manager_,
               IsScriptInstalled(KURL(start_data_.script_url)))
       .Times(testing::AtLeast(1))
       .WillRepeatedly(testing::Return(false));
-
-  Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+  worker_->StartWorkerContext(start_data_);
   testing::Mock::VerifyAndClearExpectations(mock_client_);
   testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
 
@@ -258,16 +246,13 @@
 #define MAYBE_DontPauseAfterDownload DontPauseAfterDownload
 #endif
 TEST_F(WebEmbeddedWorkerImplTest, MAYBE_DontPauseAfterDownload) {
-  EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
-  worker_->StartWorkerContext(start_data_);
-  testing::Mock::VerifyAndClearExpectations(mock_client_);
-
   // Load the shadow page.
+  EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
   EXPECT_CALL(*mock_installed_scripts_manager_,
               IsScriptInstalled(KURL(start_data_.script_url)))
       .Times(testing::AtLeast(1))
       .WillRepeatedly(testing::Return(false));
-  Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+  worker_->StartWorkerContext(start_data_);
   testing::Mock::VerifyAndClearExpectations(mock_client_);
   testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
 
@@ -297,18 +282,15 @@
 #define MAYBE_PauseAfterDownload PauseAfterDownload
 #endif
 TEST_F(WebEmbeddedWorkerImplTest, MAYBE_PauseAfterDownload) {
-  EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
-  start_data_.pause_after_download_mode =
-      WebEmbeddedWorkerStartData::kPauseAfterDownload;
-  worker_->StartWorkerContext(start_data_);
-  testing::Mock::VerifyAndClearExpectations(mock_client_);
-
   // Load the shadow page.
+  EXPECT_CALL(*mock_client_, WorkerReadyForInspection()).Times(1);
   EXPECT_CALL(*mock_installed_scripts_manager_,
               IsScriptInstalled(KURL(start_data_.script_url)))
       .Times(testing::AtLeast(1))
       .WillRepeatedly(testing::Return(false));
-  Platform::Current()->GetURLLoaderMockFactory()->ServeAsynchronousRequests();
+  start_data_.pause_after_download_mode =
+      WebEmbeddedWorkerStartData::kPauseAfterDownload;
+  worker_->StartWorkerContext(start_data_);
   testing::Mock::VerifyAndClearExpectations(mock_client_);
   testing::Mock::VerifyAndClearExpectations(mock_installed_scripts_manager_);
 
diff --git a/third_party/blink/renderer/modules/xr/BUILD.gn b/third_party/blink/renderer/modules/xr/BUILD.gn
index 7a03efc7..0f4806e 100644
--- a/third_party/blink/renderer/modules/xr/BUILD.gn
+++ b/third_party/blink/renderer/modules/xr/BUILD.gn
@@ -12,8 +12,6 @@
     "xr_bounded_reference_space.h",
     "xr_canvas_input_provider.cc",
     "xr_canvas_input_provider.h",
-    "xr_device.cc",
-    "xr_device.h",
     "xr_frame.cc",
     "xr_frame.h",
     "xr_frame_provider.cc",
diff --git a/third_party/blink/renderer/modules/xr/xr.cc b/third_party/blink/renderer/modules/xr/xr.cc
index e46765a..017c7c27 100644
--- a/third_party/blink/renderer/modules/xr/xr.cc
+++ b/third_party/blink/renderer/modules/xr/xr.cc
@@ -12,9 +12,9 @@
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/modules/event_modules.h"
 #include "third_party/blink/renderer/modules/event_target_modules.h"
-#include "third_party/blink/renderer/modules/xr/xr_device.h"
 #include "third_party/blink/renderer/modules/xr/xr_frame_provider.h"
 #include "third_party/blink/renderer/modules/xr/xr_presentation_context.h"
 #include "third_party/blink/renderer/modules/xr/xr_session.h"
@@ -44,18 +44,30 @@
 
 const char kNoDevicesMessage[] = "No XR hardware found.";
 
-// Helper method to convert IDL options into Mojo options.
-device::mojom::blink::XRSessionOptionsPtr convertIdlOptionsToMojo(
-    const XRSessionCreationOptions& options) {
+// Helper method to convert session mode into Mojo options.
+device::mojom::blink::XRSessionOptionsPtr convertModeToMojo(
+    XRSession::SessionMode mode) {
   auto session_options = device::mojom::blink::XRSessionOptions::New();
-  session_options->immersive = options.immersive();
-  session_options->environment_integration = options.environmentIntegration();
+  session_options->immersive = (mode == XRSession::kModeImmersiveVR ||
+                                mode == XRSession::kModeImmersiveAR);
+  session_options->environment_integration =
+      (mode == XRSession::kModeInlineAR || mode == XRSession::kModeImmersiveAR);
 
   return session_options;
 }
 
 }  // namespace
 
+XR::PendingSessionQuery::PendingSessionQuery(
+    ScriptPromiseResolver* resolver,
+    XRSession::SessionMode session_mode)
+    : resolver(resolver), mode(session_mode) {}
+
+void XR::PendingSessionQuery::Trace(blink::Visitor* visitor) {
+  visitor->Trace(resolver);
+  visitor->Trace(output_context);
+}
+
 XR::XR(LocalFrame& frame, int64_t ukm_source_id)
     : ContextLifecycleObserver(frame.GetDocument()),
       FocusChangedObserver(frame.GetPage()),
@@ -105,9 +117,9 @@
 
 const char* XR::checkSessionSupport(
     const XRSessionCreationOptions* options) const {
-  if (!options->immersive()) {
-    // Validation for non-immersive sessions. Validation for immersive sessions
-    // happens browser side.
+  if (options->mode() == "inline" || options->mode() == "legacy-inline-ar") {
+    // Validation for inline sessions. (Validation for immersive sessions
+    // happens browser-side.)
     if (!options->hasOutputContext()) {
       return kNoOutputContext;
     }
@@ -116,53 +128,110 @@
   return nullptr;
 }
 
-ScriptPromise XR::supportsSession(ScriptState* script_state,
-                                  const XRSessionCreationOptions* options) {
-  // Only called from XRDevice, and as such device_ must be initialized first.
-  DCHECK(device_);
-
-  // Check to see if the device is capable of supporting the requested session
-  // options. Note that reporting support here does not guarantee that creating
-  // a session with those options will succeed, as other external and
-  // time-sensitve factors (focus state, existence of another immersive session,
-  // etc.) may prevent the creation of a session as well.
-  const char* reject_reason = checkSessionSupport(options);
-  if (reject_reason) {
+ScriptPromise XR::supportsSessionMode(ScriptState* script_state,
+                                      const String& mode) {
+  LOG(ERROR) << __FUNCTION__;
+  LocalFrame* frame = GetFrame();
+  if (!frame) {
+    // Reject if the frame is inaccessible.
     return ScriptPromise::RejectWithDOMException(
-        script_state, DOMException::Create(DOMExceptionCode::kNotSupportedError,
-                                           reject_reason));
+        script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+                                           kNavigatorDetachedError));
   }
 
-  // If the above checks pass, resolve without a value. Future API iterations
-  // may specify a value to be returned here.
+  if (!frame->GetDocument()->IsFeatureEnabled(
+          mojom::FeaturePolicyFeature::kWebVr,
+          ReportOptions::kReportOnFailure)) {
+    // Only allow the call to be made if the appropriate feature policy is in
+    // place.
+    return ScriptPromise::RejectWithDOMException(
+        script_state, DOMException::Create(DOMExceptionCode::kSecurityError,
+                                           kFeaturePolicyBlocked));
+  }
+
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
   ScriptPromise promise = resolver->Promise();
 
-  device::mojom::blink::XRSessionOptionsPtr session_options =
-      convertIdlOptionsToMojo(*options);
+  if (mode == "inline") {
+    // `inline` sessions are always supported if not blocked by feature policy.
+    resolver->Resolve();
+  } else {
+    // For all other modes we need to check with the service.
+    PendingSessionQuery* query = MakeGarbageCollected<PendingSessionQuery>(
+        resolver, XRSession::stringToSessionMode(mode));
 
-  device_->SupportsSession(
-      std::move(session_options),
-      WTF::Bind(&XR::OnSupportsSessionReturned, WrapPersistent(this),
-                WrapPersistent(resolver)));
+    if (!device_) {
+      LOG(ERROR) << "!device";
+      pending_mode_queries_.push_back(query);
+
+      // The pending queries will be resolved once the device is returned.
+      EnsureDevice();
+    } else {
+      DispatchSupportsSessionMode(query);
+    }
+  }
+
+  LOG(ERROR) << "/" << __FUNCTION__;
 
   return promise;
 }
 
+void XR::DispatchSupportsSessionMode(PendingSessionQuery* query) {
+  LOG(ERROR) << __FUNCTION__;
+  if (!device_) {
+    // If we don't have a device by the time we reach this call it indicates
+    // that there's no WebXR hardware. Reject as not supported.
+    query->resolver->Reject(DOMException::Create(
+        DOMExceptionCode::kNotSupportedError, kSessionNotSupported));
+    return;
+  }
+
+  device::mojom::blink::XRSessionOptionsPtr session_options =
+      convertModeToMojo(query->mode);
+
+  device_->SupportsSession(
+      std::move(session_options),
+      WTF::Bind(&XR::OnSupportsSessionReturned, WrapPersistent(this),
+                WrapPersistent(query)));
+  LOG(ERROR) << "/" << __FUNCTION__;
+}
+
 ScriptPromise XR::requestSession(ScriptState* script_state,
                                  const XRSessionCreationOptions* options) {
-  // Only called from XRDevice, and as such device_ must be initialized first.
-  DCHECK(device_);
+  LocalFrame* frame = GetFrame();
+  if (!frame) {
+    // Reject if the frame is inaccessible.
+    return ScriptPromise::RejectWithDOMException(
+        script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
+                                           kNavigatorDetachedError));
+  }
 
-  Document* doc = To<Document>(ExecutionContext::From(script_state));
-
-  if (options->immersive() && !did_log_request_immersive_session_ && doc) {
+  Document* doc = frame->GetDocument();
+  bool immersive =
+      (options->mode() == "immersive-vr" || options->mode() == "immersive-ar");
+  if (immersive && !did_log_request_immersive_session_ && doc) {
     ukm::builders::XR_WebXR(GetSourceId())
         .SetDidRequestPresentation(1)
         .Record(doc->UkmRecorder());
     did_log_request_immersive_session_ = true;
   }
 
+  if (!doc->IsFeatureEnabled(mojom::FeaturePolicyFeature::kWebVr,
+                             ReportOptions::kReportOnFailure)) {
+    // Only allow the call to be made if the appropriate feature policy is in
+    // place.
+    return ScriptPromise::RejectWithDOMException(
+        script_state, DOMException::Create(DOMExceptionCode::kSecurityError,
+                                           kFeaturePolicyBlocked));
+  }
+
+  // If we no longer have a valid service connection reject the request.
+  if (!service_) {
+    return ScriptPromise::RejectWithDOMException(
+        script_state, DOMException::Create(DOMExceptionCode::kNotFoundError,
+                                           kNoDevicesMessage));
+  }
+
   // Check first to see if the device is capable of supporting the requested
   // options.
   const char* reject_reason = checkSessionSupport(options);
@@ -178,7 +247,7 @@
 
   // Check if the current page state prevents the requested session from being
   // created.
-  if (options->immersive()) {
+  if (options->mode() == "immersive-vr" || options->mode() == "immersive-ar") {
     if (frameProvider()->immersive_session()) {
       return ScriptPromise::RejectWithDOMException(
           script_state,
@@ -194,23 +263,51 @@
   }
 
   // All AR sessions require a user gesture.
-  if (options->environmentIntegration()) {
+  if (options->mode() == "legacy-inline-ar") {
     if (!has_user_activation) {
       return ScriptPromise::RejectWithDOMException(
           script_state, DOMException::Create(DOMExceptionCode::kSecurityError,
                                              kRequestRequiresUserActivation));
     }
+
+    doc->AddConsoleMessage(ConsoleMessage::Create(
+        kOtherMessageSource, kWarningMessageLevel,
+        "Inline AR is deprecated and will be removed soon."));
   }
 
   ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
   ScriptPromise promise = resolver->Promise();
 
-  device::mojom::blink::XRSessionOptionsPtr session_options =
-      convertIdlOptionsToMojo(*options);
-  session_options->has_user_activation = has_user_activation;
-
-  XRPresentationContext* output_context =
+  PendingSessionQuery* query = MakeGarbageCollected<PendingSessionQuery>(
+      resolver, XRSession::stringToSessionMode(options->mode()));
+  query->output_context =
       options->hasOutputContext() ? options->outputContext() : nullptr;
+  query->has_user_activation = has_user_activation;
+
+  if (!device_) {
+    pending_session_requests_.push_back(query);
+
+    // The pending queries will be resolved once the device is returned.
+    EnsureDevice();
+  } else {
+    DispatchRequestSession(query);
+  }
+
+  return promise;
+}
+
+void XR::DispatchRequestSession(PendingSessionQuery* query) {
+  if (!device_) {
+    // If we don't have a device by the time we reach this call it indicates
+    // that there's no WebXR hardware. Reject as not supported.
+    query->resolver->Reject(DOMException::Create(
+        DOMExceptionCode::kNotSupportedError, kSessionNotSupported));
+    return;
+  }
+
+  device::mojom::blink::XRSessionOptionsPtr session_options =
+      convertModeToMojo(query->mode);
+  session_options->has_user_activation = query->has_user_activation;
 
   // TODO(http://crbug.com/826899) Once device activation is sorted out for
   // WebXR, either pass in the correct value for metrics to know whether
@@ -219,73 +316,11 @@
   device_->RequestSession(
       std::move(session_options), false /* triggered by display activate */,
       WTF::Bind(&XR::OnRequestSessionReturned, WrapWeakPersistent(this),
-                WrapPersistent(resolver), WrapPersistent(output_context),
-                options->environmentIntegration(), options->immersive()));
-  return promise;
-}
-
-ScriptPromise XR::requestDevice(ScriptState* script_state) {
-  LocalFrame* frame = GetFrame();
-  if (!frame) {
-    // Reject if the frame is inaccessible.
-    return ScriptPromise::RejectWithDOMException(
-        script_state, DOMException::Create(DOMExceptionCode::kInvalidStateError,
-                                           kNavigatorDetachedError));
-  }
-
-  if (!did_log_requestDevice_ && frame->GetDocument()) {
-    ukm::builders::XR_WebXR(ukm_source_id_)
-        .SetDidRequestAvailableDevices(1)
-        .Record(frame->GetDocument()->UkmRecorder());
-    did_log_requestDevice_ = true;
-  }
-
-  if (!frame->GetDocument()->IsFeatureEnabled(
-          mojom::FeaturePolicyFeature::kWebVr,
-          ReportOptions::kReportOnFailure)) {
-    // Only allow the call to be made if the appropriate feature policy is in
-    // place.
-    return ScriptPromise::RejectWithDOMException(
-        script_state, DOMException::Create(DOMExceptionCode::kSecurityError,
-                                           kFeaturePolicyBlocked));
-  }
-
-  // If we're still waiting for a previous call to resolve return that promise
-  // again.
-  if (pending_devices_resolver_) {
-    return pending_devices_resolver_->Promise();
-  }
-
-  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
-  ScriptPromise promise = resolver->Promise();
-
-  // If we no longer have a valid service connection reject the request.
-  if (!service_) {
-    resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
-                                          kNoDevicesMessage));
-    return promise;
-  }
-
-  // If we already have a device, use that.
-  if (xr_device_) {
-    resolver->Resolve(xr_device_);
-    return promise;
-  }
-
-  // Otherwise wait for device request callback.
-  pending_devices_resolver_ = resolver;
-
-  // If we're waiting for sync, then request device is already underway.
-  if (pending_device_) {
-    return promise;
-  }
-
-  EnsureDevice();
-
-  return promise;
+                WrapPersistent(query)));
 }
 
 void XR::EnsureDevice() {
+  LOG(ERROR) << __FUNCTION__;
   // Exit if we have a device or are waiting for a device.
   if (device_ || pending_device_) {
     return;
@@ -294,6 +329,7 @@
   service_->RequestDevice(
       WTF::Bind(&XR::OnRequestDeviceReturned, WrapPersistent(this)));
   pending_device_ = true;
+  LOG(ERROR) << "/" << __FUNCTION__;
 }
 
 // This will be called when the XR hardware or capabilities have potentially
@@ -304,74 +340,80 @@
 }
 
 void XR::OnRequestDeviceReturned(device::mojom::blink::XRDevicePtr device) {
+  LOG(ERROR) << __FUNCTION__;
   pending_device_ = false;
   if (device) {
+    LOG(ERROR) << "Got device";
     device_ = std::move(device);
-    xr_device_ = MakeGarbageCollected<XRDevice>(this);
-  }
-  ResolveRequestDevice();
-}
 
-// Called when details for every connected XRDevice has been received.
-void XR::ResolveRequestDevice() {
-  if (pending_devices_resolver_) {
-    if (!device_) {
-      pending_devices_resolver_->Reject(DOMException::Create(
-          DOMExceptionCode::kNotFoundError, kNoDevicesMessage));
-    } else {
-      // Log metrics
-      if (!did_log_returned_device_ || !did_log_supports_immersive_) {
-        Document* doc = GetFrame() ? GetFrame()->GetDocument() : nullptr;
-        if (doc) {
-          ukm::builders::XR_WebXR ukm_builder(ukm_source_id_);
-          ukm_builder.SetReturnedDevice(1);
-          did_log_returned_device_ = true;
+    // Log metrics
+    if (!did_log_returned_device_ || !did_log_supports_immersive_) {
+      LOG(ERROR) << "Doing Logging";
+      Document* doc = GetFrame() ? GetFrame()->GetDocument() : nullptr;
+      if (doc) {
+        ukm::builders::XR_WebXR ukm_builder(ukm_source_id_);
+        ukm_builder.SetReturnedDevice(1);
+        did_log_returned_device_ = true;
 
-          ukm_builder.Record(doc->UkmRecorder());
+        ukm_builder.Record(doc->UkmRecorder());
 
-          device::mojom::blink::XRSessionOptionsPtr session_options =
-              device::mojom::blink::XRSessionOptions::New();
-          session_options->immersive = true;
+        device::mojom::blink::XRSessionOptionsPtr session_options =
+            device::mojom::blink::XRSessionOptions::New();
+        session_options->immersive = true;
 
-          // TODO(http://crbug.com/872086) This shouldn't need to be called.
-          // This information should be logged on the browser side.
-          device_->SupportsSession(
-              std::move(session_options),
-              WTF::Bind(&XR::ReportImmersiveSupported, WrapPersistent(this)));
-        }
+        // TODO(http://crbug.com/872086) This shouldn't need to be called.
+        // This information should be logged on the browser side.
+        device_->SupportsSession(
+            std::move(session_options),
+            WTF::Bind(&XR::ReportImmersiveSupported, WrapPersistent(this)));
       }
-
-      // Return the device.
-      pending_devices_resolver_->Resolve(xr_device_);
     }
-
-    pending_devices_resolver_ = nullptr;
   }
+
+  DispatchPendingSessionCalls();
+  LOG(ERROR) << "/" << __FUNCTION__;
 }
 
-void XR::OnSupportsSessionReturned(ScriptPromiseResolver* resolver,
+void XR::DispatchPendingSessionCalls() {
+  LOG(ERROR) << __FUNCTION__;
+  // Process any calls that were waiting for the device query to be returned.
+  for (auto& query : pending_mode_queries_) {
+    DispatchSupportsSessionMode(query);
+  }
+  pending_mode_queries_.clear();
+
+  for (auto& query : pending_session_requests_) {
+    DispatchRequestSession(query);
+  }
+  pending_session_requests_.clear();
+  LOG(ERROR) << "/" << __FUNCTION__;
+}
+
+void XR::OnSupportsSessionReturned(PendingSessionQuery* query,
                                    bool supports_session) {
+  LOG(ERROR) << __FUNCTION__;
   supports_session
-      ? resolver->Resolve()
-      : resolver->Reject(DOMException::Create(
+      ? query->resolver->Resolve()
+      : query->resolver->Reject(DOMException::Create(
             DOMExceptionCode::kNotSupportedError, kSessionNotSupported));
+  LOG(ERROR) << "/" << __FUNCTION__;
 }
 
 void XR::OnRequestSessionReturned(
-    ScriptPromiseResolver* resolver,
-    XRPresentationContext* output_context,
-    bool environment_integration,
-    bool immersive,
+    PendingSessionQuery* query,
     device::mojom::blink::XRSessionPtr session_ptr) {
   // TODO(https://crbug.com/872316) Improve the error messaging to indicate why
   // a request failed.
   if (!session_ptr) {
     DOMException* exception = DOMException::Create(
         DOMExceptionCode::kNotSupportedError, kSessionNotSupported);
-    resolver->Reject(exception);
+    query->resolver->Reject(exception);
     return;
   }
 
+  bool environment_integration = query->mode == XRSession::kModeInlineAR ||
+                                 query->mode == XRSession::kModeImmersiveAR;
+
   // immersive sessions must supply display info.
   DCHECK(session_ptr->display_info);
   // If the session supports environment integration, ensure the device does
@@ -384,12 +426,13 @@
     blend_mode = XRSession::kBlendModeAlphaBlend;
 
   XRSession* session = MakeGarbageCollected<XRSession>(
-      this, std::move(session_ptr->client_request), immersive,
-      environment_integration, output_context, blend_mode);
+      this, std::move(session_ptr->client_request), query->mode,
+      query->output_context, blend_mode);
   session->SetXRDisplayInfo(std::move(session_ptr->display_info));
   sessions_.insert(session);
 
-  if (immersive) {
+  if (query->mode == XRSession::kModeImmersiveVR ||
+      query->mode == XRSession::kModeImmersiveAR) {
     frameProvider()->BeginImmersiveSession(session, std::move(session_ptr));
   } else {
     magic_window_provider_.Bind(std::move(session_ptr->data_provider));
@@ -402,10 +445,11 @@
     }
   }
 
-  resolver->Resolve(session);
+  query->resolver->Resolve(session);
 }
 
 void XR::ReportImmersiveSupported(bool supported) {
+  LOG(ERROR) << __FUNCTION__;
   Document* doc = GetFrame() ? GetFrame()->GetDocument() : nullptr;
   if (doc && !did_log_supports_immersive_ && supported) {
     ukm::builders::XR_WebXR ukm_builder(ukm_source_id_);
@@ -413,6 +457,7 @@
     ukm_builder.Record(doc->UkmRecorder());
     did_log_supports_immersive_ = true;
   }
+  LOG(ERROR) << "/" << __FUNCTION__;
 }
 
 void XR::AddedEventListener(const AtomicString& event_type,
@@ -451,14 +496,12 @@
   if (frame_provider_)
     frame_provider_->Dispose();
 
-  // Ensure that any outstanding requestDevice promises are resolved. They will
-  // receive a null result.
-  ResolveRequestDevice();
+  device_ = nullptr;
 }
 
 void XR::Trace(blink::Visitor* visitor) {
-  visitor->Trace(xr_device_);
-  visitor->Trace(pending_devices_resolver_);
+  visitor->Trace(pending_mode_queries_);
+  visitor->Trace(pending_session_requests_);
   visitor->Trace(frame_provider_);
   visitor->Trace(sessions_);
   ContextLifecycleObserver::Trace(visitor);
diff --git a/third_party/blink/renderer/modules/xr/xr.h b/third_party/blink/renderer/modules/xr/xr.h
index 1aab050..0e885dff 100644
--- a/third_party/blink/renderer/modules/xr/xr.h
+++ b/third_party/blink/renderer/modules/xr/xr.h
@@ -12,16 +12,16 @@
 #include "third_party/blink/renderer/core/dom/context_lifecycle_observer.h"
 #include "third_party/blink/renderer/core/dom/events/event_target.h"
 #include "third_party/blink/renderer/core/page/focus_changed_observer.h"
+#include "third_party/blink/renderer/modules/xr/xr_session.h"
 #include "third_party/blink/renderer/modules/xr/xr_session_creation_options.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
 namespace blink {
 
 class ScriptPromiseResolver;
-class XRDevice;
 class XRFrameProvider;
-class XRSession;
 
 class XR final : public EventTargetWithInlineData,
                  public ContextLifecycleObserver,
@@ -39,9 +39,7 @@
 
   DEFINE_ATTRIBUTE_EVENT_LISTENER(devicechange, kDevicechange);
 
-  ScriptPromise requestDevice(ScriptState*);
-
-  ScriptPromise supportsSession(ScriptState*, const XRSessionCreationOptions*);
+  ScriptPromise supportsSessionMode(ScriptState*, const String&);
   ScriptPromise requestSession(ScriptState*, const XRSessionCreationOptions*);
 
   XRFrameProvider* frameProvider();
@@ -74,18 +72,33 @@
   int64_t GetSourceId() const { return ukm_source_id_; }
 
  private:
+  class PendingSessionQuery final
+      : public GarbageCollected<PendingSessionQuery> {
+    WTF_MAKE_NONCOPYABLE(PendingSessionQuery);
+
+   public:
+    PendingSessionQuery(ScriptPromiseResolver*, XRSession::SessionMode);
+    virtual ~PendingSessionQuery() = default;
+
+    virtual void Trace(blink::Visitor*);
+
+    Member<ScriptPromiseResolver> resolver;
+    const XRSession::SessionMode mode;
+    Member<XRPresentationContext> output_context;
+    bool has_user_activation = false;
+  };
+
   const char* checkSessionSupport(const XRSessionCreationOptions*) const;
 
   void OnRequestDeviceReturned(device::mojom::blink::XRDevicePtr device);
-  void ResolveRequestDevice();
+  void DispatchPendingSessionCalls();
 
-  void OnRequestSessionReturned(ScriptPromiseResolver* resolver,
-                                XRPresentationContext* output_context,
-                                bool environment_integration,
-                                bool immersive,
-                                device::mojom::blink::XRSessionPtr session);
-  void OnSupportsSessionReturned(ScriptPromiseResolver* resolver,
-                                 bool supports_session);
+  void DispatchRequestSession(PendingSessionQuery*);
+  void OnRequestSessionReturned(PendingSessionQuery*,
+                                device::mojom::blink::XRSessionPtr);
+
+  void DispatchSupportsSessionMode(PendingSessionQuery*);
+  void OnSupportsSessionReturned(PendingSessionQuery*, bool supports_session);
 
   void EnsureDevice();
   void ReportImmersiveSupported(bool supported);
@@ -107,8 +120,11 @@
 
   const int64_t ukm_source_id_;
 
-  Member<XRDevice> xr_device_;
-  Member<ScriptPromiseResolver> pending_devices_resolver_;
+  // Track calls that were made prior to the internal device successfully being
+  // queried. Can be removed once the service has been updated to allow the
+  // respective calls to be made directly.
+  HeapVector<Member<PendingSessionQuery>> pending_mode_queries_;
+  HeapVector<Member<PendingSessionQuery>> pending_session_requests_;
 
   Member<XRFrameProvider> frame_provider_;
   HeapHashSet<WeakMember<XRSession>> sessions_;
diff --git a/third_party/blink/renderer/modules/xr/xr.idl b/third_party/blink/renderer/modules/xr/xr.idl
index de578ac..1337c09 100644
--- a/third_party/blink/renderer/modules/xr/xr.idl
+++ b/third_party/blink/renderer/modules/xr/xr.idl
@@ -9,5 +9,6 @@
     OriginTrialEnabled=WebXR
 ] interface XR : EventTarget {
   attribute EventHandler ondevicechange;
-  [CallWith=ScriptState, MeasureAs=XRRequestDevice] Promise<XRDevice?> requestDevice();
+  [CallWith=ScriptState, MeasureAs=XRSupportsSession] Promise<void> supportsSessionMode(XRSessionMode mode);
+  [CallWith=ScriptState, MeasureAs=XRRequestSession] Promise<XRSession> requestSession([PermissiveDictionaryConversion] optional XRSessionCreationOptions options);
 };
diff --git a/third_party/blink/renderer/modules/xr/xr_device.cc b/third_party/blink/renderer/modules/xr/xr_device.cc
deleted file mode 100644
index dc955a9..0000000
--- a/third_party/blink/renderer/modules/xr/xr_device.cc
+++ /dev/null
@@ -1,30 +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.
-
-#include "third_party/blink/renderer/modules/xr/xr_device.h"
-
-#include "third_party/blink/renderer/modules/xr/xr.h"
-
-namespace blink {
-
-XRDevice::XRDevice(XR* xr) : xr_(xr) {}
-
-ScriptPromise XRDevice::supportsSession(
-    ScriptState* script_state,
-    const XRSessionCreationOptions* options) {
-  return xr_->supportsSession(script_state, options);
-}
-
-ScriptPromise XRDevice::requestSession(
-    ScriptState* script_state,
-    const XRSessionCreationOptions* options) {
-  return xr_->requestSession(script_state, options);
-}
-
-void XRDevice::Trace(blink::Visitor* visitor) {
-  visitor->Trace(xr_);
-  ScriptWrappable::Trace(visitor);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/modules/xr/xr_device.h b/third_party/blink/renderer/modules/xr/xr_device.h
deleted file mode 100644
index f4d9173..0000000
--- a/third_party/blink/renderer/modules/xr/xr_device.h
+++ /dev/null
@@ -1,39 +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.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_DEVICE_H_
-#define THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_DEVICE_H_
-
-#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
-#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
-
-namespace blink {
-
-class XR;
-class XRSessionCreationOptions;
-
-// Temporary shell class that redirects all calls to XR. Only used to break
-// removal CL into reasonably sized parts.
-class XRDevice final : public ScriptWrappable {
-  DEFINE_WRAPPERTYPEINFO();
-
- public:
-  XRDevice(XR*);
-  XR* xr() const { return xr_; }
-
-  ScriptPromise supportsSession(ScriptState*, const XRSessionCreationOptions*);
-  ScriptPromise requestSession(ScriptState*, const XRSessionCreationOptions*);
-
-  void Trace(blink::Visitor*) override;
-
- private:
-  Member<XR> xr_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_XR_XR_DEVICE_H_
diff --git a/third_party/blink/renderer/modules/xr/xr_device.idl b/third_party/blink/renderer/modules/xr/xr_device.idl
deleted file mode 100644
index 5d5a879..0000000
--- a/third_party/blink/renderer/modules/xr/xr_device.idl
+++ /dev/null
@@ -1,13 +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.
-
-// https://immersive-web.github.io/webxr/#xrdevice-interface
-[
-    SecureContext,
-    Exposed=Window,
-    OriginTrialEnabled=WebXR
-] interface XRDevice {
-  [CallWith=ScriptState, MeasureAs=XRSupportsSession] Promise<void> supportsSession([PermissiveDictionaryConversion] optional XRSessionCreationOptions options);
-  [CallWith=ScriptState, MeasureAs=XRRequestSession] Promise<XRSession> requestSession([PermissiveDictionaryConversion] optional XRSessionCreationOptions options);
-};
diff --git a/third_party/blink/renderer/modules/xr/xr_session.cc b/third_party/blink/renderer/modules/xr/xr_session.cc
index 2f9d60c..f7307458b 100644
--- a/third_party/blink/renderer/modules/xr/xr_session.cc
+++ b/third_party/blink/renderer/modules/xr/xr_session.cc
@@ -94,16 +94,52 @@
   Member<XRSession> session_;
 };
 
+XRSession::SessionMode XRSession::stringToSessionMode(
+    const String& mode_string) {
+  if (mode_string == "inline") {
+    return kModeInline;
+  }
+  if (mode_string == "legacy-inline-ar") {
+    return kModeInlineAR;
+  }
+  if (mode_string == "immersive-vr") {
+    return kModeImmersiveVR;
+  }
+  if (mode_string == "immersive-ar") {
+    return kModeImmersiveAR;
+  }
+
+  return kModeUnknown;
+}
+
+String XRSession::sessionModeToString(XRSession::SessionMode mode) {
+  if (mode == kModeInline) {
+    return "inline";
+  }
+  if (mode == kModeInlineAR) {
+    return "legacy-inline-ar";
+  }
+  if (mode == kModeImmersiveVR) {
+    return "immersive-vr";
+  }
+  if (mode == kModeImmersiveAR) {
+    return "immersive-ar";
+  }
+
+  return "";
+}
+
 XRSession::XRSession(
     XR* xr,
     device::mojom::blink::XRSessionClientRequest client_request,
-    bool immersive,
-    bool environment_integration,
+    XRSession::SessionMode mode,
     XRPresentationContext* output_context,
     EnvironmentBlendMode environment_blend_mode)
     : xr_(xr),
-      immersive_(immersive),
-      environment_integration_(environment_integration),
+      mode_(mode),
+      mode_string_(sessionModeToString(mode)),
+      environment_integration_(mode == kModeInlineAR ||
+                               mode == kModeImmersiveAR),
       output_context_(output_context),
       client_binding_(this, std::move(client_request)),
       callback_collection_(
@@ -121,7 +157,7 @@
       resize_observer_->observe(canvas);
 
       // Begin processing input events on the output context's canvas.
-      if (!immersive_) {
+      if (!immersive()) {
         canvas_input_provider_ =
             MakeGarbageCollected<XRCanvasInputProvider>(this, canvas);
       }
@@ -147,6 +183,10 @@
   }
 }
 
+bool XRSession::immersive() const {
+  return mode_ == kModeImmersiveVR || mode_ == kModeImmersiveAR;
+}
+
 void XRSession::setDepthNear(double value) {
   if (depth_near_ != value) {
     update_views_next_frame_ = true;
diff --git a/third_party/blink/renderer/modules/xr/xr_session.h b/third_party/blink/renderer/modules/xr/xr_session.h
index 1c23b36..9bc8490 100644
--- a/third_party/blink/renderer/modules/xr/xr_session.h
+++ b/third_party/blink/renderer/modules/xr/xr_session.h
@@ -43,6 +43,17 @@
   USING_GARBAGE_COLLECTED_MIXIN(XRSession);
 
  public:
+  enum SessionMode {
+    kModeUnknown = 0,
+    kModeInline = 1,
+    kModeImmersiveVR = 2,
+    kModeImmersiveAR = 3,
+    kModeInlineAR = 4
+  };
+
+  static SessionMode stringToSessionMode(const String&);
+  static String sessionModeToString(SessionMode);
+
   enum EnvironmentBlendMode {
     kBlendModeOpaque = 1,
     kBlendModeAdditive = 2,
@@ -51,18 +62,19 @@
 
   XRSession(XR*,
             device::mojom::blink::XRSessionClientRequest client_request,
-            bool immersive,
-            bool environment_integration,
+            SessionMode mode,
             XRPresentationContext* output_context,
             EnvironmentBlendMode environment_blend_mode);
   ~XRSession() override = default;
 
   XR* xr() const { return xr_; }
-  bool immersive() const { return immersive_; }
+  const String& mode() const { return mode_string_; }
   bool environmentIntegration() const { return environment_integration_; }
   XRPresentationContext* outputContext() const { return output_context_; }
   const String& environmentBlendMode() const { return blend_mode_string_; }
 
+  bool immersive() const;
+
   // Near and far depths are used when computing projection matrices for this
   // Session's views. Changes will propegate to the appropriate matrices on the
   // next frame after these values are updated.
@@ -186,7 +198,8 @@
           results);
 
   const Member<XR> xr_;
-  const bool immersive_;
+  const SessionMode mode_;
+  const String mode_string_;
   const bool environment_integration_;
   const Member<XRPresentationContext> output_context_;
   String blend_mode_string_;
diff --git a/third_party/blink/renderer/modules/xr/xr_session.idl b/third_party/blink/renderer/modules/xr/xr_session.idl
index 23f7b626..319955fe 100644
--- a/third_party/blink/renderer/modules/xr/xr_session.idl
+++ b/third_party/blink/renderer/modules/xr/xr_session.idl
@@ -3,6 +3,13 @@
 // found in the LICENSE file.
 
 // https://immersive-web.github.io/webxr/#xrsession-interface
+enum XRSessionMode {
+  "inline",
+  "legacy-inline-ar",
+  "immersive-vr",
+  "immersive-ar",
+};
+
 enum XREnvironmentBlendMode {
   "opaque",
   "additive",
@@ -15,7 +22,7 @@
     Exposed=Window,
     OriginTrialEnabled=WebXR
 ] interface XRSession : EventTarget {
-  readonly attribute boolean immersive;
+  readonly attribute XRSessionMode mode;
   readonly attribute XRPresentationContext outputContext;
   readonly attribute XREnvironmentBlendMode environmentBlendMode;
 
diff --git a/third_party/blink/renderer/modules/xr/xr_session_creation_options.idl b/third_party/blink/renderer/modules/xr/xr_session_creation_options.idl
index d66ce6f..6a876949 100644
--- a/third_party/blink/renderer/modules/xr/xr_session_creation_options.idl
+++ b/third_party/blink/renderer/modules/xr/xr_session_creation_options.idl
@@ -4,7 +4,6 @@
 
 // https://immersive-web.github.io/webxr/#xrsessioncreationoptions-interface
 dictionary XRSessionCreationOptions {
-  [RuntimeEnabled=WebXRHitTest] boolean environmentIntegration = false;
-  boolean immersive = false;
+  XRSessionMode mode = "inline";
   XRPresentationContext outputContext;
 };
diff --git a/third_party/blink/renderer/platform/exported/web_url_request.cc b/third_party/blink/renderer/platform/exported/web_url_request.cc
index 476acd1..ab20203 100644
--- a/third_party/blink/renderer/platform/exported/web_url_request.cc
+++ b/third_party/blink/renderer/platform/exported/web_url_request.cc
@@ -377,13 +377,6 @@
   resource_request_->SetPriority(static_cast<ResourceLoadPriority>(priority));
 }
 
-bool WebURLRequest::WasDiscarded() const {
-  return resource_request_->WasDiscarded();
-}
-void WebURLRequest::SetWasDiscarded(bool was_discarded) {
-  resource_request_->SetWasDiscarded(was_discarded);
-}
-
 bool WebURLRequest::IsExternalRequest() const {
   return resource_request_->IsExternalRequest();
 }
@@ -425,14 +418,6 @@
   return resource_request_->GetDevToolsToken();
 }
 
-const WebString WebURLRequest::GetOriginPolicy() const {
-  return resource_request_->GetOriginPolicy();
-}
-
-void WebURLRequest::SetOriginPolicy(const WebString& policy) {
-  resource_request_->SetOriginPolicy(policy);
-}
-
 const WebString WebURLRequest::GetRequestedWithHeader() const {
   return resource_request_->GetRequestedWithHeader();
 }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource.h b/third_party/blink/renderer/platform/loader/fetch/resource.h
index ac52ace..7874407 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource.h
@@ -417,14 +417,6 @@
     return virtual_time_pauser_;
   }
 
-  // See WebURLLoaderClient.
-  base::OnceClosure TakeContinueNavigationRequestCallback() {
-    return std::move(continue_navigation_request_callback_);
-  }
-  void SetContinueNavigationRequestCallback(base::OnceClosure closure) {
-    continue_navigation_request_callback_ = std::move(closure);
-  }
-
  protected:
   Resource(const ResourceRequest&, ResourceType, const ResourceLoaderOptions&);
 
@@ -583,7 +575,6 @@
   scoped_refptr<SharedBuffer> data_;
 
   WebScopedVirtualTimePauser virtual_time_pauser_;
-  base::OnceClosure continue_navigation_request_callback_;
 };
 
 class ResourceFactory {
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
index d64f2fdd..5ff90f1 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -1046,11 +1046,6 @@
   HandleError(error);
 }
 
-void ResourceLoader::SetContinueNavigationRequestCallback(
-    base::OnceClosure closure) {
-  resource_->SetContinueNavigationRequestCallback(std::move(closure));
-}
-
 void ResourceLoader::HandleError(const ResourceError& error) {
   if (is_cache_aware_loading_activated_ && error.IsCacheMiss() &&
       Context().ShouldLoadNewResource(resource_->GetType())) {
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.h b/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
index 7c4fa4dfb..67c911bd 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.h
@@ -140,7 +140,6 @@
                int64_t encoded_data_length,
                int64_t encoded_body_length,
                int64_t decoded_body_length) override;
-  void SetContinueNavigationRequestCallback(base::OnceClosure) override;
 
   blink::mojom::CodeCacheType GetCodeCacheType() const;
   void SendCachedCodeToResource(const char* data, int size);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request.cc b/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
index ed8be44d..e282391e 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
@@ -77,7 +77,6 @@
       referrer_string_(Referrer::ClientReferrerString()),
       referrer_policy_(network::mojom::ReferrerPolicy::kDefault),
       did_set_http_referrer_(false),
-      was_discarded_(false),
       is_external_request_(false),
       cors_preflight_policy_(
           network::mojom::CorsPreflightPolicy::kConsiderPreflight),
@@ -124,7 +123,6 @@
 
   if (request->HttpMethod() == HttpMethod())
     request->SetHTTPBody(HttpBody());
-  request->SetWasDiscarded(WasDiscarded());
   request->SetCorsPreflightPolicy(CorsPreflightPolicy());
   if (IsAdResource())
     request->SetIsAdResource();
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request.h b/third_party/blink/renderer/platform/loader/fetch/resource_request.h
index 3670d33..cfc08ca 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_request.h
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_request.h
@@ -346,9 +346,6 @@
   bool CacheControlContainsNoStore() const;
   bool HasCacheValidatorFields() const;
 
-  bool WasDiscarded() const { return was_discarded_; }
-  void SetWasDiscarded(bool was_discarded) { was_discarded_ = was_discarded; }
-
   // https://wicg.github.io/cors-rfc1918/#external-request
   bool IsExternalRequest() const { return is_external_request_; }
   void SetExternalRequestStateFromRequestorAddressSpace(mojom::IPAddressSpace);
@@ -403,9 +400,6 @@
     devtools_token_ = devtools_token;
   }
 
-  void SetOriginPolicy(const String& policy) { origin_policy_ = policy; }
-  const String& GetOriginPolicy() const { return origin_policy_; }
-
   void SetRequestedWithHeader(const String& value) {
     requested_with_header_ = value;
   }
@@ -485,7 +479,6 @@
   String referrer_string_;
   network::mojom::ReferrerPolicy referrer_policy_;
   bool did_set_http_referrer_;
-  bool was_discarded_;
   bool is_external_request_;
   network::mojom::CorsPreflightPolicy cors_preflight_policy_;
   RedirectStatus redirect_status_;
@@ -503,7 +496,6 @@
   bool is_automatic_upgrade_ = false;
 
   base::Optional<base::UnguessableToken> devtools_token_;
-  String origin_policy_;
   String requested_with_header_;
   String client_data_header_;
 
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 1a5e288..01e19b5 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -690,7 +690,7 @@
     },
     {
       name: "LayoutNG",
-      implied_by: ["LayoutNGBlockFragmentation", "LayoutNGFieldset", "LayoutNGFlexBox", "EditingNG"],
+      implied_by: ["LayoutNGBlockFragmentation", "LayoutNGFieldset", "LayoutNGFlexBox", "EditingNG", "BidiCaretAffinity"],
     },
     {
       name: "LayoutNGBlockFragmentation",
diff --git a/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.cc b/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.cc
index 5914e48..bc55f74 100644
--- a/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.cc
+++ b/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.cc
@@ -18,7 +18,9 @@
 #include "third_party/blink/public/platform/web_url_error.h"
 #include "third_party/blink/public/platform/web_url_request.h"
 #include "third_party/blink/public/platform/web_url_response.h"
+#include "third_party/blink/public/web/web_navigation_params.h"
 #include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h"
+#include "third_party/blink/renderer/platform/loader/static_data_navigation_body_loader.h"
 #include "third_party/blink/renderer/platform/testing/testing_platform_support.h"
 #include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
 #include "third_party/blink/renderer/platform/testing/weburl_loader_mock.h"
@@ -140,6 +142,39 @@
   RunUntilIdle();
 }
 
+void WebURLLoaderMockFactoryImpl::FillNavigationParamsResponse(
+    WebNavigationParams* params) {
+  if (delegate_ && delegate_->FillNavigationParamsResponse(params))
+    return;
+
+  base::Optional<WebURLError> error;
+  WebData data;
+
+  size_t redirects = 0;
+  LoadRequest(params->url, &params->response, &error, &data);
+  DCHECK(!error);
+  while (params->response.HttpStatusCode() >= 300 &&
+         params->response.HttpStatusCode() < 400) {
+    WebURL new_url(KURL(params->response.HttpHeaderField("Location")));
+    ++redirects;
+    params->redirects.reserve(redirects);
+    params->redirects.resize(redirects);
+    params->redirects[redirects - 1].redirect_response = params->response;
+    params->redirects[redirects - 1].new_url = new_url;
+    params->redirects[redirects - 1].new_http_method = "GET";
+    LoadRequest(new_url, &params->response, &error, &data);
+    DCHECK(!error);
+  }
+
+  auto body_loader = std::make_unique<StaticDataNavigationBodyLoader>();
+  if (!data.IsNull()) {
+    scoped_refptr<SharedBuffer> buffer = data;
+    body_loader->Write(*buffer);
+    body_loader->Finish();
+  }
+  params->body_loader = std::move(body_loader);
+}
+
 bool WebURLLoaderMockFactoryImpl::IsMockedURL(const blink::WebURL& url) {
   base::Optional<WebURLError> error;
   ResponseInfo response_info;
diff --git a/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.h b/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.h
index 3000148..4920ba55 100644
--- a/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.h
+++ b/third_party/blink/renderer/platform/testing/weburl_loader_mock_factory_impl.h
@@ -55,6 +55,7 @@
   void SetLoaderDelegate(WebURLLoaderTestDelegate* delegate) override {
     delegate_ = delegate;
   }
+  void FillNavigationParamsResponse(WebNavigationParams*) override;
 
   // Returns true if |url| was registered for being mocked.
   bool IsMockedURL(const WebURL& url);
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/acquire-immediate-update-and-commit-expected.html b/third_party/blink/web_tests/display-lock/lock-after-append/acquire-immediate-update-and-commit-expected.html
new file mode 100644
index 0000000..9801e1a
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/acquire-immediate-update-and-commit-expected.html
@@ -0,0 +1,18 @@
+<!doctype HTML>
+
+<style>
+#container {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightblue;
+}
+#child {
+  width: 50px;
+  height: 50px;
+  background: lightgreen;
+}
+</style>
+
+<div id="log">PASS</div>
+<div id="container"><div id="child"></div></div>
diff --git a/third_party/blink/web_tests/display-lock/lock-after-append/acquire-immediate-update-and-commit.html b/third_party/blink/web_tests/display-lock/lock-after-append/acquire-immediate-update-and-commit.html
new file mode 100644
index 0000000..ccff550
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-after-append/acquire-immediate-update-and-commit.html
@@ -0,0 +1,50 @@
+<!doctype HTML>
+
+<!--
+Runs an acquire, and calls updateAndCommit without waiting for the acquire promise.
+-->
+
+<style>
+#container {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightblue;
+}
+#child {
+  width: 50px;
+  height: 50px;
+  background: lightgreen;
+}
+</style>
+
+<div id="log"></div>
+<div id="container"></div>
+
+<script>
+// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait.
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest(status_string) {
+  if (document.getElementById("log").innerHTML === "")
+    document.getElementById("log").innerHTML = status_string;
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.getElementById("container");
+  container.displayLock.acquire({ timeout: Infinity });
+
+  let child = document.createElement("div");
+  child.id = "child";
+  container.appendChild(child);
+
+  container.displayLock.updateAndCommit().then(
+    () => { finishTest("PASS"); },
+    () => { finishTest("FAIL"); });
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-and-commit-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-and-commit-expected.html
new file mode 100644
index 0000000..9801e1a
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-and-commit-expected.html
@@ -0,0 +1,18 @@
+<!doctype HTML>
+
+<style>
+#container {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightblue;
+}
+#child {
+  width: 50px;
+  height: 50px;
+  background: lightgreen;
+}
+</style>
+
+<div id="log">PASS</div>
+<div id="container"><div id="child"></div></div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-and-commit.html b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-and-commit.html
new file mode 100644
index 0000000..2ff1ffd
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/acquire-update-and-commit.html
@@ -0,0 +1,52 @@
+<!doctype HTML>
+
+<!--
+Runs an acquire, appends a child, and calls updateAndCommit.
+-->
+
+<style>
+#container {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightblue;
+}
+#child {
+  width: 50px;
+  height: 50px;
+  background: lightgreen;
+}
+</style>
+
+<div id="log"></div>
+
+<script>
+// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait.
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest(status_string) {
+  if (document.getElementById("log").innerHTML === "")
+    document.getElementById("log").innerHTML = status_string;
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.createElement("div");
+  container.displayLock.acquire({ timeout: Infinity }).then(() => {
+    let child = document.createElement("div");
+    child.id = "child";
+    container.appendChild(child);
+
+    container.id = "container";
+    document.body.appendChild(container);
+
+    container.displayLock.updateAndCommit().then(
+      () => { finishTest("PASS"); },
+      () => { finishTest("FAIL"); });
+  });
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/commit-followed-by-update-and-commit-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/commit-followed-by-update-and-commit-expected.html
new file mode 100644
index 0000000..9801e1a
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/commit-followed-by-update-and-commit-expected.html
@@ -0,0 +1,18 @@
+<!doctype HTML>
+
+<style>
+#container {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightblue;
+}
+#child {
+  width: 50px;
+  height: 50px;
+  background: lightgreen;
+}
+</style>
+
+<div id="log">PASS</div>
+<div id="container"><div id="child"></div></div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/commit-followed-by-update-and-commit.html b/third_party/blink/web_tests/display-lock/lock-before-append/commit-followed-by-update-and-commit.html
new file mode 100644
index 0000000..ca6f5084
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/commit-followed-by-update-and-commit.html
@@ -0,0 +1,48 @@
+<!doctype HTML>
+
+<style>
+#container {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightblue;
+}
+#child {
+  width: 50px;
+  height: 50px;
+  background: lightgreen;
+}
+</style>
+
+<div id="log"></div>
+
+<script>
+// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait.
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest(status_string) {
+  if (document.getElementById("log").innerHTML === "")
+    document.getElementById("log").innerHTML = status_string;
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.createElement("div");
+  container.displayLock.acquire({ timeout: Infinity }).then(() => {
+    let child = document.createElement("div");
+    child.id = "child";
+    container.appendChild(child);
+
+    container.id = "container";
+    document.body.appendChild(container);
+
+    let first_promise = container.displayLock.commit();
+    let second_promise = container.displayLock.updateAndCommit();
+    Promise.all([first_promise, second_promise]).then(() => finishTest("PASS"));
+  });
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/multiple-update-and-commit-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/multiple-update-and-commit-expected.html
new file mode 100644
index 0000000..9801e1a
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/multiple-update-and-commit-expected.html
@@ -0,0 +1,18 @@
+<!doctype HTML>
+
+<style>
+#container {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightblue;
+}
+#child {
+  width: 50px;
+  height: 50px;
+  background: lightgreen;
+}
+</style>
+
+<div id="log">PASS</div>
+<div id="container"><div id="child"></div></div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/multiple-update-and-commit.html b/third_party/blink/web_tests/display-lock/lock-before-append/multiple-update-and-commit.html
new file mode 100644
index 0000000..f881f209
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/multiple-update-and-commit.html
@@ -0,0 +1,50 @@
+<!doctype HTML>
+
+<style>
+#container {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightblue;
+}
+#child {
+  width: 50px;
+  height: 50px;
+  background: lightgreen;
+}
+</style>
+
+<div id="log"></div>
+
+<script>
+// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait.
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest(status_string) {
+  if (document.getElementById("log").innerHTML === "")
+    document.getElementById("log").innerHTML = status_string;
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.createElement("div");
+  container.displayLock.acquire({ timeout: Infinity }).then(() => {
+    let child = document.createElement("div");
+    child.id = "child";
+    container.appendChild(child);
+
+    container.id = "container";
+    document.body.appendChild(container);
+
+    let promises = []
+    for (let i = 0; i < 10; ++i) {
+      promises.push(container.displayLock.updateAndCommit());
+    }
+    Promise.all(promises).then(() => finishTest("PASS"));
+  });
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-expected.html
new file mode 100644
index 0000000..a1a74ba
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-expected.html
@@ -0,0 +1,3 @@
+<!doctype HTML>
+
+<div id="log">PASS</div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-commit-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-commit-expected.html
new file mode 100644
index 0000000..9801e1a
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-commit-expected.html
@@ -0,0 +1,18 @@
+<!doctype HTML>
+
+<style>
+#container {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightblue;
+}
+#child {
+  width: 50px;
+  height: 50px;
+  background: lightgreen;
+}
+</style>
+
+<div id="log">PASS</div>
+<div id="container"><div id="child"></div></div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-commit.html b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-commit.html
new file mode 100644
index 0000000..9e56578f
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-commit.html
@@ -0,0 +1,48 @@
+<!doctype HTML>
+
+<style>
+#container {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightblue;
+}
+#child {
+  width: 50px;
+  height: 50px;
+  background: lightgreen;
+}
+</style>
+
+<div id="log"></div>
+
+<script>
+// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait.
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest(status_string) {
+  if (document.getElementById("log").innerHTML === "")
+    document.getElementById("log").innerHTML = status_string;
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.createElement("div");
+  container.displayLock.acquire({ timeout: Infinity }).then(() => {
+    let child = document.createElement("div");
+    child.id = "child";
+    container.appendChild(child);
+
+    container.id = "container";
+    document.body.appendChild(container);
+
+    let first_promise = container.displayLock.updateAndCommit();
+    let second_promise = container.displayLock.commit();
+    Promise.all([first_promise, second_promise]).then(() => finishTest("PASS"));
+  });
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-update-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-update-expected.html
new file mode 100644
index 0000000..9801e1a
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-update-expected.html
@@ -0,0 +1,18 @@
+<!doctype HTML>
+
+<style>
+#container {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightblue;
+}
+#child {
+  width: 50px;
+  height: 50px;
+  background: lightgreen;
+}
+</style>
+
+<div id="log">PASS</div>
+<div id="container"><div id="child"></div></div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-update.html b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-update.html
new file mode 100644
index 0000000..f0d2b63
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit-followed-by-update.html
@@ -0,0 +1,48 @@
+<!doctype HTML>
+
+<style>
+#container {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightblue;
+}
+#child {
+  width: 50px;
+  height: 50px;
+  background: lightgreen;
+}
+</style>
+
+<div id="log"></div>
+
+<script>
+// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait.
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest(status_string) {
+  if (document.getElementById("log").innerHTML === "")
+    document.getElementById("log").innerHTML = status_string;
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.createElement("div");
+  container.displayLock.acquire({ timeout: Infinity }).then(() => {
+    let child = document.createElement("div");
+    child.id = "child";
+    container.appendChild(child);
+
+    container.id = "container";
+    document.body.appendChild(container);
+
+    let first_promise = container.displayLock.updateAndCommit();
+    let second_promise = container.displayLock.update();
+    Promise.all([first_promise, second_promise]).then(() => finishTest("PASS"));
+  });
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit.html b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit.html
new file mode 100644
index 0000000..0ea2539
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/update-and-commit.html
@@ -0,0 +1,39 @@
+<!doctype HTML>
+
+<!--
+Runs an updateAndCommit() without acquiring, which fails.
+-->
+
+<style>
+#container {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightblue;
+}
+</style>
+
+<div id="log"></div>
+
+<script>
+// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait.
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest(status_string) {
+  if (document.getElementById("log").innerHTML === "")
+    document.getElementById("log").innerHTML = status_string;
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.createElement("div");
+  container.id = "container";
+  container.displayLock.updateAndCommit().then(
+    () => { finishTest("FAIL"); },
+    () => { finishTest("PASS"); });
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/update-followed-by-update-and-commit-expected.html b/third_party/blink/web_tests/display-lock/lock-before-append/update-followed-by-update-and-commit-expected.html
new file mode 100644
index 0000000..9801e1a
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/update-followed-by-update-and-commit-expected.html
@@ -0,0 +1,18 @@
+<!doctype HTML>
+
+<style>
+#container {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightblue;
+}
+#child {
+  width: 50px;
+  height: 50px;
+  background: lightgreen;
+}
+</style>
+
+<div id="log">PASS</div>
+<div id="container"><div id="child"></div></div>
diff --git a/third_party/blink/web_tests/display-lock/lock-before-append/update-followed-by-update-and-commit.html b/third_party/blink/web_tests/display-lock/lock-before-append/update-followed-by-update-and-commit.html
new file mode 100644
index 0000000..0e40582
--- /dev/null
+++ b/third_party/blink/web_tests/display-lock/lock-before-append/update-followed-by-update-and-commit.html
@@ -0,0 +1,48 @@
+<!doctype HTML>
+
+<style>
+#container {
+  contain: style layout;
+  width: 150px;
+  height: 150px;
+  background: lightblue;
+}
+#child {
+  width: 50px;
+  height: 50px;
+  background: lightgreen;
+}
+</style>
+
+<div id="log"></div>
+
+<script>
+// TODO(vmpstr): In WPT this needs to be replaced with reftest-wait.
+if (window.testRunner)
+  window.testRunner.waitUntilDone();
+
+function finishTest(status_string) {
+  if (document.getElementById("log").innerHTML === "")
+    document.getElementById("log").innerHTML = status_string;
+  if (window.testRunner)
+    window.testRunner.notifyDone();
+}
+
+function runTest() {
+  let container = document.createElement("div");
+  container.displayLock.acquire({ timeout: Infinity }).then(() => {
+    let child = document.createElement("div");
+    child.id = "child";
+    container.appendChild(child);
+
+    container.id = "container";
+    document.body.appendChild(container);
+
+    let first_promise = container.displayLock.update();
+    let second_promise = container.displayLock.updateAndCommit();
+    Promise.all([first_promise, second_promise]).then(() => finishTest("PASS"));
+  });
+}
+
+window.onload = runTest;
+</script>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
index a2fd662..948357c 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -160011,16 +160011,6 @@
      {}
     ]
    ],
-   "fetch/sec-metadata/embed.tentative.https.sub-expected.txt": [
-    [
-     {}
-    ]
-   ],
-   "fetch/sec-metadata/object.tentative.https.sub-expected.txt": [
-    [
-     {}
-    ]
-   ],
    "fetch/sec-metadata/redirect/multiple-redirect-cross-site.tentative.https.sub-expected.txt": [
     [
      {}
@@ -160501,6 +160491,11 @@
      {}
     ]
    ],
+   "fonts/noto/NotoNaskhArabic-regular.woff2": [
+    [
+     {}
+    ]
+   ],
    "fonts/noto/NotoSansAdlam-hinted/LICENSE_OFL.txt": [
     [
      {}
@@ -212715,6 +212710,18 @@
      {}
     ]
    ],
+   "css/css-syntax/anb-parsing.html": [
+    [
+     "/css/css-syntax/anb-parsing.html",
+     {}
+    ]
+   ],
+   "css/css-syntax/anb-serialization.html": [
+    [
+     "/css/css-syntax/anb-serialization.html",
+     {}
+    ]
+   ],
    "css/css-syntax/charset-is-not-a-rule.html": [
     [
      "/css/css-syntax/charset-is-not-a-rule.html",
@@ -332415,11 +332422,11 @@
    "reftest"
   ],
   "css/css-conditional/idlharness-expected.txt": [
-   "330c8bdbd01a9f8354c14567dd2386217918e64b",
+   "aa36ecb31338f12757bca6247de65a1488070c1a",
    "support"
   ],
   "css/css-conditional/idlharness.html": [
-   "410466b25230b246c09cd12d1d13b8ef58786abf",
+   "63cf750933737d3a221ccb48d2a667c110dd0bf9",
    "testharness"
   ],
   "css/css-conditional/js/001.html": [
@@ -338255,11 +338262,11 @@
    "testharness"
   ],
   "css/css-fonts/idlharness-expected.txt": [
-   "c501ecc08a0fd72f6e8aaa852893feb4c8e430ed",
+   "14c48ad383a3d3c9f89c3735b9541791b30ef2b2",
    "support"
   ],
   "css/css-fonts/idlharness.html": [
-   "9209144c3e5132a284f79df13145b174af265e59",
+   "ecc601bcf6a97a1722e3901d731f9f424d0a79e1",
    "testharness"
   ],
   "css/css-fonts/language-specific-01.html": [
@@ -351611,11 +351618,11 @@
    "reftest"
   ],
   "css/css-paint-api/idlharness-expected.txt": [
-   "338b395f14fdae38c6bda7ce328ec904aee9b40f",
+   "e71217c3cbc8ed2feef0a75ab6f069ba5ee2c0ad",
    "support"
   ],
   "css/css-paint-api/idlharness.html": [
-   "bb4c9357f243d7572134834e5678b4cd4d1076b6",
+   "c9675ab0412bb955d7a8653e7d28884a6953800b",
    "testharness"
   ],
   "css/css-paint-api/invalid-image-constructor-error-ref.html": [
@@ -352579,7 +352586,7 @@
    "support"
   ],
   "css/css-properties-values-api/idlharness.html": [
-   "e57f0f00ca26cb6a9342b1b6f84259e2bb908790",
+   "6f053757c3cef099f0cea41716a942dfa7e66100",
    "testharness"
   ],
   "css/css-properties-values-api/property-cascade.html": [
@@ -355238,6 +355245,14 @@
    "ada3963c8f75f6489dd2682016d680d54d0dbe9a",
    "support"
   ],
+  "css/css-syntax/anb-parsing.html": [
+   "7fcc06e2c7e8e1908badf6117a7b8c3f1576cf76",
+   "testharness"
+  ],
+  "css/css-syntax/anb-serialization.html": [
+   "787700cebf39e5cc4fa0d5a2934a7e52bec6da32",
+   "testharness"
+  ],
   "css/css-syntax/charset-is-not-a-rule.html": [
    "81b2a04dc5a0dd2f3434150f7bfb6a6d3f1cfef3",
    "testharness"
@@ -372499,15 +372514,15 @@
    "support"
   ],
   "css/css-values/vh_not_refreshing_on_chrome.html": [
-   "52a45a114c85bf96a175ca583d8a2b6f54b9ab6c",
+   "1749986b62c75b3deca3d40f008cade9c105e697",
    "reftest"
   ],
   "css/css-values/viewport-relative-lengths-scaled-viewport.html": [
-   "a901000394d35eed94237b3ce5acc74b1b0e7bc9",
+   "dba2af8fa07b07d2ab7c6ca9f657b6e170cd9a41",
    "testharness"
   ],
   "css/css-values/viewport-units-css2-001.html": [
-   "f0feb6d993537833569bd739e4d903b8e510881b",
+   "c51237dd8a07546d31eef6f6f9b3c84b6ac2b65b",
    "testharness"
   ],
   "css/css-variables/META.yml": [
@@ -396266,10 +396281,6 @@
    "c460aa1ecb941118b6999209ba4601eb145a61b9",
    "support"
   ],
-  "fetch/sec-metadata/embed.tentative.https.sub-expected.txt": [
-   "8a2cc8b0ebc35c059f38e668f894211c41805873",
-   "support"
-  ],
   "fetch/sec-metadata/embed.tentative.https.sub.html": [
    "1c69c021accb90db3bc4ce599ce1988f5329c8ce",
    "testharness"
@@ -396290,10 +396301,6 @@
    "c5c389503ccafd2d2cf21a3634b6995bc22a2e91",
    "testharness"
   ],
-  "fetch/sec-metadata/object.tentative.https.sub-expected.txt": [
-   "0476ef1faf5d63561ccb6ffe12563f3213472d6e",
-   "support"
-  ],
   "fetch/sec-metadata/object.tentative.https.sub.html": [
    "0b9839470d1d8c49a5c58f4b832f825f77a6460b",
    "testharness"
@@ -396754,6 +396761,10 @@
    "42cfff628b4680024908635e353bfe9bbf10d952",
    "support"
   ],
+  "fonts/noto/NotoNaskhArabic-regular.woff2": [
+   "e24020d46a4c4a4f355941b23e8bad3b9b5003cb",
+   "support"
+  ],
   "fonts/noto/NotoSansAdlam-hinted/LICENSE_OFL.txt": [
    "d952d62c065f3f35fb83a173496e90b21525aef3",
    "support"
@@ -452915,11 +452926,11 @@
    "testharness"
   ],
   "webrtc/RTCIceCandidate-constructor-expected.txt": [
-   "af3000f58a964647e8a0ae1f8ef069c7eeb0eb7a",
+   "bb163f48a594fec740fa1fbd93a101f8c271bdc1",
    "support"
   ],
   "webrtc/RTCIceCandidate-constructor.html": [
-   "9842593a83c5330e0ed19bedac9f6c9908362c41",
+   "cad0464a3c045a000270127ce50f89798f9eca0b",
    "testharness"
   ],
   "webrtc/RTCIceTransport-expected.txt": [
@@ -452931,7 +452942,7 @@
    "support"
   ],
   "webrtc/RTCIceTransport-extension.https.html": [
-   "7803bde9b3aa61f6ac500d62c8a3aed79b1a1412",
+   "e9e70379a483e1456259b521fc8094689aa15373",
    "testharness"
   ],
   "webrtc/RTCIceTransport.html": [
@@ -452943,7 +452954,7 @@
    "testharness"
   ],
   "webrtc/RTCPeerConnection-addIceCandidate-expected.txt": [
-   "b0110c0ed9936aec9bb860372cb39c3f0a83c12e",
+   "beb97c56fa587abf78454f9fba930ed61c48a7b0",
    "support"
   ],
   "webrtc/RTCPeerConnection-addIceCandidate.html": [
@@ -453391,7 +453402,7 @@
    "testharness"
   ],
   "webrtc/idlharness.https.window-expected.txt": [
-   "4e66c94edb814d87766ce7c6f040054ccf1a23fd",
+   "12913bcb81ebcc8dcccedfe5573b9937700111a2",
    "support"
   ],
   "webrtc/idlharness.https.window.js": [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-conditional/idlharness-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-conditional/idlharness-expected.txt
index 330c8bd..aa36ecb 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-conditional/idlharness-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/css-conditional/idlharness-expected.txt
@@ -1,5 +1,6 @@
 This is a testharness.js-based test.
-PASS Test css-conditional IDL implementation
+Found 57 tests; 56 PASS, 1 FAIL, 0 TIMEOUT, 0 NOTRUN.
+PASS idl_test setup
 PASS Partial interface CSSRule: original interface defined
 PASS Partial namespace CSS: original namespace defined
 PASS CSSGroupingRule interface: existence and properties of interface object
@@ -25,14 +26,34 @@
 PASS CSSMediaRule interface: existence and properties of interface prototype object's "constructor" property
 PASS CSSMediaRule interface: existence and properties of interface prototype object's @@unscopables property
 PASS CSSMediaRule interface: attribute media
+PASS CSSMediaRule must be primary interface of cssMediaRule
+PASS Stringification of cssMediaRule
+PASS CSSMediaRule interface: cssMediaRule must inherit property "media" with the proper type
+PASS CSSConditionRule interface: cssMediaRule must inherit property "conditionText" with the proper type
+PASS CSSGroupingRule interface: cssMediaRule must inherit property "cssRules" with the proper type
+PASS CSSGroupingRule interface: cssMediaRule must inherit property "insertRule(CSSOMString, unsigned long)" with the proper type
+PASS CSSGroupingRule interface: calling insertRule(CSSOMString, unsigned long) on cssMediaRule with too few arguments must throw TypeError
+PASS CSSGroupingRule interface: cssMediaRule must inherit property "deleteRule(unsigned long)" with the proper type
+PASS CSSGroupingRule interface: calling deleteRule(unsigned long) on cssMediaRule with too few arguments must throw TypeError
+PASS CSSRule interface: cssMediaRule must inherit property "SUPPORTS_RULE" with the proper type
 PASS CSSSupportsRule interface: existence and properties of interface object
 PASS CSSSupportsRule interface object length
 PASS CSSSupportsRule interface object name
 PASS CSSSupportsRule interface: existence and properties of interface prototype object
 PASS CSSSupportsRule interface: existence and properties of interface prototype object's "constructor" property
 PASS CSSSupportsRule interface: existence and properties of interface prototype object's @@unscopables property
+PASS CSSSupportsRule must be primary interface of cssSupportsRule
+PASS Stringification of cssSupportsRule
+PASS CSSConditionRule interface: cssSupportsRule must inherit property "conditionText" with the proper type
+PASS CSSGroupingRule interface: cssSupportsRule must inherit property "cssRules" with the proper type
+PASS CSSGroupingRule interface: cssSupportsRule must inherit property "insertRule(CSSOMString, unsigned long)" with the proper type
+PASS CSSGroupingRule interface: calling insertRule(CSSOMString, unsigned long) on cssSupportsRule with too few arguments must throw TypeError
+PASS CSSGroupingRule interface: cssSupportsRule must inherit property "deleteRule(unsigned long)" with the proper type
+PASS CSSGroupingRule interface: calling deleteRule(unsigned long) on cssSupportsRule with too few arguments must throw TypeError
+PASS CSSRule interface: cssSupportsRule must inherit property "SUPPORTS_RULE" with the proper type
 PASS CSSRule interface: constant SUPPORTS_RULE on interface object
 PASS CSSRule interface: constant SUPPORTS_RULE on interface prototype object
+PASS CSSRule interface: cssRule must inherit property "SUPPORTS_RULE" with the proper type
 PASS CSS namespace: operation escape(CSSOMString)
 PASS CSS namespace: operation supports(CSSOMString, CSSOMString)
 PASS CSS namespace: operation supports(CSSOMString)
diff --git a/third_party/blink/web_tests/external/wpt/css/css-conditional/idlharness.html b/third_party/blink/web_tests/external/wpt/css/css-conditional/idlharness.html
index 410466b..63cf7509 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-conditional/idlharness.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-conditional/idlharness.html
@@ -3,12 +3,22 @@
 
 <head>
   <meta charset="utf-8">
-  <title>css-conditional IDL tests</title>
+  <title>CSS Conditional Rules IDL tests</title>
   <link rel="help" href="https://drafts.csswg.org/css-conditional/">
   <script src="/resources/testharness.js"></script>
   <script src="/resources/testharnessreport.js"></script>
   <script src="/resources/WebIDLParser.js"></script>
   <script src="/resources/idlharness.js"></script>
+  <!-- used to provide objects -->
+  <style>
+    div { display: block; }
+  </style>
+  <style>
+    @media print { }
+  </style>
+  <style>
+    @supports (display: block) { }
+  </style>
 </head>
 
 <body>
@@ -16,16 +26,20 @@
 
   <script>
     'use strict';
-    promise_test(async () => {
-      const idl = await fetch('/interfaces/css-conditional.idl').then(r => r.text());
-      const cssom = await fetch('/interfaces/cssom.idl').then(r => r.text());
-      const dom = await fetch('/interfaces/dom.idl').then(r => r.text());
-      const idl_array = new IdlArray();
-      idl_array.add_idls(idl);
-      idl_array.add_dependency_idls(cssom);
-      idl_array.add_dependency_idls(dom);
-      idl_array.test();
-    }, 'Test css-conditional IDL implementation');
+    idl_test(
+      ['css-conditional'],
+      ['cssom', 'dom'],
+      idl_array => {
+        idl_array.add_objects({
+          CSSRule: ['cssRule'],
+          CSSMediaRule: ['cssMediaRule'],
+          CSSSupportsRule: ['cssSupportsRule'],
+        });
+        self.cssRule = document.styleSheets[0].cssRules[0];
+        self.cssMediaRule = document.styleSheets[1].cssRules[0];
+        self.cssSupportsRule = document.styleSheets[2].cssRules[0];
+      }
+    );
   </script>
 
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/idlharness-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-fonts/idlharness-expected.txt
index c501ecc..14c48ad 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-fonts/idlharness-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/idlharness-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-PASS Test IDL implementation of css-fonts API
+PASS idl_test setup
 PASS Partial interface CSSRule: original interface defined
 PASS Partial interface CSSRule[2]: original interface defined
 PASS CSSFontFaceRule interface: existence and properties of interface object
@@ -9,6 +9,11 @@
 PASS CSSFontFaceRule interface: existence and properties of interface prototype object's "constructor" property
 PASS CSSFontFaceRule interface: existence and properties of interface prototype object's @@unscopables property
 PASS CSSFontFaceRule interface: attribute style
+PASS CSSFontFaceRule must be primary interface of cssFontFaceRule
+PASS Stringification of cssFontFaceRule
+PASS CSSFontFaceRule interface: cssFontFaceRule must inherit property "style" with the proper type
+FAIL CSSRule interface: cssFontFaceRule must inherit property "FONT_FEATURE_VALUES_RULE" with the proper type assert_inherits: property "FONT_FEATURE_VALUES_RULE" not found in prototype chain
+FAIL CSSRule interface: cssFontFaceRule must inherit property "FONT_PALETTE_VALUES_RULE" with the proper type assert_inherits: property "FONT_PALETTE_VALUES_RULE" not found in prototype chain
 FAIL CSSFontFeatureValuesRule interface: existence and properties of interface object assert_own_property: self does not have own property "CSSFontFeatureValuesRule" expected property "CSSFontFeatureValuesRule" missing
 FAIL CSSFontFeatureValuesRule interface object length assert_own_property: self does not have own property "CSSFontFeatureValuesRule" expected property "CSSFontFeatureValuesRule" missing
 FAIL CSSFontFeatureValuesRule interface object name assert_own_property: self does not have own property "CSSFontFeatureValuesRule" expected property "CSSFontFeatureValuesRule" missing
@@ -41,5 +46,7 @@
 FAIL CSSRule interface: constant FONT_FEATURE_VALUES_RULE on interface prototype object assert_own_property: expected property "FONT_FEATURE_VALUES_RULE" missing
 FAIL CSSRule interface: constant FONT_PALETTE_VALUES_RULE on interface object assert_own_property: expected property "FONT_PALETTE_VALUES_RULE" missing
 FAIL CSSRule interface: constant FONT_PALETTE_VALUES_RULE on interface prototype object assert_own_property: expected property "FONT_PALETTE_VALUES_RULE" missing
+FAIL CSSRule interface: cssRule must inherit property "FONT_FEATURE_VALUES_RULE" with the proper type assert_inherits: property "FONT_FEATURE_VALUES_RULE" not found in prototype chain
+FAIL CSSRule interface: cssRule must inherit property "FONT_PALETTE_VALUES_RULE" with the proper type assert_inherits: property "FONT_PALETTE_VALUES_RULE" not found in prototype chain
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/idlharness.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/idlharness.html
index 9209144..ecc601b 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-fonts/idlharness.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/idlharness.html
@@ -1,19 +1,34 @@
 <!doctype html>
-<title>css-fonts IDL tests</title>
+<title>CSS Fonts IDL tests</title>
 <link rel="help" href="https://drafts.csswg.org/css-fonts-4/">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/resources/WebIDLParser.js"></script>
 <script src="/resources/idlharness.js"></script>
+
+<style>
+  div { display: block; }
+</style>
+<style>
+  @font-face {
+    font-family: fwf;
+    src: url(support/fonts/FontWithFancyFeatures.otf);
+  }
+</style>
+
 <script>
   "use strict";
 
-  promise_test(async () => {
-    const idl_array = new IdlArray();
-    const idl = await fetch("/interfaces/css-fonts.idl").then(r => r.text());
-    const cssom = await fetch("/interfaces/cssom.idl").then(r => r.text());
-    idl_array.add_idls(idl);
-    idl_array.add_dependency_idls(cssom);
-    idl_array.test();
-  }, "Test IDL implementation of css-fonts API");
+  idl_test(
+    ["css-fonts"],
+    ["cssom"],
+    idl_array => {
+      idl_array.add_objects({
+        CSSRule: ['cssRule'],
+        CSSFontFaceRule: ['cssFontFaceRule'],
+      });
+      self.cssRule = document.styleSheets[0].cssRules[0];
+      self.cssFontFaceRule = document.styleSheets[1].cssRules[0];
+    }
+  );
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-paint-api/idlharness-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-paint-api/idlharness-expected.txt
index 338b395f..e71217c3 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-paint-api/idlharness-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/css/css-paint-api/idlharness-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-PASS Test IDL implementation of CSS Painting API
+PASS idl_test setup
 PASS Partial namespace CSS: original namespace defined
 PASS PaintWorkletGlobalScope interface: existence and properties of interface object
 PASS PaintRenderingContext2D interface: existence and properties of interface object
diff --git a/third_party/blink/web_tests/external/wpt/css/css-paint-api/idlharness.html b/third_party/blink/web_tests/external/wpt/css/css-paint-api/idlharness.html
index bb4c9357..c9675ab 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-paint-api/idlharness.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-paint-api/idlharness.html
@@ -8,19 +8,9 @@
 <script>
   "use strict";
 
-  promise_test(async () => {
-    const idl_array = new IdlArray();
-    const idl = await fetch("/interfaces/css-paint-api.idl").then(r => r.text());
-    const cssom = await fetch("/interfaces/cssom.idl").then(r => r.text());
-    const html = await fetch("/interfaces/html.idl").then(r => r.text());
-    idl_array.add_idls(idl);
-    idl_array.add_dependency_idls(cssom);
-    idl_array.add_dependency_idls(html);
-    idl_array.add_untested_idls(`
-      [Exposed=Worklet]
-      interface WorkletGlobalScope {
-          attribute Console console;
-      };`);
-    idl_array.test();
-  }, "Test IDL implementation of CSS Painting API");
+  idl_test(
+    ["css-paint-api"],
+    ["cssom", "html", "worklets"]
+    // No objects in Window global
+  );
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/idlharness.html b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/idlharness.html
index e57f0f0..6f05375 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/idlharness.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/idlharness.html
@@ -8,13 +8,9 @@
 <script>
   "use strict";
 
-  promise_test(async () => {
-    const idl = await fetch("/interfaces/css-properties-values-api.idl").then(r => r.text());
-    const cssom = await fetch("/interfaces/cssom.idl").then(r => r.text());
-
-    const idl_array = new IdlArray();
-    idl_array.add_idls(idl);
-    idl_array.add_dependency_idls(cssom);
-    idl_array.test();
-  }, "Test IDL implementation of CSS Properties Values API");
+  idl_test(
+    ["css-properties-values-api"],
+    ["cssom"]
+    // No objects
+  );
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-syntax/anb-parsing.html b/third_party/blink/web_tests/external/wpt/css/css-syntax/anb-parsing.html
new file mode 100644
index 0000000..7fcc06e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-syntax/anb-parsing.html
@@ -0,0 +1,125 @@
+<!doctype html>
+<title>An+B Parsing</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+
+foo { color: blue; }
+
+</style>
+
+<meta name="author" title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#the-anb-type">
+
+<script>
+
+function roundtripANB(str) {
+    const rule = document.styleSheets[0].cssRules[0];
+    rule.selectorText = "foo";
+    rule.selectorText = `:nth-child(${str})`;
+    // Check for parse error.
+    if(rule.selectorText == "foo") return "parse error";
+    return rule.selectorText.slice(11, -1);
+}
+function testANB(input, expected) {
+    test(()=>{
+        assert_equals(roundtripANB(input), expected);
+    }, `"${input}" becomes "${expected}"`);
+}
+
+/* Just going down all the syntax clauses one-by-one */
+//  odd | even |
+testANB("odd", "2n+1");
+testANB("even", "2n");
+//  <integer> |
+testANB("1", "1");
+testANB("+1", "1");
+testANB("-1", "-1");
+//
+//  <n-dimension> |
+testANB("5n", "5n");
+testANB("5N", "5n");
+//  '+'?† n |
+testANB("+n", "n");
+testANB("n", "n");
+testANB("N", "n");
+testANB("+ n", "parse error");
+//  -n |
+testANB("-n", "-n");
+testANB("-N", "-n");
+//
+//  <ndashdigit-dimension> |
+testANB("5n-5", "5n-5");
+//  '+'?† <ndashdigit-ident> |
+testANB("+n-5", "n-5");
+testANB("n-5", "n-5");
+testANB("+ n-5", "parse error");
+//  <dashndashdigit-ident> |
+testANB("-n-5", "-n-5");
+//
+//  <n-dimension> <signed-integer> |
+testANB("5n +5", "5n+5");
+testANB("5n -5", "5n-5");
+//  '+'?† n <signed-integer> |
+testANB("+n +5", "n+5");
+testANB("n +5", "n+5");
+testANB("+n -5", "n-5");
+testANB("+ n +5", "parse error");
+testANB("n 5", "parse error");
+//  -n <signed-integer> |
+testANB("-n +5", "-n+5");
+testANB("-n -5", "-n-5");
+testANB("-n 5", "parse error");
+//
+//  <ndash-dimension> <signless-integer> |
+testANB("5n- 5", "5n-5");
+testANB("5n- -5", "parse error");
+testANB("5n- +5", "parse error");
+testANB("-5n- 5", "-5n-5");
+//  '+'?† n- <signless-integer> |
+testANB("+n- 5", "n-5");
+testANB("n- 5", "n-5");
+testANB("+ n- 5", "parse error");
+testANB("n- +5", "parse error");
+testANB("n- -5", "parse error");
+//  -n- <signless-integer> |
+testANB("-n- 5", "-n-5");
+testANB("-n- +5", "parse error");
+testANB("-n- -5", "parse error");
+//
+//  <n-dimension> ['+' | '-'] <signless-integer>
+testANB("5n + 5", "5n+5");
+testANB("5n - 5", "5n-5");
+testANB("5n + +5", "parse error");
+testANB("5n + -5", "parse error");
+testANB("5n - +5", "parse error");
+testANB("5n - -5", "parse error");
+//  '+'?† n ['+' | '-'] <signless-integer> |
+testANB("+n + 5", "n+5");
+testANB("n + 5", "n+5");
+testANB("+ n + 5", "parse error");
+testANB("+n - 5", "n-5");
+testANB("+n + +5", "parse error");
+testANB("+n + -5", "parse error");
+testANB("+n - +5", "parse error");
+testANB("+n - -5", "parse error");
+//  -n ['+' | '-'] <signless-integer>
+testANB("-n + 5", "-n+5");
+testANB("-n - 5", "-n-5");
+testANB("-n + +5", "parse error");
+testANB("-n + -5", "parse error");
+testANB("-n - +5", "parse error");
+testANB("-n - -5", "parse error");
+
+/* Swapped ordering is invalid */
+testANB("1 - n", "parse error");
+testANB("0 - n", "parse error");
+testANB("-1 + n", "parse error");
+
+/* Odd space usage */
+testANB("2 n + 2", "parse error");
+testANB("- 2n", "parse error");
+testANB("+ 2n", "parse error");
+testANB("+2 n", "parse error");
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-syntax/anb-serialization.html b/third_party/blink/web_tests/external/wpt/css/css-syntax/anb-serialization.html
new file mode 100644
index 0000000..787700c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-syntax/anb-serialization.html
@@ -0,0 +1,62 @@
+<!doctype html>
+<title>An+B Serialization</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+
+foo { color: blue; }
+
+</style>
+
+<meta name="author" title="Tab Atkins-Bittner">
+<link rel=help href="https://drafts.csswg.org/css-syntax/#serializing-anb">
+
+<script>
+
+function roundtripANB(str) {
+    const rule = document.styleSheets[0].cssRules[0];
+    rule.selectorText = "foo";
+    rule.selectorText = `:nth-child(${str})`;
+    // Check for parse error.
+    if(rule.selectorText == "foo") return "parse error";
+    return rule.selectorText.slice(11, -1);
+}
+function testANB(input, expected) {
+    test(()=>{
+        assert_equals(roundtripANB(input), expected);
+    }, `"${input}" becomes "${expected}"`);
+}
+
+/* A is 0, or omitted */
+testANB("1", "1");
+testANB("+1", "1");
+testANB("-1", "-1");
+testANB("0n + 0", "0");
+testANB("0n + 1", "1");
+testANB("0n - 1", "-1");
+
+/* A is 1 */
+testANB("1n", "n");
+testANB("1n - 0", "n");
+testANB("1n + 1", "n+1");
+testANB("1n - 1", "n-1");
+
+/* A is -1 */
+testANB("-1n", "-n");
+testANB("-1n - 0", "-n");
+testANB("-1n + 1", "-n+1");
+testANB("-1n - 1", "-n-1");
+
+/* A is implied via + or - */
+testANB("+n+1", "n+1");
+testANB("-n-1", "-n-1");
+
+/* B is 0 */
+testANB("n + 0", "n");
+testANB("n - 0", "n");
+
+/* A & B both nonzero */
+testANB("2n + 2", "2n+2");
+testANB("-2n - 2", "-2n-2");
+
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/vh_not_refreshing_on_chrome.html b/third_party/blink/web_tests/external/wpt/css/css-values/vh_not_refreshing_on_chrome.html
index 52a45a114..1749986 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-values/vh_not_refreshing_on_chrome.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/vh_not_refreshing_on_chrome.html
@@ -6,6 +6,7 @@
 	<link rel="author" title="Marc Bourlon" href="mailto:marc@bourlon.com">
 	<link rel="help" href="http://www.w3.org/TR/css3-values/#viewport-relative-lengths">
 	<link rel="match" href="reference/vh_not_refreshing_on_chrome-ref.html">
+	<meta charset="UTF-8">
 	<meta name="assert" content="vh-based dimension doesn't change when the element's other dimension doesn't change.">
 	<!-- This test exhibits a bug for Chrome 19.0.1084.56 / Mac OS X 10.6.8 -->
 	<script src="/common/reftest-wait.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/viewport-relative-lengths-scaled-viewport.html b/third_party/blink/web_tests/external/wpt/css/css-values/viewport-relative-lengths-scaled-viewport.html
index a901000..dba2af8f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-values/viewport-relative-lengths-scaled-viewport.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/viewport-relative-lengths-scaled-viewport.html
@@ -3,6 +3,7 @@
 <!-- Submitted from TestTWF Paris -->
   <head>
     <title>CSS Values and Units Test: Viewport units in scaled viewport</title>
+    <meta charset="UTF-8">
     <meta name="assert" content="viewport relative units scale with viewport.">
     <link rel="author"  title="Emil A Eklund" href="mailto:eae@chromium.org">
     <link rel="help" href="http://www.w3.org/TR/css3-values/#viewport-relative-lengths">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/viewport-units-css2-001.html b/third_party/blink/web_tests/external/wpt/css/css-values/viewport-units-css2-001.html
index f0feb6d9..c51237d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-values/viewport-units-css2-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/viewport-units-css2-001.html
@@ -2,6 +2,7 @@
 <html>
 <head>
   <title>CSS Values and Units Test: Checks viewport units against CSS 2.1 properties and the CSSOM</title>
+  <meta charset="UTF-8">
   <meta name="assert" content="Testing what happens when one applies and rereads viewport unit lengths to CSS 2.1 properties that accept length values" />
   <link rel="author" title="Christian Schaefer" href="mailto:schaepp@gmx.de">
   <link rel="help" href="http://www.w3.org/TR/css3-values/#viewport-relative-lengths">
diff --git a/third_party/blink/web_tests/external/wpt/feature-policy/reporting/xr-report-only.https.html b/third_party/blink/web_tests/external/wpt/feature-policy/reporting/xr-report-only.https.html
index b52bdbfa..6844226f 100644
--- a/third_party/blink/web_tests/external/wpt/feature-policy/reporting/xr-report-only.https.html
+++ b/third_party/blink/web_tests/external/wpt/feature-policy/reporting/xr-report-only.https.html
@@ -23,11 +23,11 @@
                           {types: ['feature-policy-violation']}).observe();
   });
   try {
-    await navigator.xr.requestDevice();
+    await navigator.xr.supportsSessionMode('inline');
   } catch (err) {
-    // If no XR devices are available, requestDevice() will throw NotFoundError,
-    // but the report should be generated anyway.
-    assert_equals(err.name, 'NotFoundError');
+    // If no XR devices are available, supportsSessionMode() will reject with a
+    // NotSupportedError, but the report should be generated anyway.
+    assert_equals(err.name, 'NotSupportedError');
   }
   check_report_format(await report);
 }, "XR report only mode");
diff --git a/third_party/blink/web_tests/external/wpt/feature-policy/reporting/xr-reporting.https.html b/third_party/blink/web_tests/external/wpt/feature-policy/reporting/xr-reporting.https.html
index b737bb9..1982ea5 100644
--- a/third_party/blink/web_tests/external/wpt/feature-policy/reporting/xr-reporting.https.html
+++ b/third_party/blink/web_tests/external/wpt/feature-policy/reporting/xr-reporting.https.html
@@ -22,7 +22,7 @@
     new ReportingObserver((reports, observer) => resolve([reports, observer]),
                           {types: ['feature-policy-violation']}).observe();
   });
-  await promise_rejects(t, 'SecurityError', navigator.xr.requestDevice(),
+  await promise_rejects(t, 'SecurityError', navigator.xr.supportsSessionMode('inline'),
                         "XR device access should not be allowed in this document.");
   const [reports, observer] = await report;
   check_report_format(reports, observer);
diff --git a/third_party/blink/web_tests/external/wpt/fetch/sec-metadata/embed.tentative.https.sub-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/sec-metadata/embed.tentative.https.sub-expected.txt
deleted file mode 100644
index 8a2cc8b..0000000
--- a/third_party/blink/web_tests/external/wpt/fetch/sec-metadata/embed.tentative.https.sub-expected.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-This is a testharness.js-based test.
-FAIL Same-Origin embed assert_equals: dest expected "embed" but got "nested-document"
-FAIL Same-Site embed assert_equals: dest expected "embed" but got "nested-document"
-FAIL Cross-Site embed assert_equals: dest expected "embed" but got "nested-document"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/fetch/sec-metadata/object.tentative.https.sub-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/sec-metadata/object.tentative.https.sub-expected.txt
deleted file mode 100644
index 0476ef1..0000000
--- a/third_party/blink/web_tests/external/wpt/fetch/sec-metadata/object.tentative.https.sub-expected.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-This is a testharness.js-based test.
-FAIL Same-Origin object assert_equals: dest expected "object" but got "nested-document"
-FAIL Same-Site object assert_equals: dest expected "object" but got "nested-document"
-FAIL Cross-Site object assert_equals: dest expected "object" but got "nested-document"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/fonts/noto/NotoNaskhArabic-regular.woff2 b/third_party/blink/web_tests/external/wpt/fonts/noto/NotoNaskhArabic-regular.woff2
new file mode 100644
index 0000000..e24020d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/fonts/noto/NotoNaskhArabic-regular.woff2
Binary files differ
diff --git a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt
index a9193b4..9934c0e 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 207 tests; 181 PASS, 26 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 207 tests; 188 PASS, 19 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS Partial interface Navigator: original interface defined
 PASS Partial dictionary WebGLContextAttributes: original dictionary defined
@@ -10,15 +10,15 @@
 PASS XR interface: existence and properties of interface prototype object
 PASS XR interface: existence and properties of interface prototype object's "constructor" property
 PASS XR interface: existence and properties of interface prototype object's @@unscopables property
-FAIL XR interface: operation supportsSessionMode(XRSessionMode) assert_own_property: interface prototype object missing non-static operation expected property "supportsSessionMode" missing
-FAIL XR interface: operation requestSession(XRSessionCreationOptions) assert_own_property: interface prototype object missing non-static operation expected property "requestSession" missing
+PASS XR interface: operation supportsSessionMode(XRSessionMode)
+PASS XR interface: operation requestSession(XRSessionCreationOptions)
 PASS XR interface: attribute ondevicechange
 PASS XR must be primary interface of navigator.xr
 PASS Stringification of navigator.xr
-FAIL XR interface: navigator.xr must inherit property "supportsSessionMode(XRSessionMode)" with the proper type assert_inherits: property "supportsSessionMode" not found in prototype chain
-FAIL XR interface: calling supportsSessionMode(XRSessionMode) on navigator.xr with too few arguments must throw TypeError assert_inherits: property "supportsSessionMode" not found in prototype chain
-FAIL XR interface: navigator.xr must inherit property "requestSession(XRSessionCreationOptions)" with the proper type assert_inherits: property "requestSession" not found in prototype chain
-FAIL XR interface: calling requestSession(XRSessionCreationOptions) on navigator.xr with too few arguments must throw TypeError assert_inherits: property "requestSession" not found in prototype chain
+PASS XR interface: navigator.xr must inherit property "supportsSessionMode(XRSessionMode)" with the proper type
+PASS XR interface: calling supportsSessionMode(XRSessionMode) on navigator.xr with too few arguments must throw TypeError
+PASS XR interface: navigator.xr must inherit property "requestSession(XRSessionCreationOptions)" with the proper type
+PASS XR interface: calling requestSession(XRSessionCreationOptions) on navigator.xr with too few arguments must throw TypeError
 PASS XR interface: navigator.xr must inherit property "ondevicechange" with the proper type
 PASS XRSession interface: existence and properties of interface object
 PASS XRSession interface object length
@@ -26,7 +26,7 @@
 PASS XRSession interface: existence and properties of interface prototype object
 PASS XRSession interface: existence and properties of interface prototype object's "constructor" property
 PASS XRSession interface: existence and properties of interface prototype object's @@unscopables property
-FAIL XRSession interface: attribute mode assert_true: The prototype object must have a property "mode" expected true got false
+PASS XRSession interface: attribute mode
 PASS XRSession interface: attribute outputContext
 PASS XRSession interface: attribute environmentBlendMode
 PASS XRSession interface: attribute depthNear
diff --git a/third_party/blink/web_tests/external/wpt/webxr/navigator_xr_requestDevice.https.html b/third_party/blink/web_tests/external/wpt/webxr/navigator_xr_requestDevice.https.html
deleted file mode 100644
index c51dd8db..0000000
--- a/third_party/blink/web_tests/external/wpt/webxr/navigator_xr_requestDevice.https.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<body>
-  <script src=/resources/testharness.js></script>
-  <script src=/resources/testharnessreport.js></script>
-  <script src="resources/webxr_util.js"></script>
-
-  <script>
-    xr_promise_test("navigator.xr.requestDevice returns a device", (t) => {
-      return XRTest.simulateDeviceConnection({ supportsImmersive: true })
-        .then( (controller) => { return navigator.xr.requestDevice() })
-        .then( (device) => {
-          t.step(() => {
-            assert_true(device != null);
-            assert_true(device instanceof XRDevice);
-          });
-        });
-    });
-  </script>
-</body>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/navigator_xr_requestDevice_no_device.https.html b/third_party/blink/web_tests/external/wpt/webxr/navigator_xr_requestDevice_no_device.https.html
deleted file mode 100644
index 3cd149b..0000000
--- a/third_party/blink/web_tests/external/wpt/webxr/navigator_xr_requestDevice_no_device.https.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<!DOCTYPE html>
-<body>
-  <script src=/resources/testharness.js></script>
-  <script src=/resources/testharnessreport.js></script>
-  <script src="resources/webxr_util.js"></script>
-
-  <script>
-    promise_test( (t) => {
-      return promise_rejects(t, 'NotFoundError', navigator.xr.requestDevice());
-    }, "navigator.xr.requestDevice properly rejects when there are 0 devices");
-  </script>
-</body>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/resources/webxr_util.js b/third_party/blink/web_tests/external/wpt/webxr/resources/webxr_util.js
index 10bdc12..7344fa0 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/resources/webxr_util.js
+++ b/third_party/blink/web_tests/external/wpt/webxr/resources/webxr_util.js
@@ -26,7 +26,6 @@
 // Requires a webglCanvas on the page.
 function xr_session_promise_test(
     name, func, fakeDeviceInit, sessionOptions, properties) {
-  let testDevice;
   let testDeviceController;
   let testSession;
 
@@ -44,16 +43,12 @@
           XRTest.simulateDeviceConnection(fakeDeviceInit)
               .then((controller) => {
                 testDeviceController = controller;
-                return navigator.xr.requestDevice();
-              })
-              .then((device) => {
-                testDevice = device;
                 return gl.makeXRCompatible();
               })
               .then(() => new Promise((resolve, reject) => {
                       // Perform the session request in a user gesture.
                       XRTest.simulateUserActivation(() => {
-                        testDevice.requestSession(sessionOptions)
+                        navigator.xr.requestSession(sessionOptions)
                             .then((session) => {
                               testSession = session;
                               // Session must have a baseLayer or frame requests
@@ -74,7 +69,7 @@
               .then(() => {
                 // Cleanup system state.
                 testSession.end().catch(() => {});
-                XRTest.simulateDeviceDisconnection(testDevice);
+                XRTest.simulateDeviceDisconnection();
               }),
       properties);
 }
@@ -97,7 +92,6 @@
 //                that API object.
 function forEachWebxrObject(callback) {
   callback(window.navigator.xr, 'navigator.xr');
-  callback(window.XRDevice, 'XRDevice');
   callback(window.XRSession, 'XRSession');
   callback(window.XRSessionCreationOptions, 'XRSessionCreationOptions');
   callback(window.XRFrameRequestCallback, 'XRFrameRequestCallback');
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive.https.html
index e9e7b9bc..c5956e7f 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive.https.html
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive.https.html
@@ -9,6 +9,6 @@
       "Tests requestSession resolves when supported",
       (session) => {
         assert_not_equals(session, null);
-      }, { supportsImmersive:true }, { immersive: true });
+      }, { supportsImmersive:true }, { mode: 'immersive-vr' });
   </script>
 </body>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive_no_gesture.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive_no_gesture.https.html
index 9f0f5f3..c1b32867 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive_no_gesture.https.html
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive_no_gesture.https.html
@@ -8,9 +8,8 @@
       "Requesting immersive session outside of a user gesture rejects",
       (t) => {
         return XRTest.simulateDeviceConnection({ supportsImmersive:true })
-          .then( (controller) => { return navigator.xr.requestDevice() })
-          .then( (device) => promise_rejects(
-            t, 'SecurityError', device.requestSession({ immersive: true })));
+          .then( (controller) => promise_rejects(
+            t, 'SecurityError', navigator.xr.requestSession({ mode: 'immersive-vr' })));
       });
   </script>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive_unsupported.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive_unsupported.https.html
index e0d2688e..60e9e6c 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive_unsupported.https.html
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_immersive_unsupported.https.html
@@ -8,13 +8,12 @@
       "Requesting an immersive session when unsupported rejects",
       (t) => {
         return XRTest.simulateDeviceConnection({ supportsImmersive:false })
-          .then( (controller) => { return navigator.xr.requestDevice() })
-          .then( (magicWindowOnlyDevice) => new Promise((resolve) => {
+          .then( (controller) => new Promise((resolve) => {
             XRTest.simulateUserActivation( () => {
               resolve(promise_rejects(
                 t,
                 "NotSupportedError",
-                magicWindowOnlyDevice.requestSession({ immersive: true })
+                navigator.xr.requestSession({ mode: 'immersive-vr' })
               ))
             });
           }));
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_non_immersive_no_gesture.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_non_immersive_no_gesture.https.html
index 1634dfe..6cf50f52 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_non_immersive_no_gesture.https.html
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_requestSession_non_immersive_no_gesture.https.html
@@ -8,9 +8,8 @@
       "Requesting non-immersive session outside of a user gesture succeeds",
       (t) => {
         return XRTest.simulateDeviceConnection({ supportsImmersive:false })
-          .then( (controller) => { return navigator.xr.requestDevice(); })
-          .then( (device) => device.requestSession({
-            immersive: false,
+          .then( (controller) => navigator.xr.requestSession({
+            mode: 'inline',
             outputContext: getOutputContext()
           }))
           .then( (session) => { assert_not_equals(session, null); });
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_supportsSession_immersive.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_supportsSession_immersive.https.html
index 3ca5eb11..c0b47013 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_supportsSession_immersive.https.html
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_supportsSession_immersive.https.html
@@ -5,11 +5,10 @@
   <script src="resources/webxr_util.js"></script>
   <script>
     xr_promise_test(
-      "supportsSession resolves when immersive options supported",
+      "supportsSessionMode resolves when immersive options supported",
       () => {
         return XRTest.simulateDeviceConnection({ supportsImmersive:true })
-          .then( (controller) => { return navigator.xr.requestDevice() })
-          .then( (device) => device.supportsSession({ immersive: true }));
+          .then( (controller) => navigator.xr.supportsSessionMode('immersive-vr'));
       });
   </script>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_supportsSession_immersive_unsupported.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_supportsSession_immersive_unsupported.https.html
index 0c1dd258..2b17b96b 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_supportsSession_immersive_unsupported.https.html
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_supportsSession_immersive_unsupported.https.html
@@ -5,15 +5,14 @@
   <script src="resources/webxr_util.js"></script>
   <script>
     xr_promise_test(
-      "supportsSession rejects when options not supported",
+      "supportsSessionMode rejects when options not supported",
       (t) => {
       return XRTest.simulateDeviceConnection({ supportsImmersive:false })
-        .then( (controller) => { return navigator.xr.requestDevice() })
-        .then( (device) => {
+        .then( (controller) => {
           return promise_rejects(
             t,
             "NotSupportedError",
-            device.supportsSession({ immersive: true })
+            navigator.xr.supportsSessionMode('immersive-vr')
           );
         });
     });
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_supportsSession_non_immersive.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_supportsSession_non_immersive.https.html
index 535b0bc..69a35c2 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrDevice_supportsSession_non_immersive.https.html
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrDevice_supportsSession_non_immersive.https.html
@@ -5,18 +5,12 @@
   <script src="resources/webxr_util.js"></script>
   <script>
     xr_promise_test(
-      "supportsSession resolves when non-immersive options supported",
+      "supportsSessionMode resolves when inline options supported",
       (t) => {
       return XRTest.simulateDeviceConnection({ supportsImmersive:true })
-        .then( (controller) => { return navigator.xr.requestDevice() })
-        .then( (device) => {
-          // Non-immersive sessions without a outputContext should not be supported.
-          promise_rejects(t, 'NotSupportedError', device.supportsSession());
-
-          // Non-immersive sessions with an outputContext should be supported.
-          return device.supportsSession({
-              outputContext: getOutputContext()
-          });
+        .then( (controller) => {
+          // Inline sessions should be supported.
+          return navigator.xr.supportsSessionMode('inline');
         });
     });
   </script>
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame.https.html
index 26c0e95..9b08f93 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame.https.html
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame.https.html
@@ -13,7 +13,7 @@
 
     let fakeDeviceInitParams = { supportsImmersive:true };
 
-    let immersiveSessionOptions = { immersive: true };
+    let immersiveSessionOptions = { mode: 'immersive-vr' };
     let nonImmersiveSessionOptions = { outputContext: getOutputContext() };
 
     let testFunction = (session) => new Promise((resolve, reject) => {
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html
index 4f4b8dfe..bc9b625 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html
@@ -12,7 +12,7 @@
 
     let fakeDeviceInitParams = { supportsImmersive:true };
 
-    let immersiveSessionOptions = { immersive: true };
+    let immersiveSessionOptions = { mode: 'immersive-vr' };
     let nonImmersiveSessionOptions = { outputContext: getOutputContext() };
 
     let testFunction = (testSession) => new Promise((resolve) => {
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_end.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_end.https.html
index 69bbda8..2719bdd 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_end.https.html
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_end.https.html
@@ -11,7 +11,7 @@
     let watcherDone = new Event("watcherdone");
     const fakeDeviceInitParams = { supportsImmersive:true };
 
-    const immersiveSessionOptions = { immersive: true };
+    const immersiveSessionOptions = { mode: 'immersive-vr' };
     const nonImmersiveSessionOptions = { outputContext: getOutputContext() };
 
     let testFunction = function(session, testDeviceController, t) {
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_mode.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_mode.https.html
new file mode 100644
index 0000000..4b54d948
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_mode.https.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<body>
+  <script src=/resources/testharness.js></script>
+  <script src=/resources/testharnessreport.js></script>
+  <script src="resources/webxr_util.js"></script>
+  <canvas></canvas>
+
+  <script>
+    xr_promise_test("Requested session has it's mode set",
+     (t) => {
+      return XRTest.simulateDeviceConnection({ supportsImmersive:true })
+        .then( (controller) => new Promise((resolve) => {
+          XRTest.simulateUserActivation( () => {
+            resolve(navigator.xr.requestSession({ mode: 'immersive-vr' }).then( (session) => {
+              assert_equals(session.mode, 'immersive-vr');
+            }));
+          });
+        }));
+    });
+  </script>
+</body>
+
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_prevent_multiple_exclusive.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_prevent_multiple_exclusive.https.html
index ff3eaef..c2e7f3b 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_prevent_multiple_exclusive.https.html
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_prevent_multiple_exclusive.https.html
@@ -10,26 +10,25 @@
       "Test prevention of multiple simultaneous immersive sessions",
       (t) => {
       return XRTest.simulateDeviceConnection({ supportsImmersive:true })
-        .then( (controller) => { return navigator.xr.requestDevice() })
-        .then( (device) => new Promise((resolve) => {
+        .then( (controller) => new Promise((resolve) => {
           XRTest.simulateUserActivation( () => {
-            resolve(device.requestSession({ immersive: true })
+            resolve(navigator.xr.requestSession({ mode: 'immersive-vr' })
               .then( (session) => new Promise((resolve) => {
                 XRTest.simulateUserActivation( () => {
-                  // Requesting a second immersive session from a device that already
-                  // has an active immersive session should fail. Immersive sessions
+                  // Requesting a second immersive session when another immersive
+                  // session is active should fail. Immersive sessions
                   // should take up the users entire view, and therefore it should
                   // be impossible for a user to be engaged with more than one.
                   resolve(promise_rejects(
                     t,
                     "InvalidStateError",
-                    device.requestSession({ immersive: true })
+                    navigator.xr.requestSession({ mode: 'immersive-vr' })
                   ).then( () => {
                       // End the immersive session and try again. Now the immersive
                       // session creation should succeed.
                       return session.end().then( () => new Promise((resolve) => {
                         XRTest.simulateUserActivation( () => {
-                          resolve(device.requestSession({ immersive: true }));
+                          resolve(navigator.xr.requestSession({ mode: 'immersive-vr' }));
                         });
                       }));
                     }));
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_callback_calls.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_callback_calls.https.html
index 48dc887..268efcd 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_callback_calls.https.html
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_callback_calls.https.html
@@ -13,7 +13,7 @@
 
     let fakeDeviceInitParams = { supportsImmersive:true };
 
-    let immersiveSessionOptions = { immersive: true };
+    let immersiveSessionOptions = { mode: 'immersive-vr' };
     let nonImmersiveSessionOptions = { outputContext: getOutputContext() };
 
     let testFunction = (testSession) => new Promise((resolve) => {
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html
index b5f4f180..f873a11 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html
@@ -28,7 +28,7 @@
     };
 
     const fakeDeviceInitOptions = { supportsImmersive:true };
-    const sessionOptions = { immersive:true };
+    const sessionOptions = { mode: 'immersive-vr' };
 
     let testSession;
 
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html
index 17b5307..ca6a7175 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestAnimationFrame_getViewerPose.https.html
@@ -14,7 +14,7 @@
 
     let fakeDeviceInitParams = { supportsImmersive: true };
 
-    let immersiveSessionOptions = { immersive: true };
+    let immersiveSessionOptions = { mode: 'immersive-vr' };
     let nonImmersiveSessionOptions = { outputContext: getOutputContext() };
 
     // Valid matrices for  when we don't care about specific values
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace.https.html
index d97852c..1eb49e0 100644
--- a/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace.https.html
+++ b/third_party/blink/web_tests/external/wpt/webxr/xrSession_requestReferenceSpace.https.html
@@ -13,7 +13,7 @@
 
     let fakeDeviceInitParams = { supportsImmersive: true };
 
-    let immersiveSessionOptions = { immersive: true };
+    let immersiveSessionOptions = { mode: 'immersive-vr' };
     let nonImmersiveSessionOptions = { outputContext: getOutputContext() };
 
     let testFunction = function(session, fakeDeviceController, t) {
diff --git a/third_party/blink/web_tests/http/tests/devtools/copy-network-request-expected.txt b/third_party/blink/web_tests/http/tests/devtools/copy-network-request-expected.txt
index 193abde..4c3e2d3 100644
--- a/third_party/blink/web_tests/http/tests/devtools/copy-network-request-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/copy-network-request-expected.txt
@@ -19,13 +19,13 @@
 cURL Windows: curl "http://example.org/path" -H "Content-Type: application/binary" --data-binary ^"1234^
 
 00^^^^'^\^"^!^" --compressed
-cURL Unix: curl 'http://example.org/path' -H 'Content-Type: application/binary' --data-binary $'1234\r\n00\u02\u03\u04\u05\'"!' --compressed
+cURL Unix: curl 'http://example.org/path' -H 'Content-Type: application/binary' --data-binary $'1234\r\n00\u02\u03\u04\u05\'"\u21' --compressed
 Powershell: Invoke-WebRequest -Uri "http://example.org/path" -Method "POST" -ContentType "application/binary" -Body ([System.Text.Encoding]::UTF8.GetBytes("1234$([char]13)$([char]10)00$([char]2)$([char]3)$([char]4)$([char]5)'`"!"))
 fetch: fetch("http://example.org/path", {"credentials":"omit","headers":{"content-type":"application/binary"},"body":"1234\r\n00\u0002\u0003\u0004\u0005'\"!","method":"POST","mode":"cors"});
 cURL Windows: curl "http://example.org/path" -H "Content-Type: application/binary" --data-binary ^"1234^
 
 ^00^^^^'^\^"^!^" --compressed
-cURL Unix: curl 'http://example.org/path' -H 'Content-Type: application/binary' --data-binary $'1234\r\n\u0100\u02\u03\u04\u05\'"!' --compressed
+cURL Unix: curl 'http://example.org/path' -H 'Content-Type: application/binary' --data-binary $'1234\r\n\u0100\u02\u03\u04\u05\'"\u21' --compressed
 Powershell: Invoke-WebRequest -Uri "http://example.org/path" -Method "POST" -ContentType "application/binary" -Body ([System.Text.Encoding]::UTF8.GetBytes("1234$([char]13)$([char]10)$([char]1)00$([char]2)$([char]3)$([char]4)$([char]5)'`"!"))
 fetch: fetch("http://example.org/path", {"credentials":"omit","headers":{"content-type":"application/binary"},"body":"1234\r\n\u000100\u0002\u0003\u0004\u0005'\"!","method":"POST","mode":"cors"});
 cURL Windows: curl "http://example.org/path" -H "Content-Type: application/binary" --data-binary ^"^%^OS^%^
@@ -33,7 +33,7 @@
 ^%^%^OS^%^%^
 
 ^\^"^\^\^\^"'^$^&^!^" --compressed
-cURL Unix: curl 'http://example.org/path' -H 'Content-Type: application/binary' --data-binary $'%OS%\r\n%%OS%%\r\n"\\"\'$&!' --compressed
+cURL Unix: curl 'http://example.org/path' -H 'Content-Type: application/binary' --data-binary $'%OS%\r\n%%OS%%\r\n"\\"\'$&\u21' --compressed
 Powershell: Invoke-WebRequest -Uri "http://example.org/path" -Method "POST" -ContentType "application/binary" -Body ([System.Text.Encoding]::UTF8.GetBytes("%OS%$([char]13)$([char]10)%%OS%%$([char]13)$([char]10)`"\`"'`$&!"))
 fetch: fetch("http://example.org/path", {"credentials":"omit","headers":{"content-type":"application/binary"},"body":"%OS%\r\n%%OS%%\r\n\"\\\"'$&!","method":"POST","mode":"cors"});
 cURL Windows: curl "http://example.org/path" -H "Content-Type: application/binary" --data-binary ^"^!^@^#^$^%^^^&*()_+~`1234567890-=^[^]^{^};':^\^",./^
@@ -47,7 +47,7 @@
 ^
 
 yuiopasdfghjklmnbvcxzQWERTYUIOPLKJHGFDSAZXCVBNM^" --compressed
-cURL Unix: curl 'http://example.org/path' -H 'Content-Type: application/binary' --data-binary $'!@#$%^&*()_+~`1234567890-=[]{};\':",./\r<>?\r\nqwer\nt\n\nyuiopasdfghjklmnbvcxzQWERTYUIOPLKJHGFDSAZXCVBNM' --compressed
+cURL Unix: curl 'http://example.org/path' -H 'Content-Type: application/binary' --data-binary $'\u21@#$%^&*()_+~`1234567890-=[]{};\':",./\r<>?\r\nqwer\nt\n\nyuiopasdfghjklmnbvcxzQWERTYUIOPLKJHGFDSAZXCVBNM' --compressed
 Powershell: Invoke-WebRequest -Uri "http://example.org/path" -Method "POST" -ContentType "application/binary" -Body ([System.Text.Encoding]::UTF8.GetBytes("!@#`$%^&*()_+~``1234567890-=[]{};':`",./$([char]13)<>?$([char]13)$([char]10)qwer$([char]10)t$([char]10)$([char]10)yuiopasdfghjklmnbvcxzQWERTYUIOPLKJHGFDSAZXCVBNM"))
 fetch: fetch("http://example.org/path", {"credentials":"omit","headers":{"content-type":"application/binary"},"body":"!@#$%^&*()_+~`1234567890-=[]{};':\",./\r<>?\r\nqwer\nt\n\nyuiopasdfghjklmnbvcxzQWERTYUIOPLKJHGFDSAZXCVBNM","method":"POST","mode":"cors"});
 cURL Windows: curl "http://example.org/path" -H "Content-Type: application/binary" --data-binary "^^€^^ÿ	^܀" --compressed
diff --git a/third_party/blink/web_tests/http/tests/loading/307-after-303-after-post-expected.txt b/third_party/blink/web_tests/http/tests/loading/307-after-303-after-post-expected.txt
index 8771e8b..93155c1 100644
--- a/third_party/blink/web_tests/http/tests/loading/307-after-303-after-post-expected.txt
+++ b/third_party/blink/web_tests/http/tests/loading/307-after-303-after-post-expected.txt
@@ -7,8 +7,6 @@
 http://127.0.0.1:8000/loading/resources/post-to-303-target.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/post-to-303-target.php, main document URL http://127.0.0.1:8000/loading/resources/post-to-303-target.php, http method POST>
 main frame - didStartProvisionalLoadForFrame
 main frame - didStartProvisionalLoadForFrame
-http://127.0.0.1:8000/loading/resources/303-to-307-target.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/303-to-307-target.php, main document URL http://127.0.0.1:8000/loading/resources/303-to-307-target.php, http method GET>
-http://127.0.0.1:8000/loading/resources/307-post-output-target.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/307-post-output-target.php, main document URL http://127.0.0.1:8000/loading/resources/307-post-output-target.php, http method GET>
 http://127.0.0.1:8000/loading/resources/307-post-output-target.php - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/307-post-output-target.php, http status code 200>
 main frame - didCommitLoadForFrame
 main frame - didReceiveTitle: 
diff --git a/third_party/blink/web_tests/http/tests/loading/redirect-methods-expected.txt b/third_party/blink/web_tests/http/tests/loading/redirect-methods-expected.txt
index 74758a5..6b627ca 100644
--- a/third_party/blink/web_tests/http/tests/loading/redirect-methods-expected.txt
+++ b/third_party/blink/web_tests/http/tests/loading/redirect-methods-expected.txt
@@ -23,7 +23,6 @@
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method POST>
 frame "0" - didStartProvisionalLoadForFrame
 frame "0" - didStartProvisionalLoadForFrame
-http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method GET>
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, http status code 200>
 frame "0" - didCommitLoadForFrame
 frame "0" - didReceiveTitle: 
@@ -49,7 +48,6 @@
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method POST>
 frame "1" - didStartProvisionalLoadForFrame
 frame "1" - didStartProvisionalLoadForFrame
-http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method GET>
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, http status code 200>
 frame "1" - didCommitLoadForFrame
 frame "1" - didReceiveTitle: 
@@ -75,7 +73,6 @@
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method POST>
 frame "2" - didStartProvisionalLoadForFrame
 frame "2" - didStartProvisionalLoadForFrame
-http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method GET>
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, http status code 200>
 frame "2" - didCommitLoadForFrame
 frame "2" - didReceiveTitle: 
@@ -101,7 +98,6 @@
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method POST>
 frame "3" - didStartProvisionalLoadForFrame
 frame "3" - didStartProvisionalLoadForFrame
-http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, main document URL http://127.0.0.1:8000/loading/redirect-methods.html, http method POST>
 http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/loading/resources/redirect-methods-result.php?redirected=true, http status code 200>
 frame "3" - didCommitLoadForFrame
 frame "3" - didReceiveTitle: 
diff --git a/third_party/blink/web_tests/http/tests/misc/favicon-loads-with-images-disabled-expected.txt b/third_party/blink/web_tests/http/tests/misc/favicon-loads-with-images-disabled-expected.txt
index 7fd84a79..52fd866 100644
--- a/third_party/blink/web_tests/http/tests/misc/favicon-loads-with-images-disabled-expected.txt
+++ b/third_party/blink/web_tests/http/tests/misc/favicon-loads-with-images-disabled-expected.txt
@@ -1,4 +1,3 @@
-http://127.0.0.1:8000/misc/favicon-loads-with-images-disabled.html - willSendRequest <NSURLRequest URL http://127.0.0.1:8000/misc/favicon-loads-with-images-disabled.html, main document URL http://127.0.0.1:8000/misc/favicon-loads-with-images-disabled.html, http method GET>
 http://127.0.0.1:8000/misc/favicon-loads-with-images-disabled.html - didReceiveResponse <NSURLResponse http://127.0.0.1:8000/misc/favicon-loads-with-images-disabled.html, http status code 200>
 Radar 6973106 and https://bugs.webkit.org/show_bug.cgi?id=27896 - Favicons still load when automatic image loading is disabled.
 This test uses DRT's resource load delegate callback mode to see if the favicon is loaded even when image loading is off.
diff --git a/third_party/blink/web_tests/http/tests/priorities/resource-load-priorities.html b/third_party/blink/web_tests/http/tests/priorities/resource-load-priorities.html
index 88de91c1..139487e3 100644
--- a/third_party/blink/web_tests/http/tests/priorities/resource-load-priorities.html
+++ b/third_party/blink/web_tests/http/tests/priorities/resource-load-priorities.html
@@ -49,9 +49,6 @@
   'Module scripts should be loaded with kHigh priority');
 
 resource_load_priority_test(
-  'iframe.html', kVeryHigh, 'Iframes should be loaded with kVeryHigh priority');
-
-resource_load_priority_test(
   'fetch.html', kHigh,
   'Requests from the Fetch API should be loaded with kHigh priority');
 
diff --git a/third_party/blink/web_tests/inspector-protocol/dom/dom-getBoxModel.js b/third_party/blink/web_tests/inspector-protocol/dom/dom-getBoxModel.js
index 1a2f82b..16c8e2bc 100644
--- a/third_party/blink/web_tests/inspector-protocol/dom/dom-getBoxModel.js
+++ b/third_party/blink/web_tests/inspector-protocol/dom/dom-getBoxModel.js
@@ -32,6 +32,7 @@
   const bn3 = (await dp.DOM.getNodeForLocation({x: 500, y: 500})).result.backendNodeId;
 
   await dp.DOM.enable();
+  await dp.DOM.getDocument();
   await nodeTracker.nodeForBackendId(bn1);
   await nodeTracker.nodeForBackendId(bn2);
   await nodeTracker.nodeForBackendId(bn3);
diff --git a/third_party/blink/web_tests/inspector-protocol/dom/dom-getNodeForLocation-skip-shadow.js b/third_party/blink/web_tests/inspector-protocol/dom/dom-getNodeForLocation-skip-shadow.js
index 61aa4b6..7ac3213 100644
--- a/third_party/blink/web_tests/inspector-protocol/dom/dom-getNodeForLocation-skip-shadow.js
+++ b/third_party/blink/web_tests/inspector-protocol/dom/dom-getNodeForLocation-skip-shadow.js
@@ -11,6 +11,7 @@
   var message = await dp.DOM.getNodeForLocation({x: 10, y: 10, includeUserAgentShadowDOM: false});
   var backendNodeId = message.result.backendNodeId;
   await dp.DOM.enable();
+  await dp.DOM.getDocument();
   testRunner.log(await nodeTracker.nodeForBackendId(backendNodeId), 'Node: ');
   testRunner.completeTest();
 })
diff --git a/third_party/blink/web_tests/inspector-protocol/dom/dom-getNodeForLocation.js b/third_party/blink/web_tests/inspector-protocol/dom/dom-getNodeForLocation.js
index e5b76369..f3048c1 100644
--- a/third_party/blink/web_tests/inspector-protocol/dom/dom-getNodeForLocation.js
+++ b/third_party/blink/web_tests/inspector-protocol/dom/dom-getNodeForLocation.js
@@ -8,6 +8,7 @@
   var response = await dp.DOM.getNodeForLocation({x: 10, y: 10});
   var backendNodeId = response.result.backendNodeId;
   await dp.DOM.enable();
+  await dp.DOM.getDocument();
   testRunner.log(await nodeTracker.nodeForBackendId(backendNodeId), 'Node: ');
   testRunner.completeTest();
 })
diff --git a/third_party/blink/web_tests/inspector-protocol/dom/dom-setInspectModeEnabled.js b/third_party/blink/web_tests/inspector-protocol/dom/dom-setInspectModeEnabled.js
index ad8a442e..75ec8dc8 100644
--- a/third_party/blink/web_tests/inspector-protocol/dom/dom-setInspectModeEnabled.js
+++ b/third_party/blink/web_tests/inspector-protocol/dom/dom-setInspectModeEnabled.js
@@ -6,6 +6,7 @@
   var nodeTracker = new NodeTracker(dp);
   dp.DOM.enable();
   dp.Overlay.enable();
+  await dp.DOM.getDocument();
   var message = await dp.Overlay.setInspectMode({ mode: 'searchForNode', highlightConfig: {} });
   if (message.error) {
     testRunner.die(message.error.message);
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/feature-policy-features-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/feature-policy-features-expected.txt
index ec58930..6732d35 100644
--- a/third_party/blink/web_tests/virtual/stable/webexposed/feature-policy-features-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/webexposed/feature-policy-features-expected.txt
@@ -18,5 +18,4 @@
 sync-xhr
 usb
 vr
-wake-lock
 
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index 585e4278..e6cadb2b 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -10349,17 +10349,13 @@
     attribute @@toStringTag
     getter ondevicechange
     method constructor
-    method requestDevice
+    method requestSession
+    method supportsSessionMode
     setter ondevicechange
 interface XRBoundedReferenceSpace : XRReferenceSpace
     attribute @@toStringTag
     getter boundsGeometry
     method constructor
-interface XRDevice
-    attribute @@toStringTag
-    method constructor
-    method requestSession
-    method supportsSession
 interface XRFrame
     attribute @@toStringTag
     getter session
@@ -10416,7 +10412,7 @@
     getter depthFar
     getter depthNear
     getter environmentBlendMode
-    getter immersive
+    getter mode
     getter onblur
     getter onend
     getter onfocus
diff --git a/third_party/blink/web_tests/xr/ar_hittest.html b/third_party/blink/web_tests/xr/ar_hittest.html
index 165a2f5a..05033bc3 100644
--- a/third_party/blink/web_tests/xr/ar_hittest.html
+++ b/third_party/blink/web_tests/xr/ar_hittest.html
@@ -17,8 +17,7 @@
                              supportsEnvironmentIntegration: true };
 
 let requestSessionOptions = [ {
-    immersive: false,
-    environmentIntegration: true,
+    mode: 'legacy-inline-ar',
     outputContext: getOutputContext()
   } ];
 
@@ -28,7 +27,8 @@
                          0, 0, 0, 1];
 
 let testFunction = function(session, t, fakeDeviceController) {
-  assert_false(session.immersive);
+  assert_equals(session.mode, 'legacy-inline-ar');
+  assert_not_equals(session.environmentBlendMode, 'opaque');
   return session.requestReferenceSpace({ type: "stationary", subtype: "eye-level" }).then((referenceSpace) => {
     let direction = new Float32Array([1.0, 0.0, 0.0]);
     let origin = new Float32Array([0.0, 0.0, 0.0]);
diff --git a/third_party/blink/web_tests/xr/events_session_resetpose.html b/third_party/blink/web_tests/xr/events_session_resetpose.html
index 47f4194b..e3e2407 100644
--- a/third_party/blink/web_tests/xr/events_session_resetpose.html
+++ b/third_party/blink/web_tests/xr/events_session_resetpose.html
@@ -19,7 +19,7 @@
 
 let requestSessionOptions = [
   { outputContext: getOutputContext() },
-  { immersive: true },
+  { mode: 'immersive-vr' },
 ];
 
 let testFunction = function(session, t, fakeDeviceController) {
diff --git a/third_party/blink/web_tests/xr/events_session_select.html b/third_party/blink/web_tests/xr/events_session_select.html
index d7f9f9b..c7fbfdc 100644
--- a/third_party/blink/web_tests/xr/events_session_select.html
+++ b/third_party/blink/web_tests/xr/events_session_select.html
@@ -17,7 +17,7 @@
 
 let fakeDeviceInitParams = { supportsImmersive:true };
 
-let requestSessionOptions = [{ immersive: true }];
+let requestSessionOptions = [{ mode: 'immersive-vr' }];
 
 let testFunction = function(session, t, fakeDeviceController) {
   let eventWatcher = new EventWatcher(
diff --git a/third_party/blink/web_tests/xr/events_session_select_subframe.html b/third_party/blink/web_tests/xr/events_session_select_subframe.html
index 864dbb36..cb23b284 100644
--- a/third_party/blink/web_tests/xr/events_session_select_subframe.html
+++ b/third_party/blink/web_tests/xr/events_session_select_subframe.html
@@ -18,7 +18,7 @@
 
 let fakeDeviceInitParams = { supportsImmersive:true };
 
-let requestSessionOptions = [{ immersive: true }];
+let requestSessionOptions = [{ mode: 'immersive-vr' }];
 
 let testFunction = function(session, t, fakeDeviceController) {
   let eventWatcher = new EventWatcher(
diff --git a/third_party/blink/web_tests/xr/exclusive_requestFrame_nolayer.html b/third_party/blink/web_tests/xr/exclusive_requestFrame_nolayer.html
index 4affa62..5d4055b 100644
--- a/third_party/blink/web_tests/xr/exclusive_requestFrame_nolayer.html
+++ b/third_party/blink/web_tests/xr/exclusive_requestFrame_nolayer.html
@@ -14,7 +14,7 @@
 let fakeDeviceInitParams = { supportsImmersive:true };
 
 let requestSessionOptions = [
-  { immersive: true },
+  { mode: 'immersive-vr' },
   { outputContext: getOutputContext() }
 ];
 
diff --git a/third_party/blink/web_tests/xr/getInputPose_hand.html b/third_party/blink/web_tests/xr/getInputPose_hand.html
index 171012e..84535795 100644
--- a/third_party/blink/web_tests/xr/getInputPose_hand.html
+++ b/third_party/blink/web_tests/xr/getInputPose_hand.html
@@ -16,7 +16,7 @@
 
 let fakeDeviceInitParams = { supportsImmersive: true };
 
-let requestSessionOptions =  [{ immersive: true }];
+let requestSessionOptions =  [{ mode: 'immersive-vr' }];
 
 let testFunction =
   (session, t, fakeDeviceController) => new Promise((resolve) => {
diff --git a/third_party/blink/web_tests/xr/getInputPose_ray.html b/third_party/blink/web_tests/xr/getInputPose_ray.html
index 208c6bb..9af0e2c6 100644
--- a/third_party/blink/web_tests/xr/getInputPose_ray.html
+++ b/third_party/blink/web_tests/xr/getInputPose_ray.html
@@ -15,7 +15,7 @@
 
 let fakeDeviceInitParams = { supportsImmersive: true };
 
-let requestSessionOptions =  [{ immersive: true }];
+let requestSessionOptions =  [{ mode: 'immersive-vr' }];
 
 let testFunction =
   (session, t, fakeDeviceController) => new Promise((resolve) => {
diff --git a/third_party/blink/web_tests/xr/navigator_xr_blocks_getVRDisplays.html b/third_party/blink/web_tests/xr/navigator_xr_blocks_getVRDisplays.html
index b945238..520333f 100644
--- a/third_party/blink/web_tests/xr/navigator_xr_blocks_getVRDisplays.html
+++ b/third_party/blink/web_tests/xr/navigator_xr_blocks_getVRDisplays.html
@@ -3,7 +3,7 @@
 <script src="../resources/testharnessreport.js"></script>
 <script>
 
-promise_test((t) => navigator.xr.requestDevice().catch(() => {
+promise_test((t) => navigator.xr.requestSession({ mode: 'immersive-vr' }).catch(() => {
   return promise_rejects(t, "InvalidStateError", navigator.getVRDisplays());
 }), "Test that calls to navigator.getVRDisplays are blocked once navigator.xr has been accessed.");
 
diff --git a/third_party/blink/web_tests/xr/navigator_xr_detached.html b/third_party/blink/web_tests/xr/navigator_xr_detached.html
index b360f448..e90a33d 100644
--- a/third_party/blink/web_tests/xr/navigator_xr_detached.html
+++ b/third_party/blink/web_tests/xr/navigator_xr_detached.html
@@ -12,8 +12,9 @@
 promise_test((t) => {
   var nav_xr = window.frames[0].navigator.xr;
   document.getElementById("subframe").remove();
-  return promise_rejects(t, "InvalidStateError", nav_xr.requestDevice());
-}, "Check that navigator.xr.requestDevice rejects on a detached navigator.");
+  return promise_rejects(t, "InvalidStateError", nav_xr.supportsSessionMode('inline'))
+      .then(() => promise_rejects(t, "InvalidStateError", nav_xr.requestSession({ mode: 'inline' })));
+}, "Check that navigator.xr.supportsSessionMode and navigator.xr.requestSession reject on a detached navigator.");
 
 </script>
 </body>
diff --git a/third_party/blink/web_tests/xr/resources/xr-test-utils.js b/third_party/blink/web_tests/xr/resources/xr-test-utils.js
index ba23310..7774739 100644
--- a/third_party/blink/web_tests/xr/resources/xr-test-utils.js
+++ b/third_party/blink/web_tests/xr/resources/xr-test-utils.js
@@ -13,70 +13,66 @@
     return XRTest.simulateDeviceConnection(deviceOptions)
         .then((controller) => {
           fakeDeviceController = controller;
-          return navigator.xr.requestDevice();
-        })
-        .then((device) => {
           if (gl) {
-            return gl.makeXRCompatible(device).then(
-                () => Promise.resolve(device));
+            return gl.makeXRCompatible().then(
+                () => Promise.resolve());
           } else {
-            return Promise.resolve(device);
+            return Promise.resolve();
           }
         })
-        .then(
-            (device) => new Promise((resolve, reject) => {
-              // Run the test with each set of sessionOptions from the array one
-              // at a time.
-              function nextSessionTest(i) {
-                // Check if it's time to break the loop.
-                if (i == sessionOptions.length) {
-                  if (sessionOptions.length == 0) {
-                    reject('No option for the session. Test Did not run.');
-                  } else {
-                    resolve();
-                  }
-                  return;
-                }
-
-                // Perform the session request in a user gesture.
-                runWithUserGesture(() => {
-                  let nextOptions = sessionOptions[i];
-                  let testSession = null;
-                  device.requestSession(nextOptions)
-                      .then((session) => {
-                        testSession = session;
-                        return func(session, t, fakeDeviceController);
-                      })
-                      .then(() => {
-                        // End the session. Silence any errors generated if the
-                        // session was already ended.
-                        // TODO(bajones): Throwing an error when a session is
-                        // already ended is not defined by the spec. This
-                        // should be defined or removed.
-                        testSession.end().catch(() => {});
-                        fakeDeviceController.setXRPresentationFrameData(null);
-                      })
-                      .then(() => nextSessionTest(++i))
-                      .catch((err) => {
-                        let optionsString = '{';
-                        let firstOption = true;
-                        for (let option in nextOptions) {
-                          if (!firstOption) {
-                            optionsString += ',';
-                          }
-                          optionsString += ` ${option}: ${nextOptions[option]}`;
-                          firstOption = false;
-                        }
-                        optionsString += ' }';
-                        reject(
-                            `Test failed while running with the following options:
-                            ${optionsString} ${err}`);
-                      });
-                });
+        .then(() => new Promise((resolve, reject) => {
+          // Run the test with each set of sessionOptions from the array one
+          // at a time.
+          function nextSessionTest(i) {
+            // Check if it's time to break the loop.
+            if (i == sessionOptions.length) {
+              if (sessionOptions.length == 0) {
+                reject('No option for the session. Test Did not run.');
+              } else {
+                resolve();
               }
+              return;
+            }
 
-              nextSessionTest(0);
-            }));
+            // Perform the session request in a user gesture.
+            runWithUserGesture(() => {
+              let nextOptions = sessionOptions[i];
+              let testSession = null;
+              navigator.xr.requestSession(nextOptions)
+                  .then((session) => {
+                    testSession = session;
+                    return func(session, t, fakeDeviceController);
+                  })
+                  .then(() => {
+                    // End the session. Silence any errors generated if the
+                    // session was already ended.
+                    // TODO(bajones): Throwing an error when a session is
+                    // already ended is not defined by the spec. This
+                    // should be defined or removed.
+                    testSession.end().catch(() => {});
+                    fakeDeviceController.setXRPresentationFrameData(null);
+                  })
+                  .then(() => nextSessionTest(++i))
+                  .catch((err) => {
+                    let optionsString = '{';
+                    let firstOption = true;
+                    for (let option in nextOptions) {
+                      if (!firstOption) {
+                        optionsString += ',';
+                      }
+                      optionsString += ` ${option}: ${nextOptions[option]}`;
+                      firstOption = false;
+                    }
+                    optionsString += ' }';
+                    reject(
+                        `Test failed while running with the following options:
+                        ${optionsString} ${err}`);
+                  });
+            });
+          }
+
+          nextSessionTest(0);
+        }));
   }, name, properties);
 }
 
diff --git a/third_party/blink/web_tests/xr/xrInputSource_add_remove.html b/third_party/blink/web_tests/xr/xrInputSource_add_remove.html
index 40bbc7f..26416e5 100644
--- a/third_party/blink/web_tests/xr/xrInputSource_add_remove.html
+++ b/third_party/blink/web_tests/xr/xrInputSource_add_remove.html
@@ -16,7 +16,7 @@
 
 let fakeDeviceInitParams = { supportsImmersive:true };
 
-let requestSessionOptions = [{ immersive: true }];
+let requestSessionOptions = [{ mode: 'immersive-vr' }];
 
 let testFunction = (session, t, fakeDeviceController) => new Promise((resolve) => {
     // Session must have a baseLayer or frame requests will be ignored.
diff --git a/third_party/blink/web_tests/xr/xrRigidTransform_constructor.html b/third_party/blink/web_tests/xr/xrRigidTransform_constructor.html
index 8c3182b..66de40c 100644
--- a/third_party/blink/web_tests/xr/xrRigidTransform_constructor.html
+++ b/third_party/blink/web_tests/xr/xrRigidTransform_constructor.html
@@ -12,7 +12,7 @@
 
 let testName = "XRRigidTransform constructor works";
 let fakeDeviceInitParams = { supportsImmersive: true };
-let requestSessionOptions =  [{ immersive: true }];
+let requestSessionOptions =  [{ mode: 'immersive-vr' }];
 
 let testFunction =
   (session, t, fakeDeviceController) => new Promise((resolve, reject) => {
diff --git a/third_party/blink/web_tests/xr/xrSession_environmentBlendMode.html b/third_party/blink/web_tests/xr/xrSession_environmentBlendMode.html
index 6f3029d..71ffb9ba 100644
--- a/third_party/blink/web_tests/xr/xrSession_environmentBlendMode.html
+++ b/third_party/blink/web_tests/xr/xrSession_environmentBlendMode.html
@@ -16,7 +16,7 @@
 
 let requestSessionOptions = [
   { outputContext: getOutputContext() },
-  { immersive: true },
+  { mode: 'immersive-vr' },
 ];
 
 let testFunction = function(session, t) {
diff --git a/third_party/blink/web_tests/xr/xrSession_requestAnimationFrame_timestamp.html b/third_party/blink/web_tests/xr/xrSession_requestAnimationFrame_timestamp.html
index 186cc02..cee7890 100644
--- a/third_party/blink/web_tests/xr/xrSession_requestAnimationFrame_timestamp.html
+++ b/third_party/blink/web_tests/xr/xrSession_requestAnimationFrame_timestamp.html
@@ -18,7 +18,7 @@
 
 let requestSessionOptions = [
   { outputContext: getOutputContext() },
-  { immersive: true },
+  { mode: 'immersive-vr' },
 ];
 
 let testFunction = function(session, t, fakeDeviceController) {
diff --git a/third_party/blink/web_tests/xr/xrStationaryReferenceSpace_floorlevel_updates.html b/third_party/blink/web_tests/xr/xrStationaryReferenceSpace_floorlevel_updates.html
index 77dc405..fb73408 100644
--- a/third_party/blink/web_tests/xr/xrStationaryReferenceSpace_floorlevel_updates.html
+++ b/third_party/blink/web_tests/xr/xrStationaryReferenceSpace_floorlevel_updates.html
@@ -17,7 +17,7 @@
 
 let requestSessionOptions = [
   { outputContext: getOutputContext() },
-  { immersive: true },
+  { mode: 'immersive-vr' },
 ];
 
 let testFunction = function(session, t, fakeDeviceController) {
diff --git a/third_party/blink/web_tests/xr/xrView_match.html b/third_party/blink/web_tests/xr/xrView_match.html
index 8800af8..0bba0c5 100644
--- a/third_party/blink/web_tests/xr/xrView_match.html
+++ b/third_party/blink/web_tests/xr/xrView_match.html
@@ -14,7 +14,7 @@
 
 let fakeDeviceInitParams = { supportsImmersive:true };
 
-let requestSessionOptions = [{ immersive: true }];
+let requestSessionOptions = [{ mode: 'immersive-vr' }];
 
 let testFunction = function(session, t, fakeDeviceController) {
   // Session must have a baseLayer or frame requests will be ignored.
diff --git a/third_party/blink/web_tests/xr/xrView_oneframeupdate.html b/third_party/blink/web_tests/xr/xrView_oneframeupdate.html
index 8a0177f44..2155eba57 100644
--- a/third_party/blink/web_tests/xr/xrView_oneframeupdate.html
+++ b/third_party/blink/web_tests/xr/xrView_oneframeupdate.html
@@ -15,7 +15,7 @@
 
 let fakeDeviceInitParams = { supportsImmersive:true };
 
-let requestSessionOptions = [{ immersive: true }];
+let requestSessionOptions = [{ mode: 'immersive-vr' }];
 
 let testFunction = function(session, t, fakeDeviceController) {
   // Session must have a baseLayer or frame requests will be ignored.
diff --git a/third_party/blink/web_tests/xr/xrViewport_valid.html b/third_party/blink/web_tests/xr/xrViewport_valid.html
index 03b7e77..391d29d 100644
--- a/third_party/blink/web_tests/xr/xrViewport_valid.html
+++ b/third_party/blink/web_tests/xr/xrViewport_valid.html
@@ -13,7 +13,7 @@
 
 let fakeDeviceInitParams = { supportsImmersive:true };
 
-let requestSessionOptions = [{ immersive: true }];
+let requestSessionOptions = [{ mode: 'immersive-vr' }];
 
 let testFunction = function(session, t, fakeDeviceController) {
   // Session must have a baseLayer or frame requests will be ignored.
diff --git a/third_party/blink/web_tests/xr/xrWebGLLayer_constructor.html b/third_party/blink/web_tests/xr/xrWebGLLayer_constructor.html
index 3defcbd..5a978b5 100644
--- a/third_party/blink/web_tests/xr/xrWebGLLayer_constructor.html
+++ b/third_party/blink/web_tests/xr/xrWebGLLayer_constructor.html
@@ -14,7 +14,7 @@
 
 let fakeDeviceInitParams = { supportsImmersive: true };
 
-let requestSessionOptions =  [{ immersive: true }];
+let requestSessionOptions =  [{ mode: 'immersive-vr' }];
 
 let testFunction =
   (session, t, fakeDeviceController) => new Promise((resolve, reject) => {
diff --git a/third_party/blink/web_tests/xr/xrWebGLLayer_dirty_framebuffer.html b/third_party/blink/web_tests/xr/xrWebGLLayer_dirty_framebuffer.html
index 292d30d..96ebeac1 100644
--- a/third_party/blink/web_tests/xr/xrWebGLLayer_dirty_framebuffer.html
+++ b/third_party/blink/web_tests/xr/xrWebGLLayer_dirty_framebuffer.html
@@ -16,7 +16,7 @@
 
 let fakeDeviceInitParams = { supportsImmersive: true };
 
-let requestSessionOptions =  [{ immersive: true }];
+let requestSessionOptions =  [{ mode: 'immersive-vr' }];
 
 let testFunction =
   (session, t, fakeDeviceController) => new Promise((resolve, reject) => {
diff --git a/third_party/blink/web_tests/xr/xrWebGLLayer_framebuffer_draw.html b/third_party/blink/web_tests/xr/xrWebGLLayer_framebuffer_draw.html
index d1b85e8..e0463a0 100644
--- a/third_party/blink/web_tests/xr/xrWebGLLayer_framebuffer_draw.html
+++ b/third_party/blink/web_tests/xr/xrWebGLLayer_framebuffer_draw.html
@@ -15,7 +15,7 @@
 
 let fakeDeviceInitParams = { supportsImmersive: true };
 
-let requestSessionOptions =  [{ immersive: true }];
+let requestSessionOptions =  [{ mode: 'immersive-vr' }];
 
 // Very simple program setup with no error checking.
 function setupProgram(gl, vertexSrc, fragmentSrc) {
diff --git a/third_party/blink/web_tests/xr/xrWebGLLayer_framebuffer_scale.html b/third_party/blink/web_tests/xr/xrWebGLLayer_framebuffer_scale.html
index 43ff8f58..b2e9ae39 100644
--- a/third_party/blink/web_tests/xr/xrWebGLLayer_framebuffer_scale.html
+++ b/third_party/blink/web_tests/xr/xrWebGLLayer_framebuffer_scale.html
@@ -14,7 +14,7 @@
 
 let fakeDeviceInitParams = { supportsImmersive: true };
 
-let requestSessionOptions =  [{ immersive: true }];
+let requestSessionOptions =  [{ mode: 'immersive-vr' }];
 
 let testFunction =
   (session, t, fakeDeviceController) => new Promise((resolve, reject) => {
diff --git a/third_party/blink/web_tests/xr/xrWebGLLayer_incompatible_device.html b/third_party/blink/web_tests/xr/xrWebGLLayer_incompatible_device.html
index ea2d3d95..5906dae 100644
--- a/third_party/blink/web_tests/xr/xrWebGLLayer_incompatible_device.html
+++ b/third_party/blink/web_tests/xr/xrWebGLLayer_incompatible_device.html
@@ -14,10 +14,9 @@
 promise_test( (t) => {
   webglCanvasSetup();
   return XRTest.simulateDeviceConnection({ supportsImmersive:true })
-    .then( (controller) => { return navigator.xr.requestDevice() })
-    .then( (device) => new Promise((resolve) => {
+    .then( (controller) => new Promise((resolve) => {
       runWithUserGesture( () => {
-        resolve(device.requestSession({ immersive: true })
+        resolve(navigator.xr.requestSession({ mode: 'immersive-vr' })
           .then( (session) => new Promise((resolve) => {
             try {
               let webglLayer = new XRWebGLLayer(session, gl);
diff --git a/third_party/blink/web_tests/xr/xrWebGLLayer_opaque_framebuffer.html b/third_party/blink/web_tests/xr/xrWebGLLayer_opaque_framebuffer.html
index 4237a543..5158e93 100644
--- a/third_party/blink/web_tests/xr/xrWebGLLayer_opaque_framebuffer.html
+++ b/third_party/blink/web_tests/xr/xrWebGLLayer_opaque_framebuffer.html
@@ -14,7 +14,7 @@
 let fakeDeviceInitParams = { supportsImmersive: true };
 
 let requestSessionOptions = [
-  { immersive: true },
+  { mode: 'immersive-vr' },
   { outputContext: getOutputContext() }
 ];
 
diff --git a/third_party/blink/web_tests/xr/xrWebGLLayer_viewport_scale.html b/third_party/blink/web_tests/xr/xrWebGLLayer_viewport_scale.html
index 14d716f0..ad4406a 100644
--- a/third_party/blink/web_tests/xr/xrWebGLLayer_viewport_scale.html
+++ b/third_party/blink/web_tests/xr/xrWebGLLayer_viewport_scale.html
@@ -15,7 +15,7 @@
 
 let fakeDeviceInitParams = { supportsImmersive: true };
 
-let requestSessionOptions =  [{ immersive: true }];
+let requestSessionOptions =  [{ mode: 'immersive-vr' }];
 
 let testFunction = function(session, t, fakeDeviceController) {
   // Session must have a baseLayer or else frame requests will be ignored.
diff --git a/third_party/feed/BUILD.gn b/third_party/feed/BUILD.gn
index 45dc96b..bb718d7 100644
--- a/third_party/feed/BUILD.gn
+++ b/third_party/feed/BUILD.gn
@@ -42,10 +42,8 @@
 }
 
 android_resources("sharedstream_contextmenumanager_resources") {
-  resource_dirs = [ "src/src/main/java/com/google/android/libraries/feed/sharedstream/contextmenumanager/res" ]
-  deps = [
-    ":sharedstream_resources",
-  ]
+  resource_dirs =
+      [ "src/src/main/java/com/google/android/libraries/feed/sharedstream/res" ]
   custom_package =
       "com.google.android.libraries.feed.sharedstream.contextmenumanager"
 }
diff --git a/third_party/feed/README.chromium b/third_party/feed/README.chromium
index 42bafb9..af78a9aa 100644
--- a/third_party/feed/README.chromium
+++ b/third_party/feed/README.chromium
@@ -2,7 +2,7 @@
 Short name: feed
 URL: https://chromium.googlesource.com/feed
 Version: 0
-Revision: d6031f504fcff6f34c4847f110a695fa54e90a9b
+Revision: ed7c2ae304814efdb0e85cfbfe5205897b0d8d03
 License: Apache 2.0
 License File: LICENSE
 Security Critical: yes
diff --git a/third_party/feed/java_sources.gni b/third_party/feed/java_sources.gni
index 660b204..ce77d21 100644
--- a/third_party/feed/java_sources.gni
+++ b/third_party/feed/java_sources.gni
@@ -182,6 +182,7 @@
   "src/src/main/java/com/google/android/libraries/feed/host/storage/JournalStorageDirect.java",
   "src/src/main/java/com/google/android/libraries/feed/host/stream/CardConfiguration.java",
   "src/src/main/java/com/google/android/libraries/feed/host/stream/SnackbarApi.java",
+  "src/src/main/java/com/google/android/libraries/feed/host/stream/SnackbarCallbackApi.java",
   "src/src/main/java/com/google/android/libraries/feed/host/stream/StreamConfiguration.java",
   "src/src/main/java/com/google/android/libraries/feed/hostimpl/logging/LoggingApiImpl.java",
   "src/src/main/java/com/google/android/libraries/feed/hostimpl/network/NetworkClientWrapper.java",
diff --git a/third_party/sqlite/amalgamation/rename_exports.h b/third_party/sqlite/amalgamation/rename_exports.h
index 22e7fb5..828955ea 100644
--- a/third_party/sqlite/amalgamation/rename_exports.h
+++ b/third_party/sqlite/amalgamation/rename_exports.h
@@ -8,389 +8,327 @@
 #define THIRD_PARTY_SQLITE_AMALGAMATION_RENAME_EXPORTS_H_
 
 #define sqlite3_activate_cerod chrome_sqlite3_activate_cerod  // Lines 5572-5574
-#define sqlite3_activate_see chrome_sqlite3_activate_see      // Lines 5562-5564
+#define sqlite3_activate_see chrome_sqlite3_activate_see  // Lines 5562-5564
 #define sqlite3_aggregate_context chrome_sqlite3_aggregate_context  // Line 5109
-#define sqlite3_aggregate_count chrome_sqlite3_aggregate_count      // Line 4892
-#define sqlite3_auto_extension chrome_sqlite3_auto_extension        // Line 6238
-#define sqlite3_backup_finish chrome_sqlite3_backup_finish          // Line 8233
+#define sqlite3_aggregate_count chrome_sqlite3_aggregate_count  // Line 4892
+#define sqlite3_auto_extension chrome_sqlite3_auto_extension  // Line 6238
+#define sqlite3_backup_finish chrome_sqlite3_backup_finish  // Line 8233
 #define sqlite3_backup_init chrome_sqlite3_backup_init  // Lines 8226-8231
 #define sqlite3_backup_pagecount chrome_sqlite3_backup_pagecount  // Line 8235
 #define sqlite3_backup_remaining chrome_sqlite3_backup_remaining  // Line 8234
-#define sqlite3_backup_step chrome_sqlite3_backup_step            // Line 8232
-#define sqlite3_bind_blob chrome_sqlite3_bind_blob                // Line 4067
+#define sqlite3_backup_step chrome_sqlite3_backup_step  // Line 8232
+#define sqlite3_bind_blob chrome_sqlite3_bind_blob  // Line 4067
 #define sqlite3_bind_blob64 chrome_sqlite3_bind_blob64  // Lines 4068-4069
 #define sqlite3_bind_double chrome_sqlite3_bind_double  // Line 4070
-#define sqlite3_bind_int chrome_sqlite3_bind_int        // Line 4071
-#define sqlite3_bind_int64 chrome_sqlite3_bind_int64    // Line 4072
-#define sqlite3_bind_null chrome_sqlite3_bind_null      // Line 4073
-#define sqlite3_bind_parameter_count \
-  chrome_sqlite3_bind_parameter_count  // Line 4102
-#define sqlite3_bind_parameter_index \
-  chrome_sqlite3_bind_parameter_index  // Line 4148
-#define sqlite3_bind_parameter_name \
-  chrome_sqlite3_bind_parameter_name                        // Line 4130
-#define sqlite3_bind_pointer chrome_sqlite3_bind_pointer    // Line 4079
-#define sqlite3_bind_text chrome_sqlite3_bind_text          // Line 4074
-#define sqlite3_bind_text16 chrome_sqlite3_bind_text16      // Line 4075
-#define sqlite3_bind_text64 chrome_sqlite3_bind_text64      // Lines 4076-4077
-#define sqlite3_bind_value chrome_sqlite3_bind_value        // Line 4078
+#define sqlite3_bind_int chrome_sqlite3_bind_int  // Line 4071
+#define sqlite3_bind_int64 chrome_sqlite3_bind_int64  // Line 4072
+#define sqlite3_bind_null chrome_sqlite3_bind_null  // Line 4073
+#define sqlite3_bind_parameter_count chrome_sqlite3_bind_parameter_count  // Line 4102
+#define sqlite3_bind_parameter_index chrome_sqlite3_bind_parameter_index  // Line 4148
+#define sqlite3_bind_parameter_name chrome_sqlite3_bind_parameter_name  // Line 4130
+#define sqlite3_bind_pointer chrome_sqlite3_bind_pointer  // Line 4079
+#define sqlite3_bind_text chrome_sqlite3_bind_text  // Line 4074
+#define sqlite3_bind_text16 chrome_sqlite3_bind_text16  // Line 4075
+#define sqlite3_bind_text64 chrome_sqlite3_bind_text64  // Lines 4076-4077
+#define sqlite3_bind_value chrome_sqlite3_bind_value  // Line 4078
 #define sqlite3_bind_zeroblob chrome_sqlite3_bind_zeroblob  // Line 4080
 #define sqlite3_bind_zeroblob64 chrome_sqlite3_bind_zeroblob64  // Line 4081
-#define sqlite3_blob_bytes chrome_sqlite3_blob_bytes            // Line 6787
-#define sqlite3_blob_close chrome_sqlite3_blob_close            // Line 6771
-#define sqlite3_blob_open chrome_sqlite3_blob_open        // Lines 6715-6723
-#define sqlite3_blob_read chrome_sqlite3_blob_read        // Line 6816
-#define sqlite3_blob_reopen chrome_sqlite3_blob_reopen    // Line 6748
-#define sqlite3_blob_write chrome_sqlite3_blob_write      // Line 6858
+#define sqlite3_blob_bytes chrome_sqlite3_blob_bytes  // Line 6787
+#define sqlite3_blob_close chrome_sqlite3_blob_close  // Line 6771
+#define sqlite3_blob_open chrome_sqlite3_blob_open  // Lines 6715-6723
+#define sqlite3_blob_read chrome_sqlite3_blob_read  // Line 6816
+#define sqlite3_blob_reopen chrome_sqlite3_blob_reopen  // Line 6748
+#define sqlite3_blob_write chrome_sqlite3_blob_write  // Line 6858
 #define sqlite3_busy_handler chrome_sqlite3_busy_handler  // Line 2504
 #define sqlite3_busy_timeout chrome_sqlite3_busy_timeout  // Line 2527
-#define sqlite3_cancel_auto_extension \
-  chrome_sqlite3_cancel_auto_extension                        // Line 6250
-#define sqlite3_changes chrome_sqlite3_changes                // Line 2333
+#define sqlite3_cancel_auto_extension chrome_sqlite3_cancel_auto_extension  // Line 6250
+#define sqlite3_changes chrome_sqlite3_changes  // Line 2333
 #define sqlite3_clear_bindings chrome_sqlite3_clear_bindings  // Line 4158
-#define sqlite3_close chrome_sqlite3_close                    // Line 331
-#define sqlite3_close_v2 chrome_sqlite3_close_v2              // Line 332
-#define sqlite3_collation_needed \
-  chrome_sqlite3_collation_needed  // Lines 5511-5515
-#define sqlite3_collation_needed16 \
-  chrome_sqlite3_collation_needed16                           // Lines 5516-5520
-#define sqlite3_column_blob chrome_sqlite3_column_blob        // Line 4638
-#define sqlite3_column_bytes chrome_sqlite3_column_bytes      // Line 4645
+#define sqlite3_close chrome_sqlite3_close  // Line 331
+#define sqlite3_close_v2 chrome_sqlite3_close_v2  // Line 332
+#define sqlite3_collation_needed chrome_sqlite3_collation_needed  // Lines 5511-5515
+#define sqlite3_collation_needed16 chrome_sqlite3_collation_needed16  // Lines 5516-5520
+#define sqlite3_column_blob chrome_sqlite3_column_blob  // Line 4638
+#define sqlite3_column_bytes chrome_sqlite3_column_bytes  // Line 4645
 #define sqlite3_column_bytes16 chrome_sqlite3_column_bytes16  // Line 4646
-#define sqlite3_column_count chrome_sqlite3_column_count      // Line 4174
-#define sqlite3_column_database_name \
-  chrome_sqlite3_column_database_name  // Line 4252
-#define sqlite3_column_database_name16 \
-  chrome_sqlite3_column_database_name16                             // Line 4253
-#define sqlite3_column_decltype chrome_sqlite3_column_decltype      // Line 4289
+#define sqlite3_column_count chrome_sqlite3_column_count  // Line 4174
+#define sqlite3_column_database_name chrome_sqlite3_column_database_name  // Line 4252
+#define sqlite3_column_database_name16 chrome_sqlite3_column_database_name16  // Line 4253
+#define sqlite3_column_decltype chrome_sqlite3_column_decltype  // Line 4289
 #define sqlite3_column_decltype16 chrome_sqlite3_column_decltype16  // Line 4290
-#define sqlite3_column_double chrome_sqlite3_column_double          // Line 4639
-#define sqlite3_column_int chrome_sqlite3_column_int                // Line 4640
-#define sqlite3_column_int64 chrome_sqlite3_column_int64            // Line 4641
-#define sqlite3_column_name chrome_sqlite3_column_name              // Line 4203
-#define sqlite3_column_name16 chrome_sqlite3_column_name16          // Line 4204
-#define sqlite3_column_origin_name \
-  chrome_sqlite3_column_origin_name  // Line 4256
-#define sqlite3_column_origin_name16 \
-  chrome_sqlite3_column_origin_name16                               // Line 4257
+#define sqlite3_column_double chrome_sqlite3_column_double  // Line 4639
+#define sqlite3_column_int chrome_sqlite3_column_int  // Line 4640
+#define sqlite3_column_int64 chrome_sqlite3_column_int64  // Line 4641
+#define sqlite3_column_name chrome_sqlite3_column_name  // Line 4203
+#define sqlite3_column_name16 chrome_sqlite3_column_name16  // Line 4204
+#define sqlite3_column_origin_name chrome_sqlite3_column_origin_name  // Line 4256
+#define sqlite3_column_origin_name16 chrome_sqlite3_column_origin_name16  // Line 4257
 #define sqlite3_column_table_name chrome_sqlite3_column_table_name  // Line 4254
-#define sqlite3_column_table_name16 \
-  chrome_sqlite3_column_table_name16                                // Line 4255
-#define sqlite3_column_text chrome_sqlite3_column_text              // Line 4642
-#define sqlite3_column_text16 chrome_sqlite3_column_text16          // Line 4643
-#define sqlite3_column_type chrome_sqlite3_column_type              // Line 4647
-#define sqlite3_column_value chrome_sqlite3_column_value            // Line 4644
-#define sqlite3_commit_hook chrome_sqlite3_commit_hook              // Line 5853
+#define sqlite3_column_table_name16 chrome_sqlite3_column_table_name16  // Line 4255
+#define sqlite3_column_text chrome_sqlite3_column_text  // Line 4642
+#define sqlite3_column_text16 chrome_sqlite3_column_text16  // Line 4643
+#define sqlite3_column_type chrome_sqlite3_column_type  // Line 4647
+#define sqlite3_column_value chrome_sqlite3_column_value  // Line 4644
+#define sqlite3_commit_hook chrome_sqlite3_commit_hook  // Line 5853
 #define sqlite3_compileoption_get chrome_sqlite3_compileoption_get  // Line 191
-#define sqlite3_compileoption_used \
-  chrome_sqlite3_compileoption_used                                 // Line 190
-#define sqlite3_complete chrome_sqlite3_complete                    // Line 2442
-#define sqlite3_complete16 chrome_sqlite3_complete16                // Line 2443
-#define sqlite3_config chrome_sqlite3_config                        // Line 1540
+#define sqlite3_compileoption_used chrome_sqlite3_compileoption_used  // Line 190
+#define sqlite3_complete chrome_sqlite3_complete  // Line 2442
+#define sqlite3_complete16 chrome_sqlite3_complete16  // Line 2443
+#define sqlite3_config chrome_sqlite3_config  // Line 1540
 #define sqlite3_context_db_handle chrome_sqlite3_context_db_handle  // Line 5136
-#define sqlite3_create_collation \
-  chrome_sqlite3_create_collation  // Lines 5461-5467
-#define sqlite3_create_collation16 \
-  chrome_sqlite3_create_collation16  // Lines 5476-5482
-#define sqlite3_create_collation_v2 \
-  chrome_sqlite3_create_collation_v2  // Lines 5468-5475
-#define sqlite3_create_function \
-  chrome_sqlite3_create_function  // Lines 4814-4823
-#define sqlite3_create_function16 \
-  chrome_sqlite3_create_function16  // Lines 4824-4833
-#define sqlite3_create_function_v2 \
-  chrome_sqlite3_create_function_v2                         // Lines 4834-4844
+#define sqlite3_create_collation chrome_sqlite3_create_collation  // Lines 5461-5467
+#define sqlite3_create_collation16 chrome_sqlite3_create_collation16  // Lines 5476-5482
+#define sqlite3_create_collation_v2 chrome_sqlite3_create_collation_v2  // Lines 5468-5475
+#define sqlite3_create_function chrome_sqlite3_create_function  // Lines 4814-4823
+#define sqlite3_create_function16 chrome_sqlite3_create_function16  // Lines 4824-4833
+#define sqlite3_create_function_v2 chrome_sqlite3_create_function_v2  // Lines 4834-4844
 #define sqlite3_create_module chrome_sqlite3_create_module  // Lines 6518-6523
-#define sqlite3_create_module_v2 \
-  chrome_sqlite3_create_module_v2  // Lines 6524-6530
-#define sqlite3_create_window_function \
-  chrome_sqlite3_create_window_function                       // Lines 4845-4856
-#define sqlite3_data_count chrome_sqlite3_data_count          // Line 4395
+#define sqlite3_create_module_v2 chrome_sqlite3_create_module_v2  // Lines 6524-6530
+#define sqlite3_create_window_function chrome_sqlite3_create_window_function  // Lines 4845-4856
+#define sqlite3_data_count chrome_sqlite3_data_count  // Line 4395
 #define sqlite3_data_directory chrome_sqlite3_data_directory  // Line 5689
-#define sqlite3_db_cacheflush chrome_sqlite3_db_cacheflush    // Line 8918
-#define sqlite3_db_config chrome_sqlite3_db_config            // Line 1559
-#define sqlite3_db_filename chrome_sqlite3_db_filename        // Line 5778
-#define sqlite3_db_handle chrome_sqlite3_db_handle            // Line 5761
-#define sqlite3_db_mutex chrome_sqlite3_db_mutex              // Line 7162
-#define sqlite3_db_readonly chrome_sqlite3_db_readonly        // Line 5788
+#define sqlite3_db_cacheflush chrome_sqlite3_db_cacheflush  // Line 8918
+#define sqlite3_db_config chrome_sqlite3_db_config  // Line 1559
+#define sqlite3_db_filename chrome_sqlite3_db_filename  // Line 5778
+#define sqlite3_db_handle chrome_sqlite3_db_handle  // Line 5761
+#define sqlite3_db_mutex chrome_sqlite3_db_mutex  // Line 7162
+#define sqlite3_db_readonly chrome_sqlite3_db_readonly  // Line 5788
 #define sqlite3_db_release_memory chrome_sqlite3_db_release_memory  // Line 5976
-#define sqlite3_db_status chrome_sqlite3_db_status                  // Line 7583
-#define sqlite3_declare_vtab chrome_sqlite3_declare_vtab            // Line 6587
+#define sqlite3_db_status chrome_sqlite3_db_status  // Line 7583
+#define sqlite3_declare_vtab chrome_sqlite3_declare_vtab  // Line 6587
 #define sqlite3_deserialize chrome_sqlite3_deserialize  // Lines 9312-9319
-#define sqlite3_enable_load_extension \
-  chrome_sqlite3_enable_load_extension  // Line 6200
-#define sqlite3_enable_shared_cache \
-  chrome_sqlite3_enable_shared_cache                      // Line 5946
-#define sqlite3_errcode chrome_sqlite3_errcode            // Line 3468
-#define sqlite3_errmsg chrome_sqlite3_errmsg              // Line 3470
-#define sqlite3_errmsg16 chrome_sqlite3_errmsg16          // Line 3471
-#define sqlite3_errstr chrome_sqlite3_errstr              // Line 3472
-#define sqlite3_exec chrome_sqlite3_exec                  // Lines 403-409
+#define sqlite3_enable_load_extension chrome_sqlite3_enable_load_extension  // Line 6200
+#define sqlite3_enable_shared_cache chrome_sqlite3_enable_shared_cache  // Line 5946
+#define sqlite3_errcode chrome_sqlite3_errcode  // Line 3468
+#define sqlite3_errmsg chrome_sqlite3_errmsg  // Line 3470
+#define sqlite3_errmsg16 chrome_sqlite3_errmsg16  // Line 3471
+#define sqlite3_errstr chrome_sqlite3_errstr  // Line 3472
+#define sqlite3_exec chrome_sqlite3_exec  // Lines 403-409
 #define sqlite3_expanded_sql chrome_sqlite3_expanded_sql  // Line 3835
-#define sqlite3_expired chrome_sqlite3_expired            // Line 4893
+#define sqlite3_expired chrome_sqlite3_expired  // Line 4893
 #define sqlite3_extended_errcode chrome_sqlite3_extended_errcode  // Line 3469
-#define sqlite3_extended_result_codes \
-  chrome_sqlite3_extended_result_codes                        // Line 2203
-#define sqlite3_file_control chrome_sqlite3_file_control      // Line 7205
-#define sqlite3_finalize chrome_sqlite3_finalize              // Line 4675
-#define sqlite3_free chrome_sqlite3_free                      // Line 2749
-#define sqlite3_free_table chrome_sqlite3_free_table          // Line 2610
+#define sqlite3_extended_result_codes chrome_sqlite3_extended_result_codes  // Line 2203
+#define sqlite3_file_control chrome_sqlite3_file_control  // Line 7205
+#define sqlite3_finalize chrome_sqlite3_finalize  // Line 4675
+#define sqlite3_free chrome_sqlite3_free  // Line 2749
+#define sqlite3_free_table chrome_sqlite3_free_table  // Line 2610
 #define sqlite3_get_autocommit chrome_sqlite3_get_autocommit  // Line 5748
-#define sqlite3_get_auxdata chrome_sqlite3_get_auxdata        // Line 5195
-#define sqlite3_get_table chrome_sqlite3_get_table            // Lines 2602-2609
+#define sqlite3_get_auxdata chrome_sqlite3_get_auxdata  // Line 5195
+#define sqlite3_get_table chrome_sqlite3_get_table  // Lines 2602-2609
 #define sqlite3_global_recover chrome_sqlite3_global_recover  // Line 4895
-#define sqlite3_initialize chrome_sqlite3_initialize          // Line 1504
-#define sqlite3_interrupt chrome_sqlite3_interrupt            // Line 2407
-#define sqlite3_key chrome_sqlite3_key                        // Lines 5530-5533
-#define sqlite3_key_v2 chrome_sqlite3_key_v2                  // Lines 5534-5538
-#define sqlite3_keyword_check chrome_sqlite3_keyword_check    // Line 7313
-#define sqlite3_keyword_count chrome_sqlite3_keyword_count    // Line 7311
-#define sqlite3_keyword_name chrome_sqlite3_keyword_name      // Line 7312
+#define sqlite3_initialize chrome_sqlite3_initialize  // Line 1504
+#define sqlite3_interrupt chrome_sqlite3_interrupt  // Line 2407
+#define sqlite3_key chrome_sqlite3_key  // Lines 5530-5533
+#define sqlite3_key_v2 chrome_sqlite3_key_v2  // Lines 5534-5538
+#define sqlite3_keyword_check chrome_sqlite3_keyword_check  // Line 7313
+#define sqlite3_keyword_count chrome_sqlite3_keyword_count  // Line 7311
+#define sqlite3_keyword_name chrome_sqlite3_keyword_name  // Line 7312
 #define sqlite3_last_insert_rowid chrome_sqlite3_last_insert_rowid  // Line 2265
-#define sqlite3_libversion chrome_sqlite3_libversion                // Line 163
+#define sqlite3_libversion chrome_sqlite3_libversion  // Line 163
 #define sqlite3_libversion_number chrome_sqlite3_libversion_number  // Line 165
-#define sqlite3_limit chrome_sqlite3_limit                          // Line 3540
+#define sqlite3_limit chrome_sqlite3_limit  // Line 3540
 #define sqlite3_load_extension chrome_sqlite3_load_extension  // Lines 6168-6173
-#define sqlite3_log chrome_sqlite3_log                        // Line 8454
-#define sqlite3_malloc chrome_sqlite3_malloc                  // Line 2745
-#define sqlite3_malloc64 chrome_sqlite3_malloc64              // Line 2746
-#define sqlite3_memory_alarm chrome_sqlite3_memory_alarm      // Lines 4897-4898
+#define sqlite3_log chrome_sqlite3_log  // Line 8454
+#define sqlite3_malloc chrome_sqlite3_malloc  // Line 2745
+#define sqlite3_malloc64 chrome_sqlite3_malloc64  // Line 2746
+#define sqlite3_memory_alarm chrome_sqlite3_memory_alarm  // Lines 4897-4898
 #define sqlite3_memory_highwater chrome_sqlite3_memory_highwater  // Line 2776
-#define sqlite3_memory_used chrome_sqlite3_memory_used            // Line 2775
-#define sqlite3_mprintf chrome_sqlite3_mprintf                    // Line 2652
-#define sqlite3_msize chrome_sqlite3_msize                        // Line 2750
-#define sqlite3_mutex_alloc chrome_sqlite3_mutex_alloc            // Line 7007
-#define sqlite3_mutex_enter chrome_sqlite3_mutex_enter            // Line 7009
-#define sqlite3_mutex_free chrome_sqlite3_mutex_free              // Line 7008
-#define sqlite3_mutex_held chrome_sqlite3_mutex_held              // Line 7121
-#define sqlite3_mutex_leave chrome_sqlite3_mutex_leave            // Line 7011
-#define sqlite3_mutex_notheld chrome_sqlite3_mutex_notheld        // Line 7122
-#define sqlite3_mutex_try chrome_sqlite3_mutex_try                // Line 7010
-#define sqlite3_next_stmt chrome_sqlite3_next_stmt                // Line 5804
-#define sqlite3_normalized_sql chrome_sqlite3_normalized_sql      // Line 3836
-#define sqlite3_open chrome_sqlite3_open        // Lines 3357-3360
-#define sqlite3_open16 chrome_sqlite3_open16    // Lines 3361-3364
+#define sqlite3_memory_used chrome_sqlite3_memory_used  // Line 2775
+#define sqlite3_mprintf chrome_sqlite3_mprintf  // Line 2652
+#define sqlite3_msize chrome_sqlite3_msize  // Line 2750
+#define sqlite3_mutex_alloc chrome_sqlite3_mutex_alloc  // Line 7007
+#define sqlite3_mutex_enter chrome_sqlite3_mutex_enter  // Line 7009
+#define sqlite3_mutex_free chrome_sqlite3_mutex_free  // Line 7008
+#define sqlite3_mutex_held chrome_sqlite3_mutex_held  // Line 7121
+#define sqlite3_mutex_leave chrome_sqlite3_mutex_leave  // Line 7011
+#define sqlite3_mutex_notheld chrome_sqlite3_mutex_notheld  // Line 7122
+#define sqlite3_mutex_try chrome_sqlite3_mutex_try  // Line 7010
+#define sqlite3_next_stmt chrome_sqlite3_next_stmt  // Line 5804
+#define sqlite3_normalized_sql chrome_sqlite3_normalized_sql  // Line 3836
+#define sqlite3_open chrome_sqlite3_open  // Lines 3357-3360
+#define sqlite3_open16 chrome_sqlite3_open16  // Lines 3361-3364
 #define sqlite3_open_v2 chrome_sqlite3_open_v2  // Lines 3365-3370
-#define sqlite3_os_end chrome_sqlite3_os_end    // Line 1507
+#define sqlite3_os_end chrome_sqlite3_os_end  // Line 1507
 #define sqlite3_os_init chrome_sqlite3_os_init  // Line 1506
 #define sqlite3_overload_function chrome_sqlite3_overload_function  // Line 6606
-#define sqlite3_prepare chrome_sqlite3_prepare            // Lines 3751-3757
-#define sqlite3_prepare16 chrome_sqlite3_prepare16        // Lines 3773-3779
+#define sqlite3_prepare chrome_sqlite3_prepare  // Lines 3751-3757
+#define sqlite3_prepare16 chrome_sqlite3_prepare16  // Lines 3773-3779
 #define sqlite3_prepare16_v2 chrome_sqlite3_prepare16_v2  // Lines 3780-3786
 #define sqlite3_prepare16_v3 chrome_sqlite3_prepare16_v3  // Lines 3787-3794
-#define sqlite3_prepare_v2 chrome_sqlite3_prepare_v2      // Lines 3758-3764
-#define sqlite3_prepare_v3 chrome_sqlite3_prepare_v3      // Lines 3765-3772
+#define sqlite3_prepare_v2 chrome_sqlite3_prepare_v2  // Lines 3758-3764
+#define sqlite3_prepare_v3 chrome_sqlite3_prepare_v3  // Lines 3765-3772
 #define sqlite3_preupdate_count chrome_sqlite3_preupdate_count  // Line 9017
 #define sqlite3_preupdate_depth chrome_sqlite3_preupdate_depth  // Line 9018
 #define sqlite3_preupdate_hook chrome_sqlite3_preupdate_hook  // Lines 9003-9015
-#define sqlite3_preupdate_new chrome_sqlite3_preupdate_new    // Line 9019
-#define sqlite3_preupdate_old chrome_sqlite3_preupdate_old    // Line 9016
-#define sqlite3_profile chrome_sqlite3_profile                // Lines 3000-3001
+#define sqlite3_preupdate_new chrome_sqlite3_preupdate_new  // Line 9019
+#define sqlite3_preupdate_old chrome_sqlite3_preupdate_old  // Line 9016
+#define sqlite3_profile chrome_sqlite3_profile  // Lines 3000-3001
 #define sqlite3_progress_handler chrome_sqlite3_progress_handler  // Line 3128
-#define sqlite3_randomness chrome_sqlite3_randomness              // Line 2799
-#define sqlite3_realloc chrome_sqlite3_realloc                    // Line 2747
-#define sqlite3_realloc64 chrome_sqlite3_realloc64                // Line 2748
-#define sqlite3_rekey chrome_sqlite3_rekey                    // Lines 5548-5551
-#define sqlite3_rekey_v2 chrome_sqlite3_rekey_v2              // Lines 5552-5556
+#define sqlite3_randomness chrome_sqlite3_randomness  // Line 2799
+#define sqlite3_realloc chrome_sqlite3_realloc  // Line 2747
+#define sqlite3_realloc64 chrome_sqlite3_realloc64  // Line 2748
+#define sqlite3_rekey chrome_sqlite3_rekey  // Lines 5548-5551
+#define sqlite3_rekey_v2 chrome_sqlite3_rekey_v2  // Lines 5552-5556
 #define sqlite3_release_memory chrome_sqlite3_release_memory  // Line 5962
-#define sqlite3_reset chrome_sqlite3_reset                    // Line 4702
-#define sqlite3_reset_auto_extension \
-  chrome_sqlite3_reset_auto_extension                         // Line 6258
-#define sqlite3_result_blob chrome_sqlite3_result_blob        // Line 5343
-#define sqlite3_result_blob64 chrome_sqlite3_result_blob64    // Lines 5344-5345
-#define sqlite3_result_double chrome_sqlite3_result_double    // Line 5346
-#define sqlite3_result_error chrome_sqlite3_result_error      // Line 5347
+#define sqlite3_reset chrome_sqlite3_reset  // Line 4702
+#define sqlite3_reset_auto_extension chrome_sqlite3_reset_auto_extension  // Line 6258
+#define sqlite3_result_blob chrome_sqlite3_result_blob  // Line 5343
+#define sqlite3_result_blob64 chrome_sqlite3_result_blob64  // Lines 5344-5345
+#define sqlite3_result_double chrome_sqlite3_result_double  // Line 5346
+#define sqlite3_result_error chrome_sqlite3_result_error  // Line 5347
 #define sqlite3_result_error16 chrome_sqlite3_result_error16  // Line 5348
 #define sqlite3_result_error_code chrome_sqlite3_result_error_code  // Line 5351
-#define sqlite3_result_error_nomem \
-  chrome_sqlite3_result_error_nomem  // Line 5350
-#define sqlite3_result_error_toobig \
-  chrome_sqlite3_result_error_toobig                            // Line 5349
-#define sqlite3_result_int chrome_sqlite3_result_int            // Line 5352
-#define sqlite3_result_int64 chrome_sqlite3_result_int64        // Line 5353
-#define sqlite3_result_null chrome_sqlite3_result_null          // Line 5354
-#define sqlite3_result_pointer chrome_sqlite3_result_pointer    // Line 5362
-#define sqlite3_result_subtype chrome_sqlite3_result_subtype    // Line 5379
-#define sqlite3_result_text chrome_sqlite3_result_text          // Line 5355
-#define sqlite3_result_text16 chrome_sqlite3_result_text16      // Line 5358
+#define sqlite3_result_error_nomem chrome_sqlite3_result_error_nomem  // Line 5350
+#define sqlite3_result_error_toobig chrome_sqlite3_result_error_toobig  // Line 5349
+#define sqlite3_result_int chrome_sqlite3_result_int  // Line 5352
+#define sqlite3_result_int64 chrome_sqlite3_result_int64  // Line 5353
+#define sqlite3_result_null chrome_sqlite3_result_null  // Line 5354
+#define sqlite3_result_pointer chrome_sqlite3_result_pointer  // Line 5362
+#define sqlite3_result_subtype chrome_sqlite3_result_subtype  // Line 5379
+#define sqlite3_result_text chrome_sqlite3_result_text  // Line 5355
+#define sqlite3_result_text16 chrome_sqlite3_result_text16  // Line 5358
 #define sqlite3_result_text16be chrome_sqlite3_result_text16be  // Line 5360
 #define sqlite3_result_text16le chrome_sqlite3_result_text16le  // Line 5359
 #define sqlite3_result_text64 chrome_sqlite3_result_text64  // Lines 5356-5357
-#define sqlite3_result_value chrome_sqlite3_result_value    // Line 5361
-#define sqlite3_result_zeroblob chrome_sqlite3_result_zeroblob      // Line 5363
+#define sqlite3_result_value chrome_sqlite3_result_value  // Line 5361
+#define sqlite3_result_zeroblob chrome_sqlite3_result_zeroblob  // Line 5363
 #define sqlite3_result_zeroblob64 chrome_sqlite3_result_zeroblob64  // Line 5364
-#define sqlite3_rollback_hook chrome_sqlite3_rollback_hook          // Line 5854
-#define sqlite3_rtree_geometry_callback \
-  chrome_sqlite3_rtree_geometry_callback  // Lines 9399-9404
-#define sqlite3_rtree_query_callback \
-  chrome_sqlite3_rtree_query_callback                         // Lines 9425-9431
-#define sqlite3_serialize chrome_sqlite3_serialize            // Lines 9260-9265
+#define sqlite3_rollback_hook chrome_sqlite3_rollback_hook  // Line 5854
+#define sqlite3_rtree_geometry_callback chrome_sqlite3_rtree_geometry_callback  // Lines 9399-9404
+#define sqlite3_rtree_query_callback chrome_sqlite3_rtree_query_callback  // Lines 9425-9431
+#define sqlite3_serialize chrome_sqlite3_serialize  // Lines 9260-9265
 #define sqlite3_set_authorizer chrome_sqlite3_set_authorizer  // Lines 2890-2894
-#define sqlite3_set_auxdata chrome_sqlite3_set_auxdata        // Line 5196
-#define sqlite3_set_last_insert_rowid \
-  chrome_sqlite3_set_last_insert_rowid                      // Line 2275
-#define sqlite3_shutdown chrome_sqlite3_shutdown            // Line 1505
-#define sqlite3_sleep chrome_sqlite3_sleep                  // Line 5594
-#define sqlite3_snapshot_cmp chrome_sqlite3_snapshot_cmp    // Lines 9194-9197
+#define sqlite3_set_auxdata chrome_sqlite3_set_auxdata  // Line 5196
+#define sqlite3_set_last_insert_rowid chrome_sqlite3_set_last_insert_rowid  // Line 2275
+#define sqlite3_shutdown chrome_sqlite3_shutdown  // Line 1505
+#define sqlite3_sleep chrome_sqlite3_sleep  // Line 5594
+#define sqlite3_snapshot_cmp chrome_sqlite3_snapshot_cmp  // Lines 9194-9197
 #define sqlite3_snapshot_free chrome_sqlite3_snapshot_free  // Line 9167
-#define sqlite3_snapshot_get chrome_sqlite3_snapshot_get    // Lines 9101-9105
+#define sqlite3_snapshot_get chrome_sqlite3_snapshot_get  // Lines 9101-9105
 #define sqlite3_snapshot_open chrome_sqlite3_snapshot_open  // Lines 9150-9154
-#define sqlite3_snapshot_recover chrome_sqlite3_snapshot_recover    // Line 9222
-#define sqlite3_snprintf chrome_sqlite3_snprintf                    // Line 2654
-#define sqlite3_soft_heap_limit chrome_sqlite3_soft_heap_limit      // Line 6040
+#define sqlite3_snapshot_recover chrome_sqlite3_snapshot_recover  // Line 9222
+#define sqlite3_snprintf chrome_sqlite3_snprintf  // Line 2654
+#define sqlite3_soft_heap_limit chrome_sqlite3_soft_heap_limit  // Line 6040
 #define sqlite3_soft_heap_limit64 chrome_sqlite3_soft_heap_limit64  // Line 6029
-#define sqlite3_sourceid chrome_sqlite3_sourceid                    // Line 164
-#define sqlite3_sql chrome_sqlite3_sql                              // Line 3834
-#define sqlite3_status chrome_sqlite3_status                        // Line 7473
-#define sqlite3_status64 chrome_sqlite3_status64            // Lines 7474-7479
-#define sqlite3_step chrome_sqlite3_step                    // Line 4374
-#define sqlite3_stmt_busy chrome_sqlite3_stmt_busy          // Line 3893
+#define sqlite3_sourceid chrome_sqlite3_sourceid  // Line 164
+#define sqlite3_sql chrome_sqlite3_sql  // Line 3834
+#define sqlite3_status chrome_sqlite3_status  // Line 7473
+#define sqlite3_status64 chrome_sqlite3_status64  // Lines 7474-7479
+#define sqlite3_step chrome_sqlite3_step  // Line 4374
+#define sqlite3_stmt_busy chrome_sqlite3_stmt_busy  // Line 3893
 #define sqlite3_stmt_readonly chrome_sqlite3_stmt_readonly  // Line 3872
-#define sqlite3_stmt_scanstatus \
-  chrome_sqlite3_stmt_scanstatus  // Lines 8870-8875
-#define sqlite3_stmt_scanstatus_reset \
-  chrome_sqlite3_stmt_scanstatus_reset                        // Line 8886
-#define sqlite3_stmt_status chrome_sqlite3_stmt_status        // Line 7736
-#define sqlite3_str_append chrome_sqlite3_str_append          // Line 7409
-#define sqlite3_str_appendall chrome_sqlite3_str_appendall    // Line 7410
+#define sqlite3_stmt_scanstatus chrome_sqlite3_stmt_scanstatus  // Lines 8870-8875
+#define sqlite3_stmt_scanstatus_reset chrome_sqlite3_stmt_scanstatus_reset  // Line 8886
+#define sqlite3_stmt_status chrome_sqlite3_stmt_status  // Line 7736
+#define sqlite3_str_append chrome_sqlite3_str_append  // Line 7409
+#define sqlite3_str_appendall chrome_sqlite3_str_appendall  // Line 7410
 #define sqlite3_str_appendchar chrome_sqlite3_str_appendchar  // Line 7411
-#define sqlite3_str_appendf chrome_sqlite3_str_appendf        // Line 7407
-#define sqlite3_str_errcode chrome_sqlite3_str_errcode        // Line 7443
-#define sqlite3_str_finish chrome_sqlite3_str_finish          // Line 7373
-#define sqlite3_str_length chrome_sqlite3_str_length          // Line 7444
-#define sqlite3_str_new chrome_sqlite3_str_new                // Line 7358
-#define sqlite3_str_reset chrome_sqlite3_str_reset            // Line 7412
-#define sqlite3_str_value chrome_sqlite3_str_value            // Line 7445
-#define sqlite3_str_vappendf chrome_sqlite3_str_vappendf      // Line 7408
-#define sqlite3_strglob chrome_sqlite3_strglob                // Line 8385
-#define sqlite3_stricmp chrome_sqlite3_stricmp                // Line 8367
-#define sqlite3_strlike chrome_sqlite3_strlike                // Line 8431
-#define sqlite3_strnicmp chrome_sqlite3_strnicmp              // Line 8368
-#define sqlite3_system_errno chrome_sqlite3_system_errno      // Line 9032
-#define sqlite3_table_column_metadata \
-  chrome_sqlite3_table_column_metadata                        // Lines 6112-6122
+#define sqlite3_str_appendf chrome_sqlite3_str_appendf  // Line 7407
+#define sqlite3_str_errcode chrome_sqlite3_str_errcode  // Line 7443
+#define sqlite3_str_finish chrome_sqlite3_str_finish  // Line 7373
+#define sqlite3_str_length chrome_sqlite3_str_length  // Line 7444
+#define sqlite3_str_new chrome_sqlite3_str_new  // Line 7358
+#define sqlite3_str_reset chrome_sqlite3_str_reset  // Line 7412
+#define sqlite3_str_value chrome_sqlite3_str_value  // Line 7445
+#define sqlite3_str_vappendf chrome_sqlite3_str_vappendf  // Line 7408
+#define sqlite3_strglob chrome_sqlite3_strglob  // Line 8385
+#define sqlite3_stricmp chrome_sqlite3_stricmp  // Line 8367
+#define sqlite3_strlike chrome_sqlite3_strlike  // Line 8431
+#define sqlite3_strnicmp chrome_sqlite3_strnicmp  // Line 8368
+#define sqlite3_system_errno chrome_sqlite3_system_errno  // Line 9032
+#define sqlite3_table_column_metadata chrome_sqlite3_table_column_metadata  // Lines 6112-6122
 #define sqlite3_temp_directory chrome_sqlite3_temp_directory  // Line 5652
-#define sqlite3_test_control chrome_sqlite3_test_control      // Line 7224
+#define sqlite3_test_control chrome_sqlite3_test_control  // Line 7224
 #define sqlite3_thread_cleanup chrome_sqlite3_thread_cleanup  // Line 4896
-#define sqlite3_threadsafe chrome_sqlite3_threadsafe          // Line 230
-#define sqlite3_total_changes chrome_sqlite3_total_changes    // Line 2370
-#define sqlite3_trace chrome_sqlite3_trace                    // Lines 2998-2999
-#define sqlite3_trace_v2 chrome_sqlite3_trace_v2              // Lines 3089-3094
+#define sqlite3_threadsafe chrome_sqlite3_threadsafe  // Line 230
+#define sqlite3_total_changes chrome_sqlite3_total_changes  // Line 2370
+#define sqlite3_trace chrome_sqlite3_trace  // Lines 2998-2999
+#define sqlite3_trace_v2 chrome_sqlite3_trace_v2  // Lines 3089-3094
 #define sqlite3_transfer_bindings chrome_sqlite3_transfer_bindings  // Line 4894
-#define sqlite3_unlock_notify chrome_sqlite3_unlock_notify    // Lines 8352-8356
-#define sqlite3_update_hook chrome_sqlite3_update_hook        // Lines 5905-5909
-#define sqlite3_uri_boolean chrome_sqlite3_uri_boolean        // Line 3412
-#define sqlite3_uri_int64 chrome_sqlite3_uri_int64            // Line 3413
-#define sqlite3_uri_parameter chrome_sqlite3_uri_parameter    // Line 3411
-#define sqlite3_user_data chrome_sqlite3_user_data            // Line 5124
-#define sqlite3_value_blob chrome_sqlite3_value_blob          // Line 5022
-#define sqlite3_value_bytes chrome_sqlite3_value_bytes        // Line 5031
-#define sqlite3_value_bytes16 chrome_sqlite3_value_bytes16    // Line 5032
-#define sqlite3_value_double chrome_sqlite3_value_double      // Line 5023
-#define sqlite3_value_dup chrome_sqlite3_value_dup            // Line 5063
-#define sqlite3_value_free chrome_sqlite3_value_free          // Line 5064
-#define sqlite3_value_int chrome_sqlite3_value_int            // Line 5024
-#define sqlite3_value_int64 chrome_sqlite3_value_int64        // Line 5025
+#define sqlite3_unlock_notify chrome_sqlite3_unlock_notify  // Lines 8352-8356
+#define sqlite3_update_hook chrome_sqlite3_update_hook  // Lines 5905-5909
+#define sqlite3_uri_boolean chrome_sqlite3_uri_boolean  // Line 3412
+#define sqlite3_uri_int64 chrome_sqlite3_uri_int64  // Line 3413
+#define sqlite3_uri_parameter chrome_sqlite3_uri_parameter  // Line 3411
+#define sqlite3_user_data chrome_sqlite3_user_data  // Line 5124
+#define sqlite3_value_blob chrome_sqlite3_value_blob  // Line 5022
+#define sqlite3_value_bytes chrome_sqlite3_value_bytes  // Line 5031
+#define sqlite3_value_bytes16 chrome_sqlite3_value_bytes16  // Line 5032
+#define sqlite3_value_double chrome_sqlite3_value_double  // Line 5023
+#define sqlite3_value_dup chrome_sqlite3_value_dup  // Line 5063
+#define sqlite3_value_free chrome_sqlite3_value_free  // Line 5064
+#define sqlite3_value_int chrome_sqlite3_value_int  // Line 5024
+#define sqlite3_value_int64 chrome_sqlite3_value_int64  // Line 5025
 #define sqlite3_value_nochange chrome_sqlite3_value_nochange  // Line 5035
-#define sqlite3_value_numeric_type \
-  chrome_sqlite3_value_numeric_type                               // Line 5034
-#define sqlite3_value_pointer chrome_sqlite3_value_pointer        // Line 5026
-#define sqlite3_value_subtype chrome_sqlite3_value_subtype        // Line 5047
-#define sqlite3_value_text chrome_sqlite3_value_text              // Line 5027
-#define sqlite3_value_text16 chrome_sqlite3_value_text16          // Line 5028
-#define sqlite3_value_text16be chrome_sqlite3_value_text16be      // Line 5030
-#define sqlite3_value_text16le chrome_sqlite3_value_text16le      // Line 5029
-#define sqlite3_value_type chrome_sqlite3_value_type              // Line 5033
-#define sqlite3_version chrome_sqlite3_version                    // Line 162
-#define sqlite3_vfs_find chrome_sqlite3_vfs_find                  // Line 6889
-#define sqlite3_vfs_register chrome_sqlite3_vfs_register          // Line 6890
-#define sqlite3_vfs_unregister chrome_sqlite3_vfs_unregister      // Line 6891
-#define sqlite3_vmprintf chrome_sqlite3_vmprintf                  // Line 2653
-#define sqlite3_vsnprintf chrome_sqlite3_vsnprintf                // Line 2655
-#define sqlite3_vtab_collation chrome_sqlite3_vtab_collation      // Line 8765
-#define sqlite3_vtab_config chrome_sqlite3_vtab_config            // Line 8677
-#define sqlite3_vtab_nochange chrome_sqlite3_vtab_nochange        // Line 8750
+#define sqlite3_value_numeric_type chrome_sqlite3_value_numeric_type  // Line 5034
+#define sqlite3_value_pointer chrome_sqlite3_value_pointer  // Line 5026
+#define sqlite3_value_subtype chrome_sqlite3_value_subtype  // Line 5047
+#define sqlite3_value_text chrome_sqlite3_value_text  // Line 5027
+#define sqlite3_value_text16 chrome_sqlite3_value_text16  // Line 5028
+#define sqlite3_value_text16be chrome_sqlite3_value_text16be  // Line 5030
+#define sqlite3_value_text16le chrome_sqlite3_value_text16le  // Line 5029
+#define sqlite3_value_type chrome_sqlite3_value_type  // Line 5033
+#define sqlite3_version chrome_sqlite3_version  // Line 162
+#define sqlite3_vfs_find chrome_sqlite3_vfs_find  // Line 6889
+#define sqlite3_vfs_register chrome_sqlite3_vfs_register  // Line 6890
+#define sqlite3_vfs_unregister chrome_sqlite3_vfs_unregister  // Line 6891
+#define sqlite3_vmprintf chrome_sqlite3_vmprintf  // Line 2653
+#define sqlite3_vsnprintf chrome_sqlite3_vsnprintf  // Line 2655
+#define sqlite3_vtab_collation chrome_sqlite3_vtab_collation  // Line 8765
+#define sqlite3_vtab_config chrome_sqlite3_vtab_config  // Line 8677
+#define sqlite3_vtab_nochange chrome_sqlite3_vtab_nochange  // Line 8750
 #define sqlite3_vtab_on_conflict chrome_sqlite3_vtab_on_conflict  // Line 8731
-#define sqlite3_wal_autocheckpoint \
-  chrome_sqlite3_wal_autocheckpoint                           // Line 8525
+#define sqlite3_wal_autocheckpoint chrome_sqlite3_wal_autocheckpoint  // Line 8525
 #define sqlite3_wal_checkpoint chrome_sqlite3_wal_checkpoint  // Line 8547
-#define sqlite3_wal_checkpoint_v2 \
-  chrome_sqlite3_wal_checkpoint_v2                // Lines 8641-8647
+#define sqlite3_wal_checkpoint_v2 chrome_sqlite3_wal_checkpoint_v2  // Lines 8641-8647
 #define sqlite3_wal_hook chrome_sqlite3_wal_hook  // Lines 8490-8494
-#define sqlite3_win32_set_directory \
-  chrome_sqlite3_win32_set_directory  // Lines 5710-5713
-#define sqlite3_win32_set_directory16 \
-  chrome_sqlite3_win32_set_directory16  // Line 5715
-#define sqlite3_win32_set_directory8 \
-  chrome_sqlite3_win32_set_directory8                         // Line 5714
+#define sqlite3_win32_set_directory chrome_sqlite3_win32_set_directory  // Lines 5710-5713
+#define sqlite3_win32_set_directory16 chrome_sqlite3_win32_set_directory16  // Line 5715
+#define sqlite3_win32_set_directory8 chrome_sqlite3_win32_set_directory8  // Line 5714
 #define sqlite3changegroup_add chrome_sqlite3changegroup_add  // Line 10412
-#define sqlite3changegroup_add_strm \
-  chrome_sqlite3changegroup_add_strm  // Lines 11074-11077
-#define sqlite3changegroup_delete \
-  chrome_sqlite3changegroup_delete                            // Line 10449
+#define sqlite3changegroup_add_strm chrome_sqlite3changegroup_add_strm  // Lines 11074-11077
+#define sqlite3changegroup_delete chrome_sqlite3changegroup_delete  // Line 10449
 #define sqlite3changegroup_new chrome_sqlite3changegroup_new  // Line 10334
-#define sqlite3changegroup_output \
-  chrome_sqlite3changegroup_output  // Lines 10439-10443
-#define sqlite3changegroup_output_strm \
-  chrome_sqlite3changegroup_output_strm  // Lines 11078-11081
-#define sqlite3changeset_apply \
-  chrome_sqlite3changeset_apply  // Lines 10609-10623
-#define sqlite3changeset_apply_strm \
-  chrome_sqlite3changeset_apply_strm  // Lines 11007-11021
-#define sqlite3changeset_apply_v2 \
-  chrome_sqlite3changeset_apply_v2  // Lines 10624-10640
-#define sqlite3changeset_apply_v2_strm \
-  chrome_sqlite3changeset_apply_v2_strm  // Lines 11022-11038
-#define sqlite3changeset_concat \
-  chrome_sqlite3changeset_concat  // Lines 10280-10287
-#define sqlite3changeset_concat_strm \
-  chrome_sqlite3changeset_concat_strm  // Lines 11039-11046
-#define sqlite3changeset_conflict \
-  chrome_sqlite3changeset_conflict  // Lines 10166-10170
-#define sqlite3changeset_finalize \
-  chrome_sqlite3changeset_finalize  // Line 10219
-#define sqlite3changeset_fk_conflicts \
-  chrome_sqlite3changeset_fk_conflicts  // Lines 10183-10186
-#define sqlite3changeset_invert \
-  chrome_sqlite3changeset_invert  // Lines 10249-10252
-#define sqlite3changeset_invert_strm \
-  chrome_sqlite3changeset_invert_strm                       // Lines 11047-11052
-#define sqlite3changeset_new chrome_sqlite3changeset_new    // Lines 10138-10142
+#define sqlite3changegroup_output chrome_sqlite3changegroup_output  // Lines 10439-10443
+#define sqlite3changegroup_output_strm chrome_sqlite3changegroup_output_strm  // Lines 11078-11081
+#define sqlite3changeset_apply chrome_sqlite3changeset_apply  // Lines 10609-10623
+#define sqlite3changeset_apply_strm chrome_sqlite3changeset_apply_strm  // Lines 11007-11021
+#define sqlite3changeset_apply_v2 chrome_sqlite3changeset_apply_v2  // Lines 10624-10640
+#define sqlite3changeset_apply_v2_strm chrome_sqlite3changeset_apply_v2_strm  // Lines 11022-11038
+#define sqlite3changeset_concat chrome_sqlite3changeset_concat  // Lines 10280-10287
+#define sqlite3changeset_concat_strm chrome_sqlite3changeset_concat_strm  // Lines 11039-11046
+#define sqlite3changeset_conflict chrome_sqlite3changeset_conflict  // Lines 10166-10170
+#define sqlite3changeset_finalize chrome_sqlite3changeset_finalize  // Line 10219
+#define sqlite3changeset_fk_conflicts chrome_sqlite3changeset_fk_conflicts  // Lines 10183-10186
+#define sqlite3changeset_invert chrome_sqlite3changeset_invert  // Lines 10249-10252
+#define sqlite3changeset_invert_strm chrome_sqlite3changeset_invert_strm  // Lines 11047-11052
+#define sqlite3changeset_new chrome_sqlite3changeset_new  // Lines 10138-10142
 #define sqlite3changeset_next chrome_sqlite3changeset_next  // Line 10010
-#define sqlite3changeset_old chrome_sqlite3changeset_old    // Lines 10104-10108
-#define sqlite3changeset_op chrome_sqlite3changeset_op      // Lines 10039-10045
-#define sqlite3changeset_pk chrome_sqlite3changeset_pk      // Lines 10073-10077
+#define sqlite3changeset_old chrome_sqlite3changeset_old  // Lines 10104-10108
+#define sqlite3changeset_op chrome_sqlite3changeset_op  // Lines 10039-10045
+#define sqlite3changeset_pk chrome_sqlite3changeset_pk  // Lines 10073-10077
 #define sqlite3changeset_start chrome_sqlite3changeset_start  // Lines 9961-9965
-#define sqlite3changeset_start_strm \
-  chrome_sqlite3changeset_start_strm  // Lines 11053-11057
-#define sqlite3changeset_start_v2 \
-  chrome_sqlite3changeset_start_v2  // Lines 9966-9971
-#define sqlite3changeset_start_v2_strm \
-  chrome_sqlite3changeset_start_v2_strm  // Lines 11058-11063
-#define sqlite3rebaser_configure \
-  chrome_sqlite3rebaser_configure                           // Lines 10882-10885
+#define sqlite3changeset_start_strm chrome_sqlite3changeset_start_strm  // Lines 11053-11057
+#define sqlite3changeset_start_v2 chrome_sqlite3changeset_start_v2  // Lines 9966-9971
+#define sqlite3changeset_start_v2_strm chrome_sqlite3changeset_start_v2_strm  // Lines 11058-11063
+#define sqlite3rebaser_configure chrome_sqlite3rebaser_configure  // Lines 10882-10885
 #define sqlite3rebaser_create chrome_sqlite3rebaser_create  // Line 10871
 #define sqlite3rebaser_delete chrome_sqlite3rebaser_delete  // Line 10915
 #define sqlite3rebaser_rebase chrome_sqlite3rebaser_rebase  // Lines 10901-10905
-#define sqlite3rebaser_rebase_strm \
-  chrome_sqlite3rebaser_rebase_strm                         // Lines 11082-11088
+#define sqlite3rebaser_rebase_strm chrome_sqlite3rebaser_rebase_strm  // Lines 11082-11088
 #define sqlite3session_attach chrome_sqlite3session_attach  // Lines 9668-9671
-#define sqlite3session_changeset \
-  chrome_sqlite3session_changeset  // Lines 9797-9801
-#define sqlite3session_changeset_strm \
-  chrome_sqlite3session_changeset_strm                      // Lines 11064-11068
+#define sqlite3session_changeset chrome_sqlite3session_changeset  // Lines 9797-9801
+#define sqlite3session_changeset_strm chrome_sqlite3session_changeset_strm  // Lines 11064-11068
 #define sqlite3session_config chrome_sqlite3session_config  // Line 11123
 #define sqlite3session_create chrome_sqlite3session_create  // Lines 9538-9542
 #define sqlite3session_delete chrome_sqlite3session_delete  // Line 9557
-#define sqlite3session_diff chrome_sqlite3session_diff      // Lines 9860-9865
+#define sqlite3session_diff chrome_sqlite3session_diff  // Lines 9860-9865
 #define sqlite3session_enable chrome_sqlite3session_enable  // Line 9578
 #define sqlite3session_indirect chrome_sqlite3session_indirect  // Line 9608
-#define sqlite3session_isempty chrome_sqlite3session_isempty    // Line 9918
-#define sqlite3session_patchset \
-  chrome_sqlite3session_patchset  // Lines 9897-9901
-#define sqlite3session_patchset_strm \
-  chrome_sqlite3session_patchset_strm  // Lines 11069-11073
-#define sqlite3session_table_filter \
-  chrome_sqlite3session_table_filter  // Lines 9683-9690
+#define sqlite3session_isempty chrome_sqlite3session_isempty  // Line 9918
+#define sqlite3session_patchset chrome_sqlite3session_patchset  // Lines 9897-9901
+#define sqlite3session_patchset_strm chrome_sqlite3session_patchset_strm  // Lines 11069-11073
+#define sqlite3session_table_filter chrome_sqlite3session_table_filter  // Lines 9683-9690
 
 #endif  // THIRD_PARTY_SQLITE_AMALGAMATION_RENAME_EXPORTS_H_
+
diff --git a/third_party/sqlite/amalgamation/sqlite3.c b/third_party/sqlite/amalgamation/sqlite3.c
index 3ca72d7..964c2c5 100644
--- a/third_party/sqlite/amalgamation/sqlite3.c
+++ b/third_party/sqlite/amalgamation/sqlite3.c
@@ -63828,11 +63828,12 @@
   UnpackedRecord *pIdxKey;   /* Unpacked index key */
 
   if( pKey ){
+    KeyInfo *pKeyInfo = pCur->pKeyInfo;
     assert( nKey==(i64)(int)nKey );
-    pIdxKey = sqlite3VdbeAllocUnpackedRecord(pCur->pKeyInfo);
+    pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
     if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
-    sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
-    if( pIdxKey->nField==0 ){
+    sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
+    if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
       rc = SQLITE_CORRUPT_BKPT;
       goto moveto_done;
     }
@@ -69717,8 +69718,71 @@
 }
 
 /*
+** The following parameters determine how many adjacent pages get involved
+** in a balancing operation.  NN is the number of neighbors on either side
+** of the page that participate in the balancing operation.  NB is the
+** total number of pages that participate, including the target page and
+** NN neighbors on either side.
+**
+** The minimum value of NN is 1 (of course).  Increasing NN above 1
+** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
+** in exchange for a larger degradation in INSERT and UPDATE performance.
+** The value of NN appears to give the best results overall.
+**
+** (Later:) The description above makes it seem as if these values are
+** tunable - as if you could change them and recompile and it would all work.
+** But that is unlikely.  NB has been 3 since the inception of SQLite and
+** we have never tested any other value.
+*/
+#define NN 1             /* Number of neighbors on either side of pPage */
+#define NB 3             /* (NN*2+1): Total pages involved in the balance */
+
+/*
 ** A CellArray object contains a cache of pointers and sizes for a
 ** consecutive sequence of cells that might be held on multiple pages.
+**
+** The cells in this array are the divider cell or cells from the pParent
+** page plus up to three child pages.  There are a total of nCell cells.
+**
+** pRef is a pointer to one of the pages that contributes cells.  This is
+** used to access information such as MemPage.intKey and MemPage.pBt->pageSize
+** which should be common to all pages that contribute cells to this array.
+**
+** apCell[] and szCell[] hold, respectively, pointers to the start of each
+** cell and the size of each cell.  Some of the apCell[] pointers might refer
+** to overflow cells.  In other words, some apCel[] pointers might not point
+** to content area of the pages.
+**
+** A szCell[] of zero means the size of that cell has not yet been computed.
+**
+** The cells come from as many as four different pages:
+**
+**             -----------
+**             | Parent  |
+**             -----------
+**            /     |     \
+**           /      |      \
+**  ---------   ---------   ---------
+**  |Child-1|   |Child-2|   |Child-3|
+**  ---------   ---------   ---------
+**
+** The order of cells is in the array is:
+**
+**       1.  All cells from Child-1 in order
+**       2.  The first divider cell from Parent
+**       3.  All cells from Child-2 in order
+**       4.  The second divider cell from Parent
+**       5.  All cells from Child-3 in order
+**
+** The apEnd[] array holds pointer to the end of page for Child-1, the
+** Parent, Child-2, the Parent (again), and Child-3.  The ixNx[] array
+** holds the number of cells contained in each of these 5 stages, and
+** all stages to the left.  Hence:
+**    ixNx[0] = Number of cells in Child-1.
+**    ixNx[1] = Number of cells in Child-1 plus 1 for first divider.
+**    ixNx[2] = Number of cells in Child-1 and Child-2 + 1 for 1st divider.
+**    ixNx[3] = Number of cells in Child-1 and Child-2 + both divider cells
+**    ixNx[4] = Total number of cells.
 */
 typedef struct CellArray CellArray;
 struct CellArray {
@@ -69726,6 +69790,8 @@
   MemPage *pRef;          /* Reference page */
   u8 **apCell;            /* All cells begin balanced */
   u16 *szCell;            /* Local size of all cells in apCell[] */
+  u8 *apEnd[NB*2];        /* MemPage.aDataEnd values */
+  int ixNx[NB*2];         /* Index of at which we move to the next apEnd[] */
 };
 
 /*
@@ -69776,37 +69842,58 @@
 ** responsibility of the caller to set it correctly.
 */
 static int rebuildPage(
-  MemPage *pPg,                   /* Edit this page */
+  CellArray *pCArray,             /* Content to be added to page pPg */
+  int iFirst,                     /* First cell in pCArray to use */
   int nCell,                      /* Final number of cells on page */
-  u8 **apCell,                    /* Array of cells */
-  u16 *szCell                     /* Array of cell sizes */
+  MemPage *pPg                    /* The page to be reconstructed */
 ){
   const int hdr = pPg->hdrOffset;          /* Offset of header on pPg */
   u8 * const aData = pPg->aData;           /* Pointer to data for pPg */
   const int usableSize = pPg->pBt->usableSize;
   u8 * const pEnd = &aData[usableSize];
-  int i;
+  int i = iFirst;                 /* Which cell to copy from pCArray*/
+  int j;                          /* Start of cell content area */
+  int iEnd = i+nCell;             /* Loop terminator */
   u8 *pCellptr = pPg->aCellIdx;
   u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager);
   u8 *pData;
+  int k;                          /* Current slot in pCArray->apEnd[] */
+  u8 *pSrcEnd;                    /* Current pCArray->apEnd[k] value */
 
-  i = get2byte(&aData[hdr+5]);
-  memcpy(&pTmp[i], &aData[i], usableSize - i);
+  assert( i<iEnd );
+  j = get2byte(&aData[hdr+5]);
+  memcpy(&pTmp[j], &aData[j], usableSize - j);
+
+  for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
+  pSrcEnd = pCArray->apEnd[k];
 
   pData = pEnd;
-  for(i=0; i<nCell; i++){
-    u8 *pCell = apCell[i];
+  while( 1/*exit by break*/ ){
+    u8 *pCell = pCArray->apCell[i];
+    u16 sz = pCArray->szCell[i];
+    assert( sz>0 );
     if( SQLITE_WITHIN(pCell,aData,pEnd) ){
-      if( ((uptr)(pCell+szCell[i]))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
+      if( ((uptr)(pCell+sz))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
       pCell = &pTmp[pCell - aData];
+    }else if( (uptr)(pCell+sz)>(uptr)pSrcEnd
+           && (uptr)(pCell)<(uptr)pSrcEnd
+    ){
+      return SQLITE_CORRUPT_BKPT;
     }
-    pData -= szCell[i];
+
+    pData -= sz;
     put2byte(pCellptr, (pData - aData));
     pCellptr += 2;
     if( pData < pCellptr ) return SQLITE_CORRUPT_BKPT;
-    memcpy(pData, pCell, szCell[i]);
-    assert( szCell[i]==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
-    testcase( szCell[i]!=pPg->xCellSize(pPg,pCell) );
+    memcpy(pData, pCell, sz);
+    assert( sz==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
+    testcase( sz!=pPg->xCellSize(pPg,pCell) );
+    i++;
+    if( i>=iEnd ) break;
+    if( pCArray->ixNx[k]<=i ){
+      k++;
+      pSrcEnd = pCArray->apEnd[k];
+    }
   }
 
   /* The pPg->nFree field is now set incorrectly. The caller will fix it. */
@@ -69821,12 +69908,11 @@
 }
 
 /*
-** Array apCell[] contains nCell pointers to b-tree cells. Array szCell
-** contains the size in bytes of each such cell. This function attempts to
-** add the cells stored in the array to page pPg. If it cannot (because
-** the page needs to be defragmented before the cells will fit), non-zero
-** is returned. Otherwise, if the cells are added successfully, zero is
-** returned.
+** The pCArray objects contains pointers to b-tree cells and the cell sizes.
+** This function attempts to add the cells stored in the array to page pPg.
+** If it cannot (because the page needs to be defragmented before the cells
+** will fit), non-zero is returned. Otherwise, if the cells are added
+** successfully, zero is returned.
 **
 ** Argument pCellptr points to the first entry in the cell-pointer array
 ** (part of page pPg) to populate. After cell apCell[0] is written to the
@@ -69854,12 +69940,17 @@
   int nCell,                      /* Number of cells to add to pPg */
   CellArray *pCArray              /* Array of cells */
 ){
-  int i;
-  u8 *aData = pPg->aData;
-  u8 *pData = *ppData;
-  int iEnd = iFirst + nCell;
+  int i = iFirst;                 /* Loop counter - cell index to insert */
+  u8 *aData = pPg->aData;         /* Complete page */
+  u8 *pData = *ppData;            /* Content area.  A subset of aData[] */
+  int iEnd = iFirst + nCell;      /* End of loop. One past last cell to ins */
+  int k;                          /* Current slot in pCArray->apEnd[] */
+  u8 *pEnd;                       /* Maximum extent of cell data */
   assert( CORRUPT_DB || pPg->hdrOffset==0 );    /* Never called on page 1 */
-  for(i=iFirst; i<iEnd; i++){
+  if( iEnd<=iFirst ) return 0;
+  for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
+  pEnd = pCArray->apEnd[k];
+  while( 1 /*Exit by break*/ ){
     int sz, rc;
     u8 *pSlot;
     sz = cachedCellSize(pCArray, i);
@@ -69874,20 +69965,33 @@
     assert( (pSlot+sz)<=pCArray->apCell[i]
          || pSlot>=(pCArray->apCell[i]+sz)
          || CORRUPT_DB );
+    if( (uptr)(pCArray->apCell[i]+sz)>(uptr)pEnd
+     && (uptr)(pCArray->apCell[i])<(uptr)pEnd
+    ){
+      assert( CORRUPT_DB );
+      (void)SQLITE_CORRUPT_BKPT;
+      return 1;
+    }
     memmove(pSlot, pCArray->apCell[i], sz);
     put2byte(pCellptr, (pSlot - aData));
     pCellptr += 2;
+    i++;
+    if( i>=iEnd ) break;
+    if( pCArray->ixNx[k]<=i ){
+      k++;
+      pEnd = pCArray->apEnd[k];
+    }
   }
   *ppData = pData;
   return 0;
 }
 
 /*
-** Array apCell[] contains nCell pointers to b-tree cells. Array szCell
-** contains the size in bytes of each such cell. This function adds the
-** space associated with each cell in the array that is currently stored
-** within the body of pPg to the pPg free-list. The cell-pointers and other
-** fields of the page are not updated.
+** The pCArray object contains pointers to b-tree cells and their sizes.
+**
+** This function adds the space associated with each cell in the array
+** that is currently stored within the body of pPg to the pPg free-list.
+** The cell-pointers and other fields of the page are not updated.
 **
 ** This function returns the total number of cells added to the free-list.
 */
@@ -69937,9 +70041,9 @@
 }
 
 /*
-** apCell[] and szCell[] contains pointers to and sizes of all cells in the
-** pages being balanced.  The current page, pPg, has pPg->nCell cells starting
-** with apCell[iOld].  After balancing, this page should hold nNew cells
+** pCArray contains pointers to and sizes of all cells in the pages being
+** balanced.  The current page, pPg, has pPg->nCell cells starting with
+** pCArray->apCell[iOld].  After balancing, this page should hold nNew cells
 ** starting at apCell[iNew].
 **
 ** This routine makes the necessary adjustments to pPg so that it contains
@@ -70039,24 +70143,9 @@
  editpage_fail:
   /* Unable to edit this page. Rebuild it from scratch instead. */
   populateCellCache(pCArray, iNew, nNew);
-  return rebuildPage(pPg, nNew, &pCArray->apCell[iNew], &pCArray->szCell[iNew]);
+  return rebuildPage(pCArray, iNew, nNew, pPg);
 }
 
-/*
-** The following parameters determine how many adjacent pages get involved
-** in a balancing operation.  NN is the number of neighbors on either side
-** of the page that participate in the balancing operation.  NB is the
-** total number of pages that participate, including the target page and
-** NN neighbors on either side.
-**
-** The minimum value of NN is 1 (of course).  Increasing NN above 1
-** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
-** in exchange for a larger degradation in INSERT and UPDATE performance.
-** The value of NN appears to give the best results overall.
-*/
-#define NN 1             /* Number of neighbors on either side of pPage */
-#define NB (NN*2+1)      /* Total pages involved in the balance */
-
 
 #ifndef SQLITE_OMIT_QUICKBALANCE
 /*
@@ -70106,12 +70195,22 @@
     u8 *pCell = pPage->apOvfl[0];
     u16 szCell = pPage->xCellSize(pPage, pCell);
     u8 *pStop;
+    CellArray b;
 
     assert( sqlite3PagerIswriteable(pNew->pDbPage) );
     assert( pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) );
     zeroPage(pNew, PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF);
-    rc = rebuildPage(pNew, 1, &pCell, &szCell);
-    if( NEVER(rc) ) return rc;
+    b.nCell = 1;
+    b.pRef = pPage;
+    b.apCell = &pCell;
+    b.szCell = &szCell;
+    b.apEnd[0] = pPage->aDataEnd;
+    b.ixNx[0] = 2;
+    rc = rebuildPage(&b, 0, 1, pNew);
+    if( NEVER(rc) ){
+      releasePage(pNew);
+      return rc;
+    }
     pNew->nFree = pBt->usableSize - pNew->cellOffset - 2 - szCell;
 
     /* If this is an auto-vacuum database, update the pointer map
@@ -70591,6 +70690,10 @@
   usableSpace = pBt->usableSize - 12 + leafCorrection;
   for(i=0; i<nOld; i++){
     MemPage *p = apOld[i];
+    b.apEnd[i*2] = p->aDataEnd;
+    b.apEnd[i*2+1] = pParent->aDataEnd;
+    b.ixNx[i*2] = cntOld[i];
+    b.ixNx[i*2+1] = cntOld[i]+1;
     szNew[i] = usableSpace - p->nFree;
     for(j=0; j<p->nOverflow; j++){
       szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]);
@@ -71272,7 +71375,11 @@
     if( memcmp(pDest, ((u8*)pX->pData) + iOffset, iAmt)!=0 ){
       int rc = sqlite3PagerWrite(pPage->pDbPage);
       if( rc ) return rc;
-      memcpy(pDest, ((u8*)pX->pData) + iOffset, iAmt);
+      /* In a corrupt database, it is possible for the source and destination
+      ** buffers to overlap.  This is harmless since the database is already
+      ** corrupt but it does cause valgrind and ASAN warnings.  So use
+      ** memmove(). */
+      memmove(pDest, ((u8*)pX->pData) + iOffset, iAmt);
     }
   }
   return SQLITE_OK;
@@ -79645,7 +79752,7 @@
   UnpackedRecord *p      /* Populate this structure before returning. */
 ){
   const unsigned char *aKey = (const unsigned char *)pKey;
-  int d;
+  u32 d;
   u32 idx;                        /* Offset in aKey[] to read from */
   u16 u;                          /* Unsigned loop counter */
   u32 szHdr;
@@ -132410,6 +132517,7 @@
   ** being updated.  Fill in aRegIdx[] with a register number that will hold
   ** the key for accessing each index.
   */
+if( onError==OE_Replace ) bReplace = 1;
   for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
     int reg;
     if( chngKey || hasFK>1 || pIdx==pPk
@@ -132423,9 +132531,7 @@
         if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){
           reg = ++pParse->nMem;
           pParse->nMem += pIdx->nColumn;
-          if( (onError==OE_Replace)
-           || (onError==OE_Default && pIdx->onError==OE_Replace)
-          ){
+          if( onError==OE_Default && pIdx->onError==OE_Replace ){
             bReplace = 1;
           }
           break;
@@ -220294,7 +220400,7 @@
 #endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
 
 /************** End of stmt.c ************************************************/
-#if __LINE__!=220297
+#if __LINE__!=220403
 #undef SQLITE_SOURCE_ID
 #define SQLITE_SOURCE_ID      "2018-12-01 12:34:55 bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238alt2"
 #endif
diff --git a/third_party/sqlite/patches/0001-Modify-default-VFS-to-support-WebDatabase.patch b/third_party/sqlite/patches/0001-Modify-default-VFS-to-support-WebDatabase.patch
index 1d86c19..1423304 100644
--- a/third_party/sqlite/patches/0001-Modify-default-VFS-to-support-WebDatabase.patch
+++ b/third_party/sqlite/patches/0001-Modify-default-VFS-to-support-WebDatabase.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: dumi <dumi@chromium.org>
 Date: Mon, 20 Jul 2009 23:40:51 +0000
-Subject: [PATCH 01/40] Modify default VFS to support WebDatabase.
+Subject: [PATCH 01/45] Modify default VFS to support WebDatabase.
 
 The renderer WebDatabase implementation needs to broker certain requests
 to the browser.  This modifies SQLite to allow monkey-patching the VFS
diff --git a/third_party/sqlite/patches/0002-Virtual-table-supporting-recovery-of-corrupted-datab.patch b/third_party/sqlite/patches/0002-Virtual-table-supporting-recovery-of-corrupted-datab.patch
index ef5d820..2153c96 100644
--- a/third_party/sqlite/patches/0002-Virtual-table-supporting-recovery-of-corrupted-datab.patch
+++ b/third_party/sqlite/patches/0002-Virtual-table-supporting-recovery-of-corrupted-datab.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Scott Hess <shess@chromium.org>
 Date: Sat, 20 Jul 2013 11:42:21 -0700
-Subject: [PATCH 02/40] Virtual table supporting recovery of corrupted
+Subject: [PATCH 02/45] Virtual table supporting recovery of corrupted
  databases.
 
 "recover" implements a virtual table which uses the SQLite pager layer
diff --git a/third_party/sqlite/patches/0003-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch b/third_party/sqlite/patches/0003-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch
index 6a49c96..1203d8c6 100644
--- a/third_party/sqlite/patches/0003-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch
+++ b/third_party/sqlite/patches/0003-Custom-shell.c-helpers-to-load-Chromium-s-ICU-data.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: "tc@google.com" <tc@google.com>
 Date: Tue, 6 Jan 2009 22:39:41 +0000
-Subject: [PATCH 03/40] Custom shell.c helpers to load Chromium's ICU data.
+Subject: [PATCH 03/45] Custom shell.c helpers to load Chromium's ICU data.
 
 History uses fts3 with an icu-based segmenter.  These changes allow building a
 sqlite3 binary for Linux or Windows which can read those files.
diff --git a/third_party/sqlite/patches/0004-fts3-Disable-fts3_tokenizer-and-fts4.patch b/third_party/sqlite/patches/0004-fts3-Disable-fts3_tokenizer-and-fts4.patch
index e77c949..c81ac86 100644
--- a/third_party/sqlite/patches/0004-fts3-Disable-fts3_tokenizer-and-fts4.patch
+++ b/third_party/sqlite/patches/0004-fts3-Disable-fts3_tokenizer-and-fts4.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Scott Hess <shess@chromium.org>
 Date: Tue, 16 Dec 2014 13:02:27 -0800
-Subject: [PATCH 04/40] [fts3] Disable fts3_tokenizer and fts4.
+Subject: [PATCH 04/45] [fts3] Disable fts3_tokenizer and fts4.
 
 fts3_tokenizer allows a SQLite user to specify a pointer to call as a
 function, which has obvious sercurity implications.  Disable fts4 until
diff --git a/third_party/sqlite/patches/0005-fuchsia-Use-dot-file-locking-for-sqlite.patch b/third_party/sqlite/patches/0005-fuchsia-Use-dot-file-locking-for-sqlite.patch
index 8f4f6e01..1e4978a 100644
--- a/third_party/sqlite/patches/0005-fuchsia-Use-dot-file-locking-for-sqlite.patch
+++ b/third_party/sqlite/patches/0005-fuchsia-Use-dot-file-locking-for-sqlite.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Scott Graham <scottmg@chromium.org>
 Date: Mon, 11 Sep 2017 13:37:46 -0700
-Subject: [PATCH 05/40] fuchsia: Use dot-file locking for sqlite
+Subject: [PATCH 05/45] fuchsia: Use dot-file locking for sqlite
 
 ---
  third_party/sqlite/src/src/os_unix.c | 4 ++++
diff --git a/third_party/sqlite/patches/0006-Fix-dbfuzz2-for-Clusterfuzz.patch b/third_party/sqlite/patches/0006-Fix-dbfuzz2-for-Clusterfuzz.patch
index c5cd6153..0e6488c 100644
--- a/third_party/sqlite/patches/0006-Fix-dbfuzz2-for-Clusterfuzz.patch
+++ b/third_party/sqlite/patches/0006-Fix-dbfuzz2-for-Clusterfuzz.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Matthew Denton <mpdenton@chromium.org>
 Date: Fri, 7 Dec 2018 14:49:36 -0700
-Subject: [PATCH 06/40] Fix dbfuzz2 for Clusterfuzz.
+Subject: [PATCH 06/45] Fix dbfuzz2 for Clusterfuzz.
 
 This backports https://www.sqlite.org/src/info/9ad796a8822f1b7e
 ---
diff --git a/third_party/sqlite/patches/0007-Fix-the-Makefile-so-that-it-honors-CFLAGS-when-build.patch b/third_party/sqlite/patches/0007-Fix-the-Makefile-so-that-it-honors-CFLAGS-when-build.patch
index 8886eab..6df439d 100644
--- a/third_party/sqlite/patches/0007-Fix-the-Makefile-so-that-it-honors-CFLAGS-when-build.patch
+++ b/third_party/sqlite/patches/0007-Fix-the-Makefile-so-that-it-honors-CFLAGS-when-build.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Wed, 19 Dec 2018 18:22:15 -0800
-Subject: [PATCH 07/40] Fix the Makefile so that it honors CFLAGS when building
+Subject: [PATCH 07/45] Fix the Makefile so that it honors CFLAGS when building
  sessionfuzz.
 
 This backports https://www.sqlite.org/src/info/54231ac4ca506e6c
diff --git a/third_party/sqlite/patches/0008-Adjustments-to-the-page-cache-to-try-to-avoid-harmle.patch b/third_party/sqlite/patches/0008-Adjustments-to-the-page-cache-to-try-to-avoid-harmle.patch
index 8d86320bf..c547e98 100644
--- a/third_party/sqlite/patches/0008-Adjustments-to-the-page-cache-to-try-to-avoid-harmle.patch
+++ b/third_party/sqlite/patches/0008-Adjustments-to-the-page-cache-to-try-to-avoid-harmle.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Fri, 11 Jan 2019 02:01:53 -0800
-Subject: [PATCH 08/40] Adjustments to the page cache to try to avoid harmless
+Subject: [PATCH 08/45] Adjustments to the page cache to try to avoid harmless
  TSAN warnings
 
 This backports https://www.sqlite.org/src/info/383437be276719ac
diff --git a/third_party/sqlite/patches/0009-Remove-an-ALWAYS-from-a-branch-that-is-not-always-ta.patch b/third_party/sqlite/patches/0009-Remove-an-ALWAYS-from-a-branch-that-is-not-always-ta.patch
index d5159f6..d228dffb 100644
--- a/third_party/sqlite/patches/0009-Remove-an-ALWAYS-from-a-branch-that-is-not-always-ta.patch
+++ b/third_party/sqlite/patches/0009-Remove-an-ALWAYS-from-a-branch-that-is-not-always-ta.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Fri, 11 Jan 2019 02:26:10 -0800
-Subject: [PATCH 09/40] Remove an ALWAYS() from a branch that is not always
+Subject: [PATCH 09/45] Remove an ALWAYS() from a branch that is not always
  taken.
 
 This backports https://www.sqlite.org/src/info/5c7dab
diff --git a/third_party/sqlite/patches/0010-Fix-a-problem-with-nested-CTEs-with-the-same-table.patch b/third_party/sqlite/patches/0010-Fix-a-problem-with-nested-CTEs-with-the-same-table.patch
index 216d8ef8..d58ab19 100644
--- a/third_party/sqlite/patches/0010-Fix-a-problem-with-nested-CTEs-with-the-same-table.patch
+++ b/third_party/sqlite/patches/0010-Fix-a-problem-with-nested-CTEs-with-the-same-table.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Fri, 11 Jan 2019 02:30:28 -0800
-Subject: [PATCH 10/40] Fix a problem with nested CTEs with the same table.
+Subject: [PATCH 10/45] Fix a problem with nested CTEs with the same table.
 
 This backports https://www.sqlite.org/src/info/202dd033019dd274
 
diff --git a/third_party/sqlite/patches/0011-Fix-detection-of-self-referencing-rows-in-foreign-ke.patch b/third_party/sqlite/patches/0011-Fix-detection-of-self-referencing-rows-in-foreign-ke.patch
index 878c4b2..6c81716b 100644
--- a/third_party/sqlite/patches/0011-Fix-detection-of-self-referencing-rows-in-foreign-ke.patch
+++ b/third_party/sqlite/patches/0011-Fix-detection-of-self-referencing-rows-in-foreign-ke.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Fri, 11 Jan 2019 03:45:18 -0800
-Subject: [PATCH 11/40] Fix detection of self-referencing rows in foreign key
+Subject: [PATCH 11/45] Fix detection of self-referencing rows in foreign key
  processing.
 
 This backports https://www.sqlite.org/src/info/16fff05347f42fe9
diff --git a/third_party/sqlite/patches/0012-Fix-a-segfault-caused-by-using-the-RAISE-function-in.patch b/third_party/sqlite/patches/0012-Fix-a-segfault-caused-by-using-the-RAISE-function-in.patch
index 5f73980..b1bb1e4 100644
--- a/third_party/sqlite/patches/0012-Fix-a-segfault-caused-by-using-the-RAISE-function-in.patch
+++ b/third_party/sqlite/patches/0012-Fix-a-segfault-caused-by-using-the-RAISE-function-in.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Fri, 11 Jan 2019 03:52:20 -0800
-Subject: [PATCH 12/40] Fix a segfault caused by using the RAISE function
+Subject: [PATCH 12/45] Fix a segfault caused by using the RAISE function
  incorrectly.
 
 This backports https://sqlite.org/src/info/ddf06db702761d66
diff --git a/third_party/sqlite/patches/0013-Fix-for-an-assert-that-could-be-false.patch b/third_party/sqlite/patches/0013-Fix-for-an-assert-that-could-be-false.patch
index d9e2804..cde4ecb 100644
--- a/third_party/sqlite/patches/0013-Fix-for-an-assert-that-could-be-false.patch
+++ b/third_party/sqlite/patches/0013-Fix-for-an-assert-that-could-be-false.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Fri, 11 Jan 2019 04:18:45 -0800
-Subject: [PATCH 13/40] Fix for an assert() that could be false.
+Subject: [PATCH 13/45] Fix for an assert() that could be false.
 
 This backports https://www.sqlite.org/src/info/23b62fb160d86dc9 /
 https://www.sqlite.org/src/info/bc891ac6b62fe7d9
diff --git a/third_party/sqlite/patches/0014-Fix-another-problem-found-by-Matthew-Denton-s-new-fu.patch b/third_party/sqlite/patches/0014-Fix-another-problem-found-by-Matthew-Denton-s-new-fu.patch
index 4b4c61a..328f0af 100644
--- a/third_party/sqlite/patches/0014-Fix-another-problem-found-by-Matthew-Denton-s-new-fu.patch
+++ b/third_party/sqlite/patches/0014-Fix-another-problem-found-by-Matthew-Denton-s-new-fu.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Fri, 11 Jan 2019 04:21:21 -0800
-Subject: [PATCH 14/40] Fix another problem found by Matthew Denton's new
+Subject: [PATCH 14/45] Fix another problem found by Matthew Denton's new
  fuzzer.
 
 This backports https://sqlite.org/src/info/2b690dbdffe144bd
diff --git a/third_party/sqlite/patches/0015-Report-a-new-corruption-case.patch b/third_party/sqlite/patches/0015-Report-a-new-corruption-case.patch
index 12ea897..e4be4e1 100644
--- a/third_party/sqlite/patches/0015-Report-a-new-corruption-case.patch
+++ b/third_party/sqlite/patches/0015-Report-a-new-corruption-case.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Fri, 11 Jan 2019 12:15:27 -0800
-Subject: [PATCH 15/40] Report a new corruption case.
+Subject: [PATCH 15/45] Report a new corruption case.
 
 This backports https://sqlite.org/src/info/cc42dd15100db28a
 
diff --git a/third_party/sqlite/patches/0016-Avoid-a-buffer-overread-in-ptrmapPutOvflPtr.patch b/third_party/sqlite/patches/0016-Avoid-a-buffer-overread-in-ptrmapPutOvflPtr.patch
index a912e8b..10cf7a4 100644
--- a/third_party/sqlite/patches/0016-Avoid-a-buffer-overread-in-ptrmapPutOvflPtr.patch
+++ b/third_party/sqlite/patches/0016-Avoid-a-buffer-overread-in-ptrmapPutOvflPtr.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Fri, 11 Jan 2019 12:19:01 -0800
-Subject: [PATCH 16/40] Avoid a buffer overread in ptrmapPutOvflPtr().
+Subject: [PATCH 16/45] Avoid a buffer overread in ptrmapPutOvflPtr().
 
 This backports https://sqlite.org/src/info/f8b781cf41800e9f
 
diff --git a/third_party/sqlite/patches/0017-Improved-detection-of-cell-corruption-in-sqlite3Vdbe.patch b/third_party/sqlite/patches/0017-Improved-detection-of-cell-corruption-in-sqlite3Vdbe.patch
index 9417c68..6fbc383 100644
--- a/third_party/sqlite/patches/0017-Improved-detection-of-cell-corruption-in-sqlite3Vdbe.patch
+++ b/third_party/sqlite/patches/0017-Improved-detection-of-cell-corruption-in-sqlite3Vdbe.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Fri, 11 Jan 2019 13:22:44 -0800
-Subject: [PATCH 17/40] Improved detection of cell corruption in
+Subject: [PATCH 17/45] Improved detection of cell corruption in
  sqlite3VdbeRecordCompareWithSkip().
 
 This backports https://www.sqlite.org/src/info/fa47f4c6589c431c
diff --git a/third_party/sqlite/patches/0018-Fix-a-segfault-in-fts3-prompted-by-a-corrupted-datab.patch b/third_party/sqlite/patches/0018-Fix-a-segfault-in-fts3-prompted-by-a-corrupted-datab.patch
index d727224..1ea955006 100644
--- a/third_party/sqlite/patches/0018-Fix-a-segfault-in-fts3-prompted-by-a-corrupted-datab.patch
+++ b/third_party/sqlite/patches/0018-Fix-a-segfault-in-fts3-prompted-by-a-corrupted-datab.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Sat, 12 Jan 2019 12:36:35 -0800
-Subject: [PATCH 18/40] Fix a segfault in fts3 prompted by a corrupted
+Subject: [PATCH 18/45] Fix a segfault in fts3 prompted by a corrupted
  database.
 
 This backports https://www.sqlite.org/src/info/2d7b1d1d41ff69d5
diff --git a/third_party/sqlite/patches/0019-Prevent-integer-overflow-from-leading-to-buffer-over.patch b/third_party/sqlite/patches/0019-Prevent-integer-overflow-from-leading-to-buffer-over.patch
index de615a9..8ce1140 100644
--- a/third_party/sqlite/patches/0019-Prevent-integer-overflow-from-leading-to-buffer-over.patch
+++ b/third_party/sqlite/patches/0019-Prevent-integer-overflow-from-leading-to-buffer-over.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Sat, 12 Jan 2019 14:30:08 -0800
-Subject: [PATCH 19/40] Prevent integer overflow from leading to buffer
+Subject: [PATCH 19/45] Prevent integer overflow from leading to buffer
  overread inside of an assert().
 
 This backports https://www.sqlite.org/src/info/0f850a25d67a752f
diff --git a/third_party/sqlite/patches/0020-Add-extra-tests-for-database-corruption-inside-defra.patch b/third_party/sqlite/patches/0020-Add-extra-tests-for-database-corruption-inside-defra.patch
index b4d0503..8fc8d77 100644
--- a/third_party/sqlite/patches/0020-Add-extra-tests-for-database-corruption-inside-defra.patch
+++ b/third_party/sqlite/patches/0020-Add-extra-tests-for-database-corruption-inside-defra.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Sat, 12 Jan 2019 17:56:03 -0800
-Subject: [PATCH 20/40] Add extra tests for database corruption inside
+Subject: [PATCH 20/45] Add extra tests for database corruption inside
  defragmentPage().
 
 This backports https://sqlite.org/src/info/997b65117f8c12db
diff --git a/third_party/sqlite/patches/0021-Fix-an-off-by-one-error-on-a-Goto-in-the-code-genera.patch b/third_party/sqlite/patches/0021-Fix-an-off-by-one-error-on-a-Goto-in-the-code-genera.patch
index 2ed2dd9b..50420f4c 100644
--- a/third_party/sqlite/patches/0021-Fix-an-off-by-one-error-on-a-Goto-in-the-code-genera.patch
+++ b/third_party/sqlite/patches/0021-Fix-an-off-by-one-error-on-a-Goto-in-the-code-genera.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Sat, 12 Jan 2019 18:04:58 -0800
-Subject: [PATCH 21/40] Fix an off-by-one error on a Goto in the code
+Subject: [PATCH 21/45] Fix an off-by-one error on a Goto in the code
  generator.
 
 This backports https://www.sqlite.org/src/info/e35eb8776ed539af
diff --git a/third_party/sqlite/patches/0022-Fix-overread-on-corrupted-btree-key.patch b/third_party/sqlite/patches/0022-Fix-overread-on-corrupted-btree-key.patch
index 315ba67c..ccf63d80 100644
--- a/third_party/sqlite/patches/0022-Fix-overread-on-corrupted-btree-key.patch
+++ b/third_party/sqlite/patches/0022-Fix-overread-on-corrupted-btree-key.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Sun, 13 Jan 2019 13:36:26 -0800
-Subject: [PATCH 22/40] Fix overread on corrupted btree key.
+Subject: [PATCH 22/45] Fix overread on corrupted btree key.
 
 This backports https://sqlite.org/src/info/160b1e31c0f27257
 
diff --git a/third_party/sqlite/patches/0023-Avoid-buffer-overreads-on-corrupted-database-files.patch b/third_party/sqlite/patches/0023-Avoid-buffer-overreads-on-corrupted-database-files.patch
index ea5da89..be3dc70 100644
--- a/third_party/sqlite/patches/0023-Avoid-buffer-overreads-on-corrupted-database-files.patch
+++ b/third_party/sqlite/patches/0023-Avoid-buffer-overreads-on-corrupted-database-files.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Sun, 13 Jan 2019 15:17:27 -0800
-Subject: [PATCH 23/40] Avoid buffer overreads on corrupted database files.
+Subject: [PATCH 23/45] Avoid buffer overreads on corrupted database files.
 
 This backports https://sqlite.org/src/info/32754ca6f86da816
 
diff --git a/third_party/sqlite/patches/0024-Fix-integer-overflow-while-running-PRAGMA-integrity_.patch b/third_party/sqlite/patches/0024-Fix-integer-overflow-while-running-PRAGMA-integrity_.patch
index 01912a0..350a7e7 100644
--- a/third_party/sqlite/patches/0024-Fix-integer-overflow-while-running-PRAGMA-integrity_.patch
+++ b/third_party/sqlite/patches/0024-Fix-integer-overflow-while-running-PRAGMA-integrity_.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Sun, 13 Jan 2019 16:12:08 -0800
-Subject: [PATCH 24/40] Fix integer overflow while running PRAGMA
+Subject: [PATCH 24/45] Fix integer overflow while running PRAGMA
  integrity_check.
 
 This backports https://sqlite.org/src/info/395599116d801324
diff --git a/third_party/sqlite/patches/0025-Improved-corruption-handling-while-balancing-pages.patch b/third_party/sqlite/patches/0025-Improved-corruption-handling-while-balancing-pages.patch
index d8e9a64a..db9b480 100644
--- a/third_party/sqlite/patches/0025-Improved-corruption-handling-while-balancing-pages.patch
+++ b/third_party/sqlite/patches/0025-Improved-corruption-handling-while-balancing-pages.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Sun, 13 Jan 2019 18:06:01 -0800
-Subject: [PATCH 25/40] Improved corruption handling while balancing pages.
+Subject: [PATCH 25/45] Improved corruption handling while balancing pages.
 
 This backports https://www.sqlite.org/src/info/35f04235c4775013
 
diff --git a/third_party/sqlite/patches/0026-Avoid-reading-off-the-front-of-a-page-buffer-when-ba.patch b/third_party/sqlite/patches/0026-Avoid-reading-off-the-front-of-a-page-buffer-when-ba.patch
index 3cbd94d8..66b2136 100644
--- a/third_party/sqlite/patches/0026-Avoid-reading-off-the-front-of-a-page-buffer-when-ba.patch
+++ b/third_party/sqlite/patches/0026-Avoid-reading-off-the-front-of-a-page-buffer-when-ba.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Sun, 13 Jan 2019 23:10:51 -0800
-Subject: [PATCH 26/40] Avoid reading off the front of a page buffer when
+Subject: [PATCH 26/45] Avoid reading off the front of a page buffer when
  balancing a corrupt btree.
 
 This backports https://www.sqlite.org/src/info/cb50509020d952fa
diff --git a/third_party/sqlite/patches/0027-Fix-MSAN-error-in-sqlite3VdbeRecordUnpack-on-a-corru.patch b/third_party/sqlite/patches/0027-Fix-MSAN-error-in-sqlite3VdbeRecordUnpack-on-a-corru.patch
index f3eecc7..c037075 100644
--- a/third_party/sqlite/patches/0027-Fix-MSAN-error-in-sqlite3VdbeRecordUnpack-on-a-corru.patch
+++ b/third_party/sqlite/patches/0027-Fix-MSAN-error-in-sqlite3VdbeRecordUnpack-on-a-corru.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Mon, 14 Jan 2019 12:32:04 -0800
-Subject: [PATCH 27/40] Fix MSAN error in sqlite3VdbeRecordUnpack() on a
+Subject: [PATCH 27/45] Fix MSAN error in sqlite3VdbeRecordUnpack() on a
  corrupt record.
 
 This backports https://www.sqlite.org/src/info/ddc3697efd61830f
diff --git a/third_party/sqlite/patches/0028-Fix-deleting-a-B-tree-entry-in-a-corrupt-database.patch b/third_party/sqlite/patches/0028-Fix-deleting-a-B-tree-entry-in-a-corrupt-database.patch
index a5de315..16d796b 100644
--- a/third_party/sqlite/patches/0028-Fix-deleting-a-B-tree-entry-in-a-corrupt-database.patch
+++ b/third_party/sqlite/patches/0028-Fix-deleting-a-B-tree-entry-in-a-corrupt-database.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Tue, 15 Jan 2019 20:35:58 -0800
-Subject: [PATCH 28/40] Fix deleting a B-tree entry in a corrupt database.
+Subject: [PATCH 28/45] Fix deleting a B-tree entry in a corrupt database.
 
 This backports https://sqlite.org/src/info/682053d1e603c21b
 
diff --git a/third_party/sqlite/patches/0029-Fix-sorting-results-with-SRT_EphemTab-and-a-LIMIT-cl.patch b/third_party/sqlite/patches/0029-Fix-sorting-results-with-SRT_EphemTab-and-a-LIMIT-cl.patch
index 34eb6b4..e10180d 100644
--- a/third_party/sqlite/patches/0029-Fix-sorting-results-with-SRT_EphemTab-and-a-LIMIT-cl.patch
+++ b/third_party/sqlite/patches/0029-Fix-sorting-results-with-SRT_EphemTab-and-a-LIMIT-cl.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Wed, 16 Jan 2019 12:46:56 -0800
-Subject: [PATCH 29/40] Fix sorting results with SRT_EphemTab and a LIMIT
+Subject: [PATCH 29/45] Fix sorting results with SRT_EphemTab and a LIMIT
  clause.
 
 This backports https://www.sqlite.org/src/info/49fcde2f1f981ac0
diff --git a/third_party/sqlite/patches/0030-Fix-detection-of-orphaned-and-malformed-autoindexes.patch b/third_party/sqlite/patches/0030-Fix-detection-of-orphaned-and-malformed-autoindexes.patch
index e2529c39..d9650ef 100644
--- a/third_party/sqlite/patches/0030-Fix-detection-of-orphaned-and-malformed-autoindexes.patch
+++ b/third_party/sqlite/patches/0030-Fix-detection-of-orphaned-and-malformed-autoindexes.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Wed, 16 Jan 2019 13:07:12 -0800
-Subject: [PATCH 30/40] Fix detection of orphaned and malformed autoindexes.
+Subject: [PATCH 30/45] Fix detection of orphaned and malformed autoindexes.
 
 This backports https://sqlite.org/src/info/10f9e39d6ed2413f
 
diff --git a/third_party/sqlite/patches/0031-Fix-potential-buffer-overread.patch b/third_party/sqlite/patches/0031-Fix-potential-buffer-overread.patch
index c933c09..7a6d22c 100644
--- a/third_party/sqlite/patches/0031-Fix-potential-buffer-overread.patch
+++ b/third_party/sqlite/patches/0031-Fix-potential-buffer-overread.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Fri, 18 Jan 2019 23:20:17 -0800
-Subject: [PATCH 31/40] Fix potential buffer overread.
+Subject: [PATCH 31/45] Fix potential buffer overread.
 
 This backports https://sqlite.org/src/info/8ba3d9f38090c4bb
 
diff --git a/third_party/sqlite/patches/0032-Fix-handling-negative-number-of-pages-database-field.patch b/third_party/sqlite/patches/0032-Fix-handling-negative-number-of-pages-database-field.patch
index 7111acbf..354febd3 100644
--- a/third_party/sqlite/patches/0032-Fix-handling-negative-number-of-pages-database-field.patch
+++ b/third_party/sqlite/patches/0032-Fix-handling-negative-number-of-pages-database-field.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Sat, 19 Jan 2019 02:33:28 -0800
-Subject: [PATCH 32/40] Fix handling negative "number-of-pages" database field.
+Subject: [PATCH 32/45] Fix handling negative "number-of-pages" database field.
 
 This backports https://www.sqlite.org/src/info/556dd8922f
 
diff --git a/third_party/sqlite/patches/0033-Fix-corner-case-in-inserting-null-into-integer-prima.patch b/third_party/sqlite/patches/0033-Fix-corner-case-in-inserting-null-into-integer-prima.patch
index 77dbd02..ccb3ad27 100644
--- a/third_party/sqlite/patches/0033-Fix-corner-case-in-inserting-null-into-integer-prima.patch
+++ b/third_party/sqlite/patches/0033-Fix-corner-case-in-inserting-null-into-integer-prima.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Sat, 19 Jan 2019 14:27:29 -0800
-Subject: [PATCH 33/40] Fix corner case in inserting null into integer primary
+Subject: [PATCH 33/45] Fix corner case in inserting null into integer primary
  key.
 
 This backports https://www.sqlite.org/src/info/9a425051e7ba59e7
diff --git a/third_party/sqlite/patches/0034-Fix-insert-infinite-recursion-on-some-corrupted-data.patch b/third_party/sqlite/patches/0034-Fix-insert-infinite-recursion-on-some-corrupted-data.patch
index 8ff6e69..e2b6f57 100644
--- a/third_party/sqlite/patches/0034-Fix-insert-infinite-recursion-on-some-corrupted-data.patch
+++ b/third_party/sqlite/patches/0034-Fix-insert-infinite-recursion-on-some-corrupted-data.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Sat, 19 Jan 2019 15:39:26 -0800
-Subject: [PATCH 34/40] Fix insert infinite recursion on some corrupted
+Subject: [PATCH 34/45] Fix insert infinite recursion on some corrupted
  databases.
 
 This backports https://www.sqlite.org/src/info/f31b3bd2a6a8aa35
diff --git a/third_party/sqlite/patches/0035-Fix-null-pointer-dereference-in-sqlite3ExprCompare.patch b/third_party/sqlite/patches/0035-Fix-null-pointer-dereference-in-sqlite3ExprCompare.patch
index 8afbbd9..9370b9c 100644
--- a/third_party/sqlite/patches/0035-Fix-null-pointer-dereference-in-sqlite3ExprCompare.patch
+++ b/third_party/sqlite/patches/0035-Fix-null-pointer-dereference-in-sqlite3ExprCompare.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Sat, 19 Jan 2019 15:48:54 -0800
-Subject: [PATCH 35/40] Fix null pointer dereference in sqlite3ExprCompare.
+Subject: [PATCH 35/45] Fix null pointer dereference in sqlite3ExprCompare.
 
 This backports https://www.sqlite.org/src/info/835e2cc55feea2f2
 
diff --git a/third_party/sqlite/patches/0036-Fix-NEVER-that-is-sometimes-true.patch b/third_party/sqlite/patches/0036-Fix-NEVER-that-is-sometimes-true.patch
index 9d1beda..ec775f9 100644
--- a/third_party/sqlite/patches/0036-Fix-NEVER-that-is-sometimes-true.patch
+++ b/third_party/sqlite/patches/0036-Fix-NEVER-that-is-sometimes-true.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Mon, 21 Jan 2019 14:26:47 -0800
-Subject: [PATCH 36/40] Fix NEVER that is sometimes true.
+Subject: [PATCH 36/45] Fix NEVER that is sometimes true.
 
 This backports https://sqlite.org/src/info/1201615cbbd30701
 
diff --git a/third_party/sqlite/patches/0037-Initialize-extra-bytes-allocated-for-saved-cursor-po.patch b/third_party/sqlite/patches/0037-Initialize-extra-bytes-allocated-for-saved-cursor-po.patch
index a281eb6..b0bd591 100644
--- a/third_party/sqlite/patches/0037-Initialize-extra-bytes-allocated-for-saved-cursor-po.patch
+++ b/third_party/sqlite/patches/0037-Initialize-extra-bytes-allocated-for-saved-cursor-po.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Mon, 21 Jan 2019 14:32:00 -0800
-Subject: [PATCH 37/40] Initialize extra bytes allocated for saved cursor
+Subject: [PATCH 37/45] Initialize extra bytes allocated for saved cursor
  position.
 
 This backports https://www.sqlite.org/src/info/2737564929e86ead
diff --git a/third_party/sqlite/patches/0038-Fix-leaks-caused-by-circular-references-in-vtable-sh.patch b/third_party/sqlite/patches/0038-Fix-leaks-caused-by-circular-references-in-vtable-sh.patch
index 4cf0bbb..4ef8d7f 100644
--- a/third_party/sqlite/patches/0038-Fix-leaks-caused-by-circular-references-in-vtable-sh.patch
+++ b/third_party/sqlite/patches/0038-Fix-leaks-caused-by-circular-references-in-vtable-sh.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Mon, 21 Jan 2019 14:57:17 -0800
-Subject: [PATCH 38/40] Fix leaks caused by circular references in vtable
+Subject: [PATCH 38/45] Fix leaks caused by circular references in vtable
  shadow tables.
 
 This backports https://sqlite.org/src/info/da587d18575ac06a
diff --git a/third_party/sqlite/patches/0039-Fix-overly-large-malloc-on-btree-corruption.patch b/third_party/sqlite/patches/0039-Fix-overly-large-malloc-on-btree-corruption.patch
index 83d6764..61736d5a 100644
--- a/third_party/sqlite/patches/0039-Fix-overly-large-malloc-on-btree-corruption.patch
+++ b/third_party/sqlite/patches/0039-Fix-overly-large-malloc-on-btree-corruption.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Mon, 21 Jan 2019 16:37:48 -0800
-Subject: [PATCH 39/40] Fix overly large malloc on btree corruption.
+Subject: [PATCH 39/45] Fix overly large malloc on btree corruption.
 
 This backports https://www.sqlite.org/src/info/3ecaaee69f49e43d
 
diff --git a/third_party/sqlite/patches/0040-Fix-null-pointer-access-on-corrupted-index-key.patch b/third_party/sqlite/patches/0040-Fix-null-pointer-access-on-corrupted-index-key.patch
index 8738610..9b636b9 100644
--- a/third_party/sqlite/patches/0040-Fix-null-pointer-access-on-corrupted-index-key.patch
+++ b/third_party/sqlite/patches/0040-Fix-null-pointer-access-on-corrupted-index-key.patch
@@ -1,7 +1,7 @@
 From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
 From: Victor Costan <pwnall@chromium.org>
 Date: Mon, 21 Jan 2019 22:29:21 -0800
-Subject: [PATCH 40/40] Fix null pointer access on corrupted index key.
+Subject: [PATCH 40/45] Fix null pointer access on corrupted index key.
 
 This backports https://www.sqlite.org/src/info/058a8006dceda78a
 
diff --git a/third_party/sqlite/patches/0041-Fix-INSERT-INTO-.-SELECT-FROM-on-corrupt-database.patch b/third_party/sqlite/patches/0041-Fix-INSERT-INTO-.-SELECT-FROM-on-corrupt-database.patch
new file mode 100644
index 0000000..f85e6dda
--- /dev/null
+++ b/third_party/sqlite/patches/0041-Fix-INSERT-INTO-.-SELECT-FROM-on-corrupt-database.patch
@@ -0,0 +1,35 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Victor Costan <pwnall@chromium.org>
+Date: Fri, 25 Jan 2019 03:19:04 -0800
+Subject: [PATCH 41/45] Fix INSERT INTO ... SELECT * FROM on corrupt database.
+
+This backports https://sqlite.org/src/info/db4b4c2c1e9f1ada
+
+Bug: 924866
+---
+ third_party/sqlite/src/src/btree.c | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
+index eaff20b24e2a..806ff751be4a 100644
+--- a/third_party/sqlite/src/src/btree.c
++++ b/third_party/sqlite/src/src/btree.c
+@@ -804,11 +804,12 @@ static int btreeMoveto(
+   UnpackedRecord *pIdxKey;   /* Unpacked index key */
+
+   if( pKey ){
++    KeyInfo *pKeyInfo = pCur->pKeyInfo;
+     assert( nKey==(i64)(int)nKey );
+-    pIdxKey = sqlite3VdbeAllocUnpackedRecord(pCur->pKeyInfo);
++    pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
+     if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
+-    sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
+-    if( pIdxKey->nField==0 ){
++    sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
++    if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
+       rc = SQLITE_CORRUPT_BKPT;
+       goto moveto_done;
+     }
+--
+2.18.0
+
diff --git a/third_party/sqlite/patches/0042-Fix-integer-overflow-in-sqlite3VdbeRecordUnpack.patch b/third_party/sqlite/patches/0042-Fix-integer-overflow-in-sqlite3VdbeRecordUnpack.patch
new file mode 100644
index 0000000..9015dcc
--- /dev/null
+++ b/third_party/sqlite/patches/0042-Fix-integer-overflow-in-sqlite3VdbeRecordUnpack.patch
@@ -0,0 +1,28 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Victor Costan <pwnall@chromium.org>
+Date: Fri, 25 Jan 2019 03:26:13 -0800
+Subject: [PATCH 42/45] Fix integer overflow in sqlite3VdbeRecordUnpack
+
+This backports https://sqlite.org/src/info/1b536f6fd8d58800
+
+Bug: 924811
+---
+ third_party/sqlite/src/src/vdbeaux.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/third_party/sqlite/src/src/vdbeaux.c b/third_party/sqlite/src/src/vdbeaux.c
+index 13b2e1ef7280..368ba9b23388 100644
+--- a/third_party/sqlite/src/src/vdbeaux.c
++++ b/third_party/sqlite/src/src/vdbeaux.c
+@@ -3710,7 +3710,7 @@ void sqlite3VdbeRecordUnpack(
+   UnpackedRecord *p      /* Populate this structure before returning. */
+ ){
+   const unsigned char *aKey = (const unsigned char *)pKey;
+-  int d;
++  u32 d;
+   u32 idx;                        /* Offset in aKey[] to read from */
+   u16 u;                          /* Unsigned loop counter */
+   u32 szHdr;
+--
+2.18.0
+
diff --git a/third_party/sqlite/patches/0043-Fix-memcpy-with-overlapping-buffers-in-corrupted-dat.patch b/third_party/sqlite/patches/0043-Fix-memcpy-with-overlapping-buffers-in-corrupted-dat.patch
new file mode 100644
index 0000000..b8eb52f
--- /dev/null
+++ b/third_party/sqlite/patches/0043-Fix-memcpy-with-overlapping-buffers-in-corrupted-dat.patch
@@ -0,0 +1,33 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Victor Costan <pwnall@chromium.org>
+Date: Fri, 25 Jan 2019 03:49:46 -0800
+Subject: [PATCH 43/45] Fix memcpy with overlapping buffers in corrupted
+ database.
+
+This backports https://www.sqlite.org/src/info/65ad6c55f1ba9bc2
+
+Bug: 924539
+---
+ third_party/sqlite/src/src/btree.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
+index 806ff751be4a..7ab155554f80 100644
+--- a/third_party/sqlite/src/src/btree.c
++++ b/third_party/sqlite/src/src/btree.c
+@@ -8249,7 +8249,11 @@ static int btreeOverwriteContent(
+     if( memcmp(pDest, ((u8*)pX->pData) + iOffset, iAmt)!=0 ){
+       int rc = sqlite3PagerWrite(pPage->pDbPage);
+       if( rc ) return rc;
+-      memcpy(pDest, ((u8*)pX->pData) + iOffset, iAmt);
++      /* In a corrupt database, it is possible for the source and destination
++      ** buffers to overlap.  This is harmless since the database is already
++      ** corrupt but it does cause valgrind and ASAN warnings.  So use
++      ** memmove(). */
++      memmove(pDest, ((u8*)pX->pData) + iOffset, iAmt);
+     }
+   }
+   return SQLITE_OK;
+--
+2.18.0
+
diff --git a/third_party/sqlite/patches/0044-Fix-null-dereference-in-UPDATE-OR-REPLACE.patch b/third_party/sqlite/patches/0044-Fix-null-dereference-in-UPDATE-OR-REPLACE.patch
new file mode 100644
index 0000000..9a55abd2
--- /dev/null
+++ b/third_party/sqlite/patches/0044-Fix-null-dereference-in-UPDATE-OR-REPLACE.patch
@@ -0,0 +1,38 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Victor Costan <pwnall@chromium.org>
+Date: Fri, 25 Jan 2019 03:57:33 -0800
+Subject: [PATCH 44/45] Fix null dereference in UPDATE OR REPLACE.
+
+This backports https://www.sqlite.org/src/info/e148cdad35520e66
+
+Bug: 923634
+---
+ third_party/sqlite/src/src/update.c | 5 ++---
+ 1 file changed, 2 insertions(+), 3 deletions(-)
+
+diff --git a/third_party/sqlite/src/src/update.c b/third_party/sqlite/src/src/update.c
+index b328d3b229bb..6e430e77fe18 100644
+--- a/third_party/sqlite/src/src/update.c
++++ b/third_party/sqlite/src/src/update.c
+@@ -354,6 +354,7 @@ void sqlite3Update(
+   ** being updated.  Fill in aRegIdx[] with a register number that will hold
+   ** the key for accessing each index.
+   */
++if( onError==OE_Replace ) bReplace = 1;
+   for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
+     int reg;
+     if( chngKey || hasFK>1 || pIdx==pPk
+@@ -367,9 +368,7 @@ void sqlite3Update(
+         if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){
+           reg = ++pParse->nMem;
+           pParse->nMem += pIdx->nColumn;
+-          if( (onError==OE_Replace)
+-           || (onError==OE_Default && pIdx->onError==OE_Replace)
+-          ){
++          if( onError==OE_Default && pIdx->onError==OE_Replace ){
+             bReplace = 1;
+           }
+           break;
+--
+2.18.0
+
diff --git a/third_party/sqlite/patches/0045-Fix-heap-buffer-overflow-while-rebalancing-corrupt-d.patch b/third_party/sqlite/patches/0045-Fix-heap-buffer-overflow-while-rebalancing-corrupt-d.patch
new file mode 100644
index 0000000..12891430
--- /dev/null
+++ b/third_party/sqlite/patches/0045-Fix-heap-buffer-overflow-while-rebalancing-corrupt-d.patch
@@ -0,0 +1,329 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Victor Costan <pwnall@chromium.org>
+Date: Fri, 25 Jan 2019 04:24:04 -0800
+Subject: [PATCH 45/45] Fix heap buffer overflow while rebalancing corrupt
+ database tree.
+
+This backports https://sqlite.org/src/info/12713f320b2c1def
+
+Bug: 924341
+---
+ third_party/sqlite/src/src/btree.c | 202 ++++++++++++++++++++++-------
+ 1 file changed, 152 insertions(+), 50 deletions(-)
+
+diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
+index 7ab155554f80..4bf2efca09d1 100644
+--- a/third_party/sqlite/src/src/btree.c
++++ b/third_party/sqlite/src/src/btree.c
+@@ -6693,9 +6693,72 @@ static void insertCell(
+   }
+ }
+
++/*
++** The following parameters determine how many adjacent pages get involved
++** in a balancing operation.  NN is the number of neighbors on either side
++** of the page that participate in the balancing operation.  NB is the
++** total number of pages that participate, including the target page and
++** NN neighbors on either side.
++**
++** The minimum value of NN is 1 (of course).  Increasing NN above 1
++** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
++** in exchange for a larger degradation in INSERT and UPDATE performance.
++** The value of NN appears to give the best results overall.
++**
++** (Later:) The description above makes it seem as if these values are
++** tunable - as if you could change them and recompile and it would all work.
++** But that is unlikely.  NB has been 3 since the inception of SQLite and
++** we have never tested any other value.
++*/
++#define NN 1             /* Number of neighbors on either side of pPage */
++#define NB 3             /* (NN*2+1): Total pages involved in the balance */
++
+ /*
+ ** A CellArray object contains a cache of pointers and sizes for a
+ ** consecutive sequence of cells that might be held on multiple pages.
++**
++** The cells in this array are the divider cell or cells from the pParent
++** page plus up to three child pages.  There are a total of nCell cells.
++**
++** pRef is a pointer to one of the pages that contributes cells.  This is
++** used to access information such as MemPage.intKey and MemPage.pBt->pageSize
++** which should be common to all pages that contribute cells to this array.
++**
++** apCell[] and szCell[] hold, respectively, pointers to the start of each
++** cell and the size of each cell.  Some of the apCell[] pointers might refer
++** to overflow cells.  In other words, some apCel[] pointers might not point
++** to content area of the pages.
++**
++** A szCell[] of zero means the size of that cell has not yet been computed.
++**
++** The cells come from as many as four different pages:
++**
++**             -----------
++**             | Parent  |
++**             -----------
++**            /     |     \
++**           /      |      \
++**  ---------   ---------   ---------
++**  |Child-1|   |Child-2|   |Child-3|
++**  ---------   ---------   ---------
++**
++** The order of cells is in the array is:
++**
++**       1.  All cells from Child-1 in order
++**       2.  The first divider cell from Parent
++**       3.  All cells from Child-2 in order
++**       4.  The second divider cell from Parent
++**       5.  All cells from Child-3 in order
++**
++** The apEnd[] array holds pointer to the end of page for Child-1, the
++** Parent, Child-2, the Parent (again), and Child-3.  The ixNx[] array
++** holds the number of cells contained in each of these 5 stages, and
++** all stages to the left.  Hence:
++**    ixNx[0] = Number of cells in Child-1.
++**    ixNx[1] = Number of cells in Child-1 plus 1 for first divider.
++**    ixNx[2] = Number of cells in Child-1 and Child-2 + 1 for 1st divider.
++**    ixNx[3] = Number of cells in Child-1 and Child-2 + both divider cells
++**    ixNx[4] = Total number of cells.
+ */
+ typedef struct CellArray CellArray;
+ struct CellArray {
+@@ -6703,6 +6766,8 @@ struct CellArray {
+   MemPage *pRef;          /* Reference page */
+   u8 **apCell;            /* All cells begin balanced */
+   u16 *szCell;            /* Local size of all cells in apCell[] */
++  u8 *apEnd[NB*2];        /* MemPage.aDataEnd values */
++  int ixNx[NB*2];         /* Index of at which we move to the next apEnd[] */
+ };
+
+ /*
+@@ -6753,37 +6818,58 @@ static u16 cachedCellSize(CellArray *p, int N){
+ ** responsibility of the caller to set it correctly.
+ */
+ static int rebuildPage(
+-  MemPage *pPg,                   /* Edit this page */
++  CellArray *pCArray,             /* Content to be added to page pPg */
++  int iFirst,                     /* First cell in pCArray to use */
+   int nCell,                      /* Final number of cells on page */
+-  u8 **apCell,                    /* Array of cells */
+-  u16 *szCell                     /* Array of cell sizes */
++  MemPage *pPg                    /* The page to be reconstructed */
+ ){
+   const int hdr = pPg->hdrOffset;          /* Offset of header on pPg */
+   u8 * const aData = pPg->aData;           /* Pointer to data for pPg */
+   const int usableSize = pPg->pBt->usableSize;
+   u8 * const pEnd = &aData[usableSize];
+-  int i;
++  int i = iFirst;                 /* Which cell to copy from pCArray*/
++  int j;                          /* Start of cell content area */
++  int iEnd = i+nCell;             /* Loop terminator */
+   u8 *pCellptr = pPg->aCellIdx;
+   u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager);
+   u8 *pData;
++  int k;                          /* Current slot in pCArray->apEnd[] */
++  u8 *pSrcEnd;                    /* Current pCArray->apEnd[k] value */
++
++  assert( i<iEnd );
++  j = get2byte(&aData[hdr+5]);
++  memcpy(&pTmp[j], &aData[j], usableSize - j);
+
+-  i = get2byte(&aData[hdr+5]);
+-  memcpy(&pTmp[i], &aData[i], usableSize - i);
++  for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
++  pSrcEnd = pCArray->apEnd[k];
+
+   pData = pEnd;
+-  for(i=0; i<nCell; i++){
+-    u8 *pCell = apCell[i];
++  while( 1/*exit by break*/ ){
++    u8 *pCell = pCArray->apCell[i];
++    u16 sz = pCArray->szCell[i];
++    assert( sz>0 );
+     if( SQLITE_WITHIN(pCell,aData,pEnd) ){
+-      if( ((uptr)(pCell+szCell[i]))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
++      if( ((uptr)(pCell+sz))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
+       pCell = &pTmp[pCell - aData];
++    }else if( (uptr)(pCell+sz)>(uptr)pSrcEnd
++           && (uptr)(pCell)<(uptr)pSrcEnd
++    ){
++      return SQLITE_CORRUPT_BKPT;
+     }
+-    pData -= szCell[i];
++
++    pData -= sz;
+     put2byte(pCellptr, (pData - aData));
+     pCellptr += 2;
+     if( pData < pCellptr ) return SQLITE_CORRUPT_BKPT;
+-    memcpy(pData, pCell, szCell[i]);
+-    assert( szCell[i]==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
+-    testcase( szCell[i]!=pPg->xCellSize(pPg,pCell) );
++    memcpy(pData, pCell, sz);
++    assert( sz==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
++    testcase( sz!=pPg->xCellSize(pPg,pCell) );
++    i++;
++    if( i>=iEnd ) break;
++    if( pCArray->ixNx[k]<=i ){
++      k++;
++      pSrcEnd = pCArray->apEnd[k];
++    }
+   }
+
+   /* The pPg->nFree field is now set incorrectly. The caller will fix it. */
+@@ -6798,12 +6884,11 @@ static int rebuildPage(
+ }
+
+ /*
+-** Array apCell[] contains nCell pointers to b-tree cells. Array szCell
+-** contains the size in bytes of each such cell. This function attempts to
+-** add the cells stored in the array to page pPg. If it cannot (because
+-** the page needs to be defragmented before the cells will fit), non-zero
+-** is returned. Otherwise, if the cells are added successfully, zero is
+-** returned.
++** The pCArray objects contains pointers to b-tree cells and the cell sizes.
++** This function attempts to add the cells stored in the array to page pPg.
++** If it cannot (because the page needs to be defragmented before the cells
++** will fit), non-zero is returned. Otherwise, if the cells are added
++** successfully, zero is returned.
+ **
+ ** Argument pCellptr points to the first entry in the cell-pointer array
+ ** (part of page pPg) to populate. After cell apCell[0] is written to the
+@@ -6831,12 +6916,17 @@ static int pageInsertArray(
+   int nCell,                      /* Number of cells to add to pPg */
+   CellArray *pCArray              /* Array of cells */
+ ){
+-  int i;
+-  u8 *aData = pPg->aData;
+-  u8 *pData = *ppData;
+-  int iEnd = iFirst + nCell;
++  int i = iFirst;                 /* Loop counter - cell index to insert */
++  u8 *aData = pPg->aData;         /* Complete page */
++  u8 *pData = *ppData;            /* Content area.  A subset of aData[] */
++  int iEnd = iFirst + nCell;      /* End of loop. One past last cell to ins */
++  int k;                          /* Current slot in pCArray->apEnd[] */
++  u8 *pEnd;                       /* Maximum extent of cell data */
+   assert( CORRUPT_DB || pPg->hdrOffset==0 );    /* Never called on page 1 */
+-  for(i=iFirst; i<iEnd; i++){
++  if( iEnd<=iFirst ) return 0;
++  for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
++  pEnd = pCArray->apEnd[k];
++  while( 1 /*Exit by break*/ ){
+     int sz, rc;
+     u8 *pSlot;
+     sz = cachedCellSize(pCArray, i);
+@@ -6851,20 +6941,33 @@ static int pageInsertArray(
+     assert( (pSlot+sz)<=pCArray->apCell[i]
+          || pSlot>=(pCArray->apCell[i]+sz)
+          || CORRUPT_DB );
++    if( (uptr)(pCArray->apCell[i]+sz)>(uptr)pEnd
++     && (uptr)(pCArray->apCell[i])<(uptr)pEnd
++    ){
++      assert( CORRUPT_DB );
++      (void)SQLITE_CORRUPT_BKPT;
++      return 1;
++    }
+     memmove(pSlot, pCArray->apCell[i], sz);
+     put2byte(pCellptr, (pSlot - aData));
+     pCellptr += 2;
++    i++;
++    if( i>=iEnd ) break;
++    if( pCArray->ixNx[k]<=i ){
++      k++;
++      pEnd = pCArray->apEnd[k];
++    }
+   }
+   *ppData = pData;
+   return 0;
+ }
+
+ /*
+-** Array apCell[] contains nCell pointers to b-tree cells. Array szCell
+-** contains the size in bytes of each such cell. This function adds the
+-** space associated with each cell in the array that is currently stored
+-** within the body of pPg to the pPg free-list. The cell-pointers and other
+-** fields of the page are not updated.
++** The pCArray object contains pointers to b-tree cells and their sizes.
++**
++** This function adds the space associated with each cell in the array
++** that is currently stored within the body of pPg to the pPg free-list.
++** The cell-pointers and other fields of the page are not updated.
+ **
+ ** This function returns the total number of cells added to the free-list.
+ */
+@@ -6914,9 +7017,9 @@ static int pageFreeArray(
+ }
+
+ /*
+-** apCell[] and szCell[] contains pointers to and sizes of all cells in the
+-** pages being balanced.  The current page, pPg, has pPg->nCell cells starting
+-** with apCell[iOld].  After balancing, this page should hold nNew cells
++** pCArray contains pointers to and sizes of all cells in the pages being
++** balanced.  The current page, pPg, has pPg->nCell cells starting with
++** pCArray->apCell[iOld].  After balancing, this page should hold nNew cells
+ ** starting at apCell[iNew].
+ **
+ ** This routine makes the necessary adjustments to pPg so that it contains
+@@ -7016,24 +7119,9 @@ static int editPage(
+  editpage_fail:
+   /* Unable to edit this page. Rebuild it from scratch instead. */
+   populateCellCache(pCArray, iNew, nNew);
+-  return rebuildPage(pPg, nNew, &pCArray->apCell[iNew], &pCArray->szCell[iNew]);
++  return rebuildPage(pCArray, iNew, nNew, pPg);
+ }
+
+-/*
+-** The following parameters determine how many adjacent pages get involved
+-** in a balancing operation.  NN is the number of neighbors on either side
+-** of the page that participate in the balancing operation.  NB is the
+-** total number of pages that participate, including the target page and
+-** NN neighbors on either side.
+-**
+-** The minimum value of NN is 1 (of course).  Increasing NN above 1
+-** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
+-** in exchange for a larger degradation in INSERT and UPDATE performance.
+-** The value of NN appears to give the best results overall.
+-*/
+-#define NN 1             /* Number of neighbors on either side of pPage */
+-#define NB (NN*2+1)      /* Total pages involved in the balance */
+-
+
+ #ifndef SQLITE_OMIT_QUICKBALANCE
+ /*
+@@ -7083,12 +7171,22 @@ static int balance_quick(MemPage *pParent, MemPage *pPage, u8 *pSpace){
+     u8 *pCell = pPage->apOvfl[0];
+     u16 szCell = pPage->xCellSize(pPage, pCell);
+     u8 *pStop;
++    CellArray b;
+
+     assert( sqlite3PagerIswriteable(pNew->pDbPage) );
+     assert( pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) );
+     zeroPage(pNew, PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF);
+-    rc = rebuildPage(pNew, 1, &pCell, &szCell);
+-    if( NEVER(rc) ) return rc;
++    b.nCell = 1;
++    b.pRef = pPage;
++    b.apCell = &pCell;
++    b.szCell = &szCell;
++    b.apEnd[0] = pPage->aDataEnd;
++    b.ixNx[0] = 2;
++    rc = rebuildPage(&b, 0, 1, pNew);
++    if( NEVER(rc) ){
++      releasePage(pNew);
++      return rc;
++    }
+     pNew->nFree = pBt->usableSize - pNew->cellOffset - 2 - szCell;
+
+     /* If this is an auto-vacuum database, update the pointer map
+@@ -7568,6 +7666,10 @@ static int balance_nonroot(
+   usableSpace = pBt->usableSize - 12 + leafCorrection;
+   for(i=0; i<nOld; i++){
+     MemPage *p = apOld[i];
++    b.apEnd[i*2] = p->aDataEnd;
++    b.apEnd[i*2+1] = pParent->aDataEnd;
++    b.ixNx[i*2] = cntOld[i];
++    b.ixNx[i*2+1] = cntOld[i]+1;
+     szNew[i] = usableSpace - p->nFree;
+     for(j=0; j<p->nOverflow; j++){
+       szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]);
+--
+2.18.0
+
diff --git a/third_party/sqlite/src/src/btree.c b/third_party/sqlite/src/src/btree.c
index eaff20b..4bf2efc 100644
--- a/third_party/sqlite/src/src/btree.c
+++ b/third_party/sqlite/src/src/btree.c
@@ -804,11 +804,12 @@
   UnpackedRecord *pIdxKey;   /* Unpacked index key */
 
   if( pKey ){
+    KeyInfo *pKeyInfo = pCur->pKeyInfo;
     assert( nKey==(i64)(int)nKey );
-    pIdxKey = sqlite3VdbeAllocUnpackedRecord(pCur->pKeyInfo);
+    pIdxKey = sqlite3VdbeAllocUnpackedRecord(pKeyInfo);
     if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
-    sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
-    if( pIdxKey->nField==0 ){
+    sqlite3VdbeRecordUnpack(pKeyInfo, (int)nKey, pKey, pIdxKey);
+    if( pIdxKey->nField==0 || pIdxKey->nField>pKeyInfo->nAllField ){
       rc = SQLITE_CORRUPT_BKPT;
       goto moveto_done;
     }
@@ -6693,8 +6694,71 @@
 }
 
 /*
+** The following parameters determine how many adjacent pages get involved
+** in a balancing operation.  NN is the number of neighbors on either side
+** of the page that participate in the balancing operation.  NB is the
+** total number of pages that participate, including the target page and
+** NN neighbors on either side.
+**
+** The minimum value of NN is 1 (of course).  Increasing NN above 1
+** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
+** in exchange for a larger degradation in INSERT and UPDATE performance.
+** The value of NN appears to give the best results overall.
+**
+** (Later:) The description above makes it seem as if these values are
+** tunable - as if you could change them and recompile and it would all work.
+** But that is unlikely.  NB has been 3 since the inception of SQLite and
+** we have never tested any other value.
+*/
+#define NN 1             /* Number of neighbors on either side of pPage */
+#define NB 3             /* (NN*2+1): Total pages involved in the balance */
+
+/*
 ** A CellArray object contains a cache of pointers and sizes for a
 ** consecutive sequence of cells that might be held on multiple pages.
+**
+** The cells in this array are the divider cell or cells from the pParent
+** page plus up to three child pages.  There are a total of nCell cells.
+**
+** pRef is a pointer to one of the pages that contributes cells.  This is
+** used to access information such as MemPage.intKey and MemPage.pBt->pageSize
+** which should be common to all pages that contribute cells to this array.
+**
+** apCell[] and szCell[] hold, respectively, pointers to the start of each
+** cell and the size of each cell.  Some of the apCell[] pointers might refer
+** to overflow cells.  In other words, some apCel[] pointers might not point
+** to content area of the pages.
+**
+** A szCell[] of zero means the size of that cell has not yet been computed.
+**
+** The cells come from as many as four different pages:
+**
+**             -----------
+**             | Parent  |
+**             -----------
+**            /     |     \
+**           /      |      \
+**  ---------   ---------   ---------
+**  |Child-1|   |Child-2|   |Child-3|
+**  ---------   ---------   ---------
+**
+** The order of cells is in the array is:
+**
+**       1.  All cells from Child-1 in order
+**       2.  The first divider cell from Parent
+**       3.  All cells from Child-2 in order
+**       4.  The second divider cell from Parent
+**       5.  All cells from Child-3 in order
+**
+** The apEnd[] array holds pointer to the end of page for Child-1, the
+** Parent, Child-2, the Parent (again), and Child-3.  The ixNx[] array
+** holds the number of cells contained in each of these 5 stages, and
+** all stages to the left.  Hence:
+**    ixNx[0] = Number of cells in Child-1.
+**    ixNx[1] = Number of cells in Child-1 plus 1 for first divider.
+**    ixNx[2] = Number of cells in Child-1 and Child-2 + 1 for 1st divider.
+**    ixNx[3] = Number of cells in Child-1 and Child-2 + both divider cells
+**    ixNx[4] = Total number of cells.
 */
 typedef struct CellArray CellArray;
 struct CellArray {
@@ -6702,6 +6766,8 @@
   MemPage *pRef;          /* Reference page */
   u8 **apCell;            /* All cells begin balanced */
   u16 *szCell;            /* Local size of all cells in apCell[] */
+  u8 *apEnd[NB*2];        /* MemPage.aDataEnd values */
+  int ixNx[NB*2];         /* Index of at which we move to the next apEnd[] */
 };
 
 /*
@@ -6752,37 +6818,58 @@
 ** responsibility of the caller to set it correctly.
 */
 static int rebuildPage(
-  MemPage *pPg,                   /* Edit this page */
+  CellArray *pCArray,             /* Content to be added to page pPg */
+  int iFirst,                     /* First cell in pCArray to use */
   int nCell,                      /* Final number of cells on page */
-  u8 **apCell,                    /* Array of cells */
-  u16 *szCell                     /* Array of cell sizes */
+  MemPage *pPg                    /* The page to be reconstructed */
 ){
   const int hdr = pPg->hdrOffset;          /* Offset of header on pPg */
   u8 * const aData = pPg->aData;           /* Pointer to data for pPg */
   const int usableSize = pPg->pBt->usableSize;
   u8 * const pEnd = &aData[usableSize];
-  int i;
+  int i = iFirst;                 /* Which cell to copy from pCArray*/
+  int j;                          /* Start of cell content area */
+  int iEnd = i+nCell;             /* Loop terminator */
   u8 *pCellptr = pPg->aCellIdx;
   u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager);
   u8 *pData;
+  int k;                          /* Current slot in pCArray->apEnd[] */
+  u8 *pSrcEnd;                    /* Current pCArray->apEnd[k] value */
 
-  i = get2byte(&aData[hdr+5]);
-  memcpy(&pTmp[i], &aData[i], usableSize - i);
+  assert( i<iEnd );
+  j = get2byte(&aData[hdr+5]);
+  memcpy(&pTmp[j], &aData[j], usableSize - j);
+
+  for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
+  pSrcEnd = pCArray->apEnd[k];
 
   pData = pEnd;
-  for(i=0; i<nCell; i++){
-    u8 *pCell = apCell[i];
+  while( 1/*exit by break*/ ){
+    u8 *pCell = pCArray->apCell[i];
+    u16 sz = pCArray->szCell[i];
+    assert( sz>0 );
     if( SQLITE_WITHIN(pCell,aData,pEnd) ){
-      if( ((uptr)(pCell+szCell[i]))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
+      if( ((uptr)(pCell+sz))>(uptr)pEnd ) return SQLITE_CORRUPT_BKPT;
       pCell = &pTmp[pCell - aData];
+    }else if( (uptr)(pCell+sz)>(uptr)pSrcEnd
+           && (uptr)(pCell)<(uptr)pSrcEnd
+    ){
+      return SQLITE_CORRUPT_BKPT;
     }
-    pData -= szCell[i];
+
+    pData -= sz;
     put2byte(pCellptr, (pData - aData));
     pCellptr += 2;
     if( pData < pCellptr ) return SQLITE_CORRUPT_BKPT;
-    memcpy(pData, pCell, szCell[i]);
-    assert( szCell[i]==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
-    testcase( szCell[i]!=pPg->xCellSize(pPg,pCell) );
+    memcpy(pData, pCell, sz);
+    assert( sz==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
+    testcase( sz!=pPg->xCellSize(pPg,pCell) );
+    i++;
+    if( i>=iEnd ) break;
+    if( pCArray->ixNx[k]<=i ){
+      k++;
+      pSrcEnd = pCArray->apEnd[k];
+    }
   }
 
   /* The pPg->nFree field is now set incorrectly. The caller will fix it. */
@@ -6797,12 +6884,11 @@
 }
 
 /*
-** Array apCell[] contains nCell pointers to b-tree cells. Array szCell
-** contains the size in bytes of each such cell. This function attempts to
-** add the cells stored in the array to page pPg. If it cannot (because
-** the page needs to be defragmented before the cells will fit), non-zero
-** is returned. Otherwise, if the cells are added successfully, zero is
-** returned.
+** The pCArray objects contains pointers to b-tree cells and the cell sizes.
+** This function attempts to add the cells stored in the array to page pPg.
+** If it cannot (because the page needs to be defragmented before the cells
+** will fit), non-zero is returned. Otherwise, if the cells are added
+** successfully, zero is returned.
 **
 ** Argument pCellptr points to the first entry in the cell-pointer array
 ** (part of page pPg) to populate. After cell apCell[0] is written to the
@@ -6830,12 +6916,17 @@
   int nCell,                      /* Number of cells to add to pPg */
   CellArray *pCArray              /* Array of cells */
 ){
-  int i;
-  u8 *aData = pPg->aData;
-  u8 *pData = *ppData;
-  int iEnd = iFirst + nCell;
+  int i = iFirst;                 /* Loop counter - cell index to insert */
+  u8 *aData = pPg->aData;         /* Complete page */
+  u8 *pData = *ppData;            /* Content area.  A subset of aData[] */
+  int iEnd = iFirst + nCell;      /* End of loop. One past last cell to ins */
+  int k;                          /* Current slot in pCArray->apEnd[] */
+  u8 *pEnd;                       /* Maximum extent of cell data */
   assert( CORRUPT_DB || pPg->hdrOffset==0 );    /* Never called on page 1 */
-  for(i=iFirst; i<iEnd; i++){
+  if( iEnd<=iFirst ) return 0;
+  for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
+  pEnd = pCArray->apEnd[k];
+  while( 1 /*Exit by break*/ ){
     int sz, rc;
     u8 *pSlot;
     sz = cachedCellSize(pCArray, i);
@@ -6850,20 +6941,33 @@
     assert( (pSlot+sz)<=pCArray->apCell[i]
          || pSlot>=(pCArray->apCell[i]+sz)
          || CORRUPT_DB );
+    if( (uptr)(pCArray->apCell[i]+sz)>(uptr)pEnd
+     && (uptr)(pCArray->apCell[i])<(uptr)pEnd
+    ){
+      assert( CORRUPT_DB );
+      (void)SQLITE_CORRUPT_BKPT;
+      return 1;
+    }
     memmove(pSlot, pCArray->apCell[i], sz);
     put2byte(pCellptr, (pSlot - aData));
     pCellptr += 2;
+    i++;
+    if( i>=iEnd ) break;
+    if( pCArray->ixNx[k]<=i ){
+      k++;
+      pEnd = pCArray->apEnd[k];
+    }
   }
   *ppData = pData;
   return 0;
 }
 
 /*
-** Array apCell[] contains nCell pointers to b-tree cells. Array szCell
-** contains the size in bytes of each such cell. This function adds the
-** space associated with each cell in the array that is currently stored
-** within the body of pPg to the pPg free-list. The cell-pointers and other
-** fields of the page are not updated.
+** The pCArray object contains pointers to b-tree cells and their sizes.
+**
+** This function adds the space associated with each cell in the array
+** that is currently stored within the body of pPg to the pPg free-list.
+** The cell-pointers and other fields of the page are not updated.
 **
 ** This function returns the total number of cells added to the free-list.
 */
@@ -6913,9 +7017,9 @@
 }
 
 /*
-** apCell[] and szCell[] contains pointers to and sizes of all cells in the
-** pages being balanced.  The current page, pPg, has pPg->nCell cells starting
-** with apCell[iOld].  After balancing, this page should hold nNew cells
+** pCArray contains pointers to and sizes of all cells in the pages being
+** balanced.  The current page, pPg, has pPg->nCell cells starting with
+** pCArray->apCell[iOld].  After balancing, this page should hold nNew cells
 ** starting at apCell[iNew].
 **
 ** This routine makes the necessary adjustments to pPg so that it contains
@@ -7015,24 +7119,9 @@
  editpage_fail:
   /* Unable to edit this page. Rebuild it from scratch instead. */
   populateCellCache(pCArray, iNew, nNew);
-  return rebuildPage(pPg, nNew, &pCArray->apCell[iNew], &pCArray->szCell[iNew]);
+  return rebuildPage(pCArray, iNew, nNew, pPg);
 }
 
-/*
-** The following parameters determine how many adjacent pages get involved
-** in a balancing operation.  NN is the number of neighbors on either side
-** of the page that participate in the balancing operation.  NB is the
-** total number of pages that participate, including the target page and
-** NN neighbors on either side.
-**
-** The minimum value of NN is 1 (of course).  Increasing NN above 1
-** (to 2 or 3) gives a modest improvement in SELECT and DELETE performance
-** in exchange for a larger degradation in INSERT and UPDATE performance.
-** The value of NN appears to give the best results overall.
-*/
-#define NN 1             /* Number of neighbors on either side of pPage */
-#define NB (NN*2+1)      /* Total pages involved in the balance */
-
 
 #ifndef SQLITE_OMIT_QUICKBALANCE
 /*
@@ -7082,12 +7171,22 @@
     u8 *pCell = pPage->apOvfl[0];
     u16 szCell = pPage->xCellSize(pPage, pCell);
     u8 *pStop;
+    CellArray b;
 
     assert( sqlite3PagerIswriteable(pNew->pDbPage) );
     assert( pPage->aData[0]==(PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF) );
     zeroPage(pNew, PTF_INTKEY|PTF_LEAFDATA|PTF_LEAF);
-    rc = rebuildPage(pNew, 1, &pCell, &szCell);
-    if( NEVER(rc) ) return rc;
+    b.nCell = 1;
+    b.pRef = pPage;
+    b.apCell = &pCell;
+    b.szCell = &szCell;
+    b.apEnd[0] = pPage->aDataEnd;
+    b.ixNx[0] = 2;
+    rc = rebuildPage(&b, 0, 1, pNew);
+    if( NEVER(rc) ){
+      releasePage(pNew);
+      return rc;
+    }
     pNew->nFree = pBt->usableSize - pNew->cellOffset - 2 - szCell;
 
     /* If this is an auto-vacuum database, update the pointer map
@@ -7567,6 +7666,10 @@
   usableSpace = pBt->usableSize - 12 + leafCorrection;
   for(i=0; i<nOld; i++){
     MemPage *p = apOld[i];
+    b.apEnd[i*2] = p->aDataEnd;
+    b.apEnd[i*2+1] = pParent->aDataEnd;
+    b.ixNx[i*2] = cntOld[i];
+    b.ixNx[i*2+1] = cntOld[i]+1;
     szNew[i] = usableSpace - p->nFree;
     for(j=0; j<p->nOverflow; j++){
       szNew[i] += 2 + p->xCellSize(p, p->apOvfl[j]);
@@ -8248,7 +8351,11 @@
     if( memcmp(pDest, ((u8*)pX->pData) + iOffset, iAmt)!=0 ){
       int rc = sqlite3PagerWrite(pPage->pDbPage);
       if( rc ) return rc;
-      memcpy(pDest, ((u8*)pX->pData) + iOffset, iAmt);
+      /* In a corrupt database, it is possible for the source and destination
+      ** buffers to overlap.  This is harmless since the database is already
+      ** corrupt but it does cause valgrind and ASAN warnings.  So use
+      ** memmove(). */
+      memmove(pDest, ((u8*)pX->pData) + iOffset, iAmt);
     }
   }
   return SQLITE_OK;
diff --git a/third_party/sqlite/src/src/update.c b/third_party/sqlite/src/src/update.c
index b328d3b..6e430e7 100644
--- a/third_party/sqlite/src/src/update.c
+++ b/third_party/sqlite/src/src/update.c
@@ -354,6 +354,7 @@
   ** being updated.  Fill in aRegIdx[] with a register number that will hold
   ** the key for accessing each index.
   */
+if( onError==OE_Replace ) bReplace = 1;
   for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
     int reg;
     if( chngKey || hasFK>1 || pIdx==pPk
@@ -367,9 +368,7 @@
         if( indexColumnIsBeingUpdated(pIdx, i, aXRef, chngRowid) ){
           reg = ++pParse->nMem;
           pParse->nMem += pIdx->nColumn;
-          if( (onError==OE_Replace)
-           || (onError==OE_Default && pIdx->onError==OE_Replace)
-          ){
+          if( onError==OE_Default && pIdx->onError==OE_Replace ){
             bReplace = 1;
           }
           break;
diff --git a/third_party/sqlite/src/src/vdbeaux.c b/third_party/sqlite/src/src/vdbeaux.c
index 13b2e1ef..368ba9b 100644
--- a/third_party/sqlite/src/src/vdbeaux.c
+++ b/third_party/sqlite/src/src/vdbeaux.c
@@ -3710,7 +3710,7 @@
   UnpackedRecord *p      /* Populate this structure before returning. */
 ){
   const unsigned char *aKey = (const unsigned char *)pKey;
-  int d;
+  u32 d;
   u32 idx;                        /* Offset in aKey[] to read from */
   u16 u;                          /* Unsigned loop counter */
   u32 szHdr;
diff --git a/tools/binary_size/libsupersize/models.py b/tools/binary_size/libsupersize/models.py
index 805973e..0b815598 100644
--- a/tools/binary_size/libsupersize/models.py
+++ b/tools/binary_size/libsupersize/models.py
@@ -974,7 +974,9 @@
       diff_status = None
       if symbol.IsDelta():
         diff_status = symbol.diff_status
-      return (symbol.object_path, name, diff_status)
+      if symbol.object_path or symbol.full_name.startswith('**'):
+        return (symbol.object_path, name, diff_status)
+      return (symbol.address, name, diff_status)
 
     # Use a custom factory to fill in name & template_name.
     def group_factory(token, symbols):
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index c995397..4c17ccfd 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -576,6 +576,11 @@
       label="Timeout during installability check, site status unknown"/>
 </enum>
 
+<enum name="AdFrameVisibility">
+  <int value="0" label="Display none"/>
+  <int value="1" label="Visible"/>
+</enum>
+
 <enum name="AdIsolatedInfo">
   <int value="0" label="Isolated ad request"/>
   <int value="1" label="Non-isolated ad request"/>
@@ -3800,9 +3805,9 @@
   <int value="167" label="RWH_INVALID_FRAME_TOKEN"/>
   <int value="168" label="RWH_BAD_FRAME_SINK_REQUEST"/>
   <int value="169" label="RWH_SURFACE_INVARIANTS_VIOLATION"/>
-  <int value="170" label="RFH_ILLEGAL_UPLOAD_PARAMS"/>
+  <int value="170" label="ILLEGAL_UPLOAD_PARAMS"/>
   <int value="171" label="RFH_BASE_URL_FOR_DATA_URL_SPECIFIED"/>
-  <int value="172" label="RFPH_ILLEGAL_UPLOAD_PARAMS"/>
+  <int value="172" label="OBSOLETE_RFPH_ILLEGAL_UPLOAD_PARAMS"/>
   <int value="173" label="OBSOLETE_SWDH_PROVIDER_CREATED_ILLEGAL_TYPE"/>
   <int value="174"
       label="OBSOLETE_SWDH_PROVIDER_CREATED_ILLEGAL_TYPE_NOT_WINDOW"/>
@@ -3835,10 +3840,10 @@
   <int value="198" label="SYNC_COMPOSITOR_NO_FUTURE_FRAME"/>
   <int value="199" label="SYNC_COMPOSITOR_NO_BEGIN_FRAME"/>
   <int value="200" label="WEBUI_BAD_HOST_ACCESS"/>
-  <int value="201" label="RFMF_BLOB_URL_TOKEN_FOR_NON_BLOB_URL"/>
+  <int value="201" label="OBSOLETE_RFMF_BLOB_URL_TOKEN_FOR_NON_BLOB_URL"/>
   <int value="202" label="PERMISSION_SERVICE_BAD_PERMISSION_DESCRIPTOR"/>
-  <int value="203" label="RFH_BLOB_URL_TOKEN_FOR_NON_BLOB_URL"/>
-  <int value="204" label="RFPH_BLOB_URL_TOKEN_FOR_NON_BLOB_URL"/>
+  <int value="203" label="BLOB_URL_TOKEN_FOR_NON_BLOB_URL"/>
+  <int value="204" label="OBSOLETE_RFPH_BLOB_URL_TOKEN_FOR_NON_BLOB_URL"/>
   <int value="205" label="RFH_ERROR_PROCESS_NON_ERROR_COMMIT"/>
   <int value="206" label="RFH_ERROR_PROCESS_NON_UNIQUE_ORIGIN_COMMIT"/>
   <int value="207" label="RFH_CANNOT_RENDER_FALLBACK_CONTENT"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 0ee88f4..bba2394f 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -1695,9 +1695,8 @@
 
 <histogram name="Android.DownloadManager.Filter"
     enum="AndroidDownloadFilterType">
-  <owner>dfalcantara@chromium.org</owner>
-  <owner>twellington@chromium.org</owner>
-  <owner>ianwen@chromium.org</owner>
+  <owner>dtrainor@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     Recorded when the user selects a filter from the Chrome download manager
     navigation drawer.
@@ -1708,6 +1707,7 @@
     enum="DownloadNotificationForegroundLifecycle">
   <owner>jming@chromium.org</owner>
   <owner>xingliu@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     Records instances where the foreground undergoes a lifecycle change (when
     the foreground starts, changes pinned notification, or stops).
@@ -1715,9 +1715,8 @@
 </histogram>
 
 <histogram name="Android.DownloadManager.InitialCount">
-  <owner>dfalcantara@chromium.org</owner>
-  <owner>twellington@chromium.org</owner>
-  <owner>ianwen@chromium.org</owner>
+  <owner>dtrainor@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     The number of non-incognito download items displayed when the download UI is
     initialized.
@@ -1725,7 +1724,8 @@
 </histogram>
 
 <histogram name="Android.DownloadManager.InitialCount.Viewed">
-  <owner>xingliu@chromium.org</owner>
+  <owner>dtrainor@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     The number of non-incognito download items displayed that are already viewed
     by the user at any time, recorded when the download UI is initialized.
@@ -1734,17 +1734,15 @@
 
 <histogram name="Android.DownloadManager.Item.OpenFailed"
     enum="AndroidDownloadFilterType">
-  <owner>dfalcantara@chromium.org</owner>
-  <owner>twellington@chromium.org</owner>
-  <owner>ianwen@chromium.org</owner>
+  <owner>dtrainor@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>Recorded when a download fails to open.</summary>
 </histogram>
 
 <histogram name="Android.DownloadManager.Item.OpenSucceeded"
     enum="AndroidDownloadFilterType">
-  <owner>dfalcantara@chromium.org</owner>
-  <owner>twellington@chromium.org</owner>
-  <owner>ianwen@chromium.org</owner>
+  <owner>dtrainor@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>Recorded when a download is opened.</summary>
 </histogram>
 
@@ -1752,23 +1750,27 @@
     enum="Android.DownloadManager.List.Section.Menu.Actions">
   <owner>dtrainor@chromium.org</owner>
   <owner>shaktisahu@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>Recorded when a menu action is taken on the images section.</summary>
 </histogram>
 
 <histogram name="Android.DownloadManager.List.View.Action"
     enum="Android.DownloadManager.List.View.Actions">
   <owner>dtrainor@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>The count of Download Home list entry actions taken.</summary>
 </histogram>
 
 <histogram name="Android.DownloadManager.Menu.Action"
     enum="Android.DownloadManager.Menu.Actions">
   <owner>dtrainor@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>The count of Download Home top level menu actions taken.</summary>
 </histogram>
 
 <histogram name="Android.DownloadManager.Menu.Delete.SelectedCount">
   <owner>dtrainor@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     The number of items selected when performing a multi-delete action.
   </summary>
@@ -1776,6 +1778,7 @@
 
 <histogram name="Android.DownloadManager.Menu.Share.SelectedCount">
   <owner>dtrainor@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     The number of items selected when performing a multi-share action.
   </summary>
@@ -1785,6 +1788,7 @@
     enum="DownloadNotificationInteractions">
   <owner>jming@chromium.org</owner>
   <owner>xingliu@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     Records instances where a user interacts with a download notification (ie.
     clicks on, pauses, resumes, cancels).
@@ -1795,6 +1799,7 @@
     enum="DownloadNotificationLaunchType">
   <owner>jming@chromium.org</owner>
   <owner>xingliu@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     Records instances when a notification is being launched for the first time
     or relaunched due to the need to dissociate the notification from the
@@ -1806,6 +1811,7 @@
     units="notifications">
   <owner>jming@chromium.org</owner>
   <owner>xingliu@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     Records the number of notifications that are already existing (presumably
     displayed) when a new notification is being launched to help understand the
@@ -1818,6 +1824,7 @@
     units="notifications">
   <owner>jming@chromium.org</owner>
   <owner>xingliu@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     Records the number of notifications that are already existing (presumably
     displayed) when a new notification is being launched to help understand the
@@ -1829,19 +1836,21 @@
 <histogram name="Android.DownloadManager.OpenSource.Audio"
     enum="AndroidDownloadOpenSource">
   <owner>xingliu@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>Records how users open audio download files on Android.</summary>
 </histogram>
 
 <histogram name="Android.DownloadManager.OpenSource.Video"
     enum="AndroidDownloadOpenSource">
   <owner>xingliu@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>Records how users open video download files on Android.</summary>
 </histogram>
 
 <histogram name="Android.DownloadManager.OtherExtensions.InitialCount"
     enum="AndroidDownloadExtensionType">
-  <owner>dfalcantara@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     The extension type for non-incognito download items that match the
     &quot;other&quot; filter type. Recorded when the download UI is initialized.
@@ -1850,8 +1859,8 @@
 
 <histogram name="Android.DownloadManager.OtherExtensions.OpenFailed"
     enum="AndroidDownloadExtensionType">
-  <owner>dfalcantara@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     The extension type for downloads that match the &quot;other&quot; filter
     type. Recorded when a download fails to open.
@@ -1860,8 +1869,8 @@
 
 <histogram name="Android.DownloadManager.OtherExtensions.OpenSucceeded"
     enum="AndroidDownloadExtensionType">
-  <owner>dfalcantara@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     The extension type for downloads that match the &quot;other&quot; filter
     type. Recorded when a download is opened.
@@ -1870,8 +1879,8 @@
 
 <histogram name="Android.DownloadManager.OtherExtensions.Share"
     enum="AndroidDownloadExtensionType">
-  <owner>dfalcantara@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     The extension type for downloads that match the &quot;other&quot; filter
     type. Recorded when downloads are shared through the download manager.
@@ -1882,6 +1891,7 @@
     enum="DownloadNotificationServiceStopped">
   <owner>jming@chromium.org</owner>
   <owner>xingliu@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     Records instances of DownloadForegroundService stops. The number of expected
     stops (stopped) and unexpected stops (task removed, low memory, etc) can be
@@ -1898,6 +1908,7 @@
     enum="DownloadNotificationServiceStopped">
   <owner>jming@chromium.org</owner>
   <owner>xingliu@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     Records instances of DownloadNotificationService stops. The number of
     expected stops (stopped) and unexpected stops (task removed, low memory,
@@ -1911,17 +1922,17 @@
 </histogram>
 
 <histogram name="Android.DownloadManager.Share.Count">
-  <owner>dfalcantara@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <owner>ianwen@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>The number of downloads shared at the same time.</summary>
 </histogram>
 
 <histogram name="Android.DownloadManager.Share.FileTypes"
     enum="AndroidDownloadFilterType">
-  <owner>dfalcantara@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <owner>ianwen@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     Recorded when downloads are shared through the download manager. A recorded
     value of &quot;All&quot; indicates that multiple types of downloads were
@@ -1931,6 +1942,7 @@
 
 <histogram name="Android.DownloadManager.ShowStorageInfo" enum="BooleanVisible">
   <owner>shaktisahu@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     Recorded when the user clicks the info button on download home to toggle the
     storage info. The state recorded is after the visibility is toggled.
@@ -1938,15 +1950,16 @@
 </histogram>
 
 <histogram name="Android.DownloadManager.SpaceUsed" units="%">
-  <owner>dfalcantara@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <owner>ianwen@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>The percentage of total storage downloads consume.</summary>
 </histogram>
 
 <histogram name="Android.DownloadManager.ViewRetentionTime.Audio"
     units="minutes" expires_after="2020-01-30">
   <owner>xingliu@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     The duration between when an audio file is downloaded and when the file is
     opened, only recorded when the user opens the file in download home UI.
@@ -1956,6 +1969,7 @@
 <histogram name="Android.DownloadManager.ViewRetentionTime.Video"
     units="minutes" expires_after="2020-01-30">
   <owner>xingliu@chromium.org</owner>
+  <owner>clank-downloads@google.com</owner>
   <summary>
     The duration between when a video file is downloaded and when the file is
     opened, only recorded when the user opens the file in download home UI.
@@ -2319,6 +2333,32 @@
   </summary>
 </histogram>
 
+<histogram name="Android.NativeBackgroundTask.TaskFinished"
+    enum="BackgroundTaskId" expires_after="2019-08-01">
+  <owner>mheikal@chromium.org</owner>
+  <owner>hanxi@chromium.org</owner>
+  <owner>hnakashima@chromium.org</owner>
+  <owner>yfriedman@chromium.org</owner>
+  <summary>
+    Records that a specific background task has finished cleanly (i.e. no
+    unexpected exits because of chrome crash or OOM). This includes tasks that
+    have been stopped due to timeout.
+  </summary>
+</histogram>
+
+<histogram name="Android.NativeBackgroundTask.TaskStarted"
+    enum="BackgroundTaskId" expires_after="2019-08-01">
+  <owner>mheikal@chromium.org</owner>
+  <owner>hanxi@chromium.org</owner>
+  <owner>hnakashima@chromium.org</owner>
+  <owner>yfriedman@chromium.org</owner>
+  <summary>
+    Records that a specific native background task has been started. This does
+    not consider tasks that are marked as DONE or RESCHEDULED before a call to
+    start native is made (regardless of whether native is already loaded).
+  </summary>
+</histogram>
+
 <histogram name="Android.NativeLibraryPreloader.Result.Browser"
     enum="NativeLibraryPreloaderResult">
   <owner>michaelbai@chromium.org</owner>
@@ -26166,7 +26206,7 @@
 <histogram name="EasyUnlock.AuthEvent.DidUserManuallyUnlockPhone"
     enum="EasyUnlockDidUserManuallyUnlockPhone">
   <owner>isherman@google.com</owner>
-  <owner>xiaowenx@google.com</owner>
+  <owner>hansberry@chromium.org</owner>
   <owner>xiyuan@google.com</owner>
   <summary>
     Upon a successful Smart Lock unlock or signin, records whether the user's
@@ -26178,7 +26218,7 @@
 
 <histogram name="EasyUnlock.AuthEvent.SignIn" enum="EasyUnlockAuthEvent">
   <owner>isherman@google.com</owner>
-  <owner>xiaowenx@google.com</owner>
+  <owner>hansberry@chromium.org</owner>
   <owner>xiyuan@google.com</owner>
   <summary>
     Measures the use of Smart Lock on the sign-in screen: records whether a
@@ -26191,7 +26231,7 @@
 <histogram name="EasyUnlock.AuthEvent.SignIn.Duration" units="ms">
   <owner>isherman@google.com</owner>
   <owner>tengs@google.com</owner>
-  <owner>xiaowenx@google.com</owner>
+  <owner>hansberry@chromium.org</owner>
   <summary>
     Measures the time elapsed between the user focusing their user pod and
     signing in using Smart Lock.
@@ -26200,7 +26240,7 @@
 
 <histogram name="EasyUnlock.AuthEvent.Unlock" enum="EasyUnlockAuthEvent">
   <owner>isherman@google.com</owner>
-  <owner>xiaowenx@google.com</owner>
+  <owner>hansberry@chromium.org</owner>
   <owner>xiyuan@google.com</owner>
   <summary>
     Measures the use of Smart Lock on the lock screen: records whether a Smart
@@ -26213,7 +26253,7 @@
 <histogram name="EasyUnlock.AuthEvent.Unlock.Duration" units="ms">
   <owner>isherman@google.com</owner>
   <owner>tengs@google.com</owner>
-  <owner>xiaowenx@google.com</owner>
+  <owner>hansberry@chromium.org</owner>
   <summary>
     Measures the time elapsed between the lock screen being shown and the user
     unlocking the device using Smart Lock. The lock screen is typically shown
@@ -26225,7 +26265,7 @@
 <histogram name="EasyUnlock.AuthProximity.RemoteDeviceModelHash"
     enum="EasyUnlockDeviceModelHash">
   <owner>tengs@chromium.org</owner>
-  <owner>xiaowenx@chromium.org</owner>
+  <owner>hansberry@chromium.org</owner>
   <summary>
     The hash of the phone model used to successfully sign in or unlock using
     Smart Lock.
@@ -26238,7 +26278,7 @@
 
 <histogram name="EasyUnlock.AuthProximity.RollingRssi" units="dBm">
   <owner>tengs@chromium.org</owner>
-  <owner>xiaowenx@chromium.org</owner>
+  <owner>hansberry@chromium.org</owner>
   <summary>
     Measures the exponentially weighted rolling average of the received signal
     strength indicator (RSSI) of the phone when the user successfully unlocks or
@@ -26261,7 +26301,7 @@
     Deprecated as of 11/2018.
   </obsolete>
   <owner>tengs@chromium.org</owner>
-  <owner>xiaowenx@chromium.org</owner>
+  <owner>hansberry@chromium.org</owner>
   <summary>
     Measures the time delta in milliseconds since the last zero RSSI value was
     read to when the user successfully unlocks or signs in using Smart Lock.
@@ -26281,7 +26321,7 @@
     Deprecated as of 11/2018.
   </obsolete>
   <owner>tengs@chromium.org</owner>
-  <owner>xiaowenx@chromium.org</owner>
+  <owner>hansberry@chromium.org</owner>
   <summary>
     Measures the difference between the current transmit power and the maximum
     transmit power of the local device when the user successfully unlocks or
@@ -26356,7 +26396,7 @@
 
 <histogram name="EasyUnlock.Setup.Devices.Count.Eligible">
   <owner>isherman@chromium.org</owner>
-  <owner>xiaowenx@chromium.org</owner>
+  <owner>hansberry@chromium.org</owner>
   <summary>
     The number of eligible devices that the CryptAuth server returns during the
     Smart Lock setup flow.
@@ -26370,7 +26410,7 @@
 
 <histogram name="EasyUnlock.Setup.Devices.Count.Ineligible">
   <owner>isherman@chromium.org</owner>
-  <owner>xiaowenx@chromium.org</owner>
+  <owner>hansberry@chromium.org</owner>
   <summary>
     The number of ineligible devices that the CryptAuth server returns during
     the Smart Lock setup flow.
@@ -26385,7 +26425,7 @@
 <histogram name="EasyUnlock.Setup.Devices.HasSecureScreenLock"
     enum="EasyUnlockHasSecureScreenLock">
   <owner>isherman@chromium.org</owner>
-  <owner>xiaowenx@chromium.org</owner>
+  <owner>hansberry@chromium.org</owner>
   <summary>
     Whether the user's phone has a secure screen lock installed. Recorded during
     Smart Lock setup, when the user's phone first connects to the Chromebook.
@@ -26395,7 +26435,7 @@
 <histogram name="EasyUnlock.Setup.Devices.HasTrustAgentEnabled"
     enum="EasyUnlockHasTrustAgentEnabled">
   <owner>isherman@chromium.org</owner>
-  <owner>xiaowenx@chromium.org</owner>
+  <owner>hansberry@chromium.org</owner>
   <summary>
     Whether the user's phone has a trust agent -- e.g. Smart Lock for Android --
     enabled. Recorded during Smart Lock (for Chrome) setup, when the user's
@@ -26413,7 +26453,7 @@
 <histogram name="EasyUnlock.Setup.Devices.IneligibilityReason"
     enum="EasyUnlockDeviceIneligibilityReason">
   <owner>isherman@chromium.org</owner>
-  <owner>xiaowenx@chromium.org</owner>
+  <owner>hansberry@chromium.org</owner>
   <summary>
     Records the most actionable reason why none of a user's devices were
     eligible as unlock keys for Smart Lock. This is recorded during the Smart
@@ -26451,7 +26491,7 @@
 <histogram name="EasyUnlock.Setup.PromoNotificationEvent"
     enum="EasyUnlockPromoNotificationEvent">
   <owner>isherman@chromium.org</owner>
-  <owner>xiaowenx@chromium.org</owner>
+  <owner>hansberry@chromium.org</owner>
   <summary>
     Measures user interactions with the Smart Lock promo notification.
   </summary>
@@ -26479,7 +26519,7 @@
   <obsolete>
     Deprecated 02/2015; replaced by EasyUnlock.AuthEvent.SignIn.
   </obsolete>
-  <owner>xiaowenx@google.com</owner>
+  <owner>hansberry@chromium.org</owner>
   <owner>xiyuan@google.com</owner>
   <summary>
     Measures the use of Easy sign-in: records whether an Easy sign-in login
@@ -26504,7 +26544,7 @@
 
 <histogram name="EasyUnlock.TrialRun.Events" enum="EasyUnlockTrialRunEvents">
   <owner>isherman@chromium.org</owner>
-  <owner>xiaowenx@chromium.org</owner>
+  <owner>hansberry@chromium.org</owner>
   <summary>
     Records when the Easy Unlock trial run is launched, and when the user
     attempts to click on the lock icon during the trial run.
@@ -34101,7 +34141,7 @@
 </histogram>
 
 <histogram name="Extensions.Messaging.MessageSize" units="bytes">
-  <owner>redevlin.cronin@chromium.org</owner>
+  <owner>rdevlin.cronin@chromium.org</owner>
   <summary>
     The size, in bytes, of a message sent from an extension using one of the
     messaging APIs (e.g. chrome.runtime.sendMessage). All message sizes are
@@ -36730,8 +36770,8 @@
 
 <histogram name="Fingerprint.Unlock.AttemptsCountBeforeSuccess" units="count"
     expires_after="2019-08-09">
-  <owner>xiaoyinh@chromium.org</owner>
-  <owner>zalcorn@chromium.org</owner>
+  <owner>yuluwu@chromium.org</owner>
+  <owner>jessejames@chromium.org</owner>
   <summary>
     Counts the number of fingerprint attempts until successful screen unlock.
   </summary>
@@ -36739,8 +36779,8 @@
 
 <histogram name="Fingerprint.Unlock.AuthSuccessful" enum="BooleanSuccess"
     expires_after="2019-08-09">
-  <owner>xiaoyinh@chromium.org</owner>
-  <owner>zalcorn@chromium.org</owner>
+  <owner>yuluwu@chromium.org</owner>
+  <owner>jessejames@chromium.org</owner>
   <summary>
     Counts the number of times that the fingerprint match successfully vs.
     rejected.
@@ -36750,16 +36790,16 @@
 <histogram name="Fingerprint.Unlock.EnrolledFingerCount" units="count"
     expires_after="2019-08-14">
   <owner>norvez@chromium.org</owner>
-  <owner>xiaoyinh@chromium.org</owner>
-  <owner>zalcorn@chromium.org</owner>
+  <owner>yuluwu@chromium.org</owner>
+  <owner>jessejames@chromium.org</owner>
   <summary>Counts the number of fingers enrolled by the user.</summary>
 </histogram>
 
 <histogram name="Fingerprint.Unlock.Match.Duration.Capture" units="ms"
     expires_after="2019-08-14">
   <owner>norvez@chromium.org</owner>
-  <owner>xiaoyinh@chromium.org</owner>
-  <owner>zalcorn@chromium.org</owner>
+  <owner>yuluwu@chromium.org</owner>
+  <owner>jessejames@chromium.org</owner>
   <summary>
     Measures the time it took to capture the fingerprint image in the 'match'
     case.
@@ -36769,8 +36809,8 @@
 <histogram name="Fingerprint.Unlock.Match.Duration.Matcher" units="ms"
     expires_after="2019-08-14">
   <owner>norvez@chromium.org</owner>
-  <owner>xiaoyinh@chromium.org</owner>
-  <owner>zalcorn@chromium.org</owner>
+  <owner>yuluwu@chromium.org</owner>
+  <owner>jessejames@chromium.org</owner>
   <summary>
     Measures the time it took to run matcher in the 'match' case.
   </summary>
@@ -36779,8 +36819,8 @@
 <histogram name="Fingerprint.Unlock.Match.Duration.Overall" units="ms"
     expires_after="2019-08-14">
   <owner>norvez@chromium.org</owner>
-  <owner>xiaoyinh@chromium.org</owner>
-  <owner>zalcorn@chromium.org</owner>
+  <owner>yuluwu@chromium.org</owner>
+  <owner>jessejames@chromium.org</owner>
   <summary>
     Measures the time it took between the detection of a finger and the 'match'
     event being sent to the AP.
@@ -36790,8 +36830,8 @@
 <histogram name="Fingerprint.Unlock.NoMatch.Duration.Capture" units="ms"
     expires_after="2019-08-14">
   <owner>norvez@chromium.org</owner>
-  <owner>xiaoyinh@chromium.org</owner>
-  <owner>zalcorn@chromium.org</owner>
+  <owner>yuluwu@chromium.org</owner>
+  <owner>jessejames@chromium.org</owner>
   <summary>
     Measures the time it took to capture the fingerprint image in the 'no-match'
     case.
@@ -36801,8 +36841,8 @@
 <histogram name="Fingerprint.Unlock.NoMatch.Duration.Matcher" units="ms"
     expires_after="2019-08-14">
   <owner>norvez@chromium.org</owner>
-  <owner>xiaoyinh@chromium.org</owner>
-  <owner>zalcorn@chromium.org</owner>
+  <owner>yuluwu@chromium.org</owner>
+  <owner>jessejames@chromium.org</owner>
   <summary>
     Measures the time it took to run the matcher in the 'no-match' case.
   </summary>
@@ -36811,8 +36851,8 @@
 <histogram name="Fingerprint.Unlock.NoMatch.Duration.Overall" units="ms"
     expires_after="2019-08-14">
   <owner>norvez@chromium.org</owner>
-  <owner>xiaoyinh@chromium.org</owner>
-  <owner>zalcorn@chromium.org</owner>
+  <owner>yuluwu@chromium.org</owner>
+  <owner>jessejames@chromium.org</owner>
   <summary>
     Measures the time it took between the detection of a finger and the
     'no-match' event being sent to the AP.
@@ -36821,8 +36861,8 @@
 
 <histogram name="Fingerprint.UnlockEnabled" enum="BooleanEnabled"
     expires_after="2019-08-09">
-  <owner>xiaoyinh@chromium.org</owner>
-  <owner>zalcorn@chromium.org</owner>
+  <owner>yuluwu@chromium.org</owner>
+  <owner>jessejames@chromium.org</owner>
   <summary>
     Track whether fingerprint is enabled to unlock the screen, when the user
     logs in.
@@ -41273,7 +41313,7 @@
 </histogram>
 
 <histogram name="InfoBar.Shown.Hidden" enum="InfoBarIdentifier">
-  <owner>dfalcantara@chromium.org</owner>
+  <owner>mdjones@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
     Records how many times a particular infobar was displayed in a hidden state
@@ -41286,7 +41326,7 @@
 </histogram>
 
 <histogram name="InfoBar.Shown.Hiding" enum="InfoBarIdentifier">
-  <owner>dfalcantara@chromium.org</owner>
+  <owner>mdjones@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
     Records how many times a particular infobar was visible and hiding a new
@@ -41295,7 +41335,7 @@
 </histogram>
 
 <histogram name="InfoBar.Shown.Visible" enum="InfoBarIdentifier">
-  <owner>dfalcantara@chromium.org</owner>
+  <owner>mdjones@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
     Records how many times a particular infobar was displayed in a visible state
@@ -42921,6 +42961,7 @@
 
 <histogram name="interstitial.decision" enum="SecurityInterstitialDecision">
   <owner>felt@chromium.org</owner>
+  <owner>carlosil@chromium.org</owner>
   <summary>
     User decision when presented with a security interstitial. As of M44,
     subresource interstitials were split into their own entries. As of M52,
@@ -42932,6 +42973,7 @@
 <histogram name="interstitial.decision.repeat_visit"
     enum="SecurityInterstitialDecision">
   <owner>felt@chromium.org</owner>
+  <owner>carlosil@chromium.org</owner>
   <summary>
     User decision when presented with a security interstitial, on a site that
     the user had previously visited. As of M44, subresource interstitials were
@@ -42944,6 +42986,7 @@
 <histogram name="interstitial.interaction"
     enum="SecurityInterstitialInteraction">
   <owner>felt@chromium.org</owner>
+  <owner>carlosil@chromium.org</owner>
   <summary>
     User interactions with a security interstitial. As of M44, subresource
     interstitials were split into their own entries. As of M52,
@@ -42983,6 +43026,7 @@
 
 <histogram name="interstitial.ssl.cause.nonoverridable" enum="SSLErrorCauses">
   <owner>felt@chromium.org</owner>
+  <owner>carlosil@chromium.org</owner>
   <summary>
     Possible non-attack causes of the non-overridable SSL interstitial. Many
     errors are not reported in this histogram and new errors may be added over
@@ -42998,6 +43042,7 @@
 
 <histogram name="interstitial.ssl.cause.overridable" enum="SSLErrorCauses">
   <owner>felt@chromium.org</owner>
+  <owner>carlosil@chromium.org</owner>
   <summary>
     Possible non-attack causes of the overridable SSL interstitial. Many errors
     are not reported in this histogram and new errors may be added over time,
@@ -43059,6 +43104,7 @@
 <histogram name="interstitial.ssl.connection_type"
     enum="ResourcePrefetchPredictorNetworkType">
   <owner>felt@chromium.org</owner>
+  <owner>carlosil@chromium.org</owner>
   <summary>
     The histogram shows the connection types associated with SSL warnings. E.g.,
     do more warnings occur on WiFi?
@@ -43191,6 +43237,7 @@
 
 <histogram name="interstitial.ssl_error_handler" enum="SSLErrorHandlerEvent">
   <owner>meacer@chromium.org</owner>
+  <owner>carlosil@chromium.org</owner>
   <summary>The type of action that the SSL error handler takes.</summary>
 </histogram>
 
@@ -43225,6 +43272,7 @@
 
 <histogram name="interstitial.ssl_error_type" enum="SSLErrorTypes">
   <owner>felt@chromium.org</owner>
+  <owner>carlosil@chromium.org</owner>
   <summary>
     The type of SSL error that the user encounters. This is recorded for all SSL
     warnings, regardless of whether they are overridable.
@@ -44080,7 +44128,7 @@
 
 <histogram name="Kiosk.LaunchType" enum="KioskLaunchType">
   <owner>xiyuan@chromium.org</owner>
-  <owner>blumberg@chromium.org</owner>
+  <owner>aghuie@chromium.org</owner>
   <summary>
     Records kiosk launches, whether it is an enterprise or consumer kiosk and
     whether it is an auto launch or manual launch.
@@ -45304,7 +45352,8 @@
 <histogram name="ManagedUsers.FilteringResult"
     enum="SupervisedUserSafetyFilterResult">
   <owner>treib@chromium.org</owner>
-  <owner>pam@chromium.org</owner>
+  <owner>escordeiro@chromium.org</owner>
+  <owner>menegola@chromium.org</owner>
   <summary>
     The counts of results from supervised user URL filtering. Each entry
     includes the outcome of the filter (i.e. allowed, blocked, or unknown) and
@@ -45315,7 +45364,8 @@
 
 <histogram name="ManagedUsers.SafeSitesDelay" units="ms">
   <owner>treib@chromium.org</owner>
-  <owner>pam@chromium.org</owner>
+  <owner>escordeiro@chromium.org</owner>
+  <owner>menegola@chromium.org</owner>
   <summary>
     The extra page load delays introduced by network requests due to the
     supervised user SafeSites feature, measured once per page load.
@@ -45325,7 +45375,8 @@
 <histogram name="ManagedUsers.SafetyFilter"
     enum="SupervisedUserSafetyFilterResult">
   <owner>treib@chromium.org</owner>
-  <owner>pam@chromium.org</owner>
+  <owner>escordeiro@chromium.org</owner>
+  <owner>menegola@chromium.org</owner>
   <summary>
     The counts of results from the supervised user safety filter. Each entry
     includes the outcome of the filter (i.e. allowed, blocked, or unknown) and
@@ -45336,9 +45387,9 @@
 </histogram>
 
 <histogram name="ManagedUsers.Whitelist.Count" units="whitelists">
-  <owner>bauerb@chromium.org</owner>
   <owner>treib@chromium.org</owner>
-  <owner>pam@chromium.org</owner>
+  <owner>escordeiro@chromium.org</owner>
+  <owner>menegola@chromium.org</owner>
   <summary>
     The number of whitelists installed for a supervised user. Recorded at every
     profile startup.
@@ -45346,9 +45397,9 @@
 </histogram>
 
 <histogram name="ManagedUsers.Whitelist.JsonParseDuration" units="ms">
-  <owner>bauerb@chromium.org</owner>
   <owner>treib@chromium.org</owner>
-  <owner>pam@chromium.org</owner>
+  <owner>escordeiro@chromium.org</owner>
+  <owner>menegola@chromium.org</owner>
   <summary>
     The total amount of time taken to parse the JSON contents of a whitelist out
     of process.
@@ -45356,18 +45407,18 @@
 </histogram>
 
 <histogram name="ManagedUsers.Whitelist.ReadDuration" units="ms">
-  <owner>bauerb@chromium.org</owner>
   <owner>treib@chromium.org</owner>
-  <owner>pam@chromium.org</owner>
+  <owner>escordeiro@chromium.org</owner>
+  <owner>menegola@chromium.org</owner>
   <summary>
     The amount of time taken to read a whitelist file from disk.
   </summary>
 </histogram>
 
 <histogram name="ManagedUsers.Whitelist.TotalLoadDuration" units="ms">
-  <owner>bauerb@chromium.org</owner>
   <owner>treib@chromium.org</owner>
-  <owner>pam@chromium.org</owner>
+  <owner>escordeiro@chromium.org</owner>
+  <owner>menegola@chromium.org</owner>
   <summary>
     The total amount of time taken to load a whitelist from disk and parse it,
     including jumps to the blocking thread.
@@ -71386,6 +71437,26 @@
   </summary>
 </histogram>
 
+<histogram name="NQE.CellularSignalStrength.AtECTComputation"
+    units="Signal Strength Level" expires_after="2019-12-01">
+  <owner>tbansal@chromium.org</owner>
+  <summary>
+    Cellular signal strength level reported by the device at the time of ECT
+    computation. Recorded only on cellular networks, and only when the value is
+    available. The value ranges between 0 and 4 (both inclusive).
+  </summary>
+</histogram>
+
+<histogram name="NQE.CellularSignalStrength.ECTReduction"
+    units="ECT level reduction" expires_after="2019-12-01">
+  <owner>tbansal@chromium.org</owner>
+  <summary>
+    Number of buckets by which effective connection type was reduced or capped
+    due to low cellular signal strength. Recorded only on cellular networks, and
+    only when the value of the effective connection typed is capped.
+  </summary>
+</histogram>
+
 <histogram name="NQE.CellularSignalStrength.LevelAvailable"
     enum="BooleanAvailable">
   <owner>tbansal@chromium.org</owner>
@@ -73672,7 +73743,6 @@
 </histogram>
 
 <histogram name="OfflinePages.SavePage.PercentLoaded" units="%">
-  <owner>dfalcantara@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <owner>ianwen@chromium.org</owner>
   <summary>
@@ -76139,6 +76209,41 @@
 </histogram>
 
 <histogram
+    name="PageLoad.Clients.Ads.FrameCounts.AdFrames.PerFrame.SmallestDimension"
+    units="pixels" expires_after="2020-01-23">
+  <owner>johnidel@chromium.org</owner>
+  <owner>jkarlin@chromium.org</owner>
+  <summary>
+    The smallest dimension of a root ad frame in pixels. Only recorded for ad
+    frames with non-zero total bytes. Recorded when the page is destroyed or
+    navigated.
+  </summary>
+</histogram>
+
+<histogram
+    name="PageLoad.Clients.Ads.FrameCounts.AdFrames.PerFrame.SqrtNumberOfPixels"
+    units="pixels" expires_after="2020-01-23">
+  <owner>johnidel@chromium.org</owner>
+  <owner>jkarlin@chromium.org</owner>
+  <summary>
+    The square root of the area of a root adframe in pixels. Only recorded for
+    ad frames with non-zero total bytes. Recorded when the page is destroyed or
+    navigated.
+  </summary>
+</histogram>
+
+<histogram name="PageLoad.Clients.Ads.FrameCounts.AdFrames.PerFrame.Visibility"
+    enum="AdFrameVisibility" expires_after="2020-01-23">
+  <owner>johnidel@chromium.org</owner>
+  <owner>jkarlin@chromium.org</owner>
+  <summary>
+    Whether or not the ad frame had a display: none style set, meaning it was
+    not visible to the user. Only recorded for ad frames with non-zero total
+    bytes. Recorded when the page is destroyed or navigated.
+  </summary>
+</histogram>
+
+<histogram
     name="PageLoad.Clients.Ads.Google.FrameCounts.MainFrameParent.AdFrames"
     units="Frames">
   <obsolete>
@@ -82746,7 +82851,6 @@
   <owner>kouhei@chromium.org</owner>
   <owner>sonnyrao@chromium.org</owner>
   <owner>semenzato@chromium.org</owner>
-  <owner>bccheng@chromium.org</owner>
   <summary>
     Various memory usage % of total memory on Chrome OS devices (snapshotted
     every 30s).
@@ -82758,7 +82862,6 @@
   <owner>kouhei@chromium.org</owner>
   <owner>sonnyrao@chromium.org</owner>
   <owner>semenzato@chromium.org</owner>
-  <owner>bccheng@chromium.org</owner>
   <summary>
     Various memory usage amount on Chrome OS devices (snapshotted every 30s).
   </summary>
@@ -90797,7 +90900,7 @@
 </histogram>
 
 <histogram name="ReadingList.Unread.AgeOnDeletion" units="hours">
-  <owner>gmabard@chromium.org</owner>
+  <owner>gambard@chromium.org</owner>
   <summary>
     Time since the creation of the unread reading list entry getting deleted.
   </summary>
@@ -100723,7 +100826,6 @@
 <histogram name="Search.ContextualSearchMandatoryPromoOutcomeByGesture"
     enum="ContextualSearchOutcomeByGesture">
   <owner>donnd@chromium.org</owner>
-  <owner>pedrosimonetti@chromium.org</owner>
   <owner>twellington@chromium.org</owner>
   <summary>
     The outcome of the mandatory Promo broken down by original triggering
@@ -121208,14 +121310,14 @@
     Deprecated 5/2017 in Issue 704922. Replaced by
     V8.ArrayBufferLargeAllocations.
   </obsolete>
-  <owner>bradnelson@chromium.org</owner>
+  <owner>gdeepti@chromium.org</owner>
   <owner>titzer@chromium.org</owner>
   <owner>kschimpf@chromium.org</owner>
   <summary>Number of bytes requested in an array buffer allocation.</summary>
 </histogram>
 
 <histogram name="V8.ArrayBufferLargeAllocations" units="MB">
-  <owner>bradnelson@chromium.org</owner>
+  <owner>gdeepti@chromium.org</owner>
   <owner>titzer@chromium.org</owner>
   <summary>
     Number of bytes requested in array buffer allocations greater than one
@@ -121224,13 +121326,13 @@
 </histogram>
 
 <histogram name="V8.ArrayBufferNewSizeFailures" units="MB">
-  <owner>bradnelson@chromium.org</owner>
+  <owner>gdeepti@chromium.org</owner>
   <owner>titzer@chromium.org</owner>
   <summary>Array buffer sizes for which V8 failed to allocate memory.</summary>
 </histogram>
 
 <histogram name="V8.AsmModuleSizeBytes" units="bytes">
-  <owner>bradnelson@chromium.org</owner>
+  <owner>mstarzinger@chromium.org</owner>
   <owner>titzer@chromium.org</owner>
   <owner>aseemgarg@chromium.org</owner>
   <summary>Size of asm.js module (in asm.js format).</summary>
@@ -122300,7 +122402,7 @@
 </histogram>
 
 <histogram name="V8.SharedArrayAllocationSizes" units="MB">
-  <owner>bradnelson@chromium.org</owner>
+  <owner>gdeepti@chromium.org</owner>
   <owner>titzer@chromium.org</owner>
   <summary>
     Number of megabytes requested in shared array buffer allocations.
@@ -124248,7 +124350,8 @@
 
 <histogram name="Webapp.Install.InstallEvent" enum="WebappInstallSource">
   <owner>dominickn@chromium.org</owner>
-  <owner>mcgreevy@chromium.org</owner>
+  <owner>loyso@chromium.org</owner>
+  <owner>calamity@chromium.org</owner>
   <summary>
     Records the mechanism and source from which a web app installation was
     triggered, regardless of whether the installation was successful.
@@ -129315,7 +129418,8 @@
 </histogram>
 
 <histogram name="WebRTC.webkitApiCount" enum="WebRTCAPIName">
-  <owner>perkj@chromium.org</owner>
+  <owner>guidou@chromium.org</owner>
+  <owner>hbos@chromium.org</owner>
   <owner>mcasas@chromium.org</owner>
   <owner>emircan@chromium.org</owner>
   <summary>Counts number of calls to WebRTC APIs from JavaScript.</summary>
@@ -130370,6 +130474,15 @@
   </summary>
 </histogram>
 
+<histogram name="XHR.Sync.PageDismissal_forbidden" enum="XHRPageDismissalState"
+    expires_after="2019-06-01">
+  <owner>kdillon@chromium.org, panicker@chromium.org</owner>
+  <summary>
+    Records occurence of sync XHR requests during page dismissal state (unload,
+    beforeunload, pagehide etc) that were forbidden.
+  </summary>
+</histogram>
+
 <histogram name="XR.RuntimeAvailable" enum="XRRuntimeAvailable">
   <owner>billorr@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 99e79e0..807e80c9 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -1711,6 +1711,20 @@
   </metric>
 </event>
 
+<event name="PageForegroundSession">
+  <owner>sullivan@chromium.org</owner>
+  <summary>
+    Total time in foreground in milliseconds, recorded each time the page is
+    backgrounded. May be recorded multiple times for a single page visit.
+  </summary>
+  <metric name="ForegroundDuration">
+    <summary>
+      Total time in foreground in milliseconds, recorded each time the page is
+      backgrounded.
+    </summary>
+  </metric>
+</event>
+
 <event name="Intervention.DocumentWrite.ScriptBlock" singular="True">
   <owner>bmcquade@chromium.org</owner>
   <summary>
diff --git a/tools/vscode/settings.json5 b/tools/vscode/settings.json5
index 5fd0949..bfdcbac 100644
--- a/tools/vscode/settings.json5
+++ b/tools/vscode/settings.json5
@@ -57,7 +57,7 @@
   // Optional: Highlight current line at the left of the editor.
   // "editor.renderLineHighlight": "gutter",
   // Optional: Don't automatically add closing brackets. It gets in the way.
-  // "editor.autoClosingBrackets": false,
+  // "editor.autoClosingBrackets": "never",
   // Optional: Enable a tiny 30k feet view of your doc.
   // "editor.minimap.enabled": true,
   // "editor.minimap.maxColumn": 80,
@@ -70,4 +70,3 @@
   // Optional: Same for files opened from quick open (Ctrl+P).
   //"workbench.editor.enablePreviewFromQuickOpen": false,
 }
-
diff --git a/tools/win/sizeviewer/README.chromium b/tools/win/sizeviewer/README.chromium
index d891769..03237752f 100644
--- a/tools/win/sizeviewer/README.chromium
+++ b/tools/win/sizeviewer/README.chromium
@@ -1,5 +1,6 @@
-code_tally.exe binary from
-http://syzygy-archive.commondatastorage.googleapis.com/index.html?path=builds/official/1626/
+code_tally.exe binary is in the experimental folder in binaries.zip, available
+at:
+https://syzygy-archive.commondatastorage.googleapis.com/index.html?path=builds/official/1626/
 
 favicon.png is chart_pie.png unmodified from
 http://www.famfamfam.com/lab/icons/silk/
diff --git a/ui/accessibility/ax_role_properties.cc b/ui/accessibility/ax_role_properties.cc
index a20ac83..ef06d922 100644
--- a/ui/accessibility/ax_role_properties.cc
+++ b/ui/accessibility/ax_role_properties.cc
@@ -66,6 +66,7 @@
     case ax::mojom::Role::kComboBoxMenuButton:
     case ax::mojom::Role::kGrid:
     case ax::mojom::Role::kListBox:
+    case ax::mojom::Role::kListGrid:
     case ax::mojom::Role::kMenu:
     case ax::mojom::Role::kMenuBar:
     case ax::mojom::Role::kRadioGroup:
@@ -87,6 +88,7 @@
     case ax::mojom::Role::kComboBoxMenuButton:
     case ax::mojom::Role::kDisclosureTriangle:
     case ax::mojom::Role::kListBox:
+    case ax::mojom::Role::kListGrid:
     case ax::mojom::Role::kMenu:
     case ax::mojom::Role::kMenuBar:
     case ax::mojom::Role::kMenuButton:
@@ -200,6 +202,7 @@
     case ax::mojom::Role::kDocBibliography:
     case ax::mojom::Role::kList:
     case ax::mojom::Role::kListBox:
+    case ax::mojom::Role::kListGrid:
       return true;
     default:
       return false;
@@ -264,16 +267,29 @@
 
 bool IsSetLike(const ax::mojom::Role role) {
   switch (role) {
+    case ax::mojom::Role::kDescriptionList:
+    case ax::mojom::Role::kDirectory:
+    case ax::mojom::Role::kDocBibliography:
     case ax::mojom::Role::kFeed:
-    case ax::mojom::Role::kList:
     case ax::mojom::Role::kGroup:
+    case ax::mojom::Role::kList:
+    case ax::mojom::Role::kListBox:
+    case ax::mojom::Role::kListGrid:
     case ax::mojom::Role::kMenu:
     case ax::mojom::Role::kMenuBar:
-    case ax::mojom::Role::kTabList:
-    case ax::mojom::Role::kTree:
-    case ax::mojom::Role::kListBox:
     case ax::mojom::Role::kMenuListPopup:
     case ax::mojom::Role::kRadioGroup:
+    case ax::mojom::Role::kTabList:
+    case ax::mojom::Role::kTree:
+      return true;
+    default:
+      return false;
+  }
+}
+
+bool IsStaticList(const ax::mojom::Role role) {
+  switch (role) {
+    case ax::mojom::Role::kList:
     case ax::mojom::Role::kDescriptionList:
       return true;
     default:
@@ -374,14 +390,4 @@
   }
 }
 
-bool IsStaticList(const ax::mojom::Role role) {
-  switch (role) {
-    case ax::mojom::Role::kList:
-    case ax::mojom::Role::kDescriptionList:
-      return true;
-    default:
-      return false;
-  }
-}
-
 }  // namespace ui
diff --git a/ui/accessibility/ax_role_properties.h b/ui/accessibility/ax_role_properties.h
index d9a1e73..dc056e7 100644
--- a/ui/accessibility/ax_role_properties.h
+++ b/ui/accessibility/ax_role_properties.h
@@ -69,6 +69,9 @@
 // can hold set_size values.
 AX_EXPORT bool IsSetLike(const ax::mojom::Role role);
 
+// Returns true if the provided role belongs to a non-interactive list.
+AX_EXPORT bool IsStaticList(const ax::mojom::Role role);
+
 // Returns true if the provided role belongs to a table header.
 AX_EXPORT bool IsTableHeader(ax::mojom::Role role);
 
@@ -91,8 +94,6 @@
 // Automation.
 AX_EXPORT bool IsUIASelectable(const ax::mojom::Role role);
 
-AX_EXPORT bool IsStaticList(const ax::mojom::Role role);
-
 }  // namespace ui
 
 #endif  // UI_ACCESSIBILITY_AX_ROLE_PROPERTIES_H_
diff --git a/ui/android/delegated_frame_host_android_unittest.cc b/ui/android/delegated_frame_host_android_unittest.cc
index 994438f..ad53248 100644
--- a/ui/android/delegated_frame_host_android_unittest.cc
+++ b/ui/android/delegated_frame_host_android_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "ui/android/delegated_frame_host_android.h"
 #include "base/android/build_info.h"
+#include "base/bind_helpers.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/test_mock_time_task_runner.h"
 #include "cc/layers/layer.h"
diff --git a/ui/aura/mus/input_method_mus.cc b/ui/aura/mus/input_method_mus.cc
index e4fd043..c96796e 100644
--- a/ui/aura/mus/input_method_mus.cc
+++ b/ui/aura/mus/input_method_mus.cc
@@ -7,6 +7,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "services/ws/public/mojom/constants.mojom.h"
 #include "services/ws/public/mojom/ime/ime.mojom.h"
 #include "services/ws/public/mojom/window_tree_constants.mojom.h"
diff --git a/ui/aura/native_window_occlusion_tracker_win.h b/ui/aura/native_window_occlusion_tracker_win.h
index 238e4bf9..a6a5ae5 100644
--- a/ui/aura/native_window_occlusion_tracker_win.h
+++ b/ui/aura/native_window_occlusion_tracker_win.h
@@ -14,6 +14,7 @@
 #include "base/containers/flat_set.h"
 #include "base/sequenced_task_runner.h"
 #include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "ui/aura/aura_export.h"
 #include "ui/aura/window.h"
 #include "ui/aura/window_observer.h"
diff --git a/ui/base/cocoa/remote_accessibility_api.mm b/ui/base/cocoa/remote_accessibility_api.mm
index 8a6d9d1..b901d78 100644
--- a/ui/base/cocoa/remote_accessibility_api.mm
+++ b/ui/base/cocoa/remote_accessibility_api.mm
@@ -18,6 +18,8 @@
 base::scoped_nsobject<NSAccessibilityRemoteUIElement>
 RemoteAccessibility::GetRemoteElementFromToken(
     const std::vector<uint8_t>& token) {
+  if (token.empty())
+    return base::scoped_nsobject<NSAccessibilityRemoteUIElement>();
   base::scoped_nsobject<NSData> data(
       [[NSData alloc] initWithBytes:token.data() length:token.size()]);
   return base::scoped_nsobject<NSAccessibilityRemoteUIElement>(
diff --git a/ui/compositor/test/in_process_context_factory.cc b/ui/compositor/test/in_process_context_factory.cc
index c5c2a15b..598dd8b 100644
--- a/ui/compositor/test/in_process_context_factory.cc
+++ b/ui/compositor/test/in_process_context_factory.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/memory/ptr_util.h"
diff --git a/ui/display/manager/display_configurator.cc b/ui/display/manager/display_configurator.cc
index ac52aff..4d184bb 100644
--- a/ui/display/manager/display_configurator.cc
+++ b/ui/display/manager/display_configurator.cc
@@ -8,6 +8,7 @@
 #include <utility>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/logging.h"
 #include "base/macros.h"
diff --git a/ui/display/manager/display_manager.cc b/ui/display/manager/display_manager.cc
index e3df93b..43d520a6 100644
--- a/ui/display/manager/display_manager.cc
+++ b/ui/display/manager/display_manager.cc
@@ -2198,6 +2198,12 @@
   if (num_connected_displays_ <= 1)
     return;
 
+  // External displays mirrored because of forced tablet mode mirroring should
+  // not be considered candidates for restoring their mirrored state.
+  // https://crbug.com/919994.
+  if (layout_store_->forced_mirror_mode_for_tablet())
+    return;
+
   for (auto id : GetCurrentDisplayIdList()) {
     if (Display::IsInternalDisplayId(id))
       continue;
diff --git a/ui/display/manager/touch_device_manager.cc b/ui/display/manager/touch_device_manager.cc
index 41606b4e..1c87c85 100644
--- a/ui/display/manager/touch_device_manager.cc
+++ b/ui/display/manager/touch_device_manager.cc
@@ -35,10 +35,17 @@
 
   for (const auto& component : components) {
     if (base::StartsWith(component, "usb",
-                         base::CompareCase::INSENSITIVE_ASCII))
+                         base::CompareCase::INSENSITIVE_ASCII)) {
+      return true;
+    }
+
+    // TODO(malaykeshav): When evdi starts registering with the usb subsystem
+    // in the kernel, this would no longer be needed. All evdi displays are USB
+    // right now. This might change in the future however.
+    // See https://crbug.com/923165 for more info.
+    if (base::StartsWith(component, "evdi", base::CompareCase::SENSITIVE))
       return true;
   }
-
   return false;
 }
 
diff --git a/ui/events/event_rewriter.cc b/ui/events/event_rewriter.cc
index 55c20e21..d9efe7e 100644
--- a/ui/events/event_rewriter.cc
+++ b/ui/events/event_rewriter.cc
@@ -4,99 +4,13 @@
 
 #include "ui/events/event_rewriter.h"
 
-#include <utility>
-
 #include "ui/events/event_source.h"
 
 namespace ui {
 
-namespace {
-
-ui::EventDispatchDetails DispatcherDestroyed() {
-  ui::EventDispatchDetails details;
-  details.dispatcher_destroyed = true;
-  return details;
-}
-
-}  // anonymous namespace
-
-// Temporary fallback implementation, in terms of the old API,
-// factored out of EventSource::SendEventToSinkFromRewriter().
-// TODO(kpschoedel): Remove along with old API.
-EventDispatchDetails EventRewriter::RewriteEvent(
-    const Event& event,
-    const base::WeakPtr<Continuation> continuation) {
-  std::unique_ptr<Event> rewritten_event;
-  EventRewriteStatus status = RewriteEvent(event, &rewritten_event);
-  if (status == EVENT_REWRITE_DISCARD) {
-    CHECK(!rewritten_event);
-    return continuation->DiscardEvent();
-  }
-  if (status == EVENT_REWRITE_CONTINUE) {
-    CHECK(!rewritten_event);
-    return continuation->SendEvent(&event);
-  }
-  CHECK(rewritten_event);
-  EventDispatchDetails details =
-      continuation->SendEventFinally(rewritten_event.get());
-  while (status == EVENT_REWRITE_DISPATCH_ANOTHER) {
-    if (details.dispatcher_destroyed)
-      return details;
-    std::unique_ptr<Event> new_event;
-    status = NextDispatchEvent(*rewritten_event, &new_event);
-    if (status == EVENT_REWRITE_DISCARD)
-      return continuation->DiscardEvent();
-    CHECK_NE(EVENT_REWRITE_CONTINUE, status);
-    CHECK(new_event);
-    details = continuation->SendEventFinally(new_event.get());
-    rewritten_event = std::move(new_event);
-  }
-  return details;
-}
-
-// Temporary default implementation of the old API, so that subclasses'
-// implementations can be removed.
-// TODO(kpschoedel): Remove old API.
-EventRewriteStatus EventRewriter::RewriteEvent(
-    const Event& event,
-    std::unique_ptr<Event>* rewritten_event) {
-  NOTREACHED();
-  return EVENT_REWRITE_DISCARD;
-}
-
-// Temporary default implementation of the old API, so that subclasses'
-// implementations can be removed.
-// TODO(kpschoedel): Remove old API.
-EventRewriteStatus EventRewriter::NextDispatchEvent(
-    const Event& last_event,
-    std::unique_ptr<Event>* new_event) {
-  NOTREACHED();
-  return EVENT_REWRITE_DISCARD;
-}
-
-// TODO(kpschoedel): Remove old API.
 EventDispatchDetails EventRewriter::SendEventToEventSource(EventSource* source,
                                                            Event* event) const {
   return source->SendEventToSinkFromRewriter(event, this);
 }
 
-EventDispatchDetails EventRewriter::SendEvent(
-    const base::WeakPtr<Continuation> continuation,
-    const Event* event) {
-  return continuation ? continuation->SendEvent(event) : DispatcherDestroyed();
-}
-
-EventDispatchDetails EventRewriter::SendEventFinally(
-    const base::WeakPtr<Continuation> continuation,
-    const Event* event) {
-  return continuation ? continuation->SendEventFinally(event)
-                      : DispatcherDestroyed();
-}
-
-EventDispatchDetails EventRewriter::DiscardEvent(
-    const base::WeakPtr<Continuation> continuation) {
-  return continuation ? continuation->DiscardEvent()
-                      : DispatcherDestroyed();
-}
-
 }  // namespace ui
diff --git a/ui/events/event_rewriter.h b/ui/events/event_rewriter.h
index baef82d..a096aa9 100644
--- a/ui/events/event_rewriter.h
+++ b/ui/events/event_rewriter.h
@@ -8,46 +8,28 @@
 #include <memory>
 
 #include "base/macros.h"
-#include "base/memory/weak_ptr.h"
 #include "ui/events/event_dispatcher.h"
 #include "ui/events/events_export.h"
 
 namespace ui {
 
 class Event;
-class EventSource;  // TODO(kpschoedel): Remove with old API.
+class EventSource;
 
 // Return status of EventRewriter operations; see that class below.
-// TODO(kpschoedel): Remove old API.
 enum EventRewriteStatus {
   // Nothing was done; no rewritten event returned. Pass the original
   // event to later rewriters, or send it to the EventSink if this
   // was the final rewriter.
-  //
-  // TODO(kpschoedel): Replace old API uses of
-  //    return EVENT_REWRITE_CONTINUE;
-  // with new API
-  //    return SendEvent(continuation, &incoming_event);
   EVENT_REWRITE_CONTINUE,
 
   // The event has been rewritten. Send the rewritten event to the
   // EventSink instead of the original event (without sending
   // either to any later rewriters).
-  //
-  // TODO(kpschoedel): Replace old API uses of
-  //    *rewritten_event = std::move(replacement_event);
-  //    return EVENT_REWRITE_REWRITTEN;
-  // with new API
-  //    return SendEventFinally(continuation, replacement_event);
   EVENT_REWRITE_REWRITTEN,
 
   // The event should be discarded, neither passing it to any later
   // rewriters nor sending it to the EventSink.
-  //
-  // TODO(kpschoedel): Replace old API uses of
-  //    return EVENT_REWRITE_DISCARD;
-  // with new API
-  //    return DiscardEvent(continuation);
   EVENT_REWRITE_DISCARD,
 
   // The event has been rewritten. As for EVENT_REWRITE_REWRITTEN,
@@ -56,15 +38,6 @@
   // In addition the rewriter has one or more additional new events
   // to be retrieved using |NextDispatchEvent()| and sent to the
   // EventSink.
-  //
-  // TODO(kpschoedel): Replace old API uses of
-  //    *rewritten_event = std::move(new_event_1);
-  //    // record new_event_2 … new_event_N
-  //    return EVENT_REWRITE_DISPATCH_ANOTHER;
-  // with new API
-  //    details = SendEventFinally(new_event_1);
-  //    ⋮
-  //    return SendEventFinally(new_event_N);
   EVENT_REWRITE_DISPATCH_ANOTHER,
 };
 
@@ -72,78 +45,17 @@
 // before being dispatched from EventSource to EventSink.
 class EVENTS_EXPORT EventRewriter {
  public:
-  // Used to return events from a rewriter, and expected to be called only
-  // within an EventRewriter, normally via the corresponding EventRewriter
-  // functions (because those first validate the continuation).
-  // See |RewriteEvent()| below for usage.
-  class Continuation {
-   public:
-    Continuation() = default;
-    virtual ~Continuation() = default;
-
-    // Send an event to the sink, via any later rewriters.
-    virtual EventDispatchDetails SendEvent(const Event* event)
-        WARN_UNUSED_RESULT = 0;
-
-    // Send an event directly to the sink, bypassing any later rewriters.
-    virtual EventDispatchDetails SendEventFinally(const Event* event)
-        WARN_UNUSED_RESULT = 0;
-
-    // Discard an event, bypassing any later rewriters.
-    virtual EventDispatchDetails DiscardEvent() WARN_UNUSED_RESULT = 0;
-  };
-
   EventRewriter() = default;
   virtual ~EventRewriter() = default;
 
-  // Potentially rewrites (replaces) an event, possibly with multiple events,
-  // or causes it to be discarded.
-  //
-  // To accept the supplied event without change,
-  //    return SendEvent(continuation, &event)
-  //
-  // To replace the supplied event with a new event, call either
-  //    return SendEvent(continuation, new_event)
-  // or
-  //    return SendEventFinally(continuation, new_event)
-  // depending on whether or not |new_event| should be provided to any
-  // later rewriters. These functions can be called more than once to
-  // replace an incoming event with multiple new events; when doing so,
-  // check |details.dispatcher_destroyed| after each call.
-  //
-  // To discard the incoming event without replacement,
-  //    return DiscardEvent()
-  //
-  // In the common case of one event at a time, the EventDispatchDetails
-  // from the above calls can and should be returned directly by RewriteEvent().
-  // When a rewriter generates multiple events synchronously, it should
-  // typically bail and return on a non-vacuous EventDispatchDetails.
-  // When a rewriter generates events asynchronously (e.g. from a timer)
-  // there is no opportunity to return the result directly, but a rewriter
-  // can consider retaining it for the next call.
-  //
-  // The supplied WeakPtr<Continuation> can be saved in order to respond
-  // asynchronously, e.g. after a double-click timeout. Normally, with
-  // EventRewriters subordinate to EventSources, the Continuation lives as
-  // long as the EventRewriter remains registered. If the continuation is not
-  // valid, the Send functions will return with |details.dispatcher_destroyed|.
-  //
-  // Design note: We need to pass the continuation state explicitly because
-  // Ash registers some EventRewriter instances with multiple EventSources.
-  //
-  virtual EventDispatchDetails RewriteEvent(
-      const Event& event,
-      const base::WeakPtr<Continuation> continuation);
-
   // Potentially rewrites (replaces) an event, or requests it be discarded.
   // or discards an event. If the rewriter wants to rewrite an event, and
   // dispatch another event once the rewritten event is dispatched, it should
   // return EVENT_REWRITE_DISPATCH_ANOTHER, and return the next event to
   // dispatch from |NextDispatchEvent()|.
-  // TODO(kpschoedel): Remove old API.
   virtual EventRewriteStatus RewriteEvent(
       const Event& event,
-      std::unique_ptr<Event>* rewritten_event);
+      std::unique_ptr<Event>* rewritten_event) = 0;
 
   // Supplies an additional event to be dispatched. It is only valid to
   // call this after the immediately previous call to |RewriteEvent()|
@@ -151,26 +63,13 @@
   // Should only return either EVENT_REWRITE_REWRITTEN or
   // EVENT_REWRITE_DISPATCH_ANOTHER; otherwise the previous call should not
   // have returned EVENT_REWRITE_DISPATCH_ANOTHER.
-  // TODO(kpschoedel): Remove old API.
   virtual EventRewriteStatus NextDispatchEvent(
       const Event& last_event,
-      std::unique_ptr<Event>* new_event);
+      std::unique_ptr<Event>* new_event) = 0;
 
  protected:
-  // Continuation helpers. These check the continuation and return
-  // with |details.target_destroyed| if it is invalid.
-  static EventDispatchDetails SendEvent(
-      const base::WeakPtr<Continuation> continuation,
-      const Event* event) WARN_UNUSED_RESULT;
-  static EventDispatchDetails SendEventFinally(
-      const base::WeakPtr<Continuation> continuation,
-      const Event* event) WARN_UNUSED_RESULT;
-  static EventDispatchDetails DiscardEvent(
-      const base::WeakPtr<Continuation> continuation) WARN_UNUSED_RESULT;
-
   // A helper that calls a protected EventSource function, which sends the event
   // to subsequent event rewriters on the source and onto its event sink.
-  // TODO(kpschoedel): Replace with SendEvent(continuation, event).
   EventDispatchDetails SendEventToEventSource(EventSource* source,
                                               Event* event) const;
 
diff --git a/ui/events/event_rewriter_unittest.cc b/ui/events/event_rewriter_unittest.cc
index 75ed3148..90c5d26 100644
--- a/ui/events/event_rewriter_unittest.cc
+++ b/ui/events/event_rewriter_unittest.cc
@@ -85,9 +85,9 @@
 // same event type; it is used to test simple rewriting, and rewriter addition,
 // removal, and sequencing. Consequently EVENT_REWRITE_DISPATCH_ANOTHER is not
 // supported here (calls to NextDispatchEvent() would continue indefinitely).
-class TestConstantEventRewriterOld : public EventRewriter {
+class TestConstantEventRewriter : public EventRewriter {
  public:
-  TestConstantEventRewriterOld(EventRewriteStatus status, EventType type)
+  TestConstantEventRewriter(EventRewriteStatus status, EventType type)
       : status_(status), type_(type) {
     CHECK_NE(EVENT_REWRITE_DISPATCH_ANOTHER, status);
   }
@@ -113,9 +113,9 @@
 
 // This EventRewriter runs a simple state machine; it is used to test
 // EVENT_REWRITE_DISPATCH_ANOTHER.
-class TestStateMachineEventRewriterOld : public EventRewriter {
+class TestStateMachineEventRewriter : public EventRewriter {
  public:
-  TestStateMachineEventRewriterOld() : last_rewritten_event_(0), state_(0) {}
+  TestStateMachineEventRewriter() : last_rewritten_event_(0), state_(0) {}
   void AddRule(int from_state, EventType from_type,
                int to_state, EventType to_type, EventRewriteStatus to_status) {
     RewriteResult r = {to_state, to_type, to_status};
@@ -160,111 +160,27 @@
   int state_;
 };
 
-// This EventRewriter always accepts the original event. It is used to test
-// simple rewriting, and rewriter addition, removal, and sequencing.
-class TestAlwaysAcceptEventRewriter : public EventRewriter {
- public:
-  TestAlwaysAcceptEventRewriter() {}
-  EventDispatchDetails RewriteEvent(
-      const Event& event,
-      const base::WeakPtr<Continuation> continuation) override {
-    return SendEvent(continuation, &event);
-  }
-};
-
-// This EventRewriter always rewrites with the same event type; it is used
-// to test simple rewriting, and rewriter addition, removal, and sequencing.
-class TestConstantEventRewriter : public EventRewriter {
- public:
-  explicit TestConstantEventRewriter(EventType type) : type_(type) {}
-  EventDispatchDetails RewriteEvent(
-      const Event& event,
-      const base::WeakPtr<Continuation> continuation) override {
-    std::unique_ptr<Event> replacement_event = CreateEventForType(type_);
-    return SendEventFinally(continuation, replacement_event.get());
-  }
-
- private:
-  EventType type_;
-};
-
-// This EventRewriter runs a simple state machine; it is used to test
-// EVENT_REWRITE_DISPATCH_ANOTHER.
-class TestStateMachineEventRewriter : public EventRewriter {
- public:
-  enum RewriteAction { ACCEPT, DISCARD, REPLACE };
-  enum StateAction { RETURN, PROCEED };
-  TestStateMachineEventRewriter() : state_(0) {}
-  void AddRule(int from_state,
-               EventType from_type,
-               int to_state,
-               EventType to_type,
-               RewriteAction rewrite_action,
-               StateAction state_action) {
-    RewriteResult r = {to_state, to_type, rewrite_action, state_action};
-    rules_.insert({RewriteCase(from_state, from_type), r});
-  }
-  EventDispatchDetails RewriteEvent(
-      const Event& event,
-      const base::WeakPtr<Continuation> continuation) override {
-    for (;;) {
-      RewriteRules::iterator find =
-          rules_.find(RewriteCase(state_, event.type()));
-      if (find == rules_.end())
-        return SendEvent(continuation, &event);
-      state_ = find->second.state;
-      EventDispatchDetails details;
-      switch (find->second.rewrite_action) {
-        case ACCEPT:
-          details = SendEvent(continuation, &event);
-          break;
-        case DISCARD:
-          break;
-        case REPLACE:
-          details = SendEventFinally(
-              continuation, CreateEventForType(find->second.type).get());
-          break;
-      }
-      if (details.dispatcher_destroyed || find->second.state_action == RETURN)
-        return details;
-    }
-    NOTREACHED();
-  }
-
- private:
-  typedef std::pair<int, EventType> RewriteCase;
-  struct RewriteResult {
-    int state;
-    EventType type;
-    RewriteAction rewrite_action;
-    StateAction state_action;
-  };
-  typedef std::map<RewriteCase, RewriteResult> RewriteRules;
-  RewriteRules rules_;
-  int state_;
-};
-
 }  // namespace
 
-TEST(EventRewriterTest, EventRewritingOld) {
+TEST(EventRewriterTest, EventRewriting) {
   // TestEventRewriter r0 always rewrites events to ET_CANCEL_MODE;
   // it is placed at the beginning of the chain and later removed,
   // to verify that rewriter removal works.
-  TestConstantEventRewriterOld r0(EVENT_REWRITE_REWRITTEN, ET_CANCEL_MODE);
+  TestConstantEventRewriter r0(EVENT_REWRITE_REWRITTEN, ET_CANCEL_MODE);
 
   // TestEventRewriter r1 always returns EVENT_REWRITE_CONTINUE;
-  // it is at the beginning of the chain (once r0 is removed)
-  // to verify that a later rewriter sees the events.
-  TestConstantEventRewriterOld r1(EVENT_REWRITE_CONTINUE, ET_UNKNOWN);
+  // it is placed at the beginning of the chain to verify that a
+  // later rewriter sees the events.
+  TestConstantEventRewriter r1(EVENT_REWRITE_CONTINUE, ET_UNKNOWN);
 
   // TestEventRewriter r2 has a state machine, primarily to test
   // |EVENT_REWRITE_DISPATCH_ANOTHER|.
-  TestStateMachineEventRewriterOld r2;
+  TestStateMachineEventRewriter r2;
 
   // TestEventRewriter r3 always rewrites events to ET_CANCEL_MODE;
   // it is placed at the end of the chain to verify that previously
   // rewritten events are not passed further down the chain.
-  TestConstantEventRewriterOld r3(EVENT_REWRITE_REWRITTEN, ET_CANCEL_MODE);
+  TestConstantEventRewriter r3(EVENT_REWRITE_REWRITTEN, ET_CANCEL_MODE);
 
   TestEventRewriteProcessor p;
   TestEventRewriteSource s(&p);
@@ -280,12 +196,6 @@
   p.CheckAllReceived();
 
   // Remove r0, and verify that it's gone and that events make it through.
-  // - r0 is removed, so the resulting event should NOT be ET_CANCEL_MODE.
-  // - r2 should rewrite ET_SCROLL_FLING_START to ET_SCROLL_FLING_CANCEL,
-  //   and skip subsequent rewriters, so the resulting event should be
-  //   ET_SCROLL_FLING_CANCEL.
-  // - r3 should be skipped after r2 returns, so the resulting event
-  //   should NOT be ET_CANCEL_MODE.
   s.AddEventRewriter(&r3);
   s.RemoveEventRewriter(&r0);
   r2.AddRule(0, ET_SCROLL_FLING_START,
@@ -313,8 +223,9 @@
   p.AddExpectedEvent(ET_MOUSE_PRESSED);
   s.Send(ET_MOUSE_PRESSED);
 
-  // Removing rewriter r1 shouldn't affect r2.
+  // Removing rewriters r1 and r3 shouldn't affect r2.
   s.RemoveEventRewriter(&r1);
+  s.RemoveEventRewriter(&r3);
 
   // Continue with the state-based rewriting.
   p.AddExpectedEvent(ET_MOUSE_RELEASED);
@@ -323,89 +234,4 @@
   p.CheckAllReceived();
 }
 
-TEST(EventRewriterTest, EventRewriting) {
-  // TestEventRewriter r0 always rewrites events to ET_CANCEL_MODE;
-  // it is placed at the beginning of the chain and later removed,
-  // to verify that rewriter removal works.
-  TestConstantEventRewriter r0(ET_CANCEL_MODE);
-
-  // TestEventRewriter r1 always returns EVENT_REWRITE_CONTINUE;
-  // it is at the beginning of the chain (once r0 is removed)
-  // to verify that a later rewriter sees the events.
-  TestAlwaysAcceptEventRewriter r1;
-
-  // TestEventRewriter r2 has a state machine, primarily to test
-  // |EVENT_REWRITE_DISPATCH_ANOTHER|.
-  TestStateMachineEventRewriter r2;
-
-  // TestEventRewriter r3 always rewrites events to ET_CANCEL_MODE;
-  // it is placed at the end of the chain to verify that previously
-  // rewritten events are not passed further down the chain.
-  TestConstantEventRewriter r3(ET_CANCEL_MODE);
-
-  TestEventRewriteProcessor p;
-  TestEventRewriteSource s(&p);
-  s.AddEventRewriter(&r0);
-  s.AddEventRewriter(&r1);
-  s.AddEventRewriter(&r2);
-
-  // These events should be rewritten by r0 to ET_CANCEL_MODE.
-  p.AddExpectedEvent(ET_CANCEL_MODE);
-  s.Send(ET_MOUSE_DRAGGED);
-  p.AddExpectedEvent(ET_CANCEL_MODE);
-  s.Send(ET_MOUSE_PRESSED);
-  p.CheckAllReceived();
-
-  // Remove r0, and verify that it's gone and that events make it through.
-  // - r0 is removed, so the resulting event should NOT be ET_CANCEL_MODE.
-  // - r2 should rewrite ET_SCROLL_FLING_START to ET_SCROLL_FLING_CANCEL,
-  //   and skip subsequent rewriters, so the resulting event should be
-  //   ET_SCROLL_FLING_CANCEL.
-  // - r3 should be skipped after r2 returns, so the resulting event
-  //   should NOT be ET_CANCEL_MODE.
-  s.AddEventRewriter(&r3);
-  s.RemoveEventRewriter(&r0);
-  r2.AddRule(0, ET_SCROLL_FLING_START, 0, ET_SCROLL_FLING_CANCEL,
-             TestStateMachineEventRewriter::REPLACE,
-             TestStateMachineEventRewriter::RETURN);
-  p.AddExpectedEvent(ET_SCROLL_FLING_CANCEL);
-  s.Send(ET_SCROLL_FLING_START);
-  p.CheckAllReceived();
-  s.RemoveEventRewriter(&r3);
-
-  // Verify replacing an event with multiple events using a state machine
-  // (that happens to be analogous to sticky keys).
-  r2.AddRule(0, ET_KEY_PRESSED, 1, ET_UNKNOWN,
-             TestStateMachineEventRewriter::ACCEPT,
-             TestStateMachineEventRewriter::RETURN);
-  r2.AddRule(1, ET_MOUSE_PRESSED, 0, ET_UNKNOWN,
-             TestStateMachineEventRewriter::ACCEPT,
-             TestStateMachineEventRewriter::RETURN);
-  r2.AddRule(1, ET_KEY_RELEASED, 2, ET_UNKNOWN,
-             TestStateMachineEventRewriter::DISCARD,
-             TestStateMachineEventRewriter::RETURN);
-  r2.AddRule(2, ET_MOUSE_RELEASED, 3, ET_MOUSE_RELEASED,
-             TestStateMachineEventRewriter::REPLACE,
-             TestStateMachineEventRewriter::PROCEED);
-  r2.AddRule(3, ET_MOUSE_RELEASED, 0, ET_KEY_RELEASED,
-             TestStateMachineEventRewriter::REPLACE,
-             TestStateMachineEventRewriter::RETURN);
-  p.AddExpectedEvent(ET_KEY_PRESSED);
-  s.Send(ET_KEY_PRESSED);   // state 0 ET_KEY_PRESSED -> 1 ACCEPT ET_KEY_PRESSED
-  s.Send(ET_KEY_RELEASED);  // state 1 ET_KEY_RELEASED -> 2 DISCARD
-  p.AddExpectedEvent(ET_MOUSE_PRESSED);
-  s.Send(ET_MOUSE_PRESSED);  // no matching rule; pass event through.
-
-  // Removing rewriter r1 shouldn't affect r2.
-  s.RemoveEventRewriter(&r1);
-
-  // Continue with the state-based rewriting.
-  p.AddExpectedEvent(ET_MOUSE_RELEASED);
-  p.AddExpectedEvent(ET_KEY_RELEASED);
-  s.Send(
-      ET_MOUSE_RELEASED);  // 2 ET_MOUSE_RELEASED -> 3 PROCEED ET_MOUSE_RELEASED
-                           // 3 ET_MOUSE_RELEASED -> 0 REPLACE ET_KEY_RELEASED
-  p.CheckAllReceived();
-}
-
 }  // namespace ui
diff --git a/ui/events/event_source.cc b/ui/events/event_source.cc
index 41d6539..85a6f40 100644
--- a/ui/events/event_source.cc
+++ b/ui/events/event_source.cc
@@ -4,12 +4,13 @@
 
 #include "ui/events/event_source.h"
 
-#include <memory>
+#include <algorithm>
 
+#include "base/stl_util.h"
+#include "ui/events/event_rewriter.h"
 #include "ui/events/event_sink.h"
 
 namespace ui {
-
 namespace {
 
 bool IsLocatedEventWithDifferentLocations(const Event& event) {
@@ -22,82 +23,23 @@
 
 }  // namespace
 
-class EventSource::EventRewriterContinuation
-    : public EventRewriter::Continuation,
-      public base::LinkNode<EventRewriterContinuation> {
- public:
-  EventRewriterContinuation(EventRewriter* rewriter,
-                            EventSource* const source,
-                            EventSource::EventRewriterList* const rewriter_list)
-      : rewriter_(rewriter),
-        source_(source),
-        rewriter_list_(rewriter_list),
-        weak_ptr_factory_(this) {}
-  ~EventRewriterContinuation() override {}
-
-  EventDispatchDetails SendEvent(const Event* event) override {
-    if (this == rewriter_list_->tail())
-      return SendEventFinally(event);
-    return next()->value()->rewriter_->RewriteEvent(
-        *event, next()->value()->GetWeakPtr());
-  }
-
-  EventDispatchDetails SendEventFinally(const Event* event) override {
-    return source_->DeliverEventToSink(const_cast<Event*>(event));
-  }
-
-  EventDispatchDetails DiscardEvent() override {
-    ui::EventDispatchDetails details;
-    details.event_discarded = true;
-    return details;
-  }
-
-  EventRewriter* rewriter() const { return rewriter_; }
-
-  base::WeakPtr<EventRewriterContinuation> GetWeakPtr() {
-    return weak_ptr_factory_.GetWeakPtr();
-  }
-
- private:
-  EventRewriter* rewriter_;
-  EventSource* const source_;
-  EventSource::EventRewriterList* const rewriter_list_;
-
-  base::WeakPtrFactory<EventRewriterContinuation> weak_ptr_factory_;
-  DISALLOW_COPY_AND_ASSIGN(EventRewriterContinuation);
-};
-
 EventSource::EventSource() {}
 
-EventSource::~EventSource() {
-  while (!rewriter_list_.empty())
-    RemoveEventRewriter(rewriter_list_.head()->value()->rewriter());
-}
+EventSource::~EventSource() {}
 
 void EventSource::AddEventRewriter(EventRewriter* rewriter) {
   DCHECK(rewriter);
-  DCHECK(!GetContinuation(rewriter));
-  rewriter_list_.Append(
-      new EventRewriterContinuation(rewriter, this, &rewriter_list_));
+  DCHECK(!base::ContainsValue(rewriter_list_, rewriter));
+  rewriter_list_.push_back(rewriter);
 }
 
 void EventSource::RemoveEventRewriter(EventRewriter* rewriter) {
-  EventRewriterContinuation* continuation = GetContinuation(rewriter);
-  if (!continuation) {
-    // We need to tolerate attempting to remove an unregistered
-    // EventRewriter, because many unit tests currently do so:
-    // the rewriter gets added to the current root window source
-    // on construction, and removed from the current root window
-    // source on destruction, but the root window changes in
-    // between.
-    LOG(WARNING) << "EventRewriter not registered";
-    return;
-  }
-  continuation->RemoveFromList();
-  delete continuation;
+  auto find = std::find(rewriter_list_.begin(), rewriter_list_.end(), rewriter);
+  if (find != rewriter_list_.end())
+    rewriter_list_.erase(find);
 }
 
-EventDispatchDetails EventSource::SendEventToSink(const Event* event) {
+EventDispatchDetails EventSource::SendEventToSink(Event* event) {
   return SendEventToSinkFromRewriter(event, nullptr);
 }
 
@@ -108,45 +50,62 @@
 }
 
 EventDispatchDetails EventSource::SendEventToSinkFromRewriter(
-    const Event* event,
+    Event* event,
     const EventRewriter* rewriter) {
   std::unique_ptr<ui::Event> event_for_rewriting_ptr;
-  const Event* event_for_rewriting = event;
+  Event* event_for_rewriting = event;
   if (!rewriter_list_.empty() && IsLocatedEventWithDifferentLocations(*event)) {
     // EventRewriters don't expect an event with differing location and
     // root-location (because they don't honor the target). Provide such an
-    // event.
+    // event for rewriters.
     event_for_rewriting_ptr = ui::Event::Clone(*event);
     event_for_rewriting_ptr->AsLocatedEvent()->set_location_f(
         event_for_rewriting_ptr->AsLocatedEvent()->root_location_f());
     event_for_rewriting = event_for_rewriting_ptr.get();
   }
-  EventRewriterContinuation* continuation = nullptr;
-  if (rewriter) {
-    // If a rewriter reposted |event|, only send it to subsequent rewriters.
-    continuation = GetContinuation(rewriter);
-    CHECK(continuation);
-    continuation = continuation->next()->value();
-  } else {
-    // Otherwise, start with the first rewriter.
-    // (If the list is empty, head() == end().)
-    continuation = rewriter_list_.head()->value();
-  }
-  if (continuation == rewriter_list_.end() || continuation == nullptr)
-    return DeliverEventToSink(const_cast<Event*>(event));
-  return continuation->rewriter()->RewriteEvent(*event_for_rewriting,
-                                                continuation->GetWeakPtr());
-}
-
-EventSource::EventRewriterContinuation* EventSource::GetContinuation(
-    const EventRewriter* rewriter) const {
-  for (auto* it = rewriter_list_.head(); it != rewriter_list_.end();
-       it = it->next()) {
-    if (it->value()->rewriter() == rewriter) {
-      return it->value();
+  std::unique_ptr<Event> rewritten_event;
+  EventRewriteStatus status = EVENT_REWRITE_CONTINUE;
+  EventRewriterList::const_iterator it = rewriter_list_.begin(),
+                                    end = rewriter_list_.end();
+  // If a rewriter reposted |event|, only send it to subsequent rewriters.
+  bool send_to_rewriter = rewriter == nullptr;
+  for (; it != end; ++it) {
+    if (!send_to_rewriter) {
+      send_to_rewriter |= (*it == rewriter);
+      continue;
     }
+    status = (*it)->RewriteEvent(*event_for_rewriting, &rewritten_event);
+    if (status == EVENT_REWRITE_DISCARD) {
+      CHECK(!rewritten_event);
+      EventDispatchDetails details;
+      details.event_discarded = true;
+      return details;
+    }
+    if (status == EVENT_REWRITE_CONTINUE) {
+      CHECK(!rewritten_event);
+      continue;
+    }
+    break;
   }
-  return nullptr;
+  CHECK((it == end && !rewritten_event) || rewritten_event);
+  EventDispatchDetails details =
+      DeliverEventToSink(rewritten_event ? rewritten_event.get() : event);
+  if (details.dispatcher_destroyed)
+    return details;
+
+  while (status == EVENT_REWRITE_DISPATCH_ANOTHER) {
+    std::unique_ptr<Event> new_event;
+    status = (*it)->NextDispatchEvent(*rewritten_event, &new_event);
+    if (status == EVENT_REWRITE_DISCARD)
+      return EventDispatchDetails();
+    CHECK_NE(EVENT_REWRITE_CONTINUE, status);
+    CHECK(new_event);
+    details = DeliverEventToSink(new_event.get());
+    if (details.dispatcher_destroyed)
+      return details;
+    rewritten_event = std::move(new_event);
+  }
+  return EventDispatchDetails();
 }
 
 }  // namespace ui
diff --git a/ui/events/event_source.h b/ui/events/event_source.h
index e5e8294d..ad84e60 100644
--- a/ui/events/event_source.h
+++ b/ui/events/event_source.h
@@ -7,16 +7,15 @@
 
 #include <vector>
 
-#include "base/containers/linked_list.h"
 #include "base/macros.h"
 #include "ui/events/event_dispatcher.h"
-#include "ui/events/event_rewriter.h"
 #include "ui/events/events_export.h"
 
 namespace ui {
 
 class Event;
 class EventSink;
+class EventRewriter;
 
 // EventSource receives events from the native platform (e.g. X11, win32 etc.)
 // and sends the events to an EventSink.
@@ -35,7 +34,7 @@
   void RemoveEventRewriter(EventRewriter* rewriter);
 
   // Sends the event through all rewriters and onto the source's EventSink.
-  EventDispatchDetails SendEventToSink(const Event* event);
+  EventDispatchDetails SendEventToSink(Event* event);
 
   // Send the event to the sink after rewriting; subclass overrides may queue
   // events before delivery, i.e. for the WindowService.
@@ -45,37 +44,20 @@
   // Sends the event through the rewriters and onto the source's EventSink.
   // If |rewriter| is valid, |event| is only sent to the subsequent rewriters.
   // This is used for asynchronous reposting of events processed by |rewriter|.
-  // TODO(kpschoedel): Remove along with old EventRewriter API.
   EventDispatchDetails SendEventToSinkFromRewriter(
-      const Event* event,
+      Event* event,
       const EventRewriter* rewriter);
 
  private:
-  // Implementation of EventRewriter::Continuation. No details need to be
-  // visible outside of event_source.cc.
-  class EventRewriterContinuation;
-
-  // The role of an EventRewriter::Continuation is to propagate events
-  // out from one EventRewriter and (optionally) on to the next. Using
-  // the |base::LinkedList| container makes this simple, and also allows
-  // the container to hold the continuation directly without risk of
-  // invalidating WeakPtrs.
-  typedef base::LinkedList<EventRewriterContinuation> EventRewriterList;
-
-  // Returns the EventRewriterContinuation for a given EventRewriter,
-  // or nullptr if the rewriter is not registered with this EventSource.
-  EventRewriterContinuation* GetContinuation(
-      const EventRewriter* rewriter) const;
-
-  EventRewriterList rewriter_list_;
-
-  friend class EventRewriter;  // TODO(kpschoedel): Remove along with old API.
-  friend class EventRewriterContinuation;
+  friend class EventRewriter;
   friend class EventSourceTestApi;
 
+  typedef std::vector<EventRewriter*> EventRewriterList;
+  EventRewriterList rewriter_list_;
+
   DISALLOW_COPY_AND_ASSIGN(EventSource);
 };
 
 }  // namespace ui
 
-#endif  // UI_EVENTS_EVENT_SOURCE_H_
+#endif // UI_EVENTS_EVENT_SOURCE_H_
diff --git a/ui/keyboard/keyboard_controller_unittest.cc b/ui/keyboard/keyboard_controller_unittest.cc
index a92745ae..5281d79 100644
--- a/ui/keyboard/keyboard_controller_unittest.cc
+++ b/ui/keyboard/keyboard_controller_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/command_line.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
diff --git a/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc b/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
index e8cae25..4deec5b 100644
--- a/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
+++ b/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
@@ -8,6 +8,7 @@
 
 #include <utility>
 
+#include "base/bind_helpers.h"
 #include "base/files/platform_file.h"
 #include "base/macros.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/ui/ozone/platform/wayland/fake_server.cc b/ui/ozone/platform/wayland/fake_server.cc
index 62e7f8c..2571181 100644
--- a/ui/ozone/platform/wayland/fake_server.cc
+++ b/ui/ozone/platform/wayland/fake_server.cc
@@ -1041,6 +1041,10 @@
   return global_ != nullptr;
 }
 
+void Global::DestroyGlobal() {
+  global_.reset();
+}
+
 // static
 void Global::Bind(wl_client* client,
                   void* data,
@@ -1083,19 +1087,22 @@
 MockDataDeviceManager::~MockDataDeviceManager() {}
 
 MockOutput::MockOutput()
-    : Global(&wl_output_interface, nullptr, kOutputVersion),
-      rect_(gfx::Rect(0, 0, 800, 600)) {}
+    : Global(&wl_output_interface, nullptr, kOutputVersion) {}
 
 MockOutput::~MockOutput() {}
 
 // Notify clients of the change for output position.
 void MockOutput::OnBind() {
+  if (rect_.IsEmpty())
+    return;
+
   const char* kUnknownMake = "unknown";
   const char* kUnknownModel = "unknown";
   wl_output_send_geometry(resource(), rect_.x(), rect_.y(), 0, 0, 0,
                           kUnknownMake, kUnknownModel, 0);
   wl_output_send_mode(resource(), WL_OUTPUT_MODE_CURRENT, rect_.width(),
                       rect_.height(), 0);
+  wl_output_send_done(resource());
 }
 
 MockSeat::MockSeat() : Global(&wl_seat_interface, &seat_impl, kSeatVersion) {}
@@ -1148,6 +1155,10 @@
   base::ScopedFD server_fd(fd[0]);
   base::ScopedFD client_fd(fd[1]);
 
+  // If client has not specified rect before, user standard ones.
+  if (output_.GetRect().IsEmpty())
+    output_.SetRect(gfx::Rect(0, 0, 800, 600));
+
   if (wl_display_init_shm(display_.get()) < 0)
     return false;
   if (!compositor_.Initialize(display_.get()))
diff --git a/ui/ozone/platform/wayland/fake_server.h b/ui/ozone/platform/wayland/fake_server.h
index ddda5748..7af277b 100644
--- a/ui/ozone/platform/wayland/fake_server.h
+++ b/ui/ozone/platform/wayland/fake_server.h
@@ -277,6 +277,11 @@
 
   // Create a global object.
   bool Initialize(wl_display* display);
+
+  // Can be used by clients to explicitly destroy global objects and send
+  // global_remove event.
+  void DestroyGlobal();
+
   // Called from Bind() to send additional information to clients.
   virtual void OnBind() {}
 
@@ -453,10 +458,13 @@
     return resource ? T::FromResource(resource) : nullptr;
   }
 
-  void CreateAndInitializeOutput() {
+  MockOutput* CreateAndInitializeOutput() {
     auto output = std::make_unique<MockOutput>();
     output->Initialize(display());
+
+    MockOutput* output_ptr = output.get();
     globals_.push_back(std::move(output));
+    return output_ptr;
   }
 
   MockDataDeviceManager* data_device_manager() { return &data_device_manager_; }
diff --git a/ui/ozone/platform/wayland/wayland_connection.cc b/ui/ozone/platform/wayland/wayland_connection.cc
index b6a7c79..7b1f5bf 100644
--- a/ui/ozone/platform/wayland/wayland_connection.cc
+++ b/ui/ozone/platform/wayland/wayland_connection.cc
@@ -69,7 +69,7 @@
 
   wl_registry_add_listener(registry_.get(), &registry_listener, this);
   while (!wayland_output_manager_ ||
-         !wayland_output_manager_->IsPrimaryOutputReady()) {
+         !wayland_output_manager_->IsOutputReady()) {
     wl_display_roundtrip(display_.get());
   }
 
diff --git a/ui/ozone/platform/wayland/wayland_output_manager.cc b/ui/ozone/platform/wayland/wayland_output_manager.cc
index 82fe00a4..654f3c3a 100644
--- a/ui/ozone/platform/wayland/wayland_output_manager.cc
+++ b/ui/ozone/platform/wayland/wayland_output_manager.cc
@@ -13,13 +13,10 @@
 
 WaylandOutputManager::~WaylandOutputManager() = default;
 
-bool WaylandOutputManager::IsPrimaryOutputReady() const {
+bool WaylandOutputManager::IsOutputReady() const {
   if (output_list_.empty())
     return false;
-
-  // The very first output in the list is always treated as a primary output.
-  const auto& primary_output = output_list_.front();
-  return primary_output->is_ready();
+  return output_list_.front()->is_ready();
 }
 
 void WaylandOutputManager::AddWaylandOutput(const uint32_t output_id,
@@ -54,14 +51,7 @@
   if (output_it == output_list_.end())
     return;
 
-  bool was_primary_output = IsPrimaryOutput(output_id);
   output_list_.erase(output_it);
-
-  // If it was a primary output removed, make sure the second output, which
-  // became a primary one, announces that to observers.
-  if (was_primary_output && !output_list_.empty())
-    output_list_.front()->TriggerDelegateNotification();
-
   OnWaylandOutputRemoved(output_id);
 }
 
@@ -90,7 +80,7 @@
 
 void WaylandOutputManager::OnWaylandOutputAdded(uint32_t output_id) {
   if (wayland_screen_)
-    wayland_screen_->OnOutputAdded(output_id, IsPrimaryOutput(output_id));
+    wayland_screen_->OnOutputAdded(output_id);
 }
 
 void WaylandOutputManager::OnWaylandOutputRemoved(uint32_t output_id) {
@@ -98,21 +88,12 @@
     wayland_screen_->OnOutputRemoved(output_id);
 }
 
-bool WaylandOutputManager::IsPrimaryOutput(uint32_t output_id) const {
-  DCHECK(!output_list_.empty());
-  // The very first object in the |output_list_| is always treated as a primary
-  // output.
-  const auto& primary_output = output_list_.front();
-  return primary_output->output_id() == output_id;
-}
-
 void WaylandOutputManager::OnOutputHandleMetrics(uint32_t output_id,
                                                  const gfx::Rect& new_bounds,
                                                  int32_t scale_factor) {
-  if (wayland_screen_) {
-    wayland_screen_->OnOutputMetricsChanged(output_id, new_bounds, scale_factor,
-                                            IsPrimaryOutput(output_id));
-  }
+  if (wayland_screen_)
+    wayland_screen_->OnOutputMetricsChanged(output_id, new_bounds,
+                                            scale_factor);
 }
 
 }  // namespace ui
diff --git a/ui/ozone/platform/wayland/wayland_output_manager.h b/ui/ozone/platform/wayland/wayland_output_manager.h
index ef42919..dcd6ca2f 100644
--- a/ui/ozone/platform/wayland/wayland_output_manager.h
+++ b/ui/ozone/platform/wayland/wayland_output_manager.h
@@ -27,8 +27,9 @@
   WaylandOutputManager();
   ~WaylandOutputManager() override;
 
-  // The first output in the vector is always a primary output.
-  bool IsPrimaryOutputReady() const;
+  // Says if at least one output has already been announced by a Wayland
+  // compositor.
+  bool IsOutputReady() const;
 
   void AddWaylandOutput(const uint32_t output_id, wl_output* output);
   void RemoveWaylandOutput(const uint32_t output_id);
@@ -41,8 +42,6 @@
   void OnWaylandOutputAdded(uint32_t output_id);
   void OnWaylandOutputRemoved(uint32_t output_id);
 
-  bool IsPrimaryOutput(uint32_t output_id) const;
-
   // WaylandOutput::Delegate:
   void OnOutputHandleMetrics(uint32_t output_id,
                              const gfx::Rect& new_bounds,
diff --git a/ui/ozone/platform/wayland/wayland_screen.cc b/ui/ozone/platform/wayland/wayland_screen.cc
index 6906ee44..86fac9f7 100644
--- a/ui/ozone/platform/wayland/wayland_screen.cc
+++ b/ui/ozone/platform/wayland/wayland_screen.cc
@@ -21,27 +21,62 @@
 
 WaylandScreen::~WaylandScreen() = default;
 
-void WaylandScreen::OnOutputAdded(uint32_t output_id, bool is_primary) {
+void WaylandScreen::OnOutputAdded(uint32_t output_id) {
   display::Display new_display(output_id);
   display_list_.AddDisplay(std::move(new_display),
-                           is_primary
-                               ? display::DisplayList::Type::PRIMARY
-                               : display::DisplayList::Type::NOT_PRIMARY);
+                           display::DisplayList::Type::NOT_PRIMARY);
 }
 
 void WaylandScreen::OnOutputRemoved(uint32_t output_id) {
+  display::Display primary_display = GetPrimaryDisplay();
+  if (primary_display.id() == output_id) {
+    // First, set a new primary display as required by the |display_list_|. It's
+    // safe to set any of the displays to be a primary one. Once the output is
+    // completely removed, Wayland updates geometry of other displays. And a
+    // display, which became the one to be nearest to the origin will become a
+    // primary one.
+    for (const auto& display : display_list_.displays()) {
+      if (display.id() != output_id) {
+        display_list_.AddOrUpdateDisplay(display,
+                                         display::DisplayList::Type::PRIMARY);
+        break;
+      }
+    }
+  }
   display_list_.RemoveDisplay(output_id);
 }
 
 void WaylandScreen::OnOutputMetricsChanged(uint32_t output_id,
                                            const gfx::Rect& new_bounds,
-                                           float device_pixel_ratio,
-                                           bool is_primary) {
+                                           float device_pixel_ratio) {
   display::Display changed_display(output_id);
   changed_display.set_device_scale_factor(device_pixel_ratio);
   changed_display.set_bounds(new_bounds);
   changed_display.set_work_area(new_bounds);
 
+  bool is_primary = false;
+  display::Display display_nearest_origin =
+      GetDisplayNearestPoint(gfx::Point(0, 0));
+  // If bounds of the nearest to origin display are empty, it must have been the
+  // very first and the same display added before.
+  if (display_nearest_origin.bounds().IsEmpty()) {
+    DCHECK_EQ(display_nearest_origin.id(), changed_display.id());
+    is_primary = true;
+  } else if (changed_display.bounds().origin() <
+             display_nearest_origin.bounds().origin()) {
+    // If changed display is nearer to the origin than the previous display,
+    // that one must become a primary display.
+    is_primary = true;
+  } else if (changed_display.bounds().OffsetFromOrigin() ==
+             display_nearest_origin.bounds().OffsetFromOrigin()) {
+    // If changed display has the same origin as the nearest to origin display,
+    // |changed_display| must become a primary one or it has already been the
+    // primary one. If a user changed positions of two displays (the second at
+    // x,x was set to 0,0), the second change will modify geometry of the
+    // display, which used to be the one nearest to the origin.
+    is_primary = true;
+  }
+
   display_list_.UpdateDisplay(
       changed_display, is_primary ? display::DisplayList::Type::PRIMARY
                                   : display::DisplayList::Type::NOT_PRIMARY);
@@ -57,8 +92,7 @@
 
 display::Display WaylandScreen::GetPrimaryDisplay() const {
   auto iter = display_list_.GetPrimaryDisplayIterator();
-  if (iter == display_list_.displays().end())
-    return display::Display::GetDefaultDisplay();
+  DCHECK(iter != display_list_.displays().end());
   return *iter;
 }
 
@@ -90,8 +124,7 @@
 
 display::Display WaylandScreen::GetDisplayNearestPoint(
     const gfx::Point& point) const {
-  NOTIMPLEMENTED_LOG_ONCE();
-  return GetPrimaryDisplay();
+  return *FindDisplayNearestPoint(display_list_.displays(), point);
 }
 
 display::Display WaylandScreen::GetDisplayMatching(
diff --git a/ui/ozone/platform/wayland/wayland_screen.h b/ui/ozone/platform/wayland/wayland_screen.h
index fe6f74f..480957bf 100644
--- a/ui/ozone/platform/wayland/wayland_screen.h
+++ b/ui/ozone/platform/wayland/wayland_screen.h
@@ -25,12 +25,11 @@
   explicit WaylandScreen(WaylandConnection* connection);
   ~WaylandScreen() override;
 
-  void OnOutputAdded(uint32_t output_id, bool is_primary);
+  void OnOutputAdded(uint32_t output_id);
   void OnOutputRemoved(uint32_t output_id);
   void OnOutputMetricsChanged(uint32_t output_id,
                               const gfx::Rect& bounds,
-                              float device_pixel_ratio,
-                              bool is_primary);
+                              float device_pixel_ratio);
 
   base::WeakPtr<WaylandScreen> GetWeakPtr();
 
diff --git a/ui/ozone/platform/wayland/wayland_screen_unittest.cc b/ui/ozone/platform/wayland/wayland_screen_unittest.cc
index a84af11..fa45435 100644
--- a/ui/ozone/platform/wayland/wayland_screen_unittest.cc
+++ b/ui/ozone/platform/wayland/wayland_screen_unittest.cc
@@ -27,6 +27,7 @@
   ~TestDisplayObserver() override {}
 
   display::Display GetDisplay() { return std::move(display_); }
+  display::Display GetRemovedDisplay() { return std::move(removed_display_); }
   uint32_t GetAndClearChangedMetrics() {
     uint32_t changed_metrics = changed_metrics_;
     changed_metrics_ = 0;
@@ -39,7 +40,7 @@
   }
 
   void OnDisplayRemoved(const display::Display& old_display) override {
-    display_ = old_display;
+    removed_display_ = old_display;
   }
 
   void OnDisplayMetricsChanged(const display::Display& display,
@@ -51,6 +52,7 @@
  private:
   uint32_t changed_metrics_ = 0;
   display::Display display_;
+  display::Display removed_display_;
 
   DISALLOW_COPY_AND_ASSIGN(TestDisplayObserver);
 };
@@ -71,7 +73,7 @@
     output_manager_ = connection_->wayland_output_manager();
     ASSERT_TRUE(output_manager_);
 
-    EXPECT_TRUE(output_manager_->IsPrimaryOutputReady());
+    EXPECT_TRUE(output_manager_->IsOutputReady());
     platform_screen_ = output_manager_->CreateWaylandScreen(connection_.get());
   }
 
@@ -90,6 +92,17 @@
     return window;
   }
 
+  void UpdateOutputGeometry(wl_resource* output_resource,
+                            const gfx::Rect& new_rect) {
+    wl_output_send_geometry(output_resource, new_rect.x(), new_rect.y(),
+                            0 /* physical_width */, 0 /* physical_height */,
+                            0 /* subpixel */, "unknown_make", "unknown_model",
+                            0 /* transform */);
+    wl_output_send_mode(output_resource, WL_OUTPUT_MODE_CURRENT,
+                        new_rect.width(), new_rect.height(), 0 /* refresh */);
+    wl_output_send_done(output_resource);
+  }
+
   wl::MockOutput* output_ = nullptr;
   WaylandOutputManager* output_manager_ = nullptr;
 
@@ -118,8 +131,20 @@
   TestDisplayObserver observer;
   platform_screen_->AddObserver(&observer);
 
+  const int64_t old_primary_display_id =
+      platform_screen_->GetPrimaryDisplay().id();
+
   // Add a second display.
-  server_.CreateAndInitializeOutput();
+  wl::MockOutput* output2 = server_.CreateAndInitializeOutput();
+
+  Sync();
+
+  // Update rect of that display.
+  gfx::Rect output1_rect = server_.output()->GetRect();
+  gfx::Rect output2_rect(output1_rect.width(), 0, 800, 600);
+  // The second display is located to the right of first display like
+  // | || |.
+  UpdateOutputGeometry(output2->resource(), output2_rect);
 
   Sync();
 
@@ -127,17 +152,21 @@
   int64_t added_display_id = observer.GetDisplay().id();
   EXPECT_NE(platform_screen_->GetPrimaryDisplay().id(), added_display_id);
 
-  // Remove the second output.
-  output_manager_->RemoveWaylandOutput(added_display_id);
+  output2->DestroyGlobal();
 
   Sync();
 
   // Ensure that removed display has correct id.
-  int64_t removed_display_id = observer.GetDisplay().id();
+  int64_t removed_display_id = observer.GetRemovedDisplay().id();
   EXPECT_EQ(added_display_id, removed_display_id);
 
   // Create another display again.
-  server_.CreateAndInitializeOutput();
+  output2 = server_.CreateAndInitializeOutput();
+
+  Sync();
+
+  // Updates rect again.
+  UpdateOutputGeometry(output2->resource(), output2_rect);
 
   Sync();
 
@@ -145,16 +174,26 @@
   added_display_id = observer.GetDisplay().id();
   EXPECT_NE(platform_screen_->GetPrimaryDisplay().id(), added_display_id);
 
-  // Make sure the geometry changes are sent by syncing one more time again.
+  // Now, rearrange displays so that second display becomes a primary one.
+  output1_rect = gfx::Rect(1024, 0, 1024, 768);
+  output2_rect = gfx::Rect(0, 0, 1024, 768);
+  UpdateOutputGeometry(server_.output()->resource(), output1_rect);
+  UpdateOutputGeometry(output2->resource(), output2_rect);
+
   Sync();
 
-  int64_t old_primary_display_id = platform_screen_->GetPrimaryDisplay().id();
-  output_manager_->RemoveWaylandOutput(old_primary_display_id);
-
-  // Ensure that previously added display is now a primary one.
+  // Ensure that output2 is now the primary one.
   EXPECT_EQ(platform_screen_->GetPrimaryDisplay().id(), added_display_id);
+
+  // Remove the primary display now.
+  output2->DestroyGlobal();
+
+  Sync();
+
+  // Ensure that output1 is a primary display now.
+  EXPECT_EQ(platform_screen_->GetPrimaryDisplay().id(), old_primary_display_id);
   // Ensure that the removed display was the one, which was a primary display.
-  EXPECT_EQ(observer.GetDisplay().id(), old_primary_display_id);
+  EXPECT_EQ(observer.GetRemovedDisplay().id(), added_display_id);
 
   platform_screen_->RemoveObserver(&observer);
 }
@@ -164,13 +203,7 @@
   platform_screen_->AddObserver(&observer);
 
   const gfx::Rect new_rect(0, 0, 800, 600);
-  wl_output_send_geometry(output_->resource(), new_rect.x(), new_rect.y(),
-                          0 /* physical_width */, 0 /* physical_height */,
-                          0 /* subpixel */, "unkown_make", "unknown_model",
-                          0 /* transform */);
-  wl_output_send_mode(output_->resource(), WL_OUTPUT_MODE_CURRENT,
-                      new_rect.width(), new_rect.height(), 0 /* refresh */);
-  wl_output_send_done(output_->resource());
+  UpdateOutputGeometry(output_->resource(), new_rect);
 
   Sync();
 
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn
index ae38b8f..4decb88 100644
--- a/ui/views/BUILD.gn
+++ b/ui/views/BUILD.gn
@@ -7,7 +7,6 @@
 import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
 import("//components/vector_icons/vector_icons.gni")
-import("//services/catalog/public/tools/catalog.gni")
 import("//services/service_manager/public/service_manifest.gni")
 import("//testing/test.gni")
 import("//ui/base/ui_features.gni")
@@ -915,12 +914,13 @@
     ]
 
     deps += [
-      ":views_unittests_catalog_source",
-      "//services/catalog:lib",
       "//services/service_manager/background:lib",
       "//services/service_manager/public/cpp",
       "//services/service_manager/public/mojom",
       "//services/ws/common",
+      "//services/ws/ime/test_ime_driver:manifest",
+      "//services/ws/public/mojom",
+      "//services/ws/test_ws:manifest",
       "//testing/gtest",
       "//ui/compositor:test_support",
       "//ui/gl:test_support",
@@ -929,7 +929,6 @@
     ]
 
     data_deps = [
-      ":views_unittests_catalog",
       "//services/ws/ime/test_ime_driver",
       "//ui/resources:ui_test_pak_data",
     ]
@@ -1343,35 +1342,3 @@
     "//testing:run_perf_test",
   ]
 }
-
-if (enable_mus) {
-  service_manifest("unittests_manifest") {
-    name = "views_unittests"
-    source = "unittests_manifest.json"
-  }
-
-  service_manifest("interactive_ui_tests_manifest") {
-    name = "interactive_ui_tests"
-    source = "interactive_ui_tests_manifest.json"
-  }
-
-  catalog("views_unittests_catalog") {
-    testonly = true
-
-    embedded_services = [
-      ":unittests_manifest",
-      ":interactive_ui_tests_manifest",
-    ]
-
-    standalone_services = [
-      "//services/ws/test_ws:manifest",
-      "//services/ws/ime/test_ime_driver:manifest",
-    ]
-  }
-
-  catalog_cpp_source("views_unittests_catalog_source") {
-    testonly = true
-    catalog = ":views_unittests_catalog"
-    generated_function_name = "views::CreateViewsUnittestsCatalog"
-  }
-}
diff --git a/ui/views/DEPS b/ui/views/DEPS
index 488eb2c..58ce51c 100644
--- a/ui/views/DEPS
+++ b/ui/views/DEPS
@@ -40,7 +40,6 @@
   ],
   "views_test_base\.cc": [
     "+mojo/core/embedder",
-    "+services/catalog",
     "+services/service_manager/background",
     "+services/service_manager/public",
     "+services/ws",
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc
index 0a02451..bda7ba1 100644
--- a/ui/views/controls/menu/menu_controller.cc
+++ b/ui/views/controls/menu/menu_controller.cc
@@ -2249,7 +2249,7 @@
 
   if (!item->GetParentMenuItem()) {
     // This is a top-level menu, position it relative to the anchor bounds.
-    const gfx::Rect& anchor_bounds = pending_state_.initial_bounds;
+    const gfx::Rect& anchor_bounds = state_.initial_bounds;
 
     // First the size gets reduced to the possible space.
     if (!monitor_bounds.IsEmpty()) {
@@ -2269,6 +2269,14 @@
       } else if (state_.anchor == MENU_ANCHOR_BUBBLE_BELOW) {
         max_height = monitor_bounds.bottom() - anchor_bounds.bottom() +
                      kBubbleTipSizeTopBottom;
+      } else if (state_.anchor == MENU_ANCHOR_BUBBLE_TOUCHABLE_ABOVE) {
+        // Don't consider |border_and_shadow_insets| because when the max size
+        // is enforced, the scroll view is shown and the md shadows are not
+        // applied.
+        max_height =
+            std::max(anchor_bounds.y() - monitor_bounds.y(),
+                     monitor_bounds.bottom() - anchor_bounds.bottom()) -
+            menu_config.touchable_anchor_offset;
       }
       // The menu should always have a non-empty available area.
       DCHECK_GE(max_width, kBubbleTipSizeLeftRight);
@@ -2308,11 +2316,13 @@
     } else if (state_.anchor == MENU_ANCHOR_BUBBLE_TOUCHABLE_ABOVE) {
       // Align the left edges of the menu and anchor, and the bottom of the menu
       // with the top of the anchor.
-      x = anchor_bounds.x() - border_and_shadow_insets.left();
+      x = std::max(monitor_bounds.x(),
+                   anchor_bounds.x() - border_and_shadow_insets.left());
       y = anchor_bounds.y() - menu_size.height() +
           border_and_shadow_insets.bottom() -
           menu_config.touchable_anchor_offset;
-      // Align the right of the container with the right of the anchor.
+
+      // Align the right of the menu with the right of the anchor.
       if (x + menu_size.width() > monitor_bounds.width()) {
         x = anchor_bounds.right() - menu_size.width() +
             border_and_shadow_insets.right();
@@ -2334,10 +2344,13 @@
         x = anchor_bounds.right() - border_and_shadow_insets.left() +
             menu_config.touchable_anchor_offset;
       }
-      // Align the bottom of the menu to the bottom of the anchor.
-      if (y + menu_size.height() > monitor_bounds.height()) {
+      // Prefer aligning the bottom of the menu to the bottom of the anchor.
+      if (y + menu_size.height() > monitor_bounds.bottom()) {
         y = anchor_bounds.bottom() - menu_size.height() +
             border_and_shadow_insets.bottom();
+        // For some very tall menus, this may still be off screen.
+        if (y < monitor_bounds.y())
+          y = monitor_bounds.y();
       }
     } else if (state_.anchor == MENU_ANCHOR_BUBBLE_TOUCHABLE_RIGHT) {
       // Align the left of the menu with the right of the anchor, and the top of
@@ -2351,7 +2364,7 @@
             border_and_shadow_insets.right() -
             menu_config.touchable_anchor_offset;
       }
-      if (y + menu_size.height() > monitor_bounds.height()) {
+      if (y + menu_size.height() > monitor_bounds.bottom()) {
         // Align the bottom of the menu with the bottom of the anchor.
         y = anchor_bounds.bottom() - menu_size.height() +
             border_and_shadow_insets.bottom();
diff --git a/ui/views/controls/menu/menu_controller_unittest.cc b/ui/views/controls/menu/menu_controller_unittest.cc
index 7898e49..305d043 100644
--- a/ui/views/controls/menu/menu_controller_unittest.cc
+++ b/ui/views/controls/menu/menu_controller_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/macros.h"
 #include "base/message_loop/message_loop.h"
 #include "base/single_thread_task_runner.h"
+#include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
@@ -351,15 +352,17 @@
   }
 
   gfx::Rect CalculateMenuBounds(const MenuBoundsOptions& options) {
-    menu_controller_->state_.anchor = options.menu_anchor;
-    menu_controller_->state_.initial_bounds = options.anchor_bounds;
-    menu_controller_->state_.monitor_bounds = options.monitor_bounds;
-    menu_item_->SetActualMenuPosition(options.menu_position);
-    menu_item_->GetSubmenu()->GetScrollViewContainer()->SetPreferredSize(
-        options.menu_size);
-    bool resulting_direction;
+    SetUpMenuControllerForCalculateBounds(options);
+    bool is_leading;
     return menu_controller_->CalculateMenuBounds(menu_item_.get(), true,
-                                                 &resulting_direction);
+                                                 &is_leading);
+  }
+
+  gfx::Rect CalculateBubbleMenuBounds(const MenuBoundsOptions& options) {
+    SetUpMenuControllerForCalculateBounds(options);
+    bool is_leading;
+    return menu_controller_->CalculateBubbleMenuBounds(menu_item_.get(), true,
+                                                       &is_leading);
   }
 
 #if defined(USE_AURA)
@@ -421,6 +424,102 @@
     menu_controller_->ExitMenu();
   }
 
+  void TestMenuFitsOnScreen(MenuAnchorPosition menu_anchor_position) {
+    SCOPED_TRACE(
+        base::StringPrintf("MenuAnchorPosition: %d\n", menu_anchor_position));
+    MenuBoundsOptions options;
+    options.menu_anchor = menu_anchor_position;
+    const int display_size = 500;
+    options.monitor_bounds = gfx::Rect(0, 0, display_size, display_size);
+
+    // Simulate a bottom shelf with a tall menu.
+    const int button_size = 50;
+    options.anchor_bounds = gfx::Rect(
+        display_size / 2, display_size - button_size, button_size, button_size);
+    gfx::Rect final_bounds = CalculateBubbleMenuBounds(options);
+
+    // Adjust the final bounds to not include the shadow and border.
+    const gfx::Insets border_and_shadow_insets =
+        BubbleBorder::GetBorderAndShadowInsets(
+            MenuConfig::instance().touchable_menu_shadow_elevation);
+    final_bounds.Inset(border_and_shadow_insets);
+
+    // Test that the menu will show on screen.
+    EXPECT_TRUE(options.monitor_bounds.Contains(final_bounds));
+
+    // Simulate a left shelf with a tall menu.
+    options.anchor_bounds =
+        gfx::Rect(0, display_size / 2, button_size, button_size);
+    final_bounds = CalculateBubbleMenuBounds(options);
+
+    // Adjust the final bounds to not include the shadow and border.
+    final_bounds.Inset(border_and_shadow_insets);
+
+    // Test that the menu will show on screen.
+    EXPECT_TRUE(options.monitor_bounds.Contains(final_bounds));
+
+    // Simulate right shelf with a tall menu.
+    options.anchor_bounds = gfx::Rect(
+        display_size - button_size, display_size / 2, button_size, button_size);
+    final_bounds = CalculateBubbleMenuBounds(options);
+
+    // Adjust the final bounds to not include the shadow and border.
+    final_bounds.Inset(border_and_shadow_insets);
+
+    // Test that the menu will show on screen.
+    EXPECT_TRUE(options.monitor_bounds.Contains(final_bounds));
+  }
+
+  void TestMenuFitsOnScreenSmallAnchor(
+      MenuAnchorPosition menu_anchor_position) {
+    SCOPED_TRACE(
+        base::StringPrintf("MenuAnchorPosition: %d\n", menu_anchor_position));
+    MenuBoundsOptions options;
+    options.menu_anchor = menu_anchor_position;
+    const int display_size = 500;
+    options.monitor_bounds = gfx::Rect(0, 0, display_size, display_size);
+
+    // Simulate a click on the top left corner.
+    options.anchor_bounds = gfx::Rect(0, 0, 0, 0);
+    gfx::Rect final_bounds = CalculateBubbleMenuBounds(options);
+
+    // Adjust the final bounds to not include the shadow and border.
+    const gfx::Insets border_and_shadow_insets =
+        BubbleBorder::GetBorderAndShadowInsets(
+            MenuConfig::instance().touchable_menu_shadow_elevation);
+    final_bounds.Inset(border_and_shadow_insets);
+
+    // Test that the menu is within the monitor bounds.
+    EXPECT_TRUE(options.monitor_bounds.Contains(final_bounds));
+
+    // Simulate a click on the bottom left corner.
+    options.anchor_bounds = gfx::Rect(0, display_size, 0, 0);
+    final_bounds = CalculateBubbleMenuBounds(options);
+    // Adjust the final bounds to not include the shadow and border.
+    final_bounds.Inset(border_and_shadow_insets);
+
+    // Test that the menu is within the monitor bounds.
+    EXPECT_TRUE(options.monitor_bounds.Contains(final_bounds));
+
+    // Simulate a click on the top right corner.
+    options.anchor_bounds = gfx::Rect(display_size, 0, 0, 0);
+    final_bounds = CalculateBubbleMenuBounds(options);
+    // Adjust the final bounds to not include the shadow and border.
+    final_bounds.Inset(border_and_shadow_insets);
+
+    // Test that the menu is within the monitor bounds.
+    EXPECT_TRUE(options.monitor_bounds.Contains(final_bounds));
+
+    // Simulate a click on the bottom right corner.
+    options.anchor_bounds = gfx::Rect(display_size, display_size, 0, 0);
+    final_bounds = CalculateBubbleMenuBounds(options);
+    // Adjust the final bounds to not include the shadow and border.
+    final_bounds.Inset(border_and_shadow_insets);
+
+    // Test that the menu is within the monitor bounds.
+    EXPECT_TRUE(options.monitor_bounds.Contains(final_bounds));
+  }
+
  protected:
   void SetPendingStateItem(MenuItemView* item) {
     menu_controller_->pending_state_.item = item;
@@ -543,6 +642,15 @@
         menu_item()->GetSubmenu()->GetMenuItemAt(0)->CreateSubmenu(), location);
   }
 
+  void SetUpMenuControllerForCalculateBounds(const MenuBoundsOptions& options) {
+    menu_controller_->state_.anchor = options.menu_anchor;
+    menu_controller_->state_.initial_bounds = options.anchor_bounds;
+    menu_controller_->state_.monitor_bounds = options.monitor_bounds;
+    menu_item_->SetActualMenuPosition(options.menu_position);
+    menu_item_->GetSubmenu()->GetScrollViewContainer()->SetPreferredSize(
+        options.menu_size);
+  }
+
   GestureTestWidget* owner() { return owner_.get(); }
   ui::test::EventGenerator* event_generator() { return event_generator_.get(); }
   TestMenuItemViewShown* menu_item() { return menu_item_.get(); }
@@ -1680,6 +1788,20 @@
   EXPECT_EQ(expected, CalculateMenuBounds(options));
 }
 
+// Test that menus show up on screen with non-zero sized anchors.
+TEST_F(MenuControllerTest, TestMenuFitsOnScreen) {
+  TestMenuFitsOnScreen(MENU_ANCHOR_BUBBLE_TOUCHABLE_ABOVE);
+  TestMenuFitsOnScreen(MENU_ANCHOR_BUBBLE_TOUCHABLE_LEFT);
+  TestMenuFitsOnScreen(MENU_ANCHOR_BUBBLE_TOUCHABLE_RIGHT);
+}
+
+// Test that menus show up on screen with zero sized anchors.
+TEST_F(MenuControllerTest, TestMenuFitsOnScreenSmallAnchor) {
+  TestMenuFitsOnScreenSmallAnchor(MENU_ANCHOR_BUBBLE_TOUCHABLE_ABOVE);
+  TestMenuFitsOnScreenSmallAnchor(MENU_ANCHOR_BUBBLE_TOUCHABLE_LEFT);
+  TestMenuFitsOnScreenSmallAnchor(MENU_ANCHOR_BUBBLE_TOUCHABLE_RIGHT);
+}
+
 // Test that a menu that was originally drawn below the anchor does not get
 // squished or move above the anchor when it grows vertically and horizontally
 // beyond the monitor bounds.
diff --git a/ui/views/controls/scroll_view_unittest.cc b/ui/views/controls/scroll_view_unittest.cc
index 439d674..2da29295 100644
--- a/ui/views/controls/scroll_view_unittest.cc
+++ b/ui/views/controls/scroll_view_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/test/test_timeouts.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/timer/timer.h"
 #include "build/build_config.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/ui_base_features.h"
diff --git a/ui/views/controls/scrollbar/cocoa_scroll_bar.h b/ui/views/controls/scrollbar/cocoa_scroll_bar.h
index c69087a..cf3fb10 100644
--- a/ui/views/controls/scrollbar/cocoa_scroll_bar.h
+++ b/ui/views/controls/scrollbar/cocoa_scroll_bar.h
@@ -7,6 +7,7 @@
 
 #import "base/mac/scoped_nsobject.h"
 #include "base/macros.h"
+#include "base/timer/timer.h"
 #include "ui/compositor/layer_animation_observer.h"
 #include "ui/gfx/animation/slide_animation.h"
 #include "ui/views/controls/scrollbar/base_scroll_bar.h"
diff --git a/ui/views/controls/scrollbar/overlay_scroll_bar.h b/ui/views/controls/scrollbar/overlay_scroll_bar.h
index ac1ac38..7e66e01 100644
--- a/ui/views/controls/scrollbar/overlay_scroll_bar.h
+++ b/ui/views/controls/scrollbar/overlay_scroll_bar.h
@@ -6,6 +6,7 @@
 #define UI_VIEWS_CONTROLS_SCROLLBAR_OVERLAY_SCROLL_BAR_H_
 
 #include "base/macros.h"
+#include "base/timer/timer.h"
 #include "ui/views/controls/scrollbar/base_scroll_bar.h"
 #include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h"
 
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index cb514883..850143f 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -2258,11 +2258,12 @@
 
 void Textfield::UpdateContextMenu() {
   // TextfieldController may modify Textfield's menu, so the menu should be
-  // recreated each time it's shown. Reset the MenuRunner first so it doesn't
-  // reference the old menu model.
+  // recreated each time it's shown. Destroy the existing objects in the reverse
+  // order of creation.
   context_menu_runner_.reset();
+  context_menu_contents_.reset();
 
-  context_menu_contents_.reset(new ui::SimpleMenuModel(this));
+  context_menu_contents_ = std::make_unique<ui::SimpleMenuModel>(this);
   context_menu_contents_->AddItemWithStringId(IDS_APP_UNDO, IDS_APP_UNDO);
   context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
   context_menu_contents_->AddItemWithStringId(IDS_APP_CUT, IDS_APP_CUT);
diff --git a/ui/views/controls/textfield/textfield.h b/ui/views/controls/textfield/textfield.h
index db72373b..0707ac7e 100644
--- a/ui/views/controls/textfield/textfield.h
+++ b/ui/views/controls/textfield/textfield.h
@@ -16,6 +16,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/strings/string16.h"
 #include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "build/build_config.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/ime/text_input_client.h"
diff --git a/ui/views/interactive_ui_tests_manifest.json b/ui/views/interactive_ui_tests_manifest.json
deleted file mode 100644
index 567ca61..0000000
--- a/ui/views/interactive_ui_tests_manifest.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "name": "interactive_ui_tests",
-  "display_name": "Interactive UI Tests",
-  "interface_provider_specs": {
-    "service_manager:connector": {
-      "requires": {
-        "*": [ "app", "test" ],
-        "ui": [ "window_manager" ]
-      }
-    }
-  }
-}
diff --git a/ui/views/mus/BUILD.gn b/ui/views/mus/BUILD.gn
index aa466e8..729871c 100644
--- a/ui/views/mus/BUILD.gn
+++ b/ui/views/mus/BUILD.gn
@@ -5,7 +5,6 @@
 import("//build/config/features.gni")
 import("//build/config/jumbo.gni")
 import("//build/config/ui.gni")
-import("//services/catalog/public/tools/catalog.gni")
 import("//services/service_manager/public/service_manifest.gni")
 import("//testing/test.gni")
 import("//tools/grit/repack.gni")
diff --git a/ui/views/mus/DEPS b/ui/views/mus/DEPS
index 72bd2b4..04516d0 100644
--- a/ui/views/mus/DEPS
+++ b/ui/views/mus/DEPS
@@ -5,7 +5,7 @@
   "+mojo/converters",
   "+mojo/core/embedder",
   "+mojo/public",
-  "+services/catalog",
+  "+services/catalog/public",
   "+services/service_manager/public",
   "+services/ws",
   "+skia",
diff --git a/ui/views/mus/remote_view/remote_view_provider_unittest.cc b/ui/views/mus/remote_view/remote_view_provider_unittest.cc
index 0cd4fcac..1d727f6 100644
--- a/ui/views/mus/remote_view/remote_view_provider_unittest.cc
+++ b/ui/views/mus/remote_view/remote_view_provider_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 
 #include "base/bind.h"
+#include "base/bind_helpers.h"
 #include "base/macros.h"
 #include "base/run_loop.h"
 #include "base/unguessable_token.h"
diff --git a/ui/views/test/DEPS b/ui/views/test/DEPS
index 0919d159..98b1137 100644
--- a/ui/views/test/DEPS
+++ b/ui/views/test/DEPS
@@ -4,8 +4,9 @@
 
 specific_include_rules = {
   "platform_test_helper_mus.cc": [
-    "+services/catalog/catalog.h",
     "+services/service_manager/background/background_service_manager.h",
     "+services/service_manager/public",
+    "+services/ws/ime/test_ime_driver/manifest.h",
+    "+services/ws/test_ws/manifest.h",
   ]
 }
diff --git a/ui/views/test/platform_test_helper_mus.cc b/ui/views/test/platform_test_helper_mus.cc
index 0c678c3..505067e 100644
--- a/ui/views/test/platform_test_helper_mus.cc
+++ b/ui/views/test/platform_test_helper_mus.cc
@@ -8,12 +8,15 @@
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/threading/simple_thread.h"
-#include "services/catalog/catalog.h"
 #include "services/service_manager/background/background_service_manager.h"
 #include "services/service_manager/public/cpp/connector.h"
 #include "services/service_manager/public/cpp/constants.h"
+#include "services/service_manager/public/cpp/manifest_builder.h"
 #include "services/service_manager/public/cpp/service.h"
 #include "services/service_manager/public/cpp/service_binding.h"
+#include "services/ws/ime/test_ime_driver/manifest.h"
+#include "services/ws/public/mojom/constants.mojom.h"
+#include "services/ws/test_ws/manifest.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/aura/mus/window_tree_host_mus.h"
 #include "ui/aura/test/env_test_helper.h"
@@ -23,7 +26,6 @@
 #include "ui/views/mus/mus_client.h"
 #include "ui/views/test/views_test_helper_aura.h"
 #include "ui/views/views_delegate.h"
-#include "ui/views/views_unittests_catalog_source.h"
 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
 #include "ui/views/widget/native_widget_aura.h"
 
@@ -110,7 +112,27 @@
   void SetUpConnectionsOnBackgroundThread(base::WaitableEvent* wait) {
     background_service_manager_ =
         std::make_unique<service_manager::BackgroundServiceManager>(
-            nullptr, CreateViewsUnittestsCatalog());
+            nullptr, std::vector<service_manager::Manifest>{
+                         test_ws::GetManifest(), test_ime_driver::GetManifest(),
+
+                         // The manifest used for the test service instance when
+                         // running as a "views_unitttests" executable.
+                         service_manager::ManifestBuilder()
+                             .WithServiceName("views_unittests")
+                             .RequireCapability("*", "app")
+                             .RequireCapability("*", "test")
+                             .Build(),
+
+                         // The manifest used for the test service instance when
+                         // running as a "views_unitttests" executable.
+                         service_manager::ManifestBuilder()
+                             .WithServiceName("interactive_ui_tests")
+                             .RequireCapability("*", "app")
+                             .RequireCapability("*", "test")
+                             .RequireCapability(ws::mojom::kServiceName,
+                                                "window_manager")
+                             .Build()});
+
     service_manager::mojom::ServicePtr service;
     default_service_binding_.Bind(mojo::MakeRequest(&service));
     background_service_manager_->RegisterService(
diff --git a/ui/views/unittests_manifest.json b/ui/views/unittests_manifest.json
deleted file mode 100644
index 172d8982..0000000
--- a/ui/views/unittests_manifest.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
-  "name": "views_unittests",
-  "display_name": "Views Unittests",
-  "interface_provider_specs": {
-    "service_manager:connector": {
-      "requires": {
-        "*": [ "app", "test" ]
-      }
-    }
-  }
-}
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
index 31576939..42c4658 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -518,7 +518,7 @@
   if (compositor())
     SetVisible(true);
 
-  if (!IsVisible())
+  if (!window_mapped_in_client_ || IsMinimized())
     MapWindow(show_state);
 
   switch (show_state) {
@@ -547,7 +547,10 @@
 }
 
 bool DesktopWindowTreeHostX11::IsVisible() const {
-  return window_mapped_in_client_ && !IsMinimized();
+  // On Windows, IsVisible() returns true for minimized windows.  On X11, a
+  // minimized window is not mapped, so an explicit IsMinimized() check is
+  // necessary.
+  return window_mapped_in_client_ || IsMinimized();
 }
 
 void DesktopWindowTreeHostX11::SetSize(const gfx::Size& requested_size) {
@@ -762,7 +765,6 @@
     // after an Activate(), so just set this state now.
     has_pointer_focus_ = false;
     has_window_focus_ = true;
-    // window_mapped_in_client_ == true based on the IsVisible() check above.
     window_mapped_in_server_ = true;
     XSetErrorHandler(old_error_handler);
   }
@@ -816,7 +818,7 @@
 
   // Some WMs do not respect maximization hints on unmapped windows, so we
   // save this one for later too.
-  should_maximize_after_map_ = !IsVisible();
+  should_maximize_after_map_ = !window_mapped_in_client_;
 
   // When we are in the process of requesting to maximize a window, we can
   // accurately keep track of our restored bounds instead of relying on the
diff --git a/ui/views/widget/widget_interactive_uitest.cc b/ui/views/widget/widget_interactive_uitest.cc
index 3363537..f5e2d3e 100644
--- a/ui/views/widget/widget_interactive_uitest.cc
+++ b/ui/views/widget/widget_interactive_uitest.cc
@@ -13,6 +13,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "base/timer/timer.h"
 #include "base/win/windows_version.h"
 #include "build/build_config.h"
 #include "ui/base/ime/input_method.h"
diff --git a/ui/webui/resources/html/i18n_template.html b/ui/webui/resources/html/i18n_template.html
deleted file mode 100644
index 64203de..0000000
--- a/ui/webui/resources/html/i18n_template.html
+++ /dev/null
@@ -1,2 +0,0 @@
-<script src="../js/i18n_template_no_process.js"></script>
-<script src="../js/i18n_template_process.js"></script>
diff --git a/ui/webui/resources/js/i18n_template.js b/ui/webui/resources/js/i18n_template.js
index 02d7245..fffeb12 100644
--- a/ui/webui/resources/js/i18n_template.js
+++ b/ui/webui/resources/js/i18n_template.js
@@ -2,9 +2,5 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// Note: vulcanize sometimes disables GRIT processing. If you're importing i18n
-// stuff with <link rel="import">, you should probably be using
-// html/i18n_template.html instead of this file.
-
 // <include src="i18n_template_no_process.js">
 // <include src="i18n_template_process.js">
diff --git a/ui/webui/resources/webui_resources.grd b/ui/webui/resources/webui_resources.grd
index 8cb513f..ac47774 100644
--- a/ui/webui/resources/webui_resources.grd
+++ b/ui/webui/resources/webui_resources.grd
@@ -365,9 +365,6 @@
                  compress="gzip" />
       <structure name="IDR_WEBUI_HTML_ICON"
                  file="html/icon.html" type="chrome_html" compress="gzip" />
-      <structure name="IDR_WEBUI_HTML_I18N_TEMPLATE"
-                 file="html/i18n_template.html" type="chrome_html"
-                 compress="gzip" />
       <structure name="IDR_WEBUI_HTML_LOAD_TIME_DATA"
                  file="html/load_time_data.html" type="chrome_html"
                  compress="gzip" />