diff --git a/DEPS b/DEPS
index d2cad34..84156b0 100644
--- a/DEPS
+++ b/DEPS
@@ -194,11 +194,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'f4f8011aef1912dd54dc703d209b2a4a4d72fe69',
+  'skia_revision': '9421094d01b1c47e1b913b4b6c594058c521c2fc',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '8db0c721217075a2281129f7dd8ab5cd0cf1e377',
+  'v8_revision': 'a721ddbab67cddef2aa3a686d0f60113c2514c32',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -206,11 +206,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'e5c184751160fb0f314ee2227e5fadca440d688e',
+  'angle_revision': '4ad0f250a01010651985f2a1772c5cff11257d7a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
-  'swiftshader_revision': '2490b1ae774d558439c0ca8010a4f13cb024ab96',
+  'swiftshader_revision': '1de497cc50ab0199e47d5ba8371654c0f6fde85a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
@@ -317,7 +317,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '4e2d7cff8fc304aa9cd7cb6476c7ff72f289ed95',
+  'dawn_revision': 'b31f5e717e2d5de567ee7a5b6a32acdf16ba180c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -888,7 +888,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'fad2090a5e813bb61aa85ec1f7a565cc7ca09ccb',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '9d9199a509bf792d7d24ac91d92ed0d111f8d9fb',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1074,7 +1074,7 @@
   },
 
   'src/third_party/leveldatabase/src':
-    Var('chromium_git') + '/external/leveldb.git' + '@' + '5bd5f0f67a5eb0ed74c16b3ae847ec4e5bc3e412',
+    Var('chromium_git') + '/external/leveldb.git' + '@' + 'c46e79c760125f9adb87a575d94034032637f8d0',
 
   'src/third_party/libFuzzer/src':
     Var('chromium_git') + '/chromium/llvm-project/compiler-rt/lib/fuzzer.git' + '@' +  Var('libfuzzer_revision'),
@@ -1541,7 +1541,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@61e9eac61475a160b74efd753b220c5a2ff3cbf7',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@24010e318dc48b5e77cc7cd9916a45b0825cb47a',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/ash/ambient/ui/assistant_response_container_view.cc b/ash/ambient/ui/assistant_response_container_view.cc
index 020e198..4eb15e3a 100644
--- a/ash/ambient/ui/assistant_response_container_view.cc
+++ b/ash/ambient/ui/assistant_response_container_view.cc
@@ -6,10 +6,12 @@
 
 #include "ash/assistant/model/assistant_response.h"
 #include "ash/assistant/model/ui/assistant_card_element.h"
+#include "ash/assistant/model/ui/assistant_error_element.h"
 #include "ash/assistant/model/ui/assistant_text_element.h"
 #include "ash/assistant/model/ui/assistant_ui_element.h"
 #include "ash/assistant/ui/assistant_view_delegate.h"
 #include "ash/assistant/ui/assistant_view_ids.h"
+#include "ash/assistant/ui/main_stage/assistant_error_element_view.h"
 #include "ash/assistant/ui/main_stage/assistant_text_element_view.h"
 #include "ash/assistant/ui/main_stage/element_animator.h"
 #include "ui/views/layout/box_layout.h"
@@ -61,6 +63,10 @@
       AddTextElementView(new AssistantTextElement(
           static_cast<const AssistantCardElement*>(ui_element)->fallback()));
       break;
+    case AssistantUiElementType::kError:
+      AddErrorElementView(
+          static_cast<const AssistantErrorElement*>(ui_element));
+      break;
     case AssistantUiElementType::kText:
       AddTextElementView(static_cast<const AssistantTextElement*>(ui_element));
       break;
@@ -76,4 +82,10 @@
       std::make_unique<AssistantTextElementView>(text_element));
 }
 
+void AssistantResponseContainerView::AddErrorElementView(
+    const AssistantErrorElement* error_element) {
+  content_view()->AddChildView(
+      std::make_unique<AssistantErrorElementView>(error_element));
+}
+
 }  //  namespace ash
diff --git a/ash/ambient/ui/assistant_response_container_view.h b/ash/ambient/ui/assistant_response_container_view.h
index a69e2cc..01aac1d 100644
--- a/ash/ambient/ui/assistant_response_container_view.h
+++ b/ash/ambient/ui/assistant_response_container_view.h
@@ -12,6 +12,7 @@
 
 namespace ash {
 
+class AssistantErrorElement;
 class AssistantTextElement;
 class AssistantViewDelegate;
 
@@ -28,6 +29,7 @@
  private:
   void InitLayout();
   void AddTextElementView(const AssistantTextElement* text_element);
+  void AddErrorElementView(const AssistantErrorElement* error_element);
 
   // AnimatedContainerView:
   std::unique_ptr<ElementAnimator> HandleUiElement(
diff --git a/ash/app_list/views/assistant/assistant_main_stage.cc b/ash/app_list/views/assistant/assistant_main_stage.cc
index bc0e918..17f3c01 100644
--- a/ash/app_list/views/assistant/assistant_main_stage.cc
+++ b/ash/app_list/views/assistant/assistant_main_stage.cc
@@ -194,9 +194,6 @@
   zero_state_view_->SetPaintToLayer();
   zero_state_view_->layer()->SetFillsBoundsOpaquely(false);
 
-  stack_layout->SetVerticalAlignmentForView(
-      zero_state_view_, StackLayout::VerticalAlignment::kCenter);
-
   return content_layout_container;
 }
 
diff --git a/ash/app_list/views/assistant/assistant_page_view.cc b/ash/app_list/views/assistant/assistant_page_view.cc
index 20729d87..d8becd6 100644
--- a/ash/app_list/views/assistant/assistant_page_view.cc
+++ b/ash/app_list/views/assistant/assistant_page_view.cc
@@ -35,6 +35,10 @@
 
 namespace {
 
+// The min/max height of this page.
+constexpr int kMaxHeightDip = 440;
+constexpr int kMinHeightDip = 180;
+
 // The height of the search box in this page.
 constexpr int kSearchBoxHeightDip = 56;
 
@@ -48,9 +52,9 @@
   switch (app_list_view_state) {
     case AppListViewState::kHalf:
     case AppListViewState::kFullscreenSearch:
-      return kMaxHeightEmbeddedDip;
+      return kMaxHeightDip;
     default:
-      return kMinHeightEmbeddedDip;
+      return kMinHeightDip;
   }
 }
 
@@ -88,10 +92,10 @@
     preferred_height =
         std::max(preferred_height, host->GetMinimumSize().height());
 
-    // Snap to |kMaxHeightEmbeddedDip| if |child| exceeds |preferred_height|.
+    // Snap to |kMaxHeightDip| if |child| exceeds |preferred_height|.
     for (const auto* child : host->children()) {
       if (child->GetHeightForWidth(width) > preferred_height)
-        return kMaxHeightEmbeddedDip;
+        return kMaxHeightDip;
     }
 
     return preferred_height;
@@ -128,7 +132,7 @@
 AssistantPageView::AssistantPageView(
     AssistantViewDelegate* assistant_view_delegate)
     : assistant_view_delegate_(assistant_view_delegate),
-      min_height_dip_(kMinHeightEmbeddedDip) {
+      min_height_dip_(kMinHeightDip) {
   InitLayout();
 
   if (AssistantController::Get())  // May be |nullptr| in tests.
@@ -200,7 +204,7 @@
 void AssistantPageView::VisibilityChanged(views::View* starting_from,
                                           bool is_visible) {
   if (starting_from == this && !is_visible)
-    min_height_dip_ = kMinHeightEmbeddedDip;
+    min_height_dip_ = kMinHeightDip;
 }
 
 void AssistantPageView::OnMouseEvent(ui::MouseEvent* event) {
@@ -391,7 +395,7 @@
     return;
 
   if (new_visibility != AssistantVisibility::kVisible) {
-    min_height_dip_ = kMinHeightEmbeddedDip;
+    min_height_dip_ = kMinHeightDip;
     return;
   }
 
diff --git a/ash/app_list/views/assistant/assistant_page_view_unittest.cc b/ash/app_list/views/assistant/assistant_page_view_unittest.cc
index 5220bdd..38f620b 100644
--- a/ash/app_list/views/assistant/assistant_page_view_unittest.cc
+++ b/ash/app_list/views/assistant/assistant_page_view_unittest.cc
@@ -27,6 +27,10 @@
 using chromeos::assistant::AssistantInteractionMetadata;
 using chromeos::assistant::AssistantInteractionType;
 
+// The min/max height of the embedded Assistant.
+constexpr int kMaxHeightDip = 440;
+constexpr int kMinHeightDip = 180;
+
 #define EXPECT_INTERACTION_OF_TYPE(type_)                      \
   ({                                                           \
     base::Optional<AssistantInteractionMetadata> interaction = \
@@ -262,7 +266,7 @@
   ShowAssistantUi();
 
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(kMinHeightEmbeddedDip, main_view()->size().height());
+  EXPECT_EQ(kMinHeightDip, main_view()->size().height());
 }
 
 TEST_F(AssistantPageViewTest,
@@ -272,7 +276,7 @@
   MockTextInteraction().WithTextResponse("Short one-liner");
 
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(kMinHeightEmbeddedDip, main_view()->size().height());
+  EXPECT_EQ(kMinHeightDip, main_view()->size().height());
 }
 
 TEST_F(AssistantPageViewTest, ShouldGetBiggerWithMultilineText) {
@@ -282,7 +286,7 @@
       "This\ntext\nhas\na\nlot\nof\nlinebreaks.");
 
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(kMaxHeightEmbeddedDip, main_view()->size().height());
+  EXPECT_EQ(kMaxHeightDip, main_view()->size().height());
 }
 
 TEST_F(AssistantPageViewTest, ShouldGetBiggerWhenWrappingTextLine) {
@@ -294,7 +298,7 @@
       "If it doesn't, this looks really bad. This is what caused b/134963994.");
 
   base::RunLoop().RunUntilIdle();
-  EXPECT_EQ(kMaxHeightEmbeddedDip, main_view()->size().height());
+  EXPECT_EQ(kMaxHeightDip, main_view()->size().height());
 }
 
 TEST_F(AssistantPageViewTest, ShouldNotRequestFocusWhenOtherAppWindowOpens) {
diff --git a/ash/assistant/assistant_interaction_controller_impl.cc b/ash/assistant/assistant_interaction_controller_impl.cc
index b592e6067..785def47 100644
--- a/ash/assistant/assistant_interaction_controller_impl.cc
+++ b/ash/assistant/assistant_interaction_controller_impl.cc
@@ -14,6 +14,7 @@
 #include "ash/assistant/model/assistant_response.h"
 #include "ash/assistant/model/assistant_ui_model.h"
 #include "ash/assistant/model/ui/assistant_card_element.h"
+#include "ash/assistant/model/ui/assistant_error_element.h"
 #include "ash/assistant/model/ui/assistant_text_element.h"
 #include "ash/assistant/ui/assistant_ui_constants.h"
 #include "ash/assistant/util/assistant_util.h"
@@ -396,16 +397,15 @@
 
 void AssistantInteractionControllerImpl::OnInteractionFinished(
     AssistantInteractionResolution resolution) {
+  model_.SetMicState(MicState::kClosed);
+
   // If we don't have an active interaction, that indicates that this
   // interaction was explicitly stopped outside of LibAssistant. In this case,
   // we ensure that the mic is closed but otherwise ignore this event.
-  if (IsResponseProcessingV2Enabled() && !HasActiveInteraction()) {
-    model_.SetMicState(MicState::kClosed);
+  if (IsResponseProcessingV2Enabled() && !HasActiveInteraction())
     return;
-  }
 
   model_.SetInteractionState(InteractionState::kInactive);
-  model_.SetMicState(MicState::kClosed);
 
   // The mic timeout resolution is delivered inconsistently by LibAssistant. To
   // account for this, we need to check if the interaction resolved normally
@@ -432,23 +432,28 @@
   if (model_.pending_query().type() != AssistantQueryType::kNull)
     model_.CommitPendingQuery();
 
-  if (!IsResponseProcessingV2Enabled()) {
-    // It's possible that the pending response has already been committed. This
-    // occurs if the response contained TTS, as we flush the response to the UI
-    // when TTS is started to reduce latency.
-    if (!model_.pending_response())
-      return;
-  }
+  // It's possible that the pending response has already been committed. This
+  // occurs if the response contained TTS, as we flush the response to the UI
+  // when TTS is started to reduce latency.
+  if (!IsResponseProcessingV2Enabled() && !model_.pending_response())
+    return;
 
   AssistantResponse* response = GetResponseForActiveInteraction();
 
   // Some interaction resolutions require special handling.
   switch (resolution) {
-    case AssistantInteractionResolution::kError:
-      // In the case of error, we show an appropriate message to the user.
-      response->AddUiElement(std::make_unique<AssistantTextElement>(
-          l10n_util::GetStringUTF8(IDS_ASH_ASSISTANT_ERROR_GENERIC)));
+    case AssistantInteractionResolution::kError: {
+      // In the case of error, we show an appropriate message to the user. Do
+      // not show another error if an identical one already exists in the
+      // response.
+      auto err = std::make_unique<AssistantErrorElement>(
+          IDS_ASH_ASSISTANT_ERROR_GENERIC);
+
+      if (!response->ContainsUiElement(err.get()))
+        response->AddUiElement(std::move(err));
+
       break;
+    }
     case AssistantInteractionResolution::kMultiDeviceHotwordLoss:
       // In the case of hotword loss to another device, we show an appropriate
       // message to the user.
@@ -691,9 +696,13 @@
       }
     }
 
-    // Add an error message to the response.
-    response->AddUiElement(std::make_unique<AssistantTextElement>(
-        l10n_util::GetStringUTF8(IDS_ASH_ASSISTANT_ERROR_GENERIC)));
+    // Create an error and add it to response. Do not add it if another
+    // identical error already exists in response.
+    auto err = std::make_unique<AssistantErrorElement>(
+        IDS_ASH_ASSISTANT_ERROR_GENERIC);
+
+    if (!response->ContainsUiElement(err.get()))
+      response->AddUiElement(std::move(err));
   }
 
   response->set_has_tts(true);
@@ -967,12 +976,13 @@
 AssistantInteractionControllerImpl::GetResponseForActiveInteraction() {
   // Returns the response for the active interaction. In response processing v2,
   // this may be the pending response (if no client ops have yet been received)
-  // or else is the committed response. In response processing v2, this is
-  // always the pending response.
-  return IsResponseProcessingV2Enabled() ? model_.pending_response()
-                                               ? model_.pending_response()
-                                               : model_.response()
-                                         : model_.pending_response();
+  // or else is the committed response.
+  if (IsResponseProcessingV2Enabled()) {
+    return model_.pending_response() ? model_.pending_response()
+                                     : model_.response();
+  }
+  // In response processing v1, this is always the pending response.
+  return model_.pending_response();
 }
 
 AssistantVisibility AssistantInteractionControllerImpl::GetVisibility() const {
diff --git a/ash/assistant/assistant_interaction_controller_impl_unittest.cc b/ash/assistant/assistant_interaction_controller_impl_unittest.cc
index f86ad81..7f496f6 100644
--- a/ash/assistant/assistant_interaction_controller_impl_unittest.cc
+++ b/ash/assistant/assistant_interaction_controller_impl_unittest.cc
@@ -4,15 +4,26 @@
 
 #include "ash/assistant/assistant_interaction_controller_impl.h"
 
+#include <algorithm>
 #include <map>
 
 #include "ash/assistant/assistant_suggestions_controller_impl.h"
+#include "ash/assistant/model/assistant_interaction_model.h"
+#include "ash/assistant/model/assistant_interaction_model_observer.h"
+#include "ash/assistant/model/assistant_response.h"
+#include "ash/assistant/model/assistant_response_observer.h"
+#include "ash/assistant/model/ui/assistant_error_element.h"
+#include "ash/assistant/model/ui/assistant_ui_element.h"
 #include "ash/assistant/test/assistant_ash_test_base.h"
+#include "ash/assistant/ui/main_stage/assistant_error_element_view.h"
 #include "ash/public/cpp/assistant/controller/assistant_interaction_controller.h"
 #include "ash/public/cpp/assistant/controller/assistant_suggestions_controller.h"
 #include "ash/test/fake_android_intent_helper.h"
 #include "base/bind.h"
+#include "base/scoped_observer.h"
+#include "base/test/scoped_feature_list.h"
 #include "chromeos/services/assistant/public/cpp/assistant_service.h"
+#include "chromeos/services/assistant/public/cpp/features.h"
 #include "testing/gmock/include/gmock/gmock.h"
 
 namespace ash {
@@ -57,9 +68,21 @@
       this};
 };
 
-class AssistantInteractionControllerImplTest : public AssistantAshTestBase {
+// AssistantInteractionControllerImplTest --------------------------------------
+
+class AssistantInteractionControllerImplTest
+    : public AssistantAshTestBase,
+      public testing::WithParamInterface<bool> {
  public:
-  AssistantInteractionControllerImplTest() = default;
+  AssistantInteractionControllerImplTest() {
+    if (GetParam()) {
+      feature_list_.InitAndEnableFeature(
+          chromeos::assistant::features::kAssistantResponseProcessingV2);
+    } else {
+      feature_list_.InitAndDisableFeature(
+          chromeos::assistant::features::kAssistantResponseProcessingV2);
+    }
+  }
 
   AssistantInteractionControllerImpl* interaction_controller() {
     return static_cast<AssistantInteractionControllerImpl*>(
@@ -85,11 +108,14 @@
     result.localized_app_name = app_name;
     return result;
   }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
 };
 
 }  // namespace
 
-TEST_F(AssistantInteractionControllerImplTest,
+TEST_P(AssistantInteractionControllerImplTest,
        ShouldBecomeActiveWhenInteractionStarts) {
   EXPECT_EQ(interaction_model()->interaction_state(),
             InteractionState::kInactive);
@@ -101,7 +127,7 @@
             InteractionState::kActive);
 }
 
-TEST_F(AssistantInteractionControllerImplTest,
+TEST_P(AssistantInteractionControllerImplTest,
        ShouldReturnErrorWhenOpenAppIsCalledWhileInactive) {
   EXPECT_EQ(interaction_model()->interaction_state(),
             InteractionState::kInactive);
@@ -111,7 +137,7 @@
   EXPECT_EQ(result, kErrorResult);
 }
 
-TEST_F(AssistantInteractionControllerImplTest,
+TEST_P(AssistantInteractionControllerImplTest,
        ShouldReturnErrorWhenOpenAppIsCalledWithoutAnAndroidIntentHelper) {
   StartInteraction();
 
@@ -120,7 +146,7 @@
   EXPECT_EQ(result, kErrorResult);
 }
 
-TEST_F(AssistantInteractionControllerImplTest,
+TEST_P(AssistantInteractionControllerImplTest,
        ShouldReturnErrorWhenOpenAppIsCalledForUnknownAndroidApp) {
   StartInteraction();
   FakeAndroidIntentHelper fake_helper;
@@ -128,7 +154,7 @@
                               CreateAndroidAppInfo("unknown-app-name")));
 }
 
-TEST_F(AssistantInteractionControllerImplTest,
+TEST_P(AssistantInteractionControllerImplTest,
        ShouldLaunchAppAndReturnSuccessWhenOpenAppIsCalled) {
   const std::string app_name = "AppName";
   const std::string intent = "intent://AppName";
@@ -143,7 +169,7 @@
   EXPECT_EQ(intent, fake_helper.last_launched_android_intent());
 }
 
-TEST_F(AssistantInteractionControllerImplTest,
+TEST_P(AssistantInteractionControllerImplTest,
        ShouldAddSchemeToIntentWhenLaunchingAndroidApp) {
   const std::string app_name = "AppName";
   const std::string intent = "#Intent-without-a-scheme";
@@ -159,7 +185,7 @@
   EXPECT_EQ(intent_with_scheme, fake_helper.last_launched_android_intent());
 }
 
-TEST_F(AssistantInteractionControllerImplTest,
+TEST_P(AssistantInteractionControllerImplTest,
        ShouldCorrectlyMapSuggestionTypeToQuerySource) {
   // Mock Assistant interaction subscriber.
   StrictMock<AssistantInteractionSubscriberMock> mock(assistant_service());
@@ -197,4 +223,36 @@
   }
 }
 
+TEST_P(AssistantInteractionControllerImplTest, ShouldDisplayGenericErrorOnce) {
+  StartInteraction();
+
+  // Call OnTtsStarted twice to mimic the behavior of libassistant when network
+  // is disconnected.
+  interaction_controller()->OnTtsStarted(/*due_to_error=*/true);
+  interaction_controller()->OnTtsStarted(/*due_to_error=*/true);
+
+  base::RunLoop().RunUntilIdle();
+
+  auto& ui_elements =
+      interaction_controller()->GetModel()->response()->GetUiElements();
+
+  EXPECT_EQ(ui_elements.size(), 1ul);
+  EXPECT_EQ(ui_elements.front()->type(), AssistantUiElementType::kError);
+
+  base::RunLoop().RunUntilIdle();
+
+  interaction_controller()->OnInteractionFinished(
+      chromeos::assistant::AssistantInteractionResolution::kError);
+
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_EQ(ui_elements.size(), 1ul);
+  EXPECT_EQ(ui_elements.front()->type(), AssistantUiElementType::kError);
+}
+
+// We parameterize all AssistantInteractionControllerImplTests to verify that
+// they work for both response processing v1 as well as response processing v2.
+INSTANTIATE_TEST_SUITE_P(All,
+                         AssistantInteractionControllerImplTest,
+                         testing::Bool());
 }  // namespace ash
diff --git a/ash/assistant/model/BUILD.gn b/ash/assistant/model/BUILD.gn
index 1cbf09d..d4a6363 100644
--- a/ash/assistant/model/BUILD.gn
+++ b/ash/assistant/model/BUILD.gn
@@ -37,6 +37,8 @@
     "assistant_ui_model_observer.h",
     "ui/assistant_card_element.cc",
     "ui/assistant_card_element.h",
+    "ui/assistant_error_element.cc",
+    "ui/assistant_error_element.h",
     "ui/assistant_text_element.cc",
     "ui/assistant_text_element.h",
     "ui/assistant_ui_element.cc",
diff --git a/ash/assistant/model/assistant_response.cc b/ash/assistant/model/assistant_response.cc
index afc1533..28e1248 100644
--- a/ash/assistant/model/assistant_response.cc
+++ b/ash/assistant/model/assistant_response.cc
@@ -4,9 +4,11 @@
 
 #include "ash/assistant/model/assistant_response.h"
 
+#include <algorithm>
 #include <utility>
 
 #include "ash/assistant/model/assistant_response_observer.h"
+#include "ash/assistant/model/ui/assistant_error_element.h"
 #include "ash/assistant/model/ui/assistant_ui_element.h"
 #include "base/bind.h"
 #include "base/memory/weak_ptr.h"
@@ -205,4 +207,26 @@
     observer.OnSuggestionsAdded(suggestions);
 }
 
+bool AssistantResponse::ContainsUiElement(
+    const AssistantUiElement* element) const {
+  DCHECK(element);
+
+  bool contains_element =
+      std::any_of(ui_elements_.cbegin(), ui_elements_.cend(),
+                  [element](const std::unique_ptr<AssistantUiElement>& other) {
+                    return *other == *element;
+                  });
+
+  return contains_element || ContainsPendingUiElement(element);
+}
+
+bool AssistantResponse::ContainsPendingUiElement(
+    const AssistantUiElement* element) const {
+  DCHECK(element);
+
+  return std::any_of(pending_ui_elements_.cbegin(), pending_ui_elements_.cend(),
+                     [element](const std::unique_ptr<PendingUiElement>& other) {
+                       return *other->ui_element == *element;
+                     });
+}
 }  // namespace ash
diff --git a/ash/assistant/model/assistant_response.h b/ash/assistant/model/assistant_response.h
index 712d9fb8..74499ae 100644
--- a/ash/assistant/model/assistant_response.h
+++ b/ash/assistant/model/assistant_response.h
@@ -88,10 +88,16 @@
   // all UI elements in the response.
   void Process(ProcessingCallback callback);
 
+  // Return true if this response contains an identical ui element.
+  bool ContainsUiElement(const AssistantUiElement* element) const;
+
  private:
   void NotifyUiElementAdded(const AssistantUiElement* ui_element);
   void NotifySuggestionsAdded(const std::vector<AssistantSuggestion>&);
 
+  // Return true if the pending ui elements contain an identical ui element.
+  bool ContainsPendingUiElement(const AssistantUiElement* other) const;
+
   struct PendingUiElement;
   class Processor;
 
diff --git a/ash/assistant/model/ui/assistant_card_element.cc b/ash/assistant/model/ui/assistant_card_element.cc
index 95739b2a..6c46d4d 100644
--- a/ash/assistant/model/ui/assistant_card_element.cc
+++ b/ash/assistant/model/ui/assistant_card_element.cc
@@ -32,8 +32,7 @@
 
   void Process() {
     // TODO(dmblack): Find a better way of determining desired card size.
-    const int width_dip =
-        kPreferredWidthDip - 2 * kUiElementHorizontalMarginDip;
+    const int width_dip = kPreferredWidthDip - 2 * kHorizontalMarginDip;
 
     // Configure parameters for the card.
     AssistantWebView::InitParams contents_params;
@@ -95,4 +94,9 @@
   processor_->Process();
 }
 
+bool AssistantCardElement::Compare(const AssistantUiElement& other) const {
+  return other.type() == AssistantUiElementType::kCard &&
+         static_cast<const AssistantCardElement&>(other).html() == html_;
+}
+
 }  // namespace ash
diff --git a/ash/assistant/model/ui/assistant_card_element.h b/ash/assistant/model/ui/assistant_card_element.h
index e9b0c94..bdcba089 100644
--- a/ash/assistant/model/ui/assistant_card_element.h
+++ b/ash/assistant/model/ui/assistant_card_element.h
@@ -7,6 +7,7 @@
 
 #include <memory>
 #include <string>
+#include <utility>
 
 #include "ash/assistant/model/ui/assistant_ui_element.h"
 #include "ash/public/cpp/assistant/assistant_web_view.h"
@@ -45,6 +46,9 @@
 
   std::unique_ptr<Processor> processor_;
 
+  // AssistantUiElement:
+  bool Compare(const AssistantUiElement& other) const override;
+
   DISALLOW_COPY_AND_ASSIGN(AssistantCardElement);
 };
 
diff --git a/ash/assistant/model/ui/assistant_error_element.cc b/ash/assistant/model/ui/assistant_error_element.cc
new file mode 100644
index 0000000..ffa1c95
--- /dev/null
+++ b/ash/assistant/model/ui/assistant_error_element.cc
@@ -0,0 +1,23 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/assistant/model/ui/assistant_error_element.h"
+
+#include "ash/assistant/ui/assistant_ui_constants.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace ash {
+
+AssistantErrorElement::AssistantErrorElement(int message_id)
+    : AssistantUiElement(AssistantUiElementType::kError),
+      message_id_(message_id) {}
+
+AssistantErrorElement::~AssistantErrorElement() = default;
+
+bool AssistantErrorElement::Compare(const AssistantUiElement& other) const {
+  return other.type() == AssistantUiElementType::kError &&
+         static_cast<const AssistantErrorElement&>(other).message_id() ==
+             message_id_;
+}
+}  // namespace ash
diff --git a/ash/assistant/model/ui/assistant_error_element.h b/ash/assistant/model/ui/assistant_error_element.h
new file mode 100644
index 0000000..4278849e
--- /dev/null
+++ b/ash/assistant/model/ui/assistant_error_element.h
@@ -0,0 +1,37 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_ASSISTANT_MODEL_UI_ASSISTANT_ERROR_ELEMENT_H_
+#define ASH_ASSISTANT_MODEL_UI_ASSISTANT_ERROR_ELEMENT_H_
+
+#include <string>
+
+#include "ash/assistant/model/ui/assistant_ui_element.h"
+#include "base/component_export.h"
+
+namespace ash {
+
+// An Assistant UI error element that will be rendered as text.
+class COMPONENT_EXPORT(ASSISTANT_MODEL) AssistantErrorElement
+    : public AssistantUiElement {
+ public:
+  explicit AssistantErrorElement(int message_id);
+
+  AssistantErrorElement(const AssistantErrorElement&) = delete;
+  AssistantErrorElement& operator=(const AssistantErrorElement&) = delete;
+
+  ~AssistantErrorElement() override;
+
+  int message_id() const { return message_id_; }
+
+ private:
+  const int message_id_;
+
+  // AssistantUiElement:
+  bool Compare(const AssistantUiElement& other) const override;
+};
+
+}  // namespace ash
+
+#endif  // ASH_ASSISTANT_MODEL_UI_ASSISTANT_ERROR_ELEMENT_H_
diff --git a/ash/assistant/model/ui/assistant_text_element.cc b/ash/assistant/model/ui/assistant_text_element.cc
index d387ec6..4f918d02 100644
--- a/ash/assistant/model/ui/assistant_text_element.cc
+++ b/ash/assistant/model/ui/assistant_text_element.cc
@@ -13,4 +13,9 @@
 
 AssistantTextElement::~AssistantTextElement() = default;
 
+bool AssistantTextElement::Compare(const AssistantUiElement& other) const {
+  return other.type() == AssistantUiElementType::kText &&
+         static_cast<const AssistantTextElement&>(other).text() == text_;
+}
+
 }  // namespace ash
diff --git a/ash/assistant/model/ui/assistant_text_element.h b/ash/assistant/model/ui/assistant_text_element.h
index 84e6e0b..f146693 100644
--- a/ash/assistant/model/ui/assistant_text_element.h
+++ b/ash/assistant/model/ui/assistant_text_element.h
@@ -25,6 +25,9 @@
  private:
   const std::string text_;
 
+  // AssistantUiElement:
+  bool Compare(const AssistantUiElement& other) const override;
+
   DISALLOW_COPY_AND_ASSIGN(AssistantTextElement);
 };
 
diff --git a/ash/assistant/model/ui/assistant_ui_element.h b/ash/assistant/model/ui/assistant_ui_element.h
index bc40aab..81bdb9ad 100644
--- a/ash/assistant/model/ui/assistant_ui_element.h
+++ b/ash/assistant/model/ui/assistant_ui_element.h
@@ -15,8 +15,9 @@
 
 // Defines possible types of Assistant UI elements.
 enum class AssistantUiElementType {
-  kCard,    // See AssistantCardElement.
-  kText,    // See AssistantTextElement.
+  kCard,   // See AssistantCardElement.
+  kError,  // See AssistantErrorElement.
+  kText,   // See AssistantTextElement.
 };
 
 // AssistantUiElement ----------------------------------------------------------
@@ -26,6 +27,10 @@
  public:
   virtual ~AssistantUiElement();
 
+  bool operator==(const AssistantUiElement& other) const {
+    return this->Compare(other);
+  }
+
   AssistantUiElementType type() const { return type_; }
 
   // Invoke to being processing the UI element for rendering. The specified
@@ -42,6 +47,8 @@
  private:
   const AssistantUiElementType type_;
 
+  virtual bool Compare(const AssistantUiElement& other) const = 0;
+
   DISALLOW_COPY_AND_ASSIGN(AssistantUiElement);
 };
 
diff --git a/ash/assistant/ui/BUILD.gn b/ash/assistant/ui/BUILD.gn
index f61e5003..e2251e6 100644
--- a/ash/assistant/ui/BUILD.gn
+++ b/ash/assistant/ui/BUILD.gn
@@ -52,6 +52,8 @@
     "main_stage/animated_container_view.h",
     "main_stage/assistant_card_element_view.cc",
     "main_stage/assistant_card_element_view.h",
+    "main_stage/assistant_error_element_view.cc",
+    "main_stage/assistant_error_element_view.h",
     "main_stage/assistant_footer_view.cc",
     "main_stage/assistant_footer_view.h",
     "main_stage/assistant_onboarding_view.cc",
diff --git a/ash/assistant/ui/assistant_ui_constants.h b/ash/assistant/ui/assistant_ui_constants.h
index c9c5872..8667802 100644
--- a/ash/assistant/ui/assistant_ui_constants.h
+++ b/ash/assistant/ui/assistant_ui_constants.h
@@ -17,16 +17,11 @@
 namespace ash {
 
 // Appearance.
-constexpr int kCornerRadiusDip = 20;
-constexpr int kMiniUiCornerRadiusDip = 24;
-constexpr int kMaxHeightDip = 640;
-constexpr int kMaxHeightEmbeddedDip = 440;
-constexpr int kMinHeightEmbeddedDip = 180;
 constexpr int kPaddingDip = 14;
 constexpr int kPreferredWidthDip = 640;
 constexpr int kSpacingDip = 8;
 constexpr int kMarginDip = 8;
-constexpr int kUiElementHorizontalMarginDip = 32;
+constexpr int kHorizontalMarginDip = 32;
 
 // Typography.
 constexpr SkColor kTextColorPrimary = gfx::kGoogleGrey900;
diff --git a/ash/assistant/ui/main_stage/assistant_error_element_view.cc b/ash/assistant/ui/main_stage/assistant_error_element_view.cc
new file mode 100644
index 0000000..e49a8a8c
--- /dev/null
+++ b/ash/assistant/ui/main_stage/assistant_error_element_view.cc
@@ -0,0 +1,21 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/assistant/ui/main_stage/assistant_error_element_view.h"
+
+#include "ash/assistant/model/ui/assistant_error_element.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace ash {
+
+AssistantErrorElementView::AssistantErrorElementView(
+    const AssistantErrorElement* error_element)
+    : AssistantTextElementView(
+          l10n_util::GetStringUTF8(error_element->message_id())) {}
+
+const char* AssistantErrorElementView::GetClassName() const {
+  return "AssistantErrorElementView";
+}
+
+}  // namespace ash
diff --git a/ash/assistant/ui/main_stage/assistant_error_element_view.h b/ash/assistant/ui/main_stage/assistant_error_element_view.h
new file mode 100644
index 0000000..580ea43
--- /dev/null
+++ b/ash/assistant/ui/main_stage/assistant_error_element_view.h
@@ -0,0 +1,29 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef ASH_ASSISTANT_UI_MAIN_STAGE_ASSISTANT_ERROR_ELEMENT_VIEW_H_
+#define ASH_ASSISTANT_UI_MAIN_STAGE_ASSISTANT_ERROR_ELEMENT_VIEW_H_
+
+#include "ash/assistant/model/ui/assistant_error_element.h"
+#include "ash/assistant/ui/main_stage/assistant_text_element_view.h"
+#include "base/component_export.h"
+
+namespace ash {
+
+// AssistantErrorElementView is the visual representation of an
+// AssistantErrorElement. AssistantErrorElementView uses the same rendering
+// logic as AssistantTextElementView.
+class COMPONENT_EXPORT(ASSISTANT_UI) AssistantErrorElementView
+    : public AssistantTextElementView {
+ public:
+  explicit AssistantErrorElementView(
+      const AssistantErrorElement* error_element);
+
+  // AssistantTextElementView:
+  const char* GetClassName() const override;
+};
+
+}  // namespace ash
+
+#endif  // ASH_ASSISTANT_UI_MAIN_STAGE_ASSISTANT_ERROR_ELEMENT_VIEW_H_
diff --git a/ash/assistant/ui/main_stage/assistant_onboarding_view.cc b/ash/assistant/ui/main_stage/assistant_onboarding_view.cc
index 7585fe9..2cd0c1d 100644
--- a/ash/assistant/ui/main_stage/assistant_onboarding_view.cc
+++ b/ash/assistant/ui/main_stage/assistant_onboarding_view.cc
@@ -41,30 +41,28 @@
 using chromeos::assistant::AssistantSuggestion;
 using chromeos::assistant::AssistantSuggestionType;
 
-constexpr int kHorizontalMarginDip = 56;
-
 // Greeting.
-constexpr int kGreetingLabelLineHeight = 24;
-constexpr int kGreetingLabelSizeDelta = 8;
+constexpr int kGreetingLabelLineHeight = 28;
+constexpr int kGreetingLabelSizeDelta = 10;
 
 // Intro.
-constexpr int kIntroLabelLineHeight = 22;
+constexpr int kIntroLabelLineHeight = 20;
 constexpr int kIntroLabelMarginTopDip = 12;
-constexpr int kIntroLabelSizeDelta = 3;
+constexpr int kIntroLabelSizeDelta = 2;
 
 // Suggestions.
 constexpr int kSuggestionsColumnCount = 3;
 constexpr int kSuggestionsColumnSetId = 1;
-constexpr int kSuggestionsCornerRadiusDip = 16;
+constexpr int kSuggestionsCornerRadiusDip = 12;
 constexpr int kSuggestionsIconSizeDip = 24;
 constexpr int kSuggestionsLabelLineHeight = 20;
 constexpr int kSuggestionsLabelSizeDelta = 2;
 constexpr int kSuggestionsMaxCount = 6;
 constexpr int kSuggestionsMarginDip = 16;
-constexpr int kSuggestionsMarginTopDip = 48;
+constexpr int kSuggestionsMarginTopDip = 32;
 constexpr int kSuggestionsPaddingDip = 16;
 constexpr int kSuggestionsPreferredHeightDip = 72;
-constexpr int kSuggestionsSpacingDip = 12;
+constexpr int kSuggestionsSpacingDip = 16;
 
 // Helpers ---------------------------------------------------------------------
 
@@ -105,8 +103,12 @@
   DCHECK_GE(index, 0);
   DCHECK_LT(index, kSuggestionsMaxCount);
   constexpr SkColor background_colors[kSuggestionsMaxCount] = {
-      gfx::kGoogleBlue050,   gfx::kGoogleYellow050, gfx::kGoogleGreen050,
-      gfx::kGoogleYellow050, gfx::kGoogleGreen050,  gfx::kGoogleRed050};
+      gfx::kGoogleBlue050,
+      gfx::kGoogleRed050,
+      gfx::kGoogleYellow050,
+      gfx::kGoogleGreen050,
+      SkColorSetRGB(0xF6, 0xE9, 0xF8),
+      gfx::kGoogleBlue050};
   return background_colors[index];
 }
 
@@ -114,8 +116,12 @@
   DCHECK_GE(index, 0);
   DCHECK_LT(index, kSuggestionsMaxCount);
   constexpr SkColor foreground_colors[kSuggestionsMaxCount] = {
-      gfx::kGoogleBlue700,   gfx::kGoogleYellow900, gfx::kGoogleGreen800,
-      gfx::kGoogleYellow900, gfx::kGoogleGreen800,  gfx::kGoogleRed800};
+      gfx::kGoogleBlue800,
+      gfx::kGoogleRed800,
+      SkColorSetRGB(0xBF, 0x50, 0x00),
+      gfx::kGoogleGreen800,
+      SkColorSetRGB(0x8A, 0x0E, 0x9E),
+      gfx::kGoogleBlue800};
   return foreground_colors[index];
 }
 
@@ -191,8 +197,9 @@
     label_ = AddChildView(std::make_unique<views::Label>());
     label_->SetAutoColorReadabilityEnabled(false);
     label_->SetEnabledColor(GetSuggestionForegroundColor(index_));
-    label_->SetFontList(assistant::ui::GetDefaultFontList().DeriveWithSizeDelta(
-        kSuggestionsLabelSizeDelta));
+    label_->SetFontList(assistant::ui::GetDefaultFontList()
+                            .DeriveWithSizeDelta(kSuggestionsLabelSizeDelta)
+                            .DeriveWithWeight(gfx::Font::Weight::MEDIUM));
     label_->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
     label_->SetLineHeight(kSuggestionsLabelLineHeight);
     label_->SetMaxLines(2);
@@ -285,7 +292,7 @@
   greeting_ = AddChildView(std::make_unique<views::Label>());
   greeting_->SetAutoColorReadabilityEnabled(false);
   greeting_->SetBackground(views::CreateSolidBackground(SK_ColorWHITE));
-  greeting_->SetEnabledColor(SK_ColorBLACK);
+  greeting_->SetEnabledColor(kTextColorPrimary);
   greeting_->SetFontList(assistant::ui::GetDefaultFontList()
                              .DeriveWithSizeDelta(kGreetingLabelSizeDelta)
                              .DeriveWithWeight(gfx::Font::Weight::MEDIUM));
@@ -298,7 +305,7 @@
   intro->SetAutoColorReadabilityEnabled(false);
   intro->SetBackground(views::CreateSolidBackground(SK_ColorWHITE));
   intro->SetBorder(views::CreateEmptyBorder(kIntroLabelMarginTopDip, 0, 0, 0));
-  intro->SetEnabledColor(gfx::kGoogleGrey900);
+  intro->SetEnabledColor(kTextColorPrimary);
   intro->SetFontList(assistant::ui::GetDefaultFontList()
                          .DeriveWithSizeDelta(kIntroLabelSizeDelta)
                          .DeriveWithWeight(gfx::Font ::Weight::MEDIUM));
diff --git a/ash/assistant/ui/main_stage/assistant_onboarding_view_unittest.cc b/ash/assistant/ui/main_stage/assistant_onboarding_view_unittest.cc
index e2974c46..e7b8007 100644
--- a/ash/assistant/ui/main_stage/assistant_onboarding_view_unittest.cc
+++ b/ash/assistant/ui/main_stage/assistant_onboarding_view_unittest.cc
@@ -293,53 +293,53 @@
         expected_suggestions.push_back(
             {/*message=*/"Square root of 71",
              /*icon_with_color=*/std::make_unique<VectorIconWithColor>(
-                 ash::kCalculateIcon, gfx::kGoogleBlue700)});
+                 ash::kCalculateIcon, gfx::kGoogleBlue800)});
         expected_suggestions.push_back(
             {/*message=*/"How far is Venus",
              /*icon_with_color=*/std::make_unique<VectorIconWithColor>(
-                 ash::kStraightenIcon, gfx::kGoogleYellow900)});
+                 ash::kStraightenIcon, gfx::kGoogleRed800)});
         expected_suggestions.push_back(
             {/*message=*/"Set timer",
              /*icon_with_color=*/std::make_unique<VectorIconWithColor>(
-                 ash::kTimerIcon, gfx::kGoogleGreen800)});
+                 ash::kTimerIcon, SkColorSetRGB(0xBF, 0x50, 0x00))});
         expected_suggestions.push_back(
             {/*message=*/"Tell me a joke",
              /*icon_with_color=*/std::make_unique<VectorIconWithColor>(
-                 ash::kSentimentVerySatisfiedIcon, gfx::kGoogleYellow900)});
+                 ash::kSentimentVerySatisfiedIcon, gfx::kGoogleGreen800)});
         expected_suggestions.push_back(
             {/*message=*/"\"Hello\" in Chinese",
              /*icon_with_color=*/std::make_unique<VectorIconWithColor>(
-                 ash::kTranslateIcon, gfx::kGoogleGreen800)});
+                 ash::kTranslateIcon, SkColorSetRGB(0x8A, 0x0E, 0x9E))});
         expected_suggestions.push_back(
             {/*message=*/"Take a screenshot",
              /*icon_with_color=*/std::make_unique<VectorIconWithColor>(
-                 ash::kScreenshotIcon, gfx::kGoogleRed800)});
+                 ash::kScreenshotIcon, gfx::kGoogleBlue800)});
         break;
       case AssistantOnboardingMode::kDefault:
         expected_suggestions.push_back(
             {/*message=*/"5K in miles",
              /*icon_with_color=*/std::make_unique<VectorIconWithColor>(
-                 ash::kConversionPathIcon, gfx::kGoogleBlue700)});
+                 ash::kConversionPathIcon, gfx::kGoogleBlue800)});
         expected_suggestions.push_back(
             {/*message=*/"Population in Nigeria",
              /*icon_with_color=*/std::make_unique<VectorIconWithColor>(
-                 ash::kPersonPinCircleIcon, gfx::kGoogleYellow900)});
+                 ash::kPersonPinCircleIcon, gfx::kGoogleRed800)});
         expected_suggestions.push_back(
             {/*message=*/"Set timer",
              /*icon_with_color=*/std::make_unique<VectorIconWithColor>(
-                 ash::kTimerIcon, gfx::kGoogleGreen800)});
+                 ash::kTimerIcon, SkColorSetRGB(0xBF, 0x50, 0x00))});
         expected_suggestions.push_back(
             {/*message=*/"Tell me a joke",
              /*icon_with_color=*/std::make_unique<VectorIconWithColor>(
-                 ash::kSentimentVerySatisfiedIcon, gfx::kGoogleYellow900)});
+                 ash::kSentimentVerySatisfiedIcon, gfx::kGoogleGreen800)});
         expected_suggestions.push_back(
             {/*message=*/"\"Hello\" in Chinese",
              /*icon_with_color=*/std::make_unique<VectorIconWithColor>(
-                 ash::kTranslateIcon, gfx::kGoogleGreen800)});
+                 ash::kTranslateIcon, SkColorSetRGB(0x8A, 0x0E, 0x9E))});
         expected_suggestions.push_back(
             {/*message=*/"Take a screenshot",
              /*icon_with_color=*/std::make_unique<VectorIconWithColor>(
-                 ash::kScreenshotIcon, gfx::kGoogleRed800)});
+                 ash::kScreenshotIcon, gfx::kGoogleBlue800)});
         break;
     }
 
diff --git a/ash/assistant/ui/main_stage/assistant_text_element_view.cc b/ash/assistant/ui/main_stage/assistant_text_element_view.cc
index 167baf5..0e1173e 100644
--- a/ash/assistant/ui/main_stage/assistant_text_element_view.cc
+++ b/ash/assistant/ui/main_stage/assistant_text_element_view.cc
@@ -18,8 +18,11 @@
 // AssistantTextElementView ----------------------------------------------------
 
 AssistantTextElementView::AssistantTextElementView(
-    const AssistantTextElement* text_element) {
-  InitLayout(text_element);
+    const AssistantTextElement* text_element)
+    : AssistantTextElementView(text_element->text()) {}
+
+AssistantTextElementView::AssistantTextElementView(const std::string& text) {
+  InitLayout(text);
 }
 
 AssistantTextElementView::~AssistantTextElementView() = default;
@@ -46,13 +49,12 @@
   PreferredSizeChanged();
 }
 
-void AssistantTextElementView::InitLayout(
-    const AssistantTextElement* text_element) {
+void AssistantTextElementView::InitLayout(const std::string& text) {
   SetLayoutManager(std::make_unique<views::FillLayout>());
 
   // Label.
-  label_ = AddChildView(
-      std::make_unique<views::Label>(base::UTF8ToUTF16(text_element->text())));
+  label_ =
+      AddChildView(std::make_unique<views::Label>(base::UTF8ToUTF16(text)));
   label_->SetAutoColorReadabilityEnabled(false);
   label_->SetBackground(views::CreateSolidBackground(SK_ColorWHITE));
   label_->SetEnabledColor(kTextColorPrimary);
diff --git a/ash/assistant/ui/main_stage/assistant_text_element_view.h b/ash/assistant/ui/main_stage/assistant_text_element_view.h
index ffc7cba..05c1a24e 100644
--- a/ash/assistant/ui/main_stage/assistant_text_element_view.h
+++ b/ash/assistant/ui/main_stage/assistant_text_element_view.h
@@ -25,6 +25,9 @@
     : public AssistantUiElementView {
  public:
   explicit AssistantTextElementView(const AssistantTextElement* text_element);
+
+  explicit AssistantTextElementView(const std::string& text);
+
   ~AssistantTextElementView() override;
 
   // AssistantUiElementView:
@@ -34,7 +37,7 @@
   void ChildPreferredSizeChanged(views::View* child) override;
 
  private:
-  void InitLayout(const AssistantTextElement* text_element);
+  void InitLayout(const std::string& text);
 
   views::Label* label_;  // Owned by view hierarchy.
 
diff --git a/ash/assistant/ui/main_stage/assistant_ui_element_view_factory.cc b/ash/assistant/ui/main_stage/assistant_ui_element_view_factory.cc
index ad27ff4..2aa5130 100644
--- a/ash/assistant/ui/main_stage/assistant_ui_element_view_factory.cc
+++ b/ash/assistant/ui/main_stage/assistant_ui_element_view_factory.cc
@@ -5,10 +5,12 @@
 #include "ash/assistant/ui/main_stage/assistant_ui_element_view_factory.h"
 
 #include "ash/assistant/model/ui/assistant_card_element.h"
+#include "ash/assistant/model/ui/assistant_error_element.h"
 #include "ash/assistant/model/ui/assistant_text_element.h"
 #include "ash/assistant/model/ui/assistant_ui_element.h"
 #include "ash/assistant/ui/assistant_view_delegate.h"
 #include "ash/assistant/ui/main_stage/assistant_card_element_view.h"
+#include "ash/assistant/ui/main_stage/assistant_error_element_view.h"
 #include "ash/assistant/ui/main_stage/assistant_text_element_view.h"
 #include "ash/assistant/ui/main_stage/assistant_ui_element_view.h"
 
@@ -26,6 +28,9 @@
     case AssistantUiElementType::kCard:
       return std::make_unique<AssistantCardElementView>(
           delegate_, static_cast<const AssistantCardElement*>(ui_element));
+    case AssistantUiElementType::kError:
+      return std::make_unique<AssistantErrorElementView>(
+          static_cast<const AssistantErrorElement*>(ui_element));
     case AssistantUiElementType::kText:
       return std::make_unique<AssistantTextElementView>(
           static_cast<const AssistantTextElement*>(ui_element));
diff --git a/ash/assistant/ui/main_stage/assistant_zero_state_view.cc b/ash/assistant/ui/main_stage/assistant_zero_state_view.cc
index 93628af1c..cb59dfb 100644
--- a/ash/assistant/ui/main_stage/assistant_zero_state_view.cc
+++ b/ash/assistant/ui/main_stage/assistant_zero_state_view.cc
@@ -17,6 +17,7 @@
 #include "chromeos/services/assistant/public/cpp/features.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/views/background.h"
+#include "ui/views/border.h"
 #include "ui/views/controls/label.h"
 #include "ui/views/layout/fill_layout.h"
 
@@ -26,6 +27,10 @@
 
 using chromeos::assistant::features::IsBetterOnboardingEnabled;
 
+// Appearance.
+constexpr int kGreetingLabelTopMarginDip = 28;
+constexpr int kOnboardingViewTopMarginDip = 48;
+
 }  // namespace
 
 AssistantZeroStateView::AssistantZeroStateView(AssistantViewDelegate* delegate)
@@ -79,6 +84,8 @@
   if (IsBetterOnboardingEnabled()) {
     onboarding_view_ =
         AddChildView(std::make_unique<AssistantOnboardingView>(delegate_));
+    onboarding_view_->SetBorder(
+        views::CreateEmptyBorder(kOnboardingViewTopMarginDip, 0, 0, 0));
   }
 
   // Greeting.
@@ -86,6 +93,8 @@
   greeting_label_->SetID(AssistantViewID::kGreetingLabel);
   greeting_label_->SetAutoColorReadabilityEnabled(false);
   greeting_label_->SetBackground(views::CreateSolidBackground(SK_ColorWHITE));
+  greeting_label_->SetBorder(
+      views::CreateEmptyBorder(kGreetingLabelTopMarginDip, 0, 0, 0));
   greeting_label_->SetEnabledColor(kTextColorPrimary);
   greeting_label_->SetFontList(
       assistant::ui::GetDefaultFontList()
diff --git a/ash/assistant/ui/main_stage/ui_element_container_view.cc b/ash/assistant/ui/main_stage/ui_element_container_view.cc
index 360fb32a..0e2cf45 100644
--- a/ash/assistant/ui/main_stage/ui_element_container_view.cc
+++ b/ash/assistant/ui/main_stage/ui_element_container_view.cc
@@ -90,8 +90,8 @@
   // Content.
   content_view()->SetLayoutManager(std::make_unique<views::BoxLayout>(
       views::BoxLayout::Orientation::kVertical,
-      gfx::Insets(0, kUiElementHorizontalMarginDip, kPaddingBottomDip,
-                  kUiElementHorizontalMarginDip),
+      gfx::Insets(0, kHorizontalMarginDip, kPaddingBottomDip,
+                  kHorizontalMarginDip),
       kSpacingDip));
 
   // Scroll indicator.
diff --git a/ash/clipboard/clipboard_history.cc b/ash/clipboard/clipboard_history.cc
index 9a5f1a79..5bf4213 100644
--- a/ash/clipboard/clipboard_history.cc
+++ b/ash/clipboard/clipboard_history.cc
@@ -71,26 +71,30 @@
   CHECK(clipboard);
 
   std::vector<base::string16> mime_types;
-  clipboard->ReadAvailableTypes(ui::ClipboardBuffer::kCopyPaste, &mime_types);
+  clipboard->ReadAvailableTypes(ui::ClipboardBuffer::kCopyPaste,
+                                /* data_dst = */ nullptr, &mime_types);
 
   ui::ClipboardData new_data;
   for (const auto& type16 : mime_types) {
     const std::string type(base::UTF16ToUTF8(type16));
     if (type == ui::ClipboardFormatType::GetPlainTextType().GetName()) {
       base::string16 text;
-      clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &text);
+      clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste,
+                          /* data_dst = */ nullptr, &text);
       new_data.set_text(base::UTF16ToUTF8(text));
     } else if (type == ui::ClipboardFormatType::GetHtmlType().GetName()) {
       uint32_t start, end;
       base::string16 html_markup;
       std::string src_url;
-      clipboard->ReadHTML(ui::ClipboardBuffer::kCopyPaste, &html_markup,
-                          &src_url, &start, &end);
+      clipboard->ReadHTML(ui::ClipboardBuffer::kCopyPaste,
+                          /* data_dst = */ nullptr, &html_markup, &src_url,
+                          &start, &end);
       new_data.set_markup_data(base::UTF16ToUTF8(html_markup));
       new_data.set_url(src_url);
     } else if (type == ui::ClipboardFormatType::GetRtfType().GetName()) {
       std::string rtf_data;
-      clipboard->ReadRTF(ui::ClipboardBuffer::kCopyPaste, &rtf_data);
+      clipboard->ReadRTF(ui::ClipboardBuffer::kCopyPaste,
+                         /* data_dst = */ nullptr, &rtf_data);
       new_data.SetRTFData(rtf_data);
     } else if (type == ui::ClipboardFormatType::GetBitmapType().GetName()) {
       // TODO(newcomer): Read the bitmap asynchronously.
diff --git a/ash/drag_drop/drag_drop_controller_unittest.cc b/ash/drag_drop/drag_drop_controller_unittest.cc
index 14ee5ff..f0185c65 100644
--- a/ash/drag_drop/drag_drop_controller_unittest.cc
+++ b/ash/drag_drop/drag_drop_controller_unittest.cc
@@ -614,7 +614,8 @@
     scw.WriteText(base::ASCIIToUTF16(clip_str));
   }
   EXPECT_TRUE(cb->IsFormatAvailable(ui::ClipboardFormatType::GetPlainTextType(),
-                                    ui::ClipboardBuffer::kCopyPaste));
+                                    ui::ClipboardBuffer::kCopyPaste,
+                                    /* data_dst = */ nullptr));
 
   std::unique_ptr<views::Widget> widget = CreateFramelessWidget();
   DragTestView* drag_view = new DragTestView;
@@ -631,8 +632,10 @@
   // Verify the clipboard contents haven't changed
   std::string result;
   EXPECT_TRUE(cb->IsFormatAvailable(ui::ClipboardFormatType::GetPlainTextType(),
-                                    ui::ClipboardBuffer::kCopyPaste));
-  cb->ReadAsciiText(ui::ClipboardBuffer::kCopyPaste, &result);
+                                    ui::ClipboardBuffer::kCopyPaste,
+                                    /* data_dst = */ nullptr));
+  cb->ReadAsciiText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                    &result);
   EXPECT_EQ(clip_str, result);
   // Destroy the clipboard here because ash doesn't delete it.
   // crbug.com/158150.
diff --git a/base/allocator/partition_allocator/partition_alloc.h b/base/allocator/partition_allocator/partition_alloc.h
index beee858..0986b354 100644
--- a/base/allocator/partition_allocator/partition_alloc.h
+++ b/base/allocator/partition_allocator/partition_alloc.h
@@ -73,6 +73,7 @@
 #include "base/compiler_specific.h"
 #include "base/notreached.h"
 #include "base/partition_alloc_buildflags.h"
+#include "base/rand_util.h"
 #include "base/stl_util.h"
 #include "base/sys_byteorder.h"
 #include "build/build_config.h"
@@ -414,6 +415,9 @@
   Page* global_empty_page_ring[kMaxFreeableSpans] = {};
   int16_t global_empty_page_ring_index = 0;
   uintptr_t inverted_self = 0;
+#if ENABLE_TAG_FOR_CHECKED_PTR2 || ENABLE_TAG_FOR_MTE_CHECKED_PTR
+  internal::PartitionTag current_partition_tag = 0;
+#endif
 
   // Some pre-computed constants.
   size_t order_index_shifts[kBitsPerSizeT + 1] = {};
@@ -445,6 +449,9 @@
       return;
 
     InitSlowPath(enforce_alignment);
+#if ENABLE_TAG_FOR_CHECKED_PTR2 || ENABLE_TAG_FOR_MTE_CHECKED_PTR
+    current_partition_tag = base::RandUint64();
+#endif
   }
 
   ALWAYS_INLINE static bool IsValidPage(Page* page);
@@ -507,6 +514,17 @@
                                   size_t raw_size)
       EXCLUSIVE_LOCKS_REQUIRED(lock_);
   void DecommitEmptyPages() EXCLUSIVE_LOCKS_REQUIRED(lock_);
+
+  ALWAYS_INLINE internal::PartitionTag GetNewPartitionTag()
+      EXCLUSIVE_LOCKS_REQUIRED(lock_) {
+#if ENABLE_TAG_FOR_CHECKED_PTR2 || ENABLE_TAG_FOR_MTE_CHECKED_PTR
+    ++current_partition_tag;
+    current_partition_tag += !current_partition_tag;  // Avoid 0.
+    return current_partition_tag;
+#else
+    return 0;
+#endif
+  }
 };
 
 template <bool thread_safe>
@@ -587,9 +605,7 @@
   }
 
   if (allow_extras && !bucket->is_direct_mapped()) {
-    // TODO(tasak): initialize tag randomly. Temporarily use
-    // kTagTemporaryInitialValue to initialize the tag.
-    internal::PartitionTagSetValue(ret, internal::kTagTemporaryInitialValue);
+    internal::PartitionTagSetValue(ret, GetNewPartitionTag());
   }
 
   return ret;
diff --git a/base/optional.h b/base/optional.h
index 3707c8bc2..1f3e7e96 100644
--- a/base/optional.h
+++ b/base/optional.h
@@ -61,7 +61,7 @@
   template <class... Args>
   void Init(Args&&... args) {
     DCHECK(!is_populated_);
-    ::new (&value_) T(std::forward<Args>(args)...);
+    ::new (std::addressof(value_)) T(std::forward<Args>(args)...);
     is_populated_ = true;
   }
 
@@ -111,7 +111,7 @@
   template <class... Args>
   void Init(Args&&... args) {
     DCHECK(!is_populated_);
-    ::new (&value_) T(std::forward<Args>(args)...);
+    ::new (std::addressof(value_)) T(std::forward<Args>(args)...);
     is_populated_ = true;
   }
 
@@ -607,12 +607,12 @@
 
   constexpr const T* operator->() const {
     CHECK(storage_.is_populated_);
-    return &storage_.value_;
+    return std::addressof(storage_.value_);
   }
 
   constexpr T* operator->() {
     CHECK(storage_.is_populated_);
-    return &storage_.value_;
+    return std::addressof(storage_.value_);
   }
 
   constexpr const T& operator*() const & {
diff --git a/base/optional_unittest.cc b/base/optional_unittest.cc
index bc6e186..903480f1 100644
--- a/base/optional_unittest.cc
+++ b/base/optional_unittest.cc
@@ -7,6 +7,7 @@
 #include <memory>
 #include <set>
 #include <string>
+#include <type_traits>
 #include <vector>
 
 #include "base/macros.h"
@@ -173,6 +174,35 @@
   void* operator new[](size_t, void*) = delete;
 };
 
+class TriviallyDestructibleOverloadAddressOf {
+ public:
+  // Unfortunately, since this can be called as part of placement-new (if it
+  // forgets to call std::addressof), we're uninitialized.  So, about the best
+  // we can do is signal a test failure here if either operator& is called.
+  TriviallyDestructibleOverloadAddressOf* operator&() {
+    EXPECT_TRUE(false);
+    return this;
+  }
+
+  // So we can test the const version of operator->.
+  const TriviallyDestructibleOverloadAddressOf* operator&() const {
+    EXPECT_TRUE(false);
+    return this;
+  }
+
+  void const_method() const {}
+  void nonconst_method() {}
+};
+
+class NonTriviallyDestructibleOverloadAddressOf {
+ public:
+  ~NonTriviallyDestructibleOverloadAddressOf() {}
+  NonTriviallyDestructibleOverloadAddressOf* operator&() {
+    EXPECT_TRUE(false);
+    return this;
+  }
+};
+
 }  // anonymous namespace
 
 static_assert(std::is_trivially_destructible<Optional<int>>::value,
@@ -2213,4 +2243,30 @@
       "move assign for non-noexcept move-assignable T must not be noexcept");
 }
 
+TEST(OptionalTest, OverrideAddressOf) {
+  // Objects with an overloaded address-of should not trigger the overload for
+  // arrow or copy assignment.
+  static_assert(std::is_trivially_destructible<
+                    TriviallyDestructibleOverloadAddressOf>::value,
+                "Trivially...AddressOf must be trivially destructible.");
+  Optional<TriviallyDestructibleOverloadAddressOf> optional;
+  TriviallyDestructibleOverloadAddressOf n;
+  optional = n;
+
+  // operator->() should not call address-of either, for either const or non-
+  // const calls.  It's not strictly necessary that we call a nonconst method
+  // to test the non-const operator->(), but it makes it very clear that the
+  // compiler can't chose the const operator->().
+  optional->nonconst_method();
+  const auto& const_optional = optional;
+  const_optional->const_method();
+
+  static_assert(!std::is_trivially_destructible<
+                    NonTriviallyDestructibleOverloadAddressOf>::value,
+                "NotTrivially...AddressOf must not be trivially destructible.");
+  Optional<NonTriviallyDestructibleOverloadAddressOf> nontrivial_optional;
+  NonTriviallyDestructibleOverloadAddressOf n1;
+  nontrivial_optional = n1;
+}
+
 }  // namespace base
diff --git a/base/process/process_metrics_mac.cc b/base/process/process_metrics_mac.cc
index 6d05c82..fb91414 100644
--- a/base/process/process_metrics_mac.cc
+++ b/base/process/process_metrics_mac.cc
@@ -298,7 +298,7 @@
 
 #if defined(ARCH_CPU_ARM64)
   // PAGE_SIZE is vm_page_size on arm, which isn't constexpr.
-  DCHECK_EQ(PAGE_SIZE % 1024, 0) << "Invalid page size";
+  DCHECK_EQ(PAGE_SIZE % 1024, 0u) << "Invalid page size";
 #else
   static_assert(PAGE_SIZE % 1024 == 0, "Invalid page size");
 #endif
diff --git a/base/util/ranges/algorithm.h b/base/util/ranges/algorithm.h
index 3b9ce44..f18a99cd 100644
--- a/base/util/ranges/algorithm.h
+++ b/base/util/ranges/algorithm.h
@@ -43,19 +43,21 @@
 }
 
 // This alias is used below to restrict iterator based APIs to types for which
-// `iterator_category` is defined. This is required in situations where
-// otherwise an undesired overload would be chosen, e.g. copy_if. In spirit this
-// is similar to C++20's std::input_or_output_iterator, a concept that each
-// iterator should satisfy.
-template <typename Iter>
+// `iterator_category` and the pre-increment and post-increment operators are
+// defined. This is required in situations where otherwise an undesired overload
+// would be chosen, e.g. copy_if. In spirit this is similar to C++20's
+// std::input_or_output_iterator, a concept that each iterator should satisfy.
+template <typename Iter,
+          typename = decltype(++std::declval<Iter&>()),
+          typename = decltype(std::declval<Iter&>()++)>
 using iterator_category_t =
     typename std::iterator_traits<Iter>::iterator_category;
 
 // This alias is used below to restrict range based APIs to types for which
-// `iterator_category` is defined for the underlying iterator. This is required
-// in situations where otherwise an undesired overload would be chosen, e.g.
-// transform. In spirit this is similar to C++20's std::ranges::range, a concept
-// that each range should satisfy.
+// `iterator_category_t` is defined for the underlying iterator. This is
+// required in situations where otherwise an undesired overload would be chosen,
+// e.g. transform. In spirit this is similar to C++20's std::ranges::range, a
+// concept that each range should satisfy.
 template <typename Range>
 using range_category_t = iterator_category_t<iterator_t<Range>>;
 
@@ -1309,8 +1311,6 @@
                              ranges::begin(range2), ranges::end(range2));
 }
 
-// TODO(crbug.com/1071094): Implement.
-
 // [alg.transform] Transform
 // Reference: https://wg21.link/alg.transform
 
@@ -1479,17 +1479,385 @@
 // [alg.replace] Replace
 // Reference: https://wg21.link/alg.replace
 
-// TODO(crbug.com/1071094): Implement.
+// Let `E(i)` be `bool(invoke(proj, *i) == old_value)`.
+//
+// Mandates: `new_value` is writable  to `first`.
+//
+// Effects: Substitutes elements referred by the iterator `i` in the range
+// `[first, last)` with `new_value`, when `E(i)` is true.
+//
+// Returns: `last`
+//
+// Complexity: Exactly `last - first` applications of the corresponding
+// predicate and any projection.
+//
+// Reference: https://wg21.link/alg.replace#:~:text=ranges::replace(I
+template <typename FordwardIterator,
+          typename T,
+          typename Proj = identity,
+          typename = internal::iterator_category_t<FordwardIterator>>
+constexpr auto replace(FordwardIterator first,
+                       FordwardIterator last,
+                       const T& old_value,
+                       const T& new_value,
+                       Proj proj = {}) {
+  // Note: In order to be able to apply `proj` to each element in [first, last)
+  // we are dispatching to std::replace_if instead of std::replace.
+  std::replace_if(
+      first, last,
+      [&proj, &old_value](auto&& lhs) {
+        return invoke(proj, std::forward<decltype(lhs)>(lhs)) == old_value;
+      },
+      new_value);
+  return last;
+}
+
+// Let `E(i)` be `bool(invoke(proj, *i) == old_value)`.
+//
+// Mandates: `new_value` is writable  to `begin(range)`.
+//
+// Effects: Substitutes elements referred by the iterator `i` in `range` with
+// `new_value`, when `E(i)` is true.
+//
+// Returns: `end(range)`
+//
+// Complexity: Exactly `size(range)` applications of the corresponding predicate
+// and any projection.
+//
+// Reference: https://wg21.link/alg.replace#:~:text=ranges::replace(R
+template <typename Range,
+          typename T,
+          typename Proj = identity,
+          typename = internal::range_category_t<Range>>
+constexpr auto replace(Range&& range,
+                       const T& old_value,
+                       const T& new_value,
+                       Proj proj = {}) {
+  return ranges::replace(ranges::begin(range), ranges::end(range), old_value,
+                         new_value, std::move(proj));
+}
+
+// Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
+//
+// Mandates: `new_value` is writable  to `first`.
+//
+// Effects: Substitutes elements referred by the iterator `i` in the range
+// `[first, last)` with `new_value`, when `E(i)` is true.
+//
+// Returns: `last`
+//
+// Complexity: Exactly `last - first` applications of the corresponding
+// predicate and any projection.
+//
+// Reference: https://wg21.link/alg.replace#:~:text=ranges::replace_if(I
+template <typename FordwardIterator,
+          typename Predicate,
+          typename T,
+          typename Proj = identity,
+          typename = internal::iterator_category_t<FordwardIterator>>
+constexpr auto replace_if(FordwardIterator first,
+                          FordwardIterator last,
+                          Predicate pred,
+                          const T& new_value,
+                          Proj proj = {}) {
+  std::replace_if(first, last, internal::ProjectedUnaryPredicate(pred, proj),
+                  new_value);
+  return last;
+}
+
+// Let `E(i)` be `bool(invoke(pred, invoke(proj, *i)))`.
+//
+// Mandates: `new_value` is writable  to `begin(range)`.
+//
+// Effects: Substitutes elements referred by the iterator `i` in `range` with
+// `new_value`, when `E(i)` is true.
+//
+// Returns: `end(range)`
+//
+// Complexity: Exactly `size(range)` applications of the corresponding predicate
+// and any projection.
+//
+// Reference: https://wg21.link/alg.replace#:~:text=ranges::replace_if(R
+template <typename Range,
+          typename Predicate,
+          typename T,
+          typename Proj = identity,
+          typename = internal::range_category_t<Range>>
+constexpr auto replace_if(Range&& range,
+                          Predicate pred,
+                          const T& new_value,
+                          Proj proj = {}) {
+  return ranges::replace_if(ranges::begin(range), ranges::end(range),
+                            std::move(pred), new_value, std::move(proj));
+}
+
+// Let `E(i)` be `bool(invoke(proj, *(first + (i - result))) == old_value)`.
+//
+// Mandates: The results of the expressions `*first` and `new_value` are
+// writable  to `result`.
+//
+// Preconditions: The ranges `[first, last)` and `[result, result + (last -
+// first))` do not overlap.
+//
+// Effects: Assigns through every iterator `i` in the range `[result, result +
+// (last - first))` a new corresponding value, `new_value` if `E(i)` is true, or
+// `*(first + (i - result))` otherwise.
+//
+// Returns: `result + (last - first)`.
+//
+// Complexity: Exactly `last - first` applications of the corresponding
+// predicate and any projection.
+//
+// Reference: https://wg21.link/alg.replace#:~:text=ranges::replace_copy(I
+template <typename InputIterator,
+          typename OutputIterator,
+          typename T,
+          typename Proj = identity,
+          typename = internal::iterator_category_t<InputIterator>,
+          typename = internal::iterator_category_t<OutputIterator>>
+constexpr auto replace_copy(InputIterator first,
+                            InputIterator last,
+                            OutputIterator result,
+                            const T& old_value,
+                            const T& new_value,
+                            Proj proj = {}) {
+  // Note: In order to be able to apply `proj` to each element in [first, last)
+  // we are dispatching to std::replace_copy_if instead of std::replace_copy.
+  std::replace_copy_if(
+      first, last, result,
+      [&proj, &old_value](auto&& lhs) {
+        return invoke(proj, std::forward<decltype(lhs)>(lhs)) == old_value;
+      },
+      new_value);
+  return last;
+}
+
+// Let `E(i)` be
+// `bool(invoke(proj, *(begin(range) + (i - result))) == old_value)`.
+//
+// Mandates: The results of the expressions `*begin(range)` and `new_value` are
+// writable  to `result`.
+//
+// Preconditions: The ranges `range` and `[result, result + size(range))` do not
+// overlap.
+//
+// Effects: Assigns through every iterator `i` in the range `[result, result +
+// size(range))` a new corresponding value, `new_value` if `E(i)` is true, or
+// `*(begin(range) + (i - result))` otherwise.
+//
+// Returns: `result + size(range)`.
+//
+// Complexity: Exactly `size(range)` applications of the corresponding
+// predicate and any projection.
+//
+// Reference: https://wg21.link/alg.replace#:~:text=ranges::replace_copy(R
+template <typename Range,
+          typename OutputIterator,
+          typename T,
+          typename Proj = identity,
+          typename = internal::range_category_t<Range>,
+          typename = internal::iterator_category_t<OutputIterator>>
+constexpr auto replace_copy(Range&& range,
+                            OutputIterator result,
+                            const T& old_value,
+                            const T& new_value,
+                            Proj proj = {}) {
+  return ranges::replace_copy(ranges::begin(range), ranges::end(range), result,
+                              old_value, new_value, std::move(proj));
+}
+
+// Let `E(i)` be `bool(invoke(pred, invoke(proj, *(first + (i - result)))))`.
+//
+// Mandates: The results of the expressions `*first` and `new_value` are
+// writable  to `result`.
+//
+// Preconditions: The ranges `[first, last)` and `[result, result + (last -
+// first))` do not overlap.
+//
+// Effects: Assigns through every iterator `i` in the range `[result, result +
+// (last - first))` a new corresponding value, `new_value` if `E(i)` is true, or
+// `*(first + (i - result))` otherwise.
+//
+// Returns: `result + (last - first)`.
+//
+// Complexity: Exactly `last - first` applications of the corresponding
+// predicate and any projection.
+//
+// Reference: https://wg21.link/alg.replace#:~:text=ranges::replace_copy_if(I
+template <typename InputIterator,
+          typename OutputIterator,
+          typename Predicate,
+          typename T,
+          typename Proj = identity,
+          typename = internal::iterator_category_t<InputIterator>,
+          typename = internal::iterator_category_t<OutputIterator>>
+constexpr auto replace_copy_if(InputIterator first,
+                               InputIterator last,
+                               OutputIterator result,
+                               Predicate pred,
+                               const T& new_value,
+                               Proj proj = {}) {
+  return std::replace_copy_if(first, last, result,
+                              internal::ProjectedUnaryPredicate(pred, proj),
+                              new_value);
+}
+
+// Let `E(i)` be
+// `bool(invoke(pred, invoke(proj, *(begin(range) + (i - result)))))`.
+//
+// Mandates: The results of the expressions `*begin(range)` and `new_value` are
+// writable  to `result`.
+//
+// Preconditions: The ranges `range` and `[result, result + size(range))` do not
+// overlap.
+//
+// Effects: Assigns through every iterator `i` in the range `[result, result +
+// size(range))` a new corresponding value, `new_value` if `E(i)` is true, or
+// `*(begin(range) + (i - result))` otherwise.
+//
+// Returns: `result + size(range)`.
+//
+// Complexity: Exactly `size(range)` applications of the corresponding
+// predicate and any projection.
+//
+// Reference: https://wg21.link/alg.replace#:~:text=ranges::replace_copy_if(R
+template <typename Range,
+          typename OutputIterator,
+          typename Predicate,
+          typename T,
+          typename Proj = identity,
+          typename = internal::range_category_t<Range>,
+          typename = internal::iterator_category_t<OutputIterator>>
+constexpr auto replace_copy_if(Range&& range,
+                               OutputIterator result,
+                               Predicate pred,
+                               const T& new_value,
+                               Proj proj = {}) {
+  return ranges::replace_copy_if(ranges::begin(range), ranges::end(range),
+                                 result, pred, new_value, std::move(proj));
+}
 
 // [alg.fill] Fill
 // Reference: https://wg21.link/alg.fill
 
-// TODO(crbug.com/1071094): Implement.
+// Let `N` be `last - first`.
+//
+// Mandates: The expression `value` is writable to the output iterator.
+//
+// Effects: Assigns `value` through all the iterators in the range
+// `[first, last)`.
+//
+// Returns: `last`.
+//
+// Complexity: Exactly `N` assignments.
+//
+// Reference: https://wg21.link/alg.fill#:~:text=ranges::fill(O
+template <typename OutputIterator,
+          typename T,
+          typename = internal::iterator_category_t<OutputIterator>>
+constexpr auto fill(OutputIterator first, OutputIterator last, const T& value) {
+  std::fill(first, last, value);
+  return last;
+}
+
+// Let `N` be `size(range)`.
+//
+// Mandates: The expression `value` is writable to the output iterator.
+//
+// Effects: Assigns `value` through all the iterators in `range`.
+//
+// Returns: `end(range)`.
+//
+// Complexity: Exactly `N` assignments.
+//
+// Reference: https://wg21.link/alg.fill#:~:text=ranges::fill(R
+template <typename Range,
+          typename T,
+          typename = internal::range_category_t<Range>>
+constexpr auto fill(Range&& range, const T& value) {
+  return ranges::fill(ranges::begin(range), ranges::end(range), value);
+}
+
+// Let `N` be `max(0, n)`.
+//
+// Mandates: The expression `value` is writable to the output iterator.
+// The type `Size` is convertible to an integral type.
+//
+// Effects: Assigns `value` through all the iterators in `[first, first + N)`.
+//
+// Returns: `first + N`.
+//
+// Complexity: Exactly `N` assignments.
+//
+// Reference: https://wg21.link/alg.fill#:~:text=ranges::fill_n(O
+template <typename OutputIterator,
+          typename Size,
+          typename T,
+          typename = internal::iterator_category_t<OutputIterator>>
+constexpr auto fill_n(OutputIterator first, Size n, const T& value) {
+  return std::fill_n(first, n, value);
+}
 
 // [alg.generate] Generate
 // Reference: https://wg21.link/alg.generate
 
-// TODO(crbug.com/1071094): Implement.
+// Let `N` be `last - first`.
+//
+// Effects: Assigns the result of successive evaluations of gen() through each
+// iterator in the range `[first, last)`.
+//
+// Returns: `last`.
+//
+// Complexity: Exactly `N` evaluations of `gen()` and assignments.
+//
+// Reference: https://wg21.link/alg.generate#:~:text=ranges::generate(O
+template <typename OutputIterator,
+          typename Generator,
+          typename = internal::iterator_category_t<OutputIterator>>
+constexpr auto generate(OutputIterator first,
+                        OutputIterator last,
+                        Generator gen) {
+  std::generate(first, last, std::move(gen));
+  return last;
+}
+
+// Let `N` be `size(range)`.
+//
+// Effects: Assigns the result of successive evaluations of gen() through each
+// iterator in `range`.
+//
+// Returns: `end(range)`.
+//
+// Complexity: Exactly `N` evaluations of `gen()` and assignments.
+//
+// Reference: https://wg21.link/alg.generate#:~:text=ranges::generate(R
+template <typename Range,
+          typename Generator,
+          typename = internal::range_category_t<Range>>
+constexpr auto generate(Range&& range, Generator gen) {
+  return ranges::generate(ranges::begin(range), ranges::end(range),
+                          std::move(gen));
+}
+
+// Let `N` be `max(0, n)`.
+//
+// Mandates: `Size` is convertible to an integral type.
+//
+// Effects: Assigns the result of successive evaluations of gen() through each
+// iterator in the range `[first, first + N)`.
+//
+// Returns: `first + N`.
+//
+// Complexity: Exactly `N` evaluations of `gen()` and assignments.
+//
+// Reference: https://wg21.link/alg.generate#:~:text=ranges::generate_n(O
+template <typename OutputIterator,
+          typename Size,
+          typename Generator,
+          typename = internal::iterator_category_t<OutputIterator>>
+constexpr auto generate_n(OutputIterator first, Size n, Generator gen) {
+  return std::generate_n(first, n, std::move(gen));
+}
 
 // [alg.remove] Remove
 // Reference: https://wg21.link/alg.remove
diff --git a/base/util/ranges/algorithm_unittest.cc b/base/util/ranges/algorithm_unittest.cc
index 4ff621b..477b440a 100644
--- a/base/util/ranges/algorithm_unittest.cc
+++ b/base/util/ranges/algorithm_unittest.cc
@@ -42,6 +42,14 @@
   int value = 0;
 };
 
+bool is_even(int i) {
+  return i % 2 == 0;
+}
+
+bool is_odd(int i) {
+  return i % 2 == 1;
+}
+
 }  // namespace
 
 TEST(RangesTest, AllOf) {
@@ -58,7 +66,6 @@
 }
 
 TEST(RangesTest, AnyOf) {
-  auto is_even = [](int i) { return i % 2 == 0; };
   int array[] = {0, 1, 2, 3, 4, 5};
 
   EXPECT_FALSE(ranges::any_of(array + 5, array + 6, is_even));
@@ -121,7 +128,6 @@
   EXPECT_EQ(array + 5, ranges::find_if(array, array + 5, is_at_least_5));
   EXPECT_EQ(array + 5, ranges::find_if(array, is_at_least_5));
 
-  auto is_odd = [](int i) { return i % 2 == 1; };
   Int values[] = {{0}, {2}, {4}, {5}};
   EXPECT_EQ(values + 3,
             ranges::find_if(values, values + 3, is_odd, &Int::value));
@@ -135,7 +141,6 @@
   EXPECT_EQ(array + 5, ranges::find_if_not(array, array + 5, is_less_than_5));
   EXPECT_EQ(array + 5, ranges::find_if_not(array, is_less_than_5));
 
-  auto is_even = [](int i) { return i % 2 == 0; };
   Int values[] = {{0}, {2}, {4}, {5}};
   EXPECT_EQ(values + 3,
             ranges::find_if_not(values, values + 3, is_even, &Int::value));
@@ -211,14 +216,12 @@
 }
 
 TEST(RangesTest, CountIf) {
-  auto is_even = [](int i) { return i % 2 == 0; };
   int array[] = {1, 2, 3, 3};
   EXPECT_EQ(0, ranges::count_if(array, array + 1, is_even));
   EXPECT_EQ(1, ranges::count_if(array, array + 2, is_even));
   EXPECT_EQ(1, ranges::count_if(array, array + 3, is_even));
   EXPECT_EQ(1, ranges::count_if(array, array + 4, is_even));
 
-  auto is_odd = [](int i) { return i % 2 == 1; };
   Int ints[] = {{1}, {2}, {3}, {3}};
   EXPECT_EQ(1, ranges::count_if(ints, is_even, &Int::value));
   EXPECT_EQ(3, ranges::count_if(ints, is_odd, &Int::value));
@@ -493,6 +496,96 @@
   EXPECT_THAT(values, ElementsAre(Int{0}, Int{0}, Int{0}, Int{0}));
 }
 
+TEST(RangesTest, Replace) {
+  int input[] = {0, 0, 0, 0, 0};
+
+  EXPECT_EQ(input + 2, ranges::replace(input, input + 2, 0, 2));
+  EXPECT_THAT(input, ElementsAre(2, 2, 0, 0, 0));
+
+  EXPECT_EQ(input + 5, ranges::replace(input, 0, 3));
+  EXPECT_THAT(input, ElementsAre(2, 2, 3, 3, 3));
+}
+
+TEST(RangesTest, ReplaceIf) {
+  int input[] = {0, 1, 2, 3, 4};
+
+  EXPECT_EQ(input + 3, ranges::replace_if(input, input + 3, is_even, 9));
+  EXPECT_THAT(input, ElementsAre(9, 1, 9, 3, 4));
+
+  EXPECT_EQ(input + 5, ranges::replace_if(input, is_odd, 0));
+  EXPECT_THAT(input, ElementsAre(0, 0, 0, 0, 4));
+
+  Int ints[] = {0, 0, 1, 1, 0};
+  EXPECT_EQ(ints + 5, ranges::replace_if(ints, is_odd, 3, &Int::value));
+  EXPECT_THAT(ints, ElementsAre(0, 0, 3, 3, 0));
+}
+
+TEST(RangesTest, ReplaceCopy) {
+  int input[] = {0, 0, 0, 0, 0};
+  int output[] = {1, 1, 1, 1, 1};
+
+  EXPECT_EQ(input + 2, ranges::replace_copy(input, input + 2, output, 0, 2));
+  EXPECT_THAT(input, ElementsAre(0, 0, 0, 0, 0));
+  EXPECT_THAT(output, ElementsAre(2, 2, 1, 1, 1));
+
+  EXPECT_EQ(input + 5, ranges::replace_copy(input, output, 0, 3));
+  EXPECT_THAT(input, ElementsAre(0, 0, 0, 0, 0));
+  EXPECT_THAT(output, ElementsAre(3, 3, 3, 3, 3));
+}
+
+TEST(RangesTest, ReplaceCopyIf) {
+  Int input[] = {0, 1, 2, 3, 4};
+  Int output[] = {0, 0, 0, 0, 0};
+
+  EXPECT_EQ(output + 3, ranges::replace_copy_if(input, input + 3, output,
+                                                is_even, 9, &Int::value));
+  EXPECT_THAT(input, ElementsAre(0, 1, 2, 3, 4));
+  EXPECT_THAT(output, ElementsAre(9, 1, 9, 0, 0));
+
+  EXPECT_EQ(output + 5,
+            ranges::replace_copy_if(input, output, is_odd, 0, &Int::value));
+  EXPECT_THAT(output, ElementsAre(0, 0, 2, 0, 4));
+}
+
+TEST(RangesTest, Fill) {
+  int input[] = {1, 2, 3, 4, 5};
+
+  EXPECT_EQ(input + 3, ranges::fill(input, input + 3, 0));
+  EXPECT_THAT(input, ElementsAre(0, 0, 0, 4, 5));
+
+  EXPECT_EQ(input + 5, ranges::fill(input, 1));
+  EXPECT_THAT(input, ElementsAre(1, 1, 1, 1, 1));
+}
+
+TEST(RangesTest, FillN) {
+  int input[] = {0, 0, 0, 0, 0};
+
+  EXPECT_EQ(input + 5, ranges::fill_n(input, 5, 5));
+  EXPECT_THAT(input, ElementsAre(5, 5, 5, 5, 5));
+
+  EXPECT_EQ(input + 3, ranges::fill_n(input, 3, 3));
+  EXPECT_THAT(input, ElementsAre(3, 3, 3, 5, 5));
+}
+
+TEST(RangesTest, Generate) {
+  int input[] = {0, 0, 0, 0, 0};
+
+  auto gen = [count = 0]() mutable { return ++count; };
+  EXPECT_EQ(input + 3, ranges::generate(input, input + 3, gen));
+  EXPECT_THAT(input, ElementsAre(1, 2, 3, 0, 0));
+
+  EXPECT_EQ(input + 5, ranges::generate(input, gen));
+  EXPECT_THAT(input, ElementsAre(1, 2, 3, 4, 5));
+}
+
+TEST(RangesTest, GenerateN) {
+  int input[] = {0, 0, 0, 0, 0};
+
+  auto gen = [count = 0]() mutable { return ++count; };
+  EXPECT_EQ(input + 4, ranges::generate_n(input, 4, gen));
+  EXPECT_THAT(input, ElementsAre(1, 2, 3, 4, 0));
+}
+
 TEST(RangesTest, LowerBound) {
   int array[] = {0, 0, 1, 1, 2, 2};
 
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni
index 63bda56..cd8d59b 100644
--- a/build/config/android/internal_rules.gni
+++ b/build/config/android/internal_rules.gni
@@ -863,6 +863,7 @@
         executable_args += [
           "--coverage-dir",
           "@WrappedPath(${_rebased_coverage_dir})",
+          "--coverage-on-the-fly",
         ]
       }
     } else if (_test_type == "linker") {
diff --git a/cc/metrics/events_metrics_manager.h b/cc/metrics/events_metrics_manager.h
index 6c44f62..ea2c49f 100644
--- a/cc/metrics/events_metrics_manager.h
+++ b/cc/metrics/events_metrics_manager.h
@@ -53,6 +53,10 @@
   // caller.
   std::vector<EventMetrics> TakeSavedEventsMetrics();
 
+  size_t saved_events_metrics_count_for_testing() const {
+    return saved_events_.size();
+  }
+
  private:
   void OnScopedMonitorEnded();
 
diff --git a/cc/paint/discardable_image_map_unittest.cc b/cc/paint/discardable_image_map_unittest.cc
index f77ea15..4dc02b1 100644
--- a/cc/paint/discardable_image_map_unittest.cc
+++ b/cc/paint/discardable_image_map_unittest.cc
@@ -1204,8 +1204,7 @@
   else
     EXPECT_FALSE(image_map2.contains_only_srgb_images());
 
-  if (image_color_space.IsHDR())
-    EXPECT_TRUE(image_map2.contains_hdr_images());
+  EXPECT_EQ(image_color_space.IsHDR(), image_map2.contains_hdr_images());
 }
 
 gfx::ColorSpace test_color_spaces[] = {
diff --git a/cc/paint/paint_image.cc b/cc/paint/paint_image.cc
index 8bab5637..955de2c 100644
--- a/cc/paint/paint_image.cc
+++ b/cc/paint/paint_image.cc
@@ -281,13 +281,11 @@
   if (paint_worklet_input_)
     return true;
 
-  auto* color_space = GetSkImageInfo().colorSpace();
-  if (!color_space) {
-    // Assume the image will be sRGB if we don't know yet.
-    return true;
-  }
+  if (const auto* color_space = GetSkImageInfo().colorSpace())
+    return color_space->isSRGB();
 
-  return color_space->isSRGB();
+  // Assume the image will be sRGB if we don't know yet.
+  return true;
 }
 
 bool PaintImage::isHDR() const {
@@ -295,13 +293,11 @@
   if (paint_worklet_input_)
     return false;
 
-  auto* color_space = GetSkImage()->colorSpace();
-  if (!color_space) {
-    // Assume the image will not be HDR if we don't know yet.
-    return false;
-  }
+  if (const auto* color_space = GetSkImageInfo().colorSpace())
+    return gfx::ColorSpace(*color_space).IsHDR();
 
-  return gfx::ColorSpace(*color_space).IsHDR();
+  // Assume the image will not be HDR if we don't know yet.
+  return false;
 }
 
 const ImageHeaderMetadata* PaintImage::GetImageHeaderMetadata() const {
diff --git a/cc/test/layer_tree_test.cc b/cc/test/layer_tree_test.cc
index a76ab72..ea7eb06 100644
--- a/cc/test/layer_tree_test.cc
+++ b/cc/test/layer_tree_test.cc
@@ -1187,7 +1187,7 @@
   return host->GetTaskRunnerProvider();
 }
 
-LayerTreeHost* LayerTreeTest::layer_tree_host() {
+LayerTreeHost* LayerTreeTest::layer_tree_host() const {
   DCHECK(task_runner_provider()->IsMainThread() ||
          task_runner_provider()->IsMainThreadBlocked());
   return layer_tree_host_.get();
diff --git a/cc/test/layer_tree_test.h b/cc/test/layer_tree_test.h
index 3e28826..cf823b2 100644
--- a/cc/test/layer_tree_test.h
+++ b/cc/test/layer_tree_test.h
@@ -164,7 +164,7 @@
   base::SingleThreadTaskRunner* ImplThreadTaskRunner() {
     return impl_task_runner_.get();
   }
-  base::SingleThreadTaskRunner* MainThreadTaskRunner() {
+  base::SingleThreadTaskRunner* MainThreadTaskRunner() const {
     return main_task_runner_.get();
   }
   Proxy* proxy();
@@ -177,7 +177,7 @@
     return ended_;
   }
 
-  LayerTreeHost* layer_tree_host();
+  LayerTreeHost* layer_tree_host() const;
   gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager() {
     return gpu_memory_buffer_manager_.get();
   }
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 43719ee..5cefe4d 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -256,7 +256,7 @@
 }
 
 void LayerTreeHost::ClearEventsMetrics() {
-  // Take evens metrics and drop them.
+  // Take events metrics and drop them.
   events_metrics_manager_.TakeSavedEventsMetrics();
 }
 
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index f365bd9a..d319970 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -184,6 +184,10 @@
   GetScopedEventMetricsMonitor(std::unique_ptr<EventMetrics> event_metrics);
   void ClearEventsMetrics();
 
+  size_t saved_events_metrics_count_for_testing() const {
+    return events_metrics_manager_.saved_events_metrics_count_for_testing();
+  }
+
   // Visibility and LayerTreeFrameSink -------------------------------
 
   // Sets or gets if the LayerTreeHost is visible. When not visible it will:
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index b2c0baa..85afa76 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -1859,28 +1859,38 @@
     gfx::ContentColorUsage content_color_usage) const {
   constexpr gfx::ColorSpace srgb = gfx::ColorSpace::CreateSRGB();
 
-  if (settings_.prefer_raster_in_srgb &&
-      content_color_usage == gfx::ContentColorUsage::kSRGB)
+  // If we are likely to software composite the resource, we use sRGB because
+  // software compositing is unable to perform color conversion.
+  if (!layer_tree_frame_sink_ || !layer_tree_frame_sink_->context_provider())
     return srgb;
 
-  gfx::ColorSpace result;
-  // The pending tree will have the most recently updated color space, so
-  // prefer that.
-  if (pending_tree_) {
-    result = pending_tree_->raster_color_space();
-  } else if (active_tree_) {
-    result = active_tree_->raster_color_space();
+  if (settings_.prefer_raster_in_srgb &&
+      content_color_usage == gfx::ContentColorUsage::kSRGB) {
+    return srgb;
   }
 
-  // If we are likely to software composite the resource, we use sRGB because
-  // software compositing is unable to perform color conversion. Also always
-  // specify a color space if color correct rasterization is requested
+  // The pending tree will has the most recently updated color space, so use it.
+  gfx::ColorSpace result;
+  if (pending_tree_)
+    result = pending_tree_->raster_color_space();
+  else if (active_tree_)
+    result = active_tree_->raster_color_space();
+
+  // Always specify a color space if color correct rasterization is requested
   // (not specifying a color space indicates that no color conversion is
   // required).
-  if (!layer_tree_frame_sink_ || !layer_tree_frame_sink_->context_provider() ||
-      !result.IsValid()) {
-    result = srgb;
-  }
+  if (!result.IsValid())
+    return srgb;
+
+  // Rasterization doesn't support more than 8 bit unorm values. If the output
+  // space has an extended range, use Display P3 for the rasterization space,
+  // to get a somewhat wider color gamut.
+  //
+  // TODO(crbug.com/1076568): Actually use the HDR color space when we have HDR
+  // content to display.
+  if (result.IsHDR())
+    return gfx::ColorSpace::CreateDisplayP3D65();
+
   return result;
 }
 
diff --git a/cc/trees/layer_tree_host_unittest.cc b/cc/trees/layer_tree_host_unittest.cc
index 3ed4b97..6281fee 100644
--- a/cc/trees/layer_tree_host_unittest.cc
+++ b/cc/trees/layer_tree_host_unittest.cc
@@ -30,6 +30,7 @@
 #include "cc/layers/picture_layer.h"
 #include "cc/layers/solid_color_layer.h"
 #include "cc/layers/video_layer.h"
+#include "cc/metrics/events_metrics_manager.h"
 #include "cc/paint/image_animation_count.h"
 #include "cc/resources/ui_resource_manager.h"
 #include "cc/test/fake_content_layer_client.h"
@@ -81,6 +82,12 @@
 #include "ui/gfx/geometry/size_conversions.h"
 #include "ui/gfx/geometry/vector2d_conversions.h"
 
+#define EXPECT_SCOPED(statements) \
+  {                               \
+    SCOPED_TRACE("");             \
+    statements;                   \
+  }
+
 using testing::_;
 using testing::AnyNumber;
 using testing::AtLeast;
@@ -1539,11 +1546,11 @@
     // Change the child layer each frame. Since the child layer is translated
     // past the viewport, it should not cause damage, but webview will still
     // invalidate if the frame doesn't check for damage early.
-    child_->SetOpacity(1.0 / (float)(frame + 1));
+    child_->SetOpacity(1.0f / (frame + 1));
 
     // For |damaged_frame_limit| consecutive frames, cause actual damage.
     if (frame >= 3 && frame < (damaged_frame_limit_ + 3)) {
-      root_->SetOpacity(1.0 / (float)frame);
+      root_->SetOpacity(1.0f / frame);
     }
   }
 
@@ -9025,5 +9032,351 @@
 
 SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestDelegatedInkMetadataOnAndOff);
 
+// Base class for EventMetrics-related tests.
+class LayerTreeHostTestEventsMetrics : public LayerTreeHostTest {
+ protected:
+  void BeginTest() override { PostSetNeedsCommitToMainThread(); }
+
+  // Simulate an event being handled on the main thread.
+  void PostSimulateEvent() {
+    MainThreadTaskRunner()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&LayerTreeHostTestEventsMetrics::SimulateEventOnMain,
+                       base::Unretained(this)));
+  }
+
+  // Verifies the number of saved events metrics on the main thread.
+  void PostVerifyMainSavedEventsMetricsCount(size_t count) const {
+    MainThreadTaskRunner()->PostTask(
+        FROM_HERE, base::BindOnce(&LayerTreeHostTestEventsMetrics::
+                                      VerifyMainSavedEventsMetricsCountOnMain,
+                                  base::Unretained(this), count));
+  }
+
+  // Verifies the number of events metrics copied from the main thread to the
+  // impl thread.
+  void VerifyImplEventsMetricsFromMainCount(LayerTreeHostImpl* impl,
+                                            size_t count) const {
+    EXPECT_EQ(count, impl->active_tree()
+                         ->events_metrics_from_main_thread_count_for_testing());
+  }
+
+ private:
+  void SimulateEventOnMain() {
+    auto scoped_event_monitor =
+        layer_tree_host()->GetScopedEventMetricsMonitor(EventMetrics::Create(
+            ui::ET_GESTURE_SCROLL_UPDATE, base::TimeTicks::Now(),
+            ui::ScrollInputType::kWheel));
+    layer_tree_host()->SetNeedsAnimate();
+    EXPECT_SCOPED(VerifyMainSavedEventsMetricsCountOnMain(1));
+  }
+
+  void VerifyMainSavedEventsMetricsCountOnMain(size_t count) const {
+    EXPECT_EQ(count,
+              layer_tree_host()->saved_events_metrics_count_for_testing());
+  }
+};
+
+// Verifies that if the commit is aborted (deferred) due to LayerTreeHost being
+// hidden, events metrics are not thrown away to be used when it becomes
+// visible.
+class LayerTreeHostTestKeepEventsMetricsForVisibility
+    : public LayerTreeHostTestEventsMetrics {
+ protected:
+  void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
+                                  const viz::BeginFrameArgs& args) override {
+    // Skip if we have already received a begin-impl-frame and acted on it.
+    if (received_will_begin_impl_frame_)
+      return;
+    received_will_begin_impl_frame_ = true;
+
+    EXPECT_SCOPED(VerifyImplEventsMetricsFromMainCount(impl, 0));
+
+    // Simulate an event being handled on the main thread. Since the main frame
+    // is not yet scheduled, we will have events metrics when the main frame is
+    // processed.
+    PostSimulateEvent();
+
+    // Hide layer tree host. Since the main frame is not yet scheduled, layer
+    // tree host will be hidden when the main frame is processed, causing it to
+    // abort.
+    PostSetLayerTreeHostVisible(false);
+  }
+
+  void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* impl,
+                                     CommitEarlyOutReason reason) override {
+    EXPECT_EQ(reason, CommitEarlyOutReason::ABORTED_NOT_VISIBLE);
+
+    // Since the main frame is aborted due to invisibility, events metrics
+    // should not have been thrown away.
+    PostVerifyMainSavedEventsMetricsCount(1);
+
+    // Make layer tree host visible so that the deferred commit is completed,
+    // causing events metrics being passed to the impl thread.
+    PostSetLayerTreeHostVisible(true);
+  }
+
+  void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
+    // Now that a commit is completed and activated, events metrics from main
+    // thread should have been moved to the impl thread.
+    PostVerifyMainSavedEventsMetricsCount(0);
+    EXPECT_SCOPED(VerifyImplEventsMetricsFromMainCount(impl, 1));
+
+    EndTest();
+  }
+
+ private:
+  void SetLayerTreeHostVisibleOnMain(bool visible) {
+    layer_tree_host()->SetVisible(visible);
+  }
+
+  void PostSetLayerTreeHostVisible(bool visible) {
+    MainThreadTaskRunner()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&LayerTreeHostTestKeepEventsMetricsForVisibility::
+                           SetLayerTreeHostVisibleOnMain,
+                       base::Unretained(this), visible));
+  }
+
+  bool received_will_begin_impl_frame_ = false;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(LayerTreeHostTestKeepEventsMetricsForVisibility);
+
+// Verifies that if the commit is aborted due to main frame update being
+// deferred, events metrics are not thrown away to be used when the actual
+// commit happens.
+class LayerTreeHostTestKeepEventsMetricsForDeferredMainFrameUpdate
+    : public LayerTreeHostTestEventsMetrics {
+ protected:
+  void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
+                                  const viz::BeginFrameArgs& args) override {
+    // Skip if we have already received a begin-impl-frame and acted on it.
+    if (received_will_begin_impl_frame_)
+      return;
+    received_will_begin_impl_frame_ = true;
+
+    EXPECT_SCOPED(VerifyImplEventsMetricsFromMainCount(impl, 0));
+
+    // Simulate an event being handled on the main thread. Since the main frame
+    // is not yet scheduled, we will have events metrics when the main frame is
+    // processed.
+    PostSimulateEvent();
+
+    // Defer main frame updates. Since the main frame is not yet scheduled, main
+    // frame updates will be deferred when the main frame is processed, causing
+    // it to abort.
+    PostDeferMainFrameUpdate();
+  }
+
+  void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* impl,
+                                     CommitEarlyOutReason reason) override {
+    EXPECT_EQ(reason, CommitEarlyOutReason::ABORTED_DEFERRED_MAIN_FRAME_UPDATE);
+
+    // Since the main frame is aborted due to deferred main frame updates,
+    // events metrics should not have been thrown away.
+    PostVerifyMainSavedEventsMetricsCount(1);
+
+    // Stop deferring main frame updates so that the deferred commit is
+    // completed, causing events metrics being passed to the impl thread.
+    PostStopDeferringMainFrameUpdate();
+  }
+
+  void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
+    // Now that a commit is completed and activated, events metrics from main
+    // thread should have been moved to the impl thread.
+    PostVerifyMainSavedEventsMetricsCount(0);
+    EXPECT_SCOPED(VerifyImplEventsMetricsFromMainCount(impl, 1));
+
+    EndTest();
+  }
+
+ private:
+  void DeferMainFrameUpdateOnMain() {
+    scoped_defer_main_frame_update_ = layer_tree_host()->DeferMainFrameUpdate();
+  }
+
+  void PostDeferMainFrameUpdate() {
+    MainThreadTaskRunner()->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            &LayerTreeHostTestKeepEventsMetricsForDeferredMainFrameUpdate::
+                DeferMainFrameUpdateOnMain,
+            base::Unretained(this)));
+  }
+
+  void StopDeferringMainFrameUpdateOnMain() {
+    scoped_defer_main_frame_update_.reset();
+  }
+
+  void PostStopDeferringMainFrameUpdate() {
+    MainThreadTaskRunner()->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            &LayerTreeHostTestKeepEventsMetricsForDeferredMainFrameUpdate::
+                StopDeferringMainFrameUpdateOnMain,
+            base::Unretained(this)));
+  }
+
+  bool received_will_begin_impl_frame_ = false;
+  std::unique_ptr<ScopedDeferMainFrameUpdate> scoped_defer_main_frame_update_;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(
+    LayerTreeHostTestKeepEventsMetricsForDeferredMainFrameUpdate);
+
+// Verifies that if the commit is aborted (deferred), events metrics are not
+// thrown away to be used when the actual commit happens.
+class LayerTreeHostTestKeepEventsMetricsForDeferredCommit
+    : public LayerTreeHostTestEventsMetrics {
+ protected:
+  void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
+                                  const viz::BeginFrameArgs& args) override {
+    // Skip if we have already received a begin-impl-frame and acted on it.
+    if (received_will_begin_impl_frame_)
+      return;
+    received_will_begin_impl_frame_ = true;
+
+    EXPECT_SCOPED(VerifyImplEventsMetricsFromMainCount(impl, 0));
+
+    // Simulate an event being handled on the main thread. Since the main frame
+    // is not yet scheduled, we will have events metrics when the main frame is
+    // processed.
+    PostSimulateEvent();
+
+    // Defer commits. Since the main frame is not yet scheduled, commits will be
+    // deferred when the main frame is processed, causing it to abort.
+    PostDeferCommit();
+  }
+
+  void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* impl,
+                                     CommitEarlyOutReason reason) override {
+    EXPECT_EQ(reason, CommitEarlyOutReason::ABORTED_DEFERRED_COMMIT);
+
+    // Since the main frame is aborted due to deferred commits, events metrics
+    // should not have been thrown away.
+    PostVerifyMainSavedEventsMetricsCount(1);
+
+    // Stop deferring commits so that the deferred commit is completed, causing
+    // events metrics being passed to the impl thread.
+    PostStopDeferringCommit();
+  }
+
+  void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
+    // Now that a commit is completed and activated, events metrics from main
+    // thread should have been moved to the impl thread.
+    PostVerifyMainSavedEventsMetricsCount(0);
+    EXPECT_SCOPED(VerifyImplEventsMetricsFromMainCount(impl, 1));
+
+    EndTest();
+  }
+
+ private:
+  void DeferCommitOnMain() {
+    layer_tree_host()->StartDeferringCommits(base::TimeDelta::FromDays(1));
+  }
+
+  void PostDeferCommit() {
+    MainThreadTaskRunner()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&LayerTreeHostTestKeepEventsMetricsForDeferredCommit::
+                           DeferCommitOnMain,
+                       base::Unretained(this)));
+  }
+
+  void StopDeferringCommitOnMain() {
+    layer_tree_host()->StopDeferringCommits(
+        PaintHoldingCommitTrigger::kFirstContentfulPaint);
+  }
+
+  void PostStopDeferringCommit() {
+    MainThreadTaskRunner()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&LayerTreeHostTestKeepEventsMetricsForDeferredCommit::
+                           StopDeferringCommitOnMain,
+                       base::Unretained(this)));
+  }
+
+  bool received_will_begin_impl_frame_ = false;
+};
+
+SINGLE_AND_MULTI_THREAD_TEST_F(
+    LayerTreeHostTestKeepEventsMetricsForDeferredCommit);
+
+// Verifies that if the commit is aborted due to no damage, events metrics are
+// thrown away, so there is nothing to report in the next commit.
+class LayerTreeHostTestIgnoreEventsMetricsForNoUpdate
+    : public LayerTreeHostTestEventsMetrics {
+ protected:
+  void WillBeginImplFrameOnThread(LayerTreeHostImpl* impl,
+                                  const viz::BeginFrameArgs& args) override {
+    // Continue only if we are waiting for the second frame's being-impl-frame.
+    // The first frame will end up in a commit which is not what we want.
+    if (state_ != State::kWaitingForSecondFrameBeginImpl)
+      return;
+    state_ = State::kReceivedSecondFrameBeginImpl;
+
+    EXPECT_SCOPED(VerifyImplEventsMetricsFromMainCount(impl, 0));
+
+    // Simulate an event being handled on the main thread. Since the main frame
+    // is not yet scheduled, we will have events metrics when the main frame is
+    // processed.
+    PostSimulateEvent();
+  }
+
+  void BeginMainFrameAbortedOnThread(LayerTreeHostImpl* impl,
+                                     CommitEarlyOutReason reason) override {
+    EXPECT_EQ(reason, CommitEarlyOutReason::FINISHED_NO_UPDATES);
+
+    // We should reach here only for the second frame.
+    EXPECT_EQ(state_, State::kReceivedSecondFrameBeginImpl);
+    state_ = State::kWaitingForThirdFrameActivation;
+
+    // Since the main frame is aborted due to no updates, events metrics should
+    // have been thrown away.
+    PostVerifyMainSavedEventsMetricsCount(0);
+
+    // Request another commit to make sure no events metrics is passed to the
+    // impl thread when it is complete.
+    PostSetNeedsCommitToMainThread();
+  }
+
+  void DidActivateTreeOnThread(LayerTreeHostImpl* impl) override {
+    switch (state_) {
+      case State::kWaitingForFirstFrameActivation:
+        // Now that the first frame's commit is completed and activated, request
+        // another begin-main-frame without requesting a full commit so that it
+        // aborts with no updates.
+        state_ = State::kWaitingForSecondFrameBeginImpl;
+        EXPECT_SCOPED(VerifyImplEventsMetricsFromMainCount(impl, 0));
+        PostSetNeedsUpdateLayersToMainThread();
+        break;
+      case State::kWaitingForThirdFrameActivation:
+        // Now that the third frame's commit is completed and activated there
+        // should be no events metrics on the main or impl thread as the events
+        // metrics were thrown away after second frame was aborted with no
+        // updates.
+        EXPECT_SCOPED(VerifyImplEventsMetricsFromMainCount(impl, 0));
+        PostVerifyMainSavedEventsMetricsCount(0);
+        EndTest();
+        break;
+      default:
+        NOTREACHED();
+    }
+  }
+
+ private:
+  enum class State {
+    kWaitingForFirstFrameActivation,
+    kWaitingForSecondFrameBeginImpl,
+    kReceivedSecondFrameBeginImpl,
+    kWaitingForThirdFrameActivation,
+  };
+
+  State state_ = State::kWaitingForFirstFrameActivation;
+};
+
+MULTI_THREAD_TEST_F(LayerTreeHostTestIgnoreEventsMetricsForNoUpdate);
+
 }  // namespace
 }  // namespace cc
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index 187207a6..b303eb5 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -730,6 +730,10 @@
     return std::move(delegated_ink_metadata_);
   }
 
+  size_t events_metrics_from_main_thread_count_for_testing() const {
+    return events_metrics_from_main_thread_.size();
+  }
+
  protected:
   float ClampPageScaleFactorToLimits(float page_scale_factor) const;
   void PushPageScaleFactorAndLimits(const float* page_scale_factor,
diff --git a/cc/trees/proxy_main.cc b/cc/trees/proxy_main.cc
index 1ad9795..e52420a 100644
--- a/cc/trees/proxy_main.cc
+++ b/cc/trees/proxy_main.cc
@@ -5,7 +5,10 @@
 #include "cc/trees/proxy_main.h"
 
 #include <algorithm>
+#include <memory>
 #include <string>
+#include <utility>
+#include <vector>
 
 #include "base/bind.h"
 #include "base/trace_event/trace_event.h"
@@ -147,6 +150,10 @@
   // after tab becomes visible again.
   if (!layer_tree_host_->IsVisible()) {
     TRACE_EVENT_INSTANT0("cc", "EarlyOut_NotVisible", TRACE_EVENT_SCOPE_THREAD);
+
+    // In this case, since the commit is deferred to a later time, gathered
+    // events metrics are not discarded so that they can be reported if the
+    // commit happens in the future.
     std::vector<std::unique_ptr<SwapPromise>> empty_swap_promises;
     ImplThreadTaskRunner()->PostTask(
         FROM_HERE, base::BindOnce(&ProxyImpl::BeginMainFrameAbortedOnImpl,
@@ -177,6 +184,10 @@
   if (skip_full_pipeline) {
     TRACE_EVENT_INSTANT0("cc", "EarlyOut_DeferCommit",
                          TRACE_EVENT_SCOPE_THREAD);
+
+    // In this case, since the commit is deferred to a later time, gathered
+    // events metrics are not discarded so that they can be reported if the
+    // commit happens in the future.
     std::vector<std::unique_ptr<SwapPromise>> empty_swap_promises;
     ImplThreadTaskRunner()->PostTask(
         FROM_HERE,
@@ -260,6 +271,10 @@
     layer_tree_host_->RecordEndOfFrameMetrics(
         begin_main_frame_start_time,
         begin_main_frame_state->active_sequence_trackers);
+
+    // In this case, since the commit is deferred to a later time, gathered
+    // events metrics are not discarded so that they can be reported if the
+    // commit happens in the future.
     std::vector<std::unique_ptr<SwapPromise>> empty_swap_promises;
     ImplThreadTaskRunner()->PostTask(
         FROM_HERE, base::BindOnce(&ProxyImpl::BeginMainFrameAbortedOnImpl,
@@ -309,8 +324,9 @@
     std::vector<std::unique_ptr<SwapPromise>> swap_promises =
         layer_tree_host_->GetSwapPromiseManager()->TakeSwapPromises();
 
-    // Since the BeginMainFrame has been aborted, handling of events on the main
-    // frame had no effect and no metrics should be reported for such events.
+    // Since the commit has been aborted due to no updates, handling of events
+    // on the main frame had no effect and no metrics should be reported for
+    // such events.
     layer_tree_host_->ClearEventsMetrics();
 
     ImplThreadTaskRunner()->PostTask(
diff --git a/chrome/VERSION b/chrome/VERSION
index 42cc8a2..ac1d61c 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=86
 MINOR=0
-BUILD=4203
+BUILD=4204
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 38ff545..f3a20d7 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -975,6 +975,8 @@
     "//chrome/browser/performance_hints/android:java",
     "//chrome/browser/preferences:java",
     "//chrome/browser/profiles/android:java",
+    "//chrome/browser/safe_browsing/android:java",
+    "//chrome/browser/safe_browsing/android:javatests",
     "//chrome/browser/safety_check/android:java",
     "//chrome/browser/safety_check/android:javatests",
     "//chrome/browser/settings:java",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
index e0599ce7..67241d86 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -1226,8 +1226,6 @@
                         .with(TabProperties.IS_SELECTED, isSelected)
                         .with(TabProperties.IPH_PROVIDER, showIPH ? mIphProvider : null)
                         .with(CARD_ALPHA, 1f)
-                        .with(TabProperties.TAB_CLOSED_LISTENER,
-                                isRealTab ? mTabClosedListener : null)
                         .with(TabProperties.CARD_ANIMATION_STATUS,
                                 ClosableTabGridView.AnimationStatus.CARD_RESTORE)
                         .with(TabProperties.TAB_SELECTION_DELEGATE,
@@ -1277,7 +1275,7 @@
                     TabProperties.SELECTABLE_TAB_CLICKED_LISTENER, mSelectableTabOnClickListener);
         } else {
             tabInfo.set(TabProperties.TAB_SELECTED_LISTENER, tabSelectedListener);
-            tabInfo.set(TabProperties.TAB_CLOSED_LISTENER, mTabClosedListener);
+            tabInfo.set(TabProperties.TAB_CLOSED_LISTENER, isRealTab ? mTabClosedListener : null);
         }
 
         if (index >= mModel.size()) {
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTest.java
index f2c43e6..80b8fd5 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTest.java
@@ -460,6 +460,22 @@
 
     @Test
     @MediumTest
+    @CommandLineFlags.Add(BaseSwitches.ENABLE_LOW_END_DEVICE_MODE)
+    @EnableFeatures({ChromeFeatureList.TAB_GROUPS_CONTINUATION_ANDROID})
+    public void testListView_select() throws IOException {
+        prepareBlankTab(2, false);
+        List<Tab> tabs = getTabsInCurrentTabModel();
+
+        TestThreadUtils.runOnUiThreadBlocking(() -> mTabSelectionEditorController.show(tabs));
+
+        mRobot.actionRobot.clickItemAtAdapterPosition(0);
+        mRobot.resultRobot.verifyToolbarActionButtonDisabled().verifyTabSelectionEditorIsVisible();
+        mRobot.actionRobot.clickEndButtonAtAdapterPosition(1);
+        mRobot.resultRobot.verifyToolbarActionButtonEnabled().verifyTabSelectionEditorIsVisible();
+    }
+
+    @Test
+    @MediumTest
     @DisableFeatures({ChromeFeatureList.TAB_GROUPS_ANDROID})
     public void testTabSelectionEditorLayoutCanBeGarbageCollected() {
         TestThreadUtils.runOnUiThreadBlocking(() -> {
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTestingRobot.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTestingRobot.java
index 08117f79..44a9f7a3 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTestingRobot.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorTestingRobot.java
@@ -35,6 +35,8 @@
 import androidx.test.espresso.NoMatchingRootException;
 import androidx.test.espresso.NoMatchingViewException;
 import androidx.test.espresso.Root;
+import androidx.test.espresso.UiController;
+import androidx.test.espresso.ViewAction;
 import androidx.test.espresso.matcher.BoundedMatcher;
 
 import org.hamcrest.Description;
@@ -165,6 +167,35 @@
                     .perform(click());
             return this;
         }
+
+        public TabSelectionEditorTestingRobot.Action clickEndButtonAtAdapterPosition(int position) {
+            onView(withId(org.chromium.chrome.tab_ui.R.id.tab_list_view))
+                    .inRoot(isTabSelectionEditorPopup())
+                    .perform(new ViewAction() {
+                        @Override
+                        public Matcher<View> getConstraints() {
+                            return isDisplayed();
+                        }
+
+                        @Override
+                        public String getDescription() {
+                            return "click on end button of item with index "
+                                    + String.valueOf(position);
+                        }
+
+                        @Override
+                        public void perform(UiController uiController, View view) {
+                            RecyclerView recyclerView = (RecyclerView) view;
+                            RecyclerView.ViewHolder viewHolder =
+                                    recyclerView.findViewHolderForAdapterPosition(position);
+                            if (viewHolder.itemView == null) return;
+                            viewHolder.itemView
+                                    .findViewById(org.chromium.chrome.tab_ui.R.id.end_button)
+                                    .performClick();
+                        }
+                    });
+            return this;
+        }
     }
 
     /**
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardTest.java
index 45f32bb..4872b5b 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabSuggestionMessageCardTest.java
@@ -154,9 +154,12 @@
 
     @Test
     @MediumTest
-    @CommandLineFlags.
-    Add({BASE_PARAMS + "/baseline_group_tab_suggestions/true/min_time_between_prefetches/0"})
+    // clang-format off
+    @CommandLineFlags.Add({BASE_PARAMS +
+        "/baseline_group_tab_suggestions/true/min_time_between_prefetches/0"})
+    @DisableIf.Build(supported_abis_includes = "x86", message = "https://crbug.com/1102423")
     public void groupTabSuggestionReviewedAndDismissed() {
+        // clang-format on
         CriteriaHelper.pollUiThread(TabSuggestionMessageService::isSuggestionAvailableForTesting);
 
         enteringTabSwitcherAndVerifySuggestionIsShown(mGroupingSuggestionMessage);
diff --git a/chrome/android/java/res/values/dimens.xml b/chrome/android/java/res/values/dimens.xml
index fdf2aa0..7c0d51c2d 100644
--- a/chrome/android/java/res/values/dimens.xml
+++ b/chrome/android/java/res/values/dimens.xml
@@ -203,7 +203,7 @@
          83dp -->
     <dimen name="webapk_adaptive_icon_size">83dp</dimen>
 
-    <dimen name="webapk_badge_icon_size">24dp</dimen>
+    <dimen name="webapk_monochrome_icon_size">24dp</dimen>
 
     <!-- Toolbar dimensions -->
     <dimen name="toolbar_tab_count_text_size_1_digit">12dp</dimen>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
index 7a683f7..0ed9c3c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ShortcutHelper.java
@@ -678,12 +678,12 @@
     }
 
     /**
-     * Returns the ideal size for a badge icon of a WebAPK.
+     * Returns the ideal size for a monochrome icon of a WebAPK.
      * @param context Context to pull resources from.
-     * @return the dimensions in pixels which the badge icon should have.
+     * @return the dimensions in pixels which the monochrome icon should have.
      */
-    public static int getIdealBadgeIconSizeInPx(Context context) {
-        return getSizeFromResourceInPx(context, R.dimen.webapk_badge_icon_size);
+    public static int getIdealMonochromeIconSizeInPx(Context context) {
+        return getSizeFromResourceInPx(context, R.dimen.webapk_monochrome_icon_size);
     }
 
     /**
@@ -747,7 +747,7 @@
         // This ordering must be kept up to date with the C++ ShortcutHelper.
         return new int[] {getIdealHomescreenIconSizeInPx(context),
                 getMinimumHomescreenIconSizeInPx(context), getIdealSplashImageSizeInPx(context),
-                getMinimumSplashImageSizeInPx(context), getIdealBadgeIconSizeInPx(context),
+                getMinimumSplashImageSizeInPx(context), getIdealMonochromeIconSizeInPx(context),
                 getIdealAdaptiveLauncherIconSizeInPx(context),
                 ViewUtils.dpToPx(context, SHORTCUT_ICON_IDEAL_SIZE_DP)};
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRequest.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRequest.java
index 03db4e5..42381aa2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRequest.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchRequest.java
@@ -176,14 +176,17 @@
     }
 
     /**
-     * Adds translation parameters.
+     * Adds translation parameters, unless they match.
      * @param sourceLanguage The language of the original search term.
      * @param targetLanguage The language the that the user prefers.
      */
     void forceTranslation(String sourceLanguage, String targetLanguage) {
         mIsTranslationForced = true;
         // If the server is providing a full URL then we shouldn't alter it.
-        if (mIsFullSearchUrlProvided) return;
+        if (mIsFullSearchUrlProvided || TextUtils.isEmpty(targetLanguage)
+                || targetLanguage.equals(sourceLanguage)) {
+            return;
+        }
 
         if (mLowPriorityUri != null) {
             mLowPriorityUri = makeTranslateUri(mLowPriorityUri, sourceLanguage, targetLanguage);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
index 70c67b2..5aa9805 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -36,6 +36,7 @@
 import org.chromium.chrome.browser.payments.ui.PaymentInformation;
 import org.chromium.chrome.browser.payments.ui.PaymentRequestSection.OptionSection.FocusChangedObserver;
 import org.chromium.chrome.browser.payments.ui.PaymentRequestUI;
+import org.chromium.chrome.browser.payments.ui.PaymentRequestUI.SelectionResult;
 import org.chromium.chrome.browser.payments.ui.SectionInformation;
 import org.chromium.chrome.browser.payments.ui.ShoppingCart;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -107,7 +108,6 @@
 import org.chromium.url.GURL;
 import org.chromium.url.Origin;
 
-import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -317,7 +317,7 @@
     private static final Comparator<Completable> COMPLETENESS_COMPARATOR =
             (a, b) -> (compareCompletablesByCompleteness(b, a));
 
-    private WeakReference<ComponentPaymentRequestImpl> mComponentPaymentRequestImpl;
+    private ComponentPaymentRequestImpl mComponentPaymentRequestImpl;
 
     private PaymentOptions mPaymentOptions;
     private boolean mRequestShipping;
@@ -627,8 +627,9 @@
     // Implement ComponentPaymentRequestDelegate:
     @Override
     public void setComponentPaymentRequestImpl(
-            WeakReference<ComponentPaymentRequestImpl> componentPaymentRequestImpl) {
+            ComponentPaymentRequestImpl componentPaymentRequestImpl) {
         assert mComponentPaymentRequestImpl == null;
+        assert componentPaymentRequestImpl != null;
         mComponentPaymentRequestImpl = componentPaymentRequestImpl;
     }
 
@@ -1166,7 +1167,8 @@
     }
 
     private void onMinimalUiErroredAndClosed() {
-        mComponentPaymentRequestImpl.get().closeClient();
+        if (getClient() == null) return;
+        closeClient();
         closeUIAndDestroyNativeObjects();
     }
 
@@ -1175,7 +1177,7 @@
         if (client != null) {
             client.onComplete();
         }
-        mComponentPaymentRequestImpl.get().closeClient();
+        closeClient();
         closeUIAndDestroyNativeObjects();
     }
 
@@ -1833,6 +1835,8 @@
     @PaymentRequestUI.SelectionResult
     public int onSectionOptionSelected(@PaymentRequestUI.DataType int optionType,
             EditableOption option, Callback<PaymentInformation> callback) {
+        PaymentRequestClient client = getClient();
+        if (client == null) return SelectionResult.NONE;
         if (optionType == PaymentRequestUI.DataType.SHIPPING_ADDRESSES) {
             // Log the change of shipping address.
             mJourneyLogger.incrementSelectionChanges(Section.SHIPPING_ADDRESS);
@@ -1848,7 +1852,7 @@
         } else if (optionType == PaymentRequestUI.DataType.SHIPPING_OPTIONS) {
             // This may update the line items.
             mUiShippingOptions.setSelectedItem(option);
-            getClient().onShippingOptionChange(option.getIdentifier());
+            client.onShippingOptionChange(option.getIdentifier());
             mPaymentInformationCallback = callback;
             return PaymentRequestUI.SelectionResult.ASYNCHRONOUS_VALIDATION;
         } else if (optionType == PaymentRequestUI.DataType.CONTACT_DETAILS) {
@@ -2228,7 +2232,7 @@
         Log.d(TAG, debugMessage);
         PaymentRequestClient client = getClient();
         if (client != null) client.onError(reason, debugMessage);
-        mComponentPaymentRequestImpl.get().closeClient();
+        closeClient();
         closeUIAndDestroyNativeObjects();
         if (mNativeObserverForTest != null) mNativeObserverForTest.onConnectionTerminated();
     }
@@ -2251,9 +2255,11 @@
     /** Called by the payment app in response to an abort request. */
     @Override
     public void onInstrumentAbortResult(boolean abortSucceeded) {
-        getClient().onAbort(abortSucceeded);
+        PaymentRequestClient client = getClient();
+        if (client == null) return;
+        client.onAbort(abortSucceeded);
         if (abortSucceeded) {
-            mComponentPaymentRequestImpl.get().closeClient();
+            closeClient();
             mJourneyLogger.setAborted(AbortReason.ABORTED_BY_MERCHANT);
             closeUIAndDestroyNativeObjects();
         } else {
@@ -2549,7 +2555,7 @@
     @Override
     public void close() {
         if (getClient() == null) return;
-        mComponentPaymentRequestImpl.get().closeClient();
+        closeClient();
         mJourneyLogger.setAborted(AbortReason.MOJO_RENDERER_CLOSING);
         if (sObserverForTest != null) sObserverForTest.onRendererClosedMojoConnection();
         closeUIAndDestroyNativeObjects();
@@ -2563,7 +2569,7 @@
     @Override
     public void onConnectionError(MojoException e) {
         if (getClient() == null) return;
-        mComponentPaymentRequestImpl.get().closeClient();
+        closeClient();
         mJourneyLogger.setAborted(AbortReason.MOJO_CONNECTION_ERROR);
         closeUIAndDestroyNativeObjects();
         if (mNativeObserverForTest != null) mNativeObserverForTest.onConnectionTerminated();
@@ -2929,8 +2935,9 @@
             disconnectFromClientWithDebugMessage(
                     ErrorStrings.PAYMENT_APP_INVALID_RESPONSE, PaymentErrorReason.NOT_SUPPORTED);
         }
-
-        getClient().onPaymentResponse(response);
+        PaymentRequestClient client = getClient();
+        if (client == null) return;
+        client.onPaymentResponse(response);
         mPaymentResponseHelper = null;
         if (sObserverForTest != null) sObserverForTest.onPaymentResponseReady();
     }
@@ -2979,6 +2986,8 @@
 
     @Override
     public void onAddressNormalized(AutofillProfile profile) {
+        PaymentRequestClient client = getClient();
+        if (client == null) return;
         ChromeActivity chromeActivity = ChromeActivity.fromWebContents(mWebContents);
 
         // Can happen if the tab is closed during the normalization process.
@@ -2996,7 +3005,7 @@
         redactShippingAddress(redactedAddress);
 
         // This updates the line items and the shipping options asynchronously.
-        getClient().onShippingAddressChange(redactedAddress);
+        client.onShippingAddressChange(redactedAddress);
     }
 
     @Override
@@ -3037,8 +3046,8 @@
             if (client != null) {
                 if (sObserverForTest != null) sObserverForTest.onCompleteReplied();
                 client.onComplete();
+                closeClient();
             }
-            mComponentPaymentRequestImpl.get().closeClient();
             ChromeActivity activity = ChromeActivity.fromWebContents(mWebContents);
             if (activity != null) {
                 activity.getLifecycleDispatcher().unregister(mUI);
@@ -3180,7 +3189,14 @@
         return -Math.log((currentTime - date) / (24 * 60 * 60 * 1000) + 2) / Math.log(count + 2);
     }
 
+    @Nullable
     private PaymentRequestClient getClient() {
-        return mComponentPaymentRequestImpl.get().getClient();
+        return mComponentPaymentRequestImpl.getClient();
+    }
+
+    // Pre-condition: the client is not null.
+    private void closeClient() {
+        assert getClient() != null;
+        mComponentPaymentRequestImpl.closeClient();
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileUtils.java
index 0e37b2d..2b7eedd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/query_tiles/QueryTileUtils.java
@@ -16,7 +16,8 @@
      * @return Whether the query tile feature is enabled.
      */
     public static boolean isFeatureEnabled() {
-        return ChromeFeatureList.isEnabled(ChromeFeatureList.QUERY_TILES);
+        return ChromeFeatureList.isEnabled(ChromeFeatureList.QUERY_TILES_GEO_FILTER)
+                && ChromeFeatureList.isEnabled(ChromeFeatureList.QUERY_TILES);
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java
index 59f7db8..a201128 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java
@@ -14,7 +14,6 @@
 
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.test.util.CommandLineFlags;
-import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.autofill.AutofillTestHelper;
@@ -56,7 +55,6 @@
     @Test
     @MediumTest
     @Feature({"Payments"})
-    @DisabledTest(message = "http://crbug.com/1104367")
     public void testSecondShowRequestCancelled() throws TimeoutException {
         mPaymentRequestTestRule.triggerUIAndWait(mPaymentRequestTestRule.getReadyToPay());
         mPaymentRequestTestRule.expectResultContains(new String[] {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java
index 7e0e73a..a658c62 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/MainSettingsFragmentTest.java
@@ -6,9 +6,11 @@
 
 import android.accounts.Account;
 import android.text.TextUtils;
+import android.view.View;
 
 import androidx.annotation.Nullable;
 import androidx.preference.Preference;
+import androidx.test.filters.LargeTest;
 import androidx.test.filters.SmallTest;
 
 import org.junit.After;
@@ -23,6 +25,7 @@
 import org.mockito.MockitoAnnotations;
 
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.about_settings.AboutChromeSettings;
 import org.chromium.chrome.browser.accessibility.settings.AccessibilitySettings;
@@ -49,6 +52,7 @@
 import org.chromium.chrome.browser.sync.settings.SyncAndServicesSettings;
 import org.chromium.chrome.browser.tracing.settings.DeveloperSettings;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.util.ChromeRenderTestRule;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.chrome.test.util.browser.sync.SyncTestUtil;
 import org.chromium.components.browser_ui.site_settings.SiteSettings;
@@ -56,6 +60,8 @@
 import org.chromium.components.search_engines.TemplateUrlService;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
+import java.io.IOException;
+
 /**
  * Test for {@link MainSettings}. Main purpose is to have a sanity check on the xml.
  */
@@ -69,7 +75,7 @@
     private final SyncTestRule mSyncTestRule = new SyncTestRule();
 
     private final SettingsActivityTestRule<MainSettings> mSettingsActivityTestRule =
-            new SettingsActivityTestRule<>(MainSettings.class);
+            new SettingsActivityTestRule<>(MainSettings.class, true);
 
     // SettingsActivity needs to be initialized and destroyed with the mock
     // signin environment setup in SyncTestRule
@@ -78,6 +84,10 @@
                                                 .around(mHomepageTestRule)
                                                 .around(mSettingsActivityTestRule);
 
+    @Rule
+    public ChromeRenderTestRule mRenderTestRule =
+            ChromeRenderTestRule.Builder.withPublicCorpus().build();
+
     @Mock
     public TemplateUrlService mMockTemplateUrlService;
     @Mock
@@ -123,6 +133,22 @@
         Mockito.doReturn(SEARCH_ENGINE_SHORT_NAME).when(mMockSearchEngine).getShortName();
     }
 
+    @Test
+    @LargeTest
+    @Feature({"RenderTest"})
+    public void testRenderDifferentSignedInStates() throws IOException {
+        launchSettingsActivity();
+        View view = mSettingsActivityTestRule.getActivity()
+                            .findViewById(android.R.id.content)
+                            .getRootView();
+        mRenderTestRule.render(view, "main_settings_signed_out");
+
+        // Sign in and render changes.
+        mSyncTestRule.setUpAccountAndSignInForTesting();
+        SyncTestUtil.waitForSyncActive();
+        mRenderTestRule.render(view, "main_settings_signed_in");
+    }
+
     /**
      * Test for the "Account" section.
      */
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
index 3c4593a..3264792 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebApkUpdateManagerUnitTest.java
@@ -977,10 +977,11 @@
      * AND
      * - "best" icon URL for the primary icon did not change.
      * AND
-     * - "best" icon URL for the badge icon did not change.
+     * - "best" icon URL for the monochrome icon did not change.
      */
     @Test
-    public void testIconUrlsChangeShouldNotUpgradeIfPrimaryIconUrlAndBadgeIconUrlDoNotChange() {
+    public void
+    testIconUrlsChangeShouldNotUpgradeIfPrimaryIconUrlAndMonochromeIconUrlDoNotChange() {
         ManifestData fetchedData = defaultManifestData();
         fetchedData.iconUrlToMurmur2HashMap.put("/icon2.png", null);
         assertFalse(checkUpdateNeededForFetchedManifest(defaultManifestData(), fetchedData));
@@ -998,8 +999,8 @@
     public void testWebManifestSameButBestIconUrlChangedShouldNotUpgrade() {
         String iconUrl1 = "/icon1.png";
         String iconUrl2 = "/icon2.png";
-        String badgeUrl1 = "/badge1.png";
-        String badgeUrl2 = "/badge2.pgn";
+        String monochromeUrl1 = "/monochrome1.png";
+        String monochromeUrl2 = "/monochrome2.png";
         String hash1 = "11";
         String hash2 = "22";
         String hash3 = "33";
@@ -1010,16 +1011,16 @@
         androidManifestData.iconUrlToMurmur2HashMap.clear();
         androidManifestData.iconUrlToMurmur2HashMap.put(iconUrl1, hash1);
         androidManifestData.iconUrlToMurmur2HashMap.put(iconUrl2, hash2);
-        androidManifestData.iconUrlToMurmur2HashMap.put(badgeUrl1, hash3);
-        androidManifestData.iconUrlToMurmur2HashMap.put(badgeUrl2, hash4);
+        androidManifestData.iconUrlToMurmur2HashMap.put(monochromeUrl1, hash3);
+        androidManifestData.iconUrlToMurmur2HashMap.put(monochromeUrl2, hash4);
 
         ManifestData fetchedManifestData = defaultManifestData();
         fetchedManifestData.primaryIconUrl = iconUrl2;
         fetchedManifestData.iconUrlToMurmur2HashMap.clear();
         fetchedManifestData.iconUrlToMurmur2HashMap.put(iconUrl1, null);
         fetchedManifestData.iconUrlToMurmur2HashMap.put(iconUrl2, hash2);
-        fetchedManifestData.iconUrlToMurmur2HashMap.put(badgeUrl1, null);
-        fetchedManifestData.iconUrlToMurmur2HashMap.put(badgeUrl2, hash4);
+        fetchedManifestData.iconUrlToMurmur2HashMap.put(monochromeUrl1, null);
+        fetchedManifestData.iconUrlToMurmur2HashMap.put(monochromeUrl2, hash4);
 
         assertFalse(checkUpdateNeededForFetchedManifest(androidManifestData, fetchedManifestData));
     }
diff --git a/chrome/android/native_java_unittests/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java b/chrome/android/native_java_unittests/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java
index fa25b57f7..62067fc 100644
--- a/chrome/android/native_java_unittests/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java
+++ b/chrome/android/native_java_unittests/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorUnitTest.java
@@ -24,6 +24,7 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.CalledByNativeJavaTest;
 import org.chromium.base.annotations.NativeJavaTestFeatures;
+import org.chromium.base.test.util.FlakyTest;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
@@ -156,6 +157,7 @@
     @CalledByNativeJavaTest
     @NativeJavaTestFeatures.Disable({ChromeFeatureList.OMNIBOX_COMPACT_SUGGESTIONS,
             ChromeFeatureList.OMNIBOX_SUGGESTIONS_WRAP_AROUND})
+    @FlakyTest(message = "https://crbug.com/1105304")
     public void
     getSuggestionIconTypeForSearch_Default() {
         int[][] testCases = {
@@ -308,6 +310,7 @@
     @CalledByNativeJavaTest
     @NativeJavaTestFeatures.Disable({ChromeFeatureList.OMNIBOX_COMPACT_SUGGESTIONS,
             ChromeFeatureList.OMNIBOX_SUGGESTIONS_WRAP_AROUND})
+    @FlakyTest(message = "https://crbug.com/1105305")
     public void
     suggestionFavicons_showFaviconWhenAvailable() {
         final ArgumentCaptor<LargeIconCallback> callback =
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index d1f6a08..f70e9f4 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2620,6 +2620,10 @@
      flag_descriptions::kShareButtonInTopToolbarName,
      flag_descriptions::kShareButtonInTopToolbarDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(chrome::android::kShareButtonInTopToolbar)},
+    {"chrome-share-highlights-android",
+     flag_descriptions::kChromeShareHighlightsAndroidName,
+     flag_descriptions::kChromeShareHighlightsAndroidDescription, kOsAndroid,
+     FEATURE_VALUE_TYPE(chrome::android::kChromeShareHighlightsAndroid)},
     {"chrome-share-qr-code", flag_descriptions::kChromeShareQRCodeName,
      flag_descriptions::kChromeShareQRCodeDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(chrome::android::kChromeShareQRCode)},
@@ -3159,6 +3163,10 @@
     {"enable-cros-ime-sandbox", flag_descriptions::kImeServiceSandboxName,
      flag_descriptions::kImeServiceSandboxDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(chromeos::features::kEnableImeSandbox)},
+    {"enable-cros-language-settings-update",
+     flag_descriptions::kCrosLanguageSettingsUpdateName,
+     flag_descriptions::kCrosLanguageSettingsUpdateDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(chromeos::features::kLanguageSettingsUpdate)},
     {"enable-cros-virtual-keyboard-bordered-key",
      flag_descriptions::kVirtualKeyboardBorderedKeyName,
      flag_descriptions::kVirtualKeyboardBorderedKeyDescription, kOsCrOS,
diff --git a/chrome/browser/android/shortcut_helper.cc b/chrome/browser/android/shortcut_helper.cc
index eeb6903..bf0dcf7 100644
--- a/chrome/browser/android/shortcut_helper.cc
+++ b/chrome/browser/android/shortcut_helper.cc
@@ -45,7 +45,7 @@
 int g_minimum_homescreen_icon_size = -1;
 int g_ideal_splash_image_size = -1;
 int g_minimum_splash_image_size = -1;
-int g_ideal_badge_icon_size = -1;
+int g_ideal_monochrome_icon_size = -1;
 int g_ideal_adaptive_launcher_icon_size = -1;
 int g_ideal_shortcut_icon_size = -1;
 
@@ -68,7 +68,7 @@
   g_minimum_homescreen_icon_size = sizes[1];
   g_ideal_splash_image_size = sizes[2];
   g_minimum_splash_image_size = sizes[3];
-  g_ideal_badge_icon_size = sizes[4];
+  g_ideal_monochrome_icon_size = sizes[4];
   g_ideal_adaptive_launcher_icon_size = sizes[5];
   g_ideal_shortcut_icon_size = sizes[6];
 
diff --git a/chrome/browser/android/webapk/webapk.proto b/chrome/browser/android/webapk/webapk.proto
index 8aa204b3..f8f5e0d7b 100644
--- a/chrome/browser/android/webapk/webapk.proto
+++ b/chrome/browser/android/webapk/webapk.proto
@@ -126,9 +126,8 @@
     // The icon can be displayed in any context.
     ANY = 1;
 
-    // The icon can be used where space constraints and/or color requirements
-    // differ from those of the application icon.
-    // BADGE = 2; We do not plan to support Badge purpose, and will ignore it.
+    // The icon can be used where a monochrome icon with a solid fill is needed.
+    // MONOCHROME = 2; This is not currently used, so ignore it.
 
     // The icon is designed with the intention to be masked.
     MASKABLE = 3;
diff --git a/chrome/browser/chromeos/apps/apk_web_app_installer.cc b/chrome/browser/chromeos/apps/apk_web_app_installer.cc
index 9576875..ef15c18 100644
--- a/chrome/browser/chromeos/apps/apk_web_app_installer.cc
+++ b/chrome/browser/chromeos/apps/apk_web_app_installer.cc
@@ -90,8 +90,8 @@
   DCHECK(web_app_info_->scope.is_valid());
 
   if (web_app_info->theme_color != kInvalidColor) {
-    web_app_info_->theme_color =
-        static_cast<SkColor>(web_app_info->theme_color);
+    web_app_info_->theme_color = SkColorSetA(
+        static_cast<SkColor>(web_app_info->theme_color), SK_AlphaOPAQUE);
   }
   web_app_info_->display_mode = blink::mojom::DisplayMode::kStandalone;
   web_app_info_->open_as_window = true;
diff --git a/chrome/browser/chromeos/apps/apk_web_app_installer_unittest.cc b/chrome/browser/chromeos/apps/apk_web_app_installer_unittest.cc
index 3f84345..1df164e 100644
--- a/chrome/browser/chromeos/apps/apk_web_app_installer_unittest.cc
+++ b/chrome/browser/chromeos/apps/apk_web_app_installer_unittest.cc
@@ -24,7 +24,7 @@
 arc::mojom::WebAppInfoPtr GetWebAppInfo() {
   return arc::mojom::WebAppInfo::New("Fake App Title",
                                      "https://www.google.com/index.html",
-                                     "https://www.google.com/", 10000);
+                                     "https://www.google.com/", 0xFFAABBCC);
 }
 
 constexpr int kGeneratedIconSize = 128;
@@ -118,8 +118,8 @@
             apk_web_app_installer.web_app_info().app_url);
   EXPECT_EQ(GURL("https://www.google.com/"),
             apk_web_app_installer.web_app_info().scope);
-  EXPECT_EQ(10000,
-            static_cast<int32_t>(
+  EXPECT_EQ(0xFFAABBCC,
+            static_cast<uint32_t>(
                 apk_web_app_installer.web_app_info().theme_color.value()));
 
   EXPECT_EQ(1u, apk_web_app_installer.web_app_info().icon_bitmaps_any.size());
diff --git a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
index f777782..22f3f75 100644
--- a/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
+++ b/chrome/browser/chromeos/extensions/autotest_private/autotest_private_api.cc
@@ -1751,7 +1751,7 @@
 AutotestPrivateGetClipboardTextDataFunction::Run() {
   base::string16 data;
   ui::Clipboard::GetForCurrentThread()->ReadText(
-      ui::ClipboardBuffer::kCopyPaste, &data);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &data);
   return RespondNow(
       OneArgument(base::Value::ToUniquePtrValue(base::Value(data))));
 }
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 5a26787..ace11ad9 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service.cc
@@ -152,7 +152,7 @@
     return;
 
   DictionaryPrefUpdate update(local_state, prefs::kEasyUnlockHardlockState);
-  update->RemoveWithoutPathExpansion(account_id.GetUserEmail(), NULL);
+  update->RemoveKey(account_id.GetUserEmail());
 
   EasyUnlockTpmKeyManager::ResetLocalStateForUser(account_id);
 }
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.cc
index 23878c9..add0d63 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.cc
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_regular.cc
@@ -265,7 +265,7 @@
   DictionaryPrefUpdate pairing_update(profile()->GetPrefs(),
                                       prefs::kEasyUnlockPairing);
   if (devices.empty())
-    pairing_update->RemoveWithoutPathExpansion(kKeyDevices, NULL);
+    pairing_update->RemoveKey(kKeyDevices);
   else
     pairing_update->SetKey(kKeyDevices, devices.Clone());
 
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.cc
index de83010..a079012 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.cc
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_service_signin_chromeos.cc
@@ -385,10 +385,6 @@
   if (account_id_ == account_id)
     return;
 
-  // Setting or clearing the account_id may changed |IsAllowed| value, so in
-  // these cases update the app state. Otherwise, it's enough to notify the app
-  // the user data has been updated.
-  const bool should_update_app_state = (account_id_ != account_id);
   account_id_ = account_id;
   pref_manager_->SetActiveUser(account_id);
   user_pod_last_focused_timestamp_ = base::TimeTicks::Now();
@@ -410,10 +406,7 @@
     return;
   }
 
-  if (should_update_app_state) {
-    UpdateAppState();
-  }
-
+  UpdateAppState();
   LoadCurrentUserDataIfNeeded();
 
   // Start loading TPM system token.
diff --git a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.cc b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.cc
index 8df2a8a..a13189a 100644
--- a/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.cc
+++ b/chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.cc
@@ -199,7 +199,7 @@
     return;
 
   DictionaryPrefUpdate update(local_state, prefs::kEasyUnlockLocalStateTpmKeys);
-  update->RemoveWithoutPathExpansion(account_id.GetUserEmail(), NULL);
+  update->RemoveKey(account_id.GetUserEmail());
 }
 
 EasyUnlockTpmKeyManager::EasyUnlockTpmKeyManager(
diff --git a/chrome/browser/chromeos/login/login_screen_extensions_lifetime_manager_browsertest.cc b/chrome/browser/chromeos/login/login_screen_extensions_lifetime_manager_browsertest.cc
new file mode 100644
index 0000000..ee4f5a7e59
--- /dev/null
+++ b/chrome/browser/chromeos/login/login_screen_extensions_lifetime_manager_browsertest.cc
@@ -0,0 +1,167 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/chromeos/login/login_screen_extensions_lifetime_manager.h"
+
+#include <string>
+
+#include "base/command_line.h"
+#include "base/path_service.h"
+#include "chrome/browser/chromeos/login/lock/screen_locker_tester.h"
+#include "chrome/browser/chromeos/login/test/device_state_mixin.h"
+#include "chrome/browser/chromeos/login/test/login_manager_mixin.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/policy/extension_force_install_mixin.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/test/base/mixin_based_in_process_browser_test.h"
+#include "chromeos/constants/chromeos_switches.h"
+#include "components/account_id/account_id.h"
+#include "components/user_manager/user.h"
+#include "components/user_manager/user_manager.h"
+#include "content/public/test/browser_test.h"
+#include "extensions/test/test_background_page_ready_observer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace chromeos {
+
+namespace {
+
+constexpr char kAllowlistedAppId[] = "bjaiihebfngildkcjkjckolinodhliff";
+constexpr char kAllowlistedAppCrxPath[] =
+    "extensions/signin_screen_manual_test_app/app_signed_by_webstore.crx";
+
+Profile* GetInitialProfile() {
+  return chromeos::ProfileHelper::GetSigninProfile()->GetOriginalProfile();
+}
+
+}  // namespace
+
+class LoginScreenExtensionsLifetimeManagerTest
+    : public MixinBasedInProcessBrowserTest {
+ protected:
+  LoginScreenExtensionsLifetimeManagerTest() {
+    // Don't shut down when no browser is open, since it breaks the test and
+    // since it's not the real Chrome OS behavior.
+    set_exit_when_last_browser_closes(false);
+  }
+
+  LoginScreenExtensionsLifetimeManagerTest(
+      const LoginScreenExtensionsLifetimeManagerTest&) = delete;
+  LoginScreenExtensionsLifetimeManagerTest& operator=(
+      const LoginScreenExtensionsLifetimeManagerTest&) = delete;
+  ~LoginScreenExtensionsLifetimeManagerTest() override = default;
+
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    // Skip showing post-login screens, as advancing through them isn't faked in
+    // the test.
+    command_line->AppendSwitch(switches::kOobeSkipPostLogin);
+
+    MixinBasedInProcessBrowserTest::SetUpCommandLine(command_line);
+  }
+
+  void SetUpOnMainThread() override {
+    MixinBasedInProcessBrowserTest::SetUpOnMainThread();
+    extension_force_install_mixin_.InitWithDeviceStateMixin(
+        GetInitialProfile(), &device_state_mixin_);
+  }
+
+  void LogIn() {
+    login_manager_mixin_.LoginAsNewRegularUser();
+    login_manager_mixin_.WaitForActiveSession();
+  }
+
+  void LockSession() { ScreenLockerTester().Lock(); }
+
+  void UnlockSession() {
+    const std::string kPassword = "pass";
+    const AccountId account_id =
+        user_manager::UserManager::Get()->GetPrimaryUser()->GetAccountId();
+    ScreenLockerTester screen_locker_tester;
+    screen_locker_tester.SetUnlockPassword(account_id, kPassword);
+    screen_locker_tester.UnlockWithPassword(account_id, kPassword);
+    screen_locker_tester.WaitForUnlock();
+  }
+
+  ExtensionForceInstallMixin* extension_force_install_mixin() {
+    return &extension_force_install_mixin_;
+  }
+
+  bool IsExtensionInstalled(const std::string& extension_id) const {
+    return extension_force_install_mixin_.GetInstalledExtension(extension_id) !=
+           nullptr;
+  }
+
+  bool IsExtensionEnabled(const std::string& extension_id) const {
+    return extension_force_install_mixin_.GetEnabledExtension(extension_id) !=
+           nullptr;
+  }
+
+  bool IsExtensionBackgroundPageReady(const std::string& extension_id) const {
+    return extension_force_install_mixin_.IsExtensionBackgroundPageReady(
+        extension_id);
+  }
+
+ private:
+  DeviceStateMixin device_state_mixin_{
+      &mixin_host_, DeviceStateMixin::State::OOBE_COMPLETED_CLOUD_ENROLLED};
+  LoginManagerMixin login_manager_mixin_{&mixin_host_};
+  ExtensionForceInstallMixin extension_force_install_mixin_{&mixin_host_};
+};
+
+// Tests that an extension force-installed on the login/lock screen gets
+// disabled during an active user session.
+IN_PROC_BROWSER_TEST_F(LoginScreenExtensionsLifetimeManagerTest, Basic) {
+  // Force-install the app while on the login screen. The app gets loaded.
+  EXPECT_TRUE(extension_force_install_mixin()->ForceInstallFromCrx(
+      base::PathService::CheckedGet(chrome::DIR_TEST_DATA)
+          .AppendASCII(kAllowlistedAppCrxPath),
+      ExtensionForceInstallMixin::WaitMode::kBackgroundPageReady));
+  ASSERT_TRUE(IsExtensionEnabled(kAllowlistedAppId));
+  EXPECT_TRUE(IsExtensionBackgroundPageReady(kAllowlistedAppId));
+
+  // The user logs in. The app gets disabled, although still installed.
+  LogIn();
+  EXPECT_TRUE(IsExtensionInstalled(kAllowlistedAppId));
+  EXPECT_FALSE(IsExtensionEnabled(kAllowlistedAppId));
+
+  // The user locks the session. The app gets enabled and the background page
+  // is loaded again.
+  extensions::ExtensionBackgroundPageReadyObserver page_observer(
+      GetInitialProfile(), kAllowlistedAppId);
+  LockSession();
+  page_observer.Wait();
+  ASSERT_TRUE(IsExtensionEnabled(kAllowlistedAppId));
+
+  // The user unlocks the session. The app gets disabled again.
+  UnlockSession();
+  EXPECT_TRUE(IsExtensionInstalled(kAllowlistedAppId));
+  EXPECT_FALSE(IsExtensionEnabled(kAllowlistedAppId));
+}
+
+// Tests that an extension force-installed into the login/lock screen when
+// they're not active doesn't get launched.
+IN_PROC_BROWSER_TEST_F(LoginScreenExtensionsLifetimeManagerTest,
+                       InstalledDuringSession) {
+  // Force-install the app during an active user session. The app gets
+  // installed, but is immediately disabled.
+  LogIn();
+  EXPECT_TRUE(extension_force_install_mixin()->ForceInstallFromCrx(
+      base::PathService::CheckedGet(chrome::DIR_TEST_DATA)
+          .AppendASCII(kAllowlistedAppCrxPath),
+      ExtensionForceInstallMixin::WaitMode::kLoad));
+  EXPECT_TRUE(IsExtensionInstalled(kAllowlistedAppId));
+  EXPECT_FALSE(IsExtensionEnabled(kAllowlistedAppId));
+
+  // The user locks the session. The app gets enabled and the background page is
+  // loaded again.
+  extensions::ExtensionBackgroundPageReadyObserver page_observer(
+      GetInitialProfile(), kAllowlistedAppId);
+  LockSession();
+  page_observer.Wait();
+  ASSERT_TRUE(IsExtensionEnabled(kAllowlistedAppId));
+  EXPECT_TRUE(IsExtensionBackgroundPageReady(kAllowlistedAppId));
+}
+
+}  // namespace chromeos
diff --git a/chrome/browser/chromeos/policy/signin_profile_extensions_policy_browsertest.cc b/chrome/browser/chromeos/policy/signin_profile_extensions_policy_browsertest.cc
index dfe1b31..06730a4 100644
--- a/chrome/browser/chromeos/policy/signin_profile_extensions_policy_browsertest.cc
+++ b/chrome/browser/chromeos/policy/signin_profile_extensions_policy_browsertest.cc
@@ -37,7 +37,6 @@
 #include "extensions/common/extension_set.h"
 #include "extensions/common/features/feature_channel.h"
 #include "extensions/common/switches.h"
-#include "extensions/test/test_background_page_ready_observer.h"
 #include "net/http/http_status_code.h"
 #include "net/test/embedded_test_server/http_request.h"
 #include "net/test/embedded_test_server/http_response.h"
@@ -282,12 +281,11 @@
 IN_PROC_BROWSER_TEST_F(SigninProfileExtensionsPolicyTest, BackgroundPage) {
   EXPECT_FALSE(
       chromeos::ProfileHelper::SigninProfileHasLoginScreenExtensions());
-  extensions::ExtensionBackgroundPageReadyObserver page_observer(
-      GetInitialProfile(), kWhitelistedAppId);
   EXPECT_TRUE(extension_force_install_mixin_.ForceInstallFromCrx(
       GetTestDataDir().AppendASCII(kWhitelistedAppCrxPath),
-      ExtensionForceInstallMixin::WaitMode::kNone));
-  page_observer.Wait();
+      ExtensionForceInstallMixin::WaitMode::kBackgroundPageReady));
+  EXPECT_TRUE(extension_force_install_mixin_.IsExtensionBackgroundPageReady(
+      kWhitelistedAppId));
   EXPECT_TRUE(chromeos::ProfileHelper::SigninProfileHasLoginScreenExtensions());
 }
 
@@ -313,20 +311,12 @@
                        IsolatedStoragePartition) {
   Profile* profile = GetInitialProfile();
 
-  extensions::ExtensionBackgroundPageReadyObserver page_observer_for_app(
-      GetInitialProfile(), kWhitelistedAppId);
-  extensions::ExtensionBackgroundPageReadyObserver page_observer_for_extension(
-      GetInitialProfile(), kWhitelistedExtensionId);
-
   EXPECT_TRUE(extension_force_install_mixin_.ForceInstallFromCrx(
       GetTestDataDir().AppendASCII(kWhitelistedAppCrxPath),
-      ExtensionForceInstallMixin::WaitMode::kNone));
+      ExtensionForceInstallMixin::WaitMode::kBackgroundPageReady));
   EXPECT_TRUE(extension_force_install_mixin_.ForceInstallFromCrx(
       GetTestDataDir().AppendASCII(kWhitelistedExtensionCrxPath),
-      ExtensionForceInstallMixin::WaitMode::kNone));
-
-  page_observer_for_app.Wait();
-  page_observer_for_extension.Wait();
+      ExtensionForceInstallMixin::WaitMode::kBackgroundPageReady));
 
   content::StoragePartition* storage_partition_for_app =
       extensions::util::GetStoragePartitionForExtensionId(
diff --git a/chrome/browser/chromeos/web_applications/chrome_help_app_ui_delegate.cc b/chrome/browser/chromeos/web_applications/chrome_help_app_ui_delegate.cc
index 82a7176ed..2f3fa2d 100644
--- a/chrome/browser/chromeos/web_applications/chrome_help_app_ui_delegate.cc
+++ b/chrome/browser/chromeos/web_applications/chrome_help_app_ui_delegate.cc
@@ -27,6 +27,7 @@
 #include "components/prefs/pref_service.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/web_ui_data_source.h"
+#include "ui/chromeos/devicetype_utils.h"
 #include "ui/events/devices/device_data_manager.h"
 #include "url/gurl.h"
 
@@ -66,6 +67,7 @@
                                 &customization_id);
   provider->GetMachineStatistic(chromeos::system::kHardwareClassKey, &hwid);
   source->AddString("customizationId", customization_id);
+  source->AddString("deviceName", ui::GetChromeOSDeviceName());
   source->AddString("hwid", hwid);
 
   // Add any features that have been enabled.
diff --git a/chrome/browser/devtools/devtools_file_helper.cc b/chrome/browser/devtools/devtools_file_helper.cc
index 98ab93a..83856a0 100644
--- a/chrome/browser/devtools/devtools_file_helper.cc
+++ b/chrome/browser/devtools/devtools_file_helper.cc
@@ -413,7 +413,7 @@
   DictionaryPrefUpdate update(profile_->GetPrefs(),
                               prefs::kDevToolsFileSystemPaths);
   base::DictionaryValue* file_systems_paths_value = update.Get();
-  file_systems_paths_value->RemoveWithoutPathExpansion(file_system_path, NULL);
+  file_systems_paths_value->RemoveKey(file_system_path);
 }
 
 bool DevToolsFileHelper::IsFileSystemAdded(
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc
index 1283cace..773a02ce 100644
--- a/chrome/browser/devtools/devtools_ui_bindings.cc
+++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -1192,7 +1192,7 @@
 void DevToolsUIBindings::RemovePreference(const std::string& name) {
   DictionaryPrefUpdate update(profile_->GetPrefs(),
                               prefs::kDevToolsPreferences);
-  update.Get()->RemoveWithoutPathExpansion(name, nullptr);
+  update.Get()->RemoveKey(name);
 }
 
 void DevToolsUIBindings::ClearPreferences() {
diff --git a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc
index 3bf353a..9422096 100644
--- a/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc
+++ b/chrome/browser/extensions/api/passwords_private/passwords_private_delegate_impl_unittest.cc
@@ -393,7 +393,8 @@
       nullptr);
 
   base::string16 result;
-  test_clipboard_->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
+  test_clipboard_->ReadText(ui::ClipboardBuffer::kCopyPaste,
+                            /* data_dst = */ nullptr, &result);
   EXPECT_EQ(form.password_value, result);
 
   histogram_tester().ExpectUniqueSample(
@@ -465,7 +466,8 @@
       nullptr);
   // Clipboard should not be modifiend in case Reauth failed
   base::string16 result;
-  test_clipboard_->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
+  test_clipboard_->ReadText(ui::ClipboardBuffer::kCopyPaste,
+                            /* data_dst = */ nullptr, &result);
   EXPECT_EQ(base::string16(), result);
   EXPECT_EQ(before_call, test_clipboard_->GetLastModifiedTime());
 
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index df415df..bdb9fe2 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -457,6 +457,11 @@
     "expiry_milestone": 87
   },
   {
+    "name": "chrome-share-highlights-android",
+    "owners": [ "gayane" ],
+    "expiry_milestone": 88
+  },
+  {
     "name": "chrome-share-qr-code",
     "owners": [ "kmilka", "tgupta" ],
     "expiry_milestone": 86
@@ -1310,6 +1315,11 @@
     "expiry_milestone": 90
   },
   {
+    "name": "enable-cros-language-settings-update",
+    "owners": [ "essential-inputs-team@google.com" ],
+    "expiry_milestone": 90
+  },
+  {
     "name": "enable-cros-virtual-keyboard-bordered-key",
     "owners": [ "essential-inputs-team@google.com" ],
     "expiry_milestone": 90
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 8ff7912..26f606f8 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -2509,6 +2509,11 @@
 const char kChromeDuetLabelsDescription[] =
     "Enables Chrome Duet (split toolbar) labels.";
 
+const char kChromeShareHighlightsAndroidName[] =
+    "Chrome Share text highlights on Android";
+const char kChromeShareHighlightsAndroidDescription[] =
+    "Enables UI to generate and share link to text highlights on Android";
+
 const char kChromeShareQRCodeName[] = "Chrome Share QRCodes";
 const char kChromeShareQRCodeDescription[] =
     "Enables UI to generate and scan QR Codes on Android";
@@ -3430,6 +3435,10 @@
     "Enables contextual nudges, periodically showing the user a label "
     "explaining how to interact with a particular UI element using gestures.";
 
+const char kCrosLanguageSettingsUpdateName[] = "Language Settings Update";
+const char kCrosLanguageSettingsUpdateDescription[] =
+    "Enable this flag to see the new language settings update.";
+
 const char kCrosRegionsModeName[] = "Cros-regions load mode";
 const char kCrosRegionsModeDescription[] =
     "This flag controls cros-regions load mode";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 4009af84..b12f41c 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1456,6 +1456,9 @@
 extern const char kShareButtonInTopToolbarName[];
 extern const char kShareButtonInTopToolbarDescription[];
 
+extern const char kChromeShareHighlightsAndroidName[];
+extern const char kChromeShareHighlightsAndroidDescription[];
+
 extern const char kChromeShareQRCodeName[];
 extern const char kChromeShareQRCodeDescription[];
 
@@ -1980,6 +1983,9 @@
 extern const char kContextualNudgesName[];
 extern const char kContextualNudgesDescription[];
 
+extern const char kCrosLanguageSettingsUpdateName[];
+extern const char kCrosLanguageSettingsUpdateDescription[];
+
 extern const char kCrosRegionsModeName[];
 extern const char kCrosRegionsModeDescription[];
 extern const char kCrosRegionsModeDefault[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index d2ba908..1f07cd2 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -125,6 +125,7 @@
     &kDarkenWebsitesCheckboxInThemesSetting,
     &kDontAutoHideBrowserControls,
     &kChromeDuetLabeled,
+    &kChromeShareHighlightsAndroid,
     &kChromeShareQRCode,
     &kChromeShareScreenshot,
     &kChromeSharingHub,
@@ -247,9 +248,11 @@
     &password_manager::features::kRecoverFromNeverSaveAndroid,
     &performance_hints::features::kContextMenuPerformanceInfo,
     &performance_hints::features::kPageInfoPerformanceHints,
+    &query_tiles::features::kQueryTilesGeoFilter,
     &query_tiles::features::kQueryTiles,
     &query_tiles::features::kQueryTilesInOmnibox,
     &query_tiles::features::kQueryTilesEnableQueryEditing,
+    &safe_browsing::kEnhancedProtection,
     &safe_browsing::kSafeBrowsingSecuritySectionUIAndroid,
     &security_state::features::kMarkHttpAsFeature,
     &signin::kMobileIdentityConsistency,
@@ -354,6 +357,9 @@
 const base::Feature kChromeDuetLabeled{"ChromeDuetLabeled",
                                        base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kChromeShareHighlightsAndroid{
+    "ChromeShareHighlightsAndroid", base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kChromeShareQRCode{"ChromeShareQRCode",
                                        base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h
index ddc4820..e93aa0a 100644
--- a/chrome/browser/flags/android/chrome_feature_list.h
+++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -37,6 +37,7 @@
 extern const base::Feature kChromeDuetAdaptive;
 extern const base::Feature kDontAutoHideBrowserControls;
 extern const base::Feature kChromeDuetLabeled;
+extern const base::Feature kChromeShareHighlightsAndroid;
 extern const base::Feature kChromeShareQRCode;
 extern const base::Feature kChromeShareScreenshot;
 extern const base::Feature kChromeSharingHub;
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
index 90e3768..8bb8d59 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -237,6 +237,7 @@
     public static final String CHROME_DUET_ADAPTIVE = "ChromeDuetAdaptive";
     public static final String DONT_AUTO_HIDE_BROWSER_CONTROLS = "DontAutoHideBrowserControls";
     public static final String CHROME_DUET_LABELED = "ChromeDuetLabeled";
+    public static final String CHROME_SHARE_HIGHLIGHTS_ANDROID = "ChromeShareHighlightsAndroid";
     public static final String CHROME_SHARE_QRCODE = "ChromeShareQRCode";
     public static final String CHROME_SHARE_SCREENSHOT = "ChromeShareScreenshot";
     public static final String CHROME_SHARING_HUB = "ChromeSharingHub";
@@ -363,6 +364,7 @@
     public static final String PRIORITIZE_BOOTSTRAP_TASKS = "PrioritizeBootstrapTasks";
     public static final String PRIVACY_ELEVATED_ANDROID = "PrivacyElevatedAndroid";
     public static final String PROBABILISTIC_CRYPTID_RENDERER = "ProbabilisticCryptidRenderer";
+    public static final String QUERY_TILES_GEO_FILTER = "QueryTilesGeoFilter";
     public static final String QUERY_TILES = "QueryTiles";
     public static final String QUERY_TILES_IN_OMNIBOX = "QueryTilesInOmnibox";
     public static final String QUERY_TILES_ENABLE_QUERY_EDITING = "QueryTilesEnableQueryEditing";
@@ -375,6 +377,8 @@
     public static final String REPORT_FEED_USER_ACTIONS = "ReportFeedUserActions";
     public static final String REVAMPED_CONTEXT_MENU = "RevampedContextMenu";
     public static final String SAFETY_CHECK_ANDROID = "SafetyCheckAndroid";
+    public static final String SAFE_BROWSING_ENHANCED_PROTECTION_ENABLED =
+            "SafeBrowsingEnhancedProtection";
     public static final String SAFE_BROWSING_SECURITY_SECTION_UI =
             "SafeBrowsingSecuritySectionUIAndroid";
     public static final String SAME_SITE_BY_DEFAULT_COOKIES = "SameSiteByDefaultCookies";
diff --git a/chrome/browser/installable/installable_manager_unittest.cc b/chrome/browser/installable/installable_manager_unittest.cc
index f142699..6f40789b 100644
--- a/chrome/browser/installable/installable_manager_unittest.cc
+++ b/chrome/browser/installable/installable_manager_unittest.cc
@@ -227,7 +227,7 @@
   EXPECT_EQ(NO_ERROR_DETECTED, GetErrorCode());
 
   // The icon MUST have IconPurpose::ANY or IconPurpose::Maskable.
-  manifest.icons[0].purpose[0] = IconPurpose::BADGE;
+  manifest.icons[0].purpose[0] = IconPurpose::MONOCHROME;
   EXPECT_FALSE(IsManifestValid(manifest, true, true));
   EXPECT_EQ(MANIFEST_MISSING_SUITABLE_ICON, GetErrorCode());
 
diff --git a/chrome/browser/media/kaleidoscope/kaleidoscope_internal_resources.grd b/chrome/browser/media/kaleidoscope/kaleidoscope_internal_resources.grd
index 184f5e7..acdb5656 100644
--- a/chrome/browser/media/kaleidoscope/kaleidoscope_internal_resources.grd
+++ b/chrome/browser/media/kaleidoscope/kaleidoscope_internal_resources.grd
@@ -15,21 +15,21 @@
         use_base_dir="false" type="BINDATA" />
 
       <!-- Private resources -->
-      <include name="IDR_KALEIDOSCOPE_CONTENT_CSS" file="internal/resources/content.css" type="chrome_html" flattenhtml="true" compress="gzip" />
-      <include name="IDR_KALEIDOSCOPE_CONTENT_HTML" file="internal/resources/content.html" type="BINDATA" compress="gzip" />
-      <include name="IDR_KALEIDOSCOPE_CONTENT_JS" file="${root_gen_dir}/chrome/browser/media/kaleidoscope/internal/resources/ks-content.js" use_base_dir="false" type="BINDATA" compress="gzip" />
-      <include name="IDR_KALEIDOSCOPE_HTML" file="internal/resources/kaleidoscope.html" type="BINDATA" compress="gzip" />
-      <include name="IDR_KALEIDOSCOPE_JS" file="internal/resources/kaleidoscope.js" type="BINDATA" compress="gzip" />
-      <include name="IDR_KALEIDOSCOPE_MESSAGES_JS" file="internal/resources/messages.js" type="BINDATA" compress="gzip" />
-      <include name="IDR_KALEIDOSCOPE_UTILS_JS" file="internal/resources/utils.js" type="BINDATA" compress="gzip" />
-      <include name="IDR_GEOMETRY_MOJOM_LITE_JS" file="${root_gen_dir}/ui/gfx/geometry/mojom/geometry.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
-      <include name="IDR_KALEIDOSCOPE_MOJOM_LITE_JS" file="${root_gen_dir}/chrome/browser/media/kaleidoscope/mojom/kaleidoscope.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+      <include name="IDR_KALEIDOSCOPE_CONTENT_CSS" file="internal/resources/content.css" type="chrome_html" flattenhtml="true" />
+      <include name="IDR_KALEIDOSCOPE_CONTENT_HTML" file="internal/resources/content.html" type="BINDATA" />
+      <include name="IDR_KALEIDOSCOPE_CONTENT_JS" file="${root_gen_dir}/chrome/browser/media/kaleidoscope/internal/resources/ks-content.js" use_base_dir="false" type="BINDATA" />
+      <include name="IDR_KALEIDOSCOPE_HTML" file="internal/resources/kaleidoscope.html" type="BINDATA" />
+      <include name="IDR_KALEIDOSCOPE_JS" file="internal/resources/kaleidoscope.js" type="BINDATA" />
+      <include name="IDR_KALEIDOSCOPE_MESSAGES_JS" file="internal/resources/messages.js" type="BINDATA" />
+      <include name="IDR_KALEIDOSCOPE_UTILS_JS" file="internal/resources/utils.js" type="BINDATA" />
+      <include name="IDR_GEOMETRY_MOJOM_LITE_JS" file="${root_gen_dir}/ui/gfx/geometry/mojom/geometry.mojom-lite.js" use_base_dir="false" type="BINDATA" />
+      <include name="IDR_KALEIDOSCOPE_MOJOM_LITE_JS" file="${root_gen_dir}/chrome/browser/media/kaleidoscope/mojom/kaleidoscope.mojom-lite.js" use_base_dir="false" type="BINDATA" />
 
       <!-- Strings -->
       <include name="IDR_KALEIDOSCOPE_LOCALE_EN" file="${root_gen_dir}/chrome/browser/media/kaleidoscope/internal/resources/_locales/en/messages.json" use_base_dir="false" type="BINDATA" compress="gzip" />
 
       <!-- Google Sans -->
-      <include name="IDR_GOOGLE_SANS_CSS" file="internal/resources/fonts/fonts.css" type="BINDATA" compress="gzip" />
+      <include name="IDR_GOOGLE_SANS_CSS" file="internal/resources/fonts/fonts.css" type="BINDATA" />
       <include name="IDR_GOOGLE_SANS_BOLD" file="internal/resources/fonts/GoogleSans-Bold.woff2" type="BINDATA" compress="gzip" />
       <include name="IDR_GOOGLE_SANS_MEDIUM" file="internal/resources/fonts/GoogleSans-Medium.woff2" type="BINDATA" compress="gzip" />
       <include name="IDR_GOOGLE_SANS_REGULAR" file="internal/resources/fonts/GoogleSans-Regular.woff2" type="BINDATA" compress="gzip" />
diff --git a/chrome/browser/password_manager/chrome_password_manager_client.cc b/chrome/browser/password_manager/chrome_password_manager_client.cc
index fcbf0e04..80c2030 100644
--- a/chrome/browser/password_manager/chrome_password_manager_client.cc
+++ b/chrome/browser/password_manager/chrome_password_manager_client.cc
@@ -1204,7 +1204,8 @@
 void ChromePasswordManagerClient::OnPaste() {
   ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
   base::string16 text;
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &text);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &text);
   was_on_paste_called_ = true;
   password_reuse_detection_manager_.OnPaste(std::move(text));
 }
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index db2c7c2..7e7a4af 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -1959,14 +1959,16 @@
     const std::string& last_data = last_clipboard_data_[clipboard_buffer];
     if (last_data.size() == expected.size()) {
       DCHECK_EQ(last_data, expected);
-      clipboard->ReadAsciiText(clipboard_buffer, &clipboard_data);
+      clipboard->ReadAsciiText(clipboard_buffer, /* data_dst = */ nullptr,
+                               &clipboard_data);
       EXPECT_EQ(expected, clipboard_data);
       return;
     }
 
     const bool expect_increase = last_data.size() < expected.size();
     while (true) {
-      clipboard->ReadAsciiText(clipboard_buffer, &clipboard_data);
+      clipboard->ReadAsciiText(clipboard_buffer, /* data_dst = */ nullptr,
+                               &clipboard_data);
       if (expect_increase) {
         if (clipboard_data.size() >= expected.size())
           break;
diff --git a/chrome/browser/plugins/plugin_power_saver_browsertest.cc b/chrome/browser/plugins/plugin_power_saver_browsertest.cc
index 48539f68..c9b1ac8b 100644
--- a/chrome/browser/plugins/plugin_power_saver_browsertest.cc
+++ b/chrome/browser/plugins/plugin_power_saver_browsertest.cc
@@ -341,6 +341,13 @@
     PluginPowerSaverBrowserTest::SetUp();
   }
 
+  void SetUpCommandLine(base::CommandLine* command_line) override {
+    // The pixel tests run more reliably in software mode.
+    command_line->AppendSwitch(switches::kDisableGpu);
+
+    PluginPowerSaverBrowserTest::SetUpCommandLine(command_line);
+  }
+
  protected:
   void LoadHTML(const std::string& file) override {
     gfx::Rect bounds(gfx::Rect(0, 0, kBrowserWidth, kBrowserHeight));
@@ -356,8 +363,10 @@
 
 // This test fail on macOS 10.12. https://crbug.com/599484.
 // Flaky on Windows, Asan, and Msan. See crbug.com/549285 and crbug.com/512140.
+// Because ChromeOS cannot use software rendering and the pixel tests continue
+// to flake with hardware acceleration, disable these on ChromeOS.
 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(ADDRESS_SANITIZER) || \
-    defined(MEMORY_SANITIZER)
+    defined(MEMORY_SANITIZER) || defined(OS_CHROMEOS)
 #define MAYBE_SmallCrossOrigin DISABLED_SmallCrossOrigin
 #else
 #define MAYBE_SmallCrossOrigin SmallCrossOrigin
@@ -379,7 +388,10 @@
 }
 
 // Flaky on Windows, Asan, and Msan. See crbug.com/549285 and crbug.com/512140.
-#if defined(OS_WIN) || defined(ADDRESS_SANITIZER) || defined(MEMORY_SANITIZER)
+// Because ChromeOS cannot use software rendering and the pixel tests continue
+// to flake with hardware acceleration, disable these on ChromeOS.
+#if defined(OS_WIN) || defined(ADDRESS_SANITIZER) || \
+    defined(MEMORY_SANITIZER) || defined(OS_CHROMEOS)
 #define MAYBE_SmallerThanPlayIcon DISABLED_SmallerThanPlayIcon
 #else
 #define MAYBE_SmallerThanPlayIcon SmallerThanPlayIcon
@@ -401,8 +413,10 @@
 
 // This test fail on macOS 10.12. https://crbug.com/599484.
 // Flaky on Windows, Asan, and Msan. See crbug.com/549285 and crbug.com/512140.
+// Because ChromeOS cannot use software rendering and the pixel tests continue
+// to flake with hardware acceleration, disable these on ChromeOS.
 #if defined(OS_MACOSX) || defined(OS_WIN) || defined(ADDRESS_SANITIZER) || \
-    defined(MEMORY_SANITIZER)
+    defined(MEMORY_SANITIZER) || defined(OS_CHROMEOS)
 #define MAYBE_PosterTests DISABLED_PosterTests
 #else
 #define MAYBE_PosterTests PosterTests
diff --git a/chrome/browser/policy/extension_force_install_mixin.cc b/chrome/browser/policy/extension_force_install_mixin.cc
index fa264f6..e0160fd0 100644
--- a/chrome/browser/policy/extension_force_install_mixin.cc
+++ b/chrome/browser/policy/extension_force_install_mixin.cc
@@ -27,15 +27,21 @@
 #include "components/crx_file/id_util.h"
 #include "extensions/browser/extension_creator.h"
 #include "extensions/browser/extension_registry.h"
+#include "extensions/browser/extension_system.h"
+#include "extensions/browser/runtime_data.h"
 #include "extensions/browser/test_extension_registry_observer.h"
+#include "extensions/common/extension.h"
+#include "extensions/common/extension_id.h"
 #include "extensions/common/file_util.h"
 #include "extensions/common/manifest_constants.h"
+#include "extensions/test/test_background_page_ready_observer.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/zlib/google/zip.h"
 #include "url/gurl.h"
 
 #if defined(OS_CHROMEOS)
+#include "chrome/browser/chromeos/login/test/device_state_mixin.h"
 #include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
 #include "components/policy/proto/chrome_device_policy.pb.h"
 #endif
@@ -68,13 +74,21 @@
   ForceInstallWaiter& operator=(const ForceInstallWaiter&) = delete;
   ~ForceInstallWaiter();
 
+  // Waits until the event specified |wait_mode| gets satisfied. Returns false
+  // if the waiting timed out.
   bool Wait();
 
  private:
+  // Implementation of Wait(). Returns the result via |success| in order to be
+  // able to use ASSERT* macros inside.
+  void WaitImpl(bool* success);
+
   const ExtensionForceInstallMixin::WaitMode wait_mode_;
   const extensions::ExtensionId extension_id_;
   Profile* const profile_;
   std::unique_ptr<extensions::TestExtensionRegistryObserver> registry_observer_;
+  std::unique_ptr<extensions::ExtensionBackgroundPageReadyObserver>
+      background_page_ready_observer_;
 };
 
 ForceInstallWaiter::ForceInstallWaiter(
@@ -92,18 +106,36 @@
           std::make_unique<extensions::TestExtensionRegistryObserver>(
               extensions::ExtensionRegistry::Get(profile_), extension_id);
       break;
+    case ExtensionForceInstallMixin::WaitMode::kBackgroundPageReady:
+      background_page_ready_observer_ =
+          std::make_unique<extensions::ExtensionBackgroundPageReadyObserver>(
+              profile_, extension_id);
+      break;
   }
 }
 
 ForceInstallWaiter::~ForceInstallWaiter() = default;
 
 bool ForceInstallWaiter::Wait() {
+  bool success = false;
+  WaitImpl(&success);
+  return success;
+}
+
+void ForceInstallWaiter::WaitImpl(bool* success) {
   switch (wait_mode_) {
     case ExtensionForceInstallMixin::WaitMode::kNone:
       // No waiting needed.
-      return true;
+      *success = true;
+      break;
     case ExtensionForceInstallMixin::WaitMode::kLoad:
-      return registry_observer_->WaitForExtensionLoaded() != nullptr;
+      *success = registry_observer_->WaitForExtensionLoaded() != nullptr;
+      break;
+    case ExtensionForceInstallMixin::WaitMode::kBackgroundPageReady: {
+      ASSERT_NO_FATAL_FAILURE(background_page_ready_observer_->Wait());
+      *success = true;
+      break;
+    }
   }
 }
 
@@ -201,6 +233,17 @@
                             update_manifest_url.spec().c_str());
 }
 
+void UpdatePolicyViaDeviceStateMixin(
+    const extensions::ExtensionId& extension_id,
+    const GURL& update_manifest_url,
+    chromeos::DeviceStateMixin* device_state_mixin) {
+  device_state_mixin->RequestDevicePolicyUpdate()
+      ->policy_payload()
+      ->mutable_device_login_screen_extensions()
+      ->add_device_login_screen_extensions(
+          MakeForceInstallPolicyItemValue(extension_id, update_manifest_url));
+}
+
 void UpdatePolicyViaDevicePolicyCrosTestHelper(
     const extensions::ExtensionId& extension_id,
     const GURL& update_manifest_url,
@@ -225,6 +268,17 @@
 
 #if defined(OS_CHROMEOS)
 
+void ExtensionForceInstallMixin::InitWithDeviceStateMixin(
+    Profile* profile,
+    chromeos::DeviceStateMixin* device_state_mixin) {
+  DCHECK(profile);
+  DCHECK(device_state_mixin);
+  DCHECK(!profile_) << "Init already called";
+  DCHECK(!device_state_mixin_);
+  profile_ = profile;
+  device_state_mixin_ = device_state_mixin;
+}
+
 void ExtensionForceInstallMixin::InitWithDevicePolicyCrosTestHelper(
     Profile* profile,
     policy::DevicePolicyCrosTestHelper* device_policy_cros_test_helper) {
@@ -297,15 +351,33 @@
   return registry->enabled_extensions().GetByID(extension_id);
 }
 
+bool ExtensionForceInstallMixin::IsExtensionBackgroundPageReady(
+    const extensions::ExtensionId& extension_id) const {
+  DCHECK(crx_file::id_util::IdIsValid(extension_id));
+  DCHECK(profile_) << "Init not called";
+
+  const auto* const extension = GetInstalledExtension(extension_id);
+  if (!extension) {
+    ADD_FAILURE() << "Extension " << extension_id << " not installed";
+    return false;
+  }
+  auto* const extension_system = extensions::ExtensionSystem::Get(profile_);
+  DCHECK(extension_system);
+  return extension_system->runtime_data()->IsBackgroundPageReady(extension);
+}
+
 void ExtensionForceInstallMixin::SetUpOnMainThread() {
   ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-  ASSERT_TRUE(base::CreateDirectory(GetServedDirPath()));
-  embedded_test_server_.ServeFilesFromDirectory(GetServedDirPath());
+  const base::FilePath served_dir_path =
+      temp_dir_.GetPath().AppendASCII(kServedDirName);
+  ASSERT_TRUE(base::CreateDirectory(served_dir_path));
+  embedded_test_server_.ServeFilesFromDirectory(served_dir_path);
   ASSERT_TRUE(embedded_test_server_.Start());
 }
 
-base::FilePath ExtensionForceInstallMixin::GetServedDirPath() const {
-  return temp_dir_.GetPath().AppendASCII(kServedDirName);
+base::FilePath ExtensionForceInstallMixin::GetPathInServedDir(
+    const std::string& file_name) const {
+  return temp_dir_.GetPath().AppendASCII(kServedDirName).AppendASCII(file_name);
 }
 
 GURL ExtensionForceInstallMixin::GetServedUpdateManifestUrl(
@@ -331,8 +403,8 @@
     const base::Version& extension_version) {
   DCHECK(embedded_test_server_.Started()) << "Called before setup";
 
-  const base::FilePath served_crx_path = GetServedDirPath().AppendASCII(
-      GetServedCrxFileName(extension_id, extension_version));
+  const base::FilePath served_crx_path =
+      GetPathInServedDir(GetServedCrxFileName(extension_id, extension_version));
   base::ScopedAllowBlockingForTesting scoped_allow_blocking;
   if (!base::CopyFile(source_crx_path, served_crx_path)) {
     ADD_FAILURE() << "Failed to copy CRX from " << source_crx_path.value()
@@ -368,7 +440,7 @@
 
   if (!ParseCrxOuterData(temp_crx_path, extension_id))
     return false;
-  const base::FilePath served_crx_path = GetServedDirPath().AppendASCII(
+  const base::FilePath served_crx_path = GetPathInServedDir(
       GetServedCrxFileName(*extension_id, extension_version));
   if (!base::Move(temp_crx_path, served_crx_path)) {
     ADD_FAILURE() << "Failed to move the created CRX file to "
@@ -404,8 +476,8 @@
   const GURL crx_url = GetServedCrxUrl(extension_id, extension_version);
   const std::string update_manifest =
       GenerateUpdateManifest(extension_id, extension_version, crx_url);
-  const base::FilePath update_manifest_path = GetServedDirPath().AppendASCII(
-      GetServedUpdateManifestFileName(extension_id));
+  const base::FilePath update_manifest_path =
+      GetPathInServedDir(GetServedUpdateManifestFileName(extension_id));
   // Note: Doing an atomic write, since the embedded test server might
   // concurrently try to access this file from another thread.
   base::ScopedAllowBlockingForTesting scoped_allow_blocking;
@@ -423,6 +495,11 @@
   DCHECK(profile_) << "Init not called";
 
 #if defined(OS_CHROMEOS)
+  if (device_state_mixin_) {
+    UpdatePolicyViaDeviceStateMixin(extension_id, update_manifest_url,
+                                    device_state_mixin_);
+    return true;
+  }
   if (device_policy_cros_test_helper_) {
     UpdatePolicyViaDevicePolicyCrosTestHelper(extension_id, update_manifest_url,
                                               device_policy_cros_test_helper_);
diff --git a/chrome/browser/policy/extension_force_install_mixin.h b/chrome/browser/policy/extension_force_install_mixin.h
index b3b41981..bd29b381 100644
--- a/chrome/browser/policy/extension_force_install_mixin.h
+++ b/chrome/browser/policy/extension_force_install_mixin.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_POLICY_EXTENSION_FORCE_INSTALL_MIXIN_H_
 #define CHROME_BROWSER_POLICY_EXTENSION_FORCE_INSTALL_MIXIN_H_
 
+#include <string>
+
 #include "base/files/file_path.h"
 #include "base/files/scoped_temp_dir.h"
 #include "base/optional.h"
@@ -25,6 +27,10 @@
 
 #if defined(OS_CHROMEOS)
 
+namespace chromeos {
+class DeviceStateMixin;
+}  // namespace chromeos
+
 namespace policy {
 class DevicePolicyCrosTestHelper;
 }  // namespace policy
@@ -48,13 +54,19 @@
 //       ...
 //       force_install_mixin_.InitWithDevicePolicyCrosTestHelper(...);
 //     }
-//     void ForceInstall() {
-//       EXPECT_TRUE(force_install_mixin_.ForceInstallFromCrx(...));
-//     }
 //     ExtensionForceInstallMixin force_install_mixin_{&mixin_host_};
 //   };
+//   IN_PROC_BROWSER_TEST_F(...) {
+//     EXPECT_TRUE(force_install_mixin_.ForceInstallFromCrx(...));
+//   }
 //
-// TODO(crbug.com/1090941): Add user policy, waiting for bg page, auto update.
+// Internally, the mixin owns an embedded test server that hosts files needed
+// for the forced installation:
+// * "/<extension_id>.xml" - update manifests referred to by policies,
+// * "/<extension_id>-<version>.crx" - CRX packages referred to by the update
+//   manifests.
+//
+// TODO(crbug.com/1090941): Add user policy, auto update.
 class ExtensionForceInstallMixin final : public InProcessBrowserTestMixin {
  public:
   // The type of the waiting mode for the force installation operation.
@@ -63,6 +75,8 @@
     kNone,
     // Wait until the extension is loaded.
     kLoad,
+    // Wait until the extension's background page is ready.
+    kBackgroundPageReady,
   };
 
   explicit ExtensionForceInstallMixin(InProcessBrowserTestMixinHost* host);
@@ -75,6 +89,8 @@
   // other method:
 
 #if defined(OS_CHROMEOS)
+  void InitWithDeviceStateMixin(Profile* profile,
+                                chromeos::DeviceStateMixin* device_state_mixin);
   void InitWithDevicePolicyCrosTestHelper(
       Profile* profile,
       policy::DevicePolicyCrosTestHelper* device_policy_cros_test_helper);
@@ -93,10 +109,11 @@
   // |pem_path| - if non-empty, will be used to load the private key for packing
   // the extension; when empty, a random key will be generated. |extension_id| -
   // if non-null, will be set to the installed extension ID.
-  bool ForceInstallFromSourceDir(const base::FilePath& extension_dir_path,
-                                 const base::Optional<base::FilePath>& pem_path,
-                                 WaitMode wait_mode,
-                                 std::string* extension_id = nullptr);
+  bool ForceInstallFromSourceDir(
+      const base::FilePath& extension_dir_path,
+      const base::Optional<base::FilePath>& pem_path,
+      WaitMode wait_mode,
+      extensions::ExtensionId* extension_id = nullptr);
 
   // Returns the extension, or null if it's not installed yet.
   const extensions::Extension* GetInstalledExtension(
@@ -104,14 +121,17 @@
   // Returns the extension, or null if it's not installed or not enabled yet.
   const extensions::Extension* GetEnabledExtension(
       const extensions::ExtensionId& extension_id) const;
+  // Returns whether the installed extension's background page is ready.
+  bool IsExtensionBackgroundPageReady(
+      const extensions::ExtensionId& extension_id) const;
 
   // InProcessBrowserTestMixin:
   void SetUpOnMainThread() override;
 
  private:
-  // Returns the directory whose contents are served by the embedded test
-  // server.
-  base::FilePath GetServedDirPath() const;
+  // Returns the path to the file that is served by the embedded test server
+  // under the given name.
+  base::FilePath GetPathInServedDir(const std::string& file_name) const;
   // Returns the URL of the update manifest pointing to the embedded test
   // server.
   GURL GetServedUpdateManifestUrl(
@@ -129,7 +149,7 @@
   bool CreateAndServeCrx(const base::FilePath& extension_dir_path,
                          const base::Optional<base::FilePath>& pem_path,
                          const base::Version& extension_version,
-                         std::string* extension_id);
+                         extensions::ExtensionId* extension_id);
   // Force-installs the CRX file served by the embedded test server.
   bool ForceInstallFromServedCrx(const extensions::ExtensionId& extension_id,
                                  const base::Version& extension_version,
@@ -148,6 +168,7 @@
   net::EmbeddedTestServer embedded_test_server_;
   Profile* profile_ = nullptr;
 #if defined(OS_CHROMEOS)
+  chromeos::DeviceStateMixin* device_state_mixin_ = nullptr;
   policy::DevicePolicyCrosTestHelper* device_policy_cros_test_helper_ = nullptr;
 #endif
 };
diff --git a/chrome/browser/predictors/OWNERS b/chrome/browser/predictors/OWNERS
index ce24f0e..79e9d4d 100644
--- a/chrome/browser/predictors/OWNERS
+++ b/chrome/browser/predictors/OWNERS
@@ -1,6 +1,8 @@
 alexilin@chromium.org
+falken@chromium.org
 lizeb@chromium.org
 pasko@chromium.org
+sophiechang@chromium.org
 tbansal@chromium.org
 
 # COMPONENT: Internals>Preload
diff --git a/chrome/browser/predictors/loading_predictor_browsertest.cc b/chrome/browser/predictors/loading_predictor_browsertest.cc
index a517d0ad..ad68683 100644
--- a/chrome/browser/predictors/loading_predictor_browsertest.cc
+++ b/chrome/browser/predictors/loading_predictor_browsertest.cc
@@ -1502,7 +1502,7 @@
 }
 
 class LoadingPredictorBrowserTestWithOptimizationGuide
-    : public ::testing::WithParamInterface<std::tuple<bool, bool>>,
+    : public ::testing::WithParamInterface<std::tuple<bool, bool, std::string>>,
       public LoadingPredictorBrowserTest {
  public:
   LoadingPredictorBrowserTestWithOptimizationGuide() {
@@ -1528,16 +1528,33 @@
     return std::get<1>(GetParam());
   }
 
+  std::string GetSubresourceTypeParam() const {
+    return std::string(std::get<2>(GetParam()));
+  }
+
+  // A predicted subresource.
+  struct Subresource {
+    explicit Subresource(std::string url)
+        : url(url), type(optimization_guide::proto::RESOURCE_TYPE_UNKNOWN) {}
+    Subresource(std::string url, optimization_guide::proto::ResourceType type)
+        : url(url), type(type) {}
+
+    std::string url;
+    optimization_guide::proto::ResourceType type;
+  };
+
   void SetUpOptimizationHint(
       const GURL& url,
-      const std::vector<std::string>& predicted_subresource_urls) {
+      const std::vector<Subresource>& predicted_subresources) {
     auto* optimization_guide_keyed_service =
         OptimizationGuideKeyedServiceFactory::GetForProfile(
             browser()->profile());
     optimization_guide::proto::LoadingPredictorMetadata
         loading_predictor_metadata;
-    for (const auto& subresource_url : predicted_subresource_urls) {
-      loading_predictor_metadata.add_subresources()->set_url(subresource_url);
+    for (const auto& subresource : predicted_subresources) {
+      auto* added = loading_predictor_metadata.add_subresources();
+      added->set_url(subresource.url);
+      added->set_resource_type(subresource.type);
     }
 
     optimization_guide::OptimizationMetadata optimization_metadata;
@@ -1555,7 +1572,9 @@
 
 INSTANTIATE_TEST_SUITE_P(,
                          LoadingPredictorBrowserTestWithOptimizationGuide,
-                         testing::Combine(testing::Bool(), testing::Bool()));
+                         testing::Combine(testing::Bool(),
+                                          testing::Bool(),
+                                          testing::Values("")));
 
 IN_PROC_BROWSER_TEST_P(LoadingPredictorBrowserTestWithOptimizationGuide,
                        NavigationHasLocalPredictionNoOptimizationHint) {
@@ -1609,9 +1628,10 @@
   ui_test_utils::NavigateToURL(browser(), url);
   ResetNetworkState();
 
-  SetUpOptimizationHint(
-      url, {"http://subresource.com/1", "http://subresource.com/2",
-            "http://otherresource.com/2", "skipsoverinvalidurl/////"});
+  SetUpOptimizationHint(url, {Subresource("http://subresource.com/1"),
+                              Subresource("http://subresource.com/2"),
+                              Subresource("http://otherresource.com/2"),
+                              Subresource("skipsoverinvalidurl/////")});
 
   auto observer = NavigateToURLAsync(url);
   EXPECT_TRUE(observer->WaitForRequestStart());
@@ -1657,9 +1677,10 @@
   base::HistogramTester histogram_tester;
 
   GURL url = embedded_test_server()->GetURL("m.hints.com", "/simple.html");
-  SetUpOptimizationHint(
-      url, {"http://subresource.com/1", "http://subresource.com/2",
-            "http://otherresource.com/2", "skipsoverinvalidurl/////"});
+  SetUpOptimizationHint(url, {Subresource("http://subresource.com/1"),
+                              Subresource("http://subresource.com/2"),
+                              Subresource("http://otherresource.com/2"),
+                              Subresource("skipsoverinvalidurl/////")});
   url::Origin origin = url::Origin::Create(url);
   net::NetworkIsolationKey network_isolation_key(origin, origin);
 
@@ -1718,9 +1739,10 @@
   auto observer = NavigateToURLAsync(url);
   EXPECT_TRUE(observer->WaitForResponse());
   observer->ResumeNavigation();
-  SetUpOptimizationHint(
-      url, {"http://subresource.com/1", "http://subresource.com/2",
-            "http://otherresource.com/2", "skipsoverinvalidurl/////"});
+  SetUpOptimizationHint(url, {Subresource("http://subresource.com/1"),
+                              Subresource("http://subresource.com/2"),
+                              Subresource("http://otherresource.com/2"),
+                              Subresource("skipsoverinvalidurl/////")});
 
   EXPECT_FALSE(preconnect_manager_observer()->HasHostBeenLookedUp(
       "subresource.com", network_isolation_key));
@@ -1734,10 +1756,11 @@
       embedded_test_server()->GetURL("otherhost.com", "/cachetime");
   GURL redirecting_url = embedded_test_server()->GetURL(
       "sometimesredirects.com", "/cached-redirect?" + destination_url.spec());
-  SetUpOptimizationHint(
-      destination_url,
-      {"http://subresource.com/1", "http://subresource.com/2",
-       "http://otherresource.com/2", "skipsoverinvalidurl/////"});
+  SetUpOptimizationHint(destination_url,
+                        {Subresource("http://subresource.com/1"),
+                         Subresource("http://subresource.com/2"),
+                         Subresource("http://otherresource.com/2"),
+                         Subresource("skipsoverinvalidurl/////")});
 
   // Navigate the first time to something on redirecting origin to fill the
   // predictor's database and the HTTP cache.
@@ -1755,10 +1778,11 @@
   // applied.
   auto observer = NavigateToURLAsync(redirecting_url);
   EXPECT_TRUE(observer->WaitForResponse());
-  SetUpOptimizationHint(
-      redirecting_url,
-      {"http://subresourceredirect.com/1", "http://subresourceredirect.com/2",
-       "http://otherresourceredirect.com/2", "skipsoverinvalidurl/////"});
+  SetUpOptimizationHint(redirecting_url,
+                        {Subresource("http://subresourceredirect.com/1"),
+                         Subresource("http://subresourceredirect.com/2"),
+                         Subresource("http://otherresourceredirect.com/2"),
+                         Subresource("skipsoverinvalidurl/////")});
   observer->ResumeNavigation();
 
   std::vector<std::string> expected_opt_guide_subresource_hosts = {
@@ -1838,7 +1862,9 @@
     : public LoadingPredictorBrowserTestWithOptimizationGuide {
  public:
   LoadingPredictorPrefetchBrowserTest() {
-    feature_list_.InitAndEnableFeature(features::kLoadingPredictorPrefetch);
+    feature_list_.InitAndEnableFeatureWithParameters(
+        features::kLoadingPredictorPrefetch,
+        {{"subresource_type", GetSubresourceTypeParam()}});
   }
 
   void SetUp() override {
@@ -1905,18 +1931,29 @@
                                              embedded_test_server()->port()));
 
   // Set up optimization hints.
-  std::vector<std::string> hints(
+  std::vector<Subresource> hints = {
       {"skipsoverinvalidurl/////",
-       embedded_test_server()->GetURL("subresource.com", "/1").spec(),
-       embedded_test_server()->GetURL("subresource.com", "/2").spec(),
-       embedded_test_server()->GetURL("otherresource.com", "/2").spec()});
+       optimization_guide::proto::RESOURCE_TYPE_CSS},
+      {embedded_test_server()->GetURL("subresource.com", "/css").spec(),
+       optimization_guide::proto::RESOURCE_TYPE_CSS},
+      {embedded_test_server()->GetURL("subresource.com", "/image").spec(),
+       optimization_guide::proto::RESOURCE_TYPE_UNKNOWN},
+      {embedded_test_server()->GetURL("otherresource.com", "/js").spec(),
+       optimization_guide::proto::RESOURCE_TYPE_SCRIPT}};
   SetUpOptimizationHint(url, hints);
 
   // Expect these prefetches.
-  std::vector<GURL> requests(
-      {embedded_test_server()->GetURL("subresource.com", "/1"),
-       embedded_test_server()->GetURL("subresource.com", "/2"),
-       embedded_test_server()->GetURL("otherresource.com", "/2")});
+  std::vector<GURL> requests;
+  if (GetSubresourceTypeParam() == "all") {
+    requests = {embedded_test_server()->GetURL("subresource.com", "/css"),
+                embedded_test_server()->GetURL("subresource.com", "/image"),
+                embedded_test_server()->GetURL("otherresource.com", "/js")};
+  } else if (GetSubresourceTypeParam() == "css") {
+    requests = {embedded_test_server()->GetURL("subresource.com", "/css")};
+  } else if (GetSubresourceTypeParam() == "js_css") {
+    requests = {embedded_test_server()->GetURL("subresource.com", "/css"),
+                embedded_test_server()->GetURL("otherresource.com", "/js")};
+  }
   SetExpectedRequests(std::move(requests));
 
   // Start a navigation and observe these prefetches.
@@ -1930,7 +1967,8 @@
     LoadingPredictorPrefetchBrowserTest,
     testing::Combine(
         /*IsLocalPredictionEnabled()=*/testing::Values(false),
-        /*ShouldPreconnectUsingOptimizationGuidePredictions=*/
-        testing::Values(true)));
+        /*ShouldPreconnectUsingOptimizationGuidePredictions()=*/
+        testing::Values(true),
+        /*GetSubresourceType()=*/testing::Values("all", "css", "js_css")));
 
 }  // namespace predictors
diff --git a/chrome/browser/predictors/loading_predictor_tab_helper.cc b/chrome/browser/predictors/loading_predictor_tab_helper.cc
index ee961d83..ea07832 100644
--- a/chrome/browser/predictors/loading_predictor_tab_helper.cc
+++ b/chrome/browser/predictors/loading_predictor_tab_helper.cc
@@ -84,6 +84,20 @@
   }
 }
 
+bool ShouldPrefetchDestination(network::mojom::RequestDestination destination) {
+  switch (features::kLoadingPredictorPrefetchSubresourceType.Get()) {
+    case features::PrefetchSubresourceType::kAll:
+      return true;
+    case features::PrefetchSubresourceType::kCss:
+      return destination == network::mojom::RequestDestination::kStyle;
+    case features::PrefetchSubresourceType::kJsAndCss:
+      return destination == network::mojom::RequestDestination::kScript ||
+             destination == network::mojom::RequestDestination::kStyle;
+  }
+  NOTREACHED();
+  return false;
+}
+
 // Util class for recording the status for when we received optimization hints
 // for navigations that we requested them for.
 class ScopedOptimizationHintsReceiveStatusRecorder {
@@ -358,10 +372,13 @@
       continue;
     predicted_subresources.push_back(subresource_url);
     if (base::FeatureList::IsEnabled(features::kLoadingPredictorPrefetch)) {
-      // TODO(falken): Detect duplicates.
-      prediction.prefetch_requests.emplace_back(
-          subresource_url, network_isolation_key,
-          GetDestination(subresource.resource_type()));
+      network::mojom::RequestDestination destination =
+          GetDestination(subresource.resource_type());
+      if (ShouldPrefetchDestination(destination)) {
+        // TODO(falken): Detect duplicates.
+        prediction.prefetch_requests.emplace_back(
+            subresource_url, network_isolation_key, destination);
+      }
     } else {
       url::Origin subresource_origin = url::Origin::Create(subresource_url);
       if (subresource_origin == main_frame_origin) {
diff --git a/chrome/browser/predictors/predictors_features.cc b/chrome/browser/predictors/predictors_features.cc
index 4526e5aa..f88b41c 100644
--- a/chrome/browser/predictors/predictors_features.cc
+++ b/chrome/browser/predictors/predictors_features.cc
@@ -42,6 +42,17 @@
 const base::Feature kLoadingPredictorPrefetch{
     "LoadingPredictorPrefetch", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::FeatureParam<PrefetchSubresourceType>::Option
+    kPrefetchSubresourceTypeParamOptions[] = {
+        {PrefetchSubresourceType::kAll, "all"},
+        {PrefetchSubresourceType::kCss, "css"},
+        {PrefetchSubresourceType::kJsAndCss, "js_css"}};
+
+const base::FeatureParam<PrefetchSubresourceType>
+    kLoadingPredictorPrefetchSubresourceType{
+        &kLoadingPredictorPrefetch, "subresource_type",
+        PrefetchSubresourceType::kAll, &kPrefetchSubresourceTypeParamOptions};
+
 bool ShouldUseLocalPredictions() {
   return base::FeatureList::IsEnabled(kLoadingPredictorUseLocalPredictions);
 }
diff --git a/chrome/browser/predictors/predictors_features.h b/chrome/browser/predictors/predictors_features.h
index e86b631..bca6c01 100644
--- a/chrome/browser/predictors/predictors_features.h
+++ b/chrome/browser/predictors/predictors_features.h
@@ -26,6 +26,11 @@
 
 extern const base::Feature kLoadingPredictorPrefetch;
 
+enum class PrefetchSubresourceType { kAll, kCss, kJsAndCss };
+
+extern const base::FeatureParam<PrefetchSubresourceType>
+    kLoadingPredictorPrefetchSubresourceType;
+
 // Returns whether local predictions should be used to make preconnect
 // predictions.
 bool ShouldUseLocalPredictions();
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
index 51927be..b190c5b7 100644
--- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -2602,7 +2602,7 @@
 
   std::vector<base::string16> types;
   ui::Clipboard::GetForCurrentThread()->ReadAvailableTypes(
-      ui::ClipboardBuffer::kCopyPaste, &types);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &types);
   return !types.empty();
 }
 
@@ -2612,7 +2612,7 @@
 
   return ui::Clipboard::GetForCurrentThread()->IsFormatAvailable(
       ui::ClipboardFormatType::GetPlainTextType(),
-      ui::ClipboardBuffer::kCopyPaste);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr);
 }
 
 bool RenderViewContextMenu::IsPrintPreviewEnabled() const {
diff --git a/chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.cc b/chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.cc
index 6ae4b9b..3415a498 100644
--- a/chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.cc
+++ b/chrome/browser/renderer_host/pepper/pepper_flash_clipboard_message_filter.cc
@@ -161,20 +161,24 @@
   switch (format) {
     case PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT: {
       available = clipboard->IsFormatAvailable(
-          ui::ClipboardFormatType::GetPlainTextType(), clipboard_buffer);
+          ui::ClipboardFormatType::GetPlainTextType(), clipboard_buffer,
+          /* data_dst = */ nullptr);
 #if defined(OS_WIN)
       available |= clipboard->IsFormatAvailable(
-          ui::ClipboardFormatType::GetPlainTextAType(), clipboard_buffer);
+          ui::ClipboardFormatType::GetPlainTextAType(), clipboard_buffer,
+          /* data_dst = */ nullptr);
 #endif
       break;
     }
     case PP_FLASH_CLIPBOARD_FORMAT_HTML:
       available = clipboard->IsFormatAvailable(
-          ui::ClipboardFormatType::GetHtmlType(), clipboard_buffer);
+          ui::ClipboardFormatType::GetHtmlType(), clipboard_buffer,
+          /* data_dst = */ nullptr);
       break;
     case PP_FLASH_CLIPBOARD_FORMAT_RTF:
       available = clipboard->IsFormatAvailable(
-          ui::ClipboardFormatType::GetRtfType(), clipboard_buffer);
+          ui::ClipboardFormatType::GetRtfType(), clipboard_buffer,
+          /* data_dst = */ nullptr);
       break;
     case PP_FLASH_CLIPBOARD_FORMAT_INVALID:
       break;
@@ -183,7 +187,7 @@
         std::string format_name = custom_formats_.GetFormatName(format);
         std::string clipboard_data;
         clipboard->ReadData(ui::ClipboardFormatType::GetPepperCustomDataType(),
-                            &clipboard_data);
+                            /* data_dst = */ nullptr, &clipboard_data);
         base::Pickle pickle(clipboard_data.data(), clipboard_data.size());
         available =
             IsFormatAvailableInPickle(base::UTF8ToUTF16(format_name), pickle);
@@ -210,9 +214,10 @@
   switch (format) {
     case PP_FLASH_CLIPBOARD_FORMAT_PLAINTEXT: {
       if (clipboard->IsFormatAvailable(
-              ui::ClipboardFormatType::GetPlainTextType(), clipboard_buffer)) {
+              ui::ClipboardFormatType::GetPlainTextType(), clipboard_buffer,
+              /* data_dst = */ nullptr)) {
         base::string16 text;
-        clipboard->ReadText(clipboard_buffer, &text);
+        clipboard->ReadText(clipboard_buffer, /* data_dst = */ nullptr, &text);
         if (!text.empty()) {
           result = PP_OK;
           clipboard_string = base::UTF16ToUTF8(text);
@@ -223,16 +228,19 @@
       // If the PlainText format isn't available or is empty, take the
       // ASCII text format.
       if (clipboard->IsFormatAvailable(
-              ui::ClipboardFormatType::GetPlainTextAType(), clipboard_buffer)) {
+              ui::ClipboardFormatType::GetPlainTextAType(), clipboard_buffer,
+              /* data_dst = */ nullptr)) {
         result = PP_OK;
-        clipboard->ReadAsciiText(clipboard_buffer, &clipboard_string);
+        clipboard->ReadAsciiText(clipboard_buffer, /* data_dst = */ nullptr,
+                                 &clipboard_string);
       }
 #endif
       break;
     }
     case PP_FLASH_CLIPBOARD_FORMAT_HTML: {
       if (!clipboard->IsFormatAvailable(ui::ClipboardFormatType::GetHtmlType(),
-                                        clipboard_buffer)) {
+                                        clipboard_buffer,
+                                        /* data_dst = */ nullptr)) {
         break;
       }
 
@@ -240,8 +248,8 @@
       std::string url;
       uint32_t fragment_start;
       uint32_t fragment_end;
-      clipboard->ReadHTML(clipboard_buffer, &html, &url, &fragment_start,
-                          &fragment_end);
+      clipboard->ReadHTML(clipboard_buffer, /* data_dst = */ nullptr, &html,
+                          &url, &fragment_start, &fragment_end);
       result = PP_OK;
       clipboard_string = base::UTF16ToUTF8(
           html.substr(fragment_start, fragment_end - fragment_start));
@@ -249,11 +257,13 @@
     }
     case PP_FLASH_CLIPBOARD_FORMAT_RTF: {
       if (!clipboard->IsFormatAvailable(ui::ClipboardFormatType::GetRtfType(),
-                                        clipboard_buffer)) {
+                                        clipboard_buffer,
+                                        /* data_dst = */ nullptr)) {
         break;
       }
       result = PP_OK;
-      clipboard->ReadRTF(clipboard_buffer, &clipboard_string);
+      clipboard->ReadRTF(clipboard_buffer, /* data_dst = */ nullptr,
+                         &clipboard_string);
       break;
     }
     case PP_FLASH_CLIPBOARD_FORMAT_INVALID:
@@ -264,7 +274,7 @@
             base::UTF8ToUTF16(custom_formats_.GetFormatName(format));
         std::string clipboard_data;
         clipboard->ReadData(ui::ClipboardFormatType::GetPepperCustomDataType(),
-                            &clipboard_data);
+                            /* data_dst = */ nullptr, &clipboard_data);
         base::Pickle pickle(clipboard_data.data(), clipboard_data.size());
         if (IsFormatAvailableInPickle(format_name, pickle)) {
           result = PP_OK;
diff --git a/chrome/browser/safe_browsing/android/BUILD.gn b/chrome/browser/safe_browsing/android/BUILD.gn
index a4853627..7db45b4 100644
--- a/chrome/browser/safe_browsing/android/BUILD.gn
+++ b/chrome/browser/safe_browsing/android/BUILD.gn
@@ -21,25 +21,49 @@
 android_library("java") {
   sources = [
     "java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingBridge.java",
+    "java/src/org/chromium/chrome/browser/safe_browsing/settings/RadioButtonGroupSafeBrowsingPreference.java",
     "java/src/org/chromium/chrome/browser/safe_browsing/settings/SecuritySettingsFragment.java",
   ]
   deps = [
     ":java_resources",
     "//base:base_java",
     "//base:jni_java",
+    "//chrome/browser/flags:java",
     "//components/browser_ui/settings/android:java",
+    "//components/browser_ui/widget/android:java",
     "//third_party/android_deps:androidx_fragment_fragment_java",
     "//third_party/android_deps:androidx_preference_preference_java",
     "//ui/android:ui_full_java",
   ]
   annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
+  srcjar_deps = [ ":safe_browsing_enums" ]
+}
+
+android_library("javatests") {
+  testonly = true
+  sources = [ "javatests/src/org/chromium/chrome/browser/safe_browsing/settings/SecuritySettingsFragmentTest.java" ]
+  deps = [
+    ":java",
+    "//chrome/browser/settings:test_support_java",
+    "//chrome/test/android:chrome_java_test_support",
+    "//components/browser_ui/widget/android:java",
+    "//content/public/test/android:content_java_test_support",
+    "//third_party/junit",
+  ]
 }
 
 android_resources("java_resources") {
-  sources = [ "java/res/xml/security_preferences.xml" ]
+  sources = [
+    "java/res/layout/radio_button_group_safe_browsing_preference.xml",
+    "java/res/xml/security_preferences.xml",
+  ]
   deps = [
     "//chrome/browser/ui/android/strings:ui_strings_grd",
     "//components/browser_ui/settings/android:java_resources",
   ]
   custom_package = "org.chromium.chrome.browser.safe_browsing.settings"
 }
+
+java_cpp_enum("safe_browsing_enums") {
+  sources = [ "//components/safe_browsing/core/common/safe_browsing_prefs.h" ]
+}
diff --git a/chrome/browser/safe_browsing/android/java/res/layout/radio_button_group_safe_browsing_preference.xml b/chrome/browser/safe_browsing/android/java/res/layout/radio_button_group_safe_browsing_preference.xml
new file mode 100644
index 0000000..1c92522
--- /dev/null
+++ b/chrome/browser/safe_browsing/android/java/res/layout/radio_button_group_safe_browsing_preference.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2020 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+
+<org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:focusable="false">
+
+    <org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionAndAuxButton
+        android:id="@+id/enhanced_protection"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:visibility="gone"
+        app:primaryText="@string/safe_browsing_enhanced_protection_title"
+        app:descriptionText="@string/safe_browsing_enhanced_protection_summary" />
+
+    <org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionAndAuxButton
+        android:id="@+id/standard_protection"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        app:primaryText="@string/safe_browsing_standard_protection_title"
+        app:descriptionText="@string/safe_browsing_standard_protection_summary" />
+
+    <!--  Add paddingEnd to make it align with the other radio buttons.  -->
+    <org.chromium.components.browser_ui.widget.RadioButtonWithDescription
+        android:id="@+id/no_protection"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingEnd="@dimen/radio_button_with_description_and_aux_button_aux_button_length"
+        app:primaryText="@string/safe_browsing_no_protection_title"
+        app:descriptionText="@string/safe_browsing_no_protection_summary" />
+
+</org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionLayout>
diff --git a/chrome/browser/safe_browsing/android/java/res/xml/security_preferences.xml b/chrome/browser/safe_browsing/android/java/res/xml/security_preferences.xml
index b7422ef..6220780 100644
--- a/chrome/browser/safe_browsing/android/java/res/xml/security_preferences.xml
+++ b/chrome/browser/safe_browsing/android/java/res/xml/security_preferences.xml
@@ -4,10 +4,17 @@
      found in the LICENSE file. -->
 
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orderingFromXml="false">
+    xmlns:app="http://schemas.android.com/apk/res-auto">
 
     <PreferenceCategory
         android:key="safe_browsing_section"
         android:title="@string/prefs_section_safe_browsing_title"/>
-<!-- TODO(crbug.com/1097310): Add Safe Browsing Radio Button Group -->
+
+<!--  TODO(crbug.com/1097310): Add managed text view for Safe Browsing preference.  -->
+
+    <org.chromium.chrome.browser.safe_browsing.settings.RadioButtonGroupSafeBrowsingPreference
+        android:key="safe_browsing_radio_button_group"
+        android:selectable="false"
+        app:allowDividerAbove="false"
+        app:allowDividerBelow="false" />
 </PreferenceScreen>
diff --git a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingBridge.java b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingBridge.java
index 37d43ea..a2010b1a 100644
--- a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingBridge.java
+++ b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingBridge.java
@@ -43,11 +43,30 @@
         return SafeBrowsingBridgeJni.get().getSafeBrowsingExtendedReportingManaged();
     }
 
+    /**
+     * @return The Safe Browsing state. It can be Enhanced Protection, Standard Protection, or No
+     *         Protection.
+     */
+    public static @SafeBrowsingState int getSafeBrowsingState() {
+        return SafeBrowsingBridgeJni.get().getSafeBrowsingState();
+    }
+
+    /**
+     * @param state Set the Safe Browsing state. It can be Enhanced Protection, Standard Protection,
+     *         or No Protection.
+     */
+    public static void setSafeBrowsingState(@SafeBrowsingState int state) {
+        SafeBrowsingBridgeJni.get().setSafeBrowsingState(state);
+    }
+
     @NativeMethods
     interface Natives {
         int umaValueForFile(String path);
         boolean getSafeBrowsingExtendedReportingEnabled();
         void setSafeBrowsingExtendedReportingEnabled(boolean enabled);
         boolean getSafeBrowsingExtendedReportingManaged();
+        @SafeBrowsingState
+        int getSafeBrowsingState();
+        void setSafeBrowsingState(@SafeBrowsingState int state);
     }
 }
diff --git a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/RadioButtonGroupSafeBrowsingPreference.java b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/RadioButtonGroupSafeBrowsingPreference.java
new file mode 100644
index 0000000..2f27c585
--- /dev/null
+++ b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/RadioButtonGroupSafeBrowsingPreference.java
@@ -0,0 +1,113 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.safe_browsing.settings;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.RadioGroup;
+
+import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
+import org.chromium.chrome.browser.safe_browsing.SafeBrowsingState;
+import org.chromium.components.browser_ui.widget.RadioButtonWithDescription;
+import org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionAndAuxButton;
+import org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionLayout;
+
+/**
+ * A radio button group used for Safe Browsing. Currently, it has 3 options: Enhanced Protection,
+ * Standard Protection and No Protection. When the Enhanced Protection flag is disabled, the
+ * Enhanced Protection option will be removed.
+ */
+public class RadioButtonGroupSafeBrowsingPreference
+        extends Preference implements RadioGroup.OnCheckedChangeListener {
+    private @Nullable RadioButtonWithDescriptionAndAuxButton mEnhancedProtection;
+    private RadioButtonWithDescriptionAndAuxButton mStandardProtection;
+    private RadioButtonWithDescription mNoProtection;
+    private @SafeBrowsingState int mSafeBrowsingState;
+    private boolean mIsEnhancedProtectionEnabled;
+
+    public RadioButtonGroupSafeBrowsingPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        setLayoutResource(R.layout.radio_button_group_safe_browsing_preference);
+    }
+
+    /**
+     * Set Safe Browsing state and Enhanced Protection state. Called before onBindViewHolder.
+     * @param safeBrowsingState The current Safe Browsing state.
+     * @param isEnhancedProtectionEnabled Whether to show the Enhanced Protection button.
+     */
+    public void init(
+            @SafeBrowsingState int safeBrowsingState, boolean isEnhancedProtectionEnabled) {
+        mSafeBrowsingState = safeBrowsingState;
+        mIsEnhancedProtectionEnabled = isEnhancedProtectionEnabled;
+        assert ((mSafeBrowsingState != SafeBrowsingState.ENHANCED_PROTECTION)
+                || mIsEnhancedProtectionEnabled)
+            : "Safe Browsing state shouldn't be enhanced protection when the flag is disabled.";
+    }
+
+    @Override
+    public void onCheckedChanged(RadioGroup group, int checkedId) {
+        if (mIsEnhancedProtectionEnabled && checkedId == mEnhancedProtection.getId()) {
+            mSafeBrowsingState = SafeBrowsingState.ENHANCED_PROTECTION;
+        } else if (checkedId == mStandardProtection.getId()) {
+            mSafeBrowsingState = SafeBrowsingState.STANDARD_PROTECTION;
+        } else if (checkedId == mNoProtection.getId()) {
+            mSafeBrowsingState = SafeBrowsingState.NO_SAFE_BROWSING;
+        } else {
+            assert false : "Should not be reached.";
+        }
+        callChangeListener(mSafeBrowsingState);
+    }
+
+    @Override
+    public void onBindViewHolder(PreferenceViewHolder holder) {
+        super.onBindViewHolder(holder);
+        if (mIsEnhancedProtectionEnabled) {
+            mEnhancedProtection = (RadioButtonWithDescriptionAndAuxButton) holder.findViewById(
+                    R.id.enhanced_protection);
+            mEnhancedProtection.setVisibility(View.VISIBLE);
+        }
+        mStandardProtection = (RadioButtonWithDescriptionAndAuxButton) holder.findViewById(
+                R.id.standard_protection);
+        mNoProtection = (RadioButtonWithDescription) holder.findViewById(R.id.no_protection);
+        RadioButtonWithDescriptionLayout groupLayout =
+                (RadioButtonWithDescriptionLayout) mNoProtection.getRootView();
+        groupLayout.setOnCheckedChangeListener(this);
+
+        assert ((mSafeBrowsingState != SafeBrowsingState.ENHANCED_PROTECTION)
+                || mIsEnhancedProtectionEnabled)
+            : "Safe Browsing state shouldn't be enhanced protection when the flag is disabled.";
+        if (mIsEnhancedProtectionEnabled) {
+            mEnhancedProtection.setChecked(
+                    mSafeBrowsingState == SafeBrowsingState.ENHANCED_PROTECTION);
+        }
+        mStandardProtection.setChecked(mSafeBrowsingState == SafeBrowsingState.STANDARD_PROTECTION);
+        mNoProtection.setChecked(mSafeBrowsingState == SafeBrowsingState.NO_SAFE_BROWSING);
+    }
+
+    @VisibleForTesting
+    public @SafeBrowsingState int getSafeBrowsingStateForTesting() {
+        return mSafeBrowsingState;
+    }
+
+    @VisibleForTesting
+    public RadioButtonWithDescriptionAndAuxButton getEnhancedProtectionButtonForTesting() {
+        return mEnhancedProtection;
+    }
+
+    @VisibleForTesting
+    public RadioButtonWithDescriptionAndAuxButton getStandardProtectionButtonForTesting() {
+        return mStandardProtection;
+    }
+
+    @VisibleForTesting
+    public RadioButtonWithDescription getNoProtectionButtonForTesting() {
+        return mNoProtection;
+    }
+}
diff --git a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/SecuritySettingsFragment.java b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/SecuritySettingsFragment.java
index b0731dd..34c6b08 100644
--- a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/SecuritySettingsFragment.java
+++ b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/SecuritySettingsFragment.java
@@ -6,17 +6,36 @@
 
 import android.os.Bundle;
 
+import androidx.annotation.VisibleForTesting;
 import androidx.preference.PreferenceFragmentCompat;
 
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.safe_browsing.SafeBrowsingBridge;
+import org.chromium.chrome.browser.safe_browsing.SafeBrowsingState;
 import org.chromium.components.browser_ui.settings.SettingsUtils;
 
 /**
  * Fragment containing security settings.
  */
 public class SecuritySettingsFragment extends PreferenceFragmentCompat {
+    @VisibleForTesting
+    public static final String PREF_SAFE_BROWSING = "safe_browsing_radio_button_group";
+
     @Override
     public void onCreatePreferences(Bundle bundle, String s) {
         SettingsUtils.addPreferencesFromResource(this, R.xml.security_preferences);
         getActivity().setTitle(R.string.prefs_security_title);
+
+        RadioButtonGroupSafeBrowsingPreference safeBrowsingPreference =
+                findPreference(PREF_SAFE_BROWSING);
+        safeBrowsingPreference.init(SafeBrowsingBridge.getSafeBrowsingState(),
+                ChromeFeatureList.isEnabled(
+                        ChromeFeatureList.SAFE_BROWSING_ENHANCED_PROTECTION_ENABLED));
+        safeBrowsingPreference.setOnPreferenceChangeListener((preference, newValue) -> {
+            @SafeBrowsingState
+            int newState = (int) newValue;
+            SafeBrowsingBridge.setSafeBrowsingState(newState);
+            return true;
+        });
     }
 }
diff --git a/chrome/browser/safe_browsing/android/javatests/src/org/chromium/chrome/browser/safe_browsing/settings/SecuritySettingsFragmentTest.java b/chrome/browser/safe_browsing/android/javatests/src/org/chromium/chrome/browser/safe_browsing/settings/SecuritySettingsFragmentTest.java
new file mode 100644
index 0000000..cd62cc2
--- /dev/null
+++ b/chrome/browser/safe_browsing/android/javatests/src/org/chromium/chrome/browser/safe_browsing/settings/SecuritySettingsFragmentTest.java
@@ -0,0 +1,156 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.safe_browsing.settings;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.BaseJUnit4ClassRunner;
+import org.chromium.base.test.util.Feature;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.safe_browsing.SafeBrowsingBridge;
+import org.chromium.chrome.browser.safe_browsing.SafeBrowsingState;
+import org.chromium.chrome.browser.settings.SettingsActivityTestRule;
+import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.components.browser_ui.widget.RadioButtonWithDescription;
+import org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionAndAuxButton;
+import org.chromium.content_public.browser.test.util.TestThreadUtils;
+
+/**
+ * Tests for {@link SecuritySettingsFragment}.
+ */
+@RunWith(BaseJUnit4ClassRunner.class)
+// clang-format off
+@Features.EnableFeatures({ChromeFeatureList.SAFE_BROWSING_SECURITY_SECTION_UI})
+public class SecuritySettingsFragmentTest {
+    // clang-format on
+    private static final String ASSERT_SAFE_BROWSING_STATE_RADIO_BUTTON_GROUP =
+            "Incorrect Safe Browsing state in the radio button group.";
+    private static final String ASSERT_RADIO_BUTTON_CHECKED =
+            "Incorrect radio button checked state.";
+    private static final String ASSERT_SAFE_BROWSING_STATE_NATIVE =
+            "Incorrect Safe Browsing state from native.";
+
+    @Rule
+    public SettingsActivityTestRule<SecuritySettingsFragment> mTestRule =
+            new SettingsActivityTestRule<>(SecuritySettingsFragment.class);
+
+    @Rule
+    public TestRule mFeatureProcessor = new Features.InstrumentationProcessor();
+
+    private RadioButtonGroupSafeBrowsingPreference mSafeBrowsingPreference;
+
+    @Before
+    public void setUp() {
+        launchSettingsActivity();
+    }
+
+    private void launchSettingsActivity() {
+        mTestRule.startSettingsActivity();
+        SecuritySettingsFragment fragment = mTestRule.getFragment();
+        mSafeBrowsingPreference =
+                fragment.findPreference(SecuritySettingsFragment.PREF_SAFE_BROWSING);
+        Assert.assertNotNull(
+                "Safe Browsing preference should not be null.", mSafeBrowsingPreference);
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"SafeBrowsing"})
+    @Features.EnableFeatures(ChromeFeatureList.SAFE_BROWSING_ENHANCED_PROTECTION_ENABLED)
+    public void testOnStartup() {
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            @SafeBrowsingState
+            int currentState = SafeBrowsingBridge.getSafeBrowsingState();
+            boolean enhanced_protection_checked =
+                    currentState == SafeBrowsingState.ENHANCED_PROTECTION;
+            boolean standard_protection_checked =
+                    currentState == SafeBrowsingState.STANDARD_PROTECTION;
+            boolean no_protection_checked = currentState == SafeBrowsingState.NO_SAFE_BROWSING;
+            Assert.assertEquals(ASSERT_RADIO_BUTTON_CHECKED, enhanced_protection_checked,
+                    getEnhancedProtectionButton().isChecked());
+            Assert.assertEquals(ASSERT_RADIO_BUTTON_CHECKED, standard_protection_checked,
+                    getStandardProtectionButton().isChecked());
+            Assert.assertEquals(ASSERT_RADIO_BUTTON_CHECKED, no_protection_checked,
+                    getNoProtectionButton().isChecked());
+        });
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"SafeBrowsing"})
+    @Features.EnableFeatures(ChromeFeatureList.SAFE_BROWSING_ENHANCED_PROTECTION_ENABLED)
+    public void testCheckRadioButtons() {
+        TestThreadUtils.runOnUiThreadBlocking(() -> {
+            // Click the Enhanced Protection button.
+            getEnhancedProtectionButton().onClick(null);
+            Assert.assertEquals(ASSERT_SAFE_BROWSING_STATE_RADIO_BUTTON_GROUP,
+                    SafeBrowsingState.ENHANCED_PROTECTION, getSafeBrowsingState());
+            Assert.assertTrue(
+                    ASSERT_RADIO_BUTTON_CHECKED, getEnhancedProtectionButton().isChecked());
+            Assert.assertFalse(
+                    ASSERT_RADIO_BUTTON_CHECKED, getStandardProtectionButton().isChecked());
+            Assert.assertFalse(ASSERT_RADIO_BUTTON_CHECKED, getNoProtectionButton().isChecked());
+            Assert.assertEquals(ASSERT_SAFE_BROWSING_STATE_NATIVE,
+                    SafeBrowsingState.ENHANCED_PROTECTION,
+                    SafeBrowsingBridge.getSafeBrowsingState());
+
+            // Click the Standard Protection button.
+            getStandardProtectionButton().onClick(null);
+            Assert.assertEquals(ASSERT_SAFE_BROWSING_STATE_RADIO_BUTTON_GROUP,
+                    SafeBrowsingState.STANDARD_PROTECTION, getSafeBrowsingState());
+            Assert.assertFalse(
+                    ASSERT_RADIO_BUTTON_CHECKED, getEnhancedProtectionButton().isChecked());
+            Assert.assertTrue(
+                    ASSERT_RADIO_BUTTON_CHECKED, getStandardProtectionButton().isChecked());
+            Assert.assertFalse(ASSERT_RADIO_BUTTON_CHECKED, getNoProtectionButton().isChecked());
+            Assert.assertEquals(ASSERT_SAFE_BROWSING_STATE_NATIVE,
+                    SafeBrowsingState.STANDARD_PROTECTION,
+                    SafeBrowsingBridge.getSafeBrowsingState());
+
+            // Click the No Protection button.
+            getNoProtectionButton().onClick(null);
+            Assert.assertEquals(ASSERT_SAFE_BROWSING_STATE_RADIO_BUTTON_GROUP,
+                    SafeBrowsingState.NO_SAFE_BROWSING, getSafeBrowsingState());
+            Assert.assertFalse(
+                    ASSERT_RADIO_BUTTON_CHECKED, getEnhancedProtectionButton().isChecked());
+            Assert.assertFalse(
+                    ASSERT_RADIO_BUTTON_CHECKED, getStandardProtectionButton().isChecked());
+            Assert.assertTrue(ASSERT_RADIO_BUTTON_CHECKED, getNoProtectionButton().isChecked());
+            Assert.assertEquals(ASSERT_SAFE_BROWSING_STATE_NATIVE,
+                    SafeBrowsingState.NO_SAFE_BROWSING, SafeBrowsingBridge.getSafeBrowsingState());
+        });
+    }
+
+    @Test
+    @SmallTest
+    @Feature({"SafeBrowsing"})
+    @Features.DisableFeatures(ChromeFeatureList.SAFE_BROWSING_ENHANCED_PROTECTION_ENABLED)
+    public void testEnhancedProtectionDisabled() {
+        Assert.assertNull(getEnhancedProtectionButton());
+    }
+
+    private @SafeBrowsingState int getSafeBrowsingState() {
+        return mSafeBrowsingPreference.getSafeBrowsingStateForTesting();
+    }
+
+    private RadioButtonWithDescriptionAndAuxButton getEnhancedProtectionButton() {
+        return mSafeBrowsingPreference.getEnhancedProtectionButtonForTesting();
+    }
+
+    private RadioButtonWithDescriptionAndAuxButton getStandardProtectionButton() {
+        return mSafeBrowsingPreference.getStandardProtectionButtonForTesting();
+    }
+
+    private RadioButtonWithDescription getNoProtectionButton() {
+        return mSafeBrowsingPreference.getNoProtectionButtonForTesting();
+    }
+}
diff --git a/chrome/browser/safe_browsing/android/safe_browsing_bridge.cc b/chrome/browser/safe_browsing/android/safe_browsing_bridge.cc
index 1da8503..96960af 100644
--- a/chrome/browser/safe_browsing/android/safe_browsing_bridge.cc
+++ b/chrome/browser/safe_browsing/android/safe_browsing_bridge.cc
@@ -52,4 +52,14 @@
       prefs::kSafeBrowsingScoutReportingEnabled);
 }
 
+static jint JNI_SafeBrowsingBridge_GetSafeBrowsingState(JNIEnv* env) {
+  return safe_browsing::GetSafeBrowsingState(*GetPrefService());
+}
+
+static void JNI_SafeBrowsingBridge_SetSafeBrowsingState(JNIEnv* env,
+                                                        jint state) {
+  return safe_browsing::SetSafeBrowsingState(
+      GetPrefService(), static_cast<SafeBrowsingState>(state));
+}
+
 }  // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/download_protection/download_protection_service_unittest.cc b/chrome/browser/safe_browsing/download_protection/download_protection_service_unittest.cc
index 0254ba76..326270b0 100644
--- a/chrome/browser/safe_browsing/download_protection/download_protection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/download_protection/download_protection_service_unittest.cc
@@ -3658,7 +3658,7 @@
   WebUIInfoSingleton::GetInstance()->AddListenerForTesting();
 
   {
-    SetEnhancedProtectionPref(profile()->GetPrefs(), true);
+    SetEnhancedProtectionPrefForTests(profile()->GetPrefs(), true);
     NiceMockDownloadItem item;
     content::DownloadItemUtils::AttachInfo(&item, profile(), nullptr);
     PrepareBasicDownloadItem(&item,
@@ -3691,7 +3691,7 @@
   }
 
   {
-    SetEnhancedProtectionPref(profile()->GetPrefs(), false);
+    SetEnhancedProtectionPrefForTests(profile()->GetPrefs(), false);
     NiceMockDownloadItem item;
     content::DownloadItemUtils::AttachInfo(&item, profile(), nullptr);
     PrepareBasicDownloadItem(&item,
@@ -3731,7 +3731,7 @@
 
   identity_test_env_adaptor_->identity_test_env()
       ->SetAutomaticIssueOfAccessTokens(/*grant=*/true);
-  SetEnhancedProtectionPref(profile()->GetPrefs(), true);
+  SetEnhancedProtectionPrefForTests(profile()->GetPrefs(), true);
 
   WebUIInfoSingleton::GetInstance()->AddListenerForTesting();
 
@@ -3811,7 +3811,7 @@
   WebUIInfoSingleton::GetInstance()->AddListenerForTesting();
 
   {
-    SetEnhancedProtectionPref(profile()->GetPrefs(), true);
+    SetEnhancedProtectionPrefForTests(profile()->GetPrefs(), true);
     NiceMockDownloadItem item;
     content::DownloadItemUtils::AttachInfo(
         &item, profile()->GetPrimaryOTRProfile(), nullptr);
diff --git a/chrome/browser/share/android/BUILD.gn b/chrome/browser/share/android/BUILD.gn
index f312deb5..0bb60bc6 100644
--- a/chrome/browser/share/android/BUILD.gn
+++ b/chrome/browser/share/android/BUILD.gn
@@ -9,6 +9,7 @@
     "java/res/drawable/camera_img.xml",
     "java/res/drawable/delete.xml",
     "java/res/drawable/edit.xml",
+    "java/res/drawable/link.xml",
     "java/res/drawable/qrcode_background.xml",
     "java/res/drawable/save.xml",
     "java/res/drawable/share.xml",
diff --git a/chrome/browser/share/android/java/res/drawable/link.xml b/chrome/browser/share/android/java/res/drawable/link.xml
new file mode 100644
index 0000000..f0f3664
--- /dev/null
+++ b/chrome/browser/share/android/java/res/drawable/link.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2020 The Chromium Authors. All rights reserved.
+     Use of this source code is governed by a BSD-style license that can be
+     found in the LICENSE file. -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    tools:targetApi="21"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:pathData="M17,7h-4v2h4c1.65,0 3,1.35 3,3s-1.35,3 -3,3h-4v2h4c2.76,0 5,-2.24 5,-5s-2.24,-5 -5,-5zM11,15L7,15c-1.65,0 -3,-1.35 -3,-3s1.35,-3 3,-3h4L11,7L7,7c-2.76,0 -5,2.24 -5,5s2.24,5 5,5h4v-2zM8,11h8v2L8,13z"
+      android:fillColor="@color/default_icon_color"/>
+</vector>
\ No newline at end of file
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java
index 90c022cf..7267a59 100644
--- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProvider.java
@@ -145,6 +145,10 @@
             mOrderedFirstPartyOptions.add(createCopyTextFirstPartyOption());
         }
         mOrderedFirstPartyOptions.add(createSendTabToSelfFirstPartyOption());
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_SHARING_HUB_V15)
+                && ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_SHARE_HIGHLIGHTS_ANDROID)) {
+            mOrderedFirstPartyOptions.add(createHighlightsFirstPartyOption());
+        }
         if (ChromeFeatureList.isEnabled(ChromeFeatureList.CHROME_SHARE_QRCODE)) {
             mOrderedFirstPartyOptions.add(createQrCodeFirstPartyOption());
         }
@@ -298,6 +302,24 @@
                 propertyModel, Collections.singleton(ContentType.LINK_PAGE_VISIBLE));
     }
 
+    private FirstPartyOption createHighlightsFirstPartyOption() {
+        PropertyModel propertyModel = ShareSheetPropertyModelBuilder.createPropertyModel(
+                AppCompatResources.getDrawable(
+                        mActivity, org.chromium.chrome.browser.share.R.drawable.link),
+                mActivity.getResources().getString(R.string.sharing_highlights),
+                (currentActivity)
+                        -> {
+                    RecordUserAction.record("SharingHubAndroid.SharedHighlights");
+                    RecordHistogram.recordMediumTimesHistogram(
+                            "Sharing.SharingHubAndroid.TimeToShare",
+                            System.currentTimeMillis() - mShareStartTime);
+                    mBottomSheetController.hideContent(mBottomSheetContent, true);
+                    // TODO(1102382): Init and call link-to-text feature.
+                },
+                /*isFirstParty=*/true);
+        return new FirstPartyOption(propertyModel, Collections.singleton(ContentType.TEXT));
+    }
+
     /**
      * Returns the url to share.
      *
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java
index ea18882..aa588fe 100644
--- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java
+++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/share_sheet/ChromeProvidedSharingOptionsProviderTest.java
@@ -137,7 +137,8 @@
     @MediumTest
     @Features.EnableFeatures({ChromeFeatureList.CHROME_SHARING_HUB_V15})
     @Features.DisableFeatures(
-            {ChromeFeatureList.CHROME_SHARE_SCREENSHOT, ChromeFeatureList.CHROME_SHARE_QRCODE})
+            {ChromeFeatureList.CHROME_SHARE_SCREENSHOT, ChromeFeatureList.CHROME_SHARE_QRCODE,
+                    ChromeFeatureList.CHROME_SHARE_HIGHLIGHTS_ANDROID})
     public void
     createPropertyModels_sharingHub15Enabled_includesCopyText() {
         setUpChromeProvidedSharingOptionsProviderTest(/*printingEnabled=*/false);
@@ -196,6 +197,38 @@
 
     @Test
     @MediumTest
+    @Features.DisableFeatures({ChromeFeatureList.CHROME_SHARING_HUB_V15})
+    @Features.EnableFeatures({ChromeFeatureList.CHROME_SHARE_HIGHLIGHTS_ANDROID})
+    public void createPropertyModels_sharingHub15Disabled_noHighlights() {
+        setUpChromeProvidedSharingOptionsProviderTest(/*printingEnabled=*/false);
+        List<PropertyModel> propertyModels =
+                mChromeProvidedSharingOptionsProvider.getPropertyModels(
+                        ImmutableSet.of(ContentType.TEXT));
+
+        Assert.assertEquals("Incorrect number of property models.", 0, propertyModels.size());
+        assertModelsAreFirstParty(propertyModels);
+    }
+
+    @Test
+    @MediumTest
+    @Features.EnableFeatures({ChromeFeatureList.CHROME_SHARING_HUB_V15,
+            ChromeFeatureList.CHROME_SHARE_HIGHLIGHTS_ANDROID})
+    public void
+    createPropertyModels_sharingHub15HighlightsEnabled() {
+        setUpChromeProvidedSharingOptionsProviderTest(/*printingEnabled=*/false);
+        List<PropertyModel> propertyModels =
+                mChromeProvidedSharingOptionsProvider.getPropertyModels(
+                        ImmutableSet.of(ContentType.TEXT));
+
+        Assert.assertEquals("Incorrect number of property models.", 2, propertyModels.size());
+        assertModelsAreInTheRightOrder(propertyModels,
+                ImmutableList.of(mActivity.getResources().getString(R.string.sharing_copy_text),
+                        mActivity.getResources().getString(R.string.sharing_highlights)));
+        assertModelsAreFirstParty(propertyModels);
+    }
+
+    @Test
+    @MediumTest
     public void getUrlToShare_noShareParamsUrl_returnsImageUrl() {
         ShareParams shareParams = new ShareParams.Builder(null, /*title=*/"", /*url=*/"").build();
         ChromeShareExtras chromeShareExtras =
diff --git a/chrome/browser/sharing/shared_clipboard/shared_clipboard_test_base.cc b/chrome/browser/sharing/shared_clipboard/shared_clipboard_test_base.cc
index b4192fa..7f4fd8a 100644
--- a/chrome/browser/sharing/shared_clipboard/shared_clipboard_test_base.cc
+++ b/chrome/browser/sharing/shared_clipboard/shared_clipboard_test_base.cc
@@ -43,7 +43,7 @@
 std::string SharedClipboardTestBase::GetClipboardText() {
   base::string16 text;
   ui::Clipboard::GetForCurrentThread()->ReadText(
-      ui::ClipboardBuffer::kCopyPaste, &text);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &text);
   return base::UTF16ToUTF8(text);
 }
 
diff --git a/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc b/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc
index d1bf02a..f819a73b 100644
--- a/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc
+++ b/chrome/browser/ui/android/autofill/autofill_popup_view_android.cc
@@ -92,7 +92,8 @@
     bool is_label_multiline =
         suggestion.frontend_id ==
             POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE ||
-        suggestion.frontend_id == POPUP_ITEM_ID_CREDIT_CARD_SIGNIN_PROMO;
+        suggestion.frontend_id == POPUP_ITEM_ID_CREDIT_CARD_SIGNIN_PROMO ||
+        suggestion.frontend_id == POPUP_ITEM_ID_MIXED_FORM_MESSAGE;
     Java_AutofillPopupBridge_addToAutofillSuggestionArray(
         env, data_array, i, value, label, android_icon_id,
         /*icon_at_start=*/false, suggestion.frontend_id, is_deletable,
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
index d77fd07..e5a98e0 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -933,6 +933,24 @@
       <message name="IDS_PREFS_SECTION_SAFE_BROWSING_TITLE" desc="Title for the Safe Browsing section. [CHAR-LIMIT=32]">
         Safe Browsing
       </message>
+      <message name="IDS_SAFE_BROWSING_ENHANCED_PROTECTION_TITLE" desc="Title for Safe Browsing enhanced protection mode. [CHAR-LIMIT=32]">
+        Enhanced protection
+      </message>
+      <message name="IDS_SAFE_BROWSING_ENHANCED_PROTECTION_SUMMARY" desc="Summary for Safe Browsing enhanced protection mode.">
+        Faster, proactive protection against dangerous websites, downloads, and extensions. Warns you about password breaches. Requires browsing data to be sent to Google.
+      </message>
+      <message name="IDS_SAFE_BROWSING_STANDARD_PROTECTION_TITLE" desc="Title for Safe Browsing standard protection mode. [CHAR-LIMIT=32]">
+        Standard protection
+      </message>
+      <message name="IDS_SAFE_BROWSING_STANDARD_PROTECTION_SUMMARY" desc="Summary for Safe Browsing standard protection mode.">
+        Standard protection against websites, downloads, and extensions that are known to be dangerous.
+      </message>
+      <message name="IDS_SAFE_BROWSING_NO_PROTECTION_TITLE" desc="Title for Safe Browsing no protection mode. [CHAR-LIMIT=32]">
+        No protection (not recommended)
+      </message>
+      <message name="IDS_SAFE_BROWSING_NO_PROTECTION_SUMMARY" desc="Summary for Safe Browsing no protection mode.">
+        Does not protect you against dangerous websites, downloads, and extensions. You’ll still get Safe Browsing protection, where available, in other Google services, like Gmail and Search.
+      </message>
 
       <!-- Accessibility preferences -->
       <message name="IDS_PREFS_ACCESSIBILITY" desc="Title of Accessibility settings, which allows the user to change webpage font sizes. [CHAR-LIMIT=32]">
@@ -3700,6 +3718,10 @@
         Screenshot
       </message>
 
+      <message name="IDS_SHARING_HIGHLIGHTS" desc="Label for Link-to-text button in the sharing hub.">
+        Link to text
+      </message>
+
       <message name="IDS_LINK_COPIED" desc="Text shown in the toast notification when Copy Link is selected in the sharing hub.">
         Link Copied
       </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFE_BROWSING_ENHANCED_PROTECTION_SUMMARY.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFE_BROWSING_ENHANCED_PROTECTION_SUMMARY.png.sha1
new file mode 100644
index 0000000..ffdd9d77
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFE_BROWSING_ENHANCED_PROTECTION_SUMMARY.png.sha1
@@ -0,0 +1 @@
+435925989dd5756eed78e49b301627aba7e149db
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFE_BROWSING_ENHANCED_PROTECTION_TITLE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFE_BROWSING_ENHANCED_PROTECTION_TITLE.png.sha1
new file mode 100644
index 0000000..ffdd9d77
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFE_BROWSING_ENHANCED_PROTECTION_TITLE.png.sha1
@@ -0,0 +1 @@
+435925989dd5756eed78e49b301627aba7e149db
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFE_BROWSING_NO_PROTECTION_SUMMARY.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFE_BROWSING_NO_PROTECTION_SUMMARY.png.sha1
new file mode 100644
index 0000000..ffdd9d77
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFE_BROWSING_NO_PROTECTION_SUMMARY.png.sha1
@@ -0,0 +1 @@
+435925989dd5756eed78e49b301627aba7e149db
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFE_BROWSING_NO_PROTECTION_TITLE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFE_BROWSING_NO_PROTECTION_TITLE.png.sha1
new file mode 100644
index 0000000..ffdd9d77
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFE_BROWSING_NO_PROTECTION_TITLE.png.sha1
@@ -0,0 +1 @@
+435925989dd5756eed78e49b301627aba7e149db
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFE_BROWSING_STANDARD_PROTECTION_SUMMARY.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFE_BROWSING_STANDARD_PROTECTION_SUMMARY.png.sha1
new file mode 100644
index 0000000..ffdd9d77
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFE_BROWSING_STANDARD_PROTECTION_SUMMARY.png.sha1
@@ -0,0 +1 @@
+435925989dd5756eed78e49b301627aba7e149db
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFE_BROWSING_STANDARD_PROTECTION_TITLE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFE_BROWSING_STANDARD_PROTECTION_TITLE.png.sha1
new file mode 100644
index 0000000..ffdd9d77
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SAFE_BROWSING_STANDARD_PROTECTION_TITLE.png.sha1
@@ -0,0 +1 @@
+435925989dd5756eed78e49b301627aba7e149db
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_HIGHLIGHTS.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_HIGHLIGHTS.png.sha1
new file mode 100644
index 0000000..15bc5b0
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_SHARING_HIGHLIGHTS.png.sha1
@@ -0,0 +1 @@
+dd385075e0e48f43fd9dd3163fb10444e0d00a57
\ No newline at end of file
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
index 6e5fd29..a44b2af 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
@@ -115,7 +115,7 @@
     DictionaryPrefUpdate update(
         prefs_, arc::prefs::kArcSetNotificationsEnabledDeferred);
     base::DictionaryValue* const dict = update.Get();
-    dict->RemoveWithoutPathExpansion(app_id, /* out_value */ nullptr);
+    dict->RemoveKey(app_id);
   }
 
  private:
diff --git a/chrome/browser/ui/ash/assistant/assistant_browsertest.cc b/chrome/browser/ui/ash/assistant/assistant_browsertest.cc
index 8edbf62..48eb666 100644
--- a/chrome/browser/ui/ash/assistant/assistant_browsertest.cc
+++ b/chrome/browser/ui/ash/assistant/assistant_browsertest.cc
@@ -2,14 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/strings/string_util.h"
+#include "base/run_loop.h"
 #include "base/test/bind_test_util.h"
+#include "base/test/scoped_run_loop_timeout.h"
+#include "base/time/time.h"
 #include "chrome/browser/ui/ash/assistant/assistant_test_mixin.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
 #include "chromeos/audio/cras_audio_handler.h"
-#include "chromeos/dbus/power/power_manager_client.h"
 #include "chromeos/dbus/power_manager/backlight.pb.h"
 #include "chromeos/services/assistant/public/cpp/features.h"
+#include "chromeos/services/assistant/service.h"
 #include "content/public/test/browser_test.h"
 
 namespace chromeos {
@@ -34,27 +36,22 @@
 
 }  // namespace
 
-class AssistantBrowserTest : public MixinBasedInProcessBrowserTest,
-                             public testing::WithParamInterface<bool> {
+class AssistantBrowserTest : public MixinBasedInProcessBrowserTest {
  public:
-  AssistantBrowserTest() {
-    if (GetParam()) {
-      feature_list_.InitAndEnableFeature(
-          features::kAssistantResponseProcessingV2);
-    } else {
-      feature_list_.InitAndDisableFeature(
-          features::kAssistantResponseProcessingV2);
-    }
-  }
-
+  AssistantBrowserTest() = default;
   ~AssistantBrowserTest() override = default;
 
+  AssistantTestMixin* tester() { return &tester_; }
+
   void ShowAssistantUi() {
     if (!tester()->IsVisible())
       tester()->PressAssistantKey();
   }
 
-  AssistantTestMixin* tester() { return &tester_; }
+  void CloseAssistantUi() {
+    if (tester()->IsVisible())
+      tester()->PressAssistantKey();
+  }
 
   void InitializeBrightness() {
     auto* power_manager = chromeos::PowerManagerClient::Get();
@@ -117,7 +114,7 @@
   DISALLOW_COPY_AND_ASSIGN(AssistantBrowserTest);
 };
 
-IN_PROC_BROWSER_TEST_P(AssistantBrowserTest,
+IN_PROC_BROWSER_TEST_F(AssistantBrowserTest,
                        ShouldOpenAssistantUiWhenPressingAssistantKey) {
   tester()->StartAssistantAndWaitForReady();
 
@@ -126,7 +123,7 @@
   EXPECT_TRUE(tester()->IsVisible());
 }
 
-IN_PROC_BROWSER_TEST_P(AssistantBrowserTest, ShouldDisplayTextResponse) {
+IN_PROC_BROWSER_TEST_F(AssistantBrowserTest, ShouldDisplayTextResponse) {
   tester()->StartAssistantAndWaitForReady();
 
   ShowAssistantUi();
@@ -141,7 +138,7 @@
   });
 }
 
-IN_PROC_BROWSER_TEST_P(AssistantBrowserTest, ShouldDisplayCardResponse) {
+IN_PROC_BROWSER_TEST_F(AssistantBrowserTest, ShouldDisplayCardResponse) {
   tester()->StartAssistantAndWaitForReady();
 
   ShowAssistantUi();
@@ -152,7 +149,7 @@
   tester()->ExpectCardResponse("Mount Everest");
 }
 
-IN_PROC_BROWSER_TEST_P(AssistantBrowserTest, ShouldTurnUpVolume) {
+IN_PROC_BROWSER_TEST_F(AssistantBrowserTest, ShouldTurnUpVolume) {
   tester()->StartAssistantAndWaitForReady();
 
   ShowAssistantUi();
@@ -174,7 +171,7 @@
                                    cras));
 }
 
-IN_PROC_BROWSER_TEST_P(AssistantBrowserTest, ShouldTurnDownVolume) {
+IN_PROC_BROWSER_TEST_F(AssistantBrowserTest, ShouldTurnDownVolume) {
   tester()->StartAssistantAndWaitForReady();
 
   ShowAssistantUi();
@@ -196,7 +193,7 @@
                                    cras));
 }
 
-IN_PROC_BROWSER_TEST_P(AssistantBrowserTest, ShouldTurnUpBrightness) {
+IN_PROC_BROWSER_TEST_F(AssistantBrowserTest, ShouldTurnUpBrightness) {
   tester()->StartAssistantAndWaitForReady();
 
   ShowAssistantUi();
@@ -210,7 +207,7 @@
   ExpectBrightnessUp();
 }
 
-IN_PROC_BROWSER_TEST_P(AssistantBrowserTest, ShouldTurnDownBrightness) {
+IN_PROC_BROWSER_TEST_F(AssistantBrowserTest, ShouldTurnDownBrightness) {
   tester()->StartAssistantAndWaitForReady();
 
   ShowAssistantUi();
@@ -224,9 +221,31 @@
   ExpectBrightnessDown();
 }
 
-// We parameterize all AssistantBrowserTests to verify that they work for both
-// response processing v1 as well as response processing v2.
-INSTANTIATE_TEST_SUITE_P(All, AssistantBrowserTest, testing::Bool());
+IN_PROC_BROWSER_TEST_F(AssistantBrowserTest,
+                       ShouldShowSingleErrorOnNetworkDown) {
+  tester()->StartAssistantAndWaitForReady();
+
+  ShowAssistantUi();
+
+  EXPECT_TRUE(tester()->IsVisible());
+
+  tester()->DisableFakeS3Server();
+
+  base::RunLoop().RunUntilIdle();
+
+  tester()->SendTextQuery("Is this thing on?");
+
+  tester()->ExpectErrorResponse(
+      "Something went wrong. Try again in a few seconds");
+
+  // Make sure no further changes happen to the view hierarchy.
+  tester()->ExpectNoChange(base::TimeDelta::FromSeconds(1));
+
+  // This is necessary to prevent a UserInitiatedVoicelessActivity from
+  // blocking test harness teardown while we wait on assistant to finish
+  // the interaction.
+  CloseAssistantUi();
+}
 
 }  // namespace assistant
 }  // namespace chromeos
diff --git a/chrome/browser/ui/ash/assistant/assistant_test_mixin.cc b/chrome/browser/ui/ash/assistant/assistant_test_mixin.cc
index 8447f95..c3bf99a7 100644
--- a/chrome/browser/ui/ash/assistant/assistant_test_mixin.cc
+++ b/chrome/browser/ui/ash/assistant/assistant_test_mixin.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 #include <utility>
+#include <vector>
 
 #include "ash/assistant/model/ui/assistant_card_element.h"
 #include "ash/assistant/ui/assistant_ui_constants.h"
@@ -21,7 +22,7 @@
 #include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h"
 #include "chrome/browser/chromeos/login/test/login_manager_mixin.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/browser/ui/ash/assistant/test_support/fake_s3_server.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
 #include "chromeos/constants/chromeos_switches.h"
 #include "chromeos/login/auth/user_context.h"
@@ -30,6 +31,7 @@
 #include "google_apis/gaia/gaia_urls.h"
 #include "net/dns/mock_host_resolver.h"
 #include "ui/events/test/event_generator.h"
+#include "ui/views/controls/label.h"
 
 namespace chromeos {
 namespace assistant {
@@ -44,10 +46,6 @@
       AccountId::FromUserEmailGaiaId(kTestUser, kTestUserGaiaId));
 }
 
-bool Equals(const char* left, const char* right) {
-  return strcmp(left, right) == 0;
-}
-
 // Waiter that blocks in the |Wait| method until a given |AssistantStatus|
 // is reached, or until a timeout is hit.
 // On timeout this will abort the test with a useful error message.
@@ -224,7 +222,7 @@
   // ResponseWaiter overrides:
   base::Optional<std::string> GetResponseTextOfView(
       views::View* view) const override {
-    if (Equals(view->GetClassName(), class_name_.c_str())) {
+    if (view->GetClassName() == class_name_) {
       return static_cast<ash::AssistantUiElementView*>(view)
           ->ToStringForTesting();
     }
@@ -252,7 +250,7 @@
   // ExpectedResponseWaiter overrides:
   base::Optional<std::string> GetResponseTextOfView(
       views::View* view) const override {
-    if (Equals(view->GetClassName(), class_name_.c_str())) {
+    if (view->GetClassName() == class_name_) {
       return static_cast<ash::AssistantUiElementView*>(view)
           ->ToStringForTesting();
     }
@@ -279,6 +277,44 @@
       base::TimeDelta::FromMilliseconds(10));
 }
 
+// Calls a callback when the view hierarchy changes.
+class CallbackViewHierarchyChangedObserver : views::ViewObserver {
+ public:
+  explicit CallbackViewHierarchyChangedObserver(
+      views::View* parent_view,
+      base::RepeatingCallback<void(const views::ViewHierarchyChangedDetails&)>
+          callback)
+      : callback_(callback), parent_view_(parent_view) {
+    parent_view_->AddObserver(this);
+  }
+
+  ~CallbackViewHierarchyChangedObserver() override {
+    if (parent_view_)
+      parent_view_->RemoveObserver(this);
+  }
+
+  // ViewObserver:
+  void OnViewHierarchyChanged(
+      views::View* observed_view,
+      const views::ViewHierarchyChangedDetails& details) override {
+    callback_.Run(details);
+  }
+
+  void OnViewIsDeleting(views::View* view) override {
+    DCHECK_EQ(view, parent_view_);
+
+    if (parent_view_)
+      parent_view_->RemoveObserver(this);
+
+    parent_view_ = nullptr;
+  }
+
+ private:
+  base::RepeatingCallback<void(const views::ViewHierarchyChangedDetails&)>
+      callback_;
+  views::View* parent_view_;
+};
+
 }  // namespace
 
 // Test mixin for the browser tests that logs in the given user and issues
@@ -382,6 +418,10 @@
 
 void AssistantTestMixin::TearDownOnMainThread() {
   DisableAssistant();
+  DisableFakeS3Server();
+}
+
+void AssistantTestMixin::DisableFakeS3Server() {
   fake_s3_server_.Teardown();
 }
 
@@ -495,6 +535,17 @@
   waiter.RunUntilResponseReceived();
 }
 
+void AssistantTestMixin::ExpectErrorResponse(
+    const std::string& expected_response,
+    base::TimeDelta wait_timeout) {
+  const base::test::ScopedRunLoopTimeout run_timeout(FROM_HERE, wait_timeout);
+  TypedExpectedResponseWaiter waiter("AssistantErrorElementView",
+                                     test_api_->ui_element_container(),
+                                     {expected_response});
+
+  waiter.RunUntilResponseReceived();
+}
+
 void AssistantTestMixin::ExpectTimersResponse(
     const std::vector<base::TimeDelta>& timers,
     base::TimeDelta wait_timeout) {
@@ -547,6 +598,30 @@
   return test_api_->IsVisible();
 }
 
+void AssistantTestMixin::ExpectNoChange(base::TimeDelta wait_timeout) {
+  base::test::ScopedDisableRunLoopTimeout disable_timeout;
+
+  base::RunLoop run_loop;
+
+  // Exit the runloop after wait_timeout.
+  base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+      FROM_HERE,
+      base::BindRepeating(
+          [](base::RepeatingClosure quit) { std::move(quit).Run(); },
+          run_loop.QuitClosure()),
+      wait_timeout);
+
+  // Fail the runloop when the view hierarchy changes.
+  auto callback = base::BindRepeating(
+      [](const views::ViewHierarchyChangedDetails& change) { FAIL(); });
+
+  CallbackViewHierarchyChangedObserver observer(
+      test_api_->ui_element_container(), std::move(callback));
+
+  EXPECT_NO_FATAL_FAILURE(run_loop.Run())
+      << "View hierarchy changed during ExpectNoChange.";
+}
+
 PrefService* AssistantTestMixin::GetUserPreferences() {
   return ProfileManager::GetPrimaryUserProfile()->GetPrefs();
 }
diff --git a/chrome/browser/ui/ash/assistant/assistant_test_mixin.h b/chrome/browser/ui/ash/assistant/assistant_test_mixin.h
index b4e88a1..b6883c2 100644
--- a/chrome/browser/ui/ash/assistant/assistant_test_mixin.h
+++ b/chrome/browser/ui/ash/assistant/assistant_test_mixin.h
@@ -12,6 +12,7 @@
 #include "base/macros.h"
 #include "base/time/time.h"
 #include "chrome/browser/ui/ash/assistant/test_support/fake_s3_server.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
 #include "ui/events/keycodes/keyboard_codes_posix.h"
 
@@ -56,6 +57,8 @@
   void SetUpOnMainThread() override;
   void TearDownOnMainThread() override;
 
+  void DisableFakeS3Server();
+
   // Starts the Assistant service and wait until it is ready to process
   // queries. Should be called as the first action in every test.
   void StartAssistantAndWaitForReady(
@@ -98,6 +101,12 @@
   void ExpectCardResponse(const std::string& expected_response,
                           base::TimeDelta wait_timeout = kDefaultWaitTimeout);
 
+  // Waits until an error response is rendered that contains the given text. If
+  // |expected_response| is not received in |wait_timeout|, this will fail the
+  // test.
+  void ExpectErrorResponse(const std::string& expected_response,
+                           base::TimeDelta wait_timeout = kDefaultWaitTimeout);
+
   // Waits until a text response is rendered that contains the given text.
   // If |expected_response| is not received in |wait_timeout|, this will fail
   // the test.
@@ -127,6 +136,10 @@
   // Returns true if the Assistant UI is currently visible.
   bool IsVisible();
 
+  // Watches the view hierarchy for change and fails if
+  // a view is updated / deleted / added before wait_timeout time elapses.
+  void ExpectNoChange(base::TimeDelta wait_timeout = kDefaultWaitTimeout);
+
  private:
   PrefService* GetUserPreferences();
   void SendKeyPress(ui::KeyboardCode key);
diff --git a/chrome/browser/ui/ash/assistant/test_support/fake_s3_server.cc b/chrome/browser/ui/ash/assistant/test_support/fake_s3_server.cc
index 4da0521..67b3796 100644
--- a/chrome/browser/ui/ash/assistant/test_support/fake_s3_server.cc
+++ b/chrome/browser/ui/ash/assistant/test_support/fake_s3_server.cc
@@ -183,6 +183,12 @@
 }
 
 void FakeS3Server::StartS3ServerProcess(FakeS3Mode mode) {
+  if (process_running_) {
+    LOG(WARNING)
+        << "Called FakeS3Server::StartS3ServerProcess when already running.";
+    return;
+  }
+
   base::FilePath fake_s3_server_main =
       GetExecutableDir().Append(FILE_PATH_LITERAL(kFakeS3ServerBinary));
 
@@ -193,10 +199,17 @@
   AppendArgument(&command_line, "--test_data_file", GetTestDataFileName());
 
   fake_s3_server_ = base::LaunchProcess(command_line, base::LaunchOptions{});
+  process_running_ = true;
 }
 
 void FakeS3Server::StopS3ServerProcess() {
+  if (!process_running_) {
+    LOG(WARNING)
+        << "Called FakeS3Server::StopS3ServerProcess when already stopped.";
+    return;
+  }
   fake_s3_server_.Terminate(/*exit_code=*/0, /*wait=*/true);
+  process_running_ = false;
 }
 
 std::string FakeS3Server::GetTestDataFileName() {
diff --git a/chrome/browser/ui/ash/assistant/test_support/fake_s3_server.h b/chrome/browser/ui/ash/assistant/test_support/fake_s3_server.h
index 65b4adf..e09da6b 100644
--- a/chrome/browser/ui/ash/assistant/test_support/fake_s3_server.h
+++ b/chrome/browser/ui/ash/assistant/test_support/fake_s3_server.h
@@ -65,6 +65,7 @@
   std::string access_token_{"FAKE_ACCESS_TOKEN"};
   std::string fake_s3_server_uri_;
   int data_file_version_;
+  bool process_running_ = false;
 
   std::unique_ptr<PortSelector> port_selector_;
 
diff --git a/chrome/browser/ui/ash/chrome_screenshot_grabber_browsertest.cc b/chrome/browser/ui/ash/chrome_screenshot_grabber_browsertest.cc
index 71f26f27..5832a453 100644
--- a/chrome/browser/ui/ash/chrome_screenshot_grabber_browsertest.cc
+++ b/chrome/browser/ui/ash/chrome_screenshot_grabber_browsertest.cc
@@ -72,7 +72,7 @@
   bool IsImageClipboardAvailable() {
     return ui::Clipboard::GetForCurrentThread()->IsFormatAvailable(
         ui::ClipboardFormatType::GetBitmapType(),
-        ui::ClipboardBuffer::kCopyPaste);
+        ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr);
   }
 
   scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
diff --git a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
index 7c04872..efae6d0 100644
--- a/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
+++ b/chrome/browser/ui/autofill/autofill_popup_controller_impl.cc
@@ -427,7 +427,7 @@
 bool AutofillPopupControllerImpl::CanAccept(int id) {
   return id != POPUP_ITEM_ID_SEPARATOR &&
          id != POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE &&
-         id != POPUP_ITEM_ID_TITLE;
+         id != POPUP_ITEM_ID_MIXED_FORM_MESSAGE && id != POPUP_ITEM_ID_TITLE;
 }
 
 bool AutofillPopupControllerImpl::HasSuggestions() {
diff --git a/chrome/browser/ui/omnibox/clipboard_utils.cc b/chrome/browser/ui/omnibox/clipboard_utils.cc
index e21cccb..0b7d323 100644
--- a/chrome/browser/ui/omnibox/clipboard_utils.cc
+++ b/chrome/browser/ui/omnibox/clipboard_utils.cc
@@ -15,9 +15,11 @@
   // Try text format.
   ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
   if (clipboard->IsFormatAvailable(ui::ClipboardFormatType::GetPlainTextType(),
-                                   ui::ClipboardBuffer::kCopyPaste)) {
+                                   ui::ClipboardBuffer::kCopyPaste,
+                                   /* data_dst = */ nullptr)) {
     base::string16 text;
-    clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &text);
+    clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste,
+                        /* data_dst = */ nullptr, &text);
     text = text.substr(0, kMaxClipboardTextLength);
     return OmniboxView::SanitizeTextForPaste(text);
   }
@@ -30,9 +32,10 @@
   // cannonicalized, which is not what the user expects.  By pasting in this
   // order, we are sure to paste what the user copied.
   if (clipboard->IsFormatAvailable(ui::ClipboardFormatType::GetUrlType(),
-                                   ui::ClipboardBuffer::kCopyPaste)) {
+                                   ui::ClipboardBuffer::kCopyPaste,
+                                   /* data_dst = */ nullptr)) {
     std::string url_str;
-    clipboard->ReadBookmark(nullptr, &url_str);
+    clipboard->ReadBookmark(nullptr, /* data_dst = */ nullptr, &url_str);
     // pass resulting url string through GURL to normalize
     GURL url(url_str);
     if (url.is_valid())
diff --git a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
index 7246ca9..a0ec1ac 100644
--- a/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
+++ b/chrome/browser/ui/views/autofill/autofill_popup_view_native_views.cc
@@ -1130,6 +1130,7 @@
         rows_.push_back(AutofillPopupSeparatorView::Create(this, line_number));
         break;
 
+      case autofill::PopupItemId::POPUP_ITEM_ID_MIXED_FORM_MESSAGE:
       case autofill::PopupItemId::
           POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE:
         rows_.push_back(AutofillPopupWarningView::Create(this, line_number));
diff --git a/chrome/browser/ui/views/crostini/crostini_recovery_view_browsertest.cc b/chrome/browser/ui/views/crostini/crostini_recovery_view_browsertest.cc
index 3760172..ec648d9a 100644
--- a/chrome/browser/ui/views/crostini/crostini_recovery_view_browsertest.cc
+++ b/chrome/browser/ui/views/crostini/crostini_recovery_view_browsertest.cc
@@ -157,8 +157,7 @@
   // Terminal should launch after use clicks 'Cancel'.
   Browser* terminal_browser = web_app::FindSystemWebAppBrowser(
       browser()->profile(), web_app::SystemAppType::TERMINAL);
-  CHECK_NE(nullptr, terminal_browser);
-  WaitForLoadFinished(terminal_browser->tab_strip_model()->GetWebContentsAt(0));
+  EXPECT_NE(nullptr, terminal_browser);
 
   // Any new apps launched should show the dialog again.
   crostini::LaunchCrostiniApp(
diff --git a/chrome/browser/ui/views/find_bar_views_interactive_uitest.cc b/chrome/browser/ui/views/find_bar_views_interactive_uitest.cc
index 2bdb8694..97721df 100644
--- a/chrome/browser/ui/views/find_bar_views_interactive_uitest.cc
+++ b/chrome/browser/ui/views/find_bar_views_interactive_uitest.cc
@@ -567,7 +567,7 @@
 
   base::string16 str;
   ui::Clipboard::GetForCurrentThread()->ReadText(
-      ui::ClipboardBuffer::kCopyPaste, &str);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &str);
 
   // Make sure the text is copied successfully.
   EXPECT_EQ(ASCIIToUTF16("a"), str);
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc
index a55bd22a..660f6573 100644
--- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/ui/views/location_bar/custom_tab_bar_view.h"
 #include "chrome/browser/ui/views/toolbar/toolbar_view.h"
 #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
+#include "chrome/browser/web_applications/components/web_app_install_utils.h"
 #include "chrome/common/web_application_info.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -24,6 +25,7 @@
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/theme_change_waiter.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
 #include "third_party/blink/public/mojom/frame/fullscreen.mojom.h"
 #include "ui/base/theme_provider.h"
 
@@ -48,20 +50,20 @@
   // longer be hosted apps when BMO ships.
   void InstallAndLaunchBookmarkApp(
       base::Optional<GURL> app_url = base::nullopt) {
-    if (!app_url)
-      app_url = GetAppURL();
+    blink::Manifest manifest;
+    manifest.start_url = app_url.value_or(GetAppURL());
+    manifest.scope = manifest.start_url.GetWithoutFilename();
+    manifest.theme_color = app_theme_color_;
+
     auto web_app_info = std::make_unique<WebApplicationInfo>();
-    web_app_info->app_url = *app_url;
-    web_app_info->scope = app_url->GetWithoutFilename();
-    if (app_theme_color_)
-      web_app_info->theme_color = *app_theme_color_;
+    web_app::UpdateWebAppInfoFromManifest(manifest, web_app_info.get());
 
     web_app::AppId app_id =
         web_app::InstallWebApp(profile(), std::move(web_app_info));
     app_browser_ = web_app::LaunchWebAppBrowser(profile(), app_id);
     web_contents_ = app_browser_->tab_strip_model()->GetActiveWebContents();
     // Ensure the main page has loaded and is ready for ExecJs DOM manipulation.
-    ASSERT_TRUE(content::NavigateToURL(web_contents_, *app_url));
+    ASSERT_TRUE(content::NavigateToURL(web_contents_, manifest.start_url));
 
     app_browser_view_ = BrowserView::GetBrowserViewForBrowser(app_browser_);
     app_frame_view_ = app_browser_view_->frame()->GetFrameView();
@@ -127,6 +129,21 @@
             app_frame_view_->GetFrameColor(BrowserFrameActiveState::kActive));
 }
 
+// Tests that an opaque frame color is used for a web app with a transparent
+// theme color.
+IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewBrowserTest,
+                       OpaqueFrameColorForTransparentWebAppThemeColor) {
+  // Ensure we're not using the system theme on Linux.
+  ThemeService* theme_service =
+      ThemeServiceFactory::GetForProfile(browser()->profile());
+  theme_service->UseDefaultTheme();
+
+  app_theme_color_ = SkColorSetA(SK_ColorBLUE, 0x88);
+  InstallAndLaunchBookmarkApp();
+  EXPECT_EQ(app_frame_view_->GetFrameColor(BrowserFrameActiveState::kActive),
+            SK_ColorBLUE);
+}
+
 // Tests the frame color for a bookmark app when the system theme is applied.
 IN_PROC_BROWSER_TEST_F(BrowserNonClientFrameViewBrowserTest,
                        BookmarkAppFrameColorSystemTheme) {
diff --git a/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc b/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc
index 1c76734..567bf20 100644
--- a/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc
+++ b/chrome/browser/ui/views/location_bar/custom_tab_bar_view_browsertest.cc
@@ -455,7 +455,8 @@
 
   ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
   base::string16 result;
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &result);
   EXPECT_EQ(result, base::UTF8ToUTF16("http://example.test/"));
 }
 
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view.cc b/chrome/browser/ui/views/location_bar/location_bar_view.cc
index f0c46d2..0d31cd4 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view.cc
@@ -1250,7 +1250,7 @@
           ui::ClipboardBuffer::kSelection)) {
     base::string16 text;
     ui::Clipboard::GetForCurrentThread()->ReadText(
-        ui::ClipboardBuffer::kSelection, &text);
+        ui::ClipboardBuffer::kSelection, /* data_dst = */ nullptr, &text);
     text = OmniboxView::SanitizeTextForPaste(text);
 
     if (!GetOmniboxView()->model()->CanPasteAndGo(text)) {
diff --git a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
index e38c40a..8482e6e 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_result_view.cc
@@ -362,10 +362,7 @@
   }
 
   const int suggestion_indent =
-      (popup_contents_view_->InExplicitExperimentalKeywordMode() ||
-       match_.IsSubMatch())
-          ? 70
-          : 0;
+      popup_contents_view_->InExplicitExperimentalKeywordMode() ? 70 : 0;
   const int suggestion_height = suggestion_view_->GetPreferredSize().height();
   suggestion_view_->SetBounds(suggestion_indent, 0,
                               suggestion_width - suggestion_indent,
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
index 811cd5b..ad8bc80 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views.cc
@@ -2049,7 +2049,7 @@
 void OmniboxViewViews::OnAfterCutOrCopy(ui::ClipboardBuffer clipboard_buffer) {
   ui::Clipboard* cb = ui::Clipboard::GetForCurrentThread();
   base::string16 selected_text;
-  cb->ReadText(clipboard_buffer, &selected_text);
+  cb->ReadText(clipboard_buffer, /* data_dst = */ nullptr, &selected_text);
   GURL url;
   bool write_url = false;
   model()->AdjustTextForCopy(GetSelectedRange().GetMin(), &selected_text, &url,
diff --git a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
index 57c6db3..723b45f 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_view_views_unittest.cc
@@ -834,21 +834,25 @@
   EXPECT_EQ(expected_text, omnibox_view()->GetText());
 
   // Make sure the plain text format is available, but the HTML one isn't.
-  EXPECT_TRUE(clipboard->IsFormatAvailable(
-      ui::ClipboardFormatType::GetPlainTextType(), clipboard_buffer));
-  EXPECT_FALSE(clipboard->IsFormatAvailable(
-      ui::ClipboardFormatType::GetHtmlType(), clipboard_buffer));
+  EXPECT_TRUE(
+      clipboard->IsFormatAvailable(ui::ClipboardFormatType::GetPlainTextType(),
+                                   clipboard_buffer, /* data_dst = */ nullptr));
+  EXPECT_FALSE(
+      clipboard->IsFormatAvailable(ui::ClipboardFormatType::GetHtmlType(),
+                                   clipboard_buffer, /* data_dst = */ nullptr));
 
   // Windows clipboard only supports text URLs.
   // Mac clipboard not reporting URL format available for some reason.
   // crbug.com/751031
 #if defined(OS_LINUX)
-  EXPECT_TRUE(clipboard->IsFormatAvailable(
-      ui::ClipboardFormatType::GetUrlType(), clipboard_buffer));
+  EXPECT_TRUE(
+      clipboard->IsFormatAvailable(ui::ClipboardFormatType::GetUrlType(),
+                                   clipboard_buffer, /* data_dst = */ nullptr));
 #endif
 
   std::string read_from_clipboard;
-  clipboard->ReadAsciiText(clipboard_buffer, &read_from_clipboard);
+  clipboard->ReadAsciiText(clipboard_buffer, /* data_dst = */ nullptr,
+                           &read_from_clipboard);
   EXPECT_EQ("https://test.com/", read_from_clipboard);
 }
 
@@ -869,13 +873,16 @@
 
   // Make sure HTML format isn't written. See
   // BookmarkNodeData::WriteToClipboard() for details.
-  EXPECT_TRUE(clipboard->IsFormatAvailable(
-      ui::ClipboardFormatType::GetPlainTextType(), clipboard_buffer));
-  EXPECT_FALSE(clipboard->IsFormatAvailable(
-      ui::ClipboardFormatType::GetHtmlType(), clipboard_buffer));
+  EXPECT_TRUE(
+      clipboard->IsFormatAvailable(ui::ClipboardFormatType::GetPlainTextType(),
+                                   clipboard_buffer, /* data_dst = */ nullptr));
+  EXPECT_FALSE(
+      clipboard->IsFormatAvailable(ui::ClipboardFormatType::GetHtmlType(),
+                                   clipboard_buffer, /* data_dst = */ nullptr));
 
   std::string read_from_clipboard;
-  clipboard->ReadAsciiText(clipboard_buffer, &read_from_clipboard);
+  clipboard->ReadAsciiText(clipboard_buffer, /* data_dst = */ nullptr,
+                           &read_from_clipboard);
   EXPECT_EQ("user text", read_from_clipboard);
 }
 
diff --git a/chrome/browser/ui/views/sharing/remote_copy_browsertest.cc b/chrome/browser/ui/views/sharing/remote_copy_browsertest.cc
index bd4164dc..d320346f 100644
--- a/chrome/browser/ui/views/sharing/remote_copy_browsertest.cc
+++ b/chrome/browser/ui/views/sharing/remote_copy_browsertest.cc
@@ -124,14 +124,14 @@
   std::vector<base::string16> GetAvailableClipboardTypes() {
     std::vector<base::string16> types;
     ui::Clipboard::GetForCurrentThread()->ReadAvailableTypes(
-        ui::ClipboardBuffer::kCopyPaste, &types);
+        ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &types);
     return types;
   }
 
   std::string ReadClipboardText() {
     base::string16 text;
     ui::Clipboard::GetForCurrentThread()->ReadText(
-        ui::ClipboardBuffer::kCopyPaste, &text);
+        ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &text);
     return base::UTF16ToUTF8(text);
   }
 
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index a8f932d5..84ce278a 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -3505,7 +3505,8 @@
           ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
           CHECK(clipboard);
           base::string16 clipboard_text;
-          clipboard->ReadText(ui::ClipboardBuffer::kSelection, &clipboard_text);
+          clipboard->ReadText(ui::ClipboardBuffer::kSelection,
+                              /* data_dst = */ nullptr, &clipboard_text);
           if (!clipboard_text.empty())
             controller_->CreateNewTabWithLocation(clipboard_text);
         }
diff --git a/chrome/browser/ui/web_applications/web_app_browsertest.cc b/chrome/browser/ui/web_applications/web_app_browsertest.cc
index 361dd99e..579348e 100644
--- a/chrome/browser/ui/web_applications/web_app_browsertest.cc
+++ b/chrome/browser/ui/web_applications/web_app_browsertest.cc
@@ -118,10 +118,13 @@
 IN_PROC_BROWSER_TEST_P(WebAppBrowserTest, ThemeColor) {
   {
     const SkColor theme_color = SkColorSetA(SK_ColorBLUE, 0xF0);
+    blink::Manifest manifest;
+    manifest.start_url = GURL(kExampleURL);
+    manifest.scope = GURL(kExampleURL);
+    manifest.theme_color = theme_color;
     auto web_app_info = std::make_unique<WebApplicationInfo>();
-    web_app_info->app_url = GURL(kExampleURL);
-    web_app_info->scope = GURL(kExampleURL);
-    web_app_info->theme_color = theme_color;
+    web_app::UpdateWebAppInfoFromManifest(manifest, web_app_info.get());
+
     AppId app_id = InstallWebApp(std::move(web_app_info));
     Browser* app_browser = LaunchWebAppBrowser(app_id);
 
@@ -483,7 +486,8 @@
 
   ui::Clipboard* const clipboard = ui::Clipboard::GetForCurrentThread();
   base::string16 result;
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &result);
   EXPECT_EQ(result, base::UTF8ToUTF16(kExampleURL));
 }
 
diff --git a/chrome/browser/ui/webui/about_ui.cc b/chrome/browser/ui/webui/about_ui.cc
index a4fe8c0..d6729e2 100644
--- a/chrome/browser/ui/webui/about_ui.cc
+++ b/chrome/browser/ui/webui/about_ui.cc
@@ -545,14 +545,28 @@
   std::string html;
   AppendHeader(&html, 0, "Chrome URLs");
   AppendBody(&html);
+
   html += "<h2>List of Chrome URLs</h2>\n<ul>\n";
   std::vector<std::string> hosts(
       chrome::kChromeHostURLs,
       chrome::kChromeHostURLs + chrome::kNumberOfChromeHostURLs);
   std::sort(hosts.begin(), hosts.end());
-  for (std::vector<std::string>::const_iterator i = hosts.begin();
-       i != hosts.end(); ++i)
-    html += "<li><a href='chrome://" + *i + "/'>chrome://" + *i + "</a></li>\n";
+  for (const std::string& host : hosts) {
+    html +=
+        "<li><a href='chrome://" + host + "/'>chrome://" + host + "</a></li>\n";
+  }
+
+  html += "</ul><h2>List of chrome://internals pages</h2>\n<ul>\n";
+  std::vector<std::string> internals_paths(
+      chrome::kChromeInternalsPathURLs,
+      chrome::kChromeInternalsPathURLs +
+          chrome::kNumberOfChromeInternalsPathURLs);
+  std::sort(internals_paths.begin(), internals_paths.end());
+  for (const std::string& path : internals_paths) {
+    html += "<li><a href='chrome://internals/" + path +
+            "'>chrome://internals/" + path + "</a></li>\n";
+  }
+
   html += "</ul>\n<h2>For Debug</h2>\n"
       "<p>The following pages are for debugging purposes only. Because they "
       "crash or hang the renderer, they're not linked directly; you can type "
@@ -560,6 +574,7 @@
   for (size_t i = 0; i < chrome::kNumberOfChromeDebugURLs; i++)
     html += "<li>" + std::string(chrome::kChromeDebugURLs[i]) + "</li>\n";
   html += "</ul>\n";
+
   AppendFooter(&html);
   return html;
 }
diff --git a/chrome/browser/ui/webui/internals/internals_ui.cc b/chrome/browser/ui/webui/internals/internals_ui.cc
index fc32522..03c119b 100644
--- a/chrome/browser/ui/webui/internals/internals_ui.cc
+++ b/chrome/browser/ui/webui/internals/internals_ui.cc
@@ -24,6 +24,7 @@
   source_ = content::WebUIDataSource::Create(chrome::kChromeUIInternalsHost);
 
   // Add your sub-URL internals WebUI here.
+  // Keep this set of sub-URLs in sync with |kChromeInternalsPathURLs|.
 #if defined(OS_ANDROID)
   // chrome://internals/query-tiles
   AddNotificationsInternals(web_ui);
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
index 23e90c90..85a0893 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
+++ b/chrome/browser/ui/webui/tab_search/tab_search_page_handler.cc
@@ -98,7 +98,7 @@
       TabRendererData::FromTabInModel(browser->tab_strip_model(), index);
   tab_data->pinned = tab_renderer_data.pinned;
   tab_data->title = base::UTF16ToUTF8(tab_renderer_data.title);
-  tab_data->url = tab_renderer_data.visible_url.GetContent();
+  tab_data->url = tab_renderer_data.visible_url.spec();
 
   if (tab_renderer_data.favicon.isNull()) {
     tab_data->is_default_favicon = true;
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_page_handler_unittest.cc b/chrome/browser/ui/webui/tab_search/tab_search_page_handler_unittest.cc
index 7d88429..c5b03240 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_page_handler_unittest.cc
+++ b/chrome/browser/ui/webui/tab_search/tab_search_page_handler_unittest.cc
@@ -20,10 +20,6 @@
 constexpr char kTabUrl3[] = "http://foo/3";
 constexpr char kTabUrl4[] = "http://foo/4";
 
-constexpr char kTabUrlName1[] = "foo/1";
-constexpr char kTabUrlName2[] = "foo/2";
-constexpr char kTabUrlName3[] = "foo/3";
-
 constexpr char kTabName1[] = "Tab 1";
 constexpr char kTabName2[] = "Tab 2";
 constexpr char kTabName3[] = "Tab 3";
@@ -153,11 +149,11 @@
             ASSERT_EQ(2u, window1->tabs.size());
 
             auto* tab1 = window1->tabs[0].get();
-            ExpectNewTab(tab1, kTabUrlName1, kTabName1, 0);
+            ExpectNewTab(tab1, kTabUrl1, kTabName1, 0);
             ASSERT_TRUE(tab1->active);
 
             auto* tab2 = window1->tabs[1].get();
-            ExpectNewTab(tab2, kTabUrlName2, kTabName2, 1);
+            ExpectNewTab(tab2, kTabUrl2, kTabName2, 1);
             ASSERT_FALSE(tab2->active);
 
             auto* window2 = profile_tabs->windows[1].get();
@@ -165,7 +161,7 @@
             ASSERT_EQ(1u, window2->tabs.size());
 
             auto* tab3 = window2->tabs[0].get();
-            ExpectNewTab(tab3, kTabUrlName3, kTabName3, 0);
+            ExpectNewTab(tab3, kTabUrl3, kTabName3, 0);
             ASSERT_TRUE(tab3->active);
 
             tab_id2 = tab2->tab_id;
diff --git a/chrome/browser/ui/webui/tab_search/tab_search_ui.cc b/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
index ae3dc93b..622e122b 100644
--- a/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
+++ b/chrome/browser/ui/webui/tab_search/tab_search_ui.cc
@@ -8,6 +8,8 @@
 #include "chrome/browser/ui/webui/tab_search/tab_search_page_handler.h"
 #include "chrome/browser/ui/webui/webui_util.h"
 #include "chrome/common/webui_url_constants.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
 #include "content/public/browser/web_ui_data_source.h"
@@ -29,6 +31,7 @@
 #if BUILDFLAG(ENABLE_TAB_SEARCH)
   content::WebUIDataSource* source =
       content::WebUIDataSource::Create(chrome::kChromeUITabSearchHost);
+  source->AddLocalizedString("close", IDS_CLOSE);
   source->AddResourcePath("tab_search.mojom-lite.js",
                           IDR_TAB_SEARCH_MOJO_LITE_JS);
   webui::SetupWebUIDataSource(
diff --git a/chrome/browser/web_applications/components/web_app_install_utils.cc b/chrome/browser/web_applications/components/web_app_install_utils.cc
index 811f0de..6b4405f1 100644
--- a/chrome/browser/web_applications/components/web_app_install_utils.cc
+++ b/chrome/browser/web_applications/components/web_app_install_utils.cc
@@ -144,8 +144,10 @@
   if (manifest.scope.is_valid())
     web_app_info->scope = manifest.scope;
 
-  if (manifest.theme_color)
-    web_app_info->theme_color = *manifest.theme_color;
+  if (manifest.theme_color) {
+    web_app_info->theme_color =
+        SkColorSetA(*manifest.theme_color, SK_AlphaOPAQUE);
+  }
 
   if (manifest.display != DisplayMode::kUndefined)
     web_app_info->display_mode = manifest.display;
diff --git a/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc b/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc
index 6c795eef..1a9e1a7d 100644
--- a/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc
+++ b/chrome/browser/web_applications/components/web_app_install_utils_unittest.cc
@@ -126,12 +126,12 @@
   blink::Manifest::ImageResource icon;
   icon.src = AppIcon2();
   icon.purpose = {blink::Manifest::ImageResource::Purpose::ANY,
-                  blink::Manifest::ImageResource::Purpose::BADGE};
+                  blink::Manifest::ImageResource::Purpose::MONOCHROME};
   manifest.icons.push_back(icon);
   icon.src = AppIcon3();
   manifest.icons.push_back(icon);
   // Add an icon without purpose ANY (expect to be ignored).
-  icon.purpose = {blink::Manifest::ImageResource::Purpose::BADGE};
+  icon.purpose = {blink::Manifest::ImageResource::Purpose::MONOCHROME};
   manifest.icons.push_back(icon);
 
   UpdateWebAppInfoFromManifest(manifest, &web_app_info);
@@ -241,12 +241,12 @@
   blink::Manifest::ImageResource icon;
   icon.src = AppIcon2();
   icon.purpose = {blink::Manifest::ImageResource::Purpose::ANY,
-                  blink::Manifest::ImageResource::Purpose::BADGE};
+                  blink::Manifest::ImageResource::Purpose::MONOCHROME};
   manifest.icons.push_back(icon);
   icon.src = AppIcon3();
   manifest.icons.push_back(icon);
   // Add an icon without purpose ANY (expect to be ignored).
-  icon.purpose = {blink::Manifest::ImageResource::Purpose::BADGE};
+  icon.purpose = {blink::Manifest::ImageResource::Purpose::MONOCHROME};
   manifest.icons.push_back(icon);
 
   // Test that shortcuts in the manifest replace those in |web_app_info|.
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_registrar.cc b/chrome/browser/web_applications/extensions/bookmark_app_registrar.cc
index 3cc6924..537e78a 100644
--- a/chrome/browser/web_applications/extensions/bookmark_app_registrar.cc
+++ b/chrome/browser/web_applications/extensions/bookmark_app_registrar.cc
@@ -124,12 +124,7 @@
   if (!extension)
     return base::nullopt;
 
-  base::Optional<SkColor> extension_theme_color =
-      AppThemeColorInfo::GetThemeColor(extension);
-  if (extension_theme_color)
-    return SkColorSetA(*extension_theme_color, SK_AlphaOPAQUE);
-
-  return base::nullopt;
+  return AppThemeColorInfo::GetThemeColor(extension);
 }
 
 const GURL& BookmarkAppRegistrar::GetAppLaunchURL(
diff --git a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
index 998d821..3b7b513 100644
--- a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
+++ b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
@@ -631,13 +631,17 @@
   install_observer.SetWebAppUninstalledDelegate(
       base::BindLambdaForTesting([](const AppId& app_id) { NOTREACHED(); }));
 
-  OverrideManifest(kManifestTemplate, {kInstallableIconList, "red"});
+  // CSS #RRGGBBAA syntax.
+  OverrideManifest(kManifestTemplate, {kInstallableIconList, "#00FF00F0"});
   EXPECT_EQ(GetResultAfterPageLoad(GetAppURL(), &app_id),
             ManifestUpdateResult::kAppUpdated);
   histogram_tester_.ExpectBucketCount(kUpdateHistogramName,
                                       ManifestUpdateResult::kAppUpdated, 1);
   AwaitShortcutsUpdated(kInstallableIconTopLeftColor);
-  EXPECT_EQ(GetProvider().registrar().GetAppThemeColor(app_id), SK_ColorRED);
+
+  // Updated theme_color loses any transparency.
+  EXPECT_EQ(GetProvider().registrar().GetAppThemeColor(app_id),
+            SkColorSetARGB(0xFF, 0x00, 0xFF, 0x00));
 }
 
 IN_PROC_BROWSER_TEST_P(ManifestUpdateManagerBrowserTest, CheckKeepsSameName) {
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.cc b/chrome/browser/web_applications/web_app_install_finalizer.cc
index 64e4566..c78d995 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.cc
+++ b/chrome/browser/web_applications/web_app_install_finalizer.cc
@@ -431,8 +431,8 @@
   web_app->SetDescription(base::UTF16ToUTF8(web_app_info.description));
   web_app->SetScope(web_app_info.scope);
   if (web_app_info.theme_color) {
-    web_app->SetThemeColor(
-        SkColorSetA(*web_app_info.theme_color, SK_AlphaOPAQUE));
+    DCHECK_EQ(SkColorGetA(*web_app_info.theme_color), SK_AlphaOPAQUE);
+    web_app->SetThemeColor(web_app_info.theme_color);
   }
 
   WebApp::SyncFallbackData sync_fallback_data;
diff --git a/chrome/browser/web_applications/web_app_install_task_unittest.cc b/chrome/browser/web_applications/web_app_install_task_unittest.cc
index 90c20c26..a3e0417 100644
--- a/chrome/browser/web_applications/web_app_install_task_unittest.cc
+++ b/chrome/browser/web_applications/web_app_install_task_unittest.cc
@@ -391,8 +391,7 @@
   const std::string manifest_name = "Manifest Name";
   const std::string description = "Description";
   const GURL scope = GURL("https://example.com/scope");
-  const base::Optional<SkColor> theme_color = 0xAABBCCDD;
-  const base::Optional<SkColor> expected_theme_color = 0xFFBBCCDD;  // Opaque.
+  const base::Optional<SkColor> theme_color = 0xFFAABBCC;
 
   const AppId app_id = GenerateAppIdFromURL(url);
 
@@ -435,7 +434,7 @@
   EXPECT_EQ(description, web_app->description());
   EXPECT_EQ(url, web_app->launch_url());
   EXPECT_EQ(scope, web_app->scope());
-  EXPECT_EQ(expected_theme_color, web_app->theme_color());
+  EXPECT_EQ(theme_color, web_app->theme_color());
 }
 
 TEST_F(WebAppInstallTaskTest, ForceReinstall) {
@@ -1199,8 +1198,7 @@
   const std::string name = "Name";
   const std::string description = "Description";
   const GURL scope = GURL("https://example.com/scope");
-  const base::Optional<SkColor> theme_color = 0xAABBCCDD;
-  const base::Optional<SkColor> expected_theme_color = 0xFFBBCCDD;  // Opaque.
+  const base::Optional<SkColor> theme_color = 0xFFAABBCC;
 
   const AppId app_id = GenerateAppIdFromURL(url);
 
@@ -1233,7 +1231,7 @@
   EXPECT_EQ(description, web_app->description());
   EXPECT_EQ(url, web_app->launch_url());
   EXPECT_EQ(scope, web_app->scope());
-  EXPECT_EQ(expected_theme_color, web_app->theme_color());
+  EXPECT_EQ(theme_color, web_app->theme_color());
   EXPECT_EQ(1u, test_shortcut_manager().num_register_run_on_os_login_calls());
 }
 
@@ -1245,8 +1243,7 @@
   const std::string name = "Name";
   const std::string description = "Description";
   const GURL scope = GURL("https://example.com/scope");
-  const base::Optional<SkColor> theme_color = 0xAABBCCDD;
-  const base::Optional<SkColor> expected_theme_color = 0xFFBBCCDD;  // Opaque.
+  const base::Optional<SkColor> theme_color = 0xFFAABBCC;
 
   const AppId app_id = GenerateAppIdFromURL(url);
 
@@ -1279,7 +1276,7 @@
   EXPECT_EQ(description, web_app->description());
   EXPECT_EQ(url, web_app->launch_url());
   EXPECT_EQ(scope, web_app->scope());
-  EXPECT_EQ(expected_theme_color, web_app->theme_color());
+  EXPECT_EQ(theme_color, web_app->theme_color());
   EXPECT_EQ(0u, test_shortcut_manager().num_register_run_on_os_login_calls());
 }
 
@@ -1432,8 +1429,8 @@
 
   static constexpr char kShortcutItemName[] = "shortcut item";
   static constexpr SquareSizePx kIconSize = 128;
-  static constexpr SkColor kInitialThemeColor = 0x000000;
-  static constexpr SkColor kFinalThemeColor = 0xFFFFFF;
+  static constexpr SkColor kInitialThemeColor = 0xFF000000;
+  static constexpr SkColor kFinalThemeColor = 0xFFFFFFFF;
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 4c13688d..b4b586c1 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-master-1594758783-89b5869eda45090ee3c154382bf0c8063de97283.profdata
+chrome-mac-master-1594771186-d832f8303da18f87f12d9f2a0dd0e6f277bb9e8f.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 7f8d90c..e13ba889 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-master-1594670295-0a4f7f614ea3d9de6fcc3b138431b409b2b96371.profdata
+chrome-win32-master-1594753046-ef9d371c47540400b1490f52cf3260906b5b98d4.profdata
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
index 545faba..9a582be 100644
--- a/chrome/common/webui_url_constants.cc
+++ b/chrome/common/webui_url_constants.cc
@@ -86,6 +86,8 @@
 const char kChromeUIInspectHost[] = "inspect";
 const char kChromeUIInspectURL[] = "chrome://inspect/";
 const char kChromeUIInternalsHost[] = "internals";
+const char kChromeUIInternalsQueryTilesPath[] = "query-tiles";
+const char kChromeUIInternalsWebAppPath[] = "web-app";
 const char kChromeUIInterstitialHost[] = "interstitials";
 const char kChromeUIInterstitialURL[] = "chrome://interstitials/";
 const char kChromeUIInterventionsInternalsHost[] = "interventions-internals";
@@ -541,6 +543,18 @@
 };
 const size_t kNumberOfChromeHostURLs = base::size(kChromeHostURLs);
 
+// Add chrome://internals/* subpages here to be included in chrome://chrome-urls
+// (about:about).
+const char* const kChromeInternalsPathURLs[] = {
+#if defined(OS_ANDROID)
+    kChromeUIInternalsQueryTilesPath,
+#else
+    kChromeUIInternalsWebAppPath,
+#endif  // defined(OS_ANDROID)
+};
+const size_t kNumberOfChromeInternalsPathURLs =
+    base::size(kChromeInternalsPathURLs);
+
 const char* const kChromeDebugURLs[] = {
     content::kChromeUIBadCastCrashURL,
     content::kChromeUIBrowserCrashURL,
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h
index f3a3c88..998938d 100644
--- a/chrome/common/webui_url_constants.h
+++ b/chrome/common/webui_url_constants.h
@@ -91,6 +91,8 @@
 extern const char kChromeUIInspectHost[];
 extern const char kChromeUIInspectURL[];
 extern const char kChromeUIInternalsHost[];
+extern const char kChromeUIInternalsQueryTilesPath[];
+extern const char kChromeUIInternalsWebAppPath[];
 extern const char kChromeUIInterstitialHost[];
 extern const char kChromeUIInterstitialURL[];
 extern const char kChromeUIInterventionsInternalsHost[];
@@ -367,6 +369,10 @@
 extern const char* const kChromeHostURLs[];
 extern const size_t kNumberOfChromeHostURLs;
 
+// Gets the chrome://internals pages that are shown in chrome://chrome-urls.
+extern const char* const kChromeInternalsPathURLs[];
+extern const size_t kNumberOfChromeInternalsPathURLs;
+
 // "Debug" pages which are dangerous and not for general consumption.
 extern const char* const kChromeDebugURLs[];
 extern const size_t kNumberOfChromeDebugURLs;
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 91ddb38..35dc5d8 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -2244,6 +2244,7 @@
         "../browser/chromeos/login/login_browsertest.cc",
         "../browser/chromeos/login/login_manager_test.cc",
         "../browser/chromeos/login/login_manager_test.h",
+        "../browser/chromeos/login/login_screen_extensions_lifetime_manager_browsertest.cc",
         "../browser/chromeos/login/login_screen_policy_browsertest.cc",
         "../browser/chromeos/login/login_ui_browsertest.cc",
         "../browser/chromeos/login/login_ui_hide_supervised_users_browsertest.cc",
diff --git a/chrome/test/data/banners/manifest.json b/chrome/test/data/banners/manifest.json
index 72a5f60..607f7433 100644
--- a/chrome/test/data/banners/manifest.json
+++ b/chrome/test/data/banners/manifest.json
@@ -15,7 +15,7 @@
       "src": "launcher-icon-2x.png",
       "sizes": "96x96",
       "type": "image/png",
-      "purpose": "any badge"
+      "purpose": "any monochrome"
     },
     {
       "src": "launcher-icon-3x.png",
diff --git a/chrome/test/data/banners/manifest_empty_name_short_name.json b/chrome/test/data/banners/manifest_empty_name_short_name.json
index 27ce3357..84b28b5 100644
--- a/chrome/test/data/banners/manifest_empty_name_short_name.json
+++ b/chrome/test/data/banners/manifest_empty_name_short_name.json
@@ -14,7 +14,7 @@
       "src": "launcher-icon-2x.png",
       "sizes": "96x96",
       "type": "image/png",
-      "purpose": "any badge"
+      "purpose": "any monochrome"
     },
     {
       "src": "launcher-icon-3x.png",
diff --git a/chrome/test/data/banners/manifest_too_small_icon.json b/chrome/test/data/banners/manifest_too_small_icon.json
index 0324ae0..d7b9d34 100644
--- a/chrome/test/data/banners/manifest_too_small_icon.json
+++ b/chrome/test/data/banners/manifest_too_small_icon.json
@@ -5,7 +5,7 @@
       "src": "launcher-icon-1x.png",
       "sizes": "48x48",
       "type": "image/png",
-      "purpose": "any badge"
+      "purpose": "any monochrome"
     }
   ],
   "start_url": "manifest_test_page.html",
diff --git a/chrome/test/data/banners/manifest_with_file_handlers.json b/chrome/test/data/banners/manifest_with_file_handlers.json
index f95a149..695af6e0 100644
--- a/chrome/test/data/banners/manifest_with_file_handlers.json
+++ b/chrome/test/data/banners/manifest_with_file_handlers.json
@@ -15,7 +15,7 @@
       "src": "launcher-icon-2x.png",
       "sizes": "96x96",
       "type": "image/png",
-      "purpose": "any badge"
+      "purpose": "any monochrome"
     },
     {
       "src": "launcher-icon-3x.png",
diff --git a/chrome/test/data/banners/release_notes_manifest.json b/chrome/test/data/banners/release_notes_manifest.json
index ff400ea0..e70a906 100644
--- a/chrome/test/data/banners/release_notes_manifest.json
+++ b/chrome/test/data/banners/release_notes_manifest.json
@@ -16,7 +16,7 @@
       "src": "launcher-icon-2x.png",
       "sizes": "96x96",
       "type": "image/png",
-      "purpose": "any badge"
+      "purpose": "any monochrome"
     },
     {
       "src": "launcher-icon-3x.png",
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn
index dcf6ef30..bd512b2 100644
--- a/chrome/test/data/webui/BUILD.gn
+++ b/chrome/test/data/webui/BUILD.gn
@@ -45,6 +45,7 @@
       "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_profile_avatar_selector_tests.m.js",
       "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_tabs_test.m.js",
       "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_toggle_test.m.js",
+      "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_toolbar_search_field_tests.m.js",
       "$root_gen_dir/chrome/test/data/webui/cr_elements/iron_list_focus_test.m.js",
       "$root_gen_dir/chrome/test/data/webui/cr_focus_row_behavior_test.m.js",
       "$root_gen_dir/chrome/test/data/webui/mock_controller.m.js",
@@ -200,7 +201,6 @@
       "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_slider_test.m.js",
       "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_toast_manager_test.m.js",
       "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_toast_test.m.js",
-      "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_toolbar_search_field_tests.m.js",
       "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_toolbar_tests.m.js",
       "$root_gen_dir/chrome/test/data/webui/cr_elements/cr_view_manager_test.m.js",
       "$root_gen_dir/chrome/test/data/webui/fake_chrome_event.m.js",
diff --git a/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js b/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
index 1522458..44cf01fd 100644
--- a/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
+++ b/chrome/test/data/webui/cr_elements/cr_elements_browsertest.js
@@ -85,30 +85,6 @@
  * @constructor
  * @extends {CrElementsBrowserTest}
  */
-function CrElementsToolbarSearchFieldTest() {}
-
-CrElementsToolbarSearchFieldTest.prototype = {
-  __proto__: CrElementsBrowserTest.prototype,
-
-  /** @override */
-  browsePreload:
-      'chrome://resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html',
-
-  /** @override */
-  extraLibraries: CrElementsBrowserTest.prototype.extraLibraries.concat([
-    '../test_util.js',
-    'cr_toolbar_search_field_tests.js',
-  ]),
-};
-
-TEST_F('CrElementsToolbarSearchFieldTest', 'All', function() {
-  mocha.run();
-});
-
-/**
- * @constructor
- * @extends {CrElementsBrowserTest}
- */
 function CrElementsToolbarTest() {}
 
 CrElementsToolbarTest.prototype = {
diff --git a/chrome/test/data/webui/cr_elements/cr_elements_focus_test.js b/chrome/test/data/webui/cr_elements/cr_elements_focus_test.js
index ea93242..ae9415d 100644
--- a/chrome/test/data/webui/cr_elements/cr_elements_focus_test.js
+++ b/chrome/test/data/webui/cr_elements/cr_elements_focus_test.js
@@ -56,6 +56,30 @@
  * @constructor
  * @extends {CrElementsFocusTest}
  */
+function CrElementsToolbarSearchFieldTest() {}
+
+CrElementsToolbarSearchFieldTest.prototype = {
+  __proto__: CrElementsFocusTest.prototype,
+
+  /** @override */
+  browsePreload:
+      'chrome://resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html',
+
+  /** @override */
+  extraLibraries: CrElementsFocusTest.prototype.extraLibraries.concat([
+    '../test_util.js',
+    'cr_toolbar_search_field_tests.js',
+  ]),
+};
+
+TEST_F('CrElementsToolbarSearchFieldTest', 'All', function() {
+  mocha.run();
+});
+
+/**
+ * @constructor
+ * @extends {CrElementsFocusTest}
+ */
 function CrElementsToggleTest() {}
 
 CrElementsToggleTest.prototype = {
diff --git a/chrome/test/data/webui/cr_elements/cr_elements_v3_browsertest.js b/chrome/test/data/webui/cr_elements/cr_elements_v3_browsertest.js
index 4931871..34717dd 100644
--- a/chrome/test/data/webui/cr_elements/cr_elements_v3_browsertest.js
+++ b/chrome/test/data/webui/cr_elements/cr_elements_v3_browsertest.js
@@ -263,18 +263,6 @@
 });
 
 // eslint-disable-next-line no-var
-var CrElementsToolbarSearchFieldV3Test = class extends CrElementsV3BrowserTest {
-  /** @override */
-  get browsePreload() {
-    return 'chrome://test?module=cr_elements/cr_toolbar_search_field_tests.m.js';
-  }
-};
-
-TEST_F('CrElementsToolbarSearchFieldV3Test', 'All', function() {
-  mocha.run();
-});
-
-// eslint-disable-next-line no-var
 var CrElementsToolbarV3Test = class extends CrElementsV3BrowserTest {
   /** @override */
   get browsePreload() {
diff --git a/chrome/test/data/webui/cr_elements/cr_elements_v3_focus_test.js b/chrome/test/data/webui/cr_elements/cr_elements_v3_focus_test.js
index c68cade..1bf93199 100644
--- a/chrome/test/data/webui/cr_elements/cr_elements_v3_focus_test.js
+++ b/chrome/test/data/webui/cr_elements/cr_elements_v3_focus_test.js
@@ -134,6 +134,19 @@
 });
 
 // eslint-disable-next-line no-var
+var CrElementsToolbarSearchFieldV3Test = class extends CrElementsV3FocusTest {
+  /** @override */
+  get browsePreload() {
+    return 'chrome://test?module=cr_elements/cr_toolbar_search_field_tests.m.js';
+  }
+};
+
+TEST_F('CrElementsToolbarSearchFieldV3Test', 'All', function() {
+  mocha.run();
+});
+
+
+// eslint-disable-next-line no-var
 var IronListFocusV3Test = class extends CrElementsV3FocusTest {
   /** @override */
   get browsePreload() {
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn
index fa6164f..27addd62 100644
--- a/chromecast/BUILD.gn
+++ b/chromecast/BUILD.gn
@@ -597,6 +597,7 @@
     "ENABLE_PLAYREADY=$enable_playready",
     "ENABLE_VIDEO_CAPTURE_SERVICE=$enable_video_capture_service",
     "ENABLE_VOLUME_TABLES_ACCESS=$enable_volume_tables_access",
+    "IS_ANDROID_APPLIANCE=$is_android_appliance",
     "IS_ANDROID_THINGS=$is_android_things",
     "IS_ANDROID_THINGS_NON_PUBLIC=$is_android_things_non_public",
     "IS_CAST_AUDIO_ONLY=$is_cast_audio_only",
diff --git a/chromecast/browser/cast_web_view_default.cc b/chromecast/browser/cast_web_view_default.cc
index f47c9a05..9d7abe4 100644
--- a/chromecast/browser/cast_web_view_default.cc
+++ b/chromecast/browser/cast_web_view_default.cc
@@ -110,9 +110,9 @@
   web_contents_->GetNativeView()->SetName(params.activity_id);
 #endif
 
-#if BUILDFLAG(IS_ANDROID_THINGS)
-  // Configure the ducking multiplier for AThings speakers. We don't want the
-  // Chromium MediaSession to duck since we are doing our own ducking.
+#if BUILDFLAG(IS_ANDROID_APPLIANCE)
+  // Configure the ducking multiplier for AThings-like speakers. We don't want
+  // the Chromium MediaSession to duck since we are doing our own ducking.
   constexpr double kDuckingMultiplier = 1.0;
   content::MediaSession::Get(web_contents_.get())
       ->SetDuckingVolumeMultiplier(kDuckingMultiplier);
diff --git a/chromeos/components/local_search_service/test_utils.cc b/chromeos/components/local_search_service/test_utils.cc
index 48c29f0..d01f9bd 100644
--- a/chromeos/components/local_search_service/test_utils.cc
+++ b/chromeos/components/local_search_service/test_utils.cc
@@ -4,6 +4,7 @@
 
 #include "chromeos/components/local_search_service/test_utils.h"
 
+#include <cmath>
 #include <map>
 #include <string>
 #include <utility>
diff --git a/chromeos/network/network_state_handler.cc b/chromeos/network/network_state_handler.cc
index d41b84e..b0c7106 100644
--- a/chromeos/network/network_state_handler.cc
+++ b/chromeos/network/network_state_handler.cc
@@ -343,8 +343,7 @@
 }
 
 void NetworkStateHandler::SetProhibitedTechnologies(
-    const std::vector<std::string>& prohibited_technologies,
-    const network_handler::ErrorCallback& error_callback) {
+    const std::vector<std::string>& prohibited_technologies) {
   // Make a copy of |prohibited_technologies| since the list may be edited
   // within this function.
   std::vector<std::string> prohibited_technologies_copy =
@@ -365,7 +364,7 @@
   }
 
   shill_property_handler_->SetProhibitedTechnologies(
-      prohibited_technologies_copy, error_callback);
+      prohibited_technologies_copy);
   // Signal Device/Technology state changed.
   NotifyDeviceListChanged();
 }
diff --git a/chromeos/network/network_state_handler.h b/chromeos/network/network_state_handler.h
index 89e07a5..517e978 100644
--- a/chromeos/network/network_state_handler.h
+++ b/chromeos/network/network_state_handler.h
@@ -137,8 +137,7 @@
   // values are the shill network technology identifiers. See also
   // chromeos::onc::Validator::ValidateGlobalNetworkConfiguration().
   void SetProhibitedTechnologies(
-      const std::vector<std::string>& prohibited_technologies,
-      const network_handler::ErrorCallback& error_callback);
+      const std::vector<std::string>& prohibited_technologies);
 
   // Finds and returns a device state by |device_path| or NULL if not found.
   const DeviceState* GetDeviceState(const std::string& device_path) const;
diff --git a/chromeos/network/network_state_handler_unittest.cc b/chromeos/network/network_state_handler_unittest.cc
index 2a1f5af..62042ef 100644
--- a/chromeos/network/network_state_handler_unittest.cc
+++ b/chromeos/network/network_state_handler_unittest.cc
@@ -838,7 +838,7 @@
 
   // Test SetProhibitedTechnologies() with a Tether network:
   network_state_handler_->SetProhibitedTechnologies(
-      std::vector<std::string>{kTypeTether}, network_handler::ErrorCallback());
+      std::vector<std::string>{kTypeTether});
   EXPECT_EQ(3u, test_observer_->device_list_changed_count());
   EXPECT_EQ(
       NetworkStateHandler::TECHNOLOGY_PROHIBITED,
diff --git a/chromeos/network/prohibited_technologies_handler.cc b/chromeos/network/prohibited_technologies_handler.cc
index 1e22cbe5..24ca9b80 100644
--- a/chromeos/network/prohibited_technologies_handler.cc
+++ b/chromeos/network/prohibited_technologies_handler.cc
@@ -38,8 +38,7 @@
   // Clear the list of prohibited network technologies. As a user logout always
   // triggers a browser process restart, Init() is always invoked to reallow any
   // network technology forbidden for the previous user.
-  network_state_handler_->SetProhibitedTechnologies(
-      std::vector<std::string>(), chromeos::network_handler::ErrorCallback());
+  network_state_handler_->SetProhibitedTechnologies(std::vector<std::string>());
 
   if (LoginState::IsInitialized())
     LoggedInStateChanged();
@@ -80,8 +79,7 @@
 
 void ProhibitedTechnologiesHandler::EnforceProhibitedTechnologies() {
   auto prohibited_technologies_ = GetCurrentlyProhibitedTechnologies();
-  network_state_handler_->SetProhibitedTechnologies(
-      prohibited_technologies_, network_handler::ErrorCallback());
+  network_state_handler_->SetProhibitedTechnologies(prohibited_technologies_);
   // Enable ethernet back as user doesn't have a place to enable it back
   // if user shuts down directly in a user session. As shill will persist
   // ProhibitedTechnologies which may include ethernet, making users can
diff --git a/chromeos/network/shill_property_handler.cc b/chromeos/network/shill_property_handler.cc
index 8a192d6..6b2b28f 100644
--- a/chromeos/network/shill_property_handler.cc
+++ b/chromeos/network/shill_property_handler.cc
@@ -187,8 +187,7 @@
 }
 
 void ShillPropertyHandler::SetProhibitedTechnologies(
-    const std::vector<std::string>& prohibited_technologies,
-    const network_handler::ErrorCallback& error_callback) {
+    const std::vector<std::string>& prohibited_technologies) {
   prohibited_technologies_.clear();
   prohibited_technologies_.insert(prohibited_technologies.begin(),
                                   prohibited_technologies.end());
@@ -201,7 +200,8 @@
     shill_manager_->DisableTechnology(
         technology, base::DoNothing(),
         base::BindOnce(&network_handler::ShillErrorCallbackFunction,
-                       "DisableTechnology Failed", technology, error_callback));
+                       "DisableTechnology Failed", technology,
+                       network_handler::ErrorCallback()));
   }
 
   // Send updated prohibited technology list to shill.
@@ -212,7 +212,7 @@
       "ProhibitedTechnologies", value, base::DoNothing(),
       base::BindOnce(&network_handler::ShillErrorCallbackFunction,
                      "SetTechnologiesProhibited Failed", prohibited_list,
-                     error_callback));
+                     network_handler::ErrorCallback()));
 }
 
 void ShillPropertyHandler::SetCheckPortalList(
diff --git a/chromeos/network/shill_property_handler.h b/chromeos/network/shill_property_handler.h
index 2481d57..266a0131 100644
--- a/chromeos/network/shill_property_handler.h
+++ b/chromeos/network/shill_property_handler.h
@@ -122,11 +122,8 @@
       const network_handler::ErrorCallback& error_callback);
 
   // Asynchronously sets the prohibited state for every network technology
-  // listed in |technologies|. Note: Modifies Manager state. Calls
-  // |error_callback| on failure.
-  void SetProhibitedTechnologies(
-      const std::vector<std::string>& technologies,
-      const network_handler::ErrorCallback& error_callback);
+  // listed in |technologies|. Note: Modifies Manager state.
+  void SetProhibitedTechnologies(const std::vector<std::string>& technologies);
 
   // Sets the list of devices on which portal check is enabled.
   void SetCheckPortalList(const std::string& check_portal_list);
diff --git a/chromeos/network/shill_property_handler_unittest.cc b/chromeos/network/shill_property_handler_unittest.cc
index 44726c1..425fee3 100644
--- a/chromeos/network/shill_property_handler_unittest.cc
+++ b/chromeos/network/shill_property_handler_unittest.cc
@@ -525,8 +525,7 @@
   prohibited_technologies.push_back(shill::kTypeEthernet);
   EXPECT_TRUE(
       shill_property_handler_->IsTechnologyEnabled(shill::kTypeEthernet));
-  shill_property_handler_->SetProhibitedTechnologies(
-      prohibited_technologies, network_handler::ErrorCallback());
+  shill_property_handler_->SetProhibitedTechnologies(prohibited_technologies);
   base::RunLoop().RunUntilIdle();
   // Disabled
   EXPECT_FALSE(
@@ -541,8 +540,7 @@
 
   // Can enable it back after policy changes
   prohibited_technologies.clear();
-  shill_property_handler_->SetProhibitedTechnologies(
-      prohibited_technologies, network_handler::ErrorCallback());
+  shill_property_handler_->SetProhibitedTechnologies(prohibited_technologies);
   shill_property_handler_->SetTechnologyEnabled(
       shill::kTypeEthernet, true, network_handler::ErrorCallback());
   base::RunLoop().RunUntilIdle();
diff --git a/components/arc/clipboard/arc_clipboard_bridge.cc b/components/arc/clipboard/arc_clipboard_bridge.cc
index faea56c..ce9fc07 100644
--- a/components/arc/clipboard/arc_clipboard_bridge.cc
+++ b/components/arc/clipboard/arc_clipboard_bridge.cc
@@ -48,8 +48,8 @@
   std::string url;
   uint32_t fragment_start, fragment_end;
 
-  clipboard->ReadHTML(ui::ClipboardBuffer::kCopyPaste, &markup16, &url,
-                      &fragment_start, &fragment_end);
+  clipboard->ReadHTML(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &markup16, &url, &fragment_start, &fragment_end);
 
   std::string text(base::UTF16ToUTF8(
       markup16.substr(fragment_start, fragment_end - fragment_start)));
@@ -71,9 +71,10 @@
 
   // Both Bookmark and AsciiText are represented by text/plain. If both are
   // present, only use Bookmark.
-  clipboard->ReadBookmark(&title, &text);
+  clipboard->ReadBookmark(/* data_dst = */ nullptr, &title, &text);
   if (text.size() == 0)
-    clipboard->ReadAsciiText(ui::ClipboardBuffer::kCopyPaste, &text);
+    clipboard->ReadAsciiText(ui::ClipboardBuffer::kCopyPaste,
+                             /* data_dst = */ nullptr, &text);
 
   return mojom::ClipRepresentation::New(mime_type,
                                         mojom::ClipValue::NewText(text));
@@ -83,7 +84,8 @@
   DCHECK(clipboard);
 
   std::vector<base::string16> mime_types;
-  clipboard->ReadAvailableTypes(ui::ClipboardBuffer::kCopyPaste, &mime_types);
+  clipboard->ReadAvailableTypes(ui::ClipboardBuffer::kCopyPaste,
+                                /* data_dst = */ nullptr, &mime_types);
 
   mojom::ClipDataPtr clip_data(mojom::ClipData::New());
 
diff --git a/components/arc/clipboard/arc_clipboard_bridge_unittest.cc b/components/arc/clipboard/arc_clipboard_bridge_unittest.cc
index 7a7563f..a245290 100644
--- a/components/arc/clipboard/arc_clipboard_bridge_unittest.cc
+++ b/components/arc/clipboard/arc_clipboard_bridge_unittest.cc
@@ -121,12 +121,13 @@
 
   std::vector<base::string16> mime_types;
   GetClipboard()->ReadAvailableTypes(ui::ClipboardBuffer::kCopyPaste,
-                                     &mime_types);
+                                     /* data_dst = */ nullptr, &mime_types);
   ASSERT_EQ(1u, mime_types.size());
   EXPECT_EQ(ui::kMimeTypeText, base::UTF16ToUTF8(mime_types[0]));
 
   base::string16 result;
-  GetClipboard()->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
+  GetClipboard()->ReadText(ui::ClipboardBuffer::kCopyPaste,
+                           /* data_dst = */ nullptr, &result);
   EXPECT_EQ(kSampleText, base::UTF16ToUTF8(result));
 }
 
@@ -137,14 +138,15 @@
 
   std::vector<base::string16> mime_types;
   GetClipboard()->ReadAvailableTypes(ui::ClipboardBuffer::kCopyPaste,
-                                     &mime_types);
+                                     /* data_dst = */ nullptr, &mime_types);
   ASSERT_EQ(1u, mime_types.size());
   EXPECT_EQ(ui::kMimeTypeHTML, base::UTF16ToUTF8(mime_types[0]));
 
   base::string16 markup16;
   std::string url;
   uint32_t fragment_start, fragment_end;
-  GetClipboard()->ReadHTML(ui::ClipboardBuffer::kCopyPaste, &markup16, &url,
+  GetClipboard()->ReadHTML(ui::ClipboardBuffer::kCopyPaste,
+                           /* data_dst = */ nullptr, &markup16, &url,
                            &fragment_start, &fragment_end);
   base::string16 result =
       markup16.substr(fragment_start, fragment_end - fragment_start);
diff --git a/components/autofill/core/browser/autofill_browser_util.cc b/components/autofill/core/browser/autofill_browser_util.cc
index e2efefb3..287d2af 100644
--- a/components/autofill/core/browser/autofill_browser_util.cc
+++ b/components/autofill/core/browser/autofill_browser_util.cc
@@ -5,6 +5,18 @@
 #include "components/autofill/core/browser/autofill_browser_util.h"
 
 #include "components/autofill/core/browser/autofill_client.h"
+#include "services/network/public/cpp/is_potentially_trustworthy.h"
+
+namespace {
+// Matches the blink check for mixed content.
+bool IsInsecureFormAction(const GURL& action_url) {
+  if (action_url.SchemeIs(url::kBlobScheme) ||
+      action_url.SchemeIs(url::kFileSystemScheme))
+    return false;
+  return !network::IsOriginPotentiallyTrustworthy(
+      url::Origin::Create(action_url));
+}
+}  // namespace
 
 namespace autofill {
 
@@ -13,6 +25,11 @@
          (form.action.is_valid() && form.action.SchemeIs("http"));
 }
 
+bool IsFormMixedContent(AutofillClient* client, const FormData& form) {
+  return client->IsContextSecure() &&
+         (form.action.is_valid() && IsInsecureFormAction(form.action));
+}
+
 bool ShouldAllowCreditCardFallbacks(AutofillClient* client,
                                     const FormData& form) {
   // Skip the form check if there wasn't a form yet:
diff --git a/components/autofill/core/browser/autofill_browser_util.h b/components/autofill/core/browser/autofill_browser_util.h
index f684ef3e..c03cbe8f 100644
--- a/components/autofill/core/browser/autofill_browser_util.h
+++ b/components/autofill/core/browser/autofill_browser_util.h
@@ -16,6 +16,10 @@
 // Checks whether a given form is considered insecure (by origin or action).
 bool IsFormOrClientNonSecure(AutofillClient* client, const FormData& form);
 
+// Checks whether a given form is considered mixed content. A form is mixed
+// content if is displayed on a secure context, but submits to an insecure one.
+bool IsFormMixedContent(AutofillClient* client, const FormData& form);
+
 // Returns true if context provided by the client and the given form are
 // considered "secure enough" to manually fill credit card data.
 bool ShouldAllowCreditCardFallbacks(AutofillClient* client,
diff --git a/components/autofill/core/browser/autofill_external_delegate.cc b/components/autofill/core/browser/autofill_external_delegate.cc
index dae2198e..7acf8d1 100644
--- a/components/autofill/core/browser/autofill_external_delegate.cc
+++ b/components/autofill/core/browser/autofill_external_delegate.cc
@@ -45,7 +45,9 @@
 // Returns true if the suggestion entry is an Autofill warning message.
 // Warning messages should display on top of suggestion list.
 bool IsAutofillWarningEntry(int frontend_id) {
-  return frontend_id == POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE;
+  return frontend_id ==
+             POPUP_ITEM_ID_INSECURE_CONTEXT_PAYMENT_DISABLED_MESSAGE ||
+         frontend_id == POPUP_ITEM_ID_MIXED_FORM_MESSAGE;
 }
 
 }  // namespace
@@ -129,8 +131,10 @@
     // useful to the user and no need  hide them. In this case,
     // ApplyAutofillOptions() should have added a "Clear form" option instead.
     if (!query_field_.is_autofilled) {
-      if (!suggestions.empty() && (GetPopupType() == PopupType::kAddresses ||
-                                   GetPopupType() == PopupType::kUnspecified)) {
+      if (!suggestions.empty() &&
+          (GetPopupType() == PopupType::kAddresses ||
+           GetPopupType() == PopupType::kUnspecified) &&
+          suggestions[0].frontend_id != POPUP_ITEM_ID_MIXED_FORM_MESSAGE) {
         suggestions.push_back(Suggestion(
             l10n_util::GetStringUTF16(IDS_AUTOFILL_HIDE_SUGGESTIONS)));
         suggestions.back().frontend_id =
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index a6d731c..bf13cc8fa 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -2550,6 +2550,20 @@
     }
   }
 
+  // If the feature is enabled and this is a mixed content form, we show a
+  // warning message and don't offer autofill. The warning is shown even if
+  // there are no autofill suggestions available.
+  if (IsFormMixedContent(client_, form) &&
+      base::FeatureList::IsEnabled(
+          features::kAutofillPreventMixedFormsFilling)) {
+    suggestions->clear();
+    Suggestion warning_suggestion(
+        l10n_util::GetStringUTF16(IDS_AUTOFILL_WARNING_MIXED_FORM));
+    warning_suggestion.frontend_id = POPUP_ITEM_ID_MIXED_FORM_MESSAGE;
+    suggestions->assign(1, warning_suggestion);
+    return;
+  }
+
   context->is_context_secure = !IsFormNonSecure(form);
 
   // TODO(rogerm): Early exit here on !driver()->RendererIsAvailable()?
diff --git a/components/autofill/core/browser/autofill_manager_unittest.cc b/components/autofill/core/browser/autofill_manager_unittest.cc
index 88037ee..5e69618 100644
--- a/components/autofill/core/browser/autofill_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_manager_unittest.cc
@@ -8301,6 +8301,41 @@
   EXPECT_EQ(0, personal_data_.num_times_save_upi_id_called());
 }
 
+// AutofillManagerTest with kAutofillDisabledMixedForms feature enabled.
+class AutofillManagerTestWithMixedForms : public AutofillManagerTest {
+ protected:
+  AutofillManagerTestWithMixedForms() = default;
+  ~AutofillManagerTestWithMixedForms() override = default;
+
+  void SetUp() override {
+    AutofillManagerTest::SetUp();
+
+    scoped_feature_list_.InitAndEnableFeature(
+        features::kAutofillPreventMixedFormsFilling);
+  }
+};
+
+// Test that if a form is mixed content we show a warning instead of any
+// suggestions.
+TEST_F(AutofillManagerTestWithMixedForms, GetSuggestions_MixedForm) {
+  // Set up our form data.
+  FormData form;
+  form.name = ASCIIToUTF16("MyForm");
+  form.url = GURL("https://myform.com/form.html");
+  form.action = GURL("http://myform.com/submit.html");
+  FormFieldData field;
+  test::CreateTestFormField("Name on Card", "nameoncard", "", "text", &field);
+  form.fields.push_back(field);
+
+  GetAutofillSuggestions(form, form.fields[0]);
+
+  // Test that we sent the right values to the external delegate.
+  CheckSuggestions(
+      kDefaultPageID,
+      Suggestion(l10n_util::GetStringUTF8(IDS_AUTOFILL_WARNING_MIXED_FORM), "",
+                 "", POPUP_ITEM_ID_MIXED_FORM_MESSAGE));
+}
+
 // Desktop only tests.
 #if !defined(OS_ANDROID) && !defined(OS_IOS)
 class AutofillManagerTestForVirtualCardOption : public AutofillManagerTest {
diff --git a/components/autofill/core/browser/ui/popup_item_ids.h b/components/autofill/core/browser/ui/popup_item_ids.h
index f975bc36..c16f227 100644
--- a/components/autofill/core/browser/ui/popup_item_ids.h
+++ b/components/autofill/core/browser/ui/popup_item_ids.h
@@ -35,6 +35,7 @@
   POPUP_ITEM_ID_ACCOUNT_STORAGE_USERNAME_ENTRY = -23,
   POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_RE_SIGNIN = -24,
   POPUP_ITEM_ID_PASSWORD_ACCOUNT_STORAGE_EMPTY = -25,
+  POPUP_ITEM_ID_MIXED_FORM_MESSAGE = -26
 };
 
 }  // namespace autofill
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc
index ae61ea6..bb0ec78 100644
--- a/components/autofill/core/common/autofill_features.cc
+++ b/components/autofill/core/common/autofill_features.cc
@@ -158,6 +158,11 @@
 const base::Feature kAutofillPreferServerNamePredictions{
     "AutofillPreferServerNamePredictions", base::FEATURE_DISABLED_BY_DEFAULT};
 
+// If feature is enabled, autofill will be disabled for mixed forms (forms on
+// HTTPS sites that submit over HTTP).
+const base::Feature kAutofillPreventMixedFormsFilling{
+    "AutofillPreventMixedFormsFilling", base::FEATURE_DISABLED_BY_DEFAULT};
+
 const base::Feature kAutofillProfileClientValidation{
     "AutofillProfileClientValidation", base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h
index 595d628..d249880 100644
--- a/components/autofill/core/common/autofill_features.h
+++ b/components/autofill/core/common/autofill_features.h
@@ -47,6 +47,7 @@
 extern const base::Feature kAutofillOffNoServerData;
 extern const base::Feature kAutofillOverrideWithRaterConsensus;
 extern const base::Feature kAutofillPreferServerNamePredictions;
+extern const base::Feature kAutofillPreventMixedFormsFilling;
 extern const base::Feature kAutofillProfileClientValidation;
 extern const base::Feature kAutofillProfileImportFromUnfocusableFields;
 extern const base::Feature kAutofillProfileImportFromUnifiedSection;
diff --git a/components/autofill_strings.grdp b/components/autofill_strings.grdp
index d981f4e..cd1ca15 100644
--- a/components/autofill_strings.grdp
+++ b/components/autofill_strings.grdp
@@ -21,6 +21,9 @@
   <message name="IDS_AUTOFILL_WARNING_INSECURE_CONNECTION" desc="Warning text to show when credit card autofill is disabled because the website is not using a secure connection.">
     Automatic credit card filling is disabled because this form does not use a secure connection.
   </message>
+  <message name="IDS_AUTOFILL_WARNING_MIXED_FORM" desc="Warning text shown when autofill is disabled due to a form on a secure site being submitted over an insecure connection.">
+    This form is submitted over an insecure connection. Automatic filling is disabled.
+  </message>
   <message name="IDS_AUTOFILL_CREDIT_CARD_SIGNIN_PROMO" desc="Promo text shown alongside credit card suggestions to get people to sign in.">
     To use cards from your Google Account, sign in to Chrome
   </message>
diff --git a/components/autofill_strings_grdp/IDS_AUTOFILL_WARNING_MIXED_FORM.png.sha1 b/components/autofill_strings_grdp/IDS_AUTOFILL_WARNING_MIXED_FORM.png.sha1
new file mode 100644
index 0000000..5b6d382
--- /dev/null
+++ b/components/autofill_strings_grdp/IDS_AUTOFILL_WARNING_MIXED_FORM.png.sha1
@@ -0,0 +1 @@
+a7a5f360119ebc1a0c1c01983ead9f5decba558f
\ No newline at end of file
diff --git a/components/bookmarks/browser/bookmark_node_data.cc b/components/bookmarks/browser/bookmark_node_data.cc
index 91cd83f0..c92a6453 100644
--- a/components/bookmarks/browser/bookmark_node_data.cc
+++ b/components/bookmarks/browser/bookmark_node_data.cc
@@ -140,7 +140,7 @@
 bool BookmarkNodeData::ClipboardContainsBookmarks() {
   return ui::Clipboard::GetForCurrentThread()->IsFormatAvailable(
       ui::ClipboardFormatType::GetType(kClipboardFormatString),
-      ui::ClipboardBuffer::kCopyPaste);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr);
 }
 #endif
 
@@ -222,7 +222,7 @@
   std::string data;
   ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
   clipboard->ReadData(ui::ClipboardFormatType::GetType(kClipboardFormatString),
-                      &data);
+                      /* data_dst = */ nullptr, &data);
 
   if (!data.empty()) {
     base::Pickle pickle(data.data(), static_cast<int>(data.size()));
@@ -232,7 +232,7 @@
 
   base::string16 title;
   std::string url;
-  clipboard->ReadBookmark(&title, &url);
+  clipboard->ReadBookmark(/* data_dst = */ nullptr, &title, &url);
   if (!url.empty()) {
     Element element;
     element.is_url = true;
diff --git a/components/bookmarks/browser/bookmark_node_data_unittest.cc b/components/bookmarks/browser/bookmark_node_data_unittest.cc
index b68b67b1..501ec35 100644
--- a/components/bookmarks/browser/bookmark_node_data_unittest.cc
+++ b/components/bookmarks/browser/bookmark_node_data_unittest.cc
@@ -289,7 +289,8 @@
 
   // Now read the data back in.
   base::string16 clipboard_result;
-  clipboard().ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_result);
+  clipboard().ReadText(ui::ClipboardBuffer::kCopyPaste,
+                       /* data_dst = */ nullptr, &clipboard_result);
   EXPECT_EQ(base::UTF8ToUTF16(url.spec()), clipboard_result);
 }
 
@@ -324,7 +325,8 @@
   combined_text = base::UTF8ToUTF16(url.spec()) + new_line
     + base::UTF8ToUTF16(url2.spec());
   base::string16 clipboard_result;
-  clipboard().ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_result);
+  clipboard().ReadText(ui::ClipboardBuffer::kCopyPaste,
+                       /* data_dst = */ nullptr, &clipboard_result);
   EXPECT_EQ(combined_text, clipboard_result);
 }
 
@@ -345,7 +347,8 @@
 
   // Now read the data back in.
   base::string16 clipboard_result;
-  clipboard().ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_result);
+  clipboard().ReadText(ui::ClipboardBuffer::kCopyPaste,
+                       /* data_dst = */ nullptr, &clipboard_result);
   EXPECT_EQ(base::ASCIIToUTF16("g1"), clipboard_result);
 }
 
@@ -364,7 +367,8 @@
 
   // Now read the data back in.
   base::string16 clipboard_result;
-  clipboard().ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_result);
+  clipboard().ReadText(ui::ClipboardBuffer::kCopyPaste,
+                       /* data_dst = */ nullptr, &clipboard_result);
   EXPECT_EQ(base::ASCIIToUTF16("g1"), clipboard_result);
 }
 
@@ -394,7 +398,8 @@
   base::string16 folder_title = ASCIIToUTF16("g1");
   combined_text = base::ASCIIToUTF16(url.spec()) + new_line + folder_title;
   base::string16 clipboard_result;
-  clipboard().ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_result);
+  clipboard().ReadText(ui::ClipboardBuffer::kCopyPaste,
+                       /* data_dst = */ nullptr, &clipboard_result);
   EXPECT_EQ(combined_text, clipboard_result);
 }
 
diff --git a/components/bookmarks/browser/bookmark_utils.cc b/components/bookmarks/browser/bookmark_utils.cc
index 553f77c..c9fa2ab 100644
--- a/components/bookmarks/browser/bookmark_utils.cc
+++ b/components/bookmarks/browser/bookmark_utils.cc
@@ -146,7 +146,7 @@
   base::string16 url_text;
 #if !defined(OS_IOS)
   ui::Clipboard::GetForCurrentThread()->ReadText(
-      ui::ClipboardBuffer::kCopyPaste, &url_text);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &url_text);
 #endif
   return GURL(url_text);
 }
diff --git a/components/browser_ui/widget/android/java/res/values/dimens.xml b/components/browser_ui/widget/android/java/res/values/dimens.xml
index 09bb07b8..6c43377 100644
--- a/components/browser_ui/widget/android/java/res/values/dimens.xml
+++ b/components/browser_ui/widget/android/java/res/values/dimens.xml
@@ -3,7 +3,7 @@
      Use of this source code is governed by a BSD-style license that can be
      found in the LICENSE file. -->
 
-<resources>
+<resources xmlns:tools="http://schemas.android.com/tools">
     <!-- Miscellaneous -->
     <dimen name="action_bar_shadow_height">10dp</dimen>
     <dimen name="card_padding">16dp</dimen>
@@ -29,6 +29,9 @@
 
     <!-- RadioButtonWithDescriptionAndAuxButton -->
     <dimen name="radio_button_with_description_and_aux_button_spacing">10dp</dimen>
+    <!-- The total width of expand_arrow_with_separator.xml, not used on WebView. -->
+    <dimen name="radio_button_with_description_and_aux_button_aux_button_length"
+        tools:ignore="UnusedResources">61dp</dimen>
 
     <!-- RadioButton(WithDescription)Layout dimensions -->
     <dimen name="default_vertical_margin_between_items">8dp</dimen>
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/InsetObserverView.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/InsetObserverView.java
index f9f8d34..1a8d090c 100644
--- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/InsetObserverView.java
+++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/InsetObserverView.java
@@ -8,15 +8,12 @@
 import android.content.Context;
 import android.graphics.Rect;
 import android.os.Build;
+import android.view.DisplayCutout;
 import android.view.View;
 import android.view.WindowInsets;
 
-import androidx.annotation.VisibleForTesting;
-
 import org.chromium.base.ObserverList;
 
-import java.lang.reflect.Method;
-
 /**
  * The purpose of this view is to store the system window insets (OSK, status bar) for
  * later use.
@@ -52,10 +49,8 @@
     public static InsetObserverView create(Context context) {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
             return new InsetObserverViewApi28(context);
-        } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
-            return new InsetObserverView(context);
         }
-        return new InsetObserverViewApi21(context);
+        return new InsetObserverView(context);
     }
 
     /**
@@ -111,14 +106,11 @@
         mObservers.removeObserver(observer);
     }
 
-    @SuppressWarnings("deprecation")
     @Override
-    protected boolean fitSystemWindows(Rect insets) {
-        // For Lollipop and above, onApplyWindowInsets will set the insets.
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
-            onInsetChanged(insets.left, insets.top, insets.right, insets.bottom);
-        }
-        return false;
+    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+        onInsetChanged(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
+                insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
+        return insets;
     }
 
     /**
@@ -142,28 +134,8 @@
         }
     }
 
-    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
-    protected static class InsetObserverViewApi21 extends InsetObserverView {
-        /**
-         * Creates an instance of {@link InsetObserverView} for Android versions L and above.
-         * @param context The Context to create this {@link InsetObserverView} in.
-         */
-        InsetObserverViewApi21(Context context) {
-            super(context);
-        }
-
-        @Override
-        public WindowInsets onApplyWindowInsets(WindowInsets insets) {
-            onInsetChanged(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
-                    insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
-            return insets;
-        }
-    }
-
-    // TODO(beccahughes): Remove reflection and update target API when P-SDK is landed.
-    @TargetApi(Build.VERSION_CODES.O)
-    @VisibleForTesting
-    protected static class InsetObserverViewApi28 extends InsetObserverViewApi21 {
+    @TargetApi(Build.VERSION_CODES.P)
+    private static class InsetObserverViewApi28 extends InsetObserverView {
         private Rect mCurrentSafeArea = new Rect();
 
         /**
@@ -185,13 +157,19 @@
          * @param insets The WindowInsets containing the safe area.
          */
         private void setCurrentSafeAreaFromInsets(WindowInsets insets) {
-            Object displayCutout = extractDisplayCutout(insets);
+            DisplayCutout displayCutout = insets.getDisplayCutout();
 
-            // Extract the safe area values.
-            int left = extractSafeInset(displayCutout, "Left");
-            int top = extractSafeInset(displayCutout, "Top");
-            int right = extractSafeInset(displayCutout, "Right");
-            int bottom = extractSafeInset(displayCutout, "Bottom");
+            int left = 0;
+            int top = 0;
+            int right = 0;
+            int bottom = 0;
+
+            if (displayCutout != null) {
+                left = displayCutout.getSafeInsetLeft();
+                top = displayCutout.getSafeInsetTop();
+                right = displayCutout.getSafeInsetRight();
+                bottom = displayCutout.getSafeInsetBottom();
+            }
 
             // If the safe area has not changed then we should stop now.
             if (mCurrentSafeArea.left == left && mCurrentSafeArea.top == top
@@ -205,37 +183,5 @@
                 mObserver.onSafeAreaChanged(mCurrentSafeArea);
             }
         }
-
-        /**
-         * Extracts a safe inset value from an Android P+ DisplayCutout.
-         * @param displayCutout The Android P+ DisplayCutout object.
-         * @param name The name of the inset to extract.
-         * @return The inset value as an integer or zero.
-         */
-        private int extractSafeInset(Object displayCutout, String name) {
-            try {
-                Method method = displayCutout.getClass().getMethod("getSafeInset" + name);
-                return (int) method.invoke(displayCutout);
-            } catch (Exception ex) {
-                // API is not available.
-                return 0;
-            }
-        }
-
-        /**
-         * Extracts an Android P+ DisplayCutout from {@link WindowInsets}.
-         * @param insets The WindowInsets to extract the cutout from.
-         * @return The DisplayCutout object or null.
-         */
-        @VisibleForTesting
-        protected Object extractDisplayCutout(WindowInsets insets) {
-            try {
-                Method method = insets.getClass().getMethod("getDisplayCutout");
-                return method.invoke(insets);
-            } catch (Exception ex) {
-                // API is not available.
-                return null;
-            }
-        }
     }
 }
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/InsetObserverViewTest.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/InsetObserverViewTest.java
index f432e57c..5ce4a20 100644
--- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/InsetObserverViewTest.java
+++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/InsetObserverViewTest.java
@@ -3,15 +3,18 @@
 // found in the LICENSE file.
 
 package org.chromium.components.browser_ui.widget;
-
 import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
+import android.annotation.TargetApi;
 import android.app.Activity;
-import android.content.Context;
 import android.graphics.Rect;
+import android.os.Build;
+import android.view.DisplayCutout;
 import android.view.WindowInsets;
 import android.widget.LinearLayout;
 
@@ -39,44 +42,6 @@
     /** The rect values if there is no cutout. */
     private static final Rect NO_CUTOUT_RECT = new Rect(0, 0, 0, 0);
 
-    /** Mock Android P+ Display Cutout class. */
-    private static class DisplayCutout {
-        public int getSafeInsetLeft() {
-            return 1;
-        }
-
-        public int getSafeInsetTop() {
-            return 1;
-        }
-
-        public int getSafeInsetRight() {
-            return 1;
-        }
-
-        public int getSafeInsetBottom() {
-            return 1;
-        }
-    }
-
-    /** This is a {@InsetObserverView} that will use a fake display cutout. */
-    private static class TestInsetObserverView extends InsetObserverView.InsetObserverViewApi28 {
-        private Object mDisplayCutout;
-
-        TestInsetObserverView(Context context, Object displayCutout) {
-            super(context);
-            mDisplayCutout = displayCutout;
-        }
-
-        @Override
-        protected Object extractDisplayCutout(WindowInsets insets) {
-            return mDisplayCutout;
-        }
-
-        public void setDisplayCutout(DisplayCutout displayCutout) {
-            mDisplayCutout = displayCutout;
-        }
-    }
-
     @Mock
     private InsetObserverView.WindowInsetObserver mObserver;
 
@@ -85,10 +50,16 @@
 
     private Activity mActivity;
 
-    private TestInsetObserverView mView;
+    private InsetObserverView mView;
 
     private LinearLayout mContentView;
 
+    @TargetApi(Build.VERSION_CODES.P)
+    private void setCutout(boolean hasCutout) {
+        DisplayCutout cutout = hasCutout ? new DisplayCutout(new Rect(1, 1, 1, 1), null) : null;
+        doReturn(cutout).when(mInsets).getDisplayCutout();
+    }
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -96,15 +67,37 @@
         mActivity = Robolectric.buildActivity(Activity.class).setup().get();
         mContentView = new LinearLayout(mActivity);
         mActivity.setContentView(mContentView);
+
+        mView = InsetObserverView.create(mActivity);
+        mView.addObserver(mObserver);
     }
 
-    /** Test that applying new insets does not notify the observer.. */
+    /** Test that applying new insets notifies observers. */
     @Test
     @SmallTest
-    public void applyInsets() {
-        mView = new TestInsetObserverView(mActivity, null);
-        mView.addObserver(mObserver);
+    public void applyInsets_NotifiesObservers() {
+        doReturn(1).when(mInsets).getSystemWindowInsetLeft();
+        doReturn(1).when(mInsets).getSystemWindowInsetTop();
+        doReturn(1).when(mInsets).getSystemWindowInsetRight();
+        doReturn(1).when(mInsets).getSystemWindowInsetBottom();
+        mView.onApplyWindowInsets(mInsets);
+        verify(mObserver, times(1)).onInsetChanged(1, 1, 1, 1);
 
+        // Apply the insets a second time; the observer should not be notified.
+        mView.onApplyWindowInsets(mInsets);
+        verify(mObserver, times(1)).onInsetChanged(1, 1, 1, 1);
+
+        doReturn(2).when(mInsets).getSystemWindowInsetBottom();
+        mView.onApplyWindowInsets(mInsets);
+        verify(mObserver).onInsetChanged(1, 1, 1, 2);
+    }
+
+    /** Test that applying new insets does not notify the observer. */
+    @Test
+    @SmallTest
+    @TargetApi(Build.VERSION_CODES.P)
+    public void applyInsets() {
+        setCutout(false);
         mView.onApplyWindowInsets(mInsets);
         verify(mObserver, never()).onSafeAreaChanged(any());
     }
@@ -112,10 +105,9 @@
     /** Test that applying new insets with a cutout notifies the observer. */
     @Test
     @SmallTest
+    @TargetApi(Build.VERSION_CODES.P)
     public void applyInsets_WithCutout() {
-        mView = new TestInsetObserverView(mActivity, new DisplayCutout());
-        mView.addObserver(mObserver);
-
+        setCutout(true);
         mView.onApplyWindowInsets(mInsets);
         verify(mObserver).onSafeAreaChanged(DISPLAY_CUTOUT_RECT);
     }
@@ -123,15 +115,14 @@
     /** Test applying new insets with a cutout and then remove the cutout. */
     @Test
     @SmallTest
+    @TargetApi(Build.VERSION_CODES.P)
     public void applyInsets_WithCutout_WithoutCutout() {
-        mView = new TestInsetObserverView(mActivity, new DisplayCutout());
-        mView.addObserver(mObserver);
-
+        setCutout(true);
         mView.onApplyWindowInsets(mInsets);
         verify(mObserver).onSafeAreaChanged(DISPLAY_CUTOUT_RECT);
 
         reset(mObserver);
-        mView.setDisplayCutout(null);
+        setCutout(false);
         mView.onApplyWindowInsets(mInsets);
         verify(mObserver).onSafeAreaChanged(NO_CUTOUT_RECT);
     }
@@ -139,16 +130,20 @@
     /** Test that applying new insets with a cutout but no observer is a no-op. */
     @Test
     @SmallTest
+    @TargetApi(Build.VERSION_CODES.P)
     public void applyInsets_WithCutout_NoListener() {
-        mView = new TestInsetObserverView(mActivity, new DisplayCutout());
+        setCutout(true);
+        mView.removeObserver(mObserver);
         mView.onApplyWindowInsets(mInsets);
     }
 
     /** Test that applying new insets with no observer is a no-op. */
     @Test
     @SmallTest
+    @TargetApi(Build.VERSION_CODES.P)
     public void applyInsets_NoListener() {
-        mView = new TestInsetObserverView(mActivity, null);
+        setCutout(false);
+        mView.removeObserver(mObserver);
         mView.onApplyWindowInsets(mInsets);
     }
 }
diff --git a/components/exo/data_offer.cc b/components/exo/data_offer.cc
index 8ec119a..cb558f5 100644
--- a/components/exo/data_offer.cc
+++ b/components/exo/data_offer.cc
@@ -123,7 +123,7 @@
 void ReadTextFromClipboard(const std::string& charset, base::ScopedFD fd) {
   base::string16 text;
   ui::Clipboard::GetForCurrentThread()->ReadText(
-      ui::ClipboardBuffer::kCopyPaste, &text);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &text);
   WriteFileDescriptor(std::move(fd), EncodeAsRefCountedString(text, charset));
 }
 
@@ -132,13 +132,15 @@
   std::string url;
   uint32_t start, end;
   ui::Clipboard::GetForCurrentThread()->ReadHTML(
-      ui::ClipboardBuffer::kCopyPaste, &text, &url, &start, &end);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &text, &url,
+      &start, &end);
   WriteFileDescriptor(std::move(fd), EncodeAsRefCountedString(text, charset));
 }
 
 void ReadRTFFromClipboard(base::ScopedFD fd) {
   std::string text;
   ui::Clipboard::GetForCurrentThread()->ReadRTF(ui::ClipboardBuffer::kCopyPaste,
+                                                /* data_dst = */ nullptr,
                                                 &text);
   WriteFileDescriptor(std::move(fd), base::RefCountedString::TakeString(&text));
 }
@@ -166,6 +168,7 @@
 void ReadPNGFromClipboard(base::ScopedFD fd) {
   ui::Clipboard::GetForCurrentThread()->ReadImage(
       ui::ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr,
       base::BindOnce(&OnReceivePNGFromClipboard, std::move(fd)));
 }
 
@@ -314,7 +317,8 @@
                                  const ui::Clipboard& data) {
   DCHECK_EQ(0u, data_.size());
   if (data.IsFormatAvailable(ui::ClipboardFormatType::GetPlainTextType(),
-                             ui::ClipboardBuffer::kCopyPaste)) {
+                             ui::ClipboardBuffer::kCopyPaste,
+                             /* data_dst = */ nullptr)) {
     auto utf8_callback =
         base::BindRepeating(&ReadTextFromClipboard, std::string(kUTF8));
     delegate_->OnOffer(std::string(kTextMimeTypeUtf8));
@@ -327,7 +331,8 @@
         base::BindRepeating(&ReadTextFromClipboard, std::string(kUTF16)));
   }
   if (data.IsFormatAvailable(ui::ClipboardFormatType::GetHtmlType(),
-                             ui::ClipboardBuffer::kCopyPaste)) {
+                             ui::ClipboardBuffer::kCopyPaste,
+                             /* data_dst = */ nullptr)) {
     delegate_->OnOffer(std::string(kTextHtmlMimeTypeUtf8));
     data_callbacks_.emplace(
         std::string(kTextHtmlMimeTypeUtf8),
@@ -338,13 +343,15 @@
         base::BindRepeating(&ReadHTMLFromClipboard, std::string(kUTF16)));
   }
   if (data.IsFormatAvailable(ui::ClipboardFormatType::GetRtfType(),
-                             ui::ClipboardBuffer::kCopyPaste)) {
+                             ui::ClipboardBuffer::kCopyPaste,
+                             /* data_dst = */ nullptr)) {
     delegate_->OnOffer(std::string(kTextRtfMimeType));
     data_callbacks_.emplace(std::string(kTextRtfMimeType),
                             base::BindRepeating(&ReadRTFFromClipboard));
   }
   if (data.IsFormatAvailable(ui::ClipboardFormatType::GetBitmapType(),
-                             ui::ClipboardBuffer::kCopyPaste)) {
+                             ui::ClipboardBuffer::kCopyPaste,
+                             /* data_dst = */ nullptr)) {
     delegate_->OnOffer(std::string(kImagePngMimeType));
     data_callbacks_.emplace(std::string(kImagePngMimeType),
                             base::BindRepeating(&ReadPNGFromClipboard));
diff --git a/components/exo/seat_unittest.cc b/components/exo/seat_unittest.cc
index 2218f1d..ac490f0 100644
--- a/components/exo/seat_unittest.cc
+++ b/components/exo/seat_unittest.cc
@@ -109,7 +109,7 @@
 
   std::string clipboard;
   ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
-      ui::ClipboardBuffer::kCopyPaste, &clipboard);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &clipboard);
 
   EXPECT_EQ(clipboard, std::string("TestData"));
 }
@@ -137,13 +137,14 @@
 
   base::string16 clipboard;
   ui::Clipboard::GetForCurrentThread()->ReadText(
-      ui::ClipboardBuffer::kCopyPaste, &clipboard);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &clipboard);
   EXPECT_EQ(clipboard, converted_data);
 
   std::string url;
   uint32_t start, end;
   ui::Clipboard::GetForCurrentThread()->ReadHTML(
-      ui::ClipboardBuffer::kCopyPaste, &clipboard, &url, &start, &end);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &clipboard,
+      &url, &start, &end);
   EXPECT_EQ(clipboard, converted_data);
 }
 
@@ -169,7 +170,7 @@
 
   base::string16 clipboard;
   ui::Clipboard::GetForCurrentThread()->ReadText(
-      ui::ClipboardBuffer::kCopyPaste, &clipboard);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &clipboard);
   EXPECT_EQ(clipboard, converted_data);
 }
 
@@ -198,13 +199,14 @@
 
   base::string16 clipboard;
   ui::Clipboard::GetForCurrentThread()->ReadText(
-      ui::ClipboardBuffer::kCopyPaste, &clipboard);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &clipboard);
   EXPECT_EQ(clipboard, converted_data);
 
   std::string url;
   uint32_t start, end;
   ui::Clipboard::GetForCurrentThread()->ReadHTML(
-      ui::ClipboardBuffer::kCopyPaste, &clipboard, &url, &start, &end);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &clipboard,
+      &url, &start, &end);
   EXPECT_EQ(clipboard, converted_data);
 }
 
@@ -233,13 +235,14 @@
 
   base::string16 clipboard;
   ui::Clipboard::GetForCurrentThread()->ReadText(
-      ui::ClipboardBuffer::kCopyPaste, &clipboard);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &clipboard);
   EXPECT_EQ(clipboard, converted_data);
 
   std::string url;
   uint32_t start, end;
   ui::Clipboard::GetForCurrentThread()->ReadHTML(
-      ui::ClipboardBuffer::kCopyPaste, &clipboard, &url, &start, &end);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &clipboard,
+      &url, &start, &end);
   EXPECT_EQ(clipboard, converted_data);
 }
 
@@ -259,13 +262,14 @@
 
   base::string16 clipboard;
   ui::Clipboard::GetForCurrentThread()->ReadText(
-      ui::ClipboardBuffer::kCopyPaste, &clipboard);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &clipboard);
   EXPECT_EQ(clipboard.size(), 0u);
 
   std::string url;
   uint32_t start, end;
   ui::Clipboard::GetForCurrentThread()->ReadHTML(
-      ui::ClipboardBuffer::kCopyPaste, &clipboard, &url, &start, &end);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &clipboard,
+      &url, &start, &end);
   EXPECT_EQ(clipboard.size(), 0u);
 }
 
@@ -280,8 +284,8 @@
   RunReadingTask();
 
   std::string clipboard;
-  ui::Clipboard::GetForCurrentThread()->ReadRTF(ui::ClipboardBuffer::kCopyPaste,
-                                                &clipboard);
+  ui::Clipboard::GetForCurrentThread()->ReadRTF(
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &clipboard);
 
   EXPECT_EQ(clipboard, std::string("TestData"));
 }
@@ -337,7 +341,7 @@
 
   std::string clipboard;
   ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
-      ui::ClipboardBuffer::kCopyPaste, &clipboard);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &clipboard);
   EXPECT_EQ(clipboard, "New data");
 }
 
@@ -359,7 +363,7 @@
 
   std::string clipboard;
   ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
-      ui::ClipboardBuffer::kCopyPaste, &clipboard);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &clipboard);
   EXPECT_EQ(clipboard, "New data");
 }
 
@@ -382,7 +386,7 @@
 
   std::string clipboard;
   ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
-      ui::ClipboardBuffer::kCopyPaste, &clipboard);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &clipboard);
   EXPECT_EQ(clipboard, "Original data");
 }
 
@@ -436,7 +440,7 @@
 
   std::string clipboard;
   ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
-      ui::ClipboardBuffer::kCopyPaste, &clipboard);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &clipboard);
   EXPECT_EQ(clipboard, "Golden data");
 }
 
diff --git a/components/omnibox/browser/autocomplete_classifier.cc b/components/omnibox/browser/autocomplete_classifier.cc
index f4a5339..5ea9964 100644
--- a/components/omnibox/browser/autocomplete_classifier.cc
+++ b/components/omnibox/browser/autocomplete_classifier.cc
@@ -68,7 +68,7 @@
       AutocompleteProvider::TYPE_HISTORY_QUICK |
       AutocompleteProvider::TYPE_HISTORY_URL |
       AutocompleteProvider::TYPE_SEARCH | AutocompleteProvider::TYPE_SHORTCUTS |
-      (base::FeatureList::IsEnabled(query_tiles::features::kQueryTilesInOmnibox)
+      (query_tiles::features::IsEnabledQueryTilesInOmnibox()
            ? AutocompleteProvider::TYPE_QUERY_TILE
            : 0);
 }
diff --git a/components/omnibox/browser/autocomplete_controller.cc b/components/omnibox/browser/autocomplete_controller.cc
index 6d171bf..b2c1490 100644
--- a/components/omnibox/browser/autocomplete_controller.cc
+++ b/components/omnibox/browser/autocomplete_controller.cc
@@ -641,11 +641,7 @@
     result_.ConvertOpenTabMatches(provider_client_.get(), &input_);
 
   if (OmniboxFieldTrial::IsPedalSuggestionsEnabled()) {
-    if (OmniboxFieldTrial::IsSuggestionButtonRowEnabled()) {
-      result_.ConvertInSuggestionPedalMatches(provider_client_.get());
-    } else {
-      result_.AppendDedicatedPedalMatches(provider_client_.get(), input_);
-    }
+    result_.ConvertInSuggestionPedalMatches(provider_client_.get());
   }
 
   // Sort the matches and trim to a small number of "best" matches.
diff --git a/components/omnibox/browser/autocomplete_match.cc b/components/omnibox/browser/autocomplete_match.cc
index b234d41..2a86fbb 100644
--- a/components/omnibox/browser/autocomplete_match.cc
+++ b/components/omnibox/browser/autocomplete_match.cc
@@ -106,9 +106,6 @@
 // static
 const char AutocompleteMatch::kEllipsis[] = "... ";
 
-// static
-size_t AutocompleteMatch::next_family_id_;
-
 AutocompleteMatch::AutocompleteMatch()
     : transition(ui::PAGE_TRANSITION_GENERATED) {}
 
@@ -125,7 +122,6 @@
 AutocompleteMatch::AutocompleteMatch(const AutocompleteMatch& match)
     : provider(match.provider),
       relevance(match.relevance),
-      subrelevance(match.subrelevance),
       typed_count(match.typed_count),
       deletable(match.deletable),
       fill_into_edit(match.fill_into_edit),
@@ -151,7 +147,6 @@
       answer(match.answer),
       transition(match.transition),
       type(match.type),
-      parent_type(match.parent_type),
       has_tab_match(match.has_tab_match),
       subtypes(match.subtypes),
       associated_keyword(match.associated_keyword
@@ -185,7 +180,6 @@
 
   provider = match.provider;
   relevance = match.relevance;
-  subrelevance = match.subrelevance;
   typed_count = match.typed_count;
   deletable = match.deletable;
   fill_into_edit = match.fill_into_edit;
@@ -211,7 +205,6 @@
   answer = match.answer;
   transition = match.transition;
   type = match.type;
-  parent_type = match.parent_type;
   has_tab_match = match.has_tab_match;
   subtypes = match.subtypes;
   associated_keyword.reset(
@@ -643,13 +636,6 @@
          type == AutocompleteMatchType::TILE_SUGGESTION;
 }
 
-AutocompleteMatch::Type AutocompleteMatch::GetDemotionType() const {
-  if (!IsSubMatch())
-    return type;
-  else
-    return parent_type;
-}
-
 // static
 TemplateURL* AutocompleteMatch::GetTemplateURLWithKeyword(
     TemplateURLService* template_url_service,
@@ -825,30 +811,6 @@
   }
 }
 
-// static
-size_t AutocompleteMatch::GetNextFamilyID() {
-  next_family_id_ += FAMILY_SIZE;
-  // Avoid the default value. 0 means "no submatch", so no family can use it.
-  if (next_family_id_ == 0)
-    next_family_id_ += FAMILY_SIZE;
-  return next_family_id_;
-}
-
-// static
-bool AutocompleteMatch::IsSameFamily(size_t lhs, size_t rhs) {
-  return (lhs & FAMILY_SIZE_MASK) == (rhs & FAMILY_SIZE_MASK);
-}
-
-void AutocompleteMatch::SetSubMatch(size_t subrelevance,
-                                    AutocompleteMatch::Type parent_type) {
-  this->subrelevance = subrelevance;
-  this->parent_type = parent_type;
-}
-
-bool AutocompleteMatch::IsSubMatch() const {
-  return subrelevance & ~FAMILY_SIZE_MASK;
-}
-
 void AutocompleteMatch::ComputeStrippedDestinationURL(
     const AutocompleteInput& input,
     TemplateURLService* template_url_service) {
@@ -899,37 +861,6 @@
   return answer ? answer->image_url() : image_url;
 }
 
-AutocompleteMatch AutocompleteMatch::DerivePedalSuggestion(
-    OmniboxPedal* pedal) {
-  AutocompleteMatch copy(*this);
-  copy.pedal = pedal;
-  if (subrelevance == 0)
-    subrelevance = GetNextFamilyID();
-  copy.SetSubMatch(subrelevance + PEDAL_FAMILY_ID, copy.type);
-  DCHECK(IsSameFamily(subrelevance, copy.subrelevance));
-
-  copy.type = Type::PEDAL;
-  copy.destination_url = copy.pedal->GetNavigationUrl();
-
-  // Normally this is computed by the match using a TemplateURLService
-  // but Pedal URLs are not typical and unknown, and we don't want them to
-  // be deduped, e.g. after stripping a query parameter that may do something
-  // meaningful like indicate the viewable scope of a settings page.  So here
-  // we keep the URL exactly as the Pedal specifies it.
-  copy.stripped_destination_url = copy.destination_url;
-
-  // Note: Always use empty classifications for empty text and non-empty
-  // classifications for non-empty text.
-  const auto& labels = copy.pedal->GetLabelStrings();
-  copy.contents = labels.suggestion_contents;
-  copy.contents_class = {ACMatchClassification(0, ACMatchClassification::NONE)};
-  copy.description = labels.hint;
-  copy.description_class = {
-      ACMatchClassification(0, ACMatchClassification::NONE)};
-
-  return copy;
-}
-
 void AutocompleteMatch::RecordAdditionalInfo(const std::string& property,
                                              const std::string& value) {
   DCHECK(!property.empty());
@@ -1163,8 +1094,10 @@
          !OmniboxFieldTrial::IsSuggestionButtonRowEnabled();
 }
 
+// TODO(orinj): Dedicated tab switch suggestions are eliminated. Delete this
+//  method and clean up any remaining related logic.
 bool AutocompleteMatch::IsTabSwitchSuggestion() const {
-  return (subrelevance & ~FAMILY_SIZE_MASK) == TAB_SWITCH_FAMILY_ID;
+  return false;
 }
 
 void AutocompleteMatch::UpgradeMatchWithPropertiesFrom(
diff --git a/components/omnibox/browser/autocomplete_match.h b/components/omnibox/browser/autocomplete_match.h
index c53dfcb..239b2512 100644
--- a/components/omnibox/browser/autocomplete_match.h
+++ b/components/omnibox/browser/autocomplete_match.h
@@ -119,15 +119,6 @@
   // and |description| strings.
   static const base::char16 kInvalidChars[];
 
-  // All IDs should be less than the family size, and family size must be
-  // a power of 2 so that the counter wraps.
-  enum {
-    PEDAL_FAMILY_ID = 1,
-    TAB_SWITCH_FAMILY_ID = 2,
-    FAMILY_SIZE = 1 << 2,
-  };
-  static constexpr size_t FAMILY_SIZE_MASK = ~(FAMILY_SIZE - 1);
-
   // Document subtype, for AutocompleteMatchType::DOCUMENT.
   // Update kDocumentTypeStrings when updating DocumentType.
   enum class DocumentType {
@@ -250,10 +241,6 @@
   // clipboard or query tile.
   static bool ShouldBeSkippedForGroupBySearchVsUrl(Type type);
 
-  // If this match is a submatch, returns the parent's type, otherwise this
-  // match's type.
-  Type GetDemotionType() const;
-
   // A static version GetTemplateURL() that takes the match's keyword and
   // match's hostname as parameters.  In short, returns the TemplateURL
   // associated with |keyword| if it exists; otherwise returns the TemplateURL
@@ -315,17 +302,6 @@
   static void LogSearchEngineUsed(const AutocompleteMatch& match,
                                   TemplateURLService* template_url_service);
 
-  // There are some suggestions that we would like to follow each other
-  // e.g. pedals, tab switches, possibly keyword provider suggestions.
-  // These functions provide and compare integer groups so that when we
-  // generate these suggestions, they can be given integers in the same
-  // family, which will cause them to be sorted together.
-  static size_t GetNextFamilyID();
-  static bool IsSameFamily(size_t lhs, size_t rhs);
-  // Preferred method to set both fields simultaneously.
-  void SetSubMatch(size_t subrelevance, AutocompleteMatch::Type parent_type);
-  bool IsSubMatch() const;
-
   // Computes the stripped destination URL (via GURLToStrippedGURL()) and
   // stores the result in |stripped_destination_url|.  |input| is used for the
   // same purpose as in GURLToStrippedGURL().
@@ -370,11 +346,6 @@
   // there isn't an image URL, returns an empty GURL (test with is_empty()).
   GURL ImageUrl() const;
 
-  // Returns a new Pedal match suggestion instance derived from this match,
-  // which is considered to be the triggering suggestion.  The new match
-  // will be set to use the given |pedal|.
-  AutocompleteMatch DerivePedalSuggestion(OmniboxPedal* pedal);
-
   // Adds optional information to the |additional_info| dictionary.
   void RecordAdditionalInfo(const std::string& property,
                             const std::string& value);
@@ -500,11 +471,6 @@
   // rather than being a fairly fixed value defined by the table above.
   int relevance = 0;
 
-  // This represents the numeric family that the match is part of. It is only
-  // set for certain paired suggestions. Suggestions within the same group will
-  // have similar subrelevances, and they will sort together.
-  size_t subrelevance = 0;
-
   // How many times this result was typed in / selected from the omnibox.
   // Only set for some providers and result_types.  If it is not set,
   // its value is -1.  At the time of writing this comment, it is only
@@ -609,9 +575,6 @@
   // Type of this match.
   Type type = AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED;
 
-  // If a submatch, the type of the parent.
-  Type parent_type;
-
   // True if we saw a tab that matched this suggestion.
   bool has_tab_match = false;
 
@@ -690,11 +653,6 @@
   // So users of AutocompleteMatch can use the same ellipsis that it uses.
   static const char kEllipsis[];
 
-  // A numeric quantity that only increases by the amount FAMILY_SIZE.
-  // It helps guarantee that a match family will have similar, but unique,
-  // numeric values.
-  static size_t next_family_id_;
-
 #if DCHECK_IS_ON()
   // Does a data integrity check on this match.
   void Validate() const;
diff --git a/components/omnibox/browser/autocomplete_result.cc b/components/omnibox/browser/autocomplete_result.cc
index 12700c2a4..b18cda8 100644
--- a/components/omnibox/browser/autocomplete_result.cc
+++ b/components/omnibox/browser/autocomplete_result.cc
@@ -42,20 +42,13 @@
 
 namespace {
 
-// Rotates |it| and its associated submatches to be in the front of |matches|.
+// Rotates |it| to be in the front of |matches|.
 // |it| must be a valid iterator of |matches| or equal to |matches->end()|.
 void RotateMatchToFront(ACMatches::iterator it, ACMatches* matches) {
   if (it == matches->end())
     return;
 
-  const size_t cookie = it->subrelevance;
   auto next = std::next(it);
-  if (cookie != 0) {
-    // If default match followed by sub-match(es), move them too.
-    while (next != matches->end() &&
-           AutocompleteMatch::IsSameFamily(cookie, next->subrelevance))
-      next = std::next(next);
-  }
   std::rotate(matches->begin(), it, next);
 }
 
@@ -285,15 +278,11 @@
 #endif
     // Skip over default match.
     auto next = std::next(matches_.begin());
-    // If it has submatches, skip them too.
-    if (matches_.front().subrelevance != 0 ||
-        AutocompleteMatch::ShouldBeSkippedForGroupBySearchVsUrl(
+    if (AutocompleteMatch::ShouldBeSkippedForGroupBySearchVsUrl(
             matches_.front().type)) {
       while (next != matches_.end() &&
-             (AutocompleteMatch::IsSameFamily(matches_.front().subrelevance,
-                                              next->subrelevance) ||
-              AutocompleteMatch::ShouldBeSkippedForGroupBySearchVsUrl(
-                  matches_.front().type))) {
+             (AutocompleteMatch::ShouldBeSkippedForGroupBySearchVsUrl(
+                 matches_.front().type))) {
         next = std::next(next);
       }
     }
@@ -400,26 +389,6 @@
   }
 }
 
-void AutocompleteResult::AppendDedicatedPedalMatches(
-    AutocompleteProviderClient* client,
-    const AutocompleteInput& input) {
-  const OmniboxPedalProvider* provider = client->GetPedalProvider();
-  ACMatches pedal_suggestions;
-
-  for (auto& match : matches_) {
-    // We do not want to deal with pedals of pedals, or pedals among
-    // exclusive tail suggestions.
-    if (match.pedal || match.type == ACMatchType::SEARCH_SUGGEST_TAIL)
-      continue;
-    OmniboxPedal* const pedal = provider->FindPedalMatch(match.contents);
-    if (pedal)
-      pedal_suggestions.push_back(match.DerivePedalSuggestion(pedal));
-  }
-  if (!pedal_suggestions.empty()) {
-    AppendMatches(input, pedal_suggestions);
-  }
-}
-
 void AutocompleteResult::ConvertInSuggestionPedalMatches(
     AutocompleteProviderClient* client) {
   const OmniboxPedalProvider* provider = client->GetPedalProvider();
@@ -452,32 +421,16 @@
 void AutocompleteResult::ConvertOpenTabMatches(
     AutocompleteProviderClient* client,
     const AutocompleteInput* input) {
-  ACMatches matches_to_add;
   for (auto& match : matches_) {
     // If already converted this match, don't re-search through open tabs and
-    // possibly re-change the description. Also skip submatches.
-    if (match.has_tab_match || match.IsSubMatch())
+    // possibly re-change the description.
+    if (match.has_tab_match)
       continue;
     // If URL is in a tab, remember that.
     if (client->IsTabOpenWithURL(match.destination_url, input)) {
       match.has_tab_match = true;
-      // If will have dedicated row, add a match for it.
-      if (OmniboxFieldTrial::IsTabSwitchSuggestionsDedicatedRowEnabled()) {
-        if (match.subrelevance == 0)
-          match.subrelevance = AutocompleteMatch::GetNextFamilyID();
-        AutocompleteMatch tab_switch_match = match;
-        tab_switch_match.SetSubMatch(
-            match.subrelevance + AutocompleteMatch::TAB_SWITCH_FAMILY_ID,
-            match.type);
-        tab_switch_match.contents =
-            l10n_util::GetStringUTF16(IDS_OMNIBOX_TAB_SUGGEST_HINT);
-        tab_switch_match.contents_class = {{0, ACMatchClassification::NONE}};
-        matches_to_add.push_back(tab_switch_match);
-      }
     }
   }
-  std::copy(matches_to_add.begin(), matches_to_add.end(),
-            std::back_inserter(matches_));
 }
 
 bool AutocompleteResult::HasCopiedMatches() const {
@@ -571,7 +524,7 @@
       input.type() == metrics::OmniboxInputType::URL) {
     auto best = matches->end();
     for (auto it = matches->begin(); it != matches->end(); ++it) {
-      if (it->allowed_to_be_default_match && !it->IsSubMatch() &&
+      if (it->allowed_to_be_default_match &&
           (best == matches->end() ||
            AutocompleteMatch::MoreRelevant(*it, *best))) {
         best = it;
@@ -580,7 +533,7 @@
     return best;
   } else {
     return std::find_if(matches->begin(), matches->end(), [](const auto& m) {
-      return m.allowed_to_be_default_match && !m.IsSubMatch();
+      return m.allowed_to_be_default_match;
     });
   }
 }
@@ -972,9 +925,7 @@
 std::pair<GURL, bool> AutocompleteResult::GetMatchComparisonFields(
     const AutocompleteMatch& match) {
   return std::make_pair(match.stripped_destination_url,
-                        match.type == ACMatchType::CALCULATOR ||
-                            // Separate sub-matches from their origins.
-                            match.IsSubMatch());
+                        match.type == ACMatchType::CALCULATOR);
 }
 
 void AutocompleteResult::LimitNumberOfURLsShown(
@@ -983,7 +934,7 @@
     const CompareWithDemoteByType<AutocompleteMatch>& comparing_object) {
   size_t search_count = std::count_if(
       matches_.begin(), matches_.end(), [&](const AutocompleteMatch& m) {
-        return !m.IsSubMatch() && AutocompleteMatch::IsSearchType(m.type) &&
+        return AutocompleteMatch::IsSearchType(m.type) &&
                // Don't count if would be removed.
                comparing_object.GetDemotedRelevance(m) > 0;
       });
@@ -997,16 +948,9 @@
   matches_.erase(
       std::remove_if(matches_.begin(), matches_.end(),
                      [&url_count, max_url_count](const AutocompleteMatch& m) {
-                       if (!m.IsSubMatch() &&
-                           !AutocompleteMatch::IsSearchType(m.type) &&
+                       if (!AutocompleteMatch::IsSearchType(m.type) &&
                            ++url_count > max_url_count)
                          return true;
-                       // Do not count submatches towards URL total, but
-                       // drop them if parent was dropped.
-                       if (m.IsSubMatch() &&
-                           !AutocompleteMatch::IsSearchType(m.parent_type) &&
-                           url_count > max_url_count)
-                         return true;
                        return false;
                      }),
       matches_.end());
@@ -1016,6 +960,6 @@
 void AutocompleteResult::GroupSuggestionsBySearchVsURL(iterator begin,
                                                        iterator end) {
   std::stable_partition(begin, end, [](const AutocompleteMatch& match) {
-    return match.IsSearchType(match.GetDemotionType());
+    return match.IsSearchType(match.type);
   });
 }
diff --git a/components/omnibox/browser/autocomplete_result.h b/components/omnibox/browser/autocomplete_result.h
index 15c4816..fb4d484 100644
--- a/components/omnibox/browser/autocomplete_result.h
+++ b/components/omnibox/browser/autocomplete_result.h
@@ -70,12 +70,6 @@
                    TemplateURLService* template_url_service,
                    const AutocompleteMatch* preserve_default_match = nullptr);
 
-  // Creates and adds any dedicated Pedal matches triggered by existing matches.
-  // This should be the only place where new Pedal suggestions are introduced
-  // because it doesn't dedupe; it just carefully avoids adding duplicates.
-  void AppendDedicatedPedalMatches(AutocompleteProviderClient* client,
-                                   const AutocompleteInput& input);
-
   // Sets |pedal| in matches that have Pedal-triggering text.
   void ConvertInSuggestionPedalMatches(AutocompleteProviderClient* client);
 
diff --git a/components/omnibox/browser/autocomplete_result_unittest.cc b/components/omnibox/browser/autocomplete_result_unittest.cc
index a133ed6..0e6d1743 100644
--- a/components/omnibox/browser/autocomplete_result_unittest.cc
+++ b/components/omnibox/browser/autocomplete_result_unittest.cc
@@ -1754,103 +1754,6 @@
   EXPECT_FALSE(result.match_at(2)->allowed_to_be_default_match);
 }
 
-TEST_F(AutocompleteResultTest, PedalSuggestionsCantBeDefaultMatch) {
-  TestData data[] = {
-      {1, 1, 500, true},
-      {0, 1, 1100, true},
-  };
-
-  ACMatches matches;
-  PopulateAutocompleteMatches(data, base::size(data), &matches);
-  matches[0].contents = base::UTF8ToUTF16("clear chrome history");
-  matches[1].contents = base::UTF8ToUTF16("open incognito tab");
-
-  AutocompleteInput input(base::ASCIIToUTF16("a"),
-                          metrics::OmniboxEventProto::OTHER,
-                          TestSchemeClassifier());
-  AutocompleteResult result;
-  result.AppendMatches(input, matches);
-
-  FakeAutocompleteProviderClient client;
-  result.AppendDedicatedPedalMatches(&client, input);
-
-  // Two distinct Pedals should be appended.
-  EXPECT_EQ(result.size(), 4u);
-  EXPECT_NE(result.match_at(2)->pedal, nullptr);
-  EXPECT_NE(result.match_at(3)->pedal, nullptr);
-
-  // Neither should be the default match, even though they were both
-  // derived from suggestions where the field is set true.
-  EXPECT_TRUE(result.match_at(0)->allowed_to_be_default_match);
-  EXPECT_EQ(result.match_at(0)->pedal, nullptr);
-  EXPECT_TRUE(result.match_at(1)->allowed_to_be_default_match);
-  EXPECT_EQ(result.match_at(1)->pedal, nullptr);
-  EXPECT_TRUE(result.match_at(2)->allowed_to_be_default_match);
-  EXPECT_NE(result.match_at(2)->pedal, nullptr);
-  EXPECT_TRUE(result.match_at(3)->allowed_to_be_default_match);
-  EXPECT_NE(result.match_at(3)->pedal, nullptr);
-}
-
-TEST_F(AutocompleteResultTest, PedalSuggestionsRemainUnique) {
-  TestData data[] = {
-      {1, 1, 500, false},
-      {0, 1, 1100, false},
-      {2, 1, 1000, true},
-      {0, 1, 1200, false},
-  };
-
-  ACMatches matches;
-  PopulateAutocompleteMatches(data, base::size(data), &matches);
-  matches[0].contents = base::UTF8ToUTF16("clear chrome history");
-  matches[1].contents = base::UTF8ToUTF16("open incognito tab");
-  matches[2].contents = base::UTF8ToUTF16("clear chrome history");
-
-  AutocompleteInput input(base::ASCIIToUTF16("a"),
-                          metrics::OmniboxEventProto::OTHER,
-                          TestSchemeClassifier());
-  AutocompleteResult result;
-  result.AppendMatches(input, matches);
-
-  FakeAutocompleteProviderClient client;
-  result.AppendDedicatedPedalMatches(&client, input);
-  result.DeduplicateMatches(&result.matches_);
-
-  // Exactly 2 (not 3) unique Pedals should be added with relevance close to max
-  // of the triggering suggestions.
-  EXPECT_EQ(result.size(), 6u);
-  EXPECT_NE(result.match_at(4)->pedal, nullptr);
-  EXPECT_NE(result.match_at(5)->pedal, nullptr);
-  EXPECT_NE(result.match_at(4)->pedal, result.match_at(5)->pedal);
-  EXPECT_EQ(result.match_at(4)->relevance, 1100);
-  EXPECT_EQ(result.match_at(5)->relevance, 1000);
-
-  // Now artificially modify existing suggestions and run again to ensure that
-  // no duplicates are added, but the existing Pedal suggestion is updated.
-  result.match_at(3)->contents = base::UTF8ToUTF16("open incognito tab");
-  result.AppendDedicatedPedalMatches(&client, input);
-  result.DeduplicateMatches(&result.matches_);
-  EXPECT_EQ(result.size(), 6u);
-  EXPECT_NE(result.match_at(4)->pedal, nullptr);
-  EXPECT_NE(result.match_at(5)->pedal, nullptr);
-  EXPECT_NE(result.match_at(4)->pedal, result.match_at(5)->pedal);
-  EXPECT_EQ(result.match_at(5)->relevance, 1200);
-
-  // Finally run a real final sort to make sure default match and its
-  // pedal get promoted.
-  result.SortAndCull(input, template_url_service_.get());
-  EXPECT_EQ(result.size(), 5u);
-  EXPECT_EQ(result.match_at(0)->relevance, 1000);
-  EXPECT_EQ(result.match_at(0)->pedal, nullptr);
-  EXPECT_EQ(result.match_at(1)->relevance, 1000);
-  EXPECT_NE(result.match_at(1)->pedal, nullptr);
-  EXPECT_EQ(result.match_at(2)->relevance, 1200);
-  EXPECT_EQ(result.match_at(2)->pedal, nullptr);
-  EXPECT_EQ(result.match_at(3)->relevance, 1200);
-  EXPECT_NE(result.match_at(3)->pedal, nullptr);
-  EXPECT_EQ(result.match_at(4)->relevance, 500);
-  EXPECT_EQ(result.match_at(4)->pedal, nullptr);
-}
-
 TEST_F(AutocompleteResultTest, CalculateNumMatchesPerUrlCountTest) {
   CompareWithDemoteByType<AutocompleteMatch> comparison_object(
       metrics::OmniboxEventProto::OTHER);
diff --git a/components/omnibox/browser/clipboard_provider_unittest.cc b/components/omnibox/browser/clipboard_provider_unittest.cc
index 2f779f71..db38514 100644
--- a/components/omnibox/browser/clipboard_provider_unittest.cc
+++ b/components/omnibox/browser/clipboard_provider_unittest.cc
@@ -127,7 +127,7 @@
   ASSERT_GE(provider_->matches().size(), 1U);
   EXPECT_EQ(GURL(kClipboardURL), provider_->matches().back().destination_url);
   EXPECT_EQ(AutocompleteMatchType::CLIPBOARD_URL,
-            provider_->matches().back().GetDemotionType());
+            provider_->matches().back().type);
 }
 
 TEST_F(ClipboardProviderTest, MatchesText) {
@@ -142,7 +142,7 @@
   EXPECT_EQ(base::UTF8ToUTF16(kClipboardText),
             provider_->matches().back().fill_into_edit);
   EXPECT_EQ(AutocompleteMatchType::CLIPBOARD_TEXT,
-            provider_->matches().back().GetDemotionType());
+            provider_->matches().back().type);
 }
 
 TEST_F(ClipboardProviderTest, MatchesImage) {
@@ -163,7 +163,7 @@
                                          image_bytes);
   ASSERT_GE(provider_->matches().size(), 1U);
   EXPECT_EQ(AutocompleteMatchType::CLIPBOARD_IMAGE,
-            provider_->matches().back().GetDemotionType());
+            provider_->matches().back().type);
 }
 
 TEST_F(ClipboardProviderTest, DeleteMatch) {
diff --git a/components/omnibox/browser/match_compare.h b/components/omnibox/browser/match_compare.h
index dfadec5..a47f349 100644
--- a/components/omnibox/browser/match_compare.h
+++ b/components/omnibox/browser/match_compare.h
@@ -22,7 +22,7 @@
   // Returns the relevance score of |match| demoted appropriately by
   // |demotions_by_type_|.
   int GetDemotedRelevance(const Match& match) const {
-    auto demotion_it = demotions_.find(match.GetDemotionType());
+    auto demotion_it = demotions_.find(match.type);
     return (demotion_it == demotions_.end())
                ? match.relevance
                : (match.relevance * demotion_it->second);
@@ -37,11 +37,6 @@
       // Greater relevance should come first.
       return demoted_relevance1 > demoted_relevance2;
     }
-    // "Paired" suggestions should follow each other, lower first.
-    // Even if subrelevances don't match, we must compare them to maintain
-    // ordering.
-    if (elem1.subrelevance != elem2.subrelevance)
-      return elem1.subrelevance < elem2.subrelevance;
     // For equal-relevance matches, we sort alphabetically, so that providers
     // who return multiple elements at the same priority get a "stable" sort
     // across multiple updates.
diff --git a/components/open_from_clipboard/clipboard_recent_content_generic.cc b/components/open_from_clipboard/clipboard_recent_content_generic.cc
index 9d3f259..b4841e0 100644
--- a/components/open_from_clipboard/clipboard_recent_content_generic.cc
+++ b/components/open_from_clipboard/clipboard_recent_content_generic.cc
@@ -45,7 +45,8 @@
   // Get and clean up the clipboard before processing.
   std::string gurl_string;
   ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
-  clipboard->ReadAsciiText(ui::ClipboardBuffer::kCopyPaste, &gurl_string);
+  clipboard->ReadAsciiText(ui::ClipboardBuffer::kCopyPaste,
+                           /* data_dst = */ nullptr, &gurl_string);
   base::TrimWhitespaceASCII(gurl_string, base::TrimPositions::TRIM_ALL,
                             &gurl_string);
 
@@ -63,7 +64,8 @@
     // Fall back to unicode / UTF16, as some URLs may use international domain
     // names, not punycode.
     base::string16 gurl_string16;
-    clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &gurl_string16);
+    clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste,
+                        /* data_dst = */ nullptr, &gurl_string16);
     base::TrimWhitespace(gurl_string16, base::TrimPositions::TRIM_ALL,
                          &gurl_string16);
     if (gurl_string16.find_first_of(base::kWhitespaceUTF16) !=
@@ -85,7 +87,8 @@
 
   base::string16 text_from_clipboard;
   ui::Clipboard::GetForCurrentThread()->ReadText(
-      ui::ClipboardBuffer::kCopyPaste, &text_from_clipboard);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+      &text_from_clipboard);
   base::TrimWhitespace(text_from_clipboard, base::TrimPositions::TRIM_ALL,
                        &text_from_clipboard);
   if (text_from_clipboard.empty()) {
@@ -102,6 +105,7 @@
 
   ui::Clipboard::GetForCurrentThread()->ReadImage(
       ui::ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr,
       base::BindOnce(&OnGetRecentImageFromClipboard, std::move(callback)));
 }
 
@@ -110,8 +114,8 @@
     return false;
 
   return ui::Clipboard::GetForCurrentThread()->IsFormatAvailable(
-      ui::ClipboardFormatType::GetBitmapType(),
-      ui::ClipboardBuffer::kCopyPaste);
+      ui::ClipboardFormatType::GetBitmapType(), ui::ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr);
 }
 
 base::TimeDelta ClipboardRecentContentGeneric::GetClipboardContentAge() const {
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/ComponentPaymentRequestImpl.java b/components/payments/content/android/java/src/org/chromium/components/payments/ComponentPaymentRequestImpl.java
index a518f0a..e7b9549 100644
--- a/components/payments/content/android/java/src/org/chromium/components/payments/ComponentPaymentRequestImpl.java
+++ b/components/payments/content/android/java/src/org/chromium/components/payments/ComponentPaymentRequestImpl.java
@@ -14,8 +14,6 @@
 import org.chromium.payments.mojom.PaymentRequestClient;
 import org.chromium.payments.mojom.PaymentValidationErrors;
 
-import java.lang.ref.WeakReference;
-
 /**
  * Android implementation of the PaymentRequest service defined in
  * third_party/blink/public/mojom/payments/payment_request.mojom. This component provides the parts
@@ -46,10 +44,10 @@
 
         /**
          * Set a weak reference to the client of this delegate.
-         * @param componentPaymentRequestImpl A weak reference to the client of this delegate.
+         * @param componentPaymentRequestImpl The client of this delegate.
          */
         void setComponentPaymentRequestImpl(
-                WeakReference<ComponentPaymentRequestImpl> componentPaymentRequestImpl);
+                ComponentPaymentRequestImpl componentPaymentRequestImpl);
 
         /**
          * @return The JourneyLogger of PaymentRequestImpl.
@@ -68,7 +66,7 @@
      */
     public ComponentPaymentRequestImpl(ComponentPaymentRequestDelegate delegate) {
         mDelegate = delegate;
-        mDelegate.setComponentPaymentRequestImpl(new WeakReference<>(this));
+        mDelegate.setComponentPaymentRequestImpl(this);
     }
 
     @Override
@@ -146,7 +144,8 @@
     }
 
     /**
-     * Get the PaymentRequestClient.
+     * Get the PaymentRequestClient. To close the client, the caller should call {@link
+     * #closeClient()} instead of calling {@link PaymentRequest#close()} directly.
      * @return The client.
      */
     @Nullable
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto
index f4f0a622..567978b 100644
--- a/components/policy/proto/device_management_backend.proto
+++ b/components/policy/proto/device_management_backend.proto
@@ -341,6 +341,14 @@
   optional string auth_code = 1;
 }
 
+// Device Identifier for non-Chrome OS platform.
+message BrowserDeviceIdentifier {
+  // Name of the computer.
+  optional string computer_name = 1;
+  // Device serial number (definition depending on the platform).
+  optional string serial_number = 2;
+}
+
 message PolicyFetchRequest {
   reserved 5;
 
@@ -422,6 +430,9 @@
 
   // If this is an affiliated user, this is the device's DMToken.
   optional string device_dm_token = 12;
+
+  // Device identifier for helping identify non-Chrome OS devices.
+  optional BrowserDeviceIdentifier browser_device_identifier = 13;
 }
 
 // This message customizes how the device behaves when it is disabled by its
@@ -1806,6 +1817,8 @@
   optional OSReport os_report = 7;
   // A string contains OS user name.
   optional string os_user_name = 8;
+  // Device identifier for helping identify non-Chrome OS devices.
+  optional BrowserDeviceIdentifier browser_device_identifier = 9;
 }
 
 // Report user level status on Chrome OS platform. Chrome OS equivalent of
@@ -2542,6 +2555,8 @@
   optional string os_platform = 2;
   // Platform specific version number, e.g., 6.1.7601.0 or 10.12.6
   optional string os_version = 3;
+  // Device identifier for helping identify non-Chrome OS devices.
+  optional BrowserDeviceIdentifier browser_device_identifier = 4;
 }
 
 // Gets an enrollment token to a managed Google Play account for using it with
diff --git a/components/query_tiles/switches.cc b/components/query_tiles/switches.cc
index 0e7dd70..c0ae17f 100644
--- a/components/query_tiles/switches.cc
+++ b/components/query_tiles/switches.cc
@@ -6,6 +6,8 @@
 
 namespace query_tiles {
 namespace features {
+const base::Feature kQueryTilesGeoFilter{"QueryTilesGeoFilter",
+                                         base::FEATURE_ENABLED_BY_DEFAULT};
 const base::Feature kQueryTiles{"QueryTiles",
                                 base::FEATURE_DISABLED_BY_DEFAULT};
 const base::Feature kQueryTilesInOmnibox{"QueryTilesInOmnibox",
@@ -13,6 +15,11 @@
 const base::Feature kQueryTilesEnableQueryEditing{
     "QueryTilesEnableQueryEditing", base::FEATURE_DISABLED_BY_DEFAULT};
 
+bool IsEnabledQueryTilesInOmnibox() {
+  return base::FeatureList::IsEnabled(features::kQueryTilesGeoFilter) &&
+         base::FeatureList::IsEnabled(features::kQueryTilesInOmnibox);
+}
+
 }  // namespace features
 
 namespace switches {
diff --git a/components/query_tiles/switches.h b/components/query_tiles/switches.h
index 8d8e6241..c2f745b 100644
--- a/components/query_tiles/switches.h
+++ b/components/query_tiles/switches.h
@@ -8,8 +8,13 @@
 #include "base/feature_list.h"
 
 namespace query_tiles {
+
 namespace features {
 
+// Main feature flag for the query tiles feature that allows or blocks the
+// feature in the user's country. Must be checked in addition to any other flag.
+extern const base::Feature kQueryTilesGeoFilter;
+
 // Main feature flag for the query tiles feature.
 extern const base::Feature kQueryTiles;
 
@@ -21,6 +26,9 @@
 // level of tiles will be displayed.
 extern const base::Feature kQueryTilesEnableQueryEditing;
 
+// Helper function to determine whether query tiles should be shown on omnibox.
+bool IsEnabledQueryTilesInOmnibox();
+
 }  // namespace features
 
 namespace switches {
diff --git a/components/safe_browsing/core/common/safe_browsing_prefs.cc b/components/safe_browsing/core/common/safe_browsing_prefs.cc
index 61333746..e0b3f47 100644
--- a/components/safe_browsing/core/common/safe_browsing_prefs.cc
+++ b/components/safe_browsing/core/common/safe_browsing_prefs.cc
@@ -138,6 +138,19 @@
   }
 }
 
+void SetSafeBrowsingState(PrefService* prefs, SafeBrowsingState state) {
+  if (state == ENHANCED_PROTECTION) {
+    SetEnhancedProtectionPref(prefs, true);
+    SetStandardProtectionPref(prefs, true);
+  } else if (state == STANDARD_PROTECTION) {
+    SetEnhancedProtectionPref(prefs, false);
+    SetStandardProtectionPref(prefs, true);
+  } else {
+    SetEnhancedProtectionPref(prefs, false);
+    SetStandardProtectionPref(prefs, false);
+  }
+}
+
 bool IsSafeBrowsingEnabled(const PrefService& prefs) {
   return prefs.GetBoolean(prefs::kSafeBrowsingEnabled);
 }
@@ -248,13 +261,21 @@
   prefs->SetBoolean(prefs::kSafeBrowsingScoutReportingEnabled, value);
 }
 
-void SetEnhancedProtectionPref(PrefService* prefs, bool value) {
+void SetEnhancedProtectionPrefForTests(PrefService* prefs, bool value) {
   // SafeBrowsingEnabled pref needs to be turned on in order for enhanced
   // protection pref to be turned on. This method is only used for tests.
   prefs->SetBoolean(prefs::kSafeBrowsingEnabled, value);
   prefs->SetBoolean(prefs::kSafeBrowsingEnhanced, value);
 }
 
+void SetEnhancedProtectionPref(PrefService* prefs, bool value) {
+  prefs->SetBoolean(prefs::kSafeBrowsingEnhanced, value);
+}
+
+void SetStandardProtectionPref(PrefService* prefs, bool value) {
+  prefs->SetBoolean(prefs::kSafeBrowsingEnabled, value);
+}
+
 void UpdatePrefsBeforeSecurityInterstitial(PrefService* prefs) {
   // Remember that this user saw an interstitial.
   prefs->SetBoolean(prefs::kSafeBrowsingSawInterstitialScoutReporting, true);
diff --git a/components/safe_browsing/core/common/safe_browsing_prefs.h b/components/safe_browsing/core/common/safe_browsing_prefs.h
index 3d150e7..ba20f9ca 100644
--- a/components/safe_browsing/core/common/safe_browsing_prefs.h
+++ b/components/safe_browsing/core/common/safe_browsing_prefs.h
@@ -241,6 +241,9 @@
   DELAY_UPLOADS_AND_DOWNLOADS = 3,
 };
 
+// Enum representing possible values of the Safe Browsing state.
+// A Java counterpart will be generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.chrome.browser.safe_browsing
 enum SafeBrowsingState {
   // The user is not opted into Safe Browsing.
   NO_SAFE_BROWSING = 0,
@@ -257,6 +260,8 @@
 
 SafeBrowsingState GetSafeBrowsingState(const PrefService& prefs);
 
+void SetSafeBrowsingState(PrefService* prefs, SafeBrowsingState state);
+
 // Returns whether Safe Browsing is enabled for the user.
 bool IsSafeBrowsingEnabled(const PrefService& prefs);
 
@@ -307,8 +312,14 @@
 
 // Sets the currently active Safe Browsing Enhanced Protection to the specified
 // value.
+void SetEnhancedProtectionPrefForTests(PrefService* prefs, bool value);
+
+// Set prefs to enable Safe Browsing Enhanced Protection.
 void SetEnhancedProtectionPref(PrefService* prefs, bool value);
 
+// Set prefs to enable Safe Browsing Standard Protection.
+void SetStandardProtectionPref(PrefService* prefs, bool value);
+
 // Called when a security interstitial is closed by the user.
 // |on_show_pref_existed| indicates whether the pref existed when the
 // interstitial was shown. |on_show_pref_value| contains the pref value when the
diff --git a/components/safe_browsing/core/common/safe_browsing_prefs_unittest.cc b/components/safe_browsing/core/common/safe_browsing_prefs_unittest.cc
index 92497776..68cc09f 100644
--- a/components/safe_browsing/core/common/safe_browsing_prefs_unittest.cc
+++ b/components/safe_browsing/core/common/safe_browsing_prefs_unittest.cc
@@ -126,7 +126,7 @@
   // Confirm default state.
   EXPECT_FALSE(IsEnhancedProtectionEnabled(prefs_));
 
-  SetEnhancedProtectionPref(&prefs_, true);
+  SetEnhancedProtectionPrefForTests(&prefs_, true);
   {
     base::test::ScopedFeatureList scoped_feature_list;
     scoped_feature_list.InitAndEnableFeature(kEnhancedProtection);
diff --git a/components/update_client/background_downloader_win.cc b/components/update_client/background_downloader_win.cc
index c180215..8743cc8 100644
--- a/components/update_client/background_downloader_win.cc
+++ b/components/update_client/background_downloader_win.cc
@@ -20,6 +20,7 @@
 #include "base/files/file_util.h"
 #include "base/location.h"
 #include "base/logging.h"
+#include "base/macros.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/sequenced_task_runner.h"
 #include "base/strings/string_piece.h"
@@ -395,7 +396,7 @@
 }  // namespace
 
 BackgroundDownloader::BackgroundDownloader(
-    scoped_refptr<CrxDownloader> successor)
+    std::unique_ptr<CrxDownloader> successor)
     : CrxDownloader(std::move(successor)),
       com_task_runner_(base::ThreadPool::CreateCOMSTATaskRunner(
           kTaskTraitsBackgroundDownloader)),
@@ -416,14 +417,15 @@
 void BackgroundDownloader::OnTimer() {
   DCHECK(thread_checker_.CalledOnValidThread());
   com_task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&BackgroundDownloader::OnDownloading, this));
+      FROM_HERE, base::BindOnce(&BackgroundDownloader::OnDownloading,
+                                base::Unretained(this)));
 }
 
 void BackgroundDownloader::DoStartDownload(const GURL& url) {
   DCHECK(thread_checker_.CalledOnValidThread());
   com_task_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(&BackgroundDownloader::BeginDownload, this, url));
+      FROM_HERE, base::BindOnce(&BackgroundDownloader::BeginDownload,
+                                base::Unretained(this), url));
 }
 
 // Called one time when this class is asked to do a download.
@@ -442,8 +444,9 @@
   VLOG(1) << "Starting BITS download for: " << url.spec();
 
   ResetInterfacePointers();
-  main_task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&BackgroundDownloader::StartTimer, this));
+  main_task_runner()->PostTask(FROM_HERE,
+                               base::BindOnce(&BackgroundDownloader::StartTimer,
+                                              base::Unretained(this)));
 }
 
 // Creates or opens an existing BITS job to download the |url|, and handles
@@ -532,8 +535,9 @@
     return;
 
   ResetInterfacePointers();
-  main_task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&BackgroundDownloader::StartTimer, this));
+  main_task_runner()->PostTask(FROM_HERE,
+                               base::BindOnce(&BackgroundDownloader::StartTimer,
+                                              base::Unretained(this)));
 }
 
 // Completes the BITS download, picks up the file path of the response, and
@@ -578,8 +582,9 @@
   if (!result.error)
     result.response = response_;
   main_task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&BackgroundDownloader::OnDownloadComplete, this,
-                                is_handled, result, download_metrics));
+      FROM_HERE, base::BindOnce(&BackgroundDownloader::OnDownloadComplete,
+                                base::Unretained(this), is_handled, result,
+                                download_metrics));
 
   // Once the task is posted to the the main thread, this object may be deleted
   // by its owner. It is not safe to access members of this object on this task
@@ -661,8 +666,9 @@
   GetJobByteCount(job_, &downloaded_bytes, &total_bytes);
 
   main_task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&BackgroundDownloader::OnDownloadProgress, this,
-                                downloaded_bytes, total_bytes));
+      FROM_HERE,
+      base::BindOnce(&BackgroundDownloader::OnDownloadProgress,
+                     base::Unretained(this), downloaded_bytes, total_bytes));
   return false;
 }
 
diff --git a/components/update_client/background_downloader_win.h b/components/update_client/background_downloader_win.h
index 4e0b396..28b969386 100644
--- a/components/update_client/background_downloader_win.h
+++ b/components/update_client/background_downloader_win.h
@@ -11,6 +11,7 @@
 
 #include <memory>
 
+#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/strings/string16.h"
 #include "base/threading/thread_checker.h"
@@ -38,11 +39,11 @@
 // the BITS service.
 class BackgroundDownloader : public CrxDownloader {
  public:
-  explicit BackgroundDownloader(scoped_refptr<CrxDownloader> successor);
+  explicit BackgroundDownloader(std::unique_ptr<CrxDownloader> successor);
+  ~BackgroundDownloader() override;
 
  private:
   // Overrides for CrxDownloader.
-  ~BackgroundDownloader() override;
   void DoStartDownload(const GURL& url) override;
 
   // Called asynchronously on the |com_task_runner_| at different stages during
@@ -147,6 +148,8 @@
 
   // Contains the path of the downloaded file if the download was successful.
   base::FilePath response_;
+
+  DISALLOW_COPY_AND_ASSIGN(BackgroundDownloader);
 };
 
 }  // namespace update_client
diff --git a/components/update_client/component.cc b/components/update_client/component.cc
index 07268c7..294b9da 100644
--- a/components/update_client/component.cc
+++ b/components/update_client/component.cc
@@ -759,7 +759,7 @@
   for (const auto& download_metrics : crx_downloader_->download_metrics())
     component.AppendEvent(component.MakeEventDownloadMetrics(download_metrics));
 
-  crx_downloader_ = nullptr;
+  crx_downloader_.reset();
 
   if (download_result.error) {
     DCHECK(download_result.response.empty());
@@ -832,7 +832,7 @@
   for (const auto& download_metrics : crx_downloader_->download_metrics())
     component.AppendEvent(component.MakeEventDownloadMetrics(download_metrics));
 
-  crx_downloader_ = nullptr;
+  crx_downloader_.reset();
 
   if (download_result.error) {
     DCHECK(download_result.response.empty());
diff --git a/components/update_client/component.h b/components/update_client/component.h
index cc263f4..9323a36 100644
--- a/components/update_client/component.h
+++ b/components/update_client/component.h
@@ -14,6 +14,7 @@
 #include "base/callback.h"
 #include "base/files/file_path.h"
 #include "base/gtest_prod_util.h"
+#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/optional.h"
 #include "base/sequence_checker.h"
@@ -44,8 +45,6 @@
   using CallbackHandleComplete = base::OnceCallback<void()>;
 
   Component(const UpdateContext& update_context, const std::string& id);
-  Component(const Component&) = delete;
-  Component& operator=(const Component&) = delete;
   ~Component();
 
   // Handles the current state of the component and makes it transition
@@ -184,20 +183,18 @@
   class StateNew : public State {
    public:
     explicit StateNew(Component* component);
-    StateNew(const StateNew&) = delete;
-    StateNew& operator=(const StateNew&) = delete;
     ~StateNew() override;
 
    private:
     // State overrides.
     void DoHandle() override;
+
+    DISALLOW_COPY_AND_ASSIGN(StateNew);
   };
 
   class StateChecking : public State {
    public:
     explicit StateChecking(Component* component);
-    StateChecking(const StateChecking&) = delete;
-    StateChecking& operator=(const StateChecking&) = delete;
     ~StateChecking() override;
 
    private:
@@ -205,50 +202,50 @@
     void DoHandle() override;
 
     void UpdateCheckComplete();
+
+    DISALLOW_COPY_AND_ASSIGN(StateChecking);
   };
 
   class StateUpdateError : public State {
    public:
     explicit StateUpdateError(Component* component);
-    StateUpdateError(const StateUpdateError&) = delete;
-    StateUpdateError& operator=(const StateUpdateError&) = delete;
     ~StateUpdateError() override;
 
    private:
     // State overrides.
     void DoHandle() override;
+
+    DISALLOW_COPY_AND_ASSIGN(StateUpdateError);
   };
 
   class StateCanUpdate : public State {
    public:
     explicit StateCanUpdate(Component* component);
-    StateCanUpdate(const StateCanUpdate&) = delete;
-    StateCanUpdate& operator=(const StateCanUpdate&) = delete;
     ~StateCanUpdate() override;
 
    private:
     // State overrides.
     void DoHandle() override;
     bool CanTryDiffUpdate() const;
+
+    DISALLOW_COPY_AND_ASSIGN(StateCanUpdate);
   };
 
   class StateUpToDate : public State {
    public:
     explicit StateUpToDate(Component* component);
-    StateUpToDate(const StateUpToDate&) = delete;
-    StateUpToDate& operator=(const StateUpToDate&) = delete;
     ~StateUpToDate() override;
 
    private:
     // State overrides.
     void DoHandle() override;
+
+    DISALLOW_COPY_AND_ASSIGN(StateUpToDate);
   };
 
   class StateDownloadingDiff : public State {
    public:
     explicit StateDownloadingDiff(Component* component);
-    StateDownloadingDiff(const StateDownloadingDiff&) = delete;
-    StateDownloadingDiff& operator=(const StateDownloadingDiff&) = delete;
     ~StateDownloadingDiff() override;
 
    private:
@@ -263,14 +260,14 @@
     void DownloadComplete(const CrxDownloader::Result& download_result);
 
     // Downloads updates for one CRX id only.
-    scoped_refptr<CrxDownloader> crx_downloader_;
+    std::unique_ptr<CrxDownloader> crx_downloader_;
+
+    DISALLOW_COPY_AND_ASSIGN(StateDownloadingDiff);
   };
 
   class StateDownloading : public State {
    public:
     explicit StateDownloading(Component* component);
-    StateDownloading(const StateDownloading&) = delete;
-    StateDownloading& operator=(const StateDownloading&) = delete;
     ~StateDownloading() override;
 
    private:
@@ -285,14 +282,14 @@
     void DownloadComplete(const CrxDownloader::Result& download_result);
 
     // Downloads updates for one CRX id only.
-    scoped_refptr<CrxDownloader> crx_downloader_;
+    std::unique_ptr<CrxDownloader> crx_downloader_;
+
+    DISALLOW_COPY_AND_ASSIGN(StateDownloading);
   };
 
   class StateUpdatingDiff : public State {
    public:
     explicit StateUpdatingDiff(Component* component);
-    StateUpdatingDiff(const StateUpdatingDiff&) = delete;
-    StateUpdatingDiff& operator=(const StateUpdatingDiff&) = delete;
     ~StateUpdatingDiff() override;
 
    private:
@@ -303,13 +300,13 @@
     void InstallComplete(ErrorCategory error_category,
                          int error_code,
                          int extra_code1);
+
+    DISALLOW_COPY_AND_ASSIGN(StateUpdatingDiff);
   };
 
   class StateUpdating : public State {
    public:
     explicit StateUpdating(Component* component);
-    StateUpdating(const StateUpdating&) = delete;
-    StateUpdating& operator=(const StateUpdating&) = delete;
     ~StateUpdating() override;
 
    private:
@@ -320,37 +317,37 @@
     void InstallComplete(ErrorCategory error_category,
                          int error_code,
                          int extra_code1);
+
+    DISALLOW_COPY_AND_ASSIGN(StateUpdating);
   };
 
   class StateUpdated : public State {
    public:
     explicit StateUpdated(Component* component);
-    StateUpdated(const StateUpdated&) = delete;
-    StateUpdated& operator=(const StateUpdated&) = delete;
     ~StateUpdated() override;
 
    private:
     // State overrides.
     void DoHandle() override;
+
+    DISALLOW_COPY_AND_ASSIGN(StateUpdated);
   };
 
   class StateUninstalled : public State {
    public:
     explicit StateUninstalled(Component* component);
-    StateUninstalled(const StateUninstalled&) = delete;
-    StateUninstalled& operator=(const StateUninstalled&) = delete;
     ~StateUninstalled() override;
 
    private:
     // State overrides.
     void DoHandle() override;
+
+    DISALLOW_COPY_AND_ASSIGN(StateUninstalled);
   };
 
   class StateRun : public State {
    public:
     explicit StateRun(Component* component);
-    StateRun(const StateRun&) = delete;
-    StateRun& operator=(const StateRun&) = delete;
     ~StateRun() override;
 
    private:
@@ -362,6 +359,8 @@
     // Runs the action referred by the |action_run_| member of the Component
     // class.
     std::unique_ptr<ActionRunner> action_runner_;
+
+    DISALLOW_COPY_AND_ASSIGN(StateRun);
   };
 
   // Returns true is the update payload for this component can be downloaded
@@ -480,6 +479,8 @@
   // True if this component has reached a final state because all its states
   // have been handled.
   bool is_handled_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(Component);
 };
 
 using IdToComponentPtrMap = std::map<std::string, std::unique_ptr<Component>>;
diff --git a/components/update_client/crx_downloader.cc b/components/update_client/crx_downloader.cc
index 5d634b5..bb1fe04 100644
--- a/components/update_client/crx_downloader.cc
+++ b/components/update_client/crx_downloader.cc
@@ -33,16 +33,15 @@
 
 // On Windows, the first downloader in the chain is a background downloader,
 // which uses the BITS service.
-scoped_refptr<CrxDownloader> CrxDownloader::Create(
+std::unique_ptr<CrxDownloader> CrxDownloader::Create(
     bool is_background_download,
     scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-  scoped_refptr<CrxDownloader> url_fetcher_downloader =
-      base::MakeRefCounted<UrlFetcherDownloader>(nullptr,
-                                                 network_fetcher_factory);
+  std::unique_ptr<CrxDownloader> url_fetcher_downloader =
+      std::make_unique<UrlFetcherDownloader>(nullptr, network_fetcher_factory);
 
 #if defined(OS_WIN)
   if (is_background_download) {
-    return base::MakeRefCounted<BackgroundDownloader>(
+    return std::make_unique<BackgroundDownloader>(
         std::move(url_fetcher_downloader));
   }
 #endif
@@ -50,7 +49,7 @@
   return url_fetcher_downloader;
 }
 
-CrxDownloader::CrxDownloader(scoped_refptr<CrxDownloader> successor)
+CrxDownloader::CrxDownloader(std::unique_ptr<CrxDownloader> successor)
     : main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
       successor_(std::move(successor)) {}
 
@@ -87,7 +86,7 @@
 void CrxDownloader::StartDownload(const std::vector<GURL>& urls,
                                   const std::string& expected_hash,
                                   DownloadCallback download_callback) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(thread_checker_.CalledOnValidThread());
 
   auto error = CrxDownloaderError::NONE;
   if (urls.empty()) {
@@ -116,22 +115,23 @@
     bool is_handled,
     const Result& result,
     const DownloadMetrics& download_metrics) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(thread_checker_.CalledOnValidThread());
 
   if (!result.error)
     base::ThreadPool::PostTask(
         FROM_HERE, kTaskTraits,
-        base::BindOnce(&CrxDownloader::VerifyResponse, this, is_handled, result,
-                       download_metrics));
+        base::BindOnce(&CrxDownloader::VerifyResponse, base::Unretained(this),
+                       is_handled, result, download_metrics));
   else
     main_task_runner()->PostTask(
-        FROM_HERE, base::BindOnce(&CrxDownloader::HandleDownloadError, this,
-                                  is_handled, result, download_metrics));
+        FROM_HERE, base::BindOnce(&CrxDownloader::HandleDownloadError,
+                                  base::Unretained(this), is_handled, result,
+                                  download_metrics));
 }
 
 void CrxDownloader::OnDownloadProgress(int64_t downloaded_bytes,
                                        int64_t total_bytes) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(thread_checker_.CalledOnValidThread());
 
   if (progress_callback_.is_null())
     return;
@@ -164,15 +164,16 @@
   result.response.clear();
 
   main_task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&CrxDownloader::HandleDownloadError, this,
-                                is_handled, result, download_metrics));
+      FROM_HERE, base::BindOnce(&CrxDownloader::HandleDownloadError,
+                                base::Unretained(this), is_handled, result,
+                                download_metrics));
 }
 
 void CrxDownloader::HandleDownloadError(
     bool is_handled,
     const Result& result,
     const DownloadMetrics& download_metrics) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK(thread_checker_.CalledOnValidThread());
   DCHECK_NE(0, result.error);
   DCHECK(result.response.empty());
   DCHECK_NE(0, download_metrics.error);
diff --git a/components/update_client/crx_downloader.h b/components/update_client/crx_downloader.h
index b0c8a81..983c222 100644
--- a/components/update_client/crx_downloader.h
+++ b/components/update_client/crx_downloader.h
@@ -13,9 +13,10 @@
 
 #include "base/callback.h"
 #include "base/files/file_path.h"
+#include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/sequence_checker.h"
 #include "base/single_thread_task_runner.h"
+#include "base/threading/thread_checker.h"
 #include "url/gurl.h"
 
 namespace update_client {
@@ -32,7 +33,7 @@
 // the order they are provided in the StartDownload function argument. After
 // that, the download request is routed to the next downloader in the chain.
 // The members of this class expect to be called from the main thread only.
-class CrxDownloader : public base::RefCountedThreadSafe<CrxDownloader> {
+class CrxDownloader {
  public:
   struct DownloadMetrics {
     enum Downloader { kNone = 0, kUrlFetcher, kBits };
@@ -77,20 +78,18 @@
                                    int64_t total_bytes)>;
 
   using Factory =
-      scoped_refptr<CrxDownloader> (*)(bool,
-                                       scoped_refptr<NetworkFetcherFactory>);
-
-  CrxDownloader(const CrxDownloader&) = delete;
-  CrxDownloader& operator=(const CrxDownloader&) = delete;
+      std::unique_ptr<CrxDownloader> (*)(bool,
+                                         scoped_refptr<NetworkFetcherFactory>);
 
   // Factory method to create an instance of this class and build the
   // chain of responsibility. |is_background_download| specifies that a
   // background downloader be used, if the platform supports it.
   // |task_runner| should be a task runner able to run blocking
   // code such as file IO operations.
-  static scoped_refptr<CrxDownloader> Create(
+  static std::unique_ptr<CrxDownloader> Create(
       bool is_background_download,
       scoped_refptr<NetworkFetcherFactory> network_fetcher_factory);
+  virtual ~CrxDownloader();
 
   void set_progress_callback(const ProgressCallback& progress_callback);
 
@@ -109,8 +108,7 @@
   const std::vector<DownloadMetrics> download_metrics() const;
 
  protected:
-  explicit CrxDownloader(scoped_refptr<CrxDownloader> successor);
-  virtual ~CrxDownloader();
+  explicit CrxDownloader(std::unique_ptr<CrxDownloader> successor);
 
   // Handles the fallback in the case of multiple urls and routing of the
   // download to the following successor in the chain. Derived classes must call
@@ -135,8 +133,6 @@
   }
 
  private:
-  friend class base::RefCountedThreadSafe<CrxDownloader>;
-
   virtual void DoStartDownload(const GURL& url) = 0;
 
   void VerifyResponse(bool is_handled,
@@ -147,7 +143,7 @@
                            const Result& result,
                            const DownloadMetrics& download_metrics);
 
-  SEQUENCE_CHECKER(sequence_checker_);
+  base::ThreadChecker thread_checker_;
 
   // Used to post callbacks to the main thread.
   scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
@@ -156,13 +152,15 @@
 
   // The SHA256 hash of the download payload in hexadecimal format.
   std::string expected_hash_;
-  scoped_refptr<CrxDownloader> successor_;
+  std::unique_ptr<CrxDownloader> successor_;
   DownloadCallback download_callback_;
   ProgressCallback progress_callback_;
 
   std::vector<GURL>::iterator current_url_;
 
   std::vector<DownloadMetrics> download_metrics_;
+
+  DISALLOW_COPY_AND_ASSIGN(CrxDownloader);
 };
 
 }  // namespace update_client
diff --git a/components/update_client/crx_downloader_unittest.cc b/components/update_client/crx_downloader_unittest.cc
index b6478d4..52eac3e0a 100644
--- a/components/update_client/crx_downloader_unittest.cc
+++ b/components/update_client/crx_downloader_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "components/update_client/crx_downloader.h"
 
+#include <memory>
 #include <utility>
 
 #include "base/bind.h"
@@ -68,7 +69,7 @@
                    int net_error);
 
  protected:
-  scoped_refptr<CrxDownloader> crx_downloader_;
+  std::unique_ptr<CrxDownloader> crx_downloader_;
 
   network::TestURLLoaderFactory test_url_loader_factory_;
 
@@ -119,7 +120,7 @@
 }
 
 void CrxDownloaderTest::TearDown() {
-  crx_downloader_ = nullptr;
+  crx_downloader_.reset();
 }
 
 void CrxDownloaderTest::Quit() {
@@ -174,7 +175,6 @@
   RunThreadsUntilIdle();
 }
 
-// TODO(crbug.com/1104691): rewrite the tests to not use RunUntilIdle().
 void CrxDownloaderTest::RunThreadsUntilIdle() {
   task_environment_.RunUntilIdle();
   base::RunLoop().RunUntilIdle();
diff --git a/components/update_client/update_client_unittest.cc b/components/update_client/update_client_unittest.cc
index 8f4cbac..c8fdcf6 100644
--- a/components/update_client/update_client_unittest.cc
+++ b/components/update_client/update_client_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/location.h"
+#include "base/macros.h"
 #include "base/memory/ref_counted.h"
 #include "base/optional.h"
 #include "base/path_service.h"
@@ -135,8 +136,6 @@
   };
 
   explicit MockPingManagerImpl(scoped_refptr<Configurator> config);
-  MockPingManagerImpl(const MockPingManagerImpl&) = delete;
-  MockPingManagerImpl& operator=(const MockPingManagerImpl&) = delete;
 
   void SendPing(const Component& component, Callback callback) override;
 
@@ -150,6 +149,7 @@
  private:
   std::vector<PingData> ping_data_;
   std::vector<base::Value> events_;
+  DISALLOW_COPY_AND_ASSIGN(MockPingManagerImpl);
 };
 
 MockPingManagerImpl::MockPingManagerImpl(scoped_refptr<Configurator> config)
@@ -188,8 +188,6 @@
 class UpdateClientTest : public testing::Test {
  public:
   UpdateClientTest();
-  UpdateClientTest(const UpdateClientTest&) = delete;
-  UpdateClientTest& operator=(const UpdateClientTest&) = delete;
   ~UpdateClientTest() override;
 
  protected:
@@ -215,6 +213,8 @@
       base::MakeRefCounted<TestConfigurator>(pref_.get());
   std::unique_ptr<update_client::PersistedData> metadata_ =
       std::make_unique<PersistedData>(pref_.get(), nullptr);
+
+  DISALLOW_COPY_AND_ASSIGN(UpdateClientTest);
 };
 
 constexpr int UpdateClientTest::kNumWorkerThreads_;
@@ -307,17 +307,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
   };
 
@@ -489,17 +487,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override {
       DownloadMetrics download_metrics;
       download_metrics.url = url;
@@ -734,17 +730,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override {
       DownloadMetrics download_metrics;
       download_metrics.url = url;
@@ -969,17 +963,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override {
       DownloadMetrics download_metrics;
       FilePath path;
@@ -1133,17 +1125,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override { NOTREACHED(); }
   };
 
@@ -1336,17 +1326,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override {
       DownloadMetrics download_metrics;
       FilePath path;
@@ -1660,17 +1648,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override {
       DownloadMetrics download_metrics;
       FilePath path;
@@ -2021,17 +2007,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override {
       DownloadMetrics download_metrics;
       download_metrics.url = url;
@@ -2292,17 +2276,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override {
       DownloadMetrics download_metrics;
       FilePath path;
@@ -2562,17 +2544,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
   };
 
@@ -2747,17 +2727,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override {
       DownloadMetrics download_metrics;
       FilePath path;
@@ -2931,17 +2909,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override { NOTREACHED(); }
   };
 
@@ -3078,17 +3054,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
   };
 
@@ -3190,17 +3164,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
   };
 
@@ -3254,15 +3226,14 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
       return nullptr;
     }
 
-    MockCrxDownloader() : CrxDownloader(nullptr) {}
-
    private:
+    MockCrxDownloader() : CrxDownloader(nullptr) {}
     ~MockCrxDownloader() override = default;
 
     void DoStartDownload(const GURL& url) override {}
@@ -3387,17 +3358,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
   };
 
@@ -3632,17 +3601,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override {
       DownloadMetrics download_metrics;
       FilePath path;
@@ -3830,17 +3797,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
   };
 
@@ -4002,17 +3967,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
   };
 
@@ -4187,17 +4150,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override {
       DownloadMetrics download_metrics;
       FilePath path;
@@ -4363,17 +4324,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
   };
 
@@ -4542,17 +4501,15 @@
 
   class MockCrxDownloader : public CrxDownloader {
    public:
-    static scoped_refptr<CrxDownloader> Create(
+    static std::unique_ptr<CrxDownloader> Create(
         bool is_background_download,
         scoped_refptr<NetworkFetcherFactory> network_fetcher_factory) {
-      return base::MakeRefCounted<MockCrxDownloader>();
+      return std::make_unique<MockCrxDownloader>();
     }
 
     MockCrxDownloader() : CrxDownloader(nullptr) {}
 
    private:
-    ~MockCrxDownloader() override = default;
-
     void DoStartDownload(const GURL& url) override { EXPECT_TRUE(false); }
   };
 
diff --git a/components/update_client/url_fetcher_downloader.cc b/components/update_client/url_fetcher_downloader.cc
index 906738a..fe05941 100644
--- a/components/update_client/url_fetcher_downloader.cc
+++ b/components/update_client/url_fetcher_downloader.cc
@@ -21,21 +21,23 @@
 namespace update_client {
 
 UrlFetcherDownloader::UrlFetcherDownloader(
-    scoped_refptr<CrxDownloader> successor,
+    std::unique_ptr<CrxDownloader> successor,
     scoped_refptr<NetworkFetcherFactory> network_fetcher_factory)
     : CrxDownloader(std::move(successor)),
       network_fetcher_factory_(network_fetcher_factory) {}
 
 UrlFetcherDownloader::~UrlFetcherDownloader() {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 }
 
 void UrlFetcherDownloader::DoStartDownload(const GURL& url) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   base::ThreadPool::PostTaskAndReply(
       FROM_HERE, kTaskTraits,
-      base::BindOnce(&UrlFetcherDownloader::CreateDownloadDir, this),
-      base::BindOnce(&UrlFetcherDownloader::StartURLFetch, this, url));
+      base::BindOnce(&UrlFetcherDownloader::CreateDownloadDir,
+                     base::Unretained(this)),
+      base::BindOnce(&UrlFetcherDownloader::StartURLFetch,
+                     base::Unretained(this), url));
 }
 
 void UrlFetcherDownloader::CreateDownloadDir() {
@@ -44,7 +46,7 @@
 }
 
 void UrlFetcherDownloader::StartURLFetch(const GURL& url) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
   if (download_dir_.empty()) {
     Result result;
@@ -60,7 +62,8 @@
 
     main_task_runner()->PostTask(
         FROM_HERE, base::BindOnce(&UrlFetcherDownloader::OnDownloadComplete,
-                                  this, false, result, download_metrics));
+                                  base::Unretained(this), false, result,
+                                  download_metrics));
     return;
   }
 
@@ -68,16 +71,19 @@
   network_fetcher_ = network_fetcher_factory_->Create();
   network_fetcher_->DownloadToFile(
       url, file_path_,
-      base::BindOnce(&UrlFetcherDownloader::OnResponseStarted, this),
-      base::BindRepeating(&UrlFetcherDownloader::OnDownloadProgress, this),
-      base::BindOnce(&UrlFetcherDownloader::OnNetworkFetcherComplete, this));
+      base::BindOnce(&UrlFetcherDownloader::OnResponseStarted,
+                     base::Unretained(this)),
+      base::BindRepeating(&UrlFetcherDownloader::OnDownloadProgress,
+                          base::Unretained(this)),
+      base::BindOnce(&UrlFetcherDownloader::OnNetworkFetcherComplete,
+                     base::Unretained(this)));
 
   download_start_time_ = base::TimeTicks::Now();
 }
 
 void UrlFetcherDownloader::OnNetworkFetcherComplete(int net_error,
                                                     int64_t content_size) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
   const base::TimeTicks download_end_time(base::TimeTicks::Now());
   const base::TimeDelta download_time =
@@ -125,15 +131,15 @@
   }
 
   main_task_runner()->PostTask(
-      FROM_HERE, base::BindOnce(&UrlFetcherDownloader::OnDownloadComplete, this,
-                                is_handled, result, download_metrics));
-  network_fetcher_ = nullptr;
+      FROM_HERE, base::BindOnce(&UrlFetcherDownloader::OnDownloadComplete,
+                                base::Unretained(this), is_handled, result,
+                                download_metrics));
 }
 
 // This callback is used to indicate that a download has been started.
 void UrlFetcherDownloader::OnResponseStarted(int response_code,
                                              int64_t content_length) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
   VLOG(1) << "url fetcher response started for: " << url().spec();
 
@@ -142,7 +148,7 @@
 }
 
 void UrlFetcherDownloader::OnDownloadProgress(int64_t current) {
-  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   CrxDownloader::OnDownloadProgress(current, total_bytes_);
 }
 
diff --git a/components/update_client/url_fetcher_downloader.h b/components/update_client/url_fetcher_downloader.h
index 111aa4a6..eedee7f7 100644
--- a/components/update_client/url_fetcher_downloader.h
+++ b/components/update_client/url_fetcher_downloader.h
@@ -10,8 +10,9 @@
 #include <memory>
 
 #include "base/files/file_path.h"
+#include "base/macros.h"
 #include "base/memory/ref_counted.h"
-#include "base/sequence_checker.h"
+#include "base/threading/thread_checker.h"
 #include "base/time/time.h"
 #include "components/update_client/crx_downloader.h"
 
@@ -24,14 +25,12 @@
 class UrlFetcherDownloader : public CrxDownloader {
  public:
   UrlFetcherDownloader(
-      scoped_refptr<CrxDownloader> successor,
+      std::unique_ptr<CrxDownloader> successor,
       scoped_refptr<NetworkFetcherFactory> network_fetcher_factory);
-  UrlFetcherDownloader(const UrlFetcherDownloader&) = delete;
-  UrlFetcherDownloader& operator=(const UrlFetcherDownloader&) = delete;
+  ~UrlFetcherDownloader() override;
 
  private:
   // Overrides for CrxDownloader.
-  ~UrlFetcherDownloader() override;
   void DoStartDownload(const GURL& url) override;
 
   void CreateDownloadDir();
@@ -40,7 +39,7 @@
   void OnResponseStarted(int response_code, int64_t content_length);
   void OnDownloadProgress(int64_t content_length);
 
-  SEQUENCE_CHECKER(sequence_checker_);
+  THREAD_CHECKER(thread_checker_);
 
   scoped_refptr<NetworkFetcherFactory> network_fetcher_factory_;
   std::unique_ptr<NetworkFetcher> network_fetcher_;
@@ -55,6 +54,8 @@
 
   int response_code_ = -1;
   int64_t total_bytes_ = -1;
+
+  DISALLOW_COPY_AND_ASSIGN(UrlFetcherDownloader);
 };
 
 }  // namespace update_client
diff --git a/content/browser/background_fetch/background_fetch.proto b/content/browser/background_fetch/background_fetch.proto
index fb3bcd0..1ceed72 100644
--- a/content/browser/background_fetch/background_fetch.proto
+++ b/content/browser/background_fetch/background_fetch.proto
@@ -72,7 +72,7 @@
     // https://w3c.github.io/manifest/#purpose-member
     enum Purpose {
       ANY = 1;
-      BADGE = 2;
+      MONOCHROME = 2;
       MASKABLE = 3;
     }
 
diff --git a/content/browser/background_fetch/storage/create_metadata_task.cc b/content/browser/background_fetch/storage/create_metadata_task.cc
index 96c3645d..56a9325e 100644
--- a/content/browser/background_fetch/storage/create_metadata_task.cc
+++ b/content/browser/background_fetch/storage/create_metadata_task.cc
@@ -264,9 +264,9 @@
           image_resource_proto->add_purpose(
               proto::BackgroundFetchOptions_ImageResource_Purpose_ANY);
           break;
-        case blink::Manifest::ImageResource::Purpose::BADGE:
+        case blink::Manifest::ImageResource::Purpose::MONOCHROME:
           image_resource_proto->add_purpose(
-              proto::BackgroundFetchOptions_ImageResource_Purpose_BADGE);
+              proto::BackgroundFetchOptions_ImageResource_Purpose_MONOCHROME);
           break;
         case blink::Manifest::ImageResource::Purpose::MASKABLE:
           image_resource_proto->add_purpose(
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 4cebdbea..0358d1b 100644
--- a/content/browser/background_fetch/storage/get_initialization_data_task.cc
+++ b/content/browser/background_fetch/storage/get_initialization_data_task.cc
@@ -361,9 +361,9 @@
           case proto::BackgroundFetchOptions_ImageResource_Purpose_ANY:
             ir.purpose.push_back(blink::Manifest::ImageResource::Purpose::ANY);
             break;
-          case proto::BackgroundFetchOptions_ImageResource_Purpose_BADGE:
+          case proto::BackgroundFetchOptions_ImageResource_Purpose_MONOCHROME:
             ir.purpose.push_back(
-                blink::Manifest::ImageResource::Purpose::BADGE);
+                blink::Manifest::ImageResource::Purpose::MONOCHROME);
             break;
         }
       }
diff --git a/content/browser/frame_host/clipboard_host_impl.cc b/content/browser/frame_host/clipboard_host_impl.cc
index 7f85cfb..8404c8b 100644
--- a/content/browser/frame_host/clipboard_host_impl.cc
+++ b/content/browser/frame_host/clipboard_host_impl.cc
@@ -126,7 +126,8 @@
     ui::ClipboardBuffer clipboard_buffer,
     ReadAvailableTypesCallback callback) {
   std::vector<base::string16> types;
-  clipboard_->ReadAvailableTypes(clipboard_buffer, &types);
+  clipboard_->ReadAvailableTypes(clipboard_buffer, /* data_dst = */ nullptr,
+                                 &types);
   std::move(callback).Run(types);
 }
 
@@ -137,24 +138,29 @@
   switch (format) {
     case blink::mojom::ClipboardFormat::kPlaintext:
       result = clipboard_->IsFormatAvailable(
-          ui::ClipboardFormatType::GetPlainTextType(), clipboard_buffer);
+          ui::ClipboardFormatType::GetPlainTextType(), clipboard_buffer,
+          /* data_dst = */ nullptr);
 #if defined(OS_WIN)
       result |= clipboard_->IsFormatAvailable(
-          ui::ClipboardFormatType::GetPlainTextAType(), clipboard_buffer);
+          ui::ClipboardFormatType::GetPlainTextAType(), clipboard_buffer,
+          /* data_dst = */ nullptr);
 #endif
       break;
     case blink::mojom::ClipboardFormat::kHtml:
       result = clipboard_->IsFormatAvailable(
-          ui::ClipboardFormatType::GetHtmlType(), clipboard_buffer);
+          ui::ClipboardFormatType::GetHtmlType(), clipboard_buffer,
+          /* data_dst = */ nullptr);
       break;
     case blink::mojom::ClipboardFormat::kSmartPaste:
       result = clipboard_->IsFormatAvailable(
-          ui::ClipboardFormatType::GetWebKitSmartPasteType(), clipboard_buffer);
+          ui::ClipboardFormatType::GetWebKitSmartPasteType(), clipboard_buffer,
+          /* data_dst = */ nullptr);
       break;
     case blink::mojom::ClipboardFormat::kBookmark:
 #if defined(OS_WIN) || defined(OS_MACOSX)
       result = clipboard_->IsFormatAvailable(
-          ui::ClipboardFormatType::GetUrlType(), clipboard_buffer);
+          ui::ClipboardFormatType::GetUrlType(), clipboard_buffer,
+          /* data_dst = */ nullptr);
 #else
       result = false;
 #endif
@@ -167,14 +173,17 @@
                                  ReadTextCallback callback) {
   base::string16 result;
   if (clipboard_->IsFormatAvailable(ui::ClipboardFormatType::GetPlainTextType(),
-                                    clipboard_buffer)) {
-    clipboard_->ReadText(clipboard_buffer, &result);
+                                    clipboard_buffer,
+                                    /* data_dst = */ nullptr)) {
+    clipboard_->ReadText(clipboard_buffer, /* data_dst = */ nullptr, &result);
   } else {
 #if defined(OS_WIN)
     if (clipboard_->IsFormatAvailable(
-            ui::ClipboardFormatType::GetPlainTextAType(), clipboard_buffer)) {
+            ui::ClipboardFormatType::GetPlainTextAType(), clipboard_buffer,
+            /* data_dst = */ nullptr)) {
       std::string ascii;
-      clipboard_->ReadAsciiText(clipboard_buffer, &ascii);
+      clipboard_->ReadAsciiText(clipboard_buffer,
+                                /* data_dst = */ nullptr, &ascii);
       result = base::ASCIIToUTF16(ascii);
     }
 #endif
@@ -200,8 +209,8 @@
   std::string src_url_str;
   uint32_t fragment_start = 0;
   uint32_t fragment_end = 0;
-  clipboard_->ReadHTML(clipboard_buffer, &markup, &src_url_str, &fragment_start,
-                       &fragment_end);
+  clipboard_->ReadHTML(clipboard_buffer, /* data_dst = */ nullptr, &markup,
+                       &src_url_str, &fragment_start, &fragment_end);
 
   std::string data = base::UTF16ToUTF8(markup);
   PerformPasteIfAllowed(
@@ -223,7 +232,7 @@
 void ClipboardHostImpl::ReadRtf(ui::ClipboardBuffer clipboard_buffer,
                                 ReadRtfCallback callback) {
   std::string result;
-  clipboard_->ReadRTF(clipboard_buffer, &result);
+  clipboard_->ReadRTF(clipboard_buffer, /* data_dst = */ nullptr, &result);
 
   std::string data = result;
   PerformPasteIfAllowed(clipboard_->GetSequenceNumber(clipboard_buffer),
@@ -241,6 +250,7 @@
 void ClipboardHostImpl::ReadImage(ui::ClipboardBuffer clipboard_buffer,
                                   ReadImageCallback callback) {
   clipboard_->ReadImage(clipboard_buffer,
+                        /* data_dst = */ nullptr,
                         base::BindOnce(&ClipboardHostImpl::OnReadImage,
                                        weak_ptr_factory_.GetWeakPtr(),
                                        clipboard_buffer, std::move(callback)));
@@ -269,7 +279,8 @@
                                        const base::string16& type,
                                        ReadCustomDataCallback callback) {
   base::string16 result;
-  clipboard_->ReadCustomData(clipboard_buffer, type, &result);
+  clipboard_->ReadCustomData(clipboard_buffer, type, /* data_dst = */ nullptr,
+                             &result);
 
   std::string data = base::UTF16ToUTF8(result);
   PerformPasteIfAllowed(
diff --git a/content/browser/frame_host/clipboard_host_impl_unittest.cc b/content/browser/frame_host/clipboard_host_impl_unittest.cc
index d844f75..302ecab 100644
--- a/content/browser/frame_host/clipboard_host_impl_unittest.cc
+++ b/content/browser/frame_host/clipboard_host_impl_unittest.cc
@@ -86,10 +86,10 @@
                                  ui::ClipboardBuffer::kCopyPaste));
   EXPECT_FALSE(system_clipboard()->IsFormatAvailable(
       ui::ClipboardFormatType::GetPlainTextType(),
-      ui::ClipboardBuffer::kCopyPaste));
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr));
   EXPECT_TRUE(system_clipboard()->IsFormatAvailable(
-      ui::ClipboardFormatType::GetBitmapType(),
-      ui::ClipboardBuffer::kCopyPaste));
+      ui::ClipboardFormatType::GetBitmapType(), ui::ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
 
   SkBitmap actual = ui::clipboard_test_util::ReadImage(system_clipboard());
   EXPECT_TRUE(gfx::BitmapsAreEqual(bitmap, actual));
diff --git a/content/browser/frame_host/raw_clipboard_host_impl.cc b/content/browser/frame_host/raw_clipboard_host_impl.cc
index 85d2fdf..5f311fa 100644
--- a/content/browser/frame_host/raw_clipboard_host_impl.cc
+++ b/content/browser/frame_host/raw_clipboard_host_impl.cc
@@ -91,7 +91,7 @@
     return;
   std::vector<base::string16> raw_types =
       clipboard_->ReadAvailablePlatformSpecificFormatNames(
-          ui::ClipboardBuffer::kCopyPaste);
+          ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr);
   std::move(callback).Run(raw_types);
 }
 
@@ -106,7 +106,8 @@
 
   std::string result;
   clipboard_->ReadData(
-      ui::ClipboardFormatType::GetType(base::UTF16ToUTF8(format)), &result);
+      ui::ClipboardFormatType::GetType(base::UTF16ToUTF8(format)),
+      /* data_dst = */ nullptr, &result);
   base::span<const uint8_t> span(
       reinterpret_cast<const uint8_t*>(result.data()), result.size());
   mojo_base::BigBuffer buffer = mojo_base::BigBuffer(span);
diff --git a/content/browser/loader/prefetch_browsertest.cc b/content/browser/loader/prefetch_browsertest.cc
index 3244122..70a7bd9f 100644
--- a/content/browser/loader/prefetch_browsertest.cc
+++ b/content/browser/loader/prefetch_browsertest.cc
@@ -142,16 +142,7 @@
   EXPECT_EQ(1, main_page_counter->GetRequestCount());
 
   NavigateToURLAndWaitTitle(destination_url, "Prefetch Target");
-  // PrefetchPrivacyChanges relies on kError redirect_mode, and it is handled
-  // in CorsURLLoader which code path is activated only if OOR-CORS is enabled.
-  // OOR-CORS enabled case is running only at linux-oor-cors-rel bot until the
-  // feature is enabled by default.
-  // See https://ci.chromium.org/p/chromium/builders/ci/linux-oor-cors-rel.
-  const int expected_request_count =
-      (privacy_changes_enabled_ &&
-       network::features::ShouldEnableOutOfBlinkCorsForTesting())
-          ? 1
-          : 2;
+  const int expected_request_count = privacy_changes_enabled_ ? 1 : 2;
   EXPECT_EQ(expected_request_count, destination_counter->GetRequestCount());
   EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
 }
diff --git a/content/browser/net/split_cache_browsertest.cc b/content/browser/net/split_cache_browsertest.cc
index fdffa80..3878728 100644
--- a/content/browser/net/split_cache_browsertest.cc
+++ b/content/browser/net/split_cache_browsertest.cc
@@ -762,8 +762,8 @@
       GenURL("e.com", "/worker.js")));
 }
 
-// TODO(http://crbug.com/997732): Flaky on Linux.
-#if defined(OS_LINUX)
+// TODO(http://crbug.com/997732): Flaky on Linux and macOS.
+#if defined(OS_LINUX) || defined(OS_MACOSX)
 #define MAYBE_SplitCacheDedicatedWorkerScripts \
   DISABLED_SplitCacheDedicatedWorkersScripts
 #else
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc
index eda28b5..0708283 100644
--- a/content/browser/renderer_host/compositor_impl_android.cc
+++ b/content/browser/renderer_host/compositor_impl_android.cc
@@ -117,6 +117,10 @@
   } else if (display_color_space == gfx::ColorSpace::CreateDisplayP3D65()) {
     attributes.color_space = gpu::COLOR_SPACE_DISPLAY_P3;
   } else {
+    // We don't support HDR on Android yet, but when we do, this function should
+    // be updated to support it.
+    DCHECK(!display_color_space.IsHDR());
+
     attributes.color_space = gpu::COLOR_SPACE_UNSPECIFIED;
     DLOG(ERROR) << "Android color space is neither sRGB nor P3, output color "
                    "will be incorrect.";
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc b/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
index 1f06e655..2d76b978 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_aura.cc
@@ -441,7 +441,7 @@
     case ui::TouchEditable::kPaste: {
       base::string16 result;
       ui::Clipboard::GetForCurrentThread()->ReadText(
-          ui::ClipboardBuffer::kCopyPaste, &result);
+          ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &result);
       return editable && !result.empty();
     }
     default:
diff --git a/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc b/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
index 0ddb0c4..55afcce 100644
--- a/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
+++ b/content/browser/renderer_host/input/touch_selection_controller_client_child_frame.cc
@@ -159,7 +159,7 @@
     case ui::TouchEditable::kPaste: {
       base::string16 result;
       ui::Clipboard::GetForCurrentThread()->ReadText(
-          ui::ClipboardBuffer::kCopyPaste, &result);
+          ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &result);
       return editable && !result.empty();
     }
     default:
diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index 95cd44d..ee8e690 100644
--- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -6196,7 +6196,8 @@
 
     // Retrieve the selected text from clipboard and verify it is as expected.
     base::string16 result_text;
-    clipboard->ReadText(ui::ClipboardBuffer::kSelection, &result_text);
+    clipboard->ReadText(ui::ClipboardBuffer::kSelection,
+                        /* data_dst = */ nullptr, &result_text);
     EXPECT_EQ(expected_text, result_text);
   }
 }
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc
index 2c2b7500..902be3c 100644
--- a/content/child/runtime_features.cc
+++ b/content/child/runtime_features.cc
@@ -570,7 +570,6 @@
           blink::features::kNativeFileSystemAPI.name,
           base::FeatureList::OVERRIDE_ENABLE_FEATURE)) {
     WebRuntimeFeatures::EnableFeatureFromString("NativeFileSystem", true);
-    WebRuntimeFeatures::EnableFeatureFromString("LegacyNativeFileSystem", true);
   }
   if (base::FeatureList::IsEnabled(blink::features::kNativeFileSystemAPI) &&
       base::FeatureList::IsEnabled(blink::features::kFileHandlingAPI)) {
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc
index 91acda8..bd72341 100644
--- a/content/public/test/browser_test_utils.cc
+++ b/content/public/test/browser_test_utils.cc
@@ -2809,7 +2809,7 @@
 
 void BrowserTestClipboardScope::GetText(std::string* result) {
   ui::Clipboard::GetForCurrentThread()->ReadAsciiText(
-      ui::ClipboardBuffer::kCopyPaste, result);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, result);
 }
 
 class FrameFocusedObserver::FrameTreeNodeObserverImpl
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc
index 9d75e168..ee6e21c 100644
--- a/content/renderer/render_widget.cc
+++ b/content/renderer/render_widget.cc
@@ -1527,8 +1527,7 @@
   // The ViewportVisibleRect derives from the LayerTreeView's viewport size,
   // which is set above.
   layer_tree_host_->SetViewportVisibleRect(ViewportVisibleRect());
-  layer_tree_host_->SetRasterColorSpace(
-      screen_info_.color_space.GetRasterColorSpace());
+  layer_tree_host_->SetRasterColorSpace(screen_info_.color_space);
 
   if (orientation_changed)
     OnOrientationChange();
diff --git a/content/test/data/payments/payment_app_invocation.html b/content/test/data/payments/payment_app_invocation.html
index 6cb5dc39..25e74776 100644
--- a/content/test/data/payments/payment_app_invocation.html
+++ b/content/test/data/payments/payment_app_invocation.html
@@ -33,7 +33,7 @@
               'src': 'icon-2x.png',
               'sizes': '96x96',
               'type': 'image/png',
-              'purpose': 'any badge'
+              'purpose': 'any monochrome'
             }
           ]
         }),
diff --git a/docs/testing/test_wrapper_api.md b/docs/testing/test_wrapper_api.md
new file mode 100644
index 0000000..b481bdb
--- /dev/null
+++ b/docs/testing/test_wrapper_api.md
@@ -0,0 +1,29 @@
+# Test Wrapper API
+
+In order to simplify the calling conventions for tests that we run on our
+continuous integration system, we require them to follow a simple API
+convention. For a given GN label //X:Y and build directory //Z in a checkout
+(e.g., //url:url_unittests and //out/Release), we expect there to be:
+
+    * A file `$Z/$Y.runtime_deps` containing a list of files needed to run
+      the test (in the format produced by `gn desc //Z //X:Y runtime_deps`,
+      which is a newline-separated list of paths relative to Z)
+    * An executable file `$Z/bin/run_$Y` which does everything needed to set
+      up and run the test with all of the appropriate flags. This will usually
+      be a vpython script.
+    * (on Windows) A file `$Z/bin/run_$Y.bat` file that will turn around
+      and invoke the corresponding run_$ vpython script.
+
+If you create a directory snapshot with the files listed in the .runtime_deps
+file, cd to $Z, and run bin/run_$Y, then the test should run to completion
+successfully.
+
+The script file MUST honor the `GTEST_SHARD_INDEX` and `GTEST_TOTAL_SHARDS`
+environment variables as documented in
+[the Test Executable API](test_executable_api.md) and SHOULD conform to
+the Test Executable API in other respects (i.e., honor the
+`--isolated-script-test-filter` arg and other command line flags specified
+in that API).
+
+TODO(crbug.com/816629): Convert everything to the Test Executable API, and
+change the above SHOULD to a MUST.
diff --git a/gpu/command_buffer/service/shared_context_state.cc b/gpu/command_buffer/service/shared_context_state.cc
index 16171bc..30126252 100644
--- a/gpu/command_buffer/service/shared_context_state.cc
+++ b/gpu/command_buffer/service/shared_context_state.cc
@@ -265,6 +265,7 @@
     options.fShaderErrorHandler = this;
     if (gpu_preferences.force_max_texture_size)
       options.fMaxTextureSizeOverride = gpu_preferences.force_max_texture_size;
+    options.fPreferExternalImagesOverES3 = true;
     owned_gr_context_ = GrContext::MakeGL(std::move(interface), options);
     gr_context_ = owned_gr_context_.get();
   }
diff --git a/gpu/config/gpu_workaround_list.txt b/gpu/config/gpu_workaround_list.txt
index fff34a4e..0432368 100644
--- a/gpu/config/gpu_workaround_list.txt
+++ b/gpu/config/gpu_workaround_list.txt
@@ -12,6 +12,7 @@
 decode_encode_srgb_for_generatemipmap
 depth_stencil_renderbuffer_resize_emulation
 disable_2d_canvas_auto_flush
+disable_accelerated_av1_decode
 disable_accelerated_vpx_decode
 disable_async_readpixels
 disable_av_sample_buffer_display_layer
diff --git a/headless/lib/browser/headless_clipboard.cc b/headless/lib/browser/headless_clipboard.cc
index b275aee..a4c4994e 100644
--- a/headless/lib/browser/headless_clipboard.cc
+++ b/headless/lib/browser/headless_clipboard.cc
@@ -24,8 +24,12 @@
   return GetStore(buffer).sequence_number;
 }
 
-bool HeadlessClipboard::IsFormatAvailable(const ui::ClipboardFormatType& format,
-                                          ui::ClipboardBuffer buffer) const {
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
+bool HeadlessClipboard::IsFormatAvailable(
+    const ui::ClipboardFormatType& format,
+    ui::ClipboardBuffer buffer,
+    const ui::ClipboardDataEndpoint* data_dst) const {
   return base::Contains(GetStore(buffer).data, format);
 }
 
@@ -33,26 +37,36 @@
   GetStore(buffer).Clear();
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void HeadlessClipboard::ReadAvailableTypes(
     ui::ClipboardBuffer buffer,
+    const ui::ClipboardDataEndpoint* data_dst,
     std::vector<base::string16>* types) const {
   DCHECK(types);
   types->clear();
 
-  if (IsFormatAvailable(ui::ClipboardFormatType::GetPlainTextType(), buffer))
+  if (IsFormatAvailable(ui::ClipboardFormatType::GetPlainTextType(), buffer,
+                        data_dst))
     types->push_back(base::UTF8ToUTF16(ui::kMimeTypeText));
-  if (IsFormatAvailable(ui::ClipboardFormatType::GetHtmlType(), buffer))
+  if (IsFormatAvailable(ui::ClipboardFormatType::GetHtmlType(), buffer,
+                        data_dst))
     types->push_back(base::UTF8ToUTF16(ui::kMimeTypeHTML));
 
-  if (IsFormatAvailable(ui::ClipboardFormatType::GetRtfType(), buffer))
+  if (IsFormatAvailable(ui::ClipboardFormatType::GetRtfType(), buffer,
+                        data_dst))
     types->push_back(base::UTF8ToUTF16(ui::kMimeTypeRTF));
-  if (IsFormatAvailable(ui::ClipboardFormatType::GetBitmapType(), buffer))
+  if (IsFormatAvailable(ui::ClipboardFormatType::GetBitmapType(), buffer,
+                        data_dst))
     types->push_back(base::UTF8ToUTF16(ui::kMimeTypePNG));
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 std::vector<base::string16>
 HeadlessClipboard::ReadAvailablePlatformSpecificFormatNames(
-    ui::ClipboardBuffer buffer) const {
+    ui::ClipboardBuffer buffer,
+    const ui::ClipboardDataEndpoint* data_dst) const {
   const auto& data = GetStore(buffer).data;
   std::vector<base::string16> types;
   types.reserve(data.size());
@@ -64,14 +78,20 @@
   return types;
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void HeadlessClipboard::ReadText(ui::ClipboardBuffer buffer,
+                                 const ui::ClipboardDataEndpoint* data_dst,
                                  base::string16* result) const {
   std::string result8;
-  ReadAsciiText(buffer, &result8);
+  ReadAsciiText(buffer, data_dst, &result8);
   *result = base::UTF8ToUTF16(result8);
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void HeadlessClipboard::ReadAsciiText(ui::ClipboardBuffer buffer,
+                                      const ui::ClipboardDataEndpoint* data_dst,
                                       std::string* result) const {
   result->clear();
   const DataStore& store = GetStore(buffer);
@@ -80,7 +100,10 @@
     *result = it->second;
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void HeadlessClipboard::ReadHTML(ui::ClipboardBuffer buffer,
+                                 const ui::ClipboardDataEndpoint* data_dst,
                                  base::string16* markup,
                                  std::string* src_url,
                                  uint32_t* fragment_start,
@@ -96,7 +119,10 @@
   *fragment_end = base::checked_cast<uint32_t>(markup->size());
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void HeadlessClipboard::ReadRTF(ui::ClipboardBuffer buffer,
+                                const ui::ClipboardDataEndpoint* data_dst,
                                 std::string* result) const {
   result->clear();
   const DataStore& store = GetStore(buffer);
@@ -105,16 +131,26 @@
     *result = it->second;
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void HeadlessClipboard::ReadImage(ui::ClipboardBuffer buffer,
+                                  const ui::ClipboardDataEndpoint* data_dst,
                                   ReadImageCallback callback) const {
   std::move(callback).Run(GetStore(buffer).image);
 }
 
-void HeadlessClipboard::ReadCustomData(ui::ClipboardBuffer clipboard_buffer,
-                                       const base::string16& type,
-                                       base::string16* result) const {}
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
+void HeadlessClipboard::ReadCustomData(
+    ui::ClipboardBuffer clipboard_buffer,
+    const base::string16& type,
+    const ui::ClipboardDataEndpoint* data_dst,
+    base::string16* result) const {}
 
-void HeadlessClipboard::ReadBookmark(base::string16* title,
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
+void HeadlessClipboard::ReadBookmark(const ui::ClipboardDataEndpoint* data_dst,
+                                     base::string16* title,
                                      std::string* url) const {
   const DataStore& store = GetDefaultStore();
   auto it = store.data.find(ui::ClipboardFormatType::GetUrlType());
@@ -123,7 +159,10 @@
   *title = base::UTF8ToUTF16(store.url_title);
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void HeadlessClipboard::ReadData(const ui::ClipboardFormatType& format,
+                                 const ui::ClipboardDataEndpoint* data_dst,
                                  std::string* result) const {
   result->clear();
   const DataStore& store = GetDefaultStore();
diff --git a/headless/lib/browser/headless_clipboard.h b/headless/lib/browser/headless_clipboard.h
index ef05153..e8539aa 100644
--- a/headless/lib/browser/headless_clipboard.h
+++ b/headless/lib/browser/headless_clipboard.h
@@ -26,30 +26,44 @@
   // Clipboard overrides.
   void OnPreShutdown() override;
   uint64_t GetSequenceNumber(ui::ClipboardBuffer buffer) const override;
-  bool IsFormatAvailable(const ui::ClipboardFormatType& format,
-                         ui::ClipboardBuffer buffer) const override;
+  bool IsFormatAvailable(
+      const ui::ClipboardFormatType& format,
+      ui::ClipboardBuffer buffer,
+      const ui::ClipboardDataEndpoint* data_dst) const override;
   void Clear(ui::ClipboardBuffer buffer) override;
   void ReadAvailableTypes(ui::ClipboardBuffer buffer,
+                          const ui::ClipboardDataEndpoint* data_dst,
                           std::vector<base::string16>* types) const override;
   std::vector<base::string16> ReadAvailablePlatformSpecificFormatNames(
-      ui::ClipboardBuffer buffer) const override;
+      ui::ClipboardBuffer buffer,
+      const ui::ClipboardDataEndpoint* data_dst) const override;
   void ReadText(ui::ClipboardBuffer buffer,
+                const ui::ClipboardDataEndpoint* data_dst,
                 base::string16* result) const override;
   void ReadAsciiText(ui::ClipboardBuffer buffer,
+                     const ui::ClipboardDataEndpoint* data_dst,
                      std::string* result) const override;
   void ReadHTML(ui::ClipboardBuffer buffer,
+                const ui::ClipboardDataEndpoint* data_dst,
                 base::string16* markup,
                 std::string* src_url,
                 uint32_t* fragment_start,
                 uint32_t* fragment_end) const override;
-  void ReadRTF(ui::ClipboardBuffer buffer, std::string* result) const override;
+  void ReadRTF(ui::ClipboardBuffer buffer,
+               const ui::ClipboardDataEndpoint* data_dst,
+               std::string* result) const override;
   void ReadImage(ui::ClipboardBuffer buffer,
+                 const ui::ClipboardDataEndpoint* data_dst,
                  ReadImageCallback callback) const override;
   void ReadCustomData(ui::ClipboardBuffer clipboard_buffer,
                       const base::string16& type,
+                      const ui::ClipboardDataEndpoint* data_dst,
                       base::string16* result) const override;
-  void ReadBookmark(base::string16* title, std::string* url) const override;
+  void ReadBookmark(const ui::ClipboardDataEndpoint* data_dst,
+                    base::string16* title,
+                    std::string* url) const override;
   void ReadData(const ui::ClipboardFormatType& format,
+                const ui::ClipboardDataEndpoint* data_dst,
                 std::string* result) const override;
   void WritePortableRepresentations(
       ui::ClipboardBuffer buffer,
diff --git a/headless/lib/headless_browser_browsertest.cc b/headless/lib/headless_browser_browsertest.cc
index d0a8881..9fe1b0a 100644
--- a/headless/lib/headless_browser_browsertest.cc
+++ b/headless/lib/headless_browser_browsertest.cc
@@ -281,7 +281,7 @@
       writer.WriteText(paste_text);
     }
     base::string16 copy_text;
-    clipboard->ReadText(buffer, &copy_text);
+    clipboard->ReadText(buffer, /* data_dst = */ nullptr, &copy_text);
     EXPECT_EQ(paste_text, copy_text);
   }
 }
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg
index 3c7cc63..0172b40d 100644
--- a/infra/config/generated/cr-buildbucket.cfg
+++ b/infra/config/generated/cr-buildbucket.cfg
@@ -10590,6 +10590,64 @@
       }
     }
     builders {
+      name: "linux-lacros-builder-rel"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builderless:1"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-16.04"
+      dimensions: "pool:luci.chromium.ci"
+      dimensions: "ssd:0"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      execution_timeout_secs: 36000
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "ci_test_results"
+          test_results {}
+        }
+      }
+    }
+    builders {
+      name: "linux-lacros-tester-rel"
+      swarming_host: "chromium-swarm.appspot.com"
+      swarming_tags: "vpython:native-python-wrapper"
+      dimensions: "builderless:1"
+      dimensions: "cores:8"
+      dimensions: "cpu:x86-64"
+      dimensions: "os:Ubuntu-16.04"
+      dimensions: "pool:luci.chromium.ci"
+      dimensions: "ssd:0"
+      exe {
+        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
+        cipd_version: "refs/heads/master"
+        cmd: "recipes"
+      }
+      properties: "{\"$build/goma\":{\"enable_ats\":true,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\"},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"mastername\":\"chromium.fyi\",\"recipe\":\"chromium\"}"
+      execution_timeout_secs: 36000
+      build_numbers: YES
+      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+      resultdb {
+        enable: true
+        bq_exports {
+          project: "luci-resultdb"
+          dataset: "chromium"
+          table: "ci_test_results"
+          test_results {}
+        }
+      }
+    }
+    builders {
       name: "linux-official"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
diff --git a/infra/config/generated/luci-milo.cfg b/infra/config/generated/luci-milo.cfg
index 5403510..6796647 100644
--- a/infra/config/generated/luci-milo.cfg
+++ b/infra/config/generated/luci-milo.cfg
@@ -8161,6 +8161,14 @@
     category: "linux"
   }
   builders {
+    name: "buildbucket/luci.chromium.ci/linux-lacros-builder-rel"
+    category: "linux"
+  }
+  builders {
+    name: "buildbucket/luci.chromium.ci/linux-lacros-tester-rel"
+    category: "linux"
+  }
+  builders {
     name: "buildbucket/luci.chromium.ci/linux-perfetto-rel"
     category: "linux"
   }
diff --git a/infra/config/generated/luci-notify.cfg b/infra/config/generated/luci-notify.cfg
index e092ec7..fcedbc2 100644
--- a/infra/config/generated/luci-notify.cfg
+++ b/infra/config/generated/luci-notify.cfg
@@ -2866,13 +2866,6 @@
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "chrome-gpu-build-failures@google.com"
       rotation_urls: "https://rota-ng.appspot.com/legacy/sheriff_gpu.json"
     }
@@ -2882,23 +2875,12 @@
     name: "Android Release (Nexus 5X)"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -2907,23 +2889,12 @@
     name: "Cast Linux"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -2938,23 +2909,12 @@
     name: "Fuchsia ARM64"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -2969,23 +2929,12 @@
     name: "Fuchsia x64"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "chrome-gpu-build-failures@google.com"
       rotation_urls: "https://rota-ng.appspot.com/legacy/sheriff_gpu.json"
     }
@@ -2995,23 +2944,12 @@
     name: "GPU Linux Builder"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "chrome-gpu-build-failures@google.com"
       rotation_urls: "https://rota-ng.appspot.com/legacy/sheriff_gpu.json"
     }
@@ -3021,23 +2959,12 @@
     name: "GPU Mac Builder"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "chrome-gpu-build-failures@google.com"
       rotation_urls: "https://rota-ng.appspot.com/legacy/sheriff_gpu.json"
     }
@@ -3047,23 +2974,12 @@
     name: "GPU Win x64 Builder"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -3072,23 +2988,12 @@
     name: "Linux ASan LSan Builder"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -3096,23 +3001,12 @@
     bucket: "ci-m84"
     name: "Linux ASan LSan Tests (1)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -3120,23 +3014,12 @@
     bucket: "ci-m84"
     name: "Linux ASan Tests (sandboxed)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -3145,23 +3028,12 @@
     name: "Linux Builder"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -3170,23 +3042,12 @@
     name: "Linux Builder (dbg)"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -3194,23 +3055,12 @@
     bucket: "ci-m84"
     name: "Linux Ozone Tester (Headless)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -3218,23 +3068,12 @@
     bucket: "ci-m84"
     name: "Linux Ozone Tester (Wayland)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -3242,23 +3081,12 @@
     bucket: "ci-m84"
     name: "Linux Ozone Tester (X11)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "chrome-gpu-build-failures@google.com"
       rotation_urls: "https://rota-ng.appspot.com/legacy/sheriff_gpu.json"
     }
@@ -3267,23 +3095,12 @@
     bucket: "ci-m84"
     name: "Linux Release (NVIDIA)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -3292,23 +3109,12 @@
     name: "Linux TSan Builder"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -3316,23 +3122,12 @@
     bucket: "ci-m84"
     name: "Linux TSan Tests"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -3340,23 +3135,12 @@
     bucket: "ci-m84"
     name: "Linux Tests"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -3364,59 +3148,12 @@
     bucket: "ci-m84"
     name: "Linux Tests (dbg)(1)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "Mac Builder"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "Mac Builder (dbg)"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "chrome-gpu-build-failures@google.com"
       rotation_urls: "https://rota-ng.appspot.com/legacy/sheriff_gpu.json"
     }
@@ -3425,23 +3162,12 @@
     bucket: "ci-m84"
     name: "Mac Release (Intel)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "chrome-gpu-build-failures@google.com"
       rotation_urls: "https://rota-ng.appspot.com/legacy/sheriff_gpu.json"
     }
@@ -3450,229 +3176,12 @@
     bucket: "ci-m84"
     name: "Mac Retina Release (AMD)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "Mac10.10 Tests"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "Mac10.11 Tests"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "Mac10.12 Tests"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "Mac10.13 Tests"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "Mac10.13 Tests (dbg)"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "Mac10.14 Tests"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "Mac10.15 Tests"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "WebKit Mac10.13 (retina)"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "Win 7 Tests x64 (1)"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "Win Builder (dbg)"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "Win x64 Builder"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "Win10 Tests x64"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "chrome-gpu-build-failures@google.com"
       rotation_urls: "https://rota-ng.appspot.com/legacy/sheriff_gpu.json"
     }
@@ -3681,27 +3190,6 @@
     bucket: "ci-m84"
     name: "Win10 x64 Release (NVIDIA)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "Win7 Tests (dbg)(1)"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
@@ -3758,67 +3246,6 @@
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "chromeos-amd64-generic-dbg"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "chromeos-amd64-generic-rel"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "chromeos-arm-generic-rel"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -3833,23 +3260,12 @@
     name: "fuchsia-arm64-cast"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -3864,28 +3280,6 @@
     name: "fuchsia-x64-cast"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "ios-simulator"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
@@ -3905,67 +3299,6 @@
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "ios-simulator-full-configs"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "linux-chromeos-dbg"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m84"
-    name: "linux-chromeos-rel"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -3974,23 +3307,12 @@
     name: "linux-ozone-rel"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "chrome-gpu-build-failures@google.com"
       rotation_urls: "https://rota-ng.appspot.com/legacy/sheriff_gpu.json"
     }
@@ -4000,23 +3322,12 @@
     name: "Android Release (Nexus 5X)"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -4025,23 +3336,12 @@
     name: "Cast Linux"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -4056,23 +3356,12 @@
     name: "Fuchsia ARM64"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -4087,23 +3376,12 @@
     name: "Fuchsia x64"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "chrome-gpu-build-failures@google.com"
       rotation_urls: "https://rota-ng.appspot.com/legacy/sheriff_gpu.json"
     }
@@ -4113,23 +3391,12 @@
     name: "GPU Linux Builder"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "chrome-gpu-build-failures@google.com"
       rotation_urls: "https://rota-ng.appspot.com/legacy/sheriff_gpu.json"
     }
@@ -4139,23 +3406,12 @@
     name: "GPU Mac Builder"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "chrome-gpu-build-failures@google.com"
       rotation_urls: "https://rota-ng.appspot.com/legacy/sheriff_gpu.json"
     }
@@ -4165,23 +3421,12 @@
     name: "GPU Win x64 Builder"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -4190,23 +3435,12 @@
     name: "Linux ASan LSan Builder"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -4214,23 +3448,12 @@
     bucket: "ci-m85"
     name: "Linux ASan LSan Tests (1)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -4238,23 +3461,12 @@
     bucket: "ci-m85"
     name: "Linux ASan Tests (sandboxed)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -4263,23 +3475,12 @@
     name: "Linux Builder"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -4288,23 +3489,12 @@
     name: "Linux Builder (dbg)"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -4312,23 +3502,12 @@
     bucket: "ci-m85"
     name: "Linux Ozone Tester (Headless)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -4336,23 +3515,12 @@
     bucket: "ci-m85"
     name: "Linux Ozone Tester (Wayland)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -4360,23 +3528,12 @@
     bucket: "ci-m85"
     name: "Linux Ozone Tester (X11)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "chrome-gpu-build-failures@google.com"
       rotation_urls: "https://rota-ng.appspot.com/legacy/sheriff_gpu.json"
     }
@@ -4385,23 +3542,12 @@
     bucket: "ci-m85"
     name: "Linux Release (NVIDIA)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -4410,23 +3556,12 @@
     name: "Linux TSan Builder"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -4434,23 +3569,12 @@
     bucket: "ci-m85"
     name: "Linux TSan Tests"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -4458,23 +3582,12 @@
     bucket: "ci-m85"
     name: "Linux Tests"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -4482,59 +3595,12 @@
     bucket: "ci-m85"
     name: "Linux Tests (dbg)(1)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "Mac Builder"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "Mac Builder (dbg)"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "chrome-gpu-build-failures@google.com"
       rotation_urls: "https://rota-ng.appspot.com/legacy/sheriff_gpu.json"
     }
@@ -4543,23 +3609,12 @@
     bucket: "ci-m85"
     name: "Mac Release (Intel)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "chrome-gpu-build-failures@google.com"
       rotation_urls: "https://rota-ng.appspot.com/legacy/sheriff_gpu.json"
     }
@@ -4568,229 +3623,12 @@
     bucket: "ci-m85"
     name: "Mac Retina Release (AMD)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "Mac10.10 Tests"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "Mac10.11 Tests"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "Mac10.12 Tests"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "Mac10.13 Tests"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "Mac10.13 Tests (dbg)"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "Mac10.14 Tests"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "Mac10.15 Tests"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "WebKit Mac10.13 (retina)"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "Win 7 Tests x64 (1)"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "Win Builder (dbg)"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "Win x64 Builder"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "Win10 Tests x64"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "chrome-gpu-build-failures@google.com"
       rotation_urls: "https://rota-ng.appspot.com/legacy/sheriff_gpu.json"
     }
@@ -4799,27 +3637,6 @@
     bucket: "ci-m85"
     name: "Win10 x64 Release (NVIDIA)"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "Win7 Tests (dbg)(1)"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
@@ -4876,67 +3693,6 @@
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "chromeos-amd64-generic-dbg"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "chromeos-amd64-generic-rel"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "chromeos-arm-generic-rel"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -4951,23 +3707,12 @@
     name: "fuchsia-arm64-cast"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -4982,28 +3727,6 @@
     name: "fuchsia-x64-cast"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "ios-simulator"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 notifiers {
   notifications {
@@ -5023,67 +3746,6 @@
     on_occurrence: FAILURE
     failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
     email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "ios-simulator-full-configs"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "linux-chromeos-dbg"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  builders {
-    bucket: "ci-m85"
-    name: "linux-chromeos-rel"
-    repository: "https://chromium.googlesource.com/chromium/src"
-  }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
-}
-notifiers {
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
-      rotation_urls: "https://chrome-ops-rotation-proxy.appspot.com/current/oncallator:chrome-build-sheriff"
-    }
-  }
-  notifications {
-    on_occurrence: FAILURE
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-    email {
       recipients: "thomasanderson@chromium.org"
     }
   }
@@ -5092,9 +3754,5 @@
     name: "linux-ozone-rel"
     repository: "https://chromium.googlesource.com/chromium/src"
   }
-  tree_closers {
-    tree_status_host: "chromium-status.appspot.com"
-    failed_step_regexp: "bot_update|compile|gclient runhooks|runhooks|update"
-  }
 }
 tree_closing_enabled: true
diff --git a/infra/config/generated/luci-scheduler.cfg b/infra/config/generated/luci-scheduler.cfg
index 31d4527..8d4f477 100644
--- a/infra/config/generated/luci-scheduler.cfg
+++ b/infra/config/generated/luci-scheduler.cfg
@@ -8113,6 +8113,28 @@
   }
 }
 job {
+  id: "ci-linux-lacros-builder-rel"
+  acl_sets: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "linux-lacros-builder-rel"
+  }
+}
+job {
+  id: "ci-linux-lacros-tester-rel"
+  acls {
+    role: TRIGGERER
+    granted_to: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+  }
+  acl_sets: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "linux-lacros-tester-rel"
+  }
+}
+job {
   id: "ci-linux-official"
   acl_sets: "ci"
   buildbucket {
@@ -10810,6 +10832,28 @@
   }
 }
 job {
+  id: "linux-lacros-builder-rel"
+  acl_sets: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "linux-lacros-builder-rel"
+  }
+}
+job {
+  id: "linux-lacros-tester-rel"
+  acls {
+    role: TRIGGERER
+    granted_to: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
+  }
+  acl_sets: "ci"
+  buildbucket {
+    server: "cr-buildbucket.appspot.com"
+    bucket: "luci.chromium.ci"
+    builder: "linux-lacros-tester-rel"
+  }
+}
+job {
   id: "linux-official"
   acl_sets: "ci"
   buildbucket {
@@ -11789,6 +11833,7 @@
   triggers: "linux-chromium-tests-staging-builder"
   triggers: "linux-fieldtrial-rel"
   triggers: "linux-gcc-rel"
+  triggers: "linux-lacros-builder-rel"
   triggers: "ci-linux-official"
   triggers: "ci-linux-ozone-rel"
   triggers: "linux-perfetto-rel"
diff --git a/infra/config/lib/ci.star b/infra/config/lib/ci.star
index 75d220e..eec6ef9 100644
--- a/infra/config/lib/ci.star
+++ b/infra/config/lib/ci.star
@@ -454,10 +454,15 @@
       'chromium-tree-closer' config in notifiers.star for the full criteria.
     notifies - Any extra notifiers to attach to this builder.
   """
+
+  # Branch builders should never close the tree, only builders from the main
+  # "ci" bucket.
+  bucket = defaults.get_value_from_kwargs('bucket', kwargs)
+  if tree_closing and bucket == 'ci':
+    notifies = (notifies or []) + ['chromium-tree-closer', 'chromium-tree-closer-email']
+
   # Define the builder first so that any validation of luci.builder arguments
   # (e.g. bucket) occurs before we try to use it
-  if tree_closing:
-    notifies = (notifies or []) + ['chromium-tree-closer', 'chromium-tree-closer-email']
   ret = builders.builder(
       name = name,
       resultdb_bigquery_exports = [resultdb.export_test_results(
@@ -473,7 +478,6 @@
       console_view = defaults.get_value_from_kwargs('mastername', kwargs)
 
     if console_view:
-      bucket = defaults.get_value_from_kwargs('bucket', kwargs)
       add_to_console_view = defaults.get_value(
           'add_to_console_view', add_to_console_view)
 
diff --git a/infra/config/subprojects/chromium/master-only/ci.star b/infra/config/subprojects/chromium/master-only/ci.star
index cfd77ce..7d7c2f0 100644
--- a/infra/config/subprojects/chromium/master-only/ci.star
+++ b/infra/config/subprojects/chromium/master-only/ci.star
@@ -1563,6 +1563,21 @@
 )
 
 ci.fyi_builder(
+    name = 'linux-lacros-builder-rel',
+    console_view_entry = ci.console_view_entry(
+        category = 'linux',
+    ),
+)
+
+ci.fyi_builder(
+    name = 'linux-lacros-tester-rel',
+    console_view_entry = ci.console_view_entry(
+        category = 'linux',
+    ),
+    triggered_by = ['linux-lacros-builder-rel'],
+)
+
+ci.fyi_builder(
     name = 'linux-perfetto-rel',
     console_view_entry = ci.console_view_entry(
         category = 'linux',
diff --git a/infra/config/subprojects/chromium/versioned/m85/buckets/ci.star b/infra/config/subprojects/chromium/versioned/m85/buckets/ci.star
index 6258864..8808f5f 100644
--- a/infra/config/subprojects/chromium/versioned/m85/buckets/ci.star
+++ b/infra/config/subprojects/chromium/versioned/m85/buckets/ci.star
@@ -230,7 +230,6 @@
     # TODO: Change this back down to something reasonable once these builders
     # have populated their cached by getting through the compile step
     execution_timeout = 6 * time.hour,
-    tree_closing = False,
 )
 
 ci.chromium_builder(
@@ -246,7 +245,6 @@
     # TODO: Change this back down to something reasonable once these builders
     # have populated their cached by getting through the compile step
     execution_timeout = 10 * time.hour,
-    tree_closing = False,
 )
 
 ci.chromium_builder(
@@ -262,7 +260,6 @@
     # TODO: Change this back down to something reasonable once these builders
     # have populated their cached by getting through the compile step
     execution_timeout = 10 * time.hour,
-    tree_closing = False,
 )
 
 ci.chromiumos_builder(
diff --git a/ios/web/common/user_agent_unittest.mm b/ios/web/common/user_agent_unittest.mm
index c09561e..cbc710bf 100644
--- a/ios/web/common/user_agent_unittest.mm
+++ b/ios/web/common/user_agent_unittest.mm
@@ -50,19 +50,23 @@
             GetUserAgentTypeDescription(UserAgentType::MOBILE));
   EXPECT_EQ(kDesktopDescription,
             GetUserAgentTypeDescription(UserAgentType::DESKTOP));
-  EXPECT_EQ(kAutomaticDescription,
-            GetUserAgentTypeDescription(UserAgentType::AUTOMATIC));
   EXPECT_EQ(kNoneDescription, GetUserAgentTypeDescription(UserAgentType::NONE));
   EXPECT_EQ(UserAgentType::MOBILE,
             GetUserAgentTypeWithDescription(kMobileDescription));
   EXPECT_EQ(UserAgentType::DESKTOP,
             GetUserAgentTypeWithDescription(kDesktopDescription));
-  EXPECT_EQ(UserAgentType::AUTOMATIC,
-            GetUserAgentTypeWithDescription(kAutomaticDescription));
   EXPECT_EQ(UserAgentType::NONE,
             GetUserAgentTypeWithDescription(kNoneDescription));
   EXPECT_EQ(UserAgentType::NONE,
             GetUserAgentTypeWithDescription(kInvalidDescription));
+
+  // The kUseDefaultUserAgentInWebClient feature is only available on iOS 13+.
+  if (@available(iOS 13, *)) {
+    EXPECT_EQ(kAutomaticDescription,
+              GetUserAgentTypeDescription(UserAgentType::AUTOMATIC));
+    EXPECT_EQ(UserAgentType::AUTOMATIC,
+              GetUserAgentTypeWithDescription(kAutomaticDescription));
+  }
 }
 
 // Tests the mobile user agent returned for a specific product.
diff --git a/ios/web/navigation/crw_session_storage_unittest.mm b/ios/web/navigation/crw_session_storage_unittest.mm
index 1200e6c..8f0c8793 100644
--- a/ios/web/navigation/crw_session_storage_unittest.mm
+++ b/ios/web/navigation/crw_session_storage_unittest.mm
@@ -4,6 +4,7 @@
 
 #import "ios/web/public/session/crw_session_storage.h"
 
+#include "base/ios/ios_util.h"
 #include "base/strings/sys_string_conversions.h"
 #include "base/test/scoped_feature_list.h"
 #include "ios/web/common/features.h"
@@ -112,6 +113,11 @@
 // Tests that unarchiving CRWSessionStorage data results in an equivalent
 // storage when the user agent is automatic.
 TEST_F(CRWNSessionStorageTest, EncodeDecodeAutomatic) {
+  // The kUseDefaultUserAgentInWebClient feature is only available on iOS 13+.
+  if (!base::ios::IsRunningOnIOS13OrLater()) {
+    return;
+  }
+
   base::test::ScopedFeatureList feature;
   feature.InitAndEnableFeature(web::features::kUseDefaultUserAgentInWebClient);
   session_storage_.userAgentType = web::UserAgentType::AUTOMATIC;
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index c8dca052..eb30231 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -242,6 +242,11 @@
 #endif
 };
 
+// When enabled, MediaCapabilities will check with GPU Video Accelerator
+// Factories to determine isPowerEfficient = true/false.
+const base::Feature kMediaCapabilitiesQueryGpuFactories{
+    "MediaCapabilitiesQueryGpuFactories", base::FEATURE_DISABLED_BY_DEFAULT};
+
 // Enable Media Capabilities with finch-parameters.
 const base::Feature kMediaCapabilitiesWithParameters{
     "MediaCapabilitiesWithParameters", base::FEATURE_ENABLED_BY_DEFAULT};
@@ -616,7 +621,7 @@
 
 // Enables AV1 decode acceleration for Windows.
 const base::Feature MEDIA_EXPORT kMediaFoundationAV1Decoding{
-    "MediaFoundationAV1Decoding", base::FEATURE_DISABLED_BY_DEFAULT};
+    "MediaFoundationAV1Decoding", base::FEATURE_ENABLED_BY_DEFAULT};
 
 // Enables MediaFoundation based video capture
 const base::Feature kMediaFoundationVideoCapture{
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index 016f997..58244bac 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -134,6 +134,7 @@
 MEDIA_EXPORT extern const base::Feature kKaleidoscope;
 MEDIA_EXPORT extern const base::Feature kLiveCaption;
 MEDIA_EXPORT extern const base::Feature kLowDelayVideoRenderingOnLiveStream;
+MEDIA_EXPORT extern const base::Feature kMediaCapabilitiesQueryGpuFactories;
 MEDIA_EXPORT extern const base::Feature kMediaCapabilitiesWithParameters;
 MEDIA_EXPORT extern const base::Feature kMediaCastOverlayButton;
 MEDIA_EXPORT extern const base::Feature kMediaEngagementBypassAutoplayPolicies;
diff --git a/media/gpu/vaapi/accelerated_video_encoder.cc b/media/gpu/vaapi/accelerated_video_encoder.cc
index 4bfdb0d..5e62091 100644
--- a/media/gpu/vaapi/accelerated_video_encoder.cc
+++ b/media/gpu/vaapi/accelerated_video_encoder.cc
@@ -28,12 +28,6 @@
   return nullptr;
 }
 
-BitstreamBufferMetadata AcceleratedVideoEncoder::EncodeJob::Metadata(
-    size_t payload_size) const {
-  return BitstreamBufferMetadata(payload_size, IsKeyframeRequested(),
-                                 timestamp());
-}
-
 void AcceleratedVideoEncoder::EncodeJob::AddSetupCallback(
     base::OnceClosure cb) {
   DCHECK(!cb.is_null());
@@ -76,4 +70,11 @@
                << "AcceleratedVideoEncoder that doesn't support BitrateControl"
                << "::kConstantQuantizationParameter";
 }
+
+BitstreamBufferMetadata AcceleratedVideoEncoder::GetMetadata(
+    EncodeJob* encode_job,
+    size_t payload_size) {
+  return BitstreamBufferMetadata(
+      payload_size, encode_job->IsKeyframeRequested(), encode_job->timestamp());
+}
 }  // namespace media
diff --git a/media/gpu/vaapi/accelerated_video_encoder.h b/media/gpu/vaapi/accelerated_video_encoder.h
index e5a51bd..0e2f5fcc 100644
--- a/media/gpu/vaapi/accelerated_video_encoder.h
+++ b/media/gpu/vaapi/accelerated_video_encoder.h
@@ -113,8 +113,6 @@
     // Returns the timestamp associated with this job.
     base::TimeDelta timestamp() const { return timestamp_; }
 
-    virtual BitstreamBufferMetadata Metadata(size_t payload_size) const;
-
     virtual VaapiEncodeJob* AsVaapiEncodeJob();
 
    private:
@@ -180,6 +178,9 @@
   // AcceleratedVideoEncoder is configured with
   // BitrateControl::kConstantQuantizationParameter.
   virtual void BitrateControlUpdate(uint64_t encoded_chunk_size_bytes);
+
+  virtual BitstreamBufferMetadata GetMetadata(EncodeJob* encode_job,
+                                              size_t payload_size);
 };
 
 }  // namespace media
diff --git a/media/gpu/vaapi/vaapi_video_encode_accelerator.cc b/media/gpu/vaapi/vaapi_video_encode_accelerator.cc
index 528c424..12367bc 100644
--- a/media/gpu/vaapi/vaapi_video_encode_accelerator.cc
+++ b/media/gpu/vaapi/vaapi_video_encode_accelerator.cc
@@ -277,8 +277,8 @@
 
   VLOGF(2) << "Initializing VAVEA, " << config.AsHumanReadableString();
 
-  // VaapiVEA doesn't support temporal layers but we let it pass here to support
-  // simulcast.
+  // VaapiVEA supports temporal layers for VP9 only, but we also allow VP8 to
+  // support VP8 simulcast.
   if (config.HasSpatialLayer()) {
     VLOGF(1) << "Spatial layer encoding is supported";
     return false;
@@ -618,8 +618,9 @@
   scoped_buffer.RunAndReset();
 
   child_task_runner_->PostTask(
-      FROM_HERE, base::BindOnce(&Client::BitstreamBufferReady, client_,
-                                buffer->id, encode_job->Metadata(data_size)));
+      FROM_HERE,
+      base::BindOnce(&Client::BitstreamBufferReady, client_, buffer->id,
+                     encoder_->GetMetadata(encode_job.get(), data_size)));
 }
 
 void VaapiVideoEncodeAccelerator::Encode(scoped_refptr<VideoFrame> frame,
diff --git a/media/gpu/vaapi/vp9_encoder.cc b/media/gpu/vaapi/vp9_encoder.cc
index 0c125f0..426fc17e 100644
--- a/media/gpu/vaapi/vp9_encoder.cc
+++ b/media/gpu/vaapi/vp9_encoder.cc
@@ -5,10 +5,13 @@
 #include "media/gpu/vaapi/vp9_encoder.h"
 
 #include <algorithm>
+#include <numeric>
 
 #include "base/bits.h"
+#include "base/numerics/safe_conversions.h"
 #include "media/gpu/macros.h"
 #include "media/gpu/vaapi/vp9_rate_control.h"
+#include "media/gpu/vaapi/vp9_temporal_layers.h"
 #include "third_party/libvpx/source/libvpx/vp9/ratectrl_rtc.h"
 
 namespace media {
@@ -77,9 +80,41 @@
   return std::max(kMinIntraSizePercentage, target_size_kbyte_as_percent);
 }
 
-libvpx::VP9RateControlRtcConfig CreateRCConfig(
-    const gfx::Size& encode_size,
-    const VP9Encoder::EncodeParams& encode_params) {
+VideoBitrateAllocation GetDefaultVideoBitrateAllocation(
+    const VideoEncodeAccelerator::Config& config) {
+  DCHECK(!config.HasSpatialLayer()) << "Spatial layers are not supported.";
+  VideoBitrateAllocation bitrate_allocation;
+  if (!config.HasTemporalLayer()) {
+    bitrate_allocation.SetBitrate(0, 0, config.initial_bitrate);
+    return bitrate_allocation;
+  }
+
+  const auto& spatial_layer = config.spatial_layers[0];
+  const size_t num_temporal_layers = spatial_layer.num_of_temporal_layers;
+  DCHECK_GT(num_temporal_layers, 1u);
+  DCHECK_LE(num_temporal_layers, 3u);
+  constexpr double kTemporalLayersBitrateScaleFactors
+      [][VP9TemporalLayers::kMaxSupportedTemporalLayers] = {
+          {0.50, 0.50, 0.00},  // For two temporal layers.
+          {0.25, 0.25, 0.50},  // For three temporal layers.
+      };
+
+  const uint32_t bitrate_bps = spatial_layer.bitrate_bps;
+  for (size_t i = 0; i < num_temporal_layers; ++i) {
+    const double factor =
+        kTemporalLayersBitrateScaleFactors[num_temporal_layers - 2][i];
+    bitrate_allocation.SetBitrate(
+        0 /* spatial_index */, i,
+        base::checked_cast<int>(bitrate_bps * factor));
+  }
+  return bitrate_allocation;
+}
+
+libvpx::VP9RateControlRtcConfig CreateRateControlConfig(
+    const gfx::Size encode_size,
+    const VP9Encoder::EncodeParams& encode_params,
+    const VideoBitrateAllocation& bitrate_allocation,
+    const size_t num_temporal_layers) {
   libvpx::VP9RateControlRtcConfig rc_cfg{};
   rc_cfg.width = encode_size.width();
   rc_cfg.height = encode_size.height();
@@ -88,8 +123,8 @@
   rc_cfg.min_quantizer =
       QindexToQuantizer(encode_params.scaling_settings.min_qp);
   // libvpx::VP9RateControlRtcConfig is kbps.
-  rc_cfg.target_bandwidth =
-      encode_params.bitrate_allocation.GetSumBps() / 1000.0;
+  rc_cfg.target_bandwidth = base::checked_cast<int64_t>(
+      encode_params.bitrate_allocation.GetSumBps() / 1000.0);
   // These default values come from
   // //third_party/webrtc/modules/video_coding/codecs/vp9/vp9_impl.cc.
   rc_cfg.buf_initial_sz = 500;
@@ -101,17 +136,19 @@
       rc_cfg.buf_optimal_sz, encode_params.framerate);
   rc_cfg.framerate = encode_params.framerate;
 
-  // Spatial layer variables.
+  // Spatial layers variables.
   rc_cfg.ss_number_layers = 1;
-  rc_cfg.max_quantizers[0] = rc_cfg.max_quantizer;
-  rc_cfg.min_quantizers[0] = rc_cfg.min_quantizer;
-  // TODO(crbug.com/1030199): Fill multiple temporal layers variables.
-  // Temporal layer variables.
-  rc_cfg.ts_number_layers = 1;
   rc_cfg.scaling_factor_num[0] = 1;
   rc_cfg.scaling_factor_den[0] = 1;
-  rc_cfg.layer_target_bitrate[0] = rc_cfg.target_bandwidth;
-  rc_cfg.ts_rate_decimator[0] = 1;
+  // Fill temporal layers variables.
+  rc_cfg.ts_number_layers = num_temporal_layers;
+  for (size_t ti = 0; ti < num_temporal_layers; ti++) {
+    rc_cfg.max_quantizers[ti] = rc_cfg.max_quantizer;
+    rc_cfg.min_quantizers[ti] = rc_cfg.min_quantizer;
+    rc_cfg.layer_target_bitrate[ti] = base::checked_cast<int>(
+        bitrate_allocation.GetBitrateBps(0, ti) / 1000.0);
+    rc_cfg.ts_rate_decimator[ti] = 1u << ti;
+  }
   return rc_cfg;
 }
 }  // namespace
@@ -134,7 +171,6 @@
   current_params_ = EncodeParams();
   reference_frames_.Clear();
   frame_num_ = 0;
-  InitializeFrameHeader();
 }
 
 VP9Encoder::VP9Encoder(std::unique_ptr<Accelerator> accelerator)
@@ -151,6 +187,10 @@
     DVLOGF(1) << "Invalid profile: " << GetProfileName(config.output_profile);
     return false;
   }
+  if (config.HasSpatialLayer()) {
+    DVLOGF(1) << "Spatial layer encoding is not supported";
+    return false;
+  }
 
   if (config.input_visible_size.IsEmpty()) {
     DVLOGF(1) << "Input visible size could not be empty";
@@ -163,22 +203,41 @@
                           base::bits::Align(visible_size_.height(), 16));
   Reset();
 
+  auto initial_bitrate_allocation = GetDefaultVideoBitrateAllocation(config);
   if (ave_config.bitrate_control ==
       BitrateControl::kConstantQuantizationParameter) {
+    size_t num_temporal_layers = 1;
+    if (config.HasTemporalLayer()) {
+      num_temporal_layers = config.spatial_layers[0].num_of_temporal_layers;
+      if (num_temporal_layers <
+              VP9TemporalLayers::kMinSupportedTemporalLayers ||
+          num_temporal_layers >
+              VP9TemporalLayers::kMaxSupportedTemporalLayers) {
+        VLOGF(1) << "Unsupported amount of temporal layers: "
+                 << num_temporal_layers;
+        return false;
+      }
+      temporal_layers_ =
+          std::make_unique<VP9TemporalLayers>(num_temporal_layers);
+    }
     // |rate_ctrl_| might be injected for tests.
     if (!rate_ctrl_) {
-      rate_ctrl_ = VP9RateControl::Create(
-          CreateRCConfig(visible_size_, current_params_));
+      rate_ctrl_ = VP9RateControl::Create(CreateRateControlConfig(
+          visible_size_, current_params_, initial_bitrate_allocation,
+          num_temporal_layers));
     }
     if (!rate_ctrl_)
       return false;
   } else {
+    if (config.HasTemporalLayer()) {
+      DVLOGF(1) << "Temporal layer encoding works only when in "
+                << "kConstantQuantizationParameter";
+      return false;
+    }
     DCHECK(!rate_ctrl_) << "|rate_ctrl_| should only be configured when in "
                            "kConstantQuantizationParameter";
   }
 
-  VideoBitrateAllocation initial_bitrate_allocation;
-  initial_bitrate_allocation.SetBitrate(0, 0, config.initial_bitrate);
   return UpdateRates(initial_bitrate_allocation,
                      config.initial_framerate.value_or(
                          VideoEncodeAccelerator::kDefaultFramerate));
@@ -218,14 +277,9 @@
   scoped_refptr<VP9Picture> picture = accelerator_->GetPicture(encode_job);
   DCHECK(picture);
 
-  const bool keyframe = encode_job->IsKeyframeRequested();
-  UpdateFrameHeader(keyframe);
-
-  *picture->frame_hdr = current_frame_hdr_;
-
-  // Use last, golden and altref for references.
-  const std::array<bool, kVp9NumRefsPerFrame> ref_frames_used = {
-      !keyframe, !keyframe, !keyframe};
+  std::array<bool, kVp9NumRefsPerFrame> ref_frames_used = {false, false, false};
+  SetFrameHeader(encode_job->IsKeyframeRequested(), picture.get(),
+                 &ref_frames_used);
   if (!accelerator_->SubmitFrameParameters(encode_job, current_params_, picture,
                                            reference_frames_,
                                            ref_frames_used)) {
@@ -237,6 +291,16 @@
   return true;
 }
 
+BitstreamBufferMetadata VP9Encoder::GetMetadata(EncodeJob* encode_job,
+                                                size_t payload_size) {
+  auto metadata =
+      AcceleratedVideoEncoder::GetMetadata(encode_job, payload_size);
+  auto picture = accelerator_->GetPicture(encode_job);
+  DCHECK(picture);
+  metadata.vp9 = picture->metadata_for_encoding;
+  return metadata;
+}
+
 void VP9Encoder::BitrateControlUpdate(uint64_t encoded_chunk_size_bytes) {
   if (accelerator_->bitrate_control() !=
           BitrateControl::kConstantQuantizationParameter ||
@@ -273,36 +337,55 @@
   if (!rate_ctrl_)
     return true;
 
-  rate_ctrl_->UpdateRateControl(CreateRCConfig(visible_size_, current_params_));
+  const size_t num_temporal_layers =
+      temporal_layers_ ? temporal_layers_->num_layers() : 1u;
+  rate_ctrl_->UpdateRateControl(CreateRateControlConfig(
+      visible_size_, current_params_, bitrate_allocation, num_temporal_layers));
   return true;
 }
 
-void VP9Encoder::InitializeFrameHeader() {
-  current_frame_hdr_ = {};
+Vp9FrameHeader VP9Encoder::GetDefaultFrameHeader(const bool keyframe) const {
+  Vp9FrameHeader hdr{};
   DCHECK(!visible_size_.IsEmpty());
-  current_frame_hdr_.frame_width = visible_size_.width();
-  current_frame_hdr_.frame_height = visible_size_.height();
-  current_frame_hdr_.render_width = visible_size_.width();
-  current_frame_hdr_.render_height = visible_size_.height();
-  current_frame_hdr_.quant_params.base_q_idx = kDefaultQP;
-  current_frame_hdr_.loop_filter.level = kDefaultLfLevel;
-  current_frame_hdr_.show_frame = true;
+  hdr.frame_width = visible_size_.width();
+  hdr.frame_height = visible_size_.height();
+  hdr.render_width = visible_size_.width();
+  hdr.render_height = visible_size_.height();
+  hdr.quant_params.base_q_idx = kDefaultQP;
+  hdr.loop_filter.level = kDefaultLfLevel;
+  hdr.show_frame = true;
+  hdr.frame_type =
+      keyframe ? Vp9FrameHeader::KEYFRAME : Vp9FrameHeader::INTERFRAME;
+  return hdr;
 }
 
-void VP9Encoder::UpdateFrameHeader(bool keyframe) {
-  if (keyframe) {
-    current_frame_hdr_.frame_type = Vp9FrameHeader::KEYFRAME;
-    current_frame_hdr_.refresh_frame_flags = 0xff;
-    ref_frame_index_ = 0;
+void VP9Encoder::SetFrameHeader(
+    bool keyframe,
+    VP9Picture* picture,
+    std::array<bool, kVp9NumRefsPerFrame>* ref_frames_used) {
+  DCHECK(picture);
+  DCHECK(ref_frames_used);
+
+  *picture->frame_hdr = GetDefaultFrameHeader(keyframe);
+  if (temporal_layers_) {
+    // Reference frame settings for temporal layer stream.
+    temporal_layers_->FillUsedRefFramesAndMetadata(picture, ref_frames_used);
   } else {
-    current_frame_hdr_.frame_type = Vp9FrameHeader::INTERFRAME;
-    current_frame_hdr_.ref_frame_idx[0] = ref_frame_index_;
-    current_frame_hdr_.ref_frame_idx[1] =
-        (ref_frame_index_ - 1) & (kVp9NumRefFrames - 1);
-    current_frame_hdr_.ref_frame_idx[2] =
-        (ref_frame_index_ - 2) & (kVp9NumRefFrames - 1);
-    ref_frame_index_ = (ref_frame_index_ + 1) % kVp9NumRefFrames;
-    current_frame_hdr_.refresh_frame_flags = 1 << ref_frame_index_;
+    // Reference frame settings for simple stream.
+    if (keyframe) {
+      picture->frame_hdr->refresh_frame_flags = 0xff;
+      ref_frame_index_ = 0;
+    } else {
+      picture->frame_hdr->ref_frame_idx[0] = ref_frame_index_;
+      picture->frame_hdr->ref_frame_idx[1] =
+          (ref_frame_index_ - 1) & (kVp9NumRefFrames - 1);
+      picture->frame_hdr->ref_frame_idx[2] =
+          (ref_frame_index_ - 2) & (kVp9NumRefFrames - 1);
+      ref_frame_index_ = (ref_frame_index_ + 1) % kVp9NumRefFrames;
+      picture->frame_hdr->refresh_frame_flags = 1 << ref_frame_index_;
+      // Use last, golden, alt frames.
+      ref_frames_used->fill(true);
+    }
   }
 
   if (!rate_ctrl_)
@@ -311,12 +394,15 @@
   libvpx::VP9FrameParamsQpRTC frame_params{};
   frame_params.frame_type =
       keyframe ? FRAME_TYPE::KEY_FRAME : FRAME_TYPE::INTER_FRAME;
+  if (picture->metadata_for_encoding) {
+    frame_params.temporal_layer_id =
+        picture->metadata_for_encoding->temporal_idx;
+  }
   rate_ctrl_->ComputeQP(frame_params);
-  // TODO(crbug.com/1030199): Fill temporal layer id.
-  current_frame_hdr_.quant_params.base_q_idx = rate_ctrl_->GetQP();
-  current_frame_hdr_.loop_filter.level = rate_ctrl_->GetLoopfilterLevel();
-  DVLOGF(4) << "|qp|=" << rate_ctrl_->GetQP()
-            << ", |filter_level|=" << rate_ctrl_->GetLoopfilterLevel();
+  picture->frame_hdr->quant_params.base_q_idx = rate_ctrl_->GetQP();
+  picture->frame_hdr->loop_filter.level = rate_ctrl_->GetLoopfilterLevel();
+  DVLOGF(4) << "qp=" << rate_ctrl_->GetQP()
+            << ", filter_level=" << rate_ctrl_->GetLoopfilterLevel();
 }
 
 void VP9Encoder::UpdateReferenceFrames(scoped_refptr<VP9Picture> picture) {
diff --git a/media/gpu/vaapi/vp9_encoder.h b/media/gpu/vaapi/vp9_encoder.h
index 9c0ad1c..60e5c62 100644
--- a/media/gpu/vaapi/vp9_encoder.h
+++ b/media/gpu/vaapi/vp9_encoder.h
@@ -19,6 +19,7 @@
 #include "media/gpu/vp9_reference_frame_vector.h"
 
 namespace media {
+class VP9TemporalLayers;
 class VP9RateControl;
 
 class VP9Encoder : public AcceleratedVideoEncoder {
@@ -94,14 +95,18 @@
   ScalingSettings GetScalingSettings() const override;
   bool PrepareEncodeJob(EncodeJob* encode_job) override;
   void BitrateControlUpdate(uint64_t encoded_chunk_size_bytes) override;
+  BitstreamBufferMetadata GetMetadata(EncodeJob* encode_job,
+                                      size_t payload_size) override;
 
  private:
   friend class VP9EncoderTest;
 
   void set_rate_ctrl_for_testing(std::unique_ptr<VP9RateControl> rate_ctrl);
 
-  void InitializeFrameHeader();
-  void UpdateFrameHeader(bool keyframe);
+  Vp9FrameHeader GetDefaultFrameHeader(const bool keyframe) const;
+  void SetFrameHeader(bool keyframe,
+                      VP9Picture* picture,
+                      std::array<bool, kVp9NumRefsPerFrame>* ref_frames_used);
   void UpdateReferenceFrames(scoped_refptr<VP9Picture> picture);
   void Reset();
 
@@ -114,8 +119,8 @@
 
   EncodeParams current_params_;
 
-  Vp9FrameHeader current_frame_hdr_;
   Vp9ReferenceFrameVector reference_frames_;
+  std::unique_ptr<VP9TemporalLayers> temporal_layers_;
 
   std::unique_ptr<VP9RateControl> rate_ctrl_;
   const std::unique_ptr<Accelerator> accelerator_;
@@ -123,7 +128,6 @@
   SEQUENCE_CHECKER(sequence_checker_);
   DISALLOW_COPY_AND_ASSIGN(VP9Encoder);
 };
-
 }  // namespace media
 
 #endif  // MEDIA_GPU_VAAPI_VP9_ENCODER_H_
diff --git a/media/gpu/vaapi/vp9_encoder_unittest.cc b/media/gpu/vaapi/vp9_encoder_unittest.cc
index fa0f8b5..054dc0f2 100644
--- a/media/gpu/vaapi/vp9_encoder_unittest.cc
+++ b/media/gpu/vaapi/vp9_encoder_unittest.cc
@@ -6,13 +6,17 @@
 
 #include <memory>
 #include <numeric>
+#include <tuple>
 
 #include "base/bind_helpers.h"
 #include "base/callback.h"
 #include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
 #include "base/optional.h"
+#include "base/stl_util.h"
 #include "media/filters/vp9_parser.h"
 #include "media/gpu/vaapi/vp9_rate_control.h"
+#include "media/gpu/vaapi/vp9_temporal_layers.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/libvpx/source/libvpx/vp9/common/vp9_blockd.h"
@@ -42,8 +46,91 @@
     base::nullopt /* h264 output level*/,
     VideoEncodeAccelerator::Config::StorageType::kShmem);
 
-const std::vector<bool> kRefFramesUsedForKeyFrame = {false, false, false};
-const std::vector<bool> kRefFramesUsedForInterFrame = {true, true, true};
+constexpr std::array<bool, kVp9NumRefsPerFrame> kRefFramesUsedForKeyFrame = {
+    false, false, false};
+constexpr std::array<bool, kVp9NumRefsPerFrame> kRefFramesUsedForInterFrame = {
+    true, true, true};
+
+void GetTemporalLayer(bool keyframe,
+                      int index,
+                      size_t num_temporal_layers,
+                      std::array<bool, kVp9NumRefsPerFrame>* ref_frames_used,
+                      base::Optional<uint8_t>* temporal_layer_id) {
+  switch (num_temporal_layers) {
+    case 1:
+      *ref_frames_used =
+          keyframe ? kRefFramesUsedForKeyFrame : kRefFramesUsedForInterFrame;
+      break;
+    case 2:
+      if (keyframe) {
+        *temporal_layer_id = 0;
+        *ref_frames_used = kRefFramesUsedForKeyFrame;
+        return;
+      }
+
+      {
+        // 2 temporal layers structure. See https://imgur.com/vBvHtdp.
+        constexpr std::tuple<uint8_t, std::array<bool, kVp9NumRefsPerFrame>>
+            kTwoTemporalLayersDescription[] = {
+                {0, {true, false, false}}, {1, {true, false, false}},
+                {0, {true, false, false}}, {1, {true, true, false}},
+                {0, {true, false, false}}, {1, {true, true, false}},
+                {0, {true, false, false}}, {1, {true, true, false}},
+            };
+        const auto& layer_info = kTwoTemporalLayersDescription
+            [index % base::size(kTwoTemporalLayersDescription)];
+        std::tie(*temporal_layer_id, *ref_frames_used) = layer_info;
+      }
+      break;
+    case 3:
+      if (keyframe) {
+        *temporal_layer_id = 0u;
+        *ref_frames_used = kRefFramesUsedForKeyFrame;
+        return;
+      }
+
+      {
+        // 3 temporal layers structure. See https://imgur.com/pURAGvp.
+        constexpr std::tuple<uint8_t, std::array<bool, kVp9NumRefsPerFrame>>
+            kThreeTemporalLayersDescription[] = {
+                {0, {true, false, false}}, {2, {true, false, false}},
+                {1, {true, false, false}}, {2, {true, true, false}},
+                {0, {true, false, false}}, {2, {true, true, false}},
+                {1, {true, true, false}},  {2, {true, true, false}},
+            };
+        const auto& layer_info = kThreeTemporalLayersDescription
+            [index % base::size(kThreeTemporalLayersDescription)];
+        std::tie(*temporal_layer_id, *ref_frames_used) = layer_info;
+      }
+      break;
+  }
+}
+
+VideoBitrateAllocation GetDefaultVideoBitrateAllocation(
+    size_t num_temporal_layers,
+    uint32_t bitrate) {
+  VideoBitrateAllocation bitrate_allocation;
+  if (num_temporal_layers == 1u) {
+    bitrate_allocation.SetBitrate(0, 0, bitrate);
+    return bitrate_allocation;
+  }
+
+  LOG_ASSERT(num_temporal_layers <=
+             VP9TemporalLayers::kMaxSupportedTemporalLayers);
+  constexpr double kTemporalLayersBitrateScaleFactors
+      [][VP9TemporalLayers::kMaxSupportedTemporalLayers] = {
+          {0.50, 0.50, 0.00},  // For two temporal layers.
+          {0.25, 0.25, 0.50},  // For three temporal layers.
+      };
+
+  for (size_t i = 0; i < num_temporal_layers; i++) {
+    const double factor =
+        kTemporalLayersBitrateScaleFactors[num_temporal_layers - 2][i];
+    bitrate_allocation.SetBitrate(0 /* spatial_index */, i,
+                                  base::checked_cast<int>(bitrate * factor));
+  }
+  return bitrate_allocation;
+}
 
 MATCHER_P4(MatchRtcConfigWithRates,
            size,
@@ -75,9 +162,9 @@
          arg.scaling_factor_den[0] == 1;
 }
 
-MATCHER_P2(MatchFrameParam, frame_type, temporal_idx, "") {
+MATCHER_P2(MatchFrameParam, frame_type, temporal_layer_id, "") {
   return arg.frame_type == frame_type &&
-         (!temporal_idx || arg.temporal_layer_id == *temporal_idx);
+         (!temporal_layer_id || arg.temporal_layer_id == *temporal_layer_id);
 }
 
 class MockVP9Accelerator : public VP9Encoder::Accelerator {
@@ -120,14 +207,14 @@
   void SetUp() override;
 
  protected:
-  using FrameType = Vp9FrameHeader::FrameType;
-
-  void InitializeVP9Encoder(BitrateControl bitrate_control);
-  void EncodeSequence(FrameType frame_type);
+  void InitializeVP9Encoder(BitrateControl bitrate_control,
+                            size_t num_temporal_layers);
+  void EncodeSequence(bool is_keyframe);
   void EncodeConstantQuantizationParameterSequence(
-      FrameType frame_type,
-      const std::vector<bool>& expected_ref_frames_used,
-      base::Optional<uint8_t> expected_temporal_idx = base::nullopt);
+      bool is_keyframe,
+      base::Optional<std::array<bool, kVp9NumRefsPerFrame>>
+          expected_ref_frames_used,
+      base::Optional<uint8_t> expected_temporal_layer_id = base::nullopt);
   void UpdateRatesTest(BitrateControl bitrate_control,
                        size_t num_temporal_layers);
 
@@ -136,7 +223,8 @@
       bool keyframe);
   void UpdateRatesSequence(const VideoBitrateAllocation& bitrate_allocation,
                            uint32_t framerate,
-                           BitrateControl bitrate_control);
+                           BitrateControl bitrate_control,
+                           size_t num_temporal_layers);
 
   std::unique_ptr<VP9Encoder> encoder_;
   MockVP9Accelerator* mock_accelerator_ = nullptr;
@@ -146,11 +234,7 @@
 void VP9EncoderTest::SetUp() {
   auto mock_accelerator = std::make_unique<MockVP9Accelerator>();
   mock_accelerator_ = mock_accelerator.get();
-  auto rate_ctrl = std::make_unique<MockVP9RateControl>();
-  mock_rate_ctrl_ = rate_ctrl.get();
-
   encoder_ = std::make_unique<VP9Encoder>(std::move(mock_accelerator));
-  encoder_->set_rate_ctrl_for_testing(std::move(rate_ctrl));
 }
 
 std::unique_ptr<AcceleratedVideoEncoder::EncodeJob>
@@ -166,38 +250,58 @@
       input_frame, keyframe, base::DoNothing());
 }
 
-void VP9EncoderTest::InitializeVP9Encoder(BitrateControl bitrate_control) {
+void VP9EncoderTest::InitializeVP9Encoder(BitrateControl bitrate_control,
+                                          size_t num_temporal_layers) {
+  auto config = kDefaultVideoEncodeAcceleratorConfig;
   auto ave_config = kDefaultAcceleratedVideoEncoderConfig;
   ave_config.bitrate_control = bitrate_control;
   if (bitrate_control == BitrateControl::kConstantQuantizationParameter) {
-    constexpr size_t kNumTemporalLayers = 1u;
+    auto rate_ctrl = std::make_unique<MockVP9RateControl>();
+    mock_rate_ctrl_ = rate_ctrl.get();
+    encoder_->set_rate_ctrl_for_testing(std::move(rate_ctrl));
+
     VideoBitrateAllocation initial_bitrate_allocation;
     initial_bitrate_allocation.SetBitrate(
         0, 0, kDefaultVideoEncodeAcceleratorConfig.initial_bitrate);
+    if (num_temporal_layers > 1u) {
+      VideoEncodeAccelerator::Config::SpatialLayer spatial_layer;
+      spatial_layer.width = config.input_visible_size.width();
+      spatial_layer.height = config.input_visible_size.height();
+      spatial_layer.bitrate_bps = config.initial_bitrate;
+      spatial_layer.framerate = *config.initial_framerate;
+      spatial_layer.max_qp = 30;
+      spatial_layer.num_of_temporal_layers = num_temporal_layers;
+      config.spatial_layers.push_back(spatial_layer);
+    }
 
     EXPECT_CALL(
         *mock_rate_ctrl_,
         UpdateRateControl(MatchRtcConfigWithRates(
             kDefaultVideoEncodeAcceleratorConfig.input_visible_size,
-            initial_bitrate_allocation,
-            VideoEncodeAccelerator::kDefaultFramerate, kNumTemporalLayers)))
+            GetDefaultVideoBitrateAllocation(num_temporal_layers,
+                                             config.initial_bitrate),
+            VideoEncodeAccelerator::kDefaultFramerate, num_temporal_layers)))
         .Times(1)
         .WillOnce(Return());
+  } else {
+    // VP9Encoder doesn't support temporal layer encoding in
+    // BitrateControl::kConstantQuantizationParameter.
+    ASSERT_EQ(num_temporal_layers, 1u);
   }
-  EXPECT_TRUE(
-      encoder_->Initialize(kDefaultVideoEncodeAcceleratorConfig, ave_config));
+
+  EXPECT_TRUE(encoder_->Initialize(config, ave_config));
+  EXPECT_EQ(num_temporal_layers > 1u, !!encoder_->temporal_layers_);
 }
 
-void VP9EncoderTest::EncodeSequence(FrameType frame_type) {
+void VP9EncoderTest::EncodeSequence(bool is_keyframe) {
   InSequence seq;
-  const bool keyframe = frame_type == FrameType::KEYFRAME;
-  auto encode_job = CreateEncodeJob(keyframe);
+  auto encode_job = CreateEncodeJob(is_keyframe);
   scoped_refptr<VP9Picture> picture(new VP9Picture);
   EXPECT_CALL(*mock_accelerator_, GetPicture(encode_job.get()))
       .WillOnce(Invoke(
           [picture](AcceleratedVideoEncoder::EncodeJob*) { return picture; }));
   const auto& expected_ref_frames_used =
-      keyframe ? kRefFramesUsedForKeyFrame : kRefFramesUsedForInterFrame;
+      is_keyframe ? kRefFramesUsedForKeyFrame : kRefFramesUsedForInterFrame;
   EXPECT_CALL(*mock_accelerator_,
               SubmitFrameParameters(
                   encode_job.get(), _, _, _,
@@ -208,32 +312,33 @@
 }
 
 void VP9EncoderTest::EncodeConstantQuantizationParameterSequence(
-    FrameType frame_type,
-    const std::vector<bool>& expected_ref_frames_used,
-    base::Optional<uint8_t> expected_temporal_idx) {
-  const bool keyframe = frame_type == FrameType::KEYFRAME;
+    bool is_keyframe,
+    base::Optional<std::array<bool, kVp9NumRefsPerFrame>>
+        expected_ref_frames_used,
+    base::Optional<uint8_t> expected_temporal_layer_id) {
   InSequence seq;
-  auto encode_job = CreateEncodeJob(keyframe);
+  auto encode_job = CreateEncodeJob(is_keyframe);
   scoped_refptr<VP9Picture> picture(new VP9Picture);
   EXPECT_CALL(*mock_accelerator_, GetPicture(encode_job.get()))
       .WillOnce(Invoke(
           [picture](AcceleratedVideoEncoder::EncodeJob*) { return picture; }));
 
   FRAME_TYPE libvpx_frame_type =
-      keyframe ? FRAME_TYPE::KEY_FRAME : FRAME_TYPE::INTER_FRAME;
-  EXPECT_CALL(*mock_rate_ctrl_, ComputeQP(MatchFrameParam(
-                                    libvpx_frame_type, expected_temporal_idx)))
+      is_keyframe ? FRAME_TYPE::KEY_FRAME : FRAME_TYPE::INTER_FRAME;
+  EXPECT_CALL(
+      *mock_rate_ctrl_,
+      ComputeQP(MatchFrameParam(libvpx_frame_type, expected_temporal_layer_id)))
       .WillOnce(Return());
   constexpr int kDefaultQP = 34;
   constexpr int kDefaultLoopFilterLevel = 8;
   EXPECT_CALL(*mock_rate_ctrl_, GetQP()).WillOnce(Return(kDefaultQP));
   EXPECT_CALL(*mock_rate_ctrl_, GetLoopfilterLevel())
       .WillOnce(Return(kDefaultLoopFilterLevel));
-  if (!expected_ref_frames_used.empty()) {
+  if (expected_ref_frames_used) {
     EXPECT_CALL(*mock_accelerator_,
                 SubmitFrameParameters(
                     encode_job.get(), _, _, _,
-                    ::testing::ElementsAreArray(expected_ref_frames_used)))
+                    ::testing::ElementsAreArray(*expected_ref_frames_used)))
         .WillOnce(Return(true));
   } else {
     EXPECT_CALL(*mock_accelerator_,
@@ -254,17 +359,17 @@
 void VP9EncoderTest::UpdateRatesSequence(
     const VideoBitrateAllocation& bitrate_allocation,
     uint32_t framerate,
-    BitrateControl bitrate_control) {
+    BitrateControl bitrate_control,
+    size_t num_temporal_layers) {
   ASSERT_TRUE(encoder_->current_params_.bitrate_allocation !=
                   bitrate_allocation ||
               encoder_->current_params_.framerate != framerate);
 
   if (bitrate_control == BitrateControl::kConstantQuantizationParameter) {
-    constexpr size_t kNumTemporalLayers = 1u;
     EXPECT_CALL(*mock_rate_ctrl_,
                 UpdateRateControl(MatchRtcConfigWithRates(
                     encoder_->visible_size_, bitrate_allocation, framerate,
-                    kNumTemporalLayers)))
+                    num_temporal_layers)))
         .Times(1)
         .WillOnce(Return());
   }
@@ -276,32 +381,19 @@
 
 void VP9EncoderTest::UpdateRatesTest(BitrateControl bitrate_control,
                                      size_t num_temporal_layers) {
-  ASSERT_LE(num_temporal_layers, 3u);
-  auto create_allocation =
-      [num_temporal_layers](uint32_t bitrate) -> VideoBitrateAllocation {
-    VideoBitrateAllocation bitrate_allocation;
-    constexpr int kTemporalLayerBitrateScaleFactor[] = {1, 2, 4};
-    const int kScaleFactors =
-        std::accumulate(std::cbegin(kTemporalLayerBitrateScaleFactor),
-                        std::cend(kTemporalLayerBitrateScaleFactor), 0);
-    for (size_t ti = 0; ti < num_temporal_layers; ti++) {
-      bitrate_allocation.SetBitrate(
-          0, ti,
-          bitrate * kTemporalLayerBitrateScaleFactor[ti] / kScaleFactors);
-    }
-    return bitrate_allocation;
-  };
-
+  ASSERT_TRUE(num_temporal_layers <=
+              VP9TemporalLayers::kMaxSupportedTemporalLayers);
   const auto update_rates_and_encode =
-      [this, bitrate_control](FrameType frame_type,
-                              const VideoBitrateAllocation& bitrate_allocation,
-                              uint32_t framerate) {
-        UpdateRatesSequence(bitrate_allocation, framerate, bitrate_control);
+      [this, bitrate_control, num_temporal_layers](
+          bool is_keyframe, const VideoBitrateAllocation& bitrate_allocation,
+          uint32_t framerate) {
+        UpdateRatesSequence(bitrate_allocation, framerate, bitrate_control,
+                            num_temporal_layers);
         if (bitrate_control == BitrateControl::kConstantQuantizationParameter) {
-          EncodeConstantQuantizationParameterSequence(frame_type, {},
+          EncodeConstantQuantizationParameterSequence(is_keyframe, {},
                                                       base::nullopt);
         } else {
-          EncodeSequence(frame_type);
+          EncodeSequence(is_keyframe);
         }
       };
 
@@ -310,69 +402,114 @@
   const uint32_t kFramerate =
       *kDefaultVideoEncodeAcceleratorConfig.initial_framerate;
   // Call UpdateRates before Encode.
-  update_rates_and_encode(FrameType::KEYFRAME, create_allocation(kBitrate / 2),
-                          kFramerate);
+  update_rates_and_encode(
+      true, GetDefaultVideoBitrateAllocation(num_temporal_layers, kBitrate / 2),
+      kFramerate);
   // Bitrate change only.
-  update_rates_and_encode(FrameType::INTERFRAME, create_allocation(kBitrate),
-                          kFramerate);
+  update_rates_and_encode(
+      false, GetDefaultVideoBitrateAllocation(num_temporal_layers, kBitrate),
+      kFramerate);
   // Framerate change only.
-  update_rates_and_encode(FrameType::INTERFRAME, create_allocation(kBitrate),
-                          kFramerate + 2);
+  update_rates_and_encode(
+      false, GetDefaultVideoBitrateAllocation(num_temporal_layers, kBitrate),
+      kFramerate + 2);
   // Bitrate + Frame changes.
-  update_rates_and_encode(FrameType::INTERFRAME,
-                          create_allocation(kBitrate * 3 / 4), kFramerate - 5);
+  update_rates_and_encode(
+      false,
+      GetDefaultVideoBitrateAllocation(num_temporal_layers, kBitrate * 3 / 4),
+      kFramerate - 5);
 }
 
 struct VP9EncoderTestParam {
   VP9EncoderTest::BitrateControl bitrate_control;
+  size_t num_temporal_layers;
 } kTestCasesForVP9EncoderTest[] = {
-    {VP9EncoderTest::BitrateControl::kConstantBitrate},
-    {VP9EncoderTest::BitrateControl::kConstantQuantizationParameter},
+    {VP9EncoderTest::BitrateControl::kConstantBitrate, 1u},
+    {VP9EncoderTest::BitrateControl::kConstantQuantizationParameter, 1u},
+    {VP9EncoderTest::BitrateControl::kConstantQuantizationParameter,
+     VP9TemporalLayers::kMinSupportedTemporalLayers},
+    {VP9EncoderTest::BitrateControl::kConstantQuantizationParameter,
+     VP9TemporalLayers::kMaxSupportedTemporalLayers},
 };
 
 TEST_P(VP9EncoderTest, Initialize) {
-  InitializeVP9Encoder(GetParam().bitrate_control);
+  InitializeVP9Encoder(GetParam().bitrate_control,
+                       GetParam().num_temporal_layers);
 }
 
-TEST_P(VP9EncoderTest, Encode) {
+TEST_P(VP9EncoderTest, EncodeWithoutSoftwareBitrateControl) {
   const auto& bitrate_control = GetParam().bitrate_control;
-  InitializeVP9Encoder(bitrate_control);
-  if (bitrate_control == BitrateControl::kConstantBitrate) {
-    EncodeSequence(FrameType::KEYFRAME);
-    EncodeSequence(FrameType::INTERFRAME);
-  } else {
-    EncodeConstantQuantizationParameterSequence(FrameType::KEYFRAME,
-                                                kRefFramesUsedForKeyFrame);
-    EncodeConstantQuantizationParameterSequence(FrameType::INTERFRAME,
-                                                kRefFramesUsedForInterFrame);
+  if (bitrate_control != BitrateControl::kConstantBitrate)
+    GTEST_SKIP() << "Test only for without software bitrate control";
+
+  const size_t num_temporal_layers = GetParam().num_temporal_layers;
+  InitializeVP9Encoder(bitrate_control, num_temporal_layers);
+
+  EncodeSequence(true);
+  EncodeSequence(false);
+}
+
+TEST_P(VP9EncoderTest, EncodeWithSoftwareBitrateControl) {
+  const auto& bitrate_control = GetParam().bitrate_control;
+  if (bitrate_control != BitrateControl::kConstantQuantizationParameter)
+    GTEST_SKIP() << "Test only for with software bitrate control";
+
+  const size_t num_temporal_layers = GetParam().num_temporal_layers;
+  InitializeVP9Encoder(bitrate_control, num_temporal_layers);
+
+  constexpr size_t kEncodeFrames = 20;
+  for (size_t i = 0; i < kEncodeFrames; i++) {
+    const bool is_keyframe = i == 0;
+    std::array<bool, kVp9NumRefsPerFrame> ref_frames_used;
+    base::Optional<uint8_t> temporal_layer_id;
+    GetTemporalLayer(is_keyframe, i, num_temporal_layers, &ref_frames_used,
+                     &temporal_layer_id);
+    EncodeConstantQuantizationParameterSequence(is_keyframe, ref_frames_used,
+                                                temporal_layer_id);
+  }
+}
+
+TEST_P(VP9EncoderTest, ForceKeyFrameWithoutSoftwareBitrateControl) {
+  const auto& bitrate_control = GetParam().bitrate_control;
+  if (bitrate_control != BitrateControl::kConstantBitrate)
+    GTEST_SKIP() << "Test only for with software bitrate control";
+
+  const size_t num_temporal_layers = GetParam().num_temporal_layers;
+  InitializeVP9Encoder(bitrate_control, num_temporal_layers);
+
+  EncodeSequence(true /* is_keyframe */);
+  EncodeSequence(false /* is_keyframe */);
+  EncodeSequence(true /* is_keyframe */);
+  EncodeSequence(false /* is_keyframe */);
+}
+
+TEST_P(VP9EncoderTest, ForceKeyFrameWithSoftwareBitrateControl) {
+  const auto& bitrate_control = GetParam().bitrate_control;
+  if (bitrate_control != BitrateControl::kConstantQuantizationParameter)
+    GTEST_SKIP() << "Test only for with software bitrate control";
+
+  const size_t num_temporal_layers = GetParam().num_temporal_layers;
+  InitializeVP9Encoder(bitrate_control, num_temporal_layers);
+  constexpr size_t kNumKeyFrames = 3;
+  constexpr size_t kKeyFrameInterval = 20;
+  for (size_t j = 0; j < kNumKeyFrames; j++) {
+    for (size_t i = 0; i < kKeyFrameInterval; i++) {
+      const bool is_keyframe = i == 0;
+      std::array<bool, kVp9NumRefsPerFrame> ref_frames_used;
+      base::Optional<uint8_t> temporal_layer_id;
+      GetTemporalLayer(is_keyframe, i, num_temporal_layers, &ref_frames_used,
+                       &temporal_layer_id);
+      EncodeConstantQuantizationParameterSequence(is_keyframe, ref_frames_used,
+                                                  temporal_layer_id);
+    }
   }
 }
 
 TEST_P(VP9EncoderTest, UpdateRates) {
   const auto& bitrate_control = GetParam().bitrate_control;
-  InitializeVP9Encoder(bitrate_control);
-  constexpr size_t kNumTemporalLayers = 1u;
-  UpdateRatesTest(bitrate_control, kNumTemporalLayers);
-}
-
-TEST_P(VP9EncoderTest, ForceKeyFrame) {
-  const auto& bitrate_control = GetParam().bitrate_control;
-  InitializeVP9Encoder(GetParam().bitrate_control);
-  if (bitrate_control == BitrateControl::kConstantBitrate) {
-    EncodeSequence(FrameType::KEYFRAME);
-    EncodeSequence(FrameType::INTERFRAME);
-    EncodeSequence(FrameType::KEYFRAME);
-    EncodeSequence(FrameType::INTERFRAME);
-  } else {
-    EncodeConstantQuantizationParameterSequence(FrameType::KEYFRAME,
-                                                kRefFramesUsedForKeyFrame);
-    EncodeConstantQuantizationParameterSequence(FrameType::INTERFRAME,
-                                                kRefFramesUsedForInterFrame);
-    EncodeConstantQuantizationParameterSequence(FrameType::KEYFRAME,
-                                                kRefFramesUsedForKeyFrame);
-    EncodeConstantQuantizationParameterSequence(FrameType::INTERFRAME,
-                                                kRefFramesUsedForInterFrame);
-  }
+  const size_t num_temporal_layers = GetParam().num_temporal_layers;
+  InitializeVP9Encoder(bitrate_control, num_temporal_layers);
+  UpdateRatesTest(bitrate_control, num_temporal_layers);
 }
 
 INSTANTIATE_TEST_SUITE_P(,
diff --git a/media/gpu/windows/dxva_video_decode_accelerator_win.cc b/media/gpu/windows/dxva_video_decode_accelerator_win.cc
index 14a5258..ad3b7d5 100644
--- a/media/gpu/windows/dxva_video_decode_accelerator_win.cc
+++ b/media/gpu/windows/dxva_video_decode_accelerator_win.cc
@@ -612,6 +612,8 @@
       use_keyed_mutex_(false),
       using_angle_device_(false),
       using_debug_device_(false),
+      enable_accelerated_av1_decode_(
+          !workarounds.disable_accelerated_av1_decode),
       enable_accelerated_vpx_decode_(
           !workarounds.disable_accelerated_vpx_decode),
       processing_config_changed_(false),
@@ -1423,7 +1425,8 @@
       using_ms_vpx_mft_ = true;
   }
 
-  if (base::FeatureList::IsEnabled(kMediaFoundationAV1Decoding) &&
+  if (enable_accelerated_av1_decode_ &&
+      base::FeatureList::IsEnabled(kMediaFoundationAV1Decoding) &&
       (profile >= AV1PROFILE_MIN && profile <= AV1PROFILE_MAX)) {
     codec_ = kCodecAV1;
     clsid = CLSID_CAV1DecoderMFT;
diff --git a/media/gpu/windows/dxva_video_decode_accelerator_win.h b/media/gpu/windows/dxva_video_decode_accelerator_win.h
index 38512c4cd..78e238f 100644
--- a/media/gpu/windows/dxva_video_decode_accelerator_win.h
+++ b/media/gpu/windows/dxva_video_decode_accelerator_win.h
@@ -582,7 +582,10 @@
   bool using_angle_device_;
   bool using_debug_device_;
 
-  // Enables hardware acceleration for VP9 video decoding.
+  // Enables hardware acceleration for AV1 video decoding.
+  const bool enable_accelerated_av1_decode_;
+
+  // Enables hardware acceleration for VP8/VP9 video decoding.
   const bool enable_accelerated_vpx_decode_;
 
   // The media foundation H.264 decoder has problems handling changes like
diff --git a/media/gpu/windows/supported_profile_helpers.cc b/media/gpu/windows/supported_profile_helpers.cc
index b87f37c8..79549e0d 100644
--- a/media/gpu/windows/supported_profile_helpers.cc
+++ b/media/gpu/windows/supported_profile_helpers.cc
@@ -243,7 +243,8 @@
       gfx::Size(8192, 4320), gfx::Size(8192, 8192)};
 
   const bool should_test_for_av1_support =
-      base::FeatureList::IsEnabled(kMediaFoundationAV1Decoding);
+      base::FeatureList::IsEnabled(kMediaFoundationAV1Decoding) &&
+      !workarounds.disable_accelerated_av1_decode;
 
   // Enumerate supported video profiles and look for the known profile for each
   // codec. We first look through the the decoder profiles so we don't run N
diff --git a/net/BUILD.gn b/net/BUILD.gn
index d91e722..a499040 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -158,6 +158,7 @@
     "base/parse_number.h",
     "base/port_util.cc",
     "base/port_util.h",
+    "base/privacy_mode.cc",
     "base/privacy_mode.h",
     "base/rand_callback.h",
     "base/registry_controlled_domains/registry_controlled_domain.cc",
@@ -519,8 +520,6 @@
       "cert/ev_root_ca_metadata.h",
       "cert/internal/system_trust_store.cc",
       "cert/internal/system_trust_store.h",
-      "cert/jwk_serializer.cc",
-      "cert/jwk_serializer.h",
       "cert/known_roots.cc",
       "cert/known_roots.h",
       "cert/merkle_audit_proof.cc",
@@ -4193,7 +4192,6 @@
     "cert/internal/verify_certificate_chain_unittest.cc",
     "cert/internal/verify_name_match_unittest.cc",
     "cert/internal/verify_signed_data_unittest.cc",
-    "cert/jwk_serializer_unittest.cc",
     "cert/known_roots_unittest.cc",
     "cert/merkle_audit_proof_unittest.cc",
     "cert/merkle_tree_leaf_unittest.cc",
diff --git a/net/base/net_resources.grd b/net/base/net_resources.grd
index 45d1926..2937014 100644
--- a/net/base/net_resources.grd
+++ b/net/base/net_resources.grd
@@ -9,7 +9,7 @@
   <translations />
   <release seq="1">
     <includes>
-      <include name="IDR_DIR_HEADER_HTML" file="dir_header.html" type="BINDATA" compress="gzip" />
+      <include name="IDR_DIR_HEADER_HTML" file="dir_header.html" type="BINDATA" />
     </includes>
   </release>
 </grit>
diff --git a/net/base/privacy_mode.cc b/net/base/privacy_mode.cc
new file mode 100644
index 0000000..f490a1ca
--- /dev/null
+++ b/net/base/privacy_mode.cc
@@ -0,0 +1,24 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/base/privacy_mode.h"
+
+#include "base/notreached.h"
+
+namespace net {
+
+const char* PrivacyModeToDebugString(PrivacyMode privacy_mode) {
+  switch (privacy_mode) {
+    case PRIVACY_MODE_DISABLED:
+      return "disabled";
+    case PRIVACY_MODE_ENABLED:
+      return "enabled";
+    case PRIVACY_MODE_ENABLED_WITHOUT_CLIENT_CERTS:
+      return "enabled without client certs";
+  }
+  NOTREACHED();
+  return "";
+}
+
+}  // namespace net
diff --git a/net/base/privacy_mode.h b/net/base/privacy_mode.h
index 90e99dd..c9cb6558 100644
--- a/net/base/privacy_mode.h
+++ b/net/base/privacy_mode.h
@@ -18,6 +18,8 @@
   PRIVACY_MODE_ENABLED_WITHOUT_CLIENT_CERTS = 2,
 };
 
+const char* PrivacyModeToDebugString(PrivacyMode privacy_mode);
+
 }  // namespace net
 
 #endif  // NET_BASE_PRIVACY_MODE_H_
diff --git a/net/cert/jwk_serializer.cc b/net/cert/jwk_serializer.cc
deleted file mode 100644
index 768dab0..0000000
--- a/net/cert/jwk_serializer.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/cert/jwk_serializer.h"
-
-#include "base/base64url.h"
-#include "base/strings/string_util.h"
-#include "base/values.h"
-#include "crypto/openssl_util.h"
-#include "third_party/boringssl/src/include/openssl/bn.h"
-#include "third_party/boringssl/src/include/openssl/bytestring.h"
-#include "third_party/boringssl/src/include/openssl/ec.h"
-#include "third_party/boringssl/src/include/openssl/ec_key.h"
-#include "third_party/boringssl/src/include/openssl/evp.h"
-
-namespace net {
-
-namespace JwkSerializer {
-
-namespace {
-
-bool ConvertEcKeyToJwk(EVP_PKEY* pkey,
-                       base::DictionaryValue* public_key_jwk,
-                       const crypto::OpenSSLErrStackTracer& err_tracer) {
-  EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey);
-  if (!ec_key)
-    return false;
-  const EC_GROUP* ec_group = EC_KEY_get0_group(ec_key);
-  if (!ec_group)
-    return false;
-
-  std::string curve_name;
-  int nid = EC_GROUP_get_curve_name(ec_group);
-  if (nid == NID_X9_62_prime256v1) {
-    curve_name = "P-256";
-  } else if (nid == NID_secp384r1) {
-    curve_name = "P-384";
-  } else if (nid == NID_secp521r1) {
-    curve_name = "P-521";
-  } else {
-    return false;
-  }
-
-  int degree_bytes = (EC_GROUP_get_degree(ec_group) + 7) / 8;
-
-  const EC_POINT* ec_point = EC_KEY_get0_public_key(ec_key);
-  if (!ec_point)
-    return false;
-
-  bssl::UniquePtr<BIGNUM> x(BN_new());
-  bssl::UniquePtr<BIGNUM> y(BN_new());
-  if (!EC_POINT_get_affine_coordinates_GFp(ec_group, ec_point, x.get(), y.get(),
-                                           nullptr)) {
-    return false;
-  }
-
-  // The coordinates are encoded with leading zeros included.
-  std::string x_bytes;
-  std::string y_bytes;
-  if (!BN_bn2bin_padded(reinterpret_cast<uint8_t*>(
-                            base::WriteInto(&x_bytes, degree_bytes + 1)),
-                        degree_bytes, x.get()) ||
-      !BN_bn2bin_padded(reinterpret_cast<uint8_t*>(
-                            base::WriteInto(&y_bytes, degree_bytes + 1)),
-                        degree_bytes, y.get())) {
-    return false;
-  }
-
-  public_key_jwk->SetString("kty", "EC");
-  public_key_jwk->SetString("crv", curve_name);
-
-  std::string x_b64;
-  base::Base64UrlEncode(x_bytes, base::Base64UrlEncodePolicy::OMIT_PADDING,
-                        &x_b64);
-  public_key_jwk->SetString("x", x_b64);
-
-  std::string y_b64;
-  base::Base64UrlEncode(y_bytes, base::Base64UrlEncodePolicy::OMIT_PADDING,
-                        &y_b64);
-  public_key_jwk->SetString("y", y_b64);
-
-  return true;
-}
-
-}  // namespace
-
-bool ConvertSpkiFromDerToJwk(const base::StringPiece& spki_der,
-                             base::DictionaryValue* public_key_jwk) {
-  public_key_jwk->Clear();
-
-  crypto::EnsureOpenSSLInit();
-  crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
-
-  CBS cbs;
-  CBS_init(&cbs, reinterpret_cast<const uint8_t*>(spki_der.data()),
-           spki_der.size());
-  bssl::UniquePtr<EVP_PKEY> pubkey(EVP_parse_public_key(&cbs));
-  if (!pubkey || CBS_len(&cbs) != 0)
-    return false;
-
-  if (pubkey->type == EVP_PKEY_EC) {
-    return ConvertEcKeyToJwk(pubkey.get(), public_key_jwk, err_tracer);
-  } else {
-    // TODO(juanlang): other algorithms
-    return false;
-  }
-}
-
-}  // namespace JwkSerializer
-
-}  // namespace net
diff --git a/net/cert/jwk_serializer.h b/net/cert/jwk_serializer.h
deleted file mode 100644
index ee8cc8a..0000000
--- a/net/cert/jwk_serializer.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_CERT_JWK_SERIALIZER_H_
-#define NET_CERT_JWK_SERIALIZER_H_
-
-#include "base/strings/string_piece.h"
-#include "net/base/net_export.h"
-
-namespace base {
-class DictionaryValue;
-}
-
-namespace net {
-
-namespace JwkSerializer {
-
-// Converts a subject public key info from DER to JWK.
-// See http://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-17 for
-// the output format.
-NET_EXPORT_PRIVATE bool ConvertSpkiFromDerToJwk(
-    const base::StringPiece& spki_der,
-    base::DictionaryValue* public_key_jwk);
-
-} // namespace JwkSerializer
-
-} // namespace net
-
-#endif  // NET_CERT_JWK_SERIALIZER_H_
diff --git a/net/cert/jwk_serializer_unittest.cc b/net/cert/jwk_serializer_unittest.cc
deleted file mode 100644
index e563607a..0000000
--- a/net/cert/jwk_serializer_unittest.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/cert/jwk_serializer.h"
-
-#include "base/base64url.h"
-#include "base/values.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace net {
-
-namespace {
-
-// This is the ASN.1 prefix for a P-256 public key. Specifically it's:
-// SEQUENCE
-//   SEQUENCE
-//     OID id-ecPublicKey
-//     OID prime256v1
-//   BIT STRING, length 66, 0 trailing bits: 0x04
-//
-// The 0x04 in the BIT STRING is the prefix for an uncompressed, X9.62
-// public key. Following that are the two field elements as 32-byte,
-// big-endian numbers, as required by the Channel ID.
-static const unsigned char kP256SpkiPrefix[] = {
-    0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
-    0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
-    0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
-    0x42, 0x00, 0x04
-};
-static const unsigned int kEcCoordinateSize = 32U;
-
-// This is a valid P-256 public key.
-static const unsigned char kSpkiEc[] = {
-    0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
-    0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
-    0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
-    0x42, 0x00, 0x04,
-    0x29, 0x5d, 0x6e, 0xfe, 0x33, 0x77, 0x26, 0xea,
-    0x5b, 0xa4, 0xe6, 0x1b, 0x34, 0x6e, 0x7b, 0xa0,
-    0xa3, 0x8f, 0x33, 0x49, 0xa0, 0x9c, 0xae, 0x98,
-    0xbd, 0x46, 0x0d, 0xf6, 0xd4, 0x5a, 0xdc, 0x8a,
-    0x1f, 0x8a, 0xb2, 0x20, 0x51, 0xb7, 0xd2, 0x87,
-    0x0d, 0x53, 0x7e, 0x5d, 0x94, 0xa3, 0xe0, 0x34,
-    0x16, 0xa1, 0xcc, 0x10, 0x48, 0xcd, 0x70, 0x9c,
-    0x05, 0xd3, 0xd2, 0xca, 0xdf, 0x44, 0x2f, 0xf4
-};
-
-// This is a P-256 public key with a leading 0.
-static const unsigned char kSpkiEcWithLeadingZero[] = {
-    0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
-    0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
-    0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
-    0x42, 0x00, 0x04,
-    0x00, 0x8e, 0xd5, 0x49, 0x51, 0xad, 0x7d, 0xd3,
-    0x3a, 0x59, 0x86, 0xd1, 0x2c, 0xba, 0x05, 0xd3,
-    0xa6, 0x3c, 0x5d, 0x6d, 0x28, 0xde, 0x8f, 0xdd,
-    0xa5, 0x3d, 0x30, 0x18, 0x05, 0x86, 0x76, 0x9c,
-    0x7c, 0xa7, 0xba, 0x58, 0xea, 0x1a, 0x84, 0x19,
-    0x29, 0x0a, 0x15, 0x30, 0x7d, 0x6b, 0x00, 0x41,
-    0x64, 0x56, 0x84, 0x19, 0x54, 0x3e, 0x26, 0x13,
-    0xc9, 0x1e, 0x31, 0x89, 0xe2, 0x62, 0xcb, 0x3f
-};
-
-// Section 2 of RFC 7515 defines that an URL-safe base64 encoding must be used
-// with all trailing '=' characters omitted. Returns whether the |input|
-// contains any of the forbidden base64 characters (+, -, =).
-bool ContainsNonUrlSafeBase64Characters(base::StringPiece input) {
-  return input.find_first_of("+-=") != std::string::npos;
-}
-
-}  // namespace
-
-TEST(JwkSerializerTest, ConvertSpkiFromDerToJwkEc) {
-  base::StringPiece spki;
-  base::DictionaryValue public_key_jwk;
-
-  EXPECT_FALSE(JwkSerializer::ConvertSpkiFromDerToJwk(spki, &public_key_jwk));
-  EXPECT_TRUE(public_key_jwk.empty());
-
-  // Test the result of a "normal" point on this curve.
-  spki = base::StringPiece(reinterpret_cast<const char*>(kSpkiEc),
-                           sizeof(kSpkiEc));
-  EXPECT_TRUE(JwkSerializer::ConvertSpkiFromDerToJwk(spki, &public_key_jwk));
-
-  std::string string_value;
-  EXPECT_TRUE(public_key_jwk.GetString("kty", &string_value));
-  EXPECT_STREQ("EC", string_value.c_str());
-  EXPECT_TRUE(public_key_jwk.GetString("crv", &string_value));
-  EXPECT_STREQ("P-256", string_value.c_str());
-
-  EXPECT_TRUE(public_key_jwk.GetString("x", &string_value));
-  EXPECT_FALSE(ContainsNonUrlSafeBase64Characters(string_value));
-  std::string decoded_coordinate;
-  EXPECT_TRUE(base::Base64UrlDecode(
-      string_value, base::Base64UrlDecodePolicy::DISALLOW_PADDING,
-      &decoded_coordinate));
-  EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size());
-  EXPECT_EQ(0,
-            memcmp(decoded_coordinate.data(),
-                   kSpkiEc + sizeof(kP256SpkiPrefix),
-                   kEcCoordinateSize));
-
-  EXPECT_TRUE(public_key_jwk.GetString("y", &string_value));
-  EXPECT_FALSE(ContainsNonUrlSafeBase64Characters(string_value));
-  EXPECT_TRUE(base::Base64UrlDecode(
-      string_value, base::Base64UrlDecodePolicy::DISALLOW_PADDING,
-      &decoded_coordinate));
-  EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size());
-  EXPECT_EQ(0,
-            memcmp(decoded_coordinate.data(),
-                  kSpkiEc + sizeof(kP256SpkiPrefix) + kEcCoordinateSize,
-                  kEcCoordinateSize));
-
-  // Test the result of a corner case: leading 0s in the x, y coordinates are
-  // not trimmed, but the point is fixed-length encoded.
-  spki = {reinterpret_cast<const char*>(kSpkiEcWithLeadingZero),
-          sizeof(kSpkiEcWithLeadingZero)};
-  EXPECT_TRUE(JwkSerializer::ConvertSpkiFromDerToJwk(spki, &public_key_jwk));
-
-  EXPECT_TRUE(public_key_jwk.GetString("kty", &string_value));
-  EXPECT_STREQ("EC", string_value.c_str());
-  EXPECT_TRUE(public_key_jwk.GetString("crv", &string_value));
-  EXPECT_STREQ("P-256", string_value.c_str());
-
-  EXPECT_TRUE(public_key_jwk.GetString("x", &string_value));
-  EXPECT_FALSE(ContainsNonUrlSafeBase64Characters(string_value));
-  EXPECT_TRUE(base::Base64UrlDecode(
-      string_value, base::Base64UrlDecodePolicy::DISALLOW_PADDING,
-      &decoded_coordinate));
-  EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size());
-  EXPECT_EQ(0,
-            memcmp(decoded_coordinate.data(),
-                   kSpkiEcWithLeadingZero + sizeof(kP256SpkiPrefix),
-                   kEcCoordinateSize));
-
-  EXPECT_TRUE(public_key_jwk.GetString("y", &string_value));
-  EXPECT_FALSE(ContainsNonUrlSafeBase64Characters(string_value));
-  EXPECT_TRUE(base::Base64UrlDecode(
-      string_value, base::Base64UrlDecodePolicy::DISALLOW_PADDING,
-      &decoded_coordinate));
-  EXPECT_EQ(kEcCoordinateSize, decoded_coordinate.size());
-  EXPECT_EQ(0, memcmp(
-      decoded_coordinate.data(),
-      kSpkiEcWithLeadingZero + sizeof(kP256SpkiPrefix) + kEcCoordinateSize,
-      kEcCoordinateSize));
-}
-
-}  // namespace net
diff --git a/net/log/net_log_event_type_list.h b/net/log/net_log_event_type_list.h
index 36b24fb..f952484 100644
--- a/net/log/net_log_event_type_list.h
+++ b/net/log/net_log_event_type_list.h
@@ -1670,7 +1670,10 @@
 // Measures the time taken to execute the QuicStreamFactory::Job.
 // The event parameters are:
 //   {
-//     "server_id": <The quic::QuicServerId that the Job serves>,
+//     "host": <The origin hostname that the Job serves>,
+//     "port": <The origin port>,
+//     "privacy_mode": <The privacy mode of the Job>,
+//     "network_isolation_key": <The NetworkIsolationKey of the Job>,
 //   }
 EVENT_TYPE(QUIC_STREAM_FACTORY_JOB)
 
@@ -1714,7 +1717,14 @@
 
 // The start/end of a quic::QuicSession.
 //   {
-//     "host": <The host-port string>,
+//     "host": <The origin hostname string>,
+//     "port": <The origin port>,
+//     "privacy_mode": <The privacy mode of the session>,
+//     "network_isolation_key": <The NetworkIsolationKey of the session>,
+//     "require_confirmation": <True if the session will wait for a successful
+//                              QUIC handshake before vending streams>,
+//     "cert_verify_flags": <The certificate verification flags for the
+//                           session>,
 //   }
 EVENT_TYPE(QUIC_SESSION)
 
diff --git a/net/quic/quic_chromium_client_session.cc b/net/quic/quic_chromium_client_session.cc
index f2e2bfd..49d99801 100644
--- a/net/quic/quic_chromium_client_session.cc
+++ b/net/quic/quic_chromium_client_session.cc
@@ -26,6 +26,7 @@
 #include "net/base/net_errors.h"
 #include "net/base/network_activity_monitor.h"
 #include "net/base/network_isolation_key.h"
+#include "net/base/privacy_mode.h"
 #include "net/base/url_util.h"
 #include "net/http/transport_security_state.h"
 #include "net/log/net_log_event_type.h"
@@ -270,25 +271,28 @@
 }
 
 base::Value NetLogQuicClientSessionParams(
-    const quic::QuicServerId* server_id,
+    const QuicSessionKey* session_key,
     const quic::QuicConnectionId& connection_id,
     const quic::QuicConnectionId& client_connection_id,
     const quic::ParsedQuicVersionVector& supported_versions,
     int cert_verify_flags,
     bool require_confirmation) {
-  base::DictionaryValue dict;
-  dict.SetString("host", server_id->host());
-  dict.SetInteger("port", server_id->port());
-  dict.SetBoolean("privacy_mode", server_id->privacy_mode_enabled());
-  dict.SetBoolean("require_confirmation", require_confirmation);
-  dict.SetInteger("cert_verify_flags", cert_verify_flags);
-  dict.SetString("connection_id", connection_id.ToString());
+  base::Value dict(base::Value::Type::DICTIONARY);
+  dict.SetStringKey("host", session_key->server_id().host());
+  dict.SetIntKey("port", session_key->server_id().port());
+  dict.SetStringKey("privacy_mode",
+                    PrivacyModeToDebugString(session_key->privacy_mode()));
+  dict.SetStringKey("network_isolation_key",
+                    session_key->network_isolation_key().ToDebugString());
+  dict.SetBoolKey("require_confirmation", require_confirmation);
+  dict.SetIntKey("cert_verify_flags", cert_verify_flags);
+  dict.SetStringKey("connection_id", connection_id.ToString());
   if (!client_connection_id.IsEmpty()) {
-    dict.SetString("client_connection_id", client_connection_id.ToString());
+    dict.SetStringKey("client_connection_id", client_connection_id.ToString());
   }
-  dict.SetString("versions",
-                 ParsedQuicVersionVectorToString(supported_versions));
-  return std::move(dict);
+  dict.SetStringKey("versions",
+                    ParsedQuicVersionVectorToString(supported_versions));
+  return dict;
 }
 
 base::Value NetLogQuicPushPromiseReceivedParams(
@@ -881,9 +885,8 @@
   migrate_back_to_default_timer_.SetTaskRunner(task_runner_);
   net_log_.BeginEvent(NetLogEventType::QUIC_SESSION, [&] {
     return NetLogQuicClientSessionParams(
-        &session_key.server_id(), connection_id(),
-        connection->client_connection_id(), supported_versions(),
-        cert_verify_flags, require_confirmation_);
+        &session_key, connection_id(), connection->client_connection_id(),
+        supported_versions(), cert_verify_flags, require_confirmation_);
   });
   IPEndPoint address;
   if (socket_raw && socket_raw->GetLocalAddress(&address) == OK &&
@@ -1106,6 +1109,7 @@
 void QuicChromiumClientSession::AddConnectivityObserver(
     ConnectivityObserver* observer) {
   connectivity_observer_list_.AddObserver(observer);
+  observer->OnSessionRegistered(this, GetCurrentNetwork());
 }
 
 void QuicChromiumClientSession::RemoveConnectivityObserver(
@@ -1671,6 +1675,12 @@
 
   RecordConnectionCloseErrorCode(frame, source, session_key_.host(),
                                  OneRttKeysAvailable());
+  if (OneRttKeysAvailable()) {
+    NetworkChangeNotifier::NetworkHandle current_network = GetCurrentNetwork();
+    for (auto& observer : connectivity_observer_list_)
+      observer.OnSessionClosedAfterHandshake(this, current_network, source,
+                                             frame.quic_error_code);
+  }
 
   const quic::QuicErrorCode error = frame.quic_error_code;
   const std::string& error_details = frame.error_details;
diff --git a/net/quic/quic_chromium_client_session.h b/net/quic/quic_chromium_client_session.h
index aff354aa..edb004a 100644
--- a/net/quic/quic_chromium_client_session.h
+++ b/net/quic/quic_chromium_client_session.h
@@ -164,6 +164,20 @@
         NetworkChangeNotifier::NetworkHandle network,
         int error_code) = 0;
 
+    // Called when |session| is closed by |source| with |error_code|
+    // and handshake has been confirmed.
+    virtual void OnSessionClosedAfterHandshake(
+        QuicChromiumClientSession* session,
+        NetworkChangeNotifier::NetworkHandle network,
+        quic::ConnectionCloseSource source,
+        quic::QuicErrorCode error_code) = 0;
+
+    // Called when |this| is registered to monitor the connectivity of the
+    // |session|.
+    virtual void OnSessionRegistered(
+        QuicChromiumClientSession* session,
+        NetworkChangeNotifier::NetworkHandle network) = 0;
+
     // Called when |session| is removed.
     virtual void OnSessionRemoved(QuicChromiumClientSession* session) = 0;
   };
diff --git a/net/quic/quic_connectivity_monitor.cc b/net/quic/quic_connectivity_monitor.cc
index fe57844..01ed6aa9 100644
--- a/net/quic/quic_connectivity_monitor.cc
+++ b/net/quic/quic_connectivity_monitor.cc
@@ -14,6 +14,39 @@
 
 QuicConnectivityMonitor::~QuicConnectivityMonitor() = default;
 
+void QuicConnectivityMonitor::RecordConnectivityStatsToHistograms(
+    const std::string& notification,
+    NetworkChangeNotifier::NetworkHandle affected_network) const {
+  if (notification == "OnNetworkSoonToDisconnect" ||
+      notification == "OnNetworkDisconnected") {
+    // If the disconnected network is not the default network, ignore
+    // stats collections.
+    if (affected_network != default_network_)
+      return;
+  }
+
+  // TODO(crbug.com/1090532): rename histograms prefix to
+  // Net.QuicConnectivityMonitor.
+  UMA_HISTOGRAM_COUNTS_100(
+      "Net.QuicStreamFactory.NumQuicSessionsAtNetworkChange",
+      active_sessions_.size());
+
+  // Skip degrading session collection if there are less than two sessions.
+  if (active_sessions_.size() < 2)
+    return;
+
+  size_t num_degrading_sessions = GetNumDegradingSessions();
+  const std::string raw_histogram_name =
+      "Net.QuicStreamFactory.NumDegradingSessions." + notification;
+  base::UmaHistogramExactLinear(raw_histogram_name, num_degrading_sessions,
+                                101);
+
+  int percentage = num_degrading_sessions * 100 / active_sessions_.size();
+  const std::string percentage_histogram_name =
+      "Net.QuicStreamFactory.PercentageDegradingSessions." + notification;
+  base::UmaHistogramExactLinear(percentage_histogram_name, percentage, 101);
+}
+
 size_t QuicConnectivityMonitor::GetNumDegradingSessions() const {
   return degrading_sessions_.size();
 }
@@ -51,16 +84,53 @@
     ++write_error_map_[error_code];
 }
 
+void QuicConnectivityMonitor::OnSessionClosedAfterHandshake(
+    QuicChromiumClientSession* session,
+    NetworkChangeNotifier::NetworkHandle network,
+    quic::ConnectionCloseSource source,
+    quic::QuicErrorCode error_code) {
+  if (network != default_network_)
+    return;
+
+  if (source == quic::ConnectionCloseSource::FROM_PEER) {
+    // Connection closed by the peer post handshake with PUBLIC RESET
+    // is most likely a NAT rebinding issue.
+    if (error_code == quic::QUIC_PUBLIC_RESET)
+      quic_error_map_[error_code]++;
+    return;
+  }
+
+  // Connection close by self with PACKET_WRITE_ERROR or TOO_MANY_RTOS
+  // is likely a connectivity issue.
+  if (error_code == quic::QUIC_PACKET_WRITE_ERROR ||
+      error_code == quic::QUIC_TOO_MANY_RTOS) {
+    quic_error_map_[error_code]++;
+  }
+}
+
+void QuicConnectivityMonitor::OnSessionRegistered(
+    QuicChromiumClientSession* session,
+    NetworkChangeNotifier::NetworkHandle network) {
+  if (network == default_network_) {
+    active_sessions_.insert(session);
+    total_num_sessions_tracked_++;
+  }
+}
+
 void QuicConnectivityMonitor::OnSessionRemoved(
     QuicChromiumClientSession* session) {
   degrading_sessions_.erase(session);
+  active_sessions_.erase(session);
 }
 
 void QuicConnectivityMonitor::OnDefaultNetworkUpdated(
     NetworkChangeNotifier::NetworkHandle default_network) {
   default_network_ = default_network;
+  active_sessions_.clear();
+  total_num_sessions_tracked_ = 0u;
   degrading_sessions_.clear();
   write_error_map_.clear();
+  quic_error_map_.clear();
 }
 
 void QuicConnectivityMonitor::OnIPAddressChanged() {
diff --git a/net/quic/quic_connectivity_monitor.h b/net/quic/quic_connectivity_monitor.h
index e07c39b..840769d 100644
--- a/net/quic/quic_connectivity_monitor.h
+++ b/net/quic/quic_connectivity_monitor.h
@@ -25,6 +25,11 @@
 
   ~QuicConnectivityMonitor() override;
 
+  // Records connectivity related stats to histograms.
+  void RecordConnectivityStatsToHistograms(
+      const std::string& platform_notification,
+      NetworkChangeNotifier::NetworkHandle affected_network) const;
+
   // Returns the number of sessions that are currently degrading on the default
   // network interface.
   size_t GetNumDegradingSessions() const;
@@ -65,20 +70,40 @@
       NetworkChangeNotifier::NetworkHandle network,
       int error_code) override;
 
+  void OnSessionClosedAfterHandshake(
+      QuicChromiumClientSession* session,
+      NetworkChangeNotifier::NetworkHandle network,
+      quic::ConnectionCloseSource source,
+      quic::QuicErrorCode error_code) override;
+
+  void OnSessionRegistered(
+      QuicChromiumClientSession* session,
+      NetworkChangeNotifier::NetworkHandle network) override;
+
   void OnSessionRemoved(QuicChromiumClientSession* session) override;
 
  private:
   // Size chosen per net.QuicSession.WriteError histogram.
   using WriteErrorMap = quic::QuicSmallMap<int, size_t, 20>;
+  // The most common QuicErrorCode cared by this monitor is:
+  // QUIC_PUBLIC_RESET by the peer, or
+  // QUIC_PACKET_WRITE_ERROR/QUIC_TOO_MANY_RTOS by self.
+  using QuicErrorCodeMap = quic::QuicSmallMap<quic::QuicErrorCode, size_t, 5>;
 
   // If NetworkHandle is not supported, always set to
   // NetworkChangeNotifier::kInvalidNetworkHandle.
   NetworkChangeNotifier::NetworkHandle default_network_;
   // Sessions that are currently degrading on the |default_network_|.
   quic::QuicHashSet<QuicChromiumClientSession*> degrading_sessions_;
+  // Sessions that are currently active on the |default_network_|.
+  quic::QuicHashSet<QuicChromiumClientSession*> active_sessions_;
+  // Total number of sessions that has been tracked on the current network.
+  // Sessions may have been closed.
+  size_t total_num_sessions_tracked_{0u};
 
   // Map from the write error code to the corresponding number of reports.
   WriteErrorMap write_error_map_;
+  QuicErrorCodeMap quic_error_map_;
 
   base::WeakPtrFactory<QuicConnectivityMonitor> weak_factory_{this};
   DISALLOW_COPY_AND_ASSIGN(QuicConnectivityMonitor);
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index ce86b22e..99cd7353 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -109,14 +109,15 @@
 };
 
 base::Value NetLogQuicStreamFactoryJobParams(
-    const quic::QuicServerId* server_id) {
-  base::DictionaryValue dict;
-  dict.SetString(
-      "server_id",
-      "https://" +
-          HostPortPair(server_id->host(), server_id->port()).ToString() +
-          (server_id->privacy_mode_enabled() ? "/private" : ""));
-  return std::move(dict);
+    const QuicStreamFactory::QuicSessionAliasKey* key) {
+  base::Value dict(base::Value::Type::DICTIONARY);
+  dict.SetStringKey("host", key->server_id().host());
+  dict.SetIntKey("port", key->server_id().port());
+  dict.SetStringKey("privacy_mode", PrivacyModeToDebugString(
+                                        key->session_key().privacy_mode()));
+  dict.SetStringKey("network_isolation_key",
+                    key->session_key().network_isolation_key().ToDebugString());
+  return dict;
 }
 
 std::string QuicPlatformNotificationToString(
@@ -501,9 +502,8 @@
       connection_retried_(false),
       session_(nullptr),
       network_(NetworkChangeNotifier::kInvalidNetworkHandle) {
-  net_log_.BeginEvent(NetLogEventType::QUIC_STREAM_FACTORY_JOB, [&] {
-    return NetLogQuicStreamFactoryJobParams(&key_.server_id());
-  });
+  net_log_.BeginEvent(NetLogEventType::QUIC_STREAM_FACTORY_JOB,
+                      [&] { return NetLogQuicStreamFactoryJobParams(&key_); });
   // Associate |net_log_| with |net_log|.
   net_log_.AddEventReferencingSource(
       NetLogEventType::QUIC_STREAM_FACTORY_JOB_BOUND_TO_HTTP_STREAM_JOB,
@@ -1180,14 +1180,17 @@
                       session_key.server_id().port())
              .Equals(HostPortPair::FromURL(url)));
   // Enforce session affinity for promised streams.
+  //
+  // TODO(https://crbug.com/1105544): This logic should also handle
+  // NetworkIsolationKey.
   quic::QuicClientPromisedInfo* promised =
       push_promise_index_.GetPromised(url.spec());
   if (promised) {
     QuicChromiumClientSession* session =
         static_cast<QuicChromiumClientSession*>(promised->session());
     DCHECK(session);
-    if (session->server_id().privacy_mode_enabled() ==
-        session_key.server_id().privacy_mode_enabled()) {
+    if (session->quic_session_key().privacy_mode() ==
+        session_key.privacy_mode()) {
       request->SetSession(session->CreateHandle(destination));
       ++num_push_streams_created_;
       return OK;
@@ -1229,10 +1232,7 @@
       QuicChromiumClientSession* session = key_value.second;
       if (destination.Equals(all_sessions_[session].destination()) &&
           session->CanPool(session_key.server_id().host(),
-                           session_key.server_id().privacy_mode_enabled()
-                               ? PRIVACY_MODE_ENABLED
-                               : PRIVACY_MODE_DISABLED,
-                           session_key.socket_tag(),
+                           session_key.privacy_mode(), session_key.socket_tag(),
                            session_key.network_isolation_key(),
                            session_key.disable_secure_dns())) {
         request->SetSession(session->CreateHandle(destination));
@@ -2193,35 +2193,8 @@
     NetworkChangeNotifier::NetworkHandle affected_network) const {
   UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.PlatformNotification",
                             notification, NETWORK_NOTIFICATION_MAX);
-  if (notification == NETWORK_SOON_TO_DISCONNECT ||
-      notification == NETWORK_DISCONNECTED) {
-    // If the disconnected network is not the default network, ignore
-    // stats collections.
-    if (affected_network != default_network_)
-      return;
-  }
-
-  UMA_HISTOGRAM_COUNTS_100(
-      "Net.QuicStreamFactory.NumQuicSessionsAtNetworkChange",
-      all_sessions_.size());
-
-  // Skip degrading session collection if there are less than two sessions.
-  if (all_sessions_.size() < 2)
-    return;
-
-  size_t num_degrading_sessions =
-      connectivity_monitor_.GetNumDegradingSessions();
-  const std::string raw_histogram_name =
-      "Net.QuicStreamFactory.NumDegradingSessions." +
-      QuicPlatformNotificationToString(notification);
-  base::UmaHistogramExactLinear(raw_histogram_name, num_degrading_sessions,
-                                101);
-
-  int percentage = num_degrading_sessions * 100 / all_sessions_.size();
-  const std::string percentage_histogram_name =
-      "Net.QuicStreamFactory.PercentageDegradingSessions." +
-      QuicPlatformNotificationToString(notification);
-  base::UmaHistogramExactLinear(percentage_histogram_name, percentage, 101);
+  connectivity_monitor_.RecordConnectivityStatsToHistograms(
+      QuicPlatformNotificationToString(notification), affected_network);
 }
 
 std::unique_ptr<QuicCryptoClientConfigHandle>
diff --git a/net/tools/quic/quic_simple_server.cc b/net/tools/quic/quic_simple_server.cc
index 01c3e63..0201335 100644
--- a/net/tools/quic/quic_simple_server.cc
+++ b/net/tools/quic/quic_simple_server.cc
@@ -125,7 +125,7 @@
 }
 
 void QuicSimpleServer::Shutdown() {
-  LOG(WARNING) << "QuicSimpleServer is shutting down";
+  DVLOG(1) << "QuicSimpleServer is shutting down";
   // Before we shut down the epoll server, give all active sessions a chance to
   // notify clients that they're closing.
   dispatcher_->Shutdown();
diff --git a/net/url_request/url_request_netlog_params.cc b/net/url_request/url_request_netlog_params.cc
index d6473f2..b38bc5c5 100644
--- a/net/url_request/url_request_netlog_params.cc
+++ b/net/url_request/url_request_netlog_params.cc
@@ -16,22 +16,6 @@
 
 namespace net {
 
-namespace {
-
-std::string PrivacyModeDebugString(PrivacyMode privacy_mode) {
-  switch (privacy_mode) {
-    case PRIVACY_MODE_DISABLED:
-      return "disabled";
-    case PRIVACY_MODE_ENABLED:
-      return "enabled";
-    case PRIVACY_MODE_ENABLED_WITHOUT_CLIENT_CERTS:
-      return "enabled without client certs";
-  }
-  return "";
-}
-
-}  // namespace
-
 base::Value NetLogURLRequestConstructorParams(
     const GURL& url,
     RequestPriority priority,
@@ -56,7 +40,7 @@
   dict.SetStringKey("url", url.possibly_invalid_spec());
   dict.SetStringKey("method", method);
   dict.SetIntKey("load_flags", load_flags);
-  dict.SetStringKey("privacy_mode", PrivacyModeDebugString(privacy_mode));
+  dict.SetStringKey("privacy_mode", PrivacyModeToDebugString(privacy_mode));
   dict.SetStringKey("network_isolation_key",
                     network_isolation_key.ToDebugString());
   dict.SetStringKey("site_for_cookies", site_for_cookies.ToDebugString());
diff --git a/remoting/host/chromeos/clipboard_aura.cc b/remoting/host/chromeos/clipboard_aura.cc
index 7727f7e..29a1f38 100644
--- a/remoting/host/chromeos/clipboard_aura.cc
+++ b/remoting/host/chromeos/clipboard_aura.cc
@@ -85,7 +85,8 @@
   protocol::ClipboardEvent event;
   std::string data;
 
-  clipboard->ReadAsciiText(ui::ClipboardBuffer::kCopyPaste, &data);
+  clipboard->ReadAsciiText(ui::ClipboardBuffer::kCopyPaste,
+                           /* data_dst = */ nullptr, &data);
   event.set_mime_type(kMimeTypeTextUtf8);
   event.set_data(data);
 
diff --git a/remoting/host/chromeos/clipboard_aura_unittest.cc b/remoting/host/chromeos/clipboard_aura_unittest.cc
index 3878819d..88d70de 100644
--- a/remoting/host/chromeos/clipboard_aura_unittest.cc
+++ b/remoting/host/chromeos/clipboard_aura_unittest.cc
@@ -100,7 +100,7 @@
   std::string clipboard_data;
   ui::Clipboard* aura_clipboard = ui::Clipboard::GetForCurrentThread();
   aura_clipboard->ReadAsciiText(ui::ClipboardBuffer::kCopyPaste,
-                                &clipboard_data);
+                                /* data_dst = */ nullptr, &clipboard_data);
 
   EXPECT_EQ(clipboard_data, "Test data.")
       << "InjectClipboardEvent should write to aura clipboard";
diff --git a/testing/buildbot/chromium.ci.json b/testing/buildbot/chromium.ci.json
index 50ffe13..aa3ac0b 100644
--- a/testing/buildbot/chromium.ci.json
+++ b/testing/buildbot/chromium.ci.json
@@ -249770,6 +249770,94 @@
       "empty_main"
     ]
   },
+  "linux-lacros-tester-rel": {
+    "additional_compile_targets": [
+      "chrome",
+      "chrome_sandbox",
+      "linux_symbols",
+      "symupload"
+    ],
+    "gtest_tests": [
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04",
+              "pool": "chrome.tests",
+              "ssd": "0"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "dbus_unittests",
+        "test_id_prefix": "ninja://dbus:dbus_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04",
+              "pool": "chrome.tests",
+              "ssd": "0"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "mojo_core_unittests",
+        "test_id_prefix": "ninja://mojo/core:mojo_core_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04",
+              "pool": "chrome.tests",
+              "ssd": "0"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "nacl_helper_nonsfi_unittests",
+        "test_id_prefix": "ninja://components/nacl/loader:nacl_helper_nonsfi_unittests/"
+      }
+    ],
+    "isolated_scripts": [
+      {
+        "isolate_name": "chrome_sizes",
+        "merge": {
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "chrome_sizes",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04",
+              "pool": "chrome.tests",
+              "ssd": "0"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:chrome_sizes/"
+      }
+    ]
+  },
   "linux-official": {
     "additional_compile_targets": [
       "all"
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index 9be915c..027d0033 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -56777,6 +56777,94 @@
       }
     ]
   },
+  "linux-lacros-tester-rel": {
+    "additional_compile_targets": [
+      "chrome",
+      "chrome_sandbox",
+      "linux_symbols",
+      "symupload"
+    ],
+    "gtest_tests": [
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04",
+              "pool": "chrome.tests",
+              "ssd": "0"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "dbus_unittests",
+        "test_id_prefix": "ninja://dbus:dbus_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04",
+              "pool": "chrome.tests",
+              "ssd": "0"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "mojo_core_unittests",
+        "test_id_prefix": "ninja://mojo/core:mojo_core_unittests/"
+      },
+      {
+        "merge": {
+          "args": [],
+          "script": "//testing/merge_scripts/standard_gtest_merge.py"
+        },
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04",
+              "pool": "chrome.tests",
+              "ssd": "0"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test": "nacl_helper_nonsfi_unittests",
+        "test_id_prefix": "ninja://components/nacl/loader:nacl_helper_nonsfi_unittests/"
+      }
+    ],
+    "isolated_scripts": [
+      {
+        "isolate_name": "chrome_sizes",
+        "merge": {
+          "script": "//tools/perf/process_perf_results.py"
+        },
+        "name": "chrome_sizes",
+        "swarming": {
+          "can_use_on_swarming_builders": true,
+          "dimension_sets": [
+            {
+              "os": "Ubuntu-16.04",
+              "pool": "chrome.tests",
+              "ssd": "0"
+            }
+          ],
+          "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
+        },
+        "test_id_prefix": "ninja://chrome/test:chrome_sizes/"
+      }
+    ]
+  },
   "linux-perfetto-rel": {
     "additional_compile_targets": [
       "chrome"
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl
index dcb7a92..f7eb361 100644
--- a/testing/buildbot/gn_isolate_map.pyl
+++ b/testing/buildbot/gn_isolate_map.pyl
@@ -17,6 +17,9 @@
 # much always the same as the Ninja target name, since GYP target names are not
 # hierarchical).
 #
+# TODO(crbug.com/816629): Remove the need for this file altogether :). Also,
+# see below.
+#
 # The "label" field specifies the matching GN label for the given ninja
 # target.
 #
@@ -48,6 +51,17 @@
 #  "unknown"
 #  : (the default), which indicates that we don't know what the command line
 #    needs to be (this is a fatal error).
+
+# TODO(crbug.com/816629): You may also set the type field to "wrapped_" +
+# one of the above values; doing so indicates that the target conforms to
+# the test wrapper API: for a given label //X:Y and build directory Z,
+# there will be either a "Z/bin/run_Y" bash script (on Unix systems) or a
+# "Z/bin/run_Y.bat" batch script (on Windows) that can be invoked directly
+# to run the target in a swarming task, and "Z/Y.runtime_deps" file that
+# contains the list of files and directories needed to run the task, in
+# the format that GN uses with write_runtime_deps: a newline-separated list
+# of files and directories relative to Z. Ultimately every target will
+# be converted to this format, and this entire file will be deleted.
 #
 # The optional "executable" field can be used to override the name
 # of the binary to run. If the field is not specified, the binary
@@ -1717,7 +1731,7 @@
   },
   "url_unittests": {
     "label": "//url:url_unittests",
-    "type": "console_test_launcher",
+    "type": "wrapped_console_test_launcher",
   },
   "usage_time_limit_unittests": {
     "label": "//chrome/test:usage_time_limit_unittests",
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl
index 92c70de..ae642cdd 100644
--- a/testing/buildbot/test_suites.pyl
+++ b/testing/buildbot/test_suites.pyl
@@ -5386,6 +5386,12 @@
       'storage_service_gtests',
     ],
 
+    # TODO(crbug.com/1104291) Make this suite the same as
+    # 'linux_chromeos_gtests' and delete this suite.
+    'linux_lacros_chromeos_gtests': [
+      'chromium_gtests_for_linux_and_chromeos_only',
+    ],
+
     'linux_viz_gtests': [
       'gpu_fyi_vulkan_swiftshader_gtests',
       'skia_renderer_fyi_gtests',
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 573a958..c84590f8 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -2239,6 +2239,29 @@
           'gtest_tests': 'fieldtrial_browser_tests',
         },
       },
+      'linux-lacros-tester-rel': {
+        'additional_compile_targets': [
+          'chrome',
+          'chrome_sandbox',
+          'linux_symbols',
+          'symupload'
+        ],
+        'mixins': [
+          'chrome-swarming-pool',
+          'linux-xenial',
+        ],
+        'swarming': {
+          'dimension_sets': [
+            {
+              'ssd': '0',
+            },
+          ],
+        },
+        'test_suites': {
+          'gtest_tests': 'linux_lacros_chromeos_gtests',
+          'isolated_scripts': 'chrome_sizes',
+        },
+      },
       'linux-perfetto-rel': {
         'additional_compile_targets': [ 'chrome' ],
         'mixins': [
diff --git a/testing/test.gni b/testing/test.gni
index ece76f1..984e2a3 100644
--- a/testing/test.gni
+++ b/testing/test.gni
@@ -29,6 +29,11 @@
   import("//build/config/ios/rules.gni")
 }
 
+if ((is_linux && !is_chromeos) || is_mac || is_win) {
+  import("//build/config/sanitizers/sanitizers.gni")
+  import("//build/util/generate_wrapper.gni")
+}
+
 # Define a test as an executable (or apk on Android) with the "testonly" flag
 # set.
 # Variable:
@@ -352,7 +357,7 @@
       data += [ _runtime_deps_file ]
       deps += [ ":$_gen_runner_target" ]
     }
-  } else {
+  } else if (is_chromeos && cros_board == "") {
     executable(target_name) {
       forward_variables_from(invoker, "*")
       if (!defined(deps)) {
@@ -371,6 +376,75 @@
         "//build/win:default_exe_manifest",
       ]
     }
+  } else {
+    if ((is_linux && !is_chromeos) || is_mac || is_win) {
+      _runtime_deps_file = "$root_out_dir/${target_name}.runtime_deps"
+      _executable = target_name
+      _gen_runner_target = "${target_name}__runner"
+
+      if (is_linux && defined(invoker.use_xvfb)) {
+        _use_xvfb = invoker.use_xvfb
+      } else {
+        _use_xvfb = false
+      }
+
+      generate_wrapper(_gen_runner_target) {
+        testonly = true
+        wrapper_script = "$root_build_dir/bin/run_" + _executable
+
+        if (_use_xvfb) {
+          executable = "//testing/xvfb.py"
+        } else {
+          executable = "//testing/test_env.py"
+        }
+
+        executable_args = [
+          "@WrappedPath(./${_executable})",
+          "--test-launcher-bot-mode",
+        ]
+        if (is_asan) {
+          executable_args += [ "--asan=true" ]
+        }
+        if (is_msan) {
+          executable_args += [ "--msan=true" ]
+        }
+        if (is_tsan) {
+          executable_args += [ "--tsan=true" ]
+        }
+        if (use_cfi_diag) {
+          executable_args += [ "--cfi-diag=true" ]
+        }
+
+        data = [
+          "//testing/test_env.py",
+          "//.vpython",
+        ]
+      }
+    }
+
+    executable(target_name) {
+      forward_variables_from(invoker, "*")
+      if (!defined(deps)) {
+        deps = []
+      }
+
+      if (is_win) {
+        # Initializing CFG data during process creation is a significant
+        # bottleneck for large test binaries, and CFG is not needed for tests,
+        # so disable it. See https://crbug.com/950923 for details.
+        configs -= [ "//build/config/win:cfi_linker" ]
+      }
+      testonly = true
+      deps += [
+        # Give tests the default manifest on Windows (a no-op elsewhere).
+        "//build/win:default_exe_manifest",
+      ]
+
+      if (is_linux || is_mac || is_win) {
+        write_runtime_deps = _runtime_deps_file
+        deps += [ ":$_gen_runner_target" ]
+      }
+    }
   }
 }
 
diff --git a/third_party/blink/common/manifest/manifest_icon_selector_unittest.cc b/third_party/blink/common/manifest/manifest_icon_selector_unittest.cc
index ede60a3..390c812 100644
--- a/third_party/blink/common/manifest/manifest_icon_selector_unittest.cc
+++ b/third_party/blink/common/manifest/manifest_icon_selector_unittest.cc
@@ -140,23 +140,24 @@
   sizes_144.push_back(gfx::Size(width_to_height_ratio() * 144, 144));
 
   std::vector<blink::Manifest::ImageResource> icons;
-  icons.push_back(
-      CreateIcon("http://foo.com/icon_48.png", "", sizes_48, Purpose::BADGE));
+  icons.push_back(CreateIcon("http://foo.com/icon_48.png", "", sizes_48,
+                             Purpose::MONOCHROME));
   icons.push_back(
       CreateIcon("http://foo.com/icon_96.png", "", sizes_96, Purpose::ANY));
   icons.push_back(
       CreateIcon("http://foo.com/icon_144.png", "", sizes_144, Purpose::ANY));
 
-  GURL url = FindBestMatchingIcon(icons, 48, kMinimumIconSize, Purpose::BADGE);
+  GURL url =
+      FindBestMatchingIcon(icons, 48, kMinimumIconSize, Purpose::MONOCHROME);
   EXPECT_EQ("http://foo.com/icon_48.png", url.spec());
 
   url = FindBestMatchingIcon(icons, 48, kMinimumIconSize, Purpose::ANY);
   EXPECT_EQ("http://foo.com/icon_96.png", url.spec());
 
-  url = FindBestMatchingIcon(icons, 96, kMinimumIconSize, Purpose::BADGE);
+  url = FindBestMatchingIcon(icons, 96, kMinimumIconSize, Purpose::MONOCHROME);
   EXPECT_EQ("http://foo.com/icon_48.png", url.spec());
 
-  url = FindBestMatchingIcon(icons, 96, 96, Purpose::BADGE);
+  url = FindBestMatchingIcon(icons, 96, 96, Purpose::MONOCHROME);
   EXPECT_TRUE(url.is_empty());
 
   url = FindBestMatchingIcon(icons, 144, kMinimumIconSize, Purpose::ANY);
diff --git a/third_party/blink/public/common/manifest/manifest.h b/third_party/blink/public/common/manifest/manifest.h
index 2de13de..bac0690 100644
--- a/third_party/blink/public/common/manifest/manifest.h
+++ b/third_party/blink/public/common/manifest/manifest.h
@@ -31,7 +31,7 @@
   struct BLINK_COMMON_EXPORT ImageResource {
     enum class Purpose {
       ANY = 0,
-      BADGE,
+      MONOCHROME,
       MASKABLE,
       IMAGE_RESOURCE_PURPOSE_LAST = MASKABLE,
     };
diff --git a/third_party/blink/public/common/manifest/manifest_mojom_traits.h b/third_party/blink/public/common/manifest/manifest_mojom_traits.h
index 0ca19c2..8b10200a 100644
--- a/third_party/blink/public/common/manifest/manifest_mojom_traits.h
+++ b/third_party/blink/public/common/manifest/manifest_mojom_traits.h
@@ -328,8 +328,8 @@
     switch (purpose) {
       case ::blink::Manifest::ImageResource::Purpose::ANY:
         return blink::mojom::ManifestImageResource_Purpose::ANY;
-      case ::blink::Manifest::ImageResource::Purpose::BADGE:
-        return blink::mojom::ManifestImageResource_Purpose::BADGE;
+      case ::blink::Manifest::ImageResource::Purpose::MONOCHROME:
+        return blink::mojom::ManifestImageResource_Purpose::MONOCHROME;
       case ::blink::Manifest::ImageResource::Purpose::MASKABLE:
         return blink::mojom::ManifestImageResource_Purpose::MASKABLE;
     }
@@ -342,8 +342,8 @@
       case blink::mojom::ManifestImageResource_Purpose::ANY:
         *out = ::blink::Manifest::ImageResource::Purpose::ANY;
         return true;
-      case blink::mojom::ManifestImageResource_Purpose::BADGE:
-        *out = ::blink::Manifest::ImageResource::Purpose::BADGE;
+      case blink::mojom::ManifestImageResource_Purpose::MONOCHROME:
+        *out = ::blink::Manifest::ImageResource::Purpose::MONOCHROME;
         return true;
       case blink::mojom::ManifestImageResource_Purpose::MASKABLE:
         *out = ::blink::Manifest::ImageResource::Purpose::MASKABLE;
diff --git a/third_party/blink/public/mojom/manifest/manifest.mojom b/third_party/blink/public/mojom/manifest/manifest.mojom
index a14fa7e..859da93 100644
--- a/third_party/blink/public/mojom/manifest/manifest.mojom
+++ b/third_party/blink/public/mojom/manifest/manifest.mojom
@@ -87,7 +87,7 @@
 struct ManifestImageResource {
   enum Purpose {
     ANY = 0,
-    BADGE,
+    MONOCHROME,
     MASKABLE,
   };
 
diff --git a/third_party/blink/public/mojom/web_feature/web_feature.mojom b/third_party/blink/public/mojom/web_feature/web_feature.mojom
index 8b4e7043..b182791 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -2681,6 +2681,7 @@
   kRTCConstraintEnableRtpDataChannelsFalse = 3345,
   kNativeFileSystemDragAndDrop = 3346,
   kRTCAdaptivePtime = 3347,
+  kHTMLMetaElementReferrerPolicyMultipleTokensAffectingRequest = 3348,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/renderer/bindings/core/v8/script_function.cc b/third_party/blink/renderer/bindings/core/v8/script_function.cc
index 2cb44fb..5d84c12 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_function.cc
+++ b/third_party/blink/renderer/bindings/core/v8/script_function.cc
@@ -14,7 +14,7 @@
   CustomWrappableAdapter::Trace(visitor);
 }
 
-v8::Local<v8::Function> ScriptFunction::BindToV8Function() {
+v8::Local<v8::Function> ScriptFunction::BindToV8Function(int length) {
 #if DCHECK_IS_ON()
   DCHECK(!bind_to_v8_function_already_called_);
   bind_to_v8_function_already_called_ = true;
@@ -24,7 +24,7 @@
   // The wrapper is held alive by the CallHandlerInfo internally in V8 as long
   // as the function is alive.
   return v8::Function::New(script_state_->GetContext(), CallCallback, wrapper,
-                           0, v8::ConstructorBehavior::kThrow)
+                           length, v8::ConstructorBehavior::kThrow)
       .ToLocalChecked();
 }
 
diff --git a/third_party/blink/renderer/bindings/core/v8/script_function.h b/third_party/blink/renderer/bindings/core/v8/script_function.h
index 91b186a..2e80f0b 100644
--- a/third_party/blink/renderer/bindings/core/v8/script_function.h
+++ b/third_party/blink/renderer/bindings/core/v8/script_function.h
@@ -64,7 +64,9 @@
 
   ScriptState* GetScriptState() const { return script_state_; }
 
-  v8::Local<v8::Function> BindToV8Function();
+  // It is not usually necessary to set |length| unless the function is exposed
+  // to JavaScript.
+  v8::Local<v8::Function> BindToV8Function(int length = 0);
 
  private:
   // Subclasses should implement one of Call() or CallRaw(). Most will implement
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
index 6e7a5f5..cf18f6db 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
@@ -1517,6 +1517,35 @@
             return T("bindings::V8SetReturnValue(${info}, ${return_value}, "
                      "${isolate}, ${blink_receiver});")
 
+    # [CheckSecurity=ReturnValue]
+    #
+    # The returned object must be wrapped in its own realm instead of the
+    # receiver object's relevant realm or the current realm.
+    #
+    # [CheckSecurity=ReturnValue] is used only for 'contentDocument' attribute
+    # and 'getSVGDocument' operation of HTML{IFrame,Frame,Object,Embed}Element
+    # interfaces, and Window.frameElement attribute, so far.
+    #
+    # All the interfaces above except for Window support 'contentWindow'
+    # attribute and that's the global object of the creation context of the
+    # returned V8 wrapper.  Window.frameElement is implemented with [Custom]
+    # for now and there is no need to support it.
+    #
+    # Note that the global object has its own context and there is no need to
+    # pass the creation context to ToV8.
+    if (cg_context.member_like.extended_attributes.value_of("CheckSecurity") ==
+            "ReturnValue"):
+        return T("""\
+// [CheckSecurity=ReturnValue]
+bindings::V8SetReturnValue(
+    ${info},
+    ToV8(${return_value},
+         ToV8(${blink_receiver}->contentWindow(),
+              v8::Local<v8::Object>(),
+              ${isolate}).As<v8::Object>(),
+         ${isolate}));\
+""")
+
     return_type = return_type.unwrap(typedef=True)
     return_type_body = return_type.unwrap()
 
diff --git a/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc b/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc
index 18dd0fc..ab70093 100644
--- a/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc
+++ b/third_party/blink/renderer/core/css/parser/css_property_parser_test.cc
@@ -386,12 +386,12 @@
 
 TEST(CSSPropertyParserTest, PaintUseCount) {
   auto dummy_page_holder = std::make_unique<DummyPageHolder>(IntSize(800, 600));
+  dummy_page_holder->GetFrame().Loader().CommitNavigation(
+      WebNavigationParams::CreateWithHTMLBuffer(SharedBuffer::Create(),
+                                                KURL("https://example.com")),
+      nullptr /* extra_data */);
   Document& document = dummy_page_holder->GetDocument();
   Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
-  dummy_page_holder->GetFrame()
-      .DomWindow()
-      ->GetSecurityContext()
-      .SetSecureContextModeForTesting(SecureContextMode::kSecureContext);
   WebFeature feature = WebFeature::kCSSPaintFunction;
   EXPECT_FALSE(document.IsUseCounted(feature));
   document.documentElement()->setInnerHTML(
diff --git a/third_party/blink/renderer/core/execution_context/execution_context.cc b/third_party/blink/renderer/core/execution_context/execution_context.cc
index 7a0cb6c2..cbc2941 100644
--- a/third_party/blink/renderer/core/execution_context/execution_context.cc
+++ b/third_party/blink/renderer/core/execution_context/execution_context.cc
@@ -56,11 +56,9 @@
 
 namespace blink {
 
-ExecutionContext::ExecutionContext(v8::Isolate* isolate,
-                                   Agent* agent,
-                                   SecurityContext::SecurityContextType type)
+ExecutionContext::ExecutionContext(v8::Isolate* isolate, Agent* agent)
     : isolate_(isolate),
-      security_context_(type),
+      security_context_(this),
       agent_(agent),
       circular_sequential_id_(0),
       in_dispatch_error_event_(false),
@@ -324,8 +322,10 @@
   return Url().StrippedForUseAsReferrer();
 }
 
-void ExecutionContext::ParseAndSetReferrerPolicy(const String& policies,
-                                                 bool support_legacy_keywords) {
+void ExecutionContext::ParseAndSetReferrerPolicy(
+    const String& policies,
+    bool support_legacy_keywords,
+    bool from_meta_tag_with_list_of_policies) {
   network::mojom::ReferrerPolicy referrer_policy;
 
   if (!SecurityPolicy::ReferrerPolicyFromHeaderValue(
@@ -349,17 +349,21 @@
     return;
   }
 
-  SetReferrerPolicy(referrer_policy);
+  SetReferrerPolicy(referrer_policy, from_meta_tag_with_list_of_policies);
 }
 
 void ExecutionContext::SetReferrerPolicy(
-    network::mojom::ReferrerPolicy referrer_policy) {
+    network::mojom::ReferrerPolicy referrer_policy,
+    bool from_meta_tag_with_list_of_policies) {
   // When a referrer policy has already been set, the latest value takes
   // precedence.
   UseCounter::Count(this, WebFeature::kSetReferrerPolicy);
   if (referrer_policy_ != network::mojom::ReferrerPolicy::kDefault)
     UseCounter::Count(this, WebFeature::kResetReferrerPolicy);
 
+  if (!from_meta_tag_with_list_of_policies)
+    referrer_policy_but_for_meta_tags_with_lists_of_policies_ = referrer_policy;
+
   referrer_policy_ = referrer_policy;
 }
 
diff --git a/third_party/blink/renderer/core/execution_context/execution_context.h b/third_party/blink/renderer/core/execution_context/execution_context.h
index 467f1a65..553263b 100644
--- a/third_party/blink/renderer/core/execution_context/execution_context.h
+++ b/third_party/blink/renderer/core/execution_context/execution_context.h
@@ -263,6 +263,8 @@
   }
   bool IsSecureContext(String& error_message) const;
 
+  virtual bool HasInsecureContextInAncestors() { return false; }
+
   // Returns a referrer to be used in the "Determine request's Referrer"
   // algorithm defined in the Referrer Policy spec.
   // https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer
@@ -276,12 +278,25 @@
   // If |supportLegacyKeywords| is true, then the legacy keywords
   // "never", "default", "always", and "origin-when-crossorigin" are
   // parsed as valid policies.
-  void ParseAndSetReferrerPolicy(const String& policies,
-                                 bool support_legacy_keywords = false);
-  void SetReferrerPolicy(network::mojom::ReferrerPolicy);
+  //
+  // If |from_meta_tag_with_list_of_policies| is *false*, also updates
+  // |referrer_policy_but_for_meta_tags_with_lists_of_policies_|, which
+  // maintains a counterfactual to determine what the policy would look like if
+  // we started ignoring <meta name=referrer content=policy1,policy2,...> tags
+  // in order to align with the HTML standard (crbug.com/1092930).
+  void ParseAndSetReferrerPolicy(
+      const String& policies,
+      bool support_legacy_keywords = false,
+      bool from_meta_tag_with_list_of_policies = false);
+  void SetReferrerPolicy(network::mojom::ReferrerPolicy,
+                         bool from_meta_tag_with_list_of_policies = false);
   virtual network::mojom::ReferrerPolicy GetReferrerPolicy() const {
     return referrer_policy_;
   }
+  virtual network::mojom::blink::ReferrerPolicy
+  ReferrerPolicyButForMetaTagsWithListsOfPolicies() const {
+    return referrer_policy_but_for_meta_tags_with_lists_of_policies_;
+  }
 
   virtual CoreProbeSink* GetProbeSink() { return nullptr; }
 
@@ -366,9 +381,7 @@
   virtual ukm::SourceId UkmSourceID() const { return ukm::kInvalidSourceId; }
 
  protected:
-  explicit ExecutionContext(v8::Isolate* isolate,
-                            Agent*,
-                            SecurityContext::SecurityContextType);
+  explicit ExecutionContext(v8::Isolate* isolate, Agent*);
   ~ExecutionContext() override;
 
  private:
@@ -417,6 +430,14 @@
 
   network::mojom::ReferrerPolicy referrer_policy_;
 
+  // This is the same value as |referrer_policy_| except that it ignores
+  // referrer policies set as the result of parsing <meta name=referrer> tags
+  // whose values are comma-separated lists of policies. Its purpose is to allow
+  // evaluating the impact of switching to a behavior of no longer supporting
+  // these lists (crbug.com/1092930).
+  network::mojom::blink::ReferrerPolicy
+      referrer_policy_but_for_meta_tags_with_lists_of_policies_;
+
   network::mojom::blink::IPAddressSpace address_space_;
 
   // Tracks which feature policies have already been parsed, so as not to count
diff --git a/third_party/blink/renderer/core/execution_context/remote_security_context.cc b/third_party/blink/renderer/core/execution_context/remote_security_context.cc
index 879e5df..9e8ccb00 100644
--- a/third_party/blink/renderer/core/execution_context/remote_security_context.cc
+++ b/third_party/blink/renderer/core/execution_context/remote_security_context.cc
@@ -12,7 +12,7 @@
 
 namespace blink {
 
-RemoteSecurityContext::RemoteSecurityContext() : SecurityContext(kRemoteFrame) {
+RemoteSecurityContext::RemoteSecurityContext() : SecurityContext(nullptr) {
   // RemoteSecurityContext's origin is expected to stay uninitialized until
   // we set it using replicated origin data from the browser process.
   DCHECK(!GetSecurityOrigin());
diff --git a/third_party/blink/renderer/core/execution_context/security_context.cc b/third_party/blink/renderer/core/execution_context/security_context.cc
index ebb066f..6e38ed8 100644
--- a/third_party/blink/renderer/core/execution_context/security_context.cc
+++ b/third_party/blink/renderer/core/execution_context/security_context.cc
@@ -57,34 +57,19 @@
   return serialized;
 }
 
-SecurityContext::SecurityContext(SecurityContextType context_type)
-    : insecure_request_policy_(
-          mojom::blink::InsecureRequestPolicy::kLeaveInsecureRequestsAlone),
-      context_type_for_asserts_(context_type) {}
+SecurityContext::SecurityContext(ExecutionContext* execution_context)
+    : execution_context_(execution_context),
+      insecure_request_policy_(
+          mojom::blink::InsecureRequestPolicy::kLeaveInsecureRequestsAlone) {}
 
 SecurityContext::~SecurityContext() = default;
 
 void SecurityContext::Initialize(const SecurityContextInit& init) {
-  if (security_origin_) {
-    // If |security_origin_| is non-null, this is a re-initialization. This
-    // should only happen for kWindow, when the window of an initial empty
-    // document is reused.
-    SECURITY_CHECK(context_type_for_asserts_ == kWindow);
-    // Re-initialization should only happen when origins can access each other.
-    SECURITY_CHECK(security_origin_->CanAccess(init.GetSecurityOrigin().get()));
-    // Under normal circumstances, because the origins can access each other,
-    // the SecureContextMode can't change. However, when an an origin is granted
-    // universal access, it can access any other origin, including ones that
-    // result in a different SecureContextMode.
-    SECURITY_CHECK(secure_context_mode_ == init.GetSecureContextMode() ||
-                   security_origin_->IsGrantedUniversalAccess());
-  }
-  security_origin_ = init.GetSecurityOrigin();
-  secure_context_mode_ = init.GetSecureContextMode();
   origin_trial_context_ = init.GetOriginTrialContext();
 }
 
 void SecurityContext::Trace(Visitor* visitor) const {
+  visitor->Trace(execution_context_);
   visitor->Trace(content_security_policy_);
   visitor->Trace(origin_trial_context_);
 }
@@ -104,14 +89,38 @@
   // that transition. See https://crbug.com/1068008. It would be great if we
   // could get rid of this exemption.
   bool is_worker_transition_to_opaque =
-      context_type_for_asserts_ == kWorker &&
+      execution_context_ &&
+      execution_context_->IsWorkerOrWorkletGlobalScope() &&
       IsSandboxed(network::mojom::blink::WebSandboxFlags::kOrigin) &&
       security_origin->IsOpaque() &&
       security_origin->GetOriginOrPrecursorOriginIfOpaque() == security_origin_;
-  CHECK(context_type_for_asserts_ == kRemoteFrame || !security_origin_ ||
+  CHECK(!execution_context_ || !security_origin_ ||
         security_origin_->CanAccess(security_origin.get()) ||
         is_worker_transition_to_opaque);
   security_origin_ = std::move(security_origin);
+
+  if (!security_origin_->IsPotentiallyTrustworthy()) {
+    secure_context_mode_ = SecureContextMode::kInsecureContext;
+  } else if (SchemeRegistry::SchemeShouldBypassSecureContextCheck(
+                 security_origin_->Protocol())) {
+    secure_context_mode_ = SecureContextMode::kSecureContext;
+  } else if (execution_context_) {
+    secure_context_mode_ = execution_context_->HasInsecureContextInAncestors()
+                               ? SecureContextMode::kInsecureContext
+                               : SecureContextMode::kSecureContext;
+  }
+
+  bool is_secure = secure_context_mode_ == SecureContextMode::kSecureContext;
+  if (sandbox_flags_ != network::mojom::blink::WebSandboxFlags::kNone) {
+    UseCounter::Count(
+        execution_context_,
+        is_secure ? WebFeature::kSecureContextCheckForSandboxedOriginPassed
+                  : WebFeature::kSecureContextCheckForSandboxedOriginFailed);
+  }
+
+  UseCounter::Count(execution_context_,
+                    is_secure ? WebFeature::kSecureContextCheckPassed
+                              : WebFeature::kSecureContextCheckFailed);
 }
 
 void SecurityContext::SetSecurityOriginForTesting(
diff --git a/third_party/blink/renderer/core/execution_context/security_context.h b/third_party/blink/renderer/core/execution_context/security_context.h
index 3413461..29c3feb 100644
--- a/third_party/blink/renderer/core/execution_context/security_context.h
+++ b/third_party/blink/renderer/core/execution_context/security_context.h
@@ -47,6 +47,7 @@
 
 class ContentSecurityPolicy;
 class DocumentPolicy;
+class ExecutionContext;
 class FeaturePolicy;
 class PolicyValue;
 class OriginTrialContext;
@@ -74,10 +75,7 @@
   DISALLOW_NEW();
 
  public:
-  // Used only for safety CHECKs.
-  enum SecurityContextType { kWindow, kWorker, kRemoteFrame };
-
-  explicit SecurityContext(SecurityContextType context_type);
+  explicit SecurityContext(ExecutionContext*);
   virtual ~SecurityContext();
 
   void Initialize(const SecurityContextInit&);
@@ -175,15 +173,9 @@
   }
 
   SecureContextMode GetSecureContextMode() const {
-    // secure_context_mode_ is not initialized for RemoteSecurityContexts.
-    DCHECK_NE(context_type_for_asserts_, kRemoteFrame);
     return secure_context_mode_;
   }
 
-  void SetSecureContextModeForTesting(SecureContextMode mode) {
-    secure_context_mode_ = mode;
-  }
-
  protected:
   network::mojom::blink::WebSandboxFlags sandbox_flags_;
   scoped_refptr<SecurityOrigin> security_origin_;
@@ -193,12 +185,13 @@
   std::unique_ptr<DocumentPolicy> report_only_document_policy_;
 
  private:
+  // execution_context_ will be nullptr if this is a RemoteSecurityContext.
+  Member<ExecutionContext> execution_context_;
   Member<ContentSecurityPolicy> content_security_policy_;
   mojom::blink::InsecureRequestPolicy insecure_request_policy_;
   InsecureNavigationsSet insecure_navigations_to_upgrade_;
   bool require_safe_types_ = false;
-  const SecurityContextType context_type_for_asserts_;
-  SecureContextMode secure_context_mode_;
+  SecureContextMode secure_context_mode_ = SecureContextMode::kInsecureContext;
   Member<OriginTrialContext> origin_trial_context_;
   DISALLOW_COPY_AND_ASSIGN(SecurityContext);
 };
diff --git a/third_party/blink/renderer/core/execution_context/security_context_init.cc b/third_party/blink/renderer/core/execution_context/security_context_init.cc
index 8f7d951c..3dbdca5 100644
--- a/third_party/blink/renderer/core/execution_context/security_context_init.cc
+++ b/third_party/blink/renderer/core/execution_context/security_context_init.cc
@@ -71,24 +71,13 @@
 
 }  // namespace
 
-// This constructor is used for non-Document contexts (i.e., workers and tests).
-// This does a simpler check than Documents to set secure_context_mode_. This
-// is only sufficient until there are APIs that are available in workers or
-// worklets that require a privileged context test that checks ancestors.
-SecurityContextInit::SecurityContextInit(scoped_refptr<SecurityOrigin> origin,
-                                         OriginTrialContext* origin_trials)
-    : security_origin_(std::move(origin)),
-      origin_trials_(origin_trials),
-      secure_context_mode_(security_origin_ &&
-                                   security_origin_->IsPotentiallyTrustworthy()
-                               ? SecureContextMode::kSecureContext
-                               : SecureContextMode::kInsecureContext) {}
+SecurityContextInit::SecurityContextInit(OriginTrialContext* origin_trials)
+    : origin_trials_(origin_trials) {}
 
 // A helper class that allows the security context be initialized in the
 // process of constructing the document.
-SecurityContextInit::SecurityContextInit(ExecutionContext* context,
-                                         scoped_refptr<SecurityOrigin> origin)
-    : execution_context_(context), security_origin_(std::move(origin)) {}
+SecurityContextInit::SecurityContextInit(ExecutionContext* context)
+    : execution_context_(context) {}
 
 void SecurityContextInit::CountFeaturePolicyUsage(
     mojom::blink::WebFeature feature) {
@@ -163,8 +152,9 @@
   // inherited policies. https://crbug.com/898688.
   if (frame->InViewSourceMode()) {
     execution_context_->GetSecurityContext().SetFeaturePolicy(
-        FeaturePolicy::CreateFromParentPolicy(nullptr, {},
-                                              security_origin_->ToUrlOrigin()));
+        FeaturePolicy::CreateFromParentPolicy(
+            nullptr, {},
+            execution_context_->GetSecurityOrigin()->ToUrlOrigin()));
     return;
   }
 
@@ -191,13 +181,14 @@
     UseCounter::Count(execution_context_, WebFeature::kFeaturePolicyHeader);
 
   feature_policy_header_ = FeaturePolicyParser::ParseHeader(
-      feature_policy_header, permissions_policy_header, security_origin_,
-      feature_policy_logger, this);
+      feature_policy_header, permissions_policy_header,
+      execution_context_->GetSecurityOrigin(), feature_policy_logger, this);
 
   ParsedFeaturePolicy report_only_feature_policy_header =
       FeaturePolicyParser::ParseHeader(
           response.HttpHeaderField(http_names::kFeaturePolicyReportOnly),
-          report_only_permissions_policy_header, security_origin_,
+          report_only_permissions_policy_header,
+          execution_context_->GetSecurityOrigin(),
           report_only_feature_policy_logger, this);
 
   if (!report_only_feature_policy_header.empty()) {
@@ -260,10 +251,11 @@
             : nullptr;
     feature_policy = FeaturePolicy::CreateFromParentPolicy(
         parent_feature_policy, container_policy,
-        security_origin_->ToUrlOrigin());
+        execution_context_->GetSecurityOrigin()->ToUrlOrigin());
   } else {
     feature_policy = FeaturePolicy::CreateWithOpenerPolicy(
-        frame->OpenerFeatureState(), security_origin_->ToUrlOrigin());
+        frame->OpenerFeatureState(),
+        execution_context_->GetSecurityOrigin()->ToUrlOrigin());
   }
   feature_policy->SetHeaderPolicy(feature_policy_header_);
   execution_context_->GetSecurityContext().SetFeaturePolicy(
@@ -279,54 +271,17 @@
   // enforced feature policy.
   if (!report_only_feature_policy_header.empty()) {
     std::unique_ptr<FeaturePolicy> report_only_policy =
-        FeaturePolicy::CreateFromParentPolicy(nullptr /* parent_policy */,
-                                              {} /* container_policy */,
-                                              security_origin_->ToUrlOrigin());
+        FeaturePolicy::CreateFromParentPolicy(
+            nullptr /* parent_policy */, {} /* container_policy */,
+            execution_context_->GetSecurityOrigin()->ToUrlOrigin());
     report_only_policy->SetHeaderPolicy(report_only_feature_policy_header);
     execution_context_->GetSecurityContext().SetReportOnlyFeaturePolicy(
         std::move(report_only_policy));
   }
 }
 
-void SecurityContextInit::CalculateSecureContextMode(LocalFrame* frame) {
-  if (!security_origin_->IsPotentiallyTrustworthy()) {
-    secure_context_mode_ = SecureContextMode::kInsecureContext;
-  } else if (SchemeRegistry::SchemeShouldBypassSecureContextCheck(
-                 security_origin_->Protocol())) {
-    secure_context_mode_ = SecureContextMode::kSecureContext;
-  } else if (frame) {
-    Frame* parent = frame->Tree().Parent();
-    while (parent) {
-      if (!parent->GetSecurityContext()
-               ->GetSecurityOrigin()
-               ->IsPotentiallyTrustworthy()) {
-        secure_context_mode_ = SecureContextMode::kInsecureContext;
-        break;
-      }
-      parent = parent->Tree().Parent();
-    }
-    if (!secure_context_mode_.has_value())
-      secure_context_mode_ = SecureContextMode::kSecureContext;
-  } else {
-    secure_context_mode_ = SecureContextMode::kInsecureContext;
-  }
-  bool is_secure = secure_context_mode_ == SecureContextMode::kSecureContext;
-  if (execution_context_->GetSandboxFlags() !=
-      network::mojom::blink::WebSandboxFlags::kNone) {
-    UseCounter::Count(
-        execution_context_,
-        is_secure ? WebFeature::kSecureContextCheckForSandboxedOriginPassed
-                  : WebFeature::kSecureContextCheckForSandboxedOriginFailed);
-  }
-
-  UseCounter::Count(execution_context_,
-                    is_secure ? WebFeature::kSecureContextCheckPassed
-                              : WebFeature::kSecureContextCheckFailed);
-}
-
 void SecurityContextInit::InitializeOriginTrials(
     const String& origin_trials_header) {
-  DCHECK(secure_context_mode_.has_value());
   origin_trials_ = MakeGarbageCollected<OriginTrialContext>();
   if (origin_trials_header.IsEmpty())
     return;
@@ -334,9 +289,9 @@
       OriginTrialContext::ParseHeaderValue(origin_trials_header));
   if (!tokens)
     return;
-  origin_trials_->AddTokens(
-      *tokens, security_origin_.get(),
-      secure_context_mode_ == SecureContextMode::kSecureContext);
+  origin_trials_->AddTokens(*tokens, execution_context_->GetSecurityOrigin(),
+                            execution_context_->GetSecureContextMode() ==
+                                SecureContextMode::kSecureContext);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/execution_context/security_context_init.h b/third_party/blink/renderer/core/execution_context/security_context_init.h
index 6e261669..4e1b3ee 100644
--- a/third_party/blink/renderer/core/execution_context/security_context_init.h
+++ b/third_party/blink/renderer/core/execution_context/security_context_init.h
@@ -22,7 +22,6 @@
 class LocalFrame;
 class OriginTrialContext;
 class ResourceResponse;
-class SecurityOrigin;
 
 class CORE_EXPORT SecurityContextInit : public FeaturePolicyParserDelegate {
   STACK_ALLOCATED();
@@ -30,11 +29,9 @@
  public:
   // The first constructor is for workers and tests. The second is for windows.
   // TODO(japhet): Merge these.
-  SecurityContextInit(scoped_refptr<SecurityOrigin>, OriginTrialContext*);
-  explicit SecurityContextInit(ExecutionContext*,
-                               scoped_refptr<SecurityOrigin>);
+  explicit SecurityContextInit(OriginTrialContext*);
+  explicit SecurityContextInit(ExecutionContext*);
 
-  void CalculateSecureContextMode(LocalFrame* frame);
   void InitializeOriginTrials(const String& origin_trials_header);
   void ApplyFeaturePolicy(LocalFrame* frame,
                           const ResourceResponse& response,
@@ -44,21 +41,12 @@
       DocumentPolicy::ParsedDocumentPolicy& document_policy,
       const String& report_only_document_policy_header);
 
-  const scoped_refptr<SecurityOrigin>& GetSecurityOrigin() const {
-    return security_origin_;
-  }
-
   const ParsedFeaturePolicy& FeaturePolicyHeader() const {
     return feature_policy_header_;
   }
 
   OriginTrialContext* GetOriginTrialContext() const { return origin_trials_; }
 
-  SecureContextMode GetSecureContextMode() const {
-    DCHECK(secure_context_mode_.has_value());
-    return secure_context_mode_.value();
-  }
-
   void CountFeaturePolicyUsage(mojom::blink::WebFeature feature) override;
   bool FeaturePolicyFeatureObserved(
       mojom::blink::FeaturePolicyFeature) override;
@@ -66,10 +54,8 @@
 
  private:
   ExecutionContext* execution_context_ = nullptr;
-  scoped_refptr<SecurityOrigin> security_origin_;
   ParsedFeaturePolicy feature_policy_header_;
   OriginTrialContext* origin_trials_ = nullptr;
-  base::Optional<SecureContextMode> secure_context_mode_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/exported/prerendering_test.cc b/third_party/blink/renderer/core/exported/prerendering_test.cc
index 66cd92d..5086a3b6 100644
--- a/third_party/blink/renderer/core/exported/prerendering_test.cc
+++ b/third_party/blink/renderer/core/exported/prerendering_test.cc
@@ -317,7 +317,7 @@
 
   EXPECT_EQ(1u, PrerenderProcessor()->AddCount());
   EXPECT_EQ(0u, prerender->CancelCount());
-  EXPECT_EQ(1u, prerender->AbandonCount());
+  EXPECT_EQ(0u, prerender->AbandonCount());
 
   // Check that the prerender does not emit an extra cancel when
   // garbage-collecting everything.
@@ -325,7 +325,7 @@
 
   EXPECT_EQ(1u, PrerenderProcessor()->AddCount());
   EXPECT_EQ(0u, prerender->CancelCount());
-  EXPECT_EQ(1u, prerender->AbandonCount());
+  EXPECT_EQ(0u, prerender->AbandonCount());
 }
 
 TEST_F(PrerenderingTest, TwoPrerenders) {
@@ -384,7 +384,7 @@
   EXPECT_EQ(1u, first_prerender->CancelCount());
   EXPECT_EQ(0u, first_prerender->AbandonCount());
   EXPECT_EQ(0u, second_prerender->CancelCount());
-  EXPECT_EQ(1u, second_prerender->AbandonCount());
+  EXPECT_EQ(0u, second_prerender->AbandonCount());
 }
 
 TEST_F(PrerenderingTest, TwoPrerendersAddingThird) {
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index 3753f3f..f14fba2 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -230,9 +230,7 @@
 
 LocalDOMWindow::LocalDOMWindow(LocalFrame& frame, WindowAgent* agent)
     : DOMWindow(frame),
-      ExecutionContext(V8PerIsolateData::MainThreadIsolate(),
-                       agent,
-                       SecurityContext::kWindow),
+      ExecutionContext(V8PerIsolateData::MainThreadIsolate(), agent),
       visualViewport_(MakeGarbageCollected<DOMVisualViewport>(this)),
       should_print_when_finished_loading_(false),
       input_method_controller_(
@@ -450,6 +448,20 @@
   return frame->DomWindow()->GetReferrerPolicy();
 }
 
+network::mojom::blink::ReferrerPolicy
+LocalDOMWindow::ReferrerPolicyButForMetaTagsWithListsOfPolicies() const {
+  network::mojom::ReferrerPolicy policy =
+      ExecutionContext::ReferrerPolicyButForMetaTagsWithListsOfPolicies();
+  // For srcdoc documents without their own policy, walk up the frame tree
+  // analogously to when getting the referrer policy.
+  if (!GetFrame() || policy != network::mojom::ReferrerPolicy::kDefault ||
+      !document()->IsSrcdocDocument()) {
+    return policy;
+  }
+  LocalFrame* frame = To<LocalFrame>(GetFrame()->Tree().Parent());
+  return frame->DomWindow()->ReferrerPolicyButForMetaTagsWithListsOfPolicies();
+}
+
 CoreProbeSink* LocalDOMWindow::GetProbeSink() {
   return probe::ToCoreProbeSink(GetFrame());
 }
@@ -642,6 +654,16 @@
     CountUse(feature);
 }
 
+bool LocalDOMWindow::HasInsecureContextInAncestors() {
+  for (Frame* parent = GetFrame()->Tree().Parent(); parent;
+       parent = parent->Tree().Parent()) {
+    auto* origin = parent->GetSecurityContext()->GetSecurityOrigin();
+    if (!origin->IsPotentiallyTrustworthy())
+      return true;
+  }
+  return false;
+}
+
 Document* LocalDOMWindow::InstallNewDocument(const DocumentInit& init) {
   DCHECK_EQ(init.GetFrame(), GetFrame());
   DCHECK(!document_ || !document_->IsActive());
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.h b/third_party/blink/renderer/core/frame/local_dom_window.h
index a4ce859..38f9684a 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.h
+++ b/third_party/blink/renderer/core/frame/local_dom_window.h
@@ -136,6 +136,8 @@
   EventTarget* ErrorEventTarget() final { return this; }
   String OutgoingReferrer() const final;
   network::mojom::ReferrerPolicy GetReferrerPolicy() const final;
+  network::mojom::blink::ReferrerPolicy
+  ReferrerPolicyButForMetaTagsWithListsOfPolicies() const final;
   CoreProbeSink* GetProbeSink() final;
   BrowserInterfaceBrokerProxy& GetBrowserInterfaceBroker() final;
   FrameOrWorkerScheduler* GetScheduler() final;
@@ -417,6 +419,8 @@
   bool IsLocalDOMWindow() const override { return true; }
   bool IsRemoteDOMWindow() const override { return false; }
 
+  bool HasInsecureContextInAncestors() override;
+
   void Dispose();
 
   void DispatchLoadEvent();
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index 6d91a9a4..4b62d4f 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -2402,9 +2402,12 @@
 
 WebPrescientNetworking* LocalFrame::PrescientNetworking() {
   if (!prescient_networking_) {
-    prescient_networking_ = WebLocalFrameImpl::FromFrame(this)
-                                ->Client()
-                                ->CreatePrescientNetworking();
+    WebLocalFrameImpl* web_local_frame = WebLocalFrameImpl::FromFrame(this);
+    // There is no valid WebLocalFrame, return a nullptr to ignore pre* hints.
+    if (!web_local_frame)
+      return nullptr;
+    prescient_networking_ =
+        web_local_frame->Client()->CreatePrescientNetworking();
   }
   return prescient_networking_.get();
 }
diff --git a/third_party/blink/renderer/core/frame/remote_frame.cc b/third_party/blink/renderer/core/frame/remote_frame.cc
index f23ab42..9fc6571 100644
--- a/third_party/blink/renderer/core/frame/remote_frame.cc
+++ b/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -139,6 +139,9 @@
   if (!navigation_rate_limiter().CanProceed())
     return;
 
+  if (HTMLFrameOwnerElement* element = DeprecatedLocalOwner())
+    element->CancelPendingLazyLoad();
+
   frame_request.SetFrameType(IsMainFrame()
                                  ? mojom::RequestContextFrameType::kTopLevel
                                  : mojom::RequestContextFrameType::kNested);
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.h b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
index 380964d..670dff25 100644
--- a/third_party/blink/renderer/core/frame/web_local_frame_impl.h
+++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.h
@@ -404,6 +404,10 @@
 
   void CreateFrameView();
 
+  // Sometimes Blink makes Page/Frame for internal purposes like for SVGImage
+  // (see comments in third_party/blink/renderer/core/page/page.h). In that
+  // case, such frames are not associated with a WebLocalFrame(Impl).
+  // So note that FromFrame may return nullptr even for non-null frames.
   static WebLocalFrameImpl* FromFrame(LocalFrame*);
   static WebLocalFrameImpl* FromFrame(LocalFrame&);
 
diff --git a/third_party/blink/renderer/core/html/forms/html_option_element.h b/third_party/blink/renderer/core/html/forms/html_option_element.h
index 3102f67..78a6f79 100644
--- a/third_party/blink/renderer/core/html/forms/html_option_element.h
+++ b/third_party/blink/renderer/core/html/forms/html_option_element.h
@@ -104,7 +104,7 @@
   bool IsMultiSelectFocused() const;
 
   void SetWasOptionInsertedCalled(bool flag) {
-    was_option_inserted_called_ = true;
+    was_option_inserted_called_ = flag;
   }
   bool WasOptionInsertedCalled() const { return was_option_inserted_called_; }
 
diff --git a/third_party/blink/renderer/core/html/forms/password_input_type_test.cc b/third_party/blink/renderer/core/html/forms/password_input_type_test.cc
index e24ea410..006a727 100644
--- a/third_party/blink/renderer/core/html/forms/password_input_type_test.cc
+++ b/third_party/blink/renderer/core/html/forms/password_input_type_test.cc
@@ -77,10 +77,6 @@
       nullptr /* extra_data */);
   blink::test::RunPendingTasks();
   MockInsecureInputService mock_service(page_holder->GetFrame());
-  page_holder->GetFrame()
-      .DomWindow()
-      ->GetSecurityContext()
-      .SetSecureContextModeForTesting(SecureContextMode::kSecureContext);
   page_holder->GetDocument().body()->setInnerHTML("<input type='password'>");
   page_holder->GetDocument().View()->UpdateAllLifecyclePhases(
       DocumentUpdateReason::kTest);
diff --git a/third_party/blink/renderer/core/html/html_meta_element.cc b/third_party/blink/renderer/core/html/html_meta_element.cc
index 3c332ec..a0a6244 100644
--- a/third_party/blink/renderer/core/html/html_meta_element.cc
+++ b/third_party/blink/renderer/core/html/html_meta_element.cc
@@ -582,13 +582,18 @@
       UseCounter::Count(&GetDocument(),
                         WebFeature::kHTMLMetaElementReferrerPolicyOutsideHead);
     }
+    bool comma_in_content_value = false;
     if (content_value.Contains(',')) {
+      comma_in_content_value = true;
       UseCounter::Count(
           &GetDocument(),
           WebFeature::kHTMLMetaElementReferrerPolicyMultipleTokens);
     }
+
     GetExecutionContext()->ParseAndSetReferrerPolicy(
-        content_value, true /* support legacy keywords */);
+        content_value, true /* support legacy keywords */,
+        /*from_meta_tag_with_list_of_policies=*/
+        comma_in_content_value);
   } else if (EqualIgnoringASCIICase(name_value, "handheldfriendly") &&
              EqualIgnoringASCIICase(content_value, "true")) {
     ProcessViewportContentAttribute("width=device-width",
diff --git a/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc b/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc
index dbb9411..6839ba5 100644
--- a/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc
+++ b/third_party/blink/renderer/core/html/lazy_load_frame_observer.cc
@@ -157,8 +157,10 @@
 }
 
 void LazyLoadFrameObserver::LoadImmediately() {
-  DCHECK(IsLazyLoadPending());
-  DCHECK(lazy_load_request_info_);
+  // TODO(domfarolino): Change the CHECKs to DCHECKs once we confirm there are
+  // no crashes.
+  CHECK(IsLazyLoadPending());
+  CHECK(lazy_load_request_info_);
 
   if (was_recorded_as_deferred_) {
     DCHECK(element_->GetDocument().GetFrame());
@@ -177,10 +179,10 @@
   // The content frame of the element should not have changed, since any
   // pending lazy load should have been already been cancelled in
   // DisconnectContentFrame() if the content frame changes.
-  DCHECK(element_->ContentFrame());
+  CHECK(element_->ContentFrame());
 
-  // Note that calling FrameLoader::StartNavigation() causes the
-  // |lazy_load_intersection_observer_| to be disconnected.
+  // Note that calling both FrameLoader::StartNavigation() and Frame::Navigate()
+  // causes the |lazy_load_intersection_observer_| to be disconnected.
   FrameLoadRequest request(element_->GetDocument().domWindow(),
                            scoped_request_info->resource_request);
 
@@ -193,7 +195,7 @@
                                        scoped_request_info->frame_load_type);
   }
 
-  DCHECK(!IsLazyLoadPending());
+  CHECK(!IsLazyLoadPending());
 }
 
 void LazyLoadFrameObserver::StartTrackingVisibilityMetrics() {
diff --git a/third_party/blink/renderer/core/html/parser/html_tree_builder.cc b/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
index 4f83897..9e6360c 100644
--- a/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
+++ b/third_party/blink/renderer/core/html/parser/html_tree_builder.cc
@@ -58,6 +58,7 @@
 #include "third_party/blink/renderer/platform/text/platform_locale.h"
 #include "third_party/blink/renderer/platform/wtf/text/character_names.h"
 #include "third_party/blink/renderer/platform/wtf/text/character_visitor.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_buffer.h"
 
 namespace blink {
 
@@ -190,15 +191,16 @@
     if (length == start - end_)  // It's all whitespace.
       return String(characters_->Substring(start, start - end_));
 
-    StringBuilder result;
-    result.ReserveCapacity(length);
+    // All HTML spaces are ASCII.
+    StringBuffer<LChar> result(length);
+    unsigned j = 0;
     for (unsigned i = start; i < end_; ++i) {
       UChar c = (*characters_)[i];
-      if (IsHTMLSpace<UChar>(c))
-        result.Append(c);
+      if (IsHTMLSpace(c))
+        result[j++] = static_cast<LChar>(c);
     }
-
-    return result.ToString();
+    DCHECK_EQ(j, length);
+    return String::Adopt(result);
   }
 
  private:
diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
index 93566ba..da3904bf 100644
--- a/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
+++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap.cc
@@ -6,12 +6,12 @@
 
 #include <memory>
 #include <utility>
-
 #include "base/memory/scoped_refptr.h"
 #include "base/numerics/checked_math.h"
 #include "base/numerics/clamped_math.h"
 #include "base/single_thread_task_runner.h"
 #include "gpu/command_buffer/client/shared_image_interface.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/renderer/core/dom/dom_exception.h"
 #include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h"
 #include "third_party/blink/renderer/core/html/canvas/image_data.h"
@@ -20,6 +20,7 @@
 #include "third_party/blink/renderer/platform/graphics/accelerated_static_bitmap_image.h"
 #include "third_party/blink/renderer/platform/graphics/canvas_color_params.h"
 #include "third_party/blink/renderer/platform/graphics/canvas_resource_provider.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/shared_gpu_context.h"
 #include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
 #include "third_party/blink/renderer/platform/graphics/unaccelerated_static_bitmap_image.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
@@ -247,6 +248,31 @@
       size, kLow_SkFilterQuality, color_params);
 }
 
+std::unique_ptr<CanvasResourceProvider> CreateProviderForVideoElement(
+    HTMLVideoElement* video,
+    const ImageBitmapOptions* options) {
+  // TODO(crbug.com/1098445): ImageBitmap resize test case failed when
+  // quality equals to "low" and "medium". Need further investigate to
+  // enable gpu backed imageBitmap with resize options.
+  if (!SharedGpuContext::ContextProviderWrapper() ||
+      options->hasResizeWidth() || options->hasResizeHeight()) {
+    return CanvasResourceProvider::CreateBitmapProvider(
+        IntSize(video->videoWidth(), video->videoHeight()),
+        kLow_SkFilterQuality, CanvasColorParams());
+  }
+
+  uint32_t shared_image_usage_flags = gpu::SHARED_IMAGE_USAGE_DISPLAY;
+
+  return CanvasResourceProvider::CreateSharedImageProvider(
+      IntSize(video->videoWidth(), video->videoHeight()),
+      SharedGpuContext::ContextProviderWrapper(), kLow_SkFilterQuality,
+      CanvasColorParams(CanvasColorSpace::kSRGB,
+                        CanvasColorParams::GetNativeCanvasPixelFormat(),
+                        kNonOpaque),  // Default canvas settings
+      false,  // Origin of GL texture is bottom left on screen
+      RasterMode::kGPU, shared_image_usage_flags);
+}
+
 scoped_refptr<StaticBitmapImage> FlipImageVertically(
     scoped_refptr<StaticBitmapImage> input,
     const ImageBitmap::ParsedOptions& parsed_options) {
@@ -645,12 +671,8 @@
   if (DstBufferSizeHasOverflow(parsed_options))
     return;
 
-  // TODO(fserb): this shouldn't be software?
   std::unique_ptr<CanvasResourceProvider> resource_provider =
-      CanvasResourceProvider::CreateBitmapProvider(
-          IntSize(video->videoWidth(), video->videoHeight()),
-          kLow_SkFilterQuality,
-          CanvasColorParams());  // TODO: set color space here to avoid clamping
+      CreateProviderForVideoElement(video, options);
 
   if (!resource_provider)
     return;
diff --git a/third_party/blink/renderer/core/inspector/inspector_highlight.cc b/third_party/blink/renderer/core/inspector/inspector_highlight.cc
index 591b920..1c3bb78 100644
--- a/third_party/blink/renderer/core/inspector/inspector_highlight.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_highlight.cc
@@ -107,7 +107,7 @@
                    LayoutObject& layout_object,
                    const ShapeOutsideInfo& shape_outside_info)
       : view_(&view),
-        layout_object_(layout_object),
+        layout_object_(&layout_object),
         shape_outside_info_(shape_outside_info) {}
 
   static std::unique_ptr<protocol::ListValue> BuildPath(
@@ -127,13 +127,13 @@
         shape_outside_info_.ShapeToLayoutObjectPoint(point));
     // TODO(pfeldman): Is this kIgnoreTransforms correct?
     return FloatPoint(view_->FrameToViewport(
-        RoundedIntPoint(layout_object_.LocalToAbsolutePoint(
+        RoundedIntPoint(layout_object_->LocalToAbsolutePoint(
             layout_object_point, kIgnoreTransforms))));
   }
 
  private:
   LocalFrameView* view_;
-  LayoutObject& layout_object_;
+  LayoutObject* const layout_object_;
   const ShapeOutsideInfo& shape_outside_info_;
 };
 
diff --git a/third_party/blink/renderer/core/layout/counter_node.cc b/third_party/blink/renderer/core/layout/counter_node.cc
index d51138f..c4317c31 100644
--- a/third_party/blink/renderer/core/layout/counter_node.cc
+++ b/third_party/blink/renderer/core/layout/counter_node.cc
@@ -34,7 +34,7 @@
     : type_mask_(type_mask),
       value_(value),
       count_in_parent_(0),
-      owner_(o),
+      owner_(&o),
       root_layout_object_(nullptr),
       parent_(nullptr),
       previous_sibling_(nullptr),
diff --git a/third_party/blink/renderer/core/layout/counter_node.h b/third_party/blink/renderer/core/layout/counter_node.h
index 1ba00809..2c10198 100644
--- a/third_party/blink/renderer/core/layout/counter_node.h
+++ b/third_party/blink/renderer/core/layout/counter_node.h
@@ -58,7 +58,7 @@
   bool HasSetType() const { return type_mask_ & kSetType; }
   int Value() const { return value_; }
   int CountInParent() const { return count_in_parent_; }
-  LayoutObject& Owner() const { return owner_; }
+  LayoutObject& Owner() const { return *owner_; }
   void AddLayoutObject(LayoutCounter*);
   void RemoveLayoutObject(LayoutCounter*);
 
@@ -116,7 +116,7 @@
   unsigned type_mask_;
   int value_;
   int count_in_parent_;
-  LayoutObject& owner_;
+  LayoutObject* const owner_;
   LayoutCounter* root_layout_object_;
 
   CounterNode* parent_;
diff --git a/third_party/blink/renderer/core/layout/floating_objects.cc b/third_party/blink/renderer/core/layout/floating_objects.cc
index e77e990..2dde22f 100644
--- a/third_party/blink/renderer/core/layout/floating_objects.cc
+++ b/third_party/blink/renderer/core/layout/floating_objects.cc
@@ -210,7 +210,7 @@
 
   FindNextFloatLogicalBottomAdapter(const LayoutBlockFlow& renderer,
                                     LayoutUnit below_logical_height)
-      : layout_object_(renderer),
+      : layout_object_(&renderer),
         below_logical_height_(below_logical_height),
         above_logical_height_(LayoutUnit::Max()),
         next_logical_bottom_(),
@@ -224,7 +224,7 @@
   LayoutUnit NextShapeLogicalBottom() { return next_shape_logical_bottom_; }
 
  private:
-  const LayoutBlockFlow& layout_object_;
+  const LayoutBlockFlow* const layout_object_;
   LayoutUnit below_logical_height_;
   LayoutUnit above_logical_height_;
   LayoutUnit next_logical_bottom_;
@@ -263,18 +263,18 @@
 
   // All the objects returned from the tree should be already placed.
   DCHECK(floating_object.IsPlaced());
-  DCHECK(RangesIntersect(layout_object_.LogicalTopForFloat(floating_object),
-                         layout_object_.LogicalBottomForFloat(floating_object),
+  DCHECK(RangesIntersect(layout_object_->LogicalTopForFloat(floating_object),
+                         layout_object_->LogicalBottomForFloat(floating_object),
                          below_logical_height_, above_logical_height_));
 
   LayoutUnit float_bottom =
-      layout_object_.LogicalBottomForFloat(floating_object);
+      layout_object_->LogicalBottomForFloat(floating_object);
 
   if (ShapeOutsideInfo* shape_outside =
           floating_object.GetLayoutObject()->GetShapeOutsideInfo()) {
     LayoutUnit shape_bottom =
-        layout_object_.LogicalTopForFloat(floating_object) +
-        layout_object_.MarginBeforeForChild(
+        layout_object_->LogicalTopForFloat(floating_object) +
+        layout_object_->MarginBeforeForChild(
             *floating_object.GetLayoutObject()) +
         shape_outside->ShapeLogicalBottom();
     // Use the shapeBottom unless it extends outside of the margin box, in which
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index 4f4541e..870ec24 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -423,6 +423,8 @@
 
   // Helper class forbidding calls to setNeedsLayout() during its lifetime.
   class SetLayoutNeededForbiddenScope {
+    STACK_ALLOCATED();
+
    public:
     explicit SetLayoutNeededForbiddenScope(LayoutObject&);
     ~SetLayoutNeededForbiddenScope();
diff --git a/third_party/blink/renderer/core/layout/layout_state.cc b/third_party/blink/renderer/core/layout/layout_state.cc
index 4ed2149..5767bad 100644
--- a/third_party/blink/renderer/core/layout/layout_state.cc
+++ b/third_party/blink/renderer/core/layout/layout_state.cc
@@ -37,7 +37,7 @@
       pagination_state_changed_(false),
       flow_thread_(nullptr),
       next_(nullptr),
-      layout_object_(view) {
+      layout_object_(&view) {
   DCHECK(!view.GetLayoutState());
   view.PushLayoutState(*this);
 }
@@ -47,7 +47,7 @@
     : containing_block_logical_width_changed_(
           containing_block_logical_width_changed),
       next_(layout_object.View()->GetLayoutState()),
-      layout_object_(layout_object) {
+      layout_object_(&layout_object) {
   if (layout_object.IsLayoutFlowThread())
     flow_thread_ = ToLayoutFlowThread(&layout_object);
   else
@@ -73,7 +73,7 @@
   // overflow:scroll/auto, inline blocks and writing mode roots. Additionally,
   // pagination inside SVG is not allowed.
   if (layout_object.GetPaginationBreakability() == LayoutBox::kForbidBreaks ||
-      layout_object_.IsSVGChild()) {
+      layout_object_->IsSVGChild()) {
     flow_thread_ = nullptr;
     is_paginated_ = false;
     return;
@@ -108,16 +108,16 @@
       pagination_state_changed_(false),
       flow_thread_(nullptr),
       next_(root.View()->GetLayoutState()),
-      layout_object_(root) {
+      layout_object_(&root) {
   DCHECK(!next_);
   DCHECK(!IsA<LayoutView>(root));
   root.View()->PushLayoutState(*this);
 }
 
 LayoutState::~LayoutState() {
-  if (layout_object_.View()->GetLayoutState()) {
-    DCHECK_EQ(layout_object_.View()->GetLayoutState(), this);
-    layout_object_.View()->PopLayoutState();
+  if (layout_object_->View()->GetLayoutState()) {
+    DCHECK_EQ(layout_object_->View()->GetLayoutState(), this);
+    layout_object_->View()->PopLayoutState();
   }
 }
 
diff --git a/third_party/blink/renderer/core/layout/layout_state.h b/third_party/blink/renderer/core/layout/layout_state.h
index 0e0572b..574f1b8 100644
--- a/third_party/blink/renderer/core/layout/layout_state.h
+++ b/third_party/blink/renderer/core/layout/layout_state.h
@@ -109,7 +109,7 @@
 
   LayoutFlowThread* FlowThread() const { return flow_thread_; }
 
-  LayoutObject& GetLayoutObject() const { return layout_object_; }
+  LayoutObject& GetLayoutObject() const { return *layout_object_; }
 
  private:
   // Do not add anything apart from bitfields until after m_flowThread. See
@@ -137,7 +137,7 @@
 
   AtomicString input_page_name_;
 
-  LayoutObject& layout_object_;
+  LayoutObject* const layout_object_;
   DISALLOW_COPY_AND_ASSIGN(LayoutState);
 };
 
diff --git a/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.cc b/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.cc
index 8f516e2..e479280 100644
--- a/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.cc
+++ b/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.cc
@@ -21,19 +21,19 @@
 
 MultiColumnFragmentainerGroup::MultiColumnFragmentainerGroup(
     const LayoutMultiColumnSet& column_set)
-    : column_set_(column_set) {}
+    : column_set_(&column_set) {}
 
 bool MultiColumnFragmentainerGroup::IsFirstGroup() const {
-  return &column_set_.FirstFragmentainerGroup() == this;
+  return &column_set_->FirstFragmentainerGroup() == this;
 }
 
 bool MultiColumnFragmentainerGroup::IsLastGroup() const {
-  return &column_set_.LastFragmentainerGroup() == this;
+  return &column_set_->LastFragmentainerGroup() == this;
 }
 
 LayoutSize MultiColumnFragmentainerGroup::OffsetFromColumnSet() const {
   LayoutSize offset(LayoutUnit(), LogicalTop());
-  if (!column_set_.FlowThread()->IsHorizontalWritingMode())
+  if (!column_set_->FlowThread()->IsHorizontalWritingMode())
     return offset.TransposedSize();
   return offset;
 }
@@ -41,8 +41,8 @@
 LayoutUnit
 MultiColumnFragmentainerGroup::BlockOffsetInEnclosingFragmentationContext()
     const {
-  return LogicalTop() + column_set_.LogicalTopFromMulticolContentEdge() +
-         column_set_.MultiColumnFlowThread()
+  return LogicalTop() + column_set_->LogicalTopFromMulticolContentEdge() +
+         column_set_->MultiColumnFlowThread()
              ->BlockOffsetInEnclosingFragmentationContext();
 }
 
@@ -74,8 +74,8 @@
   max_logical_height_ = CalculateMaxColumnHeight();
 
   LayoutMultiColumnFlowThread* flow_thread =
-      column_set_.MultiColumnFlowThread();
-  if (column_set_.HeightIsAuto()) {
+      column_set_->MultiColumnFlowThread();
+  if (column_set_->HeightIsAuto()) {
     FragmentationContext* enclosing_fragmentation_context =
         flow_thread->EnclosingFragmentationContext();
     if (enclosing_fragmentation_context &&
@@ -157,7 +157,7 @@
     LayoutBox::PageBoundaryRule rule,
     CoordinateSpaceConversion mode) const {
   LayoutMultiColumnFlowThread* flow_thread =
-      column_set_.MultiColumnFlowThread();
+      column_set_->MultiColumnFlowThread();
 
   // A column out of range doesn't have a flow thread portion, so we need to
   // clamp to make sure that we stay within the actual columns. This means that
@@ -174,8 +174,8 @@
 
   LayoutRect column_rect(ColumnRectAt(column_index));
   column_rect.Move(OffsetFromColumnSet());
-  column_set_.DeprecatedFlipForWritingMode(column_rect);
-  column_rect.MoveBy(column_set_.PhysicalLocation().ToLayoutPoint());
+  column_set_->DeprecatedFlipForWritingMode(column_rect);
+  column_rect.MoveBy(column_set_->PhysicalLocation().ToLayoutPoint());
 
   LayoutSize translation_relative_to_flow_thread =
       column_rect.Location() - portion_rect.Location();
@@ -231,9 +231,9 @@
   LayoutRect column_rect = ColumnRectAt(column_index);
   LayoutPoint local_point(visual_point);
   local_point.MoveBy(-column_rect.Location());
-  if (!column_set_.IsHorizontalWritingMode()) {
+  if (!column_set_->IsHorizontalWritingMode()) {
     if (snap == kSnapToColumn) {
-      LayoutUnit column_start = column_set_.StyleRef().IsLeftToRightDirection()
+      LayoutUnit column_start = column_set_->StyleRef().IsLeftToRightDirection()
                                     ? LayoutUnit()
                                     : column_rect.Height();
       if (local_point.X() < 0)
@@ -245,7 +245,7 @@
                        local_point.Y());
   }
   if (snap == kSnapToColumn) {
-    LayoutUnit column_start = column_set_.StyleRef().IsLeftToRightDirection()
+    LayoutUnit column_start = column_set_->StyleRef().IsLeftToRightDirection()
                                   ? LayoutUnit()
                                   : column_rect.Width();
     if (local_point.Y() < 0)
@@ -261,10 +261,10 @@
     const LayoutRect& bounding_box_in_flow_thread) const {
   // Find the start and end column intersected by the bounding box.
   LayoutRect flipped_bounding_box_in_flow_thread(bounding_box_in_flow_thread);
-  LayoutFlowThread* flow_thread = column_set_.FlowThread();
+  LayoutFlowThread* flow_thread = column_set_->FlowThread();
   flow_thread->DeprecatedFlipForWritingMode(
       flipped_bounding_box_in_flow_thread);
-  bool is_horizontal_writing_mode = column_set_.IsHorizontalWritingMode();
+  bool is_horizontal_writing_mode = column_set_->IsHorizontalWritingMode();
   LayoutUnit bounding_box_logical_top =
       is_horizontal_writing_mode ? flipped_bounding_box_in_flow_thread.Y()
                                  : flipped_bounding_box_in_flow_thread.X();
@@ -335,13 +335,13 @@
 LayoutUnit MultiColumnFragmentainerGroup::HeightAdjustedForRowOffset(
     LayoutUnit height) const {
   LayoutUnit adjusted_height =
-      height - LogicalTop() - column_set_.LogicalTopFromMulticolContentEdge();
+      height - LogicalTop() - column_set_->LogicalTopFromMulticolContentEdge();
   return adjusted_height.ClampNegativeToZero();
 }
 
 LayoutUnit MultiColumnFragmentainerGroup::CalculateMaxColumnHeight() const {
   LayoutMultiColumnFlowThread* flow_thread =
-      column_set_.MultiColumnFlowThread();
+      column_set_->MultiColumnFlowThread();
   LayoutUnit max_column_height = flow_thread->MaxColumnLogicalHeight();
   LayoutUnit max_height = HeightAdjustedForRowOffset(max_column_height);
   if (FragmentationContext* enclosing_fragmentation_context =
@@ -368,7 +368,7 @@
 
 LayoutUnit MultiColumnFragmentainerGroup::RebalanceColumnHeightIfNeeded()
     const {
-  if (ActualColumnCount() <= column_set_.UsedColumnCount()) {
+  if (ActualColumnCount() <= column_set_->UsedColumnCount()) {
     // With the current column height, the content fits without creating
     // overflowing columns. We're done.
     return logical_height_;
@@ -386,7 +386,7 @@
       ColumnSet(), LogicalTopInFlowThread(), LogicalBottomInFlowThread());
 
   if (shortage_finder.ForcedBreaksCount() + 1 >=
-      column_set_.UsedColumnCount()) {
+      column_set_->UsedColumnCount()) {
     // Too many forced breaks to allow any implicit breaks. Initial balancing
     // should already have set a good height. There's nothing more we should do.
     return logical_height_;
@@ -410,23 +410,23 @@
 
 LayoutRect MultiColumnFragmentainerGroup::ColumnRectAt(
     unsigned column_index) const {
-  LayoutUnit column_logical_width = column_set_.PageLogicalWidth();
+  LayoutUnit column_logical_width = column_set_->PageLogicalWidth();
   LayoutUnit column_logical_height = LogicalHeightInFlowThreadAt(column_index);
   LayoutUnit column_logical_top;
   LayoutUnit column_logical_left;
-  LayoutUnit column_gap = column_set_.ColumnGap();
+  LayoutUnit column_gap = column_set_->ColumnGap();
 
-  if (column_set_.StyleRef().IsLeftToRightDirection()) {
+  if (column_set_->StyleRef().IsLeftToRightDirection()) {
     column_logical_left += column_index * (column_logical_width + column_gap);
   } else {
-    column_logical_left += column_set_.ContentLogicalWidth() -
+    column_logical_left += column_set_->ContentLogicalWidth() -
                            column_logical_width -
                            column_index * (column_logical_width + column_gap);
   }
 
   LayoutRect column_rect(column_logical_left, column_logical_top,
                          column_logical_width, column_logical_height);
-  if (!column_set_.IsHorizontalWritingMode())
+  if (!column_set_->IsHorizontalWritingMode())
     return column_rect.TransposedRect();
   return column_rect;
 }
@@ -435,11 +435,12 @@
     unsigned column_index) const {
   LayoutUnit logical_top = LogicalTopInFlowThreadAt(column_index);
   LayoutUnit portion_logical_height = LogicalHeightInFlowThreadAt(column_index);
-  if (column_set_.IsHorizontalWritingMode())
-    return LayoutRect(LayoutUnit(), logical_top, column_set_.PageLogicalWidth(),
-                      portion_logical_height);
+  if (column_set_->IsHorizontalWritingMode()) {
+    return LayoutRect(LayoutUnit(), logical_top,
+                      column_set_->PageLogicalWidth(), portion_logical_height);
+  }
   return LayoutRect(logical_top, LayoutUnit(), portion_logical_height,
-                    column_set_.PageLogicalWidth());
+                    column_set_->PageLogicalWidth());
 }
 
 LayoutRect MultiColumnFragmentainerGroup::FlowThreadPortionOverflowRectAt(
@@ -460,11 +461,11 @@
   LayoutRect portion_rect = FlowThreadPortionRectAt(column_index);
   bool is_first_column_in_multicol_container =
       is_first_column_in_row &&
-      this == &column_set_.FirstFragmentainerGroup() &&
-      !column_set_.PreviousSiblingMultiColumnSet();
+      this == &column_set_->FirstFragmentainerGroup() &&
+      !column_set_->PreviousSiblingMultiColumnSet();
   bool is_last_column_in_multicol_container =
-      is_last_column_in_row && this == &column_set_.LastFragmentainerGroup() &&
-      !column_set_.NextSiblingMultiColumnSet();
+      is_last_column_in_row && this == &column_set_->LastFragmentainerGroup() &&
+      !column_set_->NextSiblingMultiColumnSet();
   // Calculate the overflow rectangle. It will be clipped at the logical top
   // and bottom of the column box, unless it's the first or last column in the
   // multicol container, in which case it should allow overflow. It will also
@@ -473,7 +474,7 @@
   LayoutRect overflow_rect(
       IntRect(-kMulticolMaxClipPixels, -kMulticolMaxClipPixels,
               2 * kMulticolMaxClipPixels, 2 * kMulticolMaxClipPixels));
-  if (column_set_.IsHorizontalWritingMode()) {
+  if (column_set_->IsHorizontalWritingMode()) {
     if (!is_first_column_in_multicol_container)
       overflow_rect.ShiftYEdgeTo(portion_rect.Y());
     if (!is_last_column_in_multicol_container)
@@ -520,15 +521,15 @@
 
 unsigned MultiColumnFragmentainerGroup::ColumnIndexAtVisualPoint(
     const LayoutPoint& visual_point) const {
-  LayoutUnit column_length = column_set_.PageLogicalWidth();
+  LayoutUnit column_length = column_set_->PageLogicalWidth();
   LayoutUnit offset_in_column_progression_direction =
-      column_set_.IsHorizontalWritingMode() ? visual_point.X()
-                                            : visual_point.Y();
-  if (!column_set_.StyleRef().IsLeftToRightDirection()) {
+      column_set_->IsHorizontalWritingMode() ? visual_point.X()
+                                             : visual_point.Y();
+  if (!column_set_->StyleRef().IsLeftToRightDirection()) {
     offset_in_column_progression_direction =
-        column_set_.LogicalWidth() - offset_in_column_progression_direction;
+        column_set_->LogicalWidth() - offset_in_column_progression_direction;
   }
-  LayoutUnit column_gap = column_set_.ColumnGap();
+  LayoutUnit column_gap = column_set_->ColumnGap();
   if (column_length + column_gap <= 0)
     return 0;
   // Column boundaries are in the middle of the column gap.
@@ -567,8 +568,8 @@
     const LayoutRect& rect,
     unsigned& first_column,
     unsigned& last_column) const {
-  bool is_column_ltr = column_set_.StyleRef().IsLeftToRightDirection();
-  if (column_set_.IsHorizontalWritingMode()) {
+  bool is_column_ltr = column_set_->StyleRef().IsLeftToRightDirection();
+  if (column_set_->IsHorizontalWritingMode()) {
     if (is_column_ltr) {
       first_column = ColumnIndexAtVisualPoint(rect.MinXMinYCorner());
       last_column = ColumnIndexAtVisualPoint(rect.MaxXMinYCorner());
diff --git a/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h b/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h
index 1c52891..8a6c173d 100644
--- a/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h
+++ b/third_party/blink/renderer/core/layout/multi_column_fragmentainer_group.h
@@ -36,7 +36,7 @@
  public:
   MultiColumnFragmentainerGroup(const LayoutMultiColumnSet&);
 
-  const LayoutMultiColumnSet& ColumnSet() const { return column_set_; }
+  const LayoutMultiColumnSet& ColumnSet() const { return *column_set_; }
 
   bool IsFirstGroup() const;
   bool IsLastGroup() const;
@@ -180,7 +180,7 @@
 
   unsigned UnclampedActualColumnCount() const;
 
-  const LayoutMultiColumnSet& column_set_;
+  const LayoutMultiColumnSet* const column_set_;
 
   LayoutUnit logical_top_;
   LayoutUnit logical_top_in_flow_thread_;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
index fb12ee5..cc6c311 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_column_layout_algorithm.cc
@@ -442,7 +442,7 @@
       if (entry.break_token) {
         // Copy unhandled incoming break tokens, for the next (outer)
         // fragmentainer.
-        container_builder_.AddBreakToken(std::move(entry.break_token));
+        container_builder_.AddBreakToken(entry.break_token);
       } else if (entry.spanner) {
         // Create break tokens for the spanners that were discovered (but not
         // handled) while laying out this (outer) fragmentainer, so that they
diff --git a/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc b/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc
index 6c94732..d6b2f06d 100644
--- a/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc
+++ b/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc
@@ -54,41 +54,43 @@
 
 void ShapeOutsideInfo::SetReferenceBoxLogicalSize(
     LayoutSize new_reference_box_logical_size) {
-  Document& document = layout_box_.GetDocument();
+  Document& document = layout_box_->GetDocument();
   bool is_horizontal_writing_mode =
-      layout_box_.ContainingBlock()->StyleRef().IsHorizontalWritingMode();
+      layout_box_->ContainingBlock()->StyleRef().IsHorizontalWritingMode();
 
   LayoutSize margin_box_for_use_counter = new_reference_box_logical_size;
   if (is_horizontal_writing_mode) {
-    margin_box_for_use_counter.Expand(layout_box_.MarginWidth(),
-                                      layout_box_.MarginHeight());
+    margin_box_for_use_counter.Expand(layout_box_->MarginWidth(),
+                                      layout_box_->MarginHeight());
   } else {
-    margin_box_for_use_counter.Expand(layout_box_.MarginHeight(),
-                                      layout_box_.MarginWidth());
+    margin_box_for_use_counter.Expand(layout_box_->MarginHeight(),
+                                      layout_box_->MarginWidth());
   }
 
-  const ShapeValue& shape_value = *layout_box_.StyleRef().ShapeOutside();
+  const ShapeValue& shape_value = *layout_box_->StyleRef().ShapeOutside();
   switch (ReferenceBox(shape_value)) {
     case CSSBoxType::kMargin:
       UseCounter::Count(document, WebFeature::kShapeOutsideMarginBox);
-      if (is_horizontal_writing_mode)
-        new_reference_box_logical_size.Expand(layout_box_.MarginWidth(),
-                                              layout_box_.MarginHeight());
-      else
-        new_reference_box_logical_size.Expand(layout_box_.MarginHeight(),
-                                              layout_box_.MarginWidth());
+      if (is_horizontal_writing_mode) {
+        new_reference_box_logical_size.Expand(layout_box_->MarginWidth(),
+                                              layout_box_->MarginHeight());
+      } else {
+        new_reference_box_logical_size.Expand(layout_box_->MarginHeight(),
+                                              layout_box_->MarginWidth());
+      }
       break;
     case CSSBoxType::kBorder:
       UseCounter::Count(document, WebFeature::kShapeOutsideBorderBox);
       break;
     case CSSBoxType::kPadding:
       UseCounter::Count(document, WebFeature::kShapeOutsidePaddingBox);
-      if (is_horizontal_writing_mode)
-        new_reference_box_logical_size.Shrink(layout_box_.BorderWidth(),
-                                              layout_box_.BorderHeight());
-      else
-        new_reference_box_logical_size.Shrink(layout_box_.BorderHeight(),
-                                              layout_box_.BorderWidth());
+      if (is_horizontal_writing_mode) {
+        new_reference_box_logical_size.Shrink(layout_box_->BorderWidth(),
+                                              layout_box_->BorderHeight());
+      } else {
+        new_reference_box_logical_size.Shrink(layout_box_->BorderHeight(),
+                                              layout_box_->BorderWidth());
+      }
 
       if (new_reference_box_logical_size != margin_box_for_use_counter) {
         UseCounter::Count(
@@ -102,14 +104,15 @@
       if (!is_shape_image)
         UseCounter::Count(document, WebFeature::kShapeOutsideContentBox);
 
-      if (is_horizontal_writing_mode)
+      if (is_horizontal_writing_mode) {
         new_reference_box_logical_size.Shrink(
-            layout_box_.BorderAndPaddingWidth(),
-            layout_box_.BorderAndPaddingHeight());
-      else
+            layout_box_->BorderAndPaddingWidth(),
+            layout_box_->BorderAndPaddingHeight());
+      } else {
         new_reference_box_logical_size.Shrink(
-            layout_box_.BorderAndPaddingHeight(),
-            layout_box_.BorderAndPaddingWidth());
+            layout_box_->BorderAndPaddingHeight(),
+            layout_box_->BorderAndPaddingWidth());
+      }
 
       if (!is_shape_image &&
           new_reference_box_logical_size != margin_box_for_use_counter) {
@@ -188,24 +191,24 @@
     float margin) const {
   DCHECK(!style_image->IsPendingImage());
   const LayoutSize& image_size = RoundedLayoutSize(style_image->ImageSize(
-      layout_box_.GetDocument(), layout_box_.StyleRef().EffectiveZoom(),
+      layout_box_->GetDocument(), layout_box_->StyleRef().EffectiveZoom(),
       FloatSize(reference_box_logical_size_),
-      LayoutObject::ShouldRespectImageOrientation(&layout_box_)));
+      LayoutObject::ShouldRespectImageOrientation(layout_box_)));
 
   const LayoutRect& margin_rect =
-      GetShapeImageMarginRect(layout_box_, reference_box_logical_size_);
+      GetShapeImageMarginRect(*layout_box_, reference_box_logical_size_);
   const LayoutRect& image_rect =
-      (layout_box_.IsLayoutImage())
-          ? ToLayoutImage(layout_box_).ReplacedContentRect().ToLayoutRect()
+      (layout_box_->IsLayoutImage())
+          ? ToLayoutImage(layout_box_)->ReplacedContentRect().ToLayoutRect()
           : LayoutRect(LayoutPoint(), image_size);
 
   scoped_refptr<Image> image =
-      style_image->GetImage(layout_box_, layout_box_.GetDocument(),
-                            layout_box_.StyleRef(), FloatSize(image_size));
+      style_image->GetImage(*layout_box_, layout_box_->GetDocument(),
+                            layout_box_->StyleRef(), FloatSize(image_size));
 
   return Shape::CreateRasterShape(
       image.get(), shape_image_threshold, image_rect, margin_rect, writing_mode,
-      margin, LayoutObject::ShouldRespectImageOrientation(&layout_box_));
+      margin, LayoutObject::ShouldRespectImageOrientation(layout_box_));
 }
 
 const Shape& ShapeOutsideInfo::ComputedShape() const {
@@ -214,9 +217,9 @@
 
   base::AutoReset<bool> is_in_computing_shape(&is_computing_shape_, true);
 
-  const ComputedStyle& style = *layout_box_.Style();
-  DCHECK(layout_box_.ContainingBlock());
-  const LayoutBlock& containing_block = *layout_box_.ContainingBlock();
+  const ComputedStyle& style = *layout_box_->Style();
+  DCHECK(layout_box_->ContainingBlock());
+  const LayoutBlock& containing_block = *layout_box_->ContainingBlock();
   const ComputedStyle& containing_block_style = containing_block.StyleRef();
 
   WritingMode writing_mode = containing_block_style.GetWritingMode();
@@ -229,7 +232,7 @@
           : std::max(LayoutUnit(), containing_block.ContentWidth());
 
   float margin =
-      FloatValueForLength(layout_box_.StyleRef().ShapeMargin(),
+      FloatValueForLength(layout_box_->StyleRef().ShapeMargin(),
                           percentage_resolution_inline_size.ToFloat());
 
   float shape_image_threshold = style.ShapeImageThreshold();
@@ -301,19 +304,20 @@
 }
 
 LayoutUnit ShapeOutsideInfo::LogicalTopOffset() const {
-  switch (ReferenceBox(*layout_box_.StyleRef().ShapeOutside())) {
+  switch (ReferenceBox(*layout_box_->StyleRef().ShapeOutside())) {
     case CSSBoxType::kMargin:
-      return -layout_box_.MarginBefore(layout_box_.ContainingBlock()->Style());
+      return -layout_box_->MarginBefore(
+          layout_box_->ContainingBlock()->Style());
     case CSSBoxType::kBorder:
       return LayoutUnit();
     case CSSBoxType::kPadding:
       return BorderBeforeInWritingMode(
-          layout_box_,
-          layout_box_.ContainingBlock()->StyleRef().GetWritingMode());
+          *layout_box_,
+          layout_box_->ContainingBlock()->StyleRef().GetWritingMode());
     case CSSBoxType::kContent:
       return BorderAndPaddingBeforeInWritingMode(
-          layout_box_,
-          layout_box_.ContainingBlock()->StyleRef().GetWritingMode());
+          *layout_box_,
+          layout_box_->ContainingBlock()->StyleRef().GetWritingMode());
     case CSSBoxType::kMissing:
       break;
   }
@@ -353,17 +357,17 @@
 }
 
 LayoutUnit ShapeOutsideInfo::LogicalLeftOffset() const {
-  switch (ReferenceBox(*layout_box_.StyleRef().ShapeOutside())) {
+  switch (ReferenceBox(*layout_box_->StyleRef().ShapeOutside())) {
     case CSSBoxType::kMargin:
-      return -layout_box_.MarginStart(layout_box_.ContainingBlock()->Style());
+      return -layout_box_->MarginStart(layout_box_->ContainingBlock()->Style());
     case CSSBoxType::kBorder:
       return LayoutUnit();
     case CSSBoxType::kPadding:
       return BorderStartWithStyleForWritingMode(
-          layout_box_, layout_box_.ContainingBlock()->Style());
+          *layout_box_, layout_box_->ContainingBlock()->Style());
     case CSSBoxType::kContent:
       return BorderAndPaddingStartWithStyleForWritingMode(
-          layout_box_, layout_box_.ContainingBlock()->Style());
+          *layout_box_, layout_box_->ContainingBlock()->Style());
     case CSSBoxType::kMissing:
       break;
   }
@@ -402,7 +406,7 @@
 
   LayoutUnit border_box_top =
       containing_block.LogicalTopForFloat(floating_object) +
-      containing_block.MarginBeforeForChild(layout_box_);
+      containing_block.MarginBeforeForChild(*layout_box_);
   LayoutUnit border_box_line_top = line_top - border_box_top;
 
   if (IsShapeDirty() ||
@@ -420,8 +424,8 @@
       if (segment.is_valid) {
         LayoutUnit logical_left_margin =
             containing_block.StyleRef().IsLeftToRightDirection()
-                ? containing_block.MarginStartForChild(layout_box_)
-                : containing_block.MarginEndForChild(layout_box_);
+                ? containing_block.MarginStartForChild(*layout_box_)
+                : containing_block.MarginEndForChild(*layout_box_);
         LayoutUnit raw_left_margin_box_delta =
             segment.logical_left + LogicalLeftOffset() + logical_left_margin;
         LayoutUnit left_margin_box_delta = clampTo<LayoutUnit>(
@@ -429,11 +433,11 @@
 
         LayoutUnit logical_right_margin =
             containing_block.StyleRef().IsLeftToRightDirection()
-                ? containing_block.MarginEndForChild(layout_box_)
-                : containing_block.MarginStartForChild(layout_box_);
+                ? containing_block.MarginEndForChild(*layout_box_)
+                : containing_block.MarginStartForChild(*layout_box_);
         LayoutUnit raw_right_margin_box_delta =
             segment.logical_right + LogicalLeftOffset() -
-            containing_block.LogicalWidthForChild(layout_box_) -
+            containing_block.LogicalWidthForChild(*layout_box_) -
             logical_right_margin;
         LayoutUnit right_margin_box_delta = clampTo<LayoutUnit>(
             raw_right_margin_box_delta, -float_margin_box_width, LayoutUnit());
@@ -461,13 +465,13 @@
       ComputedShape().ShapeMarginLogicalBoundingBox();
   physical_bounding_box.SetX(physical_bounding_box.X() + LogicalLeftOffset());
 
-  if (layout_box_.StyleRef().IsFlippedBlocksWritingMode())
-    physical_bounding_box.SetY(layout_box_.LogicalHeight() -
+  if (layout_box_->StyleRef().IsFlippedBlocksWritingMode())
+    physical_bounding_box.SetY(layout_box_->LogicalHeight() -
                                physical_bounding_box.MaxY());
   else
     physical_bounding_box.SetY(physical_bounding_box.Y() + LogicalTopOffset());
 
-  if (!layout_box_.StyleRef().IsHorizontalWritingMode())
+  if (!layout_box_->StyleRef().IsHorizontalWritingMode())
     physical_bounding_box = physical_bounding_box.TransposedRect();
   else
     physical_bounding_box.SetY(physical_bounding_box.Y() + LogicalTopOffset());
@@ -478,9 +482,9 @@
 FloatPoint ShapeOutsideInfo::ShapeToLayoutObjectPoint(FloatPoint point) const {
   FloatPoint result = FloatPoint(point.X() + LogicalLeftOffset(),
                                  point.Y() + LogicalTopOffset());
-  if (layout_box_.StyleRef().IsFlippedBlocksWritingMode())
-    result.SetY(layout_box_.LogicalHeight() - result.Y());
-  if (!layout_box_.StyleRef().IsHorizontalWritingMode())
+  if (layout_box_->StyleRef().IsFlippedBlocksWritingMode())
+    result.SetY(layout_box_->LogicalHeight() - result.Y());
+  if (!layout_box_->StyleRef().IsHorizontalWritingMode())
     result = result.TransposedPoint();
   return result;
 }
diff --git a/third_party/blink/renderer/core/layout/shapes/shape_outside_info.h b/third_party/blink/renderer/core/layout/shapes/shape_outside_info.h
index 020af01..84d13b2 100644
--- a/third_party/blink/renderer/core/layout/shapes/shape_outside_info.h
+++ b/third_party/blink/renderer/core/layout/shapes/shape_outside_info.h
@@ -133,8 +133,8 @@
   const Shape& ComputedShape() const;
 
  protected:
-  ShapeOutsideInfo(const LayoutBox& layout_box)
-      : layout_box_(layout_box), is_computing_shape_(false) {}
+  explicit ShapeOutsideInfo(const LayoutBox& layout_box)
+      : layout_box_(&layout_box), is_computing_shape_(false) {}
 
  private:
   static bool IsEnabledFor(const LayoutBox&);
@@ -153,7 +153,7 @@
     return static_info_map;
   }
 
-  const LayoutBox& layout_box_;
+  const LayoutBox* const layout_box_;
   mutable std::unique_ptr<Shape> shape_;
   LayoutSize reference_box_logical_size_;
   LayoutUnit percentage_resolution_inline_size_;
diff --git a/third_party/blink/renderer/core/layout/view_fragmentation_context.cc b/third_party/blink/renderer/core/layout/view_fragmentation_context.cc
index 09c8fca..ccf1334 100644
--- a/third_party/blink/renderer/core/layout/view_fragmentation_context.cc
+++ b/third_party/blink/renderer/core/layout/view_fragmentation_context.cc
@@ -9,18 +9,18 @@
 namespace blink {
 
 bool ViewFragmentationContext::IsFragmentainerLogicalHeightKnown() {
-  DCHECK(view_.PageLogicalHeight());
+  DCHECK(view_->PageLogicalHeight());
   return true;
 }
 
 LayoutUnit ViewFragmentationContext::FragmentainerLogicalHeightAt(LayoutUnit) {
-  DCHECK(view_.PageLogicalHeight());
-  return view_.PageLogicalHeight();
+  DCHECK(view_->PageLogicalHeight());
+  return view_->PageLogicalHeight();
 }
 
 LayoutUnit ViewFragmentationContext::RemainingLogicalHeightAt(
     LayoutUnit block_offset) {
-  LayoutUnit page_logical_height = view_.PageLogicalHeight();
+  LayoutUnit page_logical_height = view_->PageLogicalHeight();
   return page_logical_height - IntMod(block_offset, page_logical_height);
 }
 
diff --git a/third_party/blink/renderer/core/layout/view_fragmentation_context.h b/third_party/blink/renderer/core/layout/view_fragmentation_context.h
index c60c340..a2effb4 100644
--- a/third_party/blink/renderer/core/layout/view_fragmentation_context.h
+++ b/third_party/blink/renderer/core/layout/view_fragmentation_context.h
@@ -13,13 +13,13 @@
 
 class ViewFragmentationContext final : public FragmentationContext {
  public:
-  ViewFragmentationContext(LayoutView& view) : view_(view) {}
+  explicit ViewFragmentationContext(LayoutView& view) : view_(&view) {}
   bool IsFragmentainerLogicalHeightKnown() final;
   LayoutUnit FragmentainerLogicalHeightAt(LayoutUnit block_offset) final;
   LayoutUnit RemainingLogicalHeightAt(LayoutUnit block_offset) final;
 
  private:
-  LayoutView& view_;
+  LayoutView* const view_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
index fb35d8c8..6f01332d 100644
--- a/third_party/blink/renderer/core/loader/document_loader.cc
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -1698,9 +1698,10 @@
   frame_->DomWindow()->GetSecurityContext().SetContentSecurityPolicy(
       content_security_policy_.Get());
   frame_->DomWindow()->GetSecurityContext().ApplySandboxFlags(sandbox_flags);
+  frame_->DomWindow()->GetSecurityContext().SetSecurityOrigin(
+      std::move(security_origin));
 
-  SecurityContextInit security_init(frame_->DomWindow(), security_origin);
-  security_init.CalculateSecureContextMode(frame_.Get());
+  SecurityContextInit security_init(frame_->DomWindow());
   security_init.InitializeOriginTrials(
       response_.HttpHeaderField(http_names::kOriginTrial));
 
diff --git a/third_party/blink/renderer/core/loader/private/prerender_handle.cc b/third_party/blink/renderer/core/loader/private/prerender_handle.cc
index 81d26a8..a853a8c 100644
--- a/third_party/blink/renderer/core/loader/private/prerender_handle.cc
+++ b/third_party/blink/renderer/core/loader/private/prerender_handle.cc
@@ -74,9 +74,7 @@
       prerender_handle_client;
   auto receiver = prerender_handle_client.InitWithNewPipeAndPassReceiver();
 
-  HeapMojoRemote<mojom::blink::PrerenderHandle,
-                 HeapMojoWrapperMode::kForceWithoutContextObserver>
-      remote_handle(context);
+  HeapMojoRemote<mojom::blink::PrerenderHandle> remote_handle(context);
   prerender_processor->AddPrerender(
       std::move(attributes), std::move(prerender_handle_client),
       remote_handle.BindNewPipeAndPassReceiver(
@@ -92,9 +90,7 @@
     ExecutionContext* context,
     PrerenderClient* client,
     const KURL& url,
-    HeapMojoRemote<mojom::blink::PrerenderHandle,
-                   HeapMojoWrapperMode::kForceWithoutContextObserver>
-        remote_handle,
+    HeapMojoRemote<mojom::blink::PrerenderHandle> remote_handle,
     mojo::PendingReceiver<mojom::blink::PrerenderHandleClient> receiver)
     : ExecutionContextLifecycleObserver(context),
       url_(url),
diff --git a/third_party/blink/renderer/core/loader/private/prerender_handle.h b/third_party/blink/renderer/core/loader/private/prerender_handle.h
index 96b7a72..1420f38c 100644
--- a/third_party/blink/renderer/core/loader/private/prerender_handle.h
+++ b/third_party/blink/renderer/core/loader/private/prerender_handle.h
@@ -39,7 +39,6 @@
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
 #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
-#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 
 namespace blink {
@@ -61,14 +60,12 @@
                                  unsigned prerender_rel_types);
 
   using PassKey = util::PassKey<PrerenderHandle>;
-  PrerenderHandle(
-      PassKey,
-      ExecutionContext*,
-      PrerenderClient*,
-      const KURL&,
-      HeapMojoRemote<mojom::blink::PrerenderHandle,
-                     HeapMojoWrapperMode::kForceWithoutContextObserver>,
-      mojo::PendingReceiver<mojom::blink::PrerenderHandleClient>);
+  PrerenderHandle(PassKey,
+                  ExecutionContext*,
+                  PrerenderClient*,
+                  const KURL&,
+                  HeapMojoRemote<mojom::blink::PrerenderHandle>,
+                  mojo::PendingReceiver<mojom::blink::PrerenderHandleClient>);
   ~PrerenderHandle() override;
   void Dispose();
 
@@ -91,12 +88,8 @@
 
   KURL url_;
   WeakMember<PrerenderClient> client_;
-  HeapMojoRemote<mojom::blink::PrerenderHandle,
-                 HeapMojoWrapperMode::kForceWithoutContextObserver>
-      remote_handle_;
-  HeapMojoReceiver<mojom::blink::PrerenderHandleClient,
-                   PrerenderHandle,
-                   HeapMojoWrapperMode::kForceWithoutContextObserver>
+  HeapMojoRemote<mojom::blink::PrerenderHandle> remote_handle_;
+  HeapMojoReceiver<mojom::blink::PrerenderHandleClient, PrerenderHandle>
       receiver_;
 
   DISALLOW_COPY_AND_ASSIGN(PrerenderHandle);
diff --git a/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc b/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc
index 66c6b68..37494a2 100644
--- a/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc
+++ b/third_party/blink/renderer/core/origin_trials/origin_trial_context_test.cc
@@ -99,10 +99,6 @@
     scoped_refptr<SecurityOrigin> page_origin =
         SecurityOrigin::Create(page_url);
     execution_context_->GetSecurityContext().SetSecurityOrigin(page_origin);
-    execution_context_->GetSecurityContext().SetSecureContextModeForTesting(
-        SecurityOrigin::IsSecure(page_url)
-            ? SecureContextMode::kSecureContext
-            : SecureContextMode::kInsecureContext);
   }
 
   bool IsFeatureEnabled(const String& origin, OriginTrialFeature feature) {
diff --git a/third_party/blink/renderer/core/paint/background_image_geometry.cc b/third_party/blink/renderer/core/paint/background_image_geometry.cc
index ccc8d73..ff5f696 100644
--- a/third_party/blink/renderer/core/paint/background_image_geometry.cc
+++ b/third_party/blink/renderer/core/paint/background_image_geometry.cc
@@ -422,7 +422,7 @@
 BackgroundImageGeometry::BackgroundImageGeometry(
     const LayoutView& view,
     const PhysicalOffset& element_positioning_area_offset)
-    : box_(view), positioning_box_(view.RootBox()), painting_view_(true) {
+    : box_(&view), positioning_box_(&view.RootBox()), painting_view_(true) {
   // The background of the box generated by the root element covers the
   // entire canvas and will be painted by the view object, but the we should
   // still use the root element box for positioning.
@@ -433,7 +433,7 @@
 
 BackgroundImageGeometry::BackgroundImageGeometry(
     const LayoutBoxModelObject& obj)
-    : box_(obj), positioning_box_(obj) {
+    : box_(&obj), positioning_box_(&obj) {
   // Specialized constructor should be used for LayoutView.
   DCHECK(!IsA<LayoutView>(obj));
 }
@@ -441,10 +441,10 @@
 BackgroundImageGeometry::BackgroundImageGeometry(
     const LayoutTableCell& cell,
     const LayoutObject* background_object)
-    : box_(cell),
+    : box_(&cell),
       positioning_box_(background_object && !background_object->IsTableCell()
-                           ? ToLayoutBoxModelObject(*background_object)
-                           : cell),
+                           ? &ToLayoutBoxModelObject(*background_object)
+                           : &cell),
       painting_table_cell_(true) {
   cell_using_container_background_ =
       background_object && !background_object->IsTableCell();
@@ -466,9 +466,9 @@
     case EFillBox::kContent:
       // If the PaddingOutsets are zero then this is equivalent to
       // kPadding and we should apply the snapping logic.
-      unsnapped_dest_adjust = positioning_box_.PaddingOutsets();
+      unsnapped_dest_adjust = positioning_box_->PaddingOutsets();
       if (!unsnapped_dest_adjust.IsZero()) {
-        unsnapped_dest_adjust += positioning_box_.BorderBoxOutsets();
+        unsnapped_dest_adjust += positioning_box_->BorderBoxOutsets();
 
         // We're not trying to match a border position, so don't snap.
         snapped_dest_adjust = unsnapped_dest_adjust;
@@ -476,7 +476,7 @@
       }
       FALLTHROUGH;
     case EFillBox::kPadding:
-      unsnapped_dest_adjust = positioning_box_.BorderBoxOutsets();
+      unsnapped_dest_adjust = positioning_box_->BorderBoxOutsets();
       if (disallow_border_derived_adjustment) {
         // Nothing to drive snapping behavior, so don't snap.
         snapped_dest_adjust = unsnapped_dest_adjust;
@@ -488,7 +488,7 @@
         // move toward the border.
         FloatRect inner_border_rect =
             RoundedBorderGeometry::PixelSnappedRoundedInnerBorder(
-                positioning_box_.StyleRef(), unsnapped_positioning_area)
+                positioning_box_->StyleRef(), unsnapped_positioning_area)
                 .Rect();
         snapped_dest_adjust.SetLeft(LayoutUnit(inner_border_rect.X()) -
                                     unsnapped_dest_rect_.X());
@@ -522,12 +522,12 @@
       // rounds down. We should FromFloatFloor or FromFloatCeil to
       // move toward the border.
       BorderEdge edges[4];
-      positioning_box_.StyleRef().GetBorderEdgeInfo(edges);
+      positioning_box_->StyleRef().GetBorderEdgeInfo(edges);
       FloatRect inner_border_rect =
           RoundedBorderGeometry::PixelSnappedRoundedInnerBorder(
-              positioning_box_.StyleRef(), unsnapped_positioning_area)
+              positioning_box_->StyleRef(), unsnapped_positioning_area)
               .Rect();
-      LayoutRectOutsets box_outsets = positioning_box_.BorderBoxOutsets();
+      LayoutRectOutsets box_outsets = positioning_box_->BorderBoxOutsets();
       if (edges[static_cast<unsigned>(BoxSide::kTop)].ObscuresBackground()) {
         snapped_dest_adjust.SetTop(LayoutUnit(inner_border_rect.Y()) -
                                    unsnapped_dest_rect_.Y());
@@ -565,9 +565,9 @@
     case EFillBox::kContent:
       // If the PaddingOutsets are zero then this is equivalent to
       // kPadding and we should apply the snapping logic.
-      unsnapped_box_outset = positioning_box_.PaddingOutsets();
+      unsnapped_box_outset = positioning_box_->PaddingOutsets();
       if (!unsnapped_box_outset.IsZero()) {
-        unsnapped_box_outset += positioning_box_.BorderBoxOutsets();
+        unsnapped_box_outset += positioning_box_->BorderBoxOutsets();
 
         // We're not trying to match a border position, so don't snap.
         snapped_box_outset = unsnapped_box_outset;
@@ -575,7 +575,7 @@
       }
       FALLTHROUGH;
     case EFillBox::kPadding:
-      unsnapped_box_outset = positioning_box_.BorderBoxOutsets();
+      unsnapped_box_outset = positioning_box_->BorderBoxOutsets();
       if (disallow_border_derived_adjustment) {
         snapped_box_outset = unsnapped_box_outset;
       } else {
@@ -587,7 +587,7 @@
         // zoom).
         FloatRect inner_border_rect =
             RoundedBorderGeometry::PixelSnappedRoundedInnerBorder(
-                positioning_box_.StyleRef(), unsnapped_positioning_area)
+                positioning_box_->StyleRef(), unsnapped_positioning_area)
                 .Rect();
         snapped_box_outset.SetLeft(LayoutUnit(inner_border_rect.X()) -
                                    unsnapped_positioning_area.X());
@@ -622,7 +622,7 @@
     // No snapping for fixed attachment.
     SetHasNonLocalGeometry();
     unsnapped_positioning_area =
-        FixedAttachmentPositioningArea(box_, container, flags);
+        FixedAttachmentPositioningArea(*box_, container, flags);
     unsnapped_dest_rect_ = snapped_dest_rect_ = snapped_positioning_area =
         unsnapped_positioning_area;
   } else {
@@ -658,8 +658,8 @@
         !ShouldPaintSelfBlockBackground(paint_phase) ||
         fill_layer.Composite() != CompositeOperator::kCompositeSourceOver ||
         painting_view_ || painting_table_cell_ ||
-        positioning_box_.StyleRef().BorderImage().GetImage() ||
-        positioning_box_.StyleRef().BorderCollapse() ==
+        positioning_box_->StyleRef().BorderImage().GetImage() ||
+        positioning_box_->StyleRef().BorderCollapse() ==
             EBorderCollapse::kCollapse;
 
     // Compute all the outsets we need to apply to the rectangles. These
@@ -687,7 +687,7 @@
     unsnapped_positioning_area.Contract(unsnapped_box_outset);
 
     // Offset of the positioning area from the corner of the
-    // positioning_box_.
+    // positioning_box_->
     // TODO(schenney): Could we enable dest adjust for collapsed
     // borders if we computed this based on the actual offset between
     // the rects?
@@ -715,10 +715,10 @@
                                            ? snapped_positioning_area_size
                                            : unsnapped_positioning_area_size;
   PhysicalSize image_intrinsic_size = PhysicalSize::FromFloatSizeFloor(
-      image->ImageSize(positioning_box_.GetDocument(),
-                       positioning_box_.StyleRef().EffectiveZoom(),
+      image->ImageSize(positioning_box_->GetDocument(),
+                       positioning_box_->StyleRef().EffectiveZoom(),
                        FloatSize(positioning_area_size),
-                       LayoutObject::ShouldRespectImageOrientation(&box_)));
+                       LayoutObject::ShouldRespectImageOrientation(box_)));
   switch (type) {
     case EFillSizeType::kSizeLength: {
       tile_size_ = positioning_area_size;
@@ -1006,22 +1006,22 @@
 }
 
 const ImageResourceObserver& BackgroundImageGeometry::ImageClient() const {
-  return painting_view_ ? box_ : positioning_box_;
+  return *(painting_view_ ? box_ : positioning_box_);
 }
 
 const Document& BackgroundImageGeometry::ImageDocument() const {
-  return box_.GetDocument();
+  return box_->GetDocument();
 }
 
 const ComputedStyle& BackgroundImageGeometry::ImageStyle() const {
   const bool use_style_from_positioning_box =
       painting_view_ || cell_using_container_background_;
-  return (use_style_from_positioning_box ? positioning_box_ : box_).StyleRef();
+  return (use_style_from_positioning_box ? positioning_box_ : box_)->StyleRef();
 }
 
 InterpolationQuality BackgroundImageGeometry::ImageInterpolationQuality()
     const {
-  return box_.StyleRef().GetInterpolationQuality();
+  return box_->StyleRef().GetInterpolationQuality();
 }
 
 PhysicalOffset BackgroundImageGeometry::OffsetInBackground(
diff --git a/third_party/blink/renderer/core/paint/background_image_geometry.h b/third_party/blink/renderer/core/paint/background_image_geometry.h
index a02b998..fe008ef 100644
--- a/third_party/blink/renderer/core/paint/background_image_geometry.h
+++ b/third_party/blink/renderer/core/paint/background_image_geometry.h
@@ -158,13 +158,13 @@
   // |box_| is the source for the Document. In most cases it also provides the
   // background properties (see |positioning_box_| for exceptions.) It's also
   // the image client unless painting the view background.
-  const LayoutBoxModelObject& box_;
+  const LayoutBoxModelObject* const box_;
 
   // The positioning box is the source of geometric information for positioning
   // and sizing the background. It also provides the background properties if
   // painting the view background or a table-cell using its container's
   // (row's/column's) background.
-  const LayoutBoxModelObject& positioning_box_;
+  const LayoutBoxModelObject* positioning_box_;
 
   // When painting table cells or the view, the positioning area
   // differs from the requested paint rect.
diff --git a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc
index 74254186..469bc04 100644
--- a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc
+++ b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.cc
@@ -64,7 +64,7 @@
 namespace blink {
 
 PaintLayerCompositor::PaintLayerCompositor(LayoutView& layout_view)
-    : layout_view_(layout_view) {
+    : layout_view_(&layout_view) {
   DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
 }
 
@@ -78,7 +78,7 @@
 bool PaintLayerCompositor::InCompositingMode() const {
   // FIXME: This should assert that lifecycle is >= CompositingClean since
   // the last step of updateIfNeeded can set this bit to false.
-  DCHECK(layout_view_.Layer()->IsAllowedToQueryCompositingState());
+  DCHECK(layout_view_->Layer()->IsAllowedToQueryCompositingState());
   return compositing_;
 }
 
@@ -108,11 +108,11 @@
 
 void PaintLayerCompositor::UpdateCompositingInputsIfNeededRecursiveInternal(
     DocumentLifecycle::LifecycleState target_state) {
-  if (layout_view_.GetFrameView()->ShouldThrottleRendering())
+  if (layout_view_->GetFrameView()->ShouldThrottleRendering())
     return;
 
   for (Frame* child =
-           layout_view_.GetFrameView()->GetFrame().Tree().FirstChild();
+           layout_view_->GetFrameView()->GetFrame().Tree().FirstChild();
        child; child = child->Tree().NextSibling()) {
     auto* local_frame = DynamicTo<LocalFrame>(child);
     if (!local_frame)
@@ -132,7 +132,7 @@
   ScriptForbiddenScope forbid_script;
 
 #if DCHECK_IS_ON()
-  LocalFrameView* view = layout_view_.GetFrameView();
+  LocalFrameView* view = layout_view_->GetFrameView();
   view->SetIsUpdatingDescendantDependentFlags(true);
 #endif
   {
@@ -143,7 +143,7 @@
   view->SetIsUpdatingDescendantDependentFlags(false);
 #endif
 
-  layout_view_.CommitPendingSelection();
+  layout_view_->CommitPendingSelection();
 
   Lifecycle().AdvanceTo(DocumentLifecycle::kInCompositingInputsUpdate);
 
@@ -161,10 +161,10 @@
   Lifecycle().AdvanceTo(DocumentLifecycle::kCompositingInputsClean);
 
 #if DCHECK_IS_ON()
-  if (!layout_view_.GetDocument()
+  if (!layout_view_->GetDocument()
            .GetSettings()
            ->GetAcceleratedCompositingEnabled()) {
-    DCHECK(!layout_view_.GetDocument()
+    DCHECK(!layout_view_->GetDocument()
                 .GetSettings()
                 ->GetAcceleratedCompositingEnabled());
   }
@@ -200,17 +200,17 @@
 void PaintLayerCompositor::UpdateIfNeededRecursiveInternal(
     DocumentLifecycle::LifecycleState target_state,
     CompositingReasonsStats& compositing_reasons_stats) {
-  if (layout_view_.GetFrameView()->ShouldThrottleRendering())
+  if (layout_view_->GetFrameView()->ShouldThrottleRendering())
     return;
 
   if (target_state == DocumentLifecycle::kCompositingInputsClean)
     return;
 
-  LocalFrameView* view = layout_view_.GetFrameView();
+  LocalFrameView* view = layout_view_->GetFrameView();
   view->ResetNeedsForcedCompositingUpdate();
 
   for (Frame* child =
-           layout_view_.GetFrameView()->GetFrame().Tree().FirstChild();
+           layout_view_->GetFrameView()->GetFrame().Tree().FirstChild();
        child; child = child->Tree().NextSibling()) {
     auto* local_frame = DynamicTo<LocalFrame>(child);
     if (!local_frame)
@@ -231,7 +231,7 @@
   TRACE_EVENT0("blink,benchmark",
                "PaintLayerCompositor::updateIfNeededRecursive");
 
-  DCHECK(!layout_view_.NeedsLayout());
+  DCHECK(!layout_view_->NeedsLayout());
 
   ScriptForbiddenScope forbid_script;
 
@@ -241,7 +241,7 @@
   DCHECK_EQ(Lifecycle().GetState(), DocumentLifecycle::kCompositingClean);
   AssertNoUnresolvedDirtyBits();
   for (Frame* child =
-           layout_view_.GetFrameView()->GetFrame().Tree().FirstChild();
+           layout_view_->GetFrameView()->GetFrame().Tree().FirstChild();
        child; child = child->Tree().NextSibling()) {
     auto* local_frame = DynamicTo<LocalFrame>(child);
     if (!local_frame)
@@ -267,9 +267,9 @@
   DCHECK_NE(update_type, kCompositingUpdateNone);
   pending_update_type_ = std::max(pending_update_type_, update_type);
   if (Page* page = GetPage())
-    page->Animator().ScheduleVisualUpdate(layout_view_.GetFrame());
+    page->Animator().ScheduleVisualUpdate(layout_view_->GetFrame());
 
-  if (layout_view_.DocumentBeingDestroyed())
+  if (layout_view_->DocumentBeingDestroyed())
     return;
 
   Lifecycle().EnsureStateAtMost(DocumentLifecycle::kLayoutClean);
@@ -295,7 +295,7 @@
   CompositingUpdateType update_type = pending_update_type_;
   pending_update_type_ = kCompositingUpdateNone;
 
-  if (!layout_view_.GetDocument()
+  if (!layout_view_->GetDocument()
            .GetSettings()
            ->GetAcceleratedCompositingEnabled() ||
       update_type == kCompositingUpdateNone) {
@@ -308,7 +308,7 @@
   Vector<PaintLayer*> layers_needing_paint_invalidation;
 
   if (update_type >= kCompositingUpdateAfterCompositingInputChange) {
-    CompositingRequirementsUpdater(layout_view_)
+    CompositingRequirementsUpdater(*layout_view_)
         .Update(update_root, compositing_reasons_stats);
 
     CompositingLayerAssigner layer_assigner(this);
@@ -318,7 +318,7 @@
       update_type = std::max(update_type, kCompositingUpdateRebuildTree);
       if (ScrollingCoordinator* scrolling_coordinator =
               GetScrollingCoordinator()) {
-        LocalFrameView* frame_view = layout_view_.GetFrameView();
+        LocalFrameView* frame_view = layout_view_->GetFrameView();
         scrolling_coordinator->NotifyGeometryChanged(frame_view);
       }
     }
@@ -433,11 +433,11 @@
 
       // At this time, the ScrollingCoordinator only supports the top-level
       // frame.
-      if (layer->IsRootLayer() && layout_view_.GetFrame()->IsLocalRoot()) {
+      if (layer->IsRootLayer() && layout_view_->GetFrame()->IsLocalRoot()) {
         if (ScrollingCoordinator* scrolling_coordinator =
                 GetScrollingCoordinator()) {
           scrolling_coordinator->FrameViewRootLayerDidChange(
-              layout_view_.GetFrameView());
+              layout_view_->GetFrameView());
         }
       }
       break;
@@ -469,7 +469,7 @@
     PaintLayer* layer) {
   // If the layoutObject is not attached yet, no need to issue paint
   // invalidations.
-  if (&layer->GetLayoutObject() != &layout_view_ &&
+  if (&layer->GetLayoutObject() != layout_view_ &&
       !layer->GetLayoutObject().Parent())
     return;
 
@@ -515,7 +515,7 @@
 }
 
 PaintLayer* PaintLayerCompositor::RootLayer() const {
-  return layout_view_.Layer();
+  return layout_view_->Layer();
 }
 
 GraphicsLayer* PaintLayerCompositor::RootGraphicsLayer() const {
@@ -525,14 +525,14 @@
 }
 
 GraphicsLayer* PaintLayerCompositor::PaintRootGraphicsLayer() const {
-  if (layout_view_.GetDocument().GetPage()->GetChromeClient().IsPopup() ||
+  if (layout_view_->GetDocument().GetPage()->GetChromeClient().IsPopup() ||
       !IsMainFrame())
     return RootGraphicsLayer();
 
   // Start from the full screen overlay layer if exists. Other layers will be
   // skipped during painting.
   if (PaintLayer* layer =
-          layout_view_.GetFrameView()->GetFullScreenOverlayLayer()) {
+          layout_view_->GetFrameView()->GetFullScreenOverlayLayer()) {
     if (layer->HasCompositedLayerMapping())
       return layer->GetCompositedLayerMapping()->MainGraphicsLayer();
   }
@@ -562,7 +562,7 @@
   bool frame_is_visible =
       !frame_view->ShouldThrottleRendering() && !layer->SubtreeIsInvisible();
 
-  return layout_view_.GetDocument()
+  return layout_view_->GetDocument()
              .GetSettings()
              ->GetAcceleratedCompositingEnabled() &&
          (has_compositor_animation || frame_is_visible) &&
@@ -597,7 +597,7 @@
 void PaintLayerCompositor::UpdateTrackingRasterInvalidations() {
 #if DCHECK_IS_ON()
   DCHECK(Lifecycle().GetState() == DocumentLifecycle::kPaintClean ||
-         layout_view_.GetFrameView()->ShouldThrottleRendering());
+         layout_view_->GetFrameView()->ShouldThrottleRendering());
 #endif
 
   if (GraphicsLayer* root_layer = PaintRootGraphicsLayer())
@@ -606,7 +606,7 @@
 
 void PaintLayerCompositor::SetOwnerNeedsCompositingInputsUpdate() {
   if (HTMLFrameOwnerElement* owner_element =
-          layout_view_.GetDocument().LocalOwner()) {
+          layout_view_->GetDocument().LocalOwner()) {
     LayoutBoxModelObject* layout_object =
         owner_element->GetLayoutBoxModelObject();
     if (!layout_object || !layout_object->HasLayer())
@@ -623,15 +623,15 @@
 }
 
 Page* PaintLayerCompositor::GetPage() const {
-  return layout_view_.GetFrameView()->GetFrame().GetPage();
+  return layout_view_->GetFrameView()->GetFrame().GetPage();
 }
 
 DocumentLifecycle& PaintLayerCompositor::Lifecycle() const {
-  return layout_view_.GetDocument().Lifecycle();
+  return layout_view_->GetDocument().Lifecycle();
 }
 
 bool PaintLayerCompositor::IsMainFrame() const {
-  return layout_view_.GetFrame()->IsMainFrame();
+  return layout_view_->GetFrame()->IsMainFrame();
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h
index d297ad87..29f326d4 100644
--- a/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h
+++ b/third_party/blink/renderer/core/paint/compositing/paint_layer_compositor.h
@@ -180,7 +180,7 @@
 
   bool IsMainFrame() const;
 
-  LayoutView& layout_view_;
+  LayoutView* const layout_view_;
 
   bool compositing_ = false;
   bool root_layer_attachment_dirty_ = false;
diff --git a/third_party/blink/renderer/core/paint/find_paint_offset_and_visual_rect_needing_update.h b/third_party/blink/renderer/core/paint/find_paint_offset_and_visual_rect_needing_update.h
index 981fe05..c74bb9b 100644
--- a/third_party/blink/renderer/core/paint/find_paint_offset_and_visual_rect_needing_update.h
+++ b/third_party/blink/renderer/core/paint/find_paint_offset_and_visual_rect_needing_update.h
@@ -72,6 +72,8 @@
 };
 
 class FindVisualRectNeedingUpdateScopeBase {
+  STACK_ALLOCATED();
+
  protected:
   FindVisualRectNeedingUpdateScopeBase(const LayoutObject& object,
                                        const PaintInvalidatorContext& context,
@@ -129,6 +131,8 @@
 // For updates of visual rects (e.g. of scroll controls, caret, selection,etc.)
 // contained by an object.
 class FindVisualRectNeedingUpdateScope : FindVisualRectNeedingUpdateScopeBase {
+  STACK_ALLOCATED();
+
  public:
   FindVisualRectNeedingUpdateScope(const LayoutObject& object,
                                    const PaintInvalidatorContext& context,
@@ -148,6 +152,8 @@
 // For updates of object visual rect and location.
 class FindObjectVisualRectNeedingUpdateScope
     : FindVisualRectNeedingUpdateScopeBase {
+  STACK_ALLOCATED();
+
  public:
   FindObjectVisualRectNeedingUpdateScope(const LayoutObject& object,
                                          const FragmentData& fragment_data,
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc
index 2beb306..6e30524e 100644
--- a/third_party/blink/renderer/core/paint/paint_layer.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -188,7 +188,7 @@
 #if DCHECK_IS_ON()
       layer_list_mutation_allowed_(true),
 #endif
-      layout_object_(layout_object),
+      layout_object_(&layout_object),
       parent_(nullptr),
       previous_(nullptr),
       next_(nullptr),
@@ -254,7 +254,7 @@
 }
 
 IntRect PaintLayer::VisualRect() const {
-  return layout_object_.FragmentsVisualRectBoundingBox();
+  return layout_object_->FragmentsVisualRectBoundingBox();
 }
 
 PaintLayerCompositor* PaintLayer::Compositor() const {
@@ -594,7 +594,7 @@
     DescendantDependentFlagsUpdateFlag flag) {
 #if DCHECK_IS_ON()
   DCHECK(flag == DoesNotNeedDescendantDependentUpdate ||
-         !layout_object_.GetDocument()
+         !layout_object_->GetDocument()
               .View()
               ->IsUpdatingDescendantDependentFlags());
 #endif
@@ -738,7 +738,7 @@
     // pretend that invisible LayoutObjects have 0x0 rects. Changing
     // visibility therefore changes our rect and we need to visit
     // this LayoutObject during the PrePaintTreeWalk.
-    layout_object_.SetShouldCheckForPaintInvalidation();
+    layout_object_->SetShouldCheckForPaintInvalidation();
   }
 
   Update3DTransformedDescendantStatus();
@@ -1331,7 +1331,7 @@
     // layers to be destructed and detach from layer tree immediately. Layers
     // could have dangling scroll/clip parent if compositing update were
     // omitted.
-    if (LocalFrameView* frame_view = layout_object_.GetDocument().View())
+    if (LocalFrameView* frame_view = layout_object_->GetDocument().View())
       frame_view->SetNeedsForcedCompositingUpdate();
 
     // We need the current compositing status.
@@ -1371,7 +1371,7 @@
 
   // Remove us from the parent.
   parent_->RemoveChild(this);
-  layout_object_.DestroyLayer();
+  layout_object_->DestroyLayer();
 }
 
 void PaintLayer::InsertOnlyThisLayerAfterStyleChange() {
@@ -3126,14 +3126,14 @@
   // Layers even when the non-transparent Layers are already a
   // stacking context.
   if (diff.OpacityChanged() &&
-      layout_object_.StyleRef().HasOpacity() != old_style->HasOpacity())
+      layout_object_->StyleRef().HasOpacity() != old_style->HasOpacity())
     return false;
 
   // Changes in pointer-events affect hit test visibility of the scrollable
   // area and its |m_scrollsOverflow| value which determines if the layer
   // requires composited scrolling or not.
   if (scrollable_area_ &&
-      layout_object_.StyleRef().PointerEvents() != old_style->PointerEvents())
+      layout_object_->StyleRef().PointerEvents() != old_style->PointerEvents())
     return false;
 
   UpdateTransform(old_style, GetLayoutObject().StyleRef());
diff --git a/third_party/blink/renderer/core/paint/paint_layer.h b/third_party/blink/renderer/core/paint/paint_layer.h
index 9924d6d..3e11f92 100644
--- a/third_party/blink/renderer/core/paint/paint_layer.h
+++ b/third_party/blink/renderer/core/paint/paint_layer.h
@@ -252,9 +252,9 @@
   DOMNodeId OwnerNodeId() const final;
   IntRect VisualRect() const final;
 
-  LayoutBoxModelObject& GetLayoutObject() const { return layout_object_; }
+  LayoutBoxModelObject& GetLayoutObject() const { return *layout_object_; }
   LayoutBox* GetLayoutBox() const {
-    return layout_object_.IsBox() ? &ToLayoutBox(layout_object_) : nullptr;
+    return layout_object_->IsBox() ? ToLayoutBox(layout_object_) : nullptr;
   }
   PaintLayer* Parent() const { return parent_; }
   PaintLayer* PreviousSibling() const { return previous_; }
@@ -320,8 +320,8 @@
   // Location() is not the correct paint offset. It's also incorrect in flipped
   // blocks writing mode.
   IntSize PixelSnappedSize() const {
-    LayoutPoint location = layout_object_.IsBox()
-                               ? ToLayoutBox(layout_object_).Location()
+    LayoutPoint location = layout_object_->IsBox()
+                               ? ToLayoutBox(layout_object_)->Location()
                                : LayoutPoint();
     return PixelSnappedIntSize(Size(), location);
   }
@@ -1384,7 +1384,7 @@
   mutable unsigned layer_list_mutation_allowed_ : 1;
 #endif
 
-  LayoutBoxModelObject& layout_object_;
+  LayoutBoxModelObject* const layout_object_;
 
   PaintLayer* parent_;
   PaintLayer* previous_;
diff --git a/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.cc b/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.cc
index 69789c9..4bb932d 100644
--- a/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.cc
+++ b/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.cc
@@ -38,6 +38,13 @@
   return execution_context_->GetReferrerPolicy();
 }
 
+base::Optional<network::mojom::blink::ReferrerPolicy>
+FetchClientSettingsObjectImpl::
+    GetReferrerPolicyDisregardingMetaTagsContainingLists() const {
+  DCHECK(execution_context_->IsContextThread());
+  return execution_context_->ReferrerPolicyButForMetaTagsWithListsOfPolicies();
+}
+
 const String FetchClientSettingsObjectImpl::GetOutgoingReferrer() const {
   DCHECK(execution_context_->IsContextThread());
   return execution_context_->OutgoingReferrer();
diff --git a/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h b/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h
index 6707c9b..a744576 100644
--- a/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h
+++ b/third_party/blink/renderer/core/script/fetch_client_settings_object_impl.h
@@ -36,6 +36,9 @@
   const KURL& BaseUrl() const override;
   const SecurityOrigin* GetSecurityOrigin() const override;
   network::mojom::ReferrerPolicy GetReferrerPolicy() const override;
+  base::Optional<network::mojom::blink::ReferrerPolicy>
+  GetReferrerPolicyDisregardingMetaTagsContainingLists() const override;
+
   const String GetOutgoingReferrer() const override;
 
   HttpsState GetHttpsState() const override;
diff --git a/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.cc b/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.cc
index cbd9820..c278076 100644
--- a/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.cc
+++ b/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.cc
@@ -16,13 +16,27 @@
 
 namespace {
 
+static const V8PrivateProperty::SymbolKey
+    kByteLengthQueuingStrategySizeFunction;
+
 class ByteLengthQueuingStrategySizeFunction final : public ScriptFunction {
  public:
   static v8::Local<v8::Function> CreateFunction(ScriptState* script_state) {
     ByteLengthQueuingStrategySizeFunction* self =
         MakeGarbageCollected<ByteLengthQueuingStrategySizeFunction>(
             script_state);
-    return self->BindToV8Function();
+
+    // https://streams.spec.whatwg.org/#byte-length-queuing-strategy-size-function
+
+    // 2. Let F be ! CreateBuiltinFunction(steps, « », globalObject’s relevant
+    //    Realm).
+    // 4. Perform ! SetFunctionLength(F, 1).
+    v8::Local<v8::Function> function = self->BindToV8Function(/*length=*/1);
+
+    // 3. Perform ! SetFunctionName(F, "size").
+    function->SetName(V8String(script_state->GetIsolate(), "size"));
+
+    return function;
   }
 
   explicit ByteLengthQueuingStrategySizeFunction(ScriptState* script_state)
@@ -40,8 +54,10 @@
       chunk = args[0];
     }
 
-    // https://streams.spec.whatwg.org/#blqs-size
-    // 1. Return ? GetV(chunk, "byteLength").
+    // https://streams.spec.whatwg.org/#byte-length-queuing-strategy-size-function
+
+    // 1. Let steps be the following steps, given chunk:
+    //   1. Return ? GetV(chunk, "byteLength").
 
     // https://tc39.es/ecma262/#sec-getv
     // 1. Assert: IsPropertyKey(P) is true.
@@ -74,28 +90,18 @@
 ByteLengthQueuingStrategy::ByteLengthQueuingStrategy(
     ScriptState* script_state,
     const QueuingStrategyInit* init)
-    : high_water_mark_(script_state->GetIsolate(),
-                       HighWaterMarkOrUndefined(script_state, init)) {}
+    : high_water_mark_(init->highWaterMark()) {}
 
 ByteLengthQueuingStrategy::~ByteLengthQueuingStrategy() = default;
 
-ScriptValue ByteLengthQueuingStrategy::highWaterMark(
-    ScriptState* script_state) const {
-  return ScriptValue(script_state->GetIsolate(),
-                     high_water_mark_.NewLocal(script_state->GetIsolate()));
-}
-
 ScriptValue ByteLengthQueuingStrategy::size(ScriptState* script_state) const {
-  // We don't cache the result because normally this method will only be called
-  // once anyway.
-  return ScriptValue(
-      script_state->GetIsolate(),
-      ByteLengthQueuingStrategySizeFunction::CreateFunction(script_state));
-}
-
-void ByteLengthQueuingStrategy::Trace(Visitor* visitor) const {
-  visitor->Trace(high_water_mark_);
-  ScriptWrappable::Trace(visitor);
+  // https://streams.spec.whatwg.org/#byte-length-queuing-strategy-size-function
+  // 5. Set globalObject’s byte length queuing strategy size function to a
+  //    Function that represents a reference to F, with callback context equal
+  //    to globalObject’s relevant settings object.
+  return GetCachedSizeFunction(
+      script_state, kByteLengthQueuingStrategySizeFunction,
+      &ByteLengthQueuingStrategySizeFunction::CreateFunction);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.h b/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.h
index 620b5a88..896b83c 100644
--- a/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.h
+++ b/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.h
@@ -14,7 +14,6 @@
 class QueuingStrategyInit;
 class ScriptState;
 class ScriptValue;
-class Visitor;
 
 // https://streams.spec.whatwg.org/#blqs-class
 class ByteLengthQueuingStrategy final : public ScriptWrappable {
@@ -27,13 +26,11 @@
   ByteLengthQueuingStrategy(ScriptState*, const QueuingStrategyInit*);
   ~ByteLengthQueuingStrategy() override;
 
-  ScriptValue highWaterMark(ScriptState*) const;
+  double highWaterMark() const { return high_water_mark_; }
   ScriptValue size(ScriptState*) const;
 
-  void Trace(Visitor*) const override;
-
  private:
-  const TraceWrapperV8Reference<v8::Value> high_water_mark_;
+  const double high_water_mark_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.idl b/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.idl
index ac23897..5dec69a 100644
--- a/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.idl
+++ b/third_party/blink/renderer/core/streams/byte_length_queuing_strategy.idl
@@ -7,9 +7,9 @@
 [
     Exposed=(Window,Worker,Worklet)
 ] interface ByteLengthQueuingStrategy {
-    [CallWith=ScriptState, MeasureAs=ByteLengthQueuingStrategyConstructor] constructor([PermissiveDictionaryConversion] QueuingStrategyInit init);
-    [CallWith=ScriptState] readonly attribute any highWaterMark;
+    [CallWith=ScriptState, MeasureAs=ByteLengthQueuingStrategyConstructor] constructor(QueuingStrategyInit init);
+    readonly attribute unrestricted double highWaterMark;
 
-    // size is an accessor that returns a function.
+    // The standard specifies "Function" but the IDL compiler doesn't like it.
     [CallWith=ScriptState] readonly attribute any size;
 };
diff --git a/third_party/blink/renderer/core/streams/count_queuing_strategy.cc b/third_party/blink/renderer/core/streams/count_queuing_strategy.cc
index 4bd19c9..bfd6d1f 100644
--- a/third_party/blink/renderer/core/streams/count_queuing_strategy.cc
+++ b/third_party/blink/renderer/core/streams/count_queuing_strategy.cc
@@ -15,12 +15,24 @@
 
 namespace {
 
+static const V8PrivateProperty::SymbolKey kCountQueuingStrategySizeFunction;
+
 class CountQueuingStrategySizeFunction final : public ScriptFunction {
  public:
   static v8::Local<v8::Function> CreateFunction(ScriptState* script_state) {
     CountQueuingStrategySizeFunction* self =
         MakeGarbageCollected<CountQueuingStrategySizeFunction>(script_state);
-    return self->BindToV8Function();
+
+    // https://streams.spec.whatwg.org/#count-queuing-strategy-size-function
+    // 2. Let F be ! CreateBuiltinFunction(steps, « », globalObject’s relevant
+    //    Realm).
+    // 4. Perform ! SetFunctionLength(F, 0).
+    v8::Local<v8::Function> function = self->BindToV8Function(/*length=*/0);
+
+    // 3. Perform ! SetFunctionName(F, "size").
+    function->SetName(V8String(script_state->GetIsolate(), "size"));
+
+    return function;
   }
 
   explicit CountQueuingStrategySizeFunction(ScriptState* script_state)
@@ -28,8 +40,9 @@
 
  private:
   void CallRaw(const v8::FunctionCallbackInfo<v8::Value>& args) override {
-    // https://streams.spec.whatwg.org/#cqs-size
-    // 1. Return 1.
+    // https://streams.spec.whatwg.org/#count-queuing-strategy-size-function
+    // 1. Let steps be the following steps:
+    //   1. Return 1.
     args.GetReturnValue().Set(
         v8::Integer::New(GetScriptState()->GetIsolate(), 1));
   }
@@ -45,28 +58,18 @@
 
 CountQueuingStrategy::CountQueuingStrategy(ScriptState* script_state,
                                            const QueuingStrategyInit* init)
-    : high_water_mark_(script_state->GetIsolate(),
-                       HighWaterMarkOrUndefined(script_state, init)) {}
+    : high_water_mark_(init->highWaterMark()) {}
 
 CountQueuingStrategy::~CountQueuingStrategy() = default;
 
-ScriptValue CountQueuingStrategy::highWaterMark(
-    ScriptState* script_state) const {
-  return ScriptValue(script_state->GetIsolate(),
-                     high_water_mark_.NewLocal(script_state->GetIsolate()));
-}
-
 ScriptValue CountQueuingStrategy::size(ScriptState* script_state) const {
-  // We don't cache the result because normally this method will only be called
-  // once anyway.
-  return ScriptValue(
-      script_state->GetIsolate(),
-      CountQueuingStrategySizeFunction::CreateFunction(script_state));
-}
-
-void CountQueuingStrategy::Trace(Visitor* visitor) const {
-  visitor->Trace(high_water_mark_);
-  ScriptWrappable::Trace(visitor);
+  // https://streams.spec.whatwg.org/#count-queuing-strategy-size-function
+  // 5. Set globalObject’s count queuing strategy size function to a Function
+  //    that represents a reference to F, with callback context equal to
+  //    globalObject’s relevant settings object.
+  return GetCachedSizeFunction(
+      script_state, kCountQueuingStrategySizeFunction,
+      &CountQueuingStrategySizeFunction::CreateFunction);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/streams/count_queuing_strategy.h b/third_party/blink/renderer/core/streams/count_queuing_strategy.h
index 7a29176..c263564 100644
--- a/third_party/blink/renderer/core/streams/count_queuing_strategy.h
+++ b/third_party/blink/renderer/core/streams/count_queuing_strategy.h
@@ -15,7 +15,6 @@
 class QueuingStrategyInit;
 class ScriptState;
 class ScriptValue;
-class Visitor;
 
 // https://streams.spec.whatwg.org/#blqs-class
 class CORE_EXPORT CountQueuingStrategy final : public ScriptWrappable {
@@ -27,13 +26,11 @@
   CountQueuingStrategy(ScriptState*, const QueuingStrategyInit*);
   ~CountQueuingStrategy() override;
 
-  ScriptValue highWaterMark(ScriptState*) const;
+  double highWaterMark() const { return high_water_mark_; }
   ScriptValue size(ScriptState*) const;
 
-  void Trace(Visitor*) const override;
-
  private:
-  const TraceWrapperV8Reference<v8::Value> high_water_mark_;
+  const double high_water_mark_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/streams/count_queuing_strategy.idl b/third_party/blink/renderer/core/streams/count_queuing_strategy.idl
index fca10ee2..c288ebdd 100644
--- a/third_party/blink/renderer/core/streams/count_queuing_strategy.idl
+++ b/third_party/blink/renderer/core/streams/count_queuing_strategy.idl
@@ -7,9 +7,9 @@
 [
     Exposed=(Window,Worker,Worklet)
 ] interface CountQueuingStrategy {
-    [CallWith=ScriptState, MeasureAs=CountQueuingStrategyConstructor] constructor([PermissiveDictionaryConversion] QueuingStrategyInit init);
-    [CallWith=ScriptState] readonly attribute any highWaterMark;
+    [CallWith=ScriptState, MeasureAs=CountQueuingStrategyConstructor] constructor(QueuingStrategyInit init);
+    readonly attribute unrestricted double highWaterMark;
 
-    // size is an accessor that returns a function.
+    // The standard specifies "Function" but the IDL compiler doesn't like it.
     [CallWith=ScriptState] readonly attribute any size;
 };
diff --git a/third_party/blink/renderer/core/streams/queuing_strategy_common.cc b/third_party/blink/renderer/core/streams/queuing_strategy_common.cc
index f50890a..bb39288 100644
--- a/third_party/blink/renderer/core/streams/queuing_strategy_common.cc
+++ b/third_party/blink/renderer/core/streams/queuing_strategy_common.cc
@@ -4,20 +4,26 @@
 
 #include "third_party/blink/renderer/core/streams/queuing_strategy_common.h"
 
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_queuing_strategy_init.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 
 namespace blink {
 
-v8::Local<v8::Value> HighWaterMarkOrUndefined(ScriptState* script_state,
-                                              const QueuingStrategyInit* init) {
-  v8::Local<v8::Value> high_water_mark;
-  if (init->hasHighWaterMark()) {
-    high_water_mark = init->highWaterMark().V8Value();
-  } else {
-    high_water_mark = v8::Undefined(script_state->GetIsolate());
+ScriptValue GetCachedSizeFunction(ScriptState* script_state,
+                                  const V8PrivateProperty::SymbolKey& key,
+                                  SizeFunctionFactory factory) {
+  auto* isolate = script_state->GetIsolate();
+  auto function_cache = V8PrivateProperty::GetSymbol(isolate, key);
+  v8::Local<v8::Object> global_proxy = script_state->GetContext()->Global();
+  v8::Local<v8::Value> function;
+  if (!function_cache.GetOrUndefined(global_proxy).ToLocal(&function) ||
+      function->IsUndefined()) {
+    function = factory(script_state);
+    bool is_set = function_cache.Set(global_proxy, function);
+    DCHECK(is_set || isolate->IsExecutionTerminating());
   }
-  return high_water_mark;
+  return ScriptValue(isolate, function);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/streams/queuing_strategy_common.h b/third_party/blink/renderer/core/streams/queuing_strategy_common.h
index d62e6a8..5698595 100644
--- a/third_party/blink/renderer/core/streams/queuing_strategy_common.h
+++ b/third_party/blink/renderer/core/streams/queuing_strategy_common.h
@@ -5,15 +5,21 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_QUEUING_STRATEGY_COMMON_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_QUEUING_STRATEGY_COMMON_H_
 
+#include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
 #include "v8/include/v8.h"
 
 namespace blink {
 
 class ScriptState;
-class QueuingStrategyInit;
+class ScriptValue;
 
-v8::Local<v8::Value> HighWaterMarkOrUndefined(ScriptState* script_state,
-                                              const QueuingStrategyInit* init);
+using SizeFunctionFactory = v8::Local<v8::Function> (*)(ScriptState*);
+
+// Returns the value cached on the global proxy object under |key|, or, if that
+// is not set, caches and returns the result of calling |factory|.
+ScriptValue GetCachedSizeFunction(ScriptState*,
+                                  const V8PrivateProperty::SymbolKey& key,
+                                  SizeFunctionFactory factory);
 
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/core/streams/queuing_strategy_init.idl b/third_party/blink/renderer/core/streams/queuing_strategy_init.idl
index 7d5bd0c..f29e4b0 100644
--- a/third_party/blink/renderer/core/streams/queuing_strategy_init.idl
+++ b/third_party/blink/renderer/core/streams/queuing_strategy_init.idl
@@ -2,9 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// https://streams.spec.whatwg.org/#cqs-class
+// https://streams.spec.whatwg.org/#dictdef-queuingstrategyinit
 
-[PermissiveDictionaryConversion]
 dictionary QueuingStrategyInit {
-  any highWaterMark;
+  required unrestricted double highWaterMark;
 };
diff --git a/third_party/blink/renderer/core/streams/writable_stream.cc b/third_party/blink/renderer/core/streams/writable_stream.cc
index 5d63e8f..74d011d 100644
--- a/third_party/blink/renderer/core/streams/writable_stream.cc
+++ b/third_party/blink/renderer/core/streams/writable_stream.cc
@@ -203,8 +203,7 @@
   // introduces unnecessary trips through V8. Implement algorithms based on an
   // UnderlyingSinkBase.
   auto* init = QueuingStrategyInit::Create();
-  init->setHighWaterMark(
-      ScriptValue::From(script_state, static_cast<double>(high_water_mark)));
+  init->setHighWaterMark(static_cast<double>(high_water_mark));
   auto* strategy = CountQueuingStrategy::Create(script_state, init);
   ScriptValue strategy_value = ScriptValue::From(script_state, strategy);
   if (strategy_value.IsEmpty())
diff --git a/third_party/blink/renderer/core/testing/null_execution_context.cc b/third_party/blink/renderer/core/testing/null_execution_context.cc
index ebd73b9..28c97fd 100644
--- a/third_party/blink/renderer/core/testing/null_execution_context.cc
+++ b/third_party/blink/renderer/core/testing/null_execution_context.cc
@@ -23,10 +23,9 @@
     : ExecutionContext(
           v8::Isolate::GetCurrent(),
           MakeGarbageCollected<Agent>(v8::Isolate::GetCurrent(),
-                                      base::UnguessableToken::Null()),
-          SecurityContext::kWindow),
+                                      base::UnguessableToken::Null())),
       scheduler_(scheduler::CreateDummyFrameScheduler()) {
-  Initialize(SecurityContextInit(nullptr /* origin */, origin_trial_context));
+  Initialize(SecurityContextInit(origin_trial_context));
 }
 
 NullExecutionContext::~NullExecutionContext() {}
diff --git a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
index 60324b3..f749c79 100644
--- a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
+++ b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
@@ -189,7 +189,7 @@
     std::unique_ptr<WebContentSettingsClient> content_settings_client,
     scoped_refptr<WebWorkerFetchContext> web_worker_fetch_context,
     WorkerReportingProxy& reporting_proxy)
-    : ExecutionContext(isolate, agent, SecurityContext::kWorker),
+    : ExecutionContext(isolate, agent),
       name_(name),
       parent_devtools_token_(parent_devtools_token),
       worker_clients_(worker_clients),
@@ -199,8 +199,8 @@
           MakeGarbageCollected<WorkerOrWorkletScriptController>(this, isolate)),
       v8_cache_options_(v8_cache_options),
       reporting_proxy_(reporting_proxy) {
-  Initialize(
-      SecurityContextInit(origin, MakeGarbageCollected<OriginTrialContext>()));
+  GetSecurityContext().SetSecurityOrigin(std::move(origin));
+  Initialize(SecurityContextInit(MakeGarbageCollected<OriginTrialContext>()));
   if (worker_clients_)
     worker_clients_->ReattachThread();
 }
diff --git a/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc b/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc
index 7e157dd..b747bf3 100644
--- a/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc
+++ b/third_party/blink/renderer/modules/credentialmanager/credentials_container_test.cc
@@ -107,11 +107,6 @@
   CredentialManagerTestingContext(
       MockCredentialManager* mock_credential_manager)
       : dummy_context_(KURL("https://example.test")) {
-    dummy_context_.GetFrame()
-        .DomWindow()
-        ->GetSecurityContext()
-        .SetSecureContextModeForTesting(SecureContextMode::kSecureContext);
-
     dummy_context_.GetFrame().GetBrowserInterfaceBroker().SetBinderForTesting(
         ::blink::mojom::blink::CredentialManager::Name_,
         WTF::BindRepeating(
diff --git a/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_minimal-ui.json b/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_minimal-ui.json
index 28b8015..1cf3b1d8 100644
--- a/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_minimal-ui.json
+++ b/third_party/blink/renderer/modules/manifest/fuzzer_seed_corpus/manifest_minimal-ui.json
@@ -5,7 +5,7 @@
       "src": "launcher-icon-4x.png",
       "sizes": "192x192",
       "type": "image/png",
-      "purpose": "badge"
+      "purpose": "monochrome"
     }
   ],
   "start_url": "/",
diff --git a/third_party/blink/renderer/modules/manifest/image_resource_type_converters.cc b/third_party/blink/renderer/modules/manifest/image_resource_type_converters.cc
index d98302c..da54bf9 100644
--- a/third_party/blink/renderer/modules/manifest/image_resource_type_converters.cc
+++ b/third_party/blink/renderer/modules/manifest/image_resource_type_converters.cc
@@ -63,8 +63,8 @@
     Purpose purpose_enum;
     if (lowercase_purpose == "any") {
       purpose_enum = Purpose::ANY;
-    } else if (lowercase_purpose == "badge") {
-      purpose_enum = Purpose::BADGE;
+    } else if (lowercase_purpose == "monochrome") {
+      purpose_enum = Purpose::MONOCHROME;
     } else if (lowercase_purpose == "maskable") {
       purpose_enum = Purpose::MASKABLE;
     } else {
@@ -122,16 +122,17 @@
 
   // Parse 'purpose'
   const auto purposes = mojo::ParsePurpose(icon->purpose());
-  // ParsePurpose() would've weeded out any purposes that're not ANY or BADGE.
+  // ParsePurpose() would've weeded out any purposes that're not ANY or
+  // MONOCHROME.
   for (auto purpose : purposes) {
     switch (purpose) {
       case mojo::Purpose::ANY:
         manifest_icon.purpose.emplace_back(
             Manifest::ImageResource::Purpose::ANY);
         break;
-      case mojo::Purpose::BADGE:
+      case mojo::Purpose::MONOCHROME:
         manifest_icon.purpose.emplace_back(
-            Manifest::ImageResource::Purpose::BADGE);
+            Manifest::ImageResource::Purpose::MONOCHROME);
         break;
       case mojo::Purpose::MASKABLE:
         manifest_icon.purpose.emplace_back(
diff --git a/third_party/blink/renderer/modules/manifest/image_resource_type_converters_test.cc b/third_party/blink/renderer/modules/manifest/image_resource_type_converters_test.cc
index 03198a47..08a922b32e 100644
--- a/third_party/blink/renderer/modules/manifest/image_resource_type_converters_test.cc
+++ b/third_party/blink/renderer/modules/manifest/image_resource_type_converters_test.cc
@@ -119,22 +119,22 @@
   ASSERT_EQ(1u, converted->purpose.size());
   ASSERT_EQ(Purpose::ANY, converted->purpose.front());
 
-  resource->setPurpose(" Badge");
+  resource->setPurpose(" Monochrome");
   converted = ManifestImageResource::From(resource);
   ASSERT_EQ(1u, converted->purpose.size());
-  ASSERT_EQ(Purpose::BADGE, converted->purpose.front());
+  ASSERT_EQ(Purpose::MONOCHROME, converted->purpose.front());
 
-  resource->setPurpose(" Badge  AnY");
+  resource->setPurpose(" Monochrome  AnY");
   converted = ManifestImageResource::From(resource);
   ASSERT_EQ(2u, converted->purpose.size());
-  ASSERT_EQ(Purpose::BADGE, converted->purpose.front());
+  ASSERT_EQ(Purpose::MONOCHROME, converted->purpose.front());
   ASSERT_EQ(Purpose::ANY, converted->purpose.back());
 
-  resource->setPurpose("any badge  AnY");
+  resource->setPurpose("any monochrome  AnY");
   converted = ManifestImageResource::From(resource);
   ASSERT_EQ(2u, converted->purpose.size());
   ASSERT_EQ(Purpose::ANY, converted->purpose.front());
-  ASSERT_EQ(Purpose::BADGE, converted->purpose.back());
+  ASSERT_EQ(Purpose::MONOCHROME, converted->purpose.back());
 }
 
 TEST(ImageResourceConverter, InvalidPurposeTest) {
@@ -181,13 +181,13 @@
   blink::ManifestImageResource* resource =
       blink::ManifestImageResource::Create();
   resource->setSrc("http://example.com/lolcat.jpg");
-  resource->setPurpose("BADGE");
+  resource->setPurpose("MONOCHROME");
   resource->setSizes("32x32 64x64 128x128");
   resource->setType("image/jpeg");
 
   auto expected_resource = ManifestImageResource::New();
   expected_resource->src = blink::KURL("http://example.com/lolcat.jpg");
-  expected_resource->purpose = {Purpose::BADGE};
+  expected_resource->purpose = {Purpose::MONOCHROME};
   expected_resource->sizes = {{32, 32}, {64, 64}, {128, 128}};
   expected_resource->type = "image/jpeg";
 
@@ -197,7 +197,7 @@
 TEST(ImageResourceConverter, BlinkToMojoTypeTest) {
   blink::ManifestImageResource* icon = blink::ManifestImageResource::Create();
   icon->setSrc("http://example.com/lolcat.jpg");
-  icon->setPurpose("BADGE");
+  icon->setPurpose("MONOCHROME");
   icon->setSizes("32x32 64x64 128x128");
   icon->setType("image/jpeg");
 
@@ -207,7 +207,7 @@
   EXPECT_EQ(mojo_icon.type, blink::WebString("image/jpeg").Utf16());
   EXPECT_EQ(mojo_icon.sizes[1], gfx::Size(64, 64));
   EXPECT_EQ(mojo_icon.purpose[0],
-            blink::Manifest::ImageResource::Purpose::BADGE);
+            blink::Manifest::ImageResource::Purpose::MONOCHROME);
 }
 
 }  // namespace
diff --git a/third_party/blink/renderer/modules/manifest/manifest_parser.cc b/third_party/blink/renderer/modules/manifest/manifest_parser.cc
index c9f2437b..5e0c12c 100644
--- a/third_party/blink/renderer/modules/manifest/manifest_parser.cc
+++ b/third_party/blink/renderer/modules/manifest/manifest_parser.cc
@@ -375,8 +375,9 @@
 
     if (!CodeUnitCompareIgnoringASCIICase(keyword, "any")) {
       purposes.push_back(mojom::blink::ManifestImageResource::Purpose::ANY);
-    } else if (!CodeUnitCompareIgnoringASCIICase(keyword, "badge")) {
-      purposes.push_back(mojom::blink::ManifestImageResource::Purpose::BADGE);
+    } else if (!CodeUnitCompareIgnoringASCIICase(keyword, "monochrome")) {
+      purposes.push_back(
+          mojom::blink::ManifestImageResource::Purpose::MONOCHROME);
     } else if (!CodeUnitCompareIgnoringASCIICase(keyword, "maskable")) {
       purposes.push_back(
           mojom::blink::ManifestImageResource::Purpose::MASKABLE);
diff --git a/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc b/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc
index 12a8c70..f458bb1 100644
--- a/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc
+++ b/third_party/blink/renderer/modules/manifest/manifest_parser_unittest.cc
@@ -1004,7 +1004,7 @@
   {
     auto& manifest = ParseManifest(
         "{ \"icons\": [ {\"src\": \"\","
-        "\"purpose\": \"Any Badge Maskable\" } ] }");
+        "\"purpose\": \"Any Monochrome Maskable\" } ] }");
     EXPECT_FALSE(manifest->icons.IsEmpty());
 
     auto& icons = manifest->icons;
@@ -1012,7 +1012,7 @@
     EXPECT_EQ(icons[0]->purpose[0],
               mojom::blink::ManifestImageResource::Purpose::ANY);
     EXPECT_EQ(icons[0]->purpose[1],
-              mojom::blink::ManifestImageResource::Purpose::BADGE);
+              mojom::blink::ManifestImageResource::Purpose::MONOCHROME);
     EXPECT_EQ(icons[0]->purpose[2],
               mojom::blink::ManifestImageResource::Purpose::MASKABLE);
     EXPECT_EQ(0u, GetErrorCount());
@@ -1022,7 +1022,7 @@
   {
     auto& manifest = ParseManifest(
         "{ \"icons\": [ {\"src\": \"\","
-        "\"purpose\": \"  Any   Badge  \" } ] }");
+        "\"purpose\": \"  Any   Monochrome  \" } ] }");
     EXPECT_FALSE(manifest->icons.IsEmpty());
 
     auto& icons = manifest->icons;
@@ -1030,7 +1030,7 @@
     EXPECT_EQ(icons[0]->purpose[0],
               mojom::blink::ManifestImageResource::Purpose::ANY);
     EXPECT_EQ(icons[0]->purpose[1],
-              mojom::blink::ManifestImageResource::Purpose::BADGE);
+              mojom::blink::ManifestImageResource::Purpose::MONOCHROME);
     EXPECT_EQ(0u, GetErrorCount());
   }
 
@@ -1038,15 +1038,15 @@
   {
     auto& manifest = ParseManifest(
         "{ \"icons\": [ {\"src\": \"\","
-        "\"purpose\": \"badge badge\" } ] }");
+        "\"purpose\": \"monochrome monochrome\" } ] }");
     EXPECT_FALSE(manifest->icons.IsEmpty());
 
     auto& icons = manifest->icons;
     ASSERT_EQ(icons[0]->purpose.size(), 2u);
     EXPECT_EQ(icons[0]->purpose[0],
-              mojom::blink::ManifestImageResource::Purpose::BADGE);
+              mojom::blink::ManifestImageResource::Purpose::MONOCHROME);
     EXPECT_EQ(icons[0]->purpose[1],
-              mojom::blink::ManifestImageResource::Purpose::BADGE);
+              mojom::blink::ManifestImageResource::Purpose::MONOCHROME);
     EXPECT_EQ(0u, GetErrorCount());
   }
 
@@ -1054,13 +1054,13 @@
   {
     auto& manifest = ParseManifest(
         "{ \"icons\": [ {\"src\": \"\","
-        "\"purpose\": \"badge fizzbuzz\" } ] }");
+        "\"purpose\": \"monochrome fizzbuzz\" } ] }");
     EXPECT_FALSE(manifest->icons.IsEmpty());
 
     auto& icons = manifest->icons;
     ASSERT_EQ(icons[0]->purpose.size(), 1u);
     EXPECT_EQ(icons[0]->purpose[0],
-              mojom::blink::ManifestImageResource::Purpose::BADGE);
+              mojom::blink::ManifestImageResource::Purpose::MONOCHROME);
     ASSERT_EQ(1u, GetErrorCount());
     EXPECT_EQ(kSomeInvalidPurposeError, errors()[0]);
   }
diff --git a/third_party/blink/renderer/modules/media_capabilities/DEPS b/third_party/blink/renderer/modules/media_capabilities/DEPS
index 02607e0..3b8d274 100644
--- a/third_party/blink/renderer/modules/media_capabilities/DEPS
+++ b/third_party/blink/renderer/modules/media_capabilities/DEPS
@@ -7,6 +7,8 @@
     "+media/mojo/mojom/media_types.mojom-blink.h",
     "+media/mojo/mojom/video_decode_perf_history.mojom-blink.h",
     "+media/mojo/mojom/media_metrics_provider.mojom-blink.h",
+    "+media/video/gpu_video_accelerator_factories.h",
+    "+media/video/supported_video_decoder_config.h",
     "-third_party/blink/renderer/modules",
     "+third_party/blink/renderer/modules/encryptedmedia",
     "+third_party/blink/renderer/modules/media_capabilities",
@@ -20,5 +22,6 @@
         "+base/strings/string_number_conversions.h",
         "+base/test/bind_test_util.h",
         "+media/mojo/mojom/watch_time_recorder.mojom-blink.h",
+        "+media/video/mock_gpu_video_accelerator_factories.h",
     ],
 }
\ No newline at end of file
diff --git a/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc b/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc
index 3c14225..09ce681 100644
--- a/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc
+++ b/third_party/blink/renderer/modules/media_capabilities/media_capabilities.cc
@@ -13,17 +13,22 @@
 #include "base/metrics/histogram_macros.h"
 #include "base/optional.h"
 #include "media/base/media_switches.h"
+#include "media/base/media_util.h"
 #include "media/base/mime_util.h"
 #include "media/base/supported_types.h"
+#include "media/base/video_decoder_config.h"
 #include "media/filters/stream_parser_factory.h"
 #include "media/learning/common/media_learning_tasks.h"
 #include "media/learning/common/target_histogram.h"
 #include "media/learning/mojo/public/mojom/learning_task_controller.mojom-blink.h"
 #include "media/mojo/mojom/media_metrics_provider.mojom-blink.h"
 #include "media/mojo/mojom/media_types.mojom-blink.h"
+#include "media/video/gpu_video_accelerator_factories.h"
+#include "media/video/supported_video_decoder_config.h"
 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
 #include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h"
 #include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
+#include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/public/platform/web_encrypted_media_client.h"
 #include "third_party/blink/public/platform/web_encrypted_media_request.h"
@@ -56,6 +61,7 @@
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/heap/heap_allocator.h"
 #include "third_party/blink/renderer/platform/heap/member.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
 #include "third_party/blink/renderer/platform/media_capabilities/web_media_capabilities_info.h"
 #include "third_party/blink/renderer/platform/media_capabilities/web_media_configuration.h"
@@ -63,6 +69,8 @@
 #include "third_party/blink/renderer/platform/peerconnection/transmission_encoding_info_handler.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/blink/renderer/platform/wtf/vector.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
 
 namespace blink {
 
@@ -105,6 +113,12 @@
       kLearningNnrThresholdDefault);
 }
 
+// static
+bool UseGpuFactoriesForPowerEfficient() {
+  return base::FeatureList::IsEnabled(
+      media::kMediaCapabilitiesQueryGpuFactories);
+}
+
 // Utility function that will create a MediaCapabilitiesDecodingInfo object with
 // all the values set to either true or false.
 MediaCapabilitiesDecodingInfo* CreateDecodingInfoWith(bool value) {
@@ -513,16 +527,14 @@
 
 // Returns whether the VideoConfiguration is supported.
 // IsVideoCodecValid() MUST be called before.
-bool IsVideoConfigurationSupported(
-    const blink::VideoConfiguration* video_config,
-    const String& mime_type,
-    const String& codec) {
+bool IsVideoConfigurationSupported(const String& mime_type,
+                                   const String& codec,
+                                   media::VideoColorSpace video_color_space,
+                                   media::HdrMetadataType hdr_metadata_type) {
   media::VideoCodec video_codec = media::kUnknownVideoCodec;
   media::VideoCodecProfile video_profile;
   uint8_t video_level = 0;
-  media::VideoColorSpace video_color_space;
   bool is_video_codec_ambiguous = true;
-  media::HdrMetadataType hdr_metadata_type;
 
   // Must succeed as IsVideoCodecValid() should have been called before.
   bool parsed = media::ParseVideoCodecString(
@@ -530,9 +542,6 @@
       &video_profile, &video_level, &video_color_space);
   DCHECK(parsed && !is_video_codec_ambiguous);
 
-  ParseDynamicRangeConfigurations(video_config, &video_color_space,
-                                  &hdr_metadata_type);
-
   return media::IsSupportedVideoType({video_codec, video_profile, video_level,
                                       video_color_space, hdr_metadata_type});
 }
@@ -696,11 +705,19 @@
   // Validation errors should return above.
   DCHECK(message.IsEmpty());
 
+  media::VideoColorSpace video_color_space;
+  media::HdrMetadataType hdr_metadata_type = media::HdrMetadataType::kNone;
+  if (config->hasVideo()) {
+    ParseDynamicRangeConfigurations(config->video(), &video_color_space,
+                                    &hdr_metadata_type);
+  }
+
   if (config->hasKeySystemConfiguration()) {
     // GetEmeSupport() will call the VideoDecodePerfHistory service after
     // receiving info about support for the configuration for encrypted content.
-    return GetEmeSupport(script_state, video_codec, video_profile, config,
-                         request_time, exception_state);
+    return GetEmeSupport(script_state, video_codec, video_profile,
+                         video_color_space, config, request_time,
+                         exception_state);
   }
 
   bool audio_supported = true;
@@ -722,8 +739,8 @@
   DCHECK(config->hasVideo());
 
   // Return early for unsupported configurations.
-  if (!IsVideoConfigurationSupported(config->video(), video_mime_str,
-                                     video_codec_str)) {
+  if (!IsVideoConfigurationSupported(video_mime_str, video_codec_str,
+                                     video_color_space, hdr_metadata_type)) {
     return ScriptPromise::Cast(
         script_state, ToV8(CreateDecodingInfoWith(false), script_state));
   }
@@ -735,8 +752,8 @@
   // undefined. See comment above Promise() in script_promise_resolver.h
   ScriptPromise promise = resolver->Promise();
 
-  GetPerfInfo(video_codec, video_profile, config->video(), request_time,
-              resolver, nullptr /* access */);
+  GetPerfInfo(video_codec, video_profile, video_color_space, config,
+              request_time, resolver, nullptr /* access */);
 
   return promise;
 }
@@ -871,6 +888,7 @@
     ScriptState* script_state,
     media::VideoCodec video_codec,
     media::VideoCodecProfile video_profile,
+    media::VideoColorSpace video_color_space,
     const MediaDecodingConfiguration* configuration,
     const base::TimeTicks& request_time,
     ExceptionState& exception_state) {
@@ -994,12 +1012,9 @@
   MediaCapabilitiesKeySystemAccessInitializer* initializer =
       MakeGarbageCollected<MediaCapabilitiesKeySystemAccessInitializer>(
           script_state, key_system_config->keySystem(), config_vector,
-          WTF::Bind(
-              &MediaCapabilities::GetPerfInfo, WrapPersistent(this),
-              video_codec, video_profile,
-              WrapPersistent(configuration->hasVideo() ? configuration->video()
-                                                       : nullptr),
-              request_time));
+          WTF::Bind(&MediaCapabilities::GetPerfInfo, WrapPersistent(this),
+                    video_codec, video_profile, video_color_space,
+                    WrapPersistent(configuration), request_time));
 
   // IMPORTANT: Acquire the promise before potentially synchronously resolving
   // it in the code that follows. Otherwise the promise returned to JS will be
@@ -1014,16 +1029,19 @@
   return promise;
 }
 
-void MediaCapabilities::GetPerfInfo(media::VideoCodec video_codec,
-                                    media::VideoCodecProfile video_profile,
-                                    const VideoConfiguration* video_config,
-                                    const base::TimeTicks& request_time,
-                                    ScriptPromiseResolver* resolver,
-                                    MediaKeySystemAccess* access) {
+void MediaCapabilities::GetPerfInfo(
+    media::VideoCodec video_codec,
+    media::VideoCodecProfile video_profile,
+    media::VideoColorSpace video_color_space,
+    const MediaDecodingConfiguration* decoding_config,
+    const base::TimeTicks& request_time,
+    ScriptPromiseResolver* resolver,
+    MediaKeySystemAccess* access) {
   ExecutionContext* execution_context = resolver->GetExecutionContext();
   if (!execution_context || execution_context->IsContextDestroyed())
     return;
 
+  const VideoConfiguration* video_config = decoding_config->video();
   if (!video_config) {
     // Audio-only is always smooth and power efficient.
     MediaCapabilitiesDecodingInfo* info = CreateDecodingInfoWith(true);
@@ -1065,6 +1083,11 @@
   decode_history_service_->GetPerfInfo(
       std::move(features), WTF::Bind(&MediaCapabilities::OnPerfHistoryInfo,
                                      WrapPersistent(this), callback_id));
+
+  if (UseGpuFactoriesForPowerEfficient()) {
+    GetGpuFactoriesSupport(callback_id, video_codec, video_profile,
+                           video_color_space, decoding_config);
+  }
 }
 
 void MediaCapabilities::GetPerfInfo_ML(ExecutionContext* execution_context,
@@ -1102,6 +1125,82 @@
   }
 }
 
+void MediaCapabilities::GetGpuFactoriesSupport(
+    int callback_id,
+    media::VideoCodec video_codec,
+    media::VideoCodecProfile video_profile,
+    media::VideoColorSpace video_color_space,
+    const MediaDecodingConfiguration* decoding_config) {
+  DCHECK(UseGpuFactoriesForPowerEfficient());
+  DCHECK(decoding_config->hasVideo());
+  DCHECK(pending_cb_map_.Contains(callback_id));
+  ExecutionContext* execution_context =
+      pending_cb_map_.at(callback_id)->resolver->GetExecutionContext();
+
+  // Frame may become detached in the time it takes us to get callback for
+  // NotifyDecoderSupportKnown. In this case, report false as a means of clean
+  // shutdown.
+  if (!execution_context || execution_context->IsContextDestroyed()) {
+    OnGpuFactoriesSupport(callback_id, false);
+    return;
+  }
+
+  media::GpuVideoAcceleratorFactories* gpu_factories =
+      Platform::Current()->GetGpuFactories();
+  if (!gpu_factories) {
+    OnGpuFactoriesSupport(callback_id, false);
+    return;
+  }
+
+  if (!gpu_factories->IsDecoderSupportKnown()) {
+    gpu_factories->NotifyDecoderSupportKnown(
+        WTF::Bind(&MediaCapabilities::GetGpuFactoriesSupport,
+                  WrapPersistent(this), callback_id, video_codec, video_profile,
+                  video_color_space, WrapPersistent(decoding_config)));
+    return;
+  }
+
+  // TODO(chcunningham): Get the actual scheme and alpha mode from
+  // |decoding_config| once implemented (its already spec'ed).
+  media::EncryptionScheme encryption_scheme =
+      decoding_config->hasKeySystemConfiguration()
+          ? media::EncryptionScheme::kCenc
+          : media::EncryptionScheme::kUnencrypted;
+  media::VideoDecoderConfig::AlphaMode alpha_mode =
+      media::VideoDecoderConfig::AlphaMode::kIsOpaque;
+
+  // A few things aren't known until demuxing time. These include: coded size,
+  // visible rect, and extra data. Make reasonable guesses below. Ideally the
+  // differences won't be make/break GPU acceleration support.
+  VideoConfiguration* video_config = decoding_config->video();
+  gfx::Size natural_size(video_config->width(), video_config->height());
+  media::VideoDecoderConfig config(
+      video_codec, video_profile, alpha_mode, video_color_space,
+      media::VideoTransformation(), natural_size /* coded_size */,
+      gfx::Rect(natural_size) /* visible_rect */, natural_size,
+      media::EmptyExtraData(), encryption_scheme);
+
+  static_assert(media::VideoDecoderImplementation::kAlternate ==
+                    media::VideoDecoderImplementation::kMaxValue,
+                "Keep the array below in sync.");
+  media::VideoDecoderImplementation decoder_impls[] = {
+      media::VideoDecoderImplementation::kDefault,
+      media::VideoDecoderImplementation::kAlternate};
+  media::GpuVideoAcceleratorFactories::Supported supported =
+      media::GpuVideoAcceleratorFactories::Supported::kUnknown;
+  for (const auto& impl : decoder_impls) {
+    supported = gpu_factories->IsDecoderConfigSupported(impl, config);
+    DCHECK_NE(supported,
+              media::GpuVideoAcceleratorFactories::Supported::kUnknown);
+    if (supported == media::GpuVideoAcceleratorFactories::Supported::kTrue)
+      break;
+  }
+
+  OnGpuFactoriesSupport(
+      callback_id,
+      supported == media::GpuVideoAcceleratorFactories::Supported::kTrue);
+}
+
 void MediaCapabilities::ResolveCallbackIfReady(int callback_id) {
   DCHECK(pending_cb_map_.Contains(callback_id));
   PendingCallbackState* pending_cb = pending_cb_map_.at(callback_id);
@@ -1120,6 +1219,11 @@
       !pending_cb->is_bad_window_prediction_smooth.has_value())
     return;
 
+  if (UseGpuFactoriesForPowerEfficient() &&
+      !pending_cb->is_gpu_factories_supported.has_value()) {
+    return;
+  }
+
   if (!pending_cb->resolver->GetExecutionContext() ||
       pending_cb->resolver->GetExecutionContext()->IsContextDestroyed()) {
     // We're too late! Now that all the callbacks have provided state, its safe
@@ -1132,7 +1236,12 @@
       MediaCapabilitiesDecodingInfo::Create());
   info->setSupported(true);
   info->setKeySystemAccess(pending_cb->key_system_access);
-  info->setPowerEfficient(*pending_cb->db_is_power_efficient);
+
+  if (UseGpuFactoriesForPowerEfficient()) {
+    info->setPowerEfficient(*pending_cb->is_gpu_factories_supported);
+  } else {
+    info->setPowerEfficient(*pending_cb->db_is_power_efficient);
+  }
 
   // If ML experiment is running: AND available ML signals.
   if (pending_cb->is_bad_window_prediction_smooth.has_value() ||
@@ -1224,6 +1333,17 @@
   ResolveCallbackIfReady(callback_id);
 }
 
+void MediaCapabilities::OnGpuFactoriesSupport(int callback_id,
+                                              bool is_supported) {
+  DVLOG(2) << __func__ << " is_supported:" << is_supported;
+  DCHECK(pending_cb_map_.Contains(callback_id));
+  PendingCallbackState* pending_cb = pending_cb_map_.at(callback_id);
+
+  pending_cb->is_gpu_factories_supported = is_supported;
+
+  ResolveCallbackIfReady(callback_id);
+}
+
 int MediaCapabilities::CreateCallbackId() {
   ++last_callback_id_;
   return last_callback_id_;
diff --git a/third_party/blink/renderer/modules/media_capabilities/media_capabilities.h b/third_party/blink/renderer/modules/media_capabilities/media_capabilities.h
index a590454..a72e3f5 100644
--- a/third_party/blink/renderer/modules/media_capabilities/media_capabilities.h
+++ b/third_party/blink/renderer/modules/media_capabilities/media_capabilities.h
@@ -60,6 +60,7 @@
     base::Optional<bool> is_nnr_prediction_smooth;
     base::Optional<bool> db_is_smooth;
     base::Optional<bool> db_is_power_efficient;
+    base::Optional<bool> is_gpu_factories_supported;
     base::TimeTicks request_time;
   };
 
@@ -74,6 +75,7 @@
   ScriptPromise GetEmeSupport(ScriptState*,
                               media::VideoCodec,
                               media::VideoCodecProfile,
+                              media::VideoColorSpace,
                               const MediaDecodingConfiguration*,
                               const base::TimeTicks& request_time,
                               ExceptionState&);
@@ -81,7 +83,8 @@
   // parallel request to GetPerfInfo_ML() when learning experiment is enabled.
   void GetPerfInfo(media::VideoCodec,
                    media::VideoCodecProfile,
-                   const VideoConfiguration*,
+                   media::VideoColorSpace,
+                   const MediaDecodingConfiguration*,
                    const base::TimeTicks& request_time,
                    ScriptPromiseResolver*,
                    MediaKeySystemAccess*);
@@ -94,6 +97,15 @@
                       int width,
                       double framerate);
 
+  // Query media::GpuVideoAcceleratorFactories for support of hardware
+  // accelerate decode. Only called when |UseGpuFactoriesForPowerEfficient()|
+  // is true.
+  void GetGpuFactoriesSupport(int callback_id,
+                              media::VideoCodec video_codec,
+                              media::VideoCodecProfile video_profile,
+                              media::VideoColorSpace,
+                              const MediaDecodingConfiguration*);
+
   // Callback for perf info from the VideoDecodePerfHistory service.
   void OnPerfHistoryInfo(int callback_id,
                          bool is_smooth,
@@ -109,6 +121,9 @@
       int callback_id,
       const base::Optional<::media::learning::TargetHistogram>& histogram);
 
+  // Callback for GetGpuFactoriesSupport().
+  void OnGpuFactoriesSupport(int callback_id, bool is_supported);
+
   // Resolves the callback with associated |callback_id| and removes it from the
   // |pending_callback_map_|.
   void ResolveCallbackIfReady(int callback_id);
diff --git a/third_party/blink/renderer/modules/media_capabilities/media_capabilities_test.cc b/third_party/blink/renderer/modules/media_capabilities/media_capabilities_test.cc
index dbbdaa9..19e1176 100644
--- a/third_party/blink/renderer/modules/media_capabilities/media_capabilities_test.cc
+++ b/third_party/blink/renderer/modules/media_capabilities/media_capabilities_test.cc
@@ -9,6 +9,7 @@
 #include <algorithm>
 
 #include "base/strings/string_number_conversions.h"
+#include "base/task/post_task.h"
 #include "base/test/bind_test_util.h"
 #include "base/test/scoped_feature_list.h"
 #include "media/base/media_switches.h"
@@ -20,6 +21,7 @@
 #include "media/mojo/mojom/media_types.mojom-blink.h"
 #include "media/mojo/mojom/video_decode_perf_history.mojom-blink.h"
 #include "media/mojo/mojom/watch_time_recorder.mojom-blink.h"
+#include "media/video/mock_gpu_video_accelerator_factories.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -27,11 +29,14 @@
 #include "third_party/blink/public/platform/web_size.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_audio_configuration.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_media_capabilities_info.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_media_configuration.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_media_decoding_configuration.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_video_configuration.h"
 #include "third_party/blink/renderer/core/testing/page_test_base.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.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/wtf/text/string_view.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -43,7 +48,9 @@
 using ::media::learning::ObservationCompletion;
 using ::media::learning::TargetValue;
 using ::testing::_;
+using ::testing::InSequence;
 using ::testing::Invoke;
+using ::testing::Return;
 using ::testing::Unused;
 
 namespace blink {
@@ -213,6 +220,10 @@
     nnr_cb_ = std::move(predict_cb);
   }
 
+  void SaveGpuFactoriesNotifyCallback(base::OnceClosure cb) {
+    gpu_factories_notify_cb_ = std::move(cb);
+  }
+
   MockPerfHistoryService::GetPerfInfoCallback& perf_history_cb() {
     return perf_history_cb_;
   }
@@ -226,10 +237,23 @@
     return nnr_cb_;
   }
 
+  base::OnceClosure& gpu_factories_notify_cb() {
+    return gpu_factories_notify_cb_;
+  }
+
  private:
   MockPerfHistoryService::GetPerfInfoCallback perf_history_cb_;
   MockLearningTaskControllerService::PredictDistributionCallback bad_window_cb_;
   MockLearningTaskControllerService::PredictDistributionCallback nnr_cb_;
+  base::OnceClosure gpu_factories_notify_cb_;
+};
+
+class MockPlatform : public TestingPlatformSupport {
+ public:
+  MockPlatform() = default;
+  ~MockPlatform() override = default;
+
+  MOCK_METHOD0(GetGpuFactories, media::GpuVideoAcceleratorFactories*());
 };
 
 // This would typically be a test fixture, but we need it to be
@@ -300,14 +324,18 @@
     return nnr_service_.get();
   }
 
+  MockPlatform& GetMockPlatform() { return *mock_platform_; }
+
   void VerifyAndClearMockExpectations() {
     testing::Mock::VerifyAndClearExpectations(GetPerfHistoryService());
     testing::Mock::VerifyAndClearExpectations(GetNnrService());
     testing::Mock::VerifyAndClearExpectations(GetBadWindowService());
+    testing::Mock::VerifyAndClearExpectations(&GetMockPlatform());
   }
 
  private:
   V8TestingScope v8_scope_;
+  ScopedTestingPlatformSupport<MockPlatform> mock_platform_;
   std::unique_ptr<MockPerfHistoryService> perf_history_service_;
   std::unique_ptr<FakeMediaMetricsProvider> fake_metrics_provider_;
   Persistent<MediaCapabilities> media_capabilities_;
@@ -317,6 +345,7 @@
 
 // |kContentType|, |kCodec|, and |kCodecProfile| must match.
 const char kContentType[] = "video/webm; codecs=\"vp09.00.10.08\"";
+const char kAudioContentType[] = "audio/webm; codecs=\"opus\"";
 const media::VideoCodecProfile kCodecProfile = media::VP9PROFILE_PROFILE0;
 const media::VideoCodec kCodec = media::kCodecVP9;
 const double kFramerate = 20.5;
@@ -325,6 +354,16 @@
 const int kBitrate = 2391000;
 
 // Construct VideoConfig using the constants above.
+MediaDecodingConfiguration* CreateAudioDecodingConfig() {
+  auto* audio_config = MakeGarbageCollected<AudioConfiguration>();
+  audio_config->setContentType(kAudioContentType);
+  auto* decoding_config = MakeGarbageCollected<MediaDecodingConfiguration>();
+  decoding_config->setType("media-source");
+  decoding_config->setAudio(audio_config);
+  return decoding_config;
+}
+
+// Construct VideoConfig using the constants above.
 MediaDecodingConfiguration* CreateDecodingConfig() {
   auto* video_config = MakeGarbageCollected<VideoConfiguration>();
   video_config->setFramerate(kFramerate);
@@ -375,6 +414,7 @@
   kDB,
   kBadWindow,
   kNnr,
+  kGpuFactories,
 };
 
 // Makes a TargetHistogram with single count at |target_value|.
@@ -415,6 +455,10 @@
   };
 }
 
+testing::Action<void(base::OnceClosure)> GpuFactoriesNotifyCallback() {
+  return [](base::OnceClosure cb) { std::move(cb).Run(); };
+}
+
 // Helper to constructs field trial params with given ML prediction thresholds.
 base::FieldTrialParams MakeMlParams(double bad_window_threshold,
                                     double nnr_threshold) {
@@ -446,6 +490,16 @@
 
 }  // namespace
 
+TEST(MediaCapabilitiesTests, BasicAudio) {
+  MediaCapabilitiesTestContext context;
+  const MediaDecodingConfiguration* kDecodingConfig =
+      CreateAudioDecodingConfig();
+  MediaCapabilitiesInfo* info = DecodingInfo(kDecodingConfig, &context);
+  EXPECT_TRUE(info->supported());
+  EXPECT_TRUE(info->smooth());
+  EXPECT_TRUE(info->powerEfficient());
+}
+
 // Other tests will assume these match. Test to be sure they stay in sync.
 TEST(MediaCapabilitiesTests, ConfigMatchesFeatures) {
   const MediaDecodingConfiguration* kDecodingConfig = CreateDecodingConfig();
@@ -531,6 +585,75 @@
   EXPECT_TRUE(info->powerEfficient());
 }
 
+TEST(MediaCapabilitiesTests, PredictPowerEfficientWithGpuFactories) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitWithFeatures(
+      // Enable GpuFactories for power predictions.
+      {media::kMediaCapabilitiesQueryGpuFactories},
+      // Disable ML predictions (may/may not be disabled by default).
+      {media::kMediaLearningSmoothnessExperiment});
+
+  MediaCapabilitiesTestContext context;
+  const auto* kDecodingConfig = CreateDecodingConfig();
+  const media::mojom::blink::PredictionFeatures kFeatures = CreateFeatures();
+
+  // Setup DB to return powerEfficient = false. We later verify that opposite
+  // response from GpuFactories overrides the DB.
+  EXPECT_CALL(*context.GetPerfHistoryService(), GetPerfInfo(_, _))
+      .WillOnce(DbCallback(kFeatures, /*smooth*/ false, /*power_eff*/ false));
+
+  auto mock_gpu_factories =
+      std::make_unique<media::MockGpuVideoAcceleratorFactories>(nullptr);
+  ON_CALL(context.GetMockPlatform(), GetGpuFactories())
+      .WillByDefault(Return(mock_gpu_factories.get()));
+
+  // First, lets simulate the scenario where we ask before support is known. The
+  // async path should notify us when the info arrives. We then get GpuFactroies
+  // again and learn the config is supported.
+  EXPECT_CALL(context.GetMockPlatform(), GetGpuFactories()).Times(2);
+  {
+    // InSequence because we EXPECT two calls to IsDecoderSupportKnown with
+    // different return values.
+    InSequence s;
+    EXPECT_CALL(*mock_gpu_factories, IsDecoderSupportKnown())
+        .WillOnce(Return(false));
+    EXPECT_CALL(*mock_gpu_factories, NotifyDecoderSupportKnown(_))
+        .WillOnce(GpuFactoriesNotifyCallback());
+    EXPECT_CALL(*mock_gpu_factories, IsDecoderSupportKnown())
+        .WillOnce(Return(true));
+    EXPECT_CALL(*mock_gpu_factories, IsDecoderConfigSupported(_, _))
+        .WillOnce(
+            Return(media::GpuVideoAcceleratorFactories::Supported::kTrue));
+  }
+
+  // Info should be powerEfficient, preferring response of GpuFactories over
+  // the DB.
+  MediaCapabilitiesInfo* info = DecodingInfo(kDecodingConfig, &context);
+  EXPECT_TRUE(info->powerEfficient());
+  EXPECT_FALSE(info->smooth());
+  context.VerifyAndClearMockExpectations();
+  testing::Mock::VerifyAndClearExpectations(mock_gpu_factories.get());
+
+  // Now expect a second query with support is already known to be false. Set
+  // DB to respond with the opposite answer.
+  EXPECT_CALL(*context.GetPerfHistoryService(), GetPerfInfo(_, _))
+      .WillOnce(DbCallback(kFeatures, /*smooth*/ false, /*power_eff*/ true));
+  EXPECT_CALL(context.GetMockPlatform(), GetGpuFactories());
+  EXPECT_CALL(*mock_gpu_factories, IsDecoderSupportKnown())
+      .WillOnce(Return(true));
+  EXPECT_CALL(*mock_gpu_factories, IsDecoderConfigSupported(_, _))
+      .WillRepeatedly(
+          Return(media::GpuVideoAcceleratorFactories::Supported::kFalse));
+
+  // Info should be NOT powerEfficient, preferring response of GpuFactories over
+  // the DB.
+  info = DecodingInfo(kDecodingConfig, &context);
+  EXPECT_FALSE(info->powerEfficient());
+  EXPECT_FALSE(info->smooth());
+  context.VerifyAndClearMockExpectations();
+  testing::Mock::VerifyAndClearExpectations(mock_gpu_factories.get());
+}
+
 // Test with smoothness predictions coming solely from "bad window" ML service.
 TEST(MediaCapabilitiesTests, PredictWithBadWindowMLService) {
   // Enable ML predictions with thresholds. -1 disables the NNR predictor.
@@ -745,12 +868,18 @@
   const double kBadWindowThreshold = 2;
   const double kNnrThreshold = 3;
   base::test::ScopedFeatureList scoped_feature_list;
-  scoped_feature_list.InitAndEnableFeatureWithParameters(
-      media::kMediaLearningSmoothnessExperiment,
-      MakeMlParams(kBadWindowThreshold, kNnrThreshold));
+  scoped_feature_list.InitWithFeaturesAndParameters(
+      // Enabled features w/ parameters
+      {{media::kMediaLearningSmoothnessExperiment,
+        MakeMlParams(kBadWindowThreshold, kNnrThreshold)},
+       {media::kMediaCapabilitiesQueryGpuFactories, {}}},
+      // Disabled features.
+      {});
 
   MediaCapabilitiesTestContext context;
   const auto* kDecodingConfig = CreateDecodingConfig();
+  auto mock_gpu_factories =
+      std::make_unique<media::MockGpuVideoAcceleratorFactories>(nullptr);
 
   // DB and both ML services should be called. Save their callbacks.
   CallbackSaver cb_saver;
@@ -761,6 +890,26 @@
   EXPECT_CALL(*context.GetNnrService(), PredictDistribution(_, _))
       .WillOnce(Invoke(&cb_saver, &CallbackSaver::SaveNnrCallback));
 
+  // GpuFactories should also be called. Set it up to be async with arrival of
+  // support info. Save the "notify" callback.
+  EXPECT_CALL(context.GetMockPlatform(), GetGpuFactories())
+      .WillRepeatedly(Return(mock_gpu_factories.get()));
+  {
+    // InSequence because we EXPECT two calls to IsDecoderSupportKnown with
+    // different return values.
+    InSequence s;
+    EXPECT_CALL(*mock_gpu_factories, IsDecoderSupportKnown())
+        .WillOnce(Return(false));
+    EXPECT_CALL(*mock_gpu_factories, NotifyDecoderSupportKnown(_))
+        .WillOnce(
+            Invoke(&cb_saver, &CallbackSaver::SaveGpuFactoriesNotifyCallback));
+    EXPECT_CALL(*mock_gpu_factories, IsDecoderSupportKnown())
+        .WillOnce(Return(true));
+    EXPECT_CALL(*mock_gpu_factories, IsDecoderConfigSupported(_, _))
+        .WillRepeatedly(
+            Return(media::GpuVideoAcceleratorFactories::Supported::kFalse));
+  }
+
   // Call decodingInfo() to kick off the calls to prediction services.
   ScriptPromise promise = context.GetMediaCapabilities()->decodingInfo(
       context.GetScriptState(), kDecodingConfig, context.GetExceptionState());
@@ -769,7 +918,7 @@
   // Callbacks should all be saved after mojo's pending tasks have run.
   test::RunPendingTasks();
   ASSERT_TRUE(cb_saver.perf_history_cb() && cb_saver.bad_window_cb() &&
-              cb_saver.nnr_cb());
+              cb_saver.nnr_cb() && cb_saver.gpu_factories_notify_cb());
 
   // Complete callbacks in whatever order.
   for (size_t i = 0; i < callback_order.size(); ++i) {
@@ -784,9 +933,12 @@
       case PredictionType::kNnr:
         std::move(cb_saver.nnr_cb()).Run(MakeHistogram(kNnrThreshold + 0.5));
         break;
+      case PredictionType::kGpuFactories:
+        std::move(cb_saver.gpu_factories_notify_cb()).Run();
+        break;
     }
 
-    // Give mojo callbacks a chance to run.
+    // Give callbacks/tasks a chance to run.
     test::RunPendingTasks();
 
     // Promise should only be resolved once the final callback has run.
@@ -805,15 +957,16 @@
 
   // Smooth=false because NNR prediction exceeds threshold.
   EXPECT_FALSE(info->smooth());
-  // DB predicted power_efficient = true.
-  EXPECT_TRUE(info->powerEfficient());
+  // DB predicted power_efficient = true, but GpuFactories overrides w/ false.
+  EXPECT_FALSE(info->powerEfficient());
 }
 
 // Test that decodingInfo() behaves correctly for all orderings/timings of the
 // underlying prediction services.
 TEST(MediaCapabilitiesTests, PredictionCallbackPermutations) {
   std::vector<PredictionType> callback_order(
-      {PredictionType::kDB, PredictionType::kBadWindow, PredictionType::kNnr});
+      {PredictionType::kDB, PredictionType::kBadWindow, PredictionType::kNnr,
+       PredictionType::kGpuFactories});
   do {
     RunCallbackPermutationTest(callback_order);
   } while (std::next_permutation(callback_order.begin(), callback_order.end()));
diff --git a/third_party/blink/renderer/modules/media_controls/resources/media_controls_resources.grd b/third_party/blink/renderer/modules/media_controls/resources/media_controls_resources.grd
index 11352af0..576d004 100644
--- a/third_party/blink/renderer/modules/media_controls/resources/media_controls_resources.grd
+++ b/third_party/blink/renderer/modules/media_controls/resources/media_controls_resources.grd
@@ -9,17 +9,17 @@
   </outputs>
   <release seq="1">
     <structures fallback_to_low_resolution="true">
-      <structure type="chrome_html" name="IDR_UASTYLE_MEDIA_CONTROLS_CSS" file="mediaControls.css" flattenhtml="true" compress="gzip" />
-      <structure type="chrome_html" name="IDR_UASTYLE_MEDIA_INTERSTITIALS_CSS" file="mediaInterstitials.css" flattenhtml="true" compress="gzip" />
-      <structure type="chrome_html" name="IDR_SHADOWSTYLE_MEDIA_CONTROLS_LOADING_CSS" file="mediaControls_loading.css" flattenhtml="true" compress="gzip" />
+      <structure type="chrome_html" name="IDR_UASTYLE_MEDIA_CONTROLS_CSS" file="mediaControls.css" flattenhtml="true" />
+      <structure type="chrome_html" name="IDR_UASTYLE_MEDIA_INTERSTITIALS_CSS" file="mediaInterstitials.css" flattenhtml="true" />
+      <structure type="chrome_html" name="IDR_SHADOWSTYLE_MEDIA_CONTROLS_LOADING_CSS" file="mediaControls_loading.css" flattenhtml="true" />
     </structures>
     <includes>
-      <include name="IDR_UASTYLE_MEDIA_CONTROLS_ANDROID_CSS" file="mediaControls_Android.css" type="BINDATA" compress="gzip" />
-      <include name="IDR_SHADOWSTYLE_MEDIA_CONTROLS_ANIMATED_ARROW_CSS" file="mediaControls_animated_arrow.css" type="BINDATA" compress="gzip" />
-      <include name="IDR_SHADOWSTYLE_MEDIA_CONTROLS_SCRUBBING_MESSAGE_CSS" file="mediaControls_scrubbing_message.css" type="BINDATA" compress="gzip" />
-      <include name="IDR_MEDIA_CONTROLS_JUMP_SVG" file="jump_image.svg" type="BINDATA" compress="gzip" />
-      <include name="IDR_MEDIA_CONTROLS_ARROW_RIGHT_SVG" file="ic_arrow_right.svg" type="BINDATA" compress="gzip" />
-      <include name="IDR_MEDIA_CONTROLS_ARROW_LEFT_SVG" file="ic_arrow_left.svg" type="BINDATA" compress="gzip" />
+      <include name="IDR_UASTYLE_MEDIA_CONTROLS_ANDROID_CSS" file="mediaControls_Android.css" type="BINDATA" />
+      <include name="IDR_SHADOWSTYLE_MEDIA_CONTROLS_ANIMATED_ARROW_CSS" file="mediaControls_animated_arrow.css" type="BINDATA" />
+      <include name="IDR_SHADOWSTYLE_MEDIA_CONTROLS_SCRUBBING_MESSAGE_CSS" file="mediaControls_scrubbing_message.css" type="BINDATA" />
+      <include name="IDR_MEDIA_CONTROLS_JUMP_SVG" file="jump_image.svg" type="BINDATA" />
+      <include name="IDR_MEDIA_CONTROLS_ARROW_RIGHT_SVG" file="ic_arrow_right.svg" type="BINDATA" />
+      <include name="IDR_MEDIA_CONTROLS_ARROW_LEFT_SVG" file="ic_arrow_left.svg" type="BINDATA" />
     </includes>
   </release>
 </grit>
diff --git a/third_party/blink/renderer/modules/native_file_system/native_file_system_writable_file_stream.cc b/third_party/blink/renderer/modules/native_file_system/native_file_system_writable_file_stream.cc
index 56d5db3..4eff753 100644
--- a/third_party/blink/renderer/modules/native_file_system/native_file_system_writable_file_stream.cc
+++ b/third_party/blink/renderer/modules/native_file_system/native_file_system_writable_file_stream.cc
@@ -36,8 +36,7 @@
   auto* init = QueuingStrategyInit::Create();
   // HighWaterMark set to 1 here. This allows the stream to appear available
   // without adding additional buffering.
-  init->setHighWaterMark(
-      ScriptValue::From(script_state, static_cast<double>(1)));
+  init->setHighWaterMark(1);
   auto* strategy = CountQueuingStrategy::Create(script_state, init);
   ScriptValue strategy_value = ScriptValue::From(script_state, strategy);
 
diff --git a/third_party/blink/renderer/modules/payments/payment_test_helper.cc b/third_party/blink/renderer/modules/payments/payment_test_helper.cc
index 09aaffa..71bb2070 100644
--- a/third_party/blink/renderer/modules/payments/payment_test_helper.cc
+++ b/third_party/blink/renderer/modules/payments/payment_test_helper.cc
@@ -214,10 +214,7 @@
 }
 
 PaymentRequestV8TestingScope::PaymentRequestV8TestingScope()
-    : V8TestingScope(KURL("https://www.example.com/")) {
-  GetWindow().GetSecurityContext().SetSecureContextModeForTesting(
-      SecureContextMode::kSecureContext);
-}
+    : V8TestingScope(KURL("https://www.example.com/")) {}
 
 PaymentRequestMockFunctionScope::PaymentRequestMockFunctionScope(
     ScriptState* script_state)
diff --git a/third_party/blink/renderer/modules/sensor/sensor_test_utils.cc b/third_party/blink/renderer/modules/sensor/sensor_test_utils.cc
index 49e8cea..96539f7 100644
--- a/third_party/blink/renderer/modules/sensor/sensor_test_utils.cc
+++ b/third_party/blink/renderer/modules/sensor/sensor_test_utils.cc
@@ -39,12 +39,8 @@
 
 // SensorTestContext
 
-SensorTestContext::SensorTestContext() {
-  // Sensor's constructor has a check for this that could be removed in the
-  // future.
-  testing_scope_.GetWindow()
-      .GetSecurityContext()
-      .SetSecureContextModeForTesting(SecureContextMode::kSecureContext);
+SensorTestContext::SensorTestContext()
+    : testing_scope_(KURL("https://example.com")) {
   // Necessary for SensorProxy::ShouldSuspendUpdates() to work correctly.
   testing_scope_.GetPage().GetFocusController().SetFocused(true);
 
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc b/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc
index f0f91e3..9fbb0ab 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_container_test.cc
@@ -192,13 +192,6 @@
 
   void SetPageURL(const String& url) {
     NavigateTo(KURL(NullURL(), url));
-
-    if (url.StartsWith("https://") || url.StartsWith("http://localhost/")) {
-      GetFrame()
-          .DomWindow()
-          ->GetSecurityContext()
-          .SetSecureContextModeForTesting(SecureContextMode::kSecureContext);
-    }
   }
 
   void TestRegisterRejected(const String& script_url,
diff --git a/third_party/blink/renderer/platform/graphics/color_space_gamut.cc b/third_party/blink/renderer/platform/graphics/color_space_gamut.cc
index 2284c784..95a0b35 100644
--- a/third_party/blink/renderer/platform/graphics/color_space_gamut.cc
+++ b/third_party/blink/renderer/platform/graphics/color_space_gamut.cc
@@ -16,10 +16,12 @@
   if (!color_space.IsValid())
     return ColorSpaceGamut::kUnknown;
 
-  // Return the gamut of the color space used for raster (this will return a
-  // wide gamut for HDR profiles).
-  sk_sp<SkColorSpace> sk_color_space =
-      color_space.GetRasterColorSpace().ToSkColorSpace();
+  // TODO(crbug.com/1049334): Change this function to operate on a
+  // gfx::DisplayColorSpaces structure.
+  if (color_space.IsHDR())
+    return ColorSpaceGamut::BT2020;
+
+  sk_sp<SkColorSpace> sk_color_space = color_space.ToSkColorSpace();
   if (!sk_color_space)
     return ColorSpaceGamut::kUnknown;
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h b/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h
index f3af418..c240567 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h
@@ -65,6 +65,18 @@
   // https://html.spec.whatwg.org/C/#concept-settings-object-referrer-policy
   virtual network::mojom::ReferrerPolicy GetReferrerPolicy() const = 0;
 
+  // |GetReferrerPolicyDisregardingMetaTagsContainingLists|
+  // returns the policy that would have been set had we been ignoring all <meta
+  // name=referrer> tags with values comma-separated lists of policies. This
+  // allows histogramming the proportion of requests that would end up with
+  // different referrers were these tags ignored, helping interpret the impact
+  // of removing support for them (which is inconsistent with the spec and other
+  // engines).
+  virtual base::Optional<network::mojom::ReferrerPolicy>
+  GetReferrerPolicyDisregardingMetaTagsContainingLists() const {
+    return base::nullopt;
+  }
+
   // "referrerURL" used in the "Determine request's Referrer" algorithm:
   // https://w3c.github.io/webappsec-referrer-policy/#determine-requests-referrer
   virtual const String GetOutgoingReferrer() const = 0;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
index 8a229e01..be894cdc 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -295,9 +295,9 @@
 
 // This function corresponds with step 2 substep 7 of
 // https://fetch.spec.whatwg.org/#main-fetch.
-void SetReferrer(
-    ResourceRequest& request,
-    const FetchClientSettingsObject& fetch_client_settings_object) {
+void SetReferrer(ResourceRequest& request,
+                 const FetchClientSettingsObject& fetch_client_settings_object,
+                 UseCounter& use_counter) {
   String referrer_to_use = request.ReferrerString();
   network::mojom::ReferrerPolicy referrer_policy_to_use =
       request.GetReferrerPolicy();
@@ -305,11 +305,42 @@
   if (referrer_to_use == Referrer::ClientReferrerString())
     referrer_to_use = fetch_client_settings_object.GetOutgoingReferrer();
 
-  if (referrer_policy_to_use == network::mojom::ReferrerPolicy::kDefault)
+  bool used_referrer_policy_from_context = false;
+  if (referrer_policy_to_use == network::mojom::ReferrerPolicy::kDefault) {
+    used_referrer_policy_from_context = true;
     referrer_policy_to_use = fetch_client_settings_object.GetReferrerPolicy();
+  }
 
   Referrer generated_referrer = SecurityPolicy::GenerateReferrer(
       referrer_policy_to_use, request.Url(), referrer_to_use);
+
+  // The request's referrer would be different in the absence of <meta
+  // name=referrer> tags with comma-separated-list values exactly when both
+  // 1. the request falls back to its client settings object's policy; and
+  // 2. if we recompute the referrer using the value of the client settings
+  // object's policy, disregarding any policy that came from a meta tag with a
+  // comma-separated value, we obtain a different referrer.
+  if (used_referrer_policy_from_context) {
+    base::Optional<network::mojom::blink::ReferrerPolicy>
+        policy_but_for_meta_tags_with_policy_lists =
+            fetch_client_settings_object
+                .GetReferrerPolicyDisregardingMetaTagsContainingLists();
+
+    bool referrer_would_be_different_absent_meta_tags_with_policy_lists =
+        policy_but_for_meta_tags_with_policy_lists.has_value() &&
+        (generated_referrer.referrer !=
+         SecurityPolicy::GenerateReferrer(
+             *policy_but_for_meta_tags_with_policy_lists, request.Url(),
+             referrer_to_use)
+             .referrer);
+
+    if (referrer_would_be_different_absent_meta_tags_with_policy_lists) {
+      use_counter.CountUse(
+          mojom::WebFeature::
+              kHTMLMetaElementReferrerPolicyMultipleTokensAffectingRequest);
+    }
+  }
+
   request.SetReferrerString(generated_referrer.referrer);
   request.SetReferrerPolicy(generated_referrer.referrer_policy);
 }
@@ -907,7 +938,8 @@
                                              http_names::kGET &&
                                          !params.IsStaleRevalidation());
 
-  SetReferrer(resource_request, properties_->GetFetchClientSettingsObject());
+  SetReferrer(resource_request, properties_->GetFetchClientSettingsObject(),
+              GetUseCounter());
 
   resource_request.SetExternalRequestStateFromRequestorAddressSpace(
       properties_->GetFetchClientSettingsObject().GetAddressSpace());
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 ee67e44..9c75e13 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -728,6 +728,17 @@
     return false;
   }
 
+  const ResourceRequestHead& initial_request = resource_->GetResourceRequest();
+  if (initial_request.GetRedirectMode() ==
+      network::mojom::RedirectMode::kError) {
+    // The network::cors::CorsURLLoader would reject the redirect in any case,
+    // but we reject the redirect here because otherwise we would see confusing
+    // errors such as MixedContent errors in the console during redirect
+    // handling.
+    HandleError(ResourceError::Failure(new_url));
+    return false;
+  }
+
   std::unique_ptr<ResourceRequest> new_request =
       resource_->LastResourceRequest().CreateRedirectRequest(
           new_url, new_method, new_site_for_cookies, new_referrer,
@@ -741,7 +752,6 @@
 
   ResourceType resource_type = resource_->GetType();
 
-  const ResourceRequestHead& initial_request = resource_->GetResourceRequest();
   // The following parameters never change during the lifetime of a request.
   mojom::RequestContextType request_context =
       initial_request.GetRequestContext();
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index b100eda..d1e7c1e 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1013,9 +1013,6 @@
       // Used for API surface that will be removed when the Native File System
       // API is no longer guarded by an origin trial.
       name: "LegacyNativeFileSystem",
-      status: {"Android": "test", "default": "experimental"},
-      origin_trial_feature_name: "NativeFileSystem2",
-      origin_trial_os: ["win", "macosx", "linux", "chromeos"],
     },
     {
       name: "LegacyWindowsDWriteFontFallback",
diff --git a/third_party/blink/web_tests/LeakExpectations b/third_party/blink/web_tests/LeakExpectations
index 0fff2449..78154a9 100644
--- a/third_party/blink/web_tests/LeakExpectations
+++ b/third_party/blink/web_tests/LeakExpectations
@@ -129,17 +129,9 @@
 crbug.com/1068175 [ Linux ] external/wpt/referrer-policy/gen/worker-module.http-rp/strict-origin-when-cross-origin/worker-module.http.html [ Pass Timeout ]
 crbug.com/1068175 [ Linux ] external/wpt/referrer-policy/gen/worker-module.http-rp/strict-origin/worker-module.http.html [ Pass Timeout ]
 crbug.com/1068175 [ Linux ] virtual/omt-worker-fetch/external/wpt/referrer-policy/gen/worker-classic.http-rp/no-referrer-when-downgrade/worker-classic.http.html [ Pass Timeout ]
-crbug.com/1068175 [ Linux ] virtual/omt-worker-fetch/external/wpt/referrer-policy/gen/worker-classic.http-rp/origin-when-cross-origin/worker-classic.http.html [ Pass Timeout ]
 crbug.com/1068175 [ Linux ] virtual/omt-worker-fetch/external/wpt/referrer-policy/gen/worker-classic.http-rp/origin-when-cross-origin/worker-module.http.html [ Pass Timeout ]
 crbug.com/1068175 [ Linux ] virtual/omt-worker-fetch/external/wpt/referrer-policy/gen/worker-classic.http-rp/same-origin/worker-classic.http.html [ Pass Timeout ]
-crbug.com/1068175 [ Linux ] virtual/omt-worker-fetch/external/wpt/referrer-policy/gen/worker-classic.http-rp/same-origin/worker-module.http.html [ Pass Timeout ]
 crbug.com/1068175 [ Linux ] virtual/omt-worker-fetch/external/wpt/referrer-policy/gen/worker-classic.http-rp/strict-origin-when-cross-origin/worker-classic.http.html [ Pass Timeout ]
-crbug.com/1068175 [ Linux ] virtual/omt-worker-fetch/external/wpt/referrer-policy/gen/worker-classic.http-rp/strict-origin-when-cross-origin/worker-module.http.html [ Pass Timeout ]
-crbug.com/1068175 [ Linux ] virtual/omt-worker-fetch/external/wpt/referrer-policy/gen/worker-module.http-rp/no-referrer-when-downgrade/worker-classic.http.html [ Pass Timeout ]
-crbug.com/1068175 [ Linux ] virtual/omt-worker-fetch/external/wpt/referrer-policy/gen/worker-module.http-rp/origin-when-cross-origin/worker-classic.http.html [ Pass Timeout ]
-crbug.com/1068175 [ Linux ] virtual/omt-worker-fetch/external/wpt/referrer-policy/gen/worker-module.http-rp/origin/worker-classic.http.html [ Pass Timeout ]
-crbug.com/1068175 [ Linux ] virtual/omt-worker-fetch/external/wpt/referrer-policy/gen/worker-module.http-rp/strict-origin-when-cross-origin/worker-classic.http.html [ Pass Timeout ]
-crbug.com/1068175 [ Linux ] virtual/omt-worker-fetch/external/wpt/referrer-policy/gen/worker-module.http-rp/unsafe-url/worker-classic.http.html [ Pass Timeout ]
 crbug.com/1068175 [ Linux ] virtual/omt-worker-fetch/external/wpt/referrer-policy/gen/worker-module.http-rp/unset/worker-classic.http.html [ Pass Timeout ]
 
 # Sheriff 2020-04-20
@@ -163,7 +155,6 @@
 
 # Sheriff 2020-07-14
 crbug.com/1068175 [ Linux ] external/wpt/referrer-policy/gen/worker-module.http-rp/strict-origin-when-cross-origin/worker-classic.http.html [ Pass Timeout ]
-crbug.com/1068175 [ Linux ] virtual/cors/external/wpt/referrer-policy/gen/worker-module.http-rp/strict-origin/worker-classic.http.html [ Pass Timeout ]
 crbug.com/1068175 [ Linux ] virtual/omt-worker-fetch/external/wpt/referrer-policy/gen/worker-classic.http-rp/no-referrer/worker-classic.http.html [ Pass Timeout ]
 crbug.com/1068175 [ Linux ] external/wpt/referrer-policy/gen/worker-module.http-rp/unsafe-url/worker-classic.http.html [ Pass Timeout ]
 crbug.com/1068175 [ Linux ] external/wpt/referrer-policy/gen/worker-module.http-rp/unset/worker-module.http.html [ Pass Timeout ]
@@ -175,7 +166,6 @@
 crbug.com/1068175 [ Linux ] external/wpt/referrer-policy/gen/worker-module.http-rp/origin/worker-classic.http.html [ Pass Timeout ]
 crbug.com/1068175 [ Linux ] external/wpt/referrer-policy/gen/worker-classic.http-rp/same-origin/worker-module.http.html [ Pass Timeout ]
 crbug.com/1068175 [ Linux ] external/wpt/referrer-policy/gen/worker-classic.http-rp/origin-when-cross-origin/worker-classic.http.html [ Pass Timeout ]
-crbug.com/1068175 [ Linux ] virtual/cors/external/wpt/referrer-policy/gen/worker-classic.http-rp/origin-when-cross-origin/worker-classic.http.html [ Pass Timeout ]
 
 # This test triggers existing leaky behavior, but this test also catches
 # a prior crash.
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index d2a8cf7c..0419f45 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -1198,7 +1198,6 @@
 virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/normal-flow/min-width-applies-to-012.xht [ Pass ]
 virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/normal-flow/width-applies-to-012.xht [ Pass ]
 
-crbug.com/982194 [ Win ] virtual/layout_ng_fragment_traversal/external/wpt/css/CSS2/linebox/empty-inline-002.xht [ Failure ]
 crbug.com/982194 [ Mac ] virtual/layout_ng_fragment_traversal/fast/table/027-vertical.html [ Failure ]
 crbug.com/982194 [ Mac ] virtual/layout_ng_fragment_traversal/fast/table/border-collapsing/003-vertical.html [ Failure ]
 
@@ -2694,15 +2693,9 @@
 crbug.com/626703 [ Linux ] virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-gutters-014.html [ Failure ]
 crbug.com/626703 [ Mac ] virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-gutters-014.html [ Failure ]
 crbug.com/626703 [ Win ] virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-gutters-014.html [ Failure ]
-crbug.com/626703 [ Linux ] virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-baseline-justify-001.html [ Failure ]
-crbug.com/626703 [ Mac ] virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-baseline-justify-001.html [ Failure ]
-crbug.com/626703 [ Win ] virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-baseline-justify-001.html [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/css/css-grid/alignment/grid-baseline-justify-001.html [ Failure ]
 crbug.com/626703 [ Mac ] external/wpt/css/css-grid/alignment/grid-baseline-justify-001.html [ Failure ]
 crbug.com/626703 [ Win ] external/wpt/css/css-grid/alignment/grid-baseline-justify-001.html [ Failure ]
-crbug.com/626703 [ Linux ] virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-baseline-align-001.html [ Failure ]
-crbug.com/626703 [ Mac ] virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-baseline-align-001.html [ Failure ]
-crbug.com/626703 [ Win ] virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-baseline-align-001.html [ Failure ]
 crbug.com/626703 [ Linux ] external/wpt/css/css-grid/alignment/grid-baseline-align-001.html [ Failure ]
 crbug.com/626703 [ Mac ] external/wpt/css/css-grid/alignment/grid-baseline-align-001.html [ Failure ]
 crbug.com/626703 [ Win ] external/wpt/css/css-grid/alignment/grid-baseline-align-001.html [ Failure ]
@@ -6854,8 +6847,6 @@
 crbug.com/1104134 [ Mac10.14 ] virtual/controls-refresh-hc/fast/forms/color-scheme/range/range-pressed-state.html [ Pass Failure ]
 
 crbug.com/1102167 external/wpt/fetch/redirect-navigate/preserve-fragment.html [ Timeout Pass ]
-crbug.com/1102167 virtual/cors/external/wpt/fetch/redirect-navigate/preserve-fragment.html [ Timeout Pass ]
-crbug.com/1102167 virtual/omt-worker-fetch/external/wpt/fetch/redirect-navigate/preserve-fragment.html [ Timeout Pass ]
 
 crbug.com/1104186 [ Win ] fast/forms/color-scheme/suggestion-picker/time-suggestion-picker-appearance.html [ Pass Failure ]
 
@@ -6868,7 +6859,6 @@
 crbug.com/1104910 fast/dom/cssTarget-crash.html [ Pass Timeout Failure ]
 crbug.com/1104910 fast/peerconnection/RTCPeerConnection-reload-interesting-usage.html [ Pass Failure ]
 crbug.com/1104910 inspector-protocol/stylesheet-tracking-restart.js [ Pass Failure ]
-crbug.com/1104910 virtual/web-components-v0-disabled/fast/dom/cssTarget-crash.html [ Pass Timeout Failure ]
 crbug.com/1104910 [ Win ] virtual/cache-storage-eager-reading/external/wpt/service-workers/service-worker/registration-updateviacache.https.html [ Pass Failure ]
 crbug.com/1104910 [ Win ] http/tests/devtools/elements/styles-1/dynamic-style-tag.js [ Pass Failure ]
 crbug.com/1104910 [ Mac10.15 ] editing/selection/selection-background.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/inserted-or-removed.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/inserted-or-removed.html
index 1b3f8631..ee123164 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/inserted-or-removed.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/inserted-or-removed.html
@@ -56,6 +56,22 @@
 }, 'The last selected OPTION should win; Inserted by DOM API');
 
 test(() => {
+  const target = document.querySelector("#by-dom");
+  target.innerHTML = '';
+  const inner = `<option value="one" selected>First</option>
+      <option value="two" selected>Second</option>`;
+
+  // Emulate what jQuery 1.x/2.x does in append(inner).
+  const fragment = document.createDocumentFragment();
+  const div = document.createElement('div');
+  div.innerHTML = '<select multiple>' + inner + '</select>';
+  while (div.firstChild.firstChild)
+    fragment.appendChild(div.firstChild.firstChild);
+  target.appendChild(fragment);
+  assert_equals(target.selectedOptions[0].textContent, 'Second');
+}, 'The last selected OPTION should win; Inserted by jQuery append()');
+
+test(() => {
   const target = document.querySelector("#by-innerHTML");
   target.innerHTML = '<option selected>First</option>' +
       '<option selected>Second</option>';
diff --git a/third_party/blink/web_tests/external/wpt/streams/byte-length-queuing-strategy.any-expected.txt b/third_party/blink/web_tests/external/wpt/streams/byte-length-queuing-strategy.any-expected.txt
deleted file mode 100644
index 28310bef..0000000
--- a/third_party/blink/web_tests/external/wpt/streams/byte-length-queuing-strategy.any-expected.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-This is a testharness.js-based test.
-PASS Can construct a ByteLengthQueuingStrategy with a valid high water mark
-PASS Can construct a ByteLengthQueuingStrategy with any value as its high water mark
-FAIL ByteLengthQueuingStrategy constructor behaves as expected with strange arguments assert_throws_js: construction fails with null function "() => new ByteLengthQueuingStrategy(null)" did not throw
-FAIL ByteLengthQueuingStrategy size behaves as expected with strange arguments Illegal invocation
-FAIL ByteLengthQueuingStrategy.prototype.size should work generically on its this and its arguments Illegal invocation
-FAIL ByteLengthQueuingStrategy instances have the correct properties assert_object_equals: highWaterMark property should be a data property with the value passed the constructor value is undefined, expected object
-FAIL ByteLengthQueuingStrategy's highWaterMark property can be set to anything Cannot assign to read only property 'highWaterMark' of object '#<ByteLengthQueuingStrategy>'
-PASS ByteLengthQueuingStrategy.name is correct
-PASS subclassing ByteLengthQueuingStrategy should work correctly
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/streams/byte-length-queuing-strategy.any.serviceworker-expected.txt b/third_party/blink/web_tests/external/wpt/streams/byte-length-queuing-strategy.any.serviceworker-expected.txt
deleted file mode 100644
index 28310bef..0000000
--- a/third_party/blink/web_tests/external/wpt/streams/byte-length-queuing-strategy.any.serviceworker-expected.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-This is a testharness.js-based test.
-PASS Can construct a ByteLengthQueuingStrategy with a valid high water mark
-PASS Can construct a ByteLengthQueuingStrategy with any value as its high water mark
-FAIL ByteLengthQueuingStrategy constructor behaves as expected with strange arguments assert_throws_js: construction fails with null function "() => new ByteLengthQueuingStrategy(null)" did not throw
-FAIL ByteLengthQueuingStrategy size behaves as expected with strange arguments Illegal invocation
-FAIL ByteLengthQueuingStrategy.prototype.size should work generically on its this and its arguments Illegal invocation
-FAIL ByteLengthQueuingStrategy instances have the correct properties assert_object_equals: highWaterMark property should be a data property with the value passed the constructor value is undefined, expected object
-FAIL ByteLengthQueuingStrategy's highWaterMark property can be set to anything Cannot assign to read only property 'highWaterMark' of object '#<ByteLengthQueuingStrategy>'
-PASS ByteLengthQueuingStrategy.name is correct
-PASS subclassing ByteLengthQueuingStrategy should work correctly
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/streams/byte-length-queuing-strategy.any.sharedworker-expected.txt b/third_party/blink/web_tests/external/wpt/streams/byte-length-queuing-strategy.any.sharedworker-expected.txt
deleted file mode 100644
index 28310bef..0000000
--- a/third_party/blink/web_tests/external/wpt/streams/byte-length-queuing-strategy.any.sharedworker-expected.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-This is a testharness.js-based test.
-PASS Can construct a ByteLengthQueuingStrategy with a valid high water mark
-PASS Can construct a ByteLengthQueuingStrategy with any value as its high water mark
-FAIL ByteLengthQueuingStrategy constructor behaves as expected with strange arguments assert_throws_js: construction fails with null function "() => new ByteLengthQueuingStrategy(null)" did not throw
-FAIL ByteLengthQueuingStrategy size behaves as expected with strange arguments Illegal invocation
-FAIL ByteLengthQueuingStrategy.prototype.size should work generically on its this and its arguments Illegal invocation
-FAIL ByteLengthQueuingStrategy instances have the correct properties assert_object_equals: highWaterMark property should be a data property with the value passed the constructor value is undefined, expected object
-FAIL ByteLengthQueuingStrategy's highWaterMark property can be set to anything Cannot assign to read only property 'highWaterMark' of object '#<ByteLengthQueuingStrategy>'
-PASS ByteLengthQueuingStrategy.name is correct
-PASS subclassing ByteLengthQueuingStrategy should work correctly
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/streams/byte-length-queuing-strategy.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/streams/byte-length-queuing-strategy.any.worker-expected.txt
deleted file mode 100644
index 28310bef..0000000
--- a/third_party/blink/web_tests/external/wpt/streams/byte-length-queuing-strategy.any.worker-expected.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-This is a testharness.js-based test.
-PASS Can construct a ByteLengthQueuingStrategy with a valid high water mark
-PASS Can construct a ByteLengthQueuingStrategy with any value as its high water mark
-FAIL ByteLengthQueuingStrategy constructor behaves as expected with strange arguments assert_throws_js: construction fails with null function "() => new ByteLengthQueuingStrategy(null)" did not throw
-FAIL ByteLengthQueuingStrategy size behaves as expected with strange arguments Illegal invocation
-FAIL ByteLengthQueuingStrategy.prototype.size should work generically on its this and its arguments Illegal invocation
-FAIL ByteLengthQueuingStrategy instances have the correct properties assert_object_equals: highWaterMark property should be a data property with the value passed the constructor value is undefined, expected object
-FAIL ByteLengthQueuingStrategy's highWaterMark property can be set to anything Cannot assign to read only property 'highWaterMark' of object '#<ByteLengthQueuingStrategy>'
-PASS ByteLengthQueuingStrategy.name is correct
-PASS subclassing ByteLengthQueuingStrategy should work correctly
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/streams/count-queuing-strategy.any-expected.txt b/third_party/blink/web_tests/external/wpt/streams/count-queuing-strategy.any-expected.txt
deleted file mode 100644
index 6d6107c..0000000
--- a/third_party/blink/web_tests/external/wpt/streams/count-queuing-strategy.any-expected.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-This is a testharness.js-based test.
-PASS Can construct a CountQueuingStrategy with a valid high water mark
-PASS Can construct a CountQueuingStrategy with any value as its high water mark
-FAIL CountQueuingStrategy constructor behaves as expected with strange arguments assert_throws_js: construction fails with null function "() => new CountQueuingStrategy(null)" did not throw
-FAIL CountQueuingStrategy.prototype.size should work generically on its this and its arguments Illegal invocation
-FAIL CountQueuingStrategy size behaves as expected with strange arguments Illegal invocation
-FAIL CountQueuingStrategy instances have the correct properties assert_object_equals: highWaterMark property should be a data property with the value passed the constructor value is undefined, expected object
-FAIL CountQueuingStrategy's highWaterMark property can be set to anything Cannot assign to read only property 'highWaterMark' of object '#<CountQueuingStrategy>'
-PASS CountQueuingStrategy.name is correct
-PASS subclassing CountQueuingStrategy should work correctly
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/streams/count-queuing-strategy.any.serviceworker-expected.txt b/third_party/blink/web_tests/external/wpt/streams/count-queuing-strategy.any.serviceworker-expected.txt
deleted file mode 100644
index 6d6107c..0000000
--- a/third_party/blink/web_tests/external/wpt/streams/count-queuing-strategy.any.serviceworker-expected.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-This is a testharness.js-based test.
-PASS Can construct a CountQueuingStrategy with a valid high water mark
-PASS Can construct a CountQueuingStrategy with any value as its high water mark
-FAIL CountQueuingStrategy constructor behaves as expected with strange arguments assert_throws_js: construction fails with null function "() => new CountQueuingStrategy(null)" did not throw
-FAIL CountQueuingStrategy.prototype.size should work generically on its this and its arguments Illegal invocation
-FAIL CountQueuingStrategy size behaves as expected with strange arguments Illegal invocation
-FAIL CountQueuingStrategy instances have the correct properties assert_object_equals: highWaterMark property should be a data property with the value passed the constructor value is undefined, expected object
-FAIL CountQueuingStrategy's highWaterMark property can be set to anything Cannot assign to read only property 'highWaterMark' of object '#<CountQueuingStrategy>'
-PASS CountQueuingStrategy.name is correct
-PASS subclassing CountQueuingStrategy should work correctly
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/streams/count-queuing-strategy.any.sharedworker-expected.txt b/third_party/blink/web_tests/external/wpt/streams/count-queuing-strategy.any.sharedworker-expected.txt
deleted file mode 100644
index 6d6107c..0000000
--- a/third_party/blink/web_tests/external/wpt/streams/count-queuing-strategy.any.sharedworker-expected.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-This is a testharness.js-based test.
-PASS Can construct a CountQueuingStrategy with a valid high water mark
-PASS Can construct a CountQueuingStrategy with any value as its high water mark
-FAIL CountQueuingStrategy constructor behaves as expected with strange arguments assert_throws_js: construction fails with null function "() => new CountQueuingStrategy(null)" did not throw
-FAIL CountQueuingStrategy.prototype.size should work generically on its this and its arguments Illegal invocation
-FAIL CountQueuingStrategy size behaves as expected with strange arguments Illegal invocation
-FAIL CountQueuingStrategy instances have the correct properties assert_object_equals: highWaterMark property should be a data property with the value passed the constructor value is undefined, expected object
-FAIL CountQueuingStrategy's highWaterMark property can be set to anything Cannot assign to read only property 'highWaterMark' of object '#<CountQueuingStrategy>'
-PASS CountQueuingStrategy.name is correct
-PASS subclassing CountQueuingStrategy should work correctly
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/streams/count-queuing-strategy.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/streams/count-queuing-strategy.any.worker-expected.txt
deleted file mode 100644
index 6d6107c..0000000
--- a/third_party/blink/web_tests/external/wpt/streams/count-queuing-strategy.any.worker-expected.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-This is a testharness.js-based test.
-PASS Can construct a CountQueuingStrategy with a valid high water mark
-PASS Can construct a CountQueuingStrategy with any value as its high water mark
-FAIL CountQueuingStrategy constructor behaves as expected with strange arguments assert_throws_js: construction fails with null function "() => new CountQueuingStrategy(null)" did not throw
-FAIL CountQueuingStrategy.prototype.size should work generically on its this and its arguments Illegal invocation
-FAIL CountQueuingStrategy size behaves as expected with strange arguments Illegal invocation
-FAIL CountQueuingStrategy instances have the correct properties assert_object_equals: highWaterMark property should be a data property with the value passed the constructor value is undefined, expected object
-FAIL CountQueuingStrategy's highWaterMark property can be set to anything Cannot assign to read only property 'highWaterMark' of object '#<CountQueuingStrategy>'
-PASS CountQueuingStrategy.name is correct
-PASS subclassing CountQueuingStrategy should work correctly
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/streams/queuing-strategies-size-function-per-global.window.js b/third_party/blink/web_tests/external/wpt/streams/queuing-strategies-size-function-per-global.window.js
new file mode 100644
index 0000000..0f869f1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/streams/queuing-strategies-size-function-per-global.window.js
@@ -0,0 +1,14 @@
+const iframe = document.createElement('iframe');
+document.body.appendChild(iframe);
+
+for (const type of ['CountQueuingStrategy', 'ByteLengthQueuingStrategy']) {
+  test(() => {
+    const myQs = new window[type]({ highWaterMark: 1 });
+    const yourQs = new iframe.contentWindow[type]({ highWaterMark: 1 });
+    assert_not_equals(myQs.size, yourQs.size,
+                      'size should not be the same object');
+  }, `${type} size should be different for objects in different realms`);
+}
+
+// Cleanup the document to avoid messing up the result page.
+iframe.remove();
diff --git a/third_party/blink/web_tests/external/wpt/streams/queuing-strategies.any-expected.txt b/third_party/blink/web_tests/external/wpt/streams/queuing-strategies.any-expected.txt
deleted file mode 100644
index a98677b..0000000
--- a/third_party/blink/web_tests/external/wpt/streams/queuing-strategies.any-expected.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-This is a testharness.js-based test.
-PASS CountQueuingStrategy: Can construct a with a valid high water mark
-FAIL CountQueuingStrategy: Constructor behaves as expected with strange arguments assert_throws_js: construction fails with null function "() => new QueuingStrategy(null)" did not throw
-FAIL CountQueuingStrategy: highWaterMark constructor values are converted per the unrestricted double rules assert_equals: false gets set correctly expected (number) 0 but got (boolean) false
-FAIL CountQueuingStrategy: size is the same function across all instances assert_equals: expected function "function () { [native code] }" but got function "function () { [native code] }"
-FAIL CountQueuingStrategy: size should have the right name assert_equals: expected "size" but got ""
-PASS CountQueuingStrategy: subclassing should work correctly
-PASS ByteLengthQueuingStrategy: Can construct a with a valid high water mark
-FAIL ByteLengthQueuingStrategy: Constructor behaves as expected with strange arguments assert_throws_js: construction fails with null function "() => new QueuingStrategy(null)" did not throw
-FAIL ByteLengthQueuingStrategy: highWaterMark constructor values are converted per the unrestricted double rules assert_equals: false gets set correctly expected (number) 0 but got (boolean) false
-FAIL ByteLengthQueuingStrategy: size is the same function across all instances assert_equals: expected function "function () { [native code] }" but got function "function () { [native code] }"
-FAIL ByteLengthQueuingStrategy: size should have the right name assert_equals: expected "size" but got ""
-PASS ByteLengthQueuingStrategy: subclassing should work correctly
-PASS CountQueuingStrategy: size should have the right length
-FAIL ByteLengthQueuingStrategy: size should have the right length assert_equals: expected 1 but got 0
-PASS CountQueuingStrategy: size behaves as expected with strange arguments
-PASS ByteLengthQueuingStrategy: size behaves as expected with strange arguments
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/streams/queuing-strategies.any.serviceworker-expected.txt b/third_party/blink/web_tests/external/wpt/streams/queuing-strategies.any.serviceworker-expected.txt
deleted file mode 100644
index a98677b..0000000
--- a/third_party/blink/web_tests/external/wpt/streams/queuing-strategies.any.serviceworker-expected.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-This is a testharness.js-based test.
-PASS CountQueuingStrategy: Can construct a with a valid high water mark
-FAIL CountQueuingStrategy: Constructor behaves as expected with strange arguments assert_throws_js: construction fails with null function "() => new QueuingStrategy(null)" did not throw
-FAIL CountQueuingStrategy: highWaterMark constructor values are converted per the unrestricted double rules assert_equals: false gets set correctly expected (number) 0 but got (boolean) false
-FAIL CountQueuingStrategy: size is the same function across all instances assert_equals: expected function "function () { [native code] }" but got function "function () { [native code] }"
-FAIL CountQueuingStrategy: size should have the right name assert_equals: expected "size" but got ""
-PASS CountQueuingStrategy: subclassing should work correctly
-PASS ByteLengthQueuingStrategy: Can construct a with a valid high water mark
-FAIL ByteLengthQueuingStrategy: Constructor behaves as expected with strange arguments assert_throws_js: construction fails with null function "() => new QueuingStrategy(null)" did not throw
-FAIL ByteLengthQueuingStrategy: highWaterMark constructor values are converted per the unrestricted double rules assert_equals: false gets set correctly expected (number) 0 but got (boolean) false
-FAIL ByteLengthQueuingStrategy: size is the same function across all instances assert_equals: expected function "function () { [native code] }" but got function "function () { [native code] }"
-FAIL ByteLengthQueuingStrategy: size should have the right name assert_equals: expected "size" but got ""
-PASS ByteLengthQueuingStrategy: subclassing should work correctly
-PASS CountQueuingStrategy: size should have the right length
-FAIL ByteLengthQueuingStrategy: size should have the right length assert_equals: expected 1 but got 0
-PASS CountQueuingStrategy: size behaves as expected with strange arguments
-PASS ByteLengthQueuingStrategy: size behaves as expected with strange arguments
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/streams/queuing-strategies.any.sharedworker-expected.txt b/third_party/blink/web_tests/external/wpt/streams/queuing-strategies.any.sharedworker-expected.txt
deleted file mode 100644
index a98677b..0000000
--- a/third_party/blink/web_tests/external/wpt/streams/queuing-strategies.any.sharedworker-expected.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-This is a testharness.js-based test.
-PASS CountQueuingStrategy: Can construct a with a valid high water mark
-FAIL CountQueuingStrategy: Constructor behaves as expected with strange arguments assert_throws_js: construction fails with null function "() => new QueuingStrategy(null)" did not throw
-FAIL CountQueuingStrategy: highWaterMark constructor values are converted per the unrestricted double rules assert_equals: false gets set correctly expected (number) 0 but got (boolean) false
-FAIL CountQueuingStrategy: size is the same function across all instances assert_equals: expected function "function () { [native code] }" but got function "function () { [native code] }"
-FAIL CountQueuingStrategy: size should have the right name assert_equals: expected "size" but got ""
-PASS CountQueuingStrategy: subclassing should work correctly
-PASS ByteLengthQueuingStrategy: Can construct a with a valid high water mark
-FAIL ByteLengthQueuingStrategy: Constructor behaves as expected with strange arguments assert_throws_js: construction fails with null function "() => new QueuingStrategy(null)" did not throw
-FAIL ByteLengthQueuingStrategy: highWaterMark constructor values are converted per the unrestricted double rules assert_equals: false gets set correctly expected (number) 0 but got (boolean) false
-FAIL ByteLengthQueuingStrategy: size is the same function across all instances assert_equals: expected function "function () { [native code] }" but got function "function () { [native code] }"
-FAIL ByteLengthQueuingStrategy: size should have the right name assert_equals: expected "size" but got ""
-PASS ByteLengthQueuingStrategy: subclassing should work correctly
-PASS CountQueuingStrategy: size should have the right length
-FAIL ByteLengthQueuingStrategy: size should have the right length assert_equals: expected 1 but got 0
-PASS CountQueuingStrategy: size behaves as expected with strange arguments
-PASS ByteLengthQueuingStrategy: size behaves as expected with strange arguments
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/streams/queuing-strategies.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/streams/queuing-strategies.any.worker-expected.txt
deleted file mode 100644
index a98677b..0000000
--- a/third_party/blink/web_tests/external/wpt/streams/queuing-strategies.any.worker-expected.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-This is a testharness.js-based test.
-PASS CountQueuingStrategy: Can construct a with a valid high water mark
-FAIL CountQueuingStrategy: Constructor behaves as expected with strange arguments assert_throws_js: construction fails with null function "() => new QueuingStrategy(null)" did not throw
-FAIL CountQueuingStrategy: highWaterMark constructor values are converted per the unrestricted double rules assert_equals: false gets set correctly expected (number) 0 but got (boolean) false
-FAIL CountQueuingStrategy: size is the same function across all instances assert_equals: expected function "function () { [native code] }" but got function "function () { [native code] }"
-FAIL CountQueuingStrategy: size should have the right name assert_equals: expected "size" but got ""
-PASS CountQueuingStrategy: subclassing should work correctly
-PASS ByteLengthQueuingStrategy: Can construct a with a valid high water mark
-FAIL ByteLengthQueuingStrategy: Constructor behaves as expected with strange arguments assert_throws_js: construction fails with null function "() => new QueuingStrategy(null)" did not throw
-FAIL ByteLengthQueuingStrategy: highWaterMark constructor values are converted per the unrestricted double rules assert_equals: false gets set correctly expected (number) 0 but got (boolean) false
-FAIL ByteLengthQueuingStrategy: size is the same function across all instances assert_equals: expected function "function () { [native code] }" but got function "function () { [native code] }"
-FAIL ByteLengthQueuingStrategy: size should have the right name assert_equals: expected "size" but got ""
-PASS ByteLengthQueuingStrategy: subclassing should work correctly
-PASS CountQueuingStrategy: size should have the right length
-FAIL ByteLengthQueuingStrategy: size should have the right length assert_equals: expected 1 but got 0
-PASS CountQueuingStrategy: size behaves as expected with strange arguments
-PASS ByteLengthQueuingStrategy: size behaves as expected with strange arguments
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/flag-specific/force-device-scale-factor=1.5/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.png b/third_party/blink/web_tests/flag-specific/force-device-scale-factor=1.5/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.png
deleted file mode 100644
index 735bbbdd..0000000
--- a/third_party/blink/web_tests/flag-specific/force-device-scale-factor=1.5/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/http/tests/html/document_metadata/referrer-comma-separated-affecting-request-use-counter.html b/third_party/blink/web_tests/http/tests/html/document_metadata/referrer-comma-separated-affecting-request-use-counter.html
new file mode 100644
index 0000000..b5e48fc
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/html/document_metadata/referrer-comma-separated-affecting-request-use-counter.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+
+<!-- It's important these blocking script fetches precede the meta tag, in
+  order not to affect the use counters being measured. -->
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script>
+<script src="/gen/third_party/blink/public/mojom/web_feature/web_feature.mojom.js"></script>
+
+<head>
+  <meta name=referrer content="origin, origin" />
+</head>
+
+<script>
+  'use strict';
+
+  promise_test(async t => {
+    try {
+      await fetch('/resources/dummy.html', {
+        referrerPolicy: 'origin'
+      });
+      assert_false(internals.isUseCounted(document, blink.mojom.WebFeature.kHTMLMetaElementReferrerPolicyMultipleTokensAffectingRequest), "Counter shouldn't be populated");
+    } finally {
+      internals.clearUseCounter(document, blink.mojom.WebFeature.kHTMLMetaElementReferrerPolicyMultipleTokensAffectingRequest);
+    }
+  }, "<meta name=referrer> with multiple tokens doesn't affect the referrers of requests with explicitly set policies.");
+
+  promise_test(async t => {
+    try {
+      await fetch('/resources/dummy.html');
+      assert_true(internals.isUseCounted(document, blink.mojom.WebFeature.kHTMLMetaElementReferrerPolicyMultipleTokensAffectingRequest), "Counter should be populated");
+    } finally {
+      internals.clearUseCounter(document, blink.mojom.WebFeature.kHTMLMetaElementReferrerPolicyMultipleTokensAffectingRequest);
+    }
+  }, "<meta name=referrer> with multiple tokens does affect the referrers of this request using its document's policy.");
+</script>
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/native-file-system-origin-trial-interfaces.html b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/native-file-system-origin-trial-interfaces.html
index ad559b2f..81c93db 100644
--- a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/native-file-system-origin-trial-interfaces.html
+++ b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/native-file-system-origin-trial-interfaces.html
@@ -11,12 +11,11 @@
 <script>
 test(t => {
   OriginTrialsHelper.check_properties_exist(this, {
-    'FileSystemHandle': ['isFile', 'isDirectory', 'name', 'queryPermission', 'requestPermission'],
+    'FileSystemHandle': ['kind', 'name', 'queryPermission', 'requestPermission'],
     'FileSystemFileHandle': ['getFile', 'createWritable'],
-    'FileSystemDirectoryHandle': ['getFile', 'getDirectory', 'getEntries', 'removeEntry'],
+    'FileSystemDirectoryHandle': ['getFileHandle', 'getDirectoryHandle', 'getEntries', 'removeEntry'],
     'FileSystemWritableFileStream': ['write', 'truncate', 'close', 'seek'],
-    'global': ['chooseFileSystemEntries'],
+    'global': ['showOpenFilePicker', 'showSaveFilePicker', 'showDirectoryPicker', 'getOriginPrivateDirectory'],
   });
-  assert_true('getSystemDirectory' in self.FileSystemDirectoryHandle);
 }, 'Native File System API interfaces and properties in Origin-Trial enabled document.');
 </script>
diff --git a/third_party/blink/web_tests/http/tests/payments/payment-instruments.html b/third_party/blink/web_tests/http/tests/payments/payment-instruments.html
index 7ceccbda..bc51519 100644
--- a/third_party/blink/web_tests/http/tests/payments/payment-instruments.html
+++ b/third_party/blink/web_tests/http/tests/payments/payment-instruments.html
@@ -37,7 +37,7 @@
                     'src': './resources/icon-2x.png',
                     'sizes': '96x96',
                     'type': 'image/png',
-                    'purpose': 'any badge'
+                    'purpose': 'any monochrome'
                   }
                 ],
                 method: 'basic-card',
@@ -300,7 +300,7 @@
                     'src': './resources/icon-2x.png',
                     'sizes': '96x96',
                     'type': 'image/png',
-                    'purpose': 'any badge'
+                    'purpose': 'any monochrome'
                   }
                 ],
                 method: 'basic-card',
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 9ebe579..2f372ec 100644
--- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -558,13 +558,10 @@
     setter onloadstart
     setter onprogress
 interface FileSystemDirectoryHandle : FileSystemHandle
-    static method getSystemDirectory
     attribute @@toStringTag
     method constructor
-    method getDirectory
     method getDirectoryHandle
     method getEntries
-    method getFile
     method getFileHandle
     method removeEntry
     method resolve
@@ -575,8 +572,6 @@
     method getFile
 interface FileSystemHandle
     attribute @@toStringTag
-    getter isDirectory
-    getter isFile
     getter kind
     getter name
     method constructor
diff --git a/third_party/blink/web_tests/http/tests/streams/chromium/touching-global-object.html b/third_party/blink/web_tests/http/tests/streams/chromium/touching-global-object.html
index f265cb1..cc57ae1 100644
--- a/third_party/blink/web_tests/http/tests/streams/chromium/touching-global-object.html
+++ b/third_party/blink/web_tests/http/tests/streams/chromium/touching-global-object.html
@@ -90,7 +90,7 @@
       close() {
         resolve();
       }
-    }, new CountQueuingStrategy(10));
+    }, new CountQueuingStrategy({ highWaterMark: 10}));
     emptyRS.pipeThrough({
       writable: closeResolvesWS,
       readable: new ReadableStream()
@@ -144,7 +144,7 @@
   }
 
   async function testWritableStreamClose() {
-    const ws = new WritableStream({}, new ByteLengthQueuingStrategy(1024));
+    const ws = new WritableStream({}, new ByteLengthQueuingStrategy({ highWaterMark: 1024 }));
     const writer = ws.getWriter();
     await writer.close();
     await writer.closed;
diff --git a/third_party/blink/web_tests/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.html b/third_party/blink/web_tests/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.html
new file mode 100644
index 0000000..afba406
--- /dev/null
+++ b/third_party/blink/web_tests/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<script>
+onload = () => {
+    outerDiv.scrollTop = 300;
+    innerDiv.scrollTop = 400;
+}
+</script>
+<div style="height: 300px; overflow-y: scroll;" id="outerDiv">
+    <div style="height: 300px;"></div>
+    <div style="height: 400px; overflow-y: scroll;" id="innerDiv">
+        <div style="height: 800px; width: 300px; background: green"></div>
+    </div>
+</div>
diff --git a/third_party/blink/web_tests/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled.html b/third_party/blink/web_tests/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled.html
index 2ea5371..1ff3b9b 100644
--- a/third_party/blink/web_tests/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled.html
+++ b/third_party/blink/web_tests/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled.html
@@ -1,18 +1,18 @@
 <!DOCTYPE html>
-<html>
-<head>
-    <script src="../resources/text-based-repaint.js" type="text/javascript"></script>
-    <script>
-    function repaintTest() {
-        // Now scroll once in the #innerDiv to the green area.
-        if (window.eventSender)
-            eventSender.mouseScrollBy(0, -10);
-    }
-    window.addEventListener("load", runRepaintAndPixelTest, false);
-    </script>
-</head>
-<body>
-<!-- Bug 71550 - REGRESSION (r93614): Content remains despite parent element being scrolled off page using javascript. -->
+<script src="../resources/text-based-repaint.js"></script>
+<script>
+onload = () => {
+  // Scroll the outerDiv until we reach innerDiv.
+  outerDiv.scrollTop = 300;
+  runRepaintAndPixelTest();
+};
+
+function repaintTest() {
+    // Now scroll the innerDiv once to the green area.
+    innerDiv.scrollTop = 400;
+}
+</script>
+<!-- https://bugs.webkit.org/show_bug.cgi?id=71550 -->
 <!-- For the test to pass you should not see any RED or PURPLE, only green -->
 <div style="height: 300px; overflow-y: scroll;" id="outerDiv">
     <div style="height: 300px; background: purple;"></div>
@@ -21,17 +21,3 @@
         <div style="height: 400px; width: 300px; background: green"></div>
     </div>
 </div>
-<script>
-if (window.eventSender) {
-    if (window.internals)
-        internals.settings.setScrollAnimatorEnabled(false);
-
-    // Scroll the #outerDiv until we reach the #innerDiv.
-    eventSender.mouseMoveTo(50, 50);
-    eventSender.mouseScrollBy(0, -8);
-} else {
-    document.write("This test is better run under DumpRenderTree. To manually test it, continuously scroll down on the top-most element. There should be no repaint issue.");
-}
-</script>
-</body>
-</html>
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.png b/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.png
deleted file mode 100644
index a16ab6fd..0000000
--- a/third_party/blink/web_tests/platform/mac/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.png b/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.png
deleted file mode 100644
index decc654..0000000
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/scroll/overflow-scroll-in-overflow-scroll-scrolled-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/svg/as-image/preconnect-in-svg.html b/third_party/blink/web_tests/svg/as-image/preconnect-in-svg.html
new file mode 100644
index 0000000..c91178a
--- /dev/null
+++ b/third_party/blink/web_tests/svg/as-image/preconnect-in-svg.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<img src="data:image/svg+xml,
+  <svg xmlns='http://www.w3.org/2000/svg' xmlns:h='http://www.w3.org/1999/xhtml'>
+    <h:link rel='preconnect' href='http://example.com'/>
+  </svg>">
+<script>
+  // Test for https://crbug.com/1069289. The test passes if it does not crash.
+  test(() => {}, 'Preconnect request in SVG image does not crash.');
+</script>
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 7b815d3..5b8f6dce 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -493,13 +493,10 @@
 [Worker]     method readAsDataURL
 [Worker]     method readAsText
 [Worker] interface FileSystemDirectoryHandle : FileSystemHandle
-[Worker]     static method getSystemDirectory
 [Worker]     attribute @@toStringTag
 [Worker]     method constructor
-[Worker]     method getDirectory
 [Worker]     method getDirectoryHandle
 [Worker]     method getEntries
-[Worker]     method getFile
 [Worker]     method getFileHandle
 [Worker]     method removeEntry
 [Worker]     method resolve
@@ -510,8 +507,6 @@
 [Worker]     method getFile
 [Worker] interface FileSystemHandle
 [Worker]     attribute @@toStringTag
-[Worker]     getter isDirectory
-[Worker]     getter isFile
 [Worker]     getter kind
 [Worker]     getter name
 [Worker]     method constructor
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 313de99..baacc4d 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
@@ -2439,13 +2439,10 @@
     setter onloadstart
     setter onprogress
 interface FileSystemDirectoryHandle : FileSystemHandle
-    static method getSystemDirectory
     attribute @@toStringTag
     method constructor
-    method getDirectory
     method getDirectoryHandle
     method getEntries
-    method getFile
     method getFileHandle
     method removeEntry
     method resolve
@@ -2456,8 +2453,6 @@
     method getFile
 interface FileSystemHandle
     attribute @@toStringTag
-    getter isDirectory
-    getter isFile
     getter kind
     getter name
     method constructor
@@ -11921,7 +11916,6 @@
     method cancelAnimationFrame
     method cancelIdleCallback
     method captureEvents
-    method chooseFileSystemEntries
     method clearInterval
     method clearTimeout
     method close
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
index 3fb5b88..f12f3fcc 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -488,13 +488,10 @@
 [Worker]     method readAsDataURL
 [Worker]     method readAsText
 [Worker] interface FileSystemDirectoryHandle : FileSystemHandle
-[Worker]     static method getSystemDirectory
 [Worker]     attribute @@toStringTag
 [Worker]     method constructor
-[Worker]     method getDirectory
 [Worker]     method getDirectoryHandle
 [Worker]     method getEntries
-[Worker]     method getFile
 [Worker]     method getFileHandle
 [Worker]     method removeEntry
 [Worker]     method resolve
@@ -505,8 +502,6 @@
 [Worker]     method getFile
 [Worker] interface FileSystemHandle
 [Worker]     attribute @@toStringTag
-[Worker]     getter isDirectory
-[Worker]     getter isFile
 [Worker]     getter kind
 [Worker]     getter name
 [Worker]     method constructor
diff --git a/third_party/blink/web_tests/wpt_internal/html/semantics/embedded-content/the-iframe-element/iframe-subsequent-navigations-crash.sub.html b/third_party/blink/web_tests/wpt_internal/html/semantics/embedded-content/the-iframe-element/iframe-subsequent-navigations-crash.sub.html
new file mode 100644
index 0000000..c15293b
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/html/semantics/embedded-content/the-iframe-element/iframe-subsequent-navigations-crash.sub.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<head>
+  <title>Subsequent navigations to lazily loaded iframes do not crash the renderer</title>
+  <link rel="author" title="Dom Farolino" href="mailto:dom@chromium.org">
+  <link rel="help" href="https://html.spec.whatwg.org/multipage/urls-and-fetching.html#lazy-loading-attributes">
+  <script src="/resources/testharness.js"></script>
+  <script src="/resources/testharnessreport.js"></script>
+</head>
+
+<body>
+  <!-- This is used to represent the top of the viewport, so we can scroll the
+       below-viewport iframe out-of-view later in the test -->
+  <div id="top_div"></div>
+  <div style="height:1000vh;"></div>
+  <iframe id="below_viewport" loading="lazy"
+          src="http://{{domains[www]}}:{{ports[https][0]}}/html/semantics/embedded-content/the-iframe-element/resources/subframe.html">
+  </iframe>
+
+<script>
+  const t = async_test();
+  const iframe = document.querySelector('#below_viewport');
+  const top_div = document.querySelector('#top_div');
+
+  let has_window_load_fired = false;
+
+  // This should be triggered first.
+  window.addEventListener('load', t.step_func(() => {
+    has_window_load_fired = true;
+    // Scroll the loading=lazy below-viewport iframe into view, so that it loads.
+    iframe.scrollIntoView();
+  }));
+
+  iframe.onload = t.step_func_done(async () => {
+    assert_true(has_window_load_fired,
+                "The loading=lazy below-viewport iframe should not block the " +
+                "window load event");
+    await changeIframeSourceAndScrollToTop();
+  });
+
+  async function changeIframeSourceAndScrollToTop() {
+    // Lazily load a different iframe.
+    iframe.src =
+      'http://{{domains[www2]}}:{{ports[https][0]}}/html/semantics/embedded-content/the-iframe-element/resources/subframe.html'
+    await new Promise(resolve => {
+      iframe.onload = resolve;
+    });
+
+    top_div.scrollIntoView();
+
+    await new Promise(resolve => {
+      setTimeout(resolve, 500);
+    });
+
+    iframe.scrollIntoView();
+  }
+</script>
+</body>
diff --git a/third_party/jstemplate/jsevalcontext.js b/third_party/jstemplate/jsevalcontext.js
index b517c0d..cdb9ade 100644
--- a/third_party/jstemplate/jsevalcontext.js
+++ b/third_party/jstemplate/jsevalcontext.js
@@ -305,25 +305,21 @@
 /**
  * This is used to create TrustedScript.
  *
- * @type {TrustedTypePolicy|undefined}
+ * @type {!TrustedTypePolicy}
  */
-let opaqueScriptPolicy;
+let unsanitizedPolicy;
 if (window.trustedTypes) {
-  opaqueScriptPolicy =
-      trustedTypes.createPolicy('jstemplate', {
-        createScript: opaqueScript => {
-          // This is relatively safe because attribute's values can
-          // only reach here with `JsEvalContext` bootstrap. And even
-          // if opaqueScript calls dangerous sinks (e.g. innerHTML),
-          // it'll still be subject to type check with Trusted Types.
-          // This could be exploited if bootstrap is called with an
-          // event which can be triggered after the page load
-          // (e.g. onclick).
-          // TODO(crbug.com/525224): Eliminate the use of jstemplate
-          // in WebUI
-          return opaqueScript;
-        },
-      });
+  // This is relatively safe because attribute's values can
+  // only reach here with `JsEvalContext` bootstrap. And even
+  // if opaqueScript calls dangerous sinks (e.g. innerHTML),
+  // it'll still be subject to type check with Trusted Types.
+  // This could be exploited if bootstrap is called with an
+  // event which can be triggered after the page load
+  // (e.g. onclick).
+  // TODO(crbug.com/525224): Eliminate the use of jstemplate
+  // in WebUI
+  unsanitizedPolicy = trustedTypes.createPolicy(
+      'jstemplate', {createScript: opaqueScript => opaqueScript});
 }
 
 
@@ -351,7 +347,7 @@
       /** @type {string} */
       const f = `(function(a_, b_) { with (a_) with (b_) return ${expr} })`;
       /** @type {!TrustedScript|string} */
-      const opaqueExpr = window.trustedTypes ? opaqueScriptPolicy.createScript(f) : f;
+      const opaqueExpr = window.trustedTypes ? unsanitizedPolicy.createScript(f) : f;
 
       // TODO(crbug.com/1087743): Support Function constructor in Trusted Types
       // TODO(crbug.com/1091600): Support TrustedScript type as an argument to
diff --git a/tools/android/dependency_analysis/js/README.md b/tools/android/dependency_analysis/js/README.md
index ae47232..74dec70 100644
--- a/tools/android/dependency_analysis/js/README.md
+++ b/tools/android/dependency_analysis/js/README.md
@@ -19,7 +19,20 @@
 **The following instructions assume you are in the `dependency_analysis/js` = `$DEP_ANALYSIS_DIR/js` directory.**
 
 ### Install dependencies
-You will need to install `npm` if it is not already installed (check with `npm -v`), either [from the site](https://www.npmjs.com/get-npm) or via [nvm](https://github.com/nvm-sh/nvm#about) (Node Version Manager).
+
+First, ensure you have a new Node.js version. The dependency viewer doesn't work with v8, for example.
+
+```
+node -v
+```
+
+Install the latest version with:
+
+```
+nvm install node
+```
+
+You will also need to install `npm` if it is not already installed (check with `npm -v`), either [from the site](https://www.npmjs.com/get-npm) or via [nvm](https://github.com/nvm-sh/nvm#about) (Node Version Manager).
 
 To install dependencies:
 
diff --git a/tools/binary_size/milestone_apk_sizes.py b/tools/binary_size/milestone_apk_sizes.py
index 0c92698..c5104fb4 100755
--- a/tools/binary_size/milestone_apk_sizes.py
+++ b/tools/binary_size/milestone_apk_sizes.py
@@ -97,7 +97,6 @@
     artifacts.append(_Artifact(prefix, name))
     return artifacts[-1]
 
-  chrome = make_artifact('arm/ChromeStable.apk')
   webview = make_artifact('arm/AndroidWebview.apk')
   webview64 = make_artifact('arm_64/AndroidWebview.apk')
   chrome_modern = make_artifact('arm/ChromeModernStable.apks')
@@ -133,7 +132,6 @@
 
   # Add metrics in the order that we want them in the .csv output.
   metrics = collections.OrderedDict()
-  chrome.AddSize(metrics)
   chrome_modern.AddSize(metrics)
   chrome_modern64.AddSize(metrics)
   webview.AddSize(metrics)
@@ -160,13 +158,13 @@
   go_install_size = (
       trichrome_chrome.GetApkSize() + trichrome_webview.GetAndroidGoSize() +
       trichrome_library.GetAndroidGoSize())
-  metrics['Android Go TriChrome Install Size'] = go_install_size
+  metrics['Android Go (TriChrome) Install Size'] = go_install_size
 
   system_apks_size = sum(x.GetCompressedSize() for x in trichrome_system_apks)
   stubs_sizes = sum(x.GetApkSize() for x in trichrome_system_stubs)
-  metrics['Trichrome Compressed System Image'] = system_apks_size + stubs_sizes
+  metrics['Android Go (Trichrome) Compressed System Image'] = (
+      system_apks_size + stubs_sizes)
 
-  chrome.AddMethodCount(metrics)
   monochrome.AddMethodCount(metrics)
 
   # Separate where spreadsheet has computed columns for easier copy/paste.
diff --git a/tools/mb/mb.py b/tools/mb/mb.py
index f79ff0b..7c3c758 100755
--- a/tools/mb/mb.py
+++ b/tools/mb/mb.py
@@ -1148,21 +1148,28 @@
     label = labels[0]
 
     build_dir = self.args.path
+
     command, extra_files = self.GetIsolateCommand(target, vals)
 
-    # Any warning for an unused arg will get interleaved into the cmd's stdout.
-    # When that happens, the isolate step below will fail with an obscure error
-    # when it tries processing the lines of the warning. Fail quickly in that
-    # case to avoid confusion.
-    cmd = self.GNCmd('desc', build_dir, label, 'runtime_deps',
-                     '--fail-on-unused-args')
-    ret, out, _ = self.Call(cmd)
-    if ret:
-      if out:
-        self.Print(out)
-      return ret
+    # TODO(crbug.com/816629): Convert everything to wrapped_isolated_scripts
+    # and remove the else-branch of this.
+    if isolate_map[target]['type'] == 'wrapped_console_launcher':
+      runtime_deps = self.ReadFile(
+          self.PathJoin(build_dir, target + '.runtime_deps')).splitlines()
+    else:
+      # Any warning for an unused arg will get interleaved into the cmd's
+      # stdout. When that happens, the isolate step below will fail with an
+      # obscure error when it tries processing the lines of the warning. Fail
+      # quickly in that case to avoid confusion
+      cmd = self.GNCmd('desc', build_dir, label, 'runtime_deps',
+                       '--fail-on-unused-args')
+      ret, out, _ = self.Call(cmd)
+      if ret:
+        if out:
+          self.Print(out)
+        return ret
 
-    runtime_deps = out.splitlines()
+      runtime_deps = out.splitlines()
 
     ret = self.WriteIsolateFiles(build_dir, command, target, runtime_deps, vals,
                                  extra_files)
@@ -1385,13 +1392,32 @@
 
     is_android = 'target_os="android"' in vals['gn_args']
     is_fuchsia = 'target_os="fuchsia"' in vals['gn_args']
-    is_cros = 'target_os="chromeos"' in vals['gn_args']
-    is_ios = 'target_os="ios"' in vals['gn_args']
+    is_cros = ('target_os="chromeos"' in vals['gn_args']
+               or 'is_chromeos_device=true' in vals['gn_args']
+               or vals.get('cros_passthrough', False))
     is_cros_device = ('is_chromeos_device=true' in vals['gn_args']
                       or vals.get('cros_passthrough', False))
-    is_mac = self.platform == 'darwin'
+    is_ios = 'target_os="ios"' in vals['gn_args']
+    is_linux = ('target_os="linux"' in vals['gn_args']
+                or (self.platform in ('linux', 'linux2') and not is_android
+                    and not is_fuchsia and not is_cros))
+    is_mac = self.platform == 'darwin' and not is_ios
     is_win = self.platform == 'win32' or 'target_os="win"' in vals['gn_args']
 
+    test_type = isolate_map[target]['type']
+    if test_type.startswith('wrapped_'):
+      if is_mac or is_linux:
+        cmdline = ['bin/run_{}'.format(target)]
+        return cmdline, []
+      elif is_win:
+        cmdline = ['bin/run_{}.bat'.format(target)]
+        return cmdline, []
+      else:
+        test_type = test_type[len('wrapped_'):]
+
+    # TODO(crbug.com/816629): Convert everything to wrapped_isolated_scripts
+    # and delete the rest of this function.
+
     # This should be true if tests with type='windowed_test_launcher' are
     # expected to run using xvfb. For example, Linux Desktop, X11 CrOS and
     # Ozone CrOS builds on Linux (xvfb is not used on CrOS HW or VMs). Note
@@ -1410,7 +1436,6 @@
     clang_coverage = 'use_clang_coverage=true' in vals['gn_args']
     java_coverage = 'use_jacoco_coverage=true' in vals['gn_args']
 
-    test_type = isolate_map[target]['type']
     use_python3 = isolate_map[target].get('use_python3', False)
 
     executable = isolate_map[target].get('executable', target)
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 30af6d8..297e7b2 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -24,6 +24,7 @@
       # they monitor binary size growth, which may be affected by the tables.
       'linux-chrome': 'official_goma',
       'linux-chromeos-chrome': 'official_goma_chromeos',
+      'linux-lacros': 'lacros_on_linux_release_bot',
       'mac-chrome': 'official_goma',
       'mac-chrome-beta': 'official_goma',
       'mac-chrome-stable': 'official_goma',
@@ -246,6 +247,8 @@
       'Linux remote_run Builder': 'release_bot',
       'Linux remote_run Tester': 'release_bot',
       'Linux Viz': 'release_trybot',
+      'linux-lacros-builder-rel': 'lacros_on_linux_release_bot',
+      'linux-lacros-tester-rel': 'lacros_on_linux_release_bot',
       'Mac Builder Next': 'gpu_tests_release_bot_minimal_symbols_no_nacl',
       'Mac deterministic': 'release_bot_mac_strip_minimal_symbols_deterministic',
       'Mac deterministic (dbg)': 'debug_bot_deterministic',
@@ -1537,6 +1540,10 @@
       'chromeos_kevin', 'include_unwind_tables', 'official',
     ],
 
+    'lacros_on_linux_release_bot': [
+      'lacros_on_linux', 'release_bot',
+    ],
+
     'chromeos_msan_release_bot': [
       'chromeos', 'msan', 'release_bot',
     ],
@@ -2742,6 +2749,10 @@
       'args_file': '//build/args/chromeos/kevin.gni',
     },
 
+    'lacros_on_linux': {
+      'gn_args': 'use_ozone=true ozone_platform_wayland=true ozone_platform="wayland" use_gtk=false chromeos_is_browser_only=true'
+    },
+
     'libfuzzer': { 'gn_args': 'use_libfuzzer=true' },
 
     'link_jobs_32': {
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index ebba3bd..3f3863d 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -28386,6 +28386,8 @@
   <int value="3345" label="RTCConstraintEnableRtpDataChannelsFalse"/>
   <int value="3346" label="NativeFileSystemDragAndDrop"/>
   <int value="3347" label="RTCAdaptivePtime"/>
+  <int value="3348"
+      label="HTMLMetaElementReferrerPolicyMultipleTokensAffectingRequest"/>
 </enum>
 
 <enum name="FeaturePolicyAllowlistType">
@@ -41413,6 +41415,7 @@
       label="OmniboxUIExperimentHideSteadyStateUrlPathQueryAndRef:disabled"/>
   <int value="-127666141" label="TabGroups:disabled"/>
   <int value="-127231994" label="VrBrowsingNativeAndroidUi:disabled"/>
+  <int value="-124604792" label="LanguageSettingsUpdate:enabled"/>
   <int value="-122492389" label="enable-browser-task-scheduler"/>
   <int value="-120521482" label="DirectManipulationStylus:enabled"/>
   <int value="-120091289" label="CrostiniAppSearch:enabled"/>
@@ -41814,6 +41817,7 @@
   <int value="328722396" label="NTPCondensedLayout:disabled"/>
   <int value="330138076" label="enable-clear-browsing-data-counters"/>
   <int value="330439654" label="SyncPseudoUSSExtensions:enabled"/>
+  <int value="330653520" label="ChromeShareHighlightsAndroid:enabled"/>
   <int value="331770879" label="CrostiniAppSearch:disabled"/>
   <int value="332391072" label="cs-contextual-cards-bar-integration"/>
   <int value="334802038" label="OfflinePreviews:disabled"/>
@@ -42799,6 +42803,7 @@
   <int value="1393500952" label="EnableVirtualKeyboardUkm:disabled"/>
   <int value="1393722373" label="SaveEditedPDFForm:disabled"/>
   <int value="1397069250" label="NetworkService:disabled"/>
+  <int value="1398148960" label="LanguageSettingsUpdate:disabled"/>
   <int value="1399950951" label="AutofillTokenPrefixMatching:disabled"/>
   <int value="1403195370" label="ArcCupsApi:enabled"/>
   <int value="1405459667" label="enable-fast-text-autosizing"/>
@@ -43045,6 +43050,7 @@
   <int value="1677258310" label="DragAppsInTabletMode:disabled"/>
   <int value="1679558835" label="ArcAvailableForChildAccount:enabled"/>
   <int value="1680248931" label="use-fake-device-for-media-stream:enabled"/>
+  <int value="1683560662" label="ChromeShareHighlightsAndroid:disabled"/>
   <int value="1684043382" label="AssistantKeyRemapping:enabled"/>
   <int value="1685280468" label="AppServiceShelf:enabled"/>
   <int value="1688075820" label="OmniboxExperimentalKeywordMode:disabled"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index 8680455..9c5c8424 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -56476,7 +56476,7 @@
 </histogram>
 
 <histogram name="Extensions.ExtensionAddDisabledRemotelyReason"
-    enum="ExtensionUpdateCheckDataKey" expires_after="M86">
+    enum="ExtensionUpdateCheckDataKey" expires_after="2021-02-01">
   <owner>bdea@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -56523,7 +56523,7 @@
 </histogram>
 
 <histogram name="Extensions.ExtensionDisabledRemotely"
-    enum="ExtensionUpdateCheckDataKey" expires_after="M86">
+    enum="ExtensionUpdateCheckDataKey" expires_after="2021-02-01">
   <owner>bdea@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -56644,8 +56644,8 @@
   </summary>
 </histogram>
 
-<histogram name="Extensions.ExtensionReenabledRemotely" units="units"
-    expires_after="M86">
+<histogram name="Extensions.ExtensionReenabledRemotely" units="count"
+    expires_after="2021-02-01">
   <owner>bdea@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -69955,6 +69955,24 @@
   </summary>
 </histogram>
 
+<histogram name="InputMethod.VirtualKeyboard.CharactersPerMinute" units="units"
+    expires_after="2021-07-06">
+  <owner>keithlee@google.com</owner>
+  <owner>essential-inputs-team@google.com</owner>
+  <summary>
+    The character per minute ratio recoded during a typing session.
+  </summary>
+</histogram>
+
+<histogram name="InputMethod.VirtualKeyboard.CharactersPerSession"
+    units="units" expires_after="2021-07-06">
+  <owner>keithlee@google.com</owner>
+  <owner>essential-inputs-team@google.com</owner>
+  <summary>
+    The total number of characters committed during a typing session.
+  </summary>
+</histogram>
+
 <histogram name="InputMethod.VirtualKeyboard.ContainerBehavior"
     enum="VirtualKeyboardContainerType" expires_after="M95">
   <owner>essential-inputs-team@google.com</owner>
@@ -70089,6 +70107,13 @@
   </summary>
 </histogram>
 
+<histogram name="InputMethod.VirtualKeyboard.SessionDuration" units="units"
+    expires_after="2021-07-06">
+  <owner>keithlee@google.com</owner>
+  <owner>essential-inputs-team@google.com</owner>
+  <summary>The duration in seconds of a typing session.</summary>
+</histogram>
+
 <histogram name="InputMethod.VirtualKeyboard.SwitchMode" enum="IMEVKMode"
     expires_after="2021-06-30">
   <owner>essential-inputs-team@google.com</owner>
@@ -124283,7 +124308,7 @@
 </histogram>
 
 <histogram name="PasswordManager.ChromeSignInPageHashSaved"
-    enum="ChromeSignInPageHashSaved" expires_after="M86">
+    enum="ChromeSignInPageHashSaved" expires_after="2021-02-01">
   <owner>vakh@chromium.org</owner>
   <owner>vasilii@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
@@ -124894,7 +124919,7 @@
 </histogram>
 
 <histogram name="PasswordManager.IsSyncPasswordHashSaved"
-    enum="IsSyncPasswordHashSaved" expires_after="M86">
+    enum="IsSyncPasswordHashSaved" expires_after="2021-02-01">
   <owner>vakh@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 44b2e51..a47d92c 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -1,12 +1,12 @@
 {
     "trace_processor_shell": {
         "win": {
-            "hash": "407d980fe52940546808b5ab66dfdda8e127e602",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/c73e6969fbeb24194933c0a63cf6df7c5977f9bc/trace_processor_shell.exe"
+            "hash": "940dc509a546e0680eb22717a7a054e0dd880cc9",
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/55ef680dab933301b0a9aec7d3021714dcde26cd/trace_processor_shell.exe"
         },
         "mac": {
-            "hash": "b74caa5ca3d386d41b113730a359de1eaf5ae3cd",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/c73e6969fbeb24194933c0a63cf6df7c5977f9bc/trace_processor_shell"
+            "hash": "a2b0896e1d305a1b1fed14f2e745fe6d0398092d",
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/55ef680dab933301b0a9aec7d3021714dcde26cd/trace_processor_shell"
         },
         "linux": {
             "hash": "4a91142dbaa04283f5443eda976d03572ed5f859",
diff --git a/ui/base/clipboard/clipboard.h b/ui/base/clipboard/clipboard.h
index 6d841015..e3289fe 100644
--- a/ui/base/clipboard/clipboard.h
+++ b/ui/base/clipboard/clipboard.h
@@ -107,9 +107,13 @@
   // whether it has changed.
   virtual uint64_t GetSequenceNumber(ClipboardBuffer buffer) const = 0;
 
-  // Tests whether the clipboard contains a certain format
-  virtual bool IsFormatAvailable(const ClipboardFormatType& format,
-                                 ClipboardBuffer buffer) const = 0;
+  // Tests whether the clipboard contains a certain format.
+  // TODO(crbug.com/1103614): Update |data_dst| in all references to its
+  // appropriate ClipboardDataEndpoint for web-originates uses.
+  virtual bool IsFormatAvailable(
+      const ClipboardFormatType& format,
+      ClipboardBuffer buffer,
+      const ClipboardDataEndpoint* data_dst) const = 0;
 
   // Returns whether the clipboard has data that is marked by its originator as
   // confidential. This is available for opt-in checking by the user of this API
@@ -129,27 +133,42 @@
   // TODO(huangdarwin): Rename to ReadAvailablePortableFormatNames().
   // Includes all sanitized types.
   // Also, includes pickled types by splitting them out of the pickled format.
+  // TODO(crbug.com/1103614): Update |data_dst| in all references to its
+  // appropriate ClipboardDataEndpoint for web-originated uses.
   virtual void ReadAvailableTypes(ClipboardBuffer buffer,
+                                  const ClipboardDataEndpoint* data_dst,
                                   std::vector<base::string16>* types) const = 0;
   // Includes all types, including unsanitized types.
   // Omits formats held within pickles, as they're different from what a native
   // application would see.
+  // TODO(crbug.com/1103614): Update |dst| in all references to its appropriate
+  // ClipboardDataEndpoint for web-originates uses.
   virtual std::vector<base::string16> ReadAvailablePlatformSpecificFormatNames(
-      ClipboardBuffer buffer) const = 0;
+      ClipboardBuffer buffer,
+      const ClipboardDataEndpoint* data_dst) const = 0;
 
   // Reads Unicode text from the clipboard, if available.
+  // TODO(crbug.com/1103614): Update |data_dst| in all references to its
+  // appropriate ClipboardDataEndpoint for web-originates uses.
   virtual void ReadText(ClipboardBuffer buffer,
+                        const ClipboardDataEndpoint* data_dst,
                         base::string16* result) const = 0;
 
   // Reads ASCII text from the clipboard, if available.
+  // TODO(crbug.com/1103614): Update |data_dst| in all references to its
+  // appropriate ClipboardDataEndpoint for web-originates uses.
   virtual void ReadAsciiText(ClipboardBuffer buffer,
+                             const ClipboardDataEndpoint* data_dst,
                              std::string* result) const = 0;
 
   // Reads HTML from the clipboard, if available. If the HTML fragment requires
   // context to parse, |fragment_start| and |fragment_end| are indexes into
   // markup indicating the beginning and end of the actual fragment. Otherwise,
   // they will contain 0 and markup->size().
+  // TODO(crbug.com/1103614): Update |data_dst| in all references to its
+  // appropriate ClipboardDataEndpoint for web-originates uses.
   virtual void ReadHTML(ClipboardBuffer buffer,
+                        const ClipboardDataEndpoint* data_dst,
                         base::string16* markup,
                         std::string* src_url,
                         uint32_t* fragment_start,
@@ -157,25 +176,42 @@
 
   // Reads RTF from the clipboard, if available. Stores the result as a byte
   // vector.
-  virtual void ReadRTF(ClipboardBuffer buffer, std::string* result) const = 0;
+  // TODO(crbug.com/1103614): Update |data_dst| in all references to its
+  // appropriate ClipboardDataEndpoint for web-originates uses.
+  virtual void ReadRTF(ClipboardBuffer buffer,
+                       const ClipboardDataEndpoint* data_dst,
+                       std::string* result) const = 0;
 
   using ReadImageCallback = base::OnceCallback<void(const SkBitmap&)>;
 
   // Reads an image from the clipboard, if available.
+  // TODO(crbug.com/1103614): Update |data_dst| in all references to its
+  // appropriate ClipboardDataEndpoint for web-originates uses.
   virtual void ReadImage(ClipboardBuffer buffer,
+                         const ClipboardDataEndpoint* data_dst,
                          ReadImageCallback callback) const = 0;
 
+  // TODO(crbug.com/1103614): Update |data_dst| in all references to its
+  // appropriate ClipboardDataEndpoint for web-originates uses.
   virtual void ReadCustomData(ClipboardBuffer buffer,
                               const base::string16& type,
+                              const ClipboardDataEndpoint* data_dst,
                               base::string16* result) const = 0;
 
   // Reads a bookmark from the clipboard, if available.
   // |title| or |url| may be null.
-  virtual void ReadBookmark(base::string16* title, std::string* url) const = 0;
+  // TODO(crbug.com/1103614): Update |data_dst| in all references to its
+  // appropriate ClipboardDataEndpoint for web-originates uses.
+  virtual void ReadBookmark(const ClipboardDataEndpoint* data_dst,
+                            base::string16* title,
+                            std::string* url) const = 0;
 
   // Reads raw data from the clipboard with the given format type. Stores result
   // as a byte vector.
+  // TODO(crbug.com/1103614): Update |data_dst| in all references to its
+  // appropriate ClipboardDataEndpoint for web-originates uses.
   virtual void ReadData(const ClipboardFormatType& format,
+                        const ClipboardDataEndpoint* data_dst,
                         std::string* result) const = 0;
 
   // Returns an estimate of the time the clipboard was last updated.  If the
diff --git a/ui/base/clipboard/clipboard_android.cc b/ui/base/clipboard/clipboard_android.cc
index c7b7cad..4a2949b 100644
--- a/ui/base/clipboard/clipboard_android.cc
+++ b/ui/base/clipboard/clipboard_android.cc
@@ -366,8 +366,12 @@
   return g_map.Get().GetSequenceNumber();
 }
 
-bool ClipboardAndroid::IsFormatAvailable(const ClipboardFormatType& format,
-                                         ClipboardBuffer buffer) const {
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
+bool ClipboardAndroid::IsFormatAvailable(
+    const ClipboardFormatType& format,
+    ClipboardBuffer buffer,
+    const ClipboardDataEndpoint* data_dst) const {
   DCHECK(CalledOnValidThread());
   DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
 
@@ -383,8 +387,11 @@
   g_map.Get().Clear();
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardAndroid::ReadAvailableTypes(
     ClipboardBuffer buffer,
+    const ClipboardDataEndpoint* data_dst,
     std::vector<base::string16>* types) const {
   DCHECK(CalledOnValidThread());
   DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
@@ -394,22 +401,26 @@
 
   // would be nice to ask the ClipboardMap to enumerate the types it supports,
   // rather than hardcode the list here.
-  if (IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer))
+  if (IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer,
+                        data_dst))
     types->push_back(base::UTF8ToUTF16(kMimeTypeText));
-  if (IsFormatAvailable(ClipboardFormatType::GetHtmlType(), buffer))
+  if (IsFormatAvailable(ClipboardFormatType::GetHtmlType(), buffer, data_dst))
     types->push_back(base::UTF8ToUTF16(kMimeTypeHTML));
 
   // these formats aren't supported by the ClipboardMap currently, but might
   // be one day?
-  if (IsFormatAvailable(ClipboardFormatType::GetRtfType(), buffer))
+  if (IsFormatAvailable(ClipboardFormatType::GetRtfType(), buffer, data_dst))
     types->push_back(base::UTF8ToUTF16(kMimeTypeRTF));
-  if (IsFormatAvailable(ClipboardFormatType::GetBitmapType(), buffer))
+  if (IsFormatAvailable(ClipboardFormatType::GetBitmapType(), buffer, data_dst))
     types->push_back(base::UTF8ToUTF16(kMimeTypePNG));
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 std::vector<base::string16>
 ClipboardAndroid::ReadAvailablePlatformSpecificFormatNames(
-    ClipboardBuffer buffer) const {
+    ClipboardBuffer buffer,
+    const ClipboardDataEndpoint* data_dst) const {
   DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
   std::vector<std::string> formats = g_map.Get().GetFormats();
 
@@ -421,16 +432,22 @@
   return types;
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardAndroid::ReadText(ClipboardBuffer buffer,
+                                const ClipboardDataEndpoint* data_dst,
                                 base::string16* result) const {
   DCHECK(CalledOnValidThread());
   DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
   std::string utf8;
-  ReadAsciiText(buffer, &utf8);
+  ReadAsciiText(buffer, data_dst, &utf8);
   *result = base::UTF8ToUTF16(utf8);
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardAndroid::ReadAsciiText(ClipboardBuffer buffer,
+                                     const ClipboardDataEndpoint* data_dst,
                                      std::string* result) const {
   DCHECK(CalledOnValidThread());
   DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
@@ -438,8 +455,11 @@
   *result = g_map.Get().Get(ClipboardFormatType::GetPlainTextType().GetName());
 }
 
-// Note: |src_url| isn't really used. It is only implemented in Windows
+// Note: |src_url| isn't really used. It is only implemented in Windows.
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardAndroid::ReadHTML(ClipboardBuffer buffer,
+                                const ClipboardDataEndpoint* data_dst,
                                 base::string16* markup,
                                 std::string* src_url,
                                 uint32_t* fragment_start,
@@ -458,13 +478,19 @@
   *fragment_end = static_cast<uint32_t>(markup->length());
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardAndroid::ReadRTF(ClipboardBuffer buffer,
+                               const ClipboardDataEndpoint* data_dst,
                                std::string* result) const {
   DCHECK(CalledOnValidThread());
   NOTIMPLEMENTED();
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardAndroid::ReadImage(ClipboardBuffer buffer,
+                                 const ClipboardDataEndpoint* data_dst,
                                  ReadImageCallback callback) const {
   DCHECK(CalledOnValidThread());
   DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
@@ -472,20 +498,29 @@
   g_map.Get().GetImage(std::move(callback));
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardAndroid::ReadCustomData(ClipboardBuffer buffer,
                                       const base::string16& type,
+                                      const ClipboardDataEndpoint* data_dst,
                                       base::string16* result) const {
   DCHECK(CalledOnValidThread());
   NOTIMPLEMENTED();
 }
 
-void ClipboardAndroid::ReadBookmark(base::string16* title,
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
+void ClipboardAndroid::ReadBookmark(const ClipboardDataEndpoint* data_dst,
+                                    base::string16* title,
                                     std::string* url) const {
   DCHECK(CalledOnValidThread());
   NOTIMPLEMENTED();
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardAndroid::ReadData(const ClipboardFormatType& format,
+                                const ClipboardDataEndpoint* data_dst,
                                 std::string* result) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kData);
diff --git a/ui/base/clipboard/clipboard_android.h b/ui/base/clipboard/clipboard_android.h
index ed45919..2d5c127 100644
--- a/ui/base/clipboard/clipboard_android.h
+++ b/ui/base/clipboard/clipboard_android.h
@@ -60,28 +60,43 @@
   void OnPreShutdown() override;
   uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
   bool IsFormatAvailable(const ClipboardFormatType& format,
-                         ClipboardBuffer buffer) const override;
+                         ClipboardBuffer buffer,
+                         const ClipboardDataEndpoint* data_dst) const override;
   void Clear(ClipboardBuffer buffer) override;
   void ReadAvailableTypes(ClipboardBuffer buffer,
+                          const ClipboardDataEndpoint* data_dst,
                           std::vector<base::string16>* types) const override;
   std::vector<base::string16> ReadAvailablePlatformSpecificFormatNames(
-      ClipboardBuffer buffer) const override;
-  void ReadText(ClipboardBuffer buffer, base::string16* result) const override;
+      ClipboardBuffer buffer,
+      const ClipboardDataEndpoint* data_dst) const override;
+  void ReadText(ClipboardBuffer buffer,
+                const ClipboardDataEndpoint* data_dst,
+                base::string16* result) const override;
   void ReadAsciiText(ClipboardBuffer buffer,
+                     const ClipboardDataEndpoint* data_dst,
                      std::string* result) const override;
   void ReadHTML(ClipboardBuffer buffer,
+                const ClipboardDataEndpoint* data_dst,
                 base::string16* markup,
                 std::string* src_url,
                 uint32_t* fragment_start,
                 uint32_t* fragment_end) const override;
-  void ReadRTF(ClipboardBuffer buffer, std::string* result) const override;
+  void ReadRTF(ClipboardBuffer buffer,
+               const ClipboardDataEndpoint* data_dst,
+               std::string* result) const override;
   void ReadImage(ClipboardBuffer buffer,
+                 const ClipboardDataEndpoint* data_dst,
                  ReadImageCallback callback) const override;
   void ReadCustomData(ClipboardBuffer buffer,
                       const base::string16& type,
+                      const ClipboardDataEndpoint* data_dst,
                       base::string16* result) const override;
-  void ReadBookmark(base::string16* title, std::string* url) const override;
+  void ReadBookmark(const ClipboardDataEndpoint* data_dst,
+                    base::string16* title,
+
+                    std::string* url) const override;
   void ReadData(const ClipboardFormatType& format,
+                const ClipboardDataEndpoint* data_dst,
                 std::string* result) const override;
   base::Time GetLastModifiedTime() const override;
   void ClearLastModifiedTime() override;
diff --git a/ui/base/clipboard/clipboard_android_test_support.cc b/ui/base/clipboard/clipboard_android_test_support.cc
index c14b76b..fa69f2ba 100644
--- a/ui/base/clipboard/clipboard_android_test_support.cc
+++ b/ui/base/clipboard/clipboard_android_test_support.cc
@@ -34,9 +34,11 @@
   }
   auto* clipboard = Clipboard::GetForCurrentThread();
   return clipboard->IsFormatAvailable(ClipboardFormatType::GetHtmlType(),
-                                      ClipboardBuffer::kCopyPaste) &&
+                                      ClipboardBuffer::kCopyPaste,
+                                      /* data_dst = */ nullptr) &&
          clipboard->IsFormatAvailable(ClipboardFormatType::GetPlainTextType(),
-                                      ClipboardBuffer::kCopyPaste);
+                                      ClipboardBuffer::kCopyPaste,
+                                      /* data_dst = */ nullptr);
 }
 
 jboolean JNI_ClipboardAndroidTestSupport_NativeClipboardContains(
@@ -47,13 +49,15 @@
   // well as the Android side.
   auto* clipboard = Clipboard::GetForCurrentThread();
   if (clipboard->IsFormatAvailable(ClipboardFormatType::GetHtmlType(),
-                                   ClipboardBuffer::kCopyPaste)) {
+                                   ClipboardBuffer::kCopyPaste,
+                                   /* data_dst = */ nullptr)) {
     LOG(ERROR) << "HTML still in clipboard.";
     return false;
   }
 
   if (!clipboard->IsFormatAvailable(ClipboardFormatType::GetPlainTextType(),
-                                    ClipboardBuffer::kCopyPaste)) {
+                                    ClipboardBuffer::kCopyPaste,
+                                    /* data_dst = */ nullptr)) {
     LOG(ERROR) << "Plain text not in clipboard.";
     return false;
   }
@@ -62,7 +66,8 @@
   base::android::ConvertJavaStringToUTF8(env, j_text, &expected_text);
 
   std::string contents;
-  clipboard->ReadAsciiText(ClipboardBuffer::kCopyPaste, &contents);
+  clipboard->ReadAsciiText(ClipboardBuffer::kCopyPaste,
+                           /* data_dst = */ nullptr, &contents);
   if (expected_text != contents) {
     LOG(ERROR) << "Clipboard contents do not match. Expected: " << expected_text
                << " Actual: " << contents;
diff --git a/ui/base/clipboard/clipboard_mac.h b/ui/base/clipboard/clipboard_mac.h
index d0f854bf..849c3b8 100644
--- a/ui/base/clipboard/clipboard_mac.h
+++ b/ui/base/clipboard/clipboard_mac.h
@@ -32,30 +32,44 @@
   void OnPreShutdown() override;
   uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
   bool IsFormatAvailable(const ClipboardFormatType& format,
-                         ClipboardBuffer buffer) const override;
+                         ClipboardBuffer buffer,
+                         const ClipboardDataEndpoint* data_dst) const override;
   bool IsMarkedByOriginatorAsConfidential() const override;
   void MarkAsConfidential() override;
   void Clear(ClipboardBuffer buffer) override;
   void ReadAvailableTypes(ClipboardBuffer buffer,
+                          const ClipboardDataEndpoint* data_dst,
                           std::vector<base::string16>* types) const override;
   std::vector<base::string16> ReadAvailablePlatformSpecificFormatNames(
-      ClipboardBuffer buffer) const override;
-  void ReadText(ClipboardBuffer buffer, base::string16* result) const override;
+      ClipboardBuffer buffer,
+      const ClipboardDataEndpoint* data_dst) const override;
+  void ReadText(ClipboardBuffer buffer,
+                const ClipboardDataEndpoint* data_dst,
+                base::string16* result) const override;
   void ReadAsciiText(ClipboardBuffer buffer,
+                     const ClipboardDataEndpoint* data_dst,
                      std::string* result) const override;
   void ReadHTML(ClipboardBuffer buffer,
+                const ClipboardDataEndpoint* data_dst,
                 base::string16* markup,
                 std::string* src_url,
                 uint32_t* fragment_start,
                 uint32_t* fragment_end) const override;
-  void ReadRTF(ClipboardBuffer buffer, std::string* result) const override;
+  void ReadRTF(ClipboardBuffer buffer,
+               const ClipboardDataEndpoint* data_dst,
+               std::string* result) const override;
   void ReadImage(ClipboardBuffer buffer,
+                 const ClipboardDataEndpoint* data_dst,
                  ReadImageCallback callback) const override;
   void ReadCustomData(ClipboardBuffer buffer,
                       const base::string16& type,
+                      const ClipboardDataEndpoint* data_dst,
                       base::string16* result) const override;
-  void ReadBookmark(base::string16* title, std::string* url) const override;
+  void ReadBookmark(const ClipboardDataEndpoint* data_dst,
+                    base::string16* title,
+                    std::string* url) const override;
   void ReadData(const ClipboardFormatType& format,
+                const ClipboardDataEndpoint* data_dst,
                 std::string* result) const override;
   void WritePortableRepresentations(
       ClipboardBuffer buffer,
diff --git a/ui/base/clipboard/clipboard_mac.mm b/ui/base/clipboard/clipboard_mac.mm
index 4a0dab3..8e71324 100644
--- a/ui/base/clipboard/clipboard_mac.mm
+++ b/ui/base/clipboard/clipboard_mac.mm
@@ -70,8 +70,12 @@
   return [pb changeCount];
 }
 
-bool ClipboardMac::IsFormatAvailable(const ClipboardFormatType& format,
-                                     ClipboardBuffer buffer) const {
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
+bool ClipboardMac::IsFormatAvailable(
+    const ClipboardFormatType& format,
+    ClipboardBuffer buffer,
+    const ClipboardDataEndpoint* data_dst) const {
   DCHECK(CalledOnValidThread());
   DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
 
@@ -116,18 +120,22 @@
   [pb declareTypes:@[] owner:nil];
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardMac::ReadAvailableTypes(
     ClipboardBuffer buffer,
+    const ClipboardDataEndpoint* data_dst,
     std::vector<base::string16>* types) const {
   DCHECK(CalledOnValidThread());
   DCHECK(types);
 
   types->clear();
-  if (IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer))
+  if (IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer,
+                        data_dst))
     types->push_back(base::UTF8ToUTF16(kMimeTypeText));
-  if (IsFormatAvailable(ClipboardFormatType::GetHtmlType(), buffer))
+  if (IsFormatAvailable(ClipboardFormatType::GetHtmlType(), buffer, data_dst))
     types->push_back(base::UTF8ToUTF16(kMimeTypeHTML));
-  if (IsFormatAvailable(ClipboardFormatType::GetRtfType(), buffer))
+  if (IsFormatAvailable(ClipboardFormatType::GetRtfType(), buffer, data_dst))
     types->push_back(base::UTF8ToUTF16(kMimeTypeRTF));
 
   NSPasteboard* pb = GetPasteboard();
@@ -141,9 +149,12 @@
   }
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 std::vector<base::string16>
 ClipboardMac::ReadAvailablePlatformSpecificFormatNames(
-    ClipboardBuffer buffer) const {
+    ClipboardBuffer buffer,
+    const ClipboardDataEndpoint* data_dst) const {
   DCHECK(CalledOnValidThread());
   DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
 
@@ -157,7 +168,10 @@
   return type_names;
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardMac::ReadText(ClipboardBuffer buffer,
+                            const ClipboardDataEndpoint* data_dst,
                             base::string16* result) const {
   DCHECK(CalledOnValidThread());
   DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
@@ -168,7 +182,10 @@
   *result = base::SysNSStringToUTF16(contents);
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardMac::ReadAsciiText(ClipboardBuffer buffer,
+                                 const ClipboardDataEndpoint* data_dst,
                                  std::string* result) const {
   DCHECK(CalledOnValidThread());
   DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
@@ -182,7 +199,10 @@
     result->assign([contents UTF8String]);
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardMac::ReadHTML(ClipboardBuffer buffer,
+                            const ClipboardDataEndpoint* data_dst,
                             base::string16* markup,
                             std::string* src_url,
                             uint32_t* fragment_start,
@@ -214,22 +234,32 @@
   *fragment_end = static_cast<uint32_t>(markup->length());
 }
 
-void ClipboardMac::ReadRTF(ClipboardBuffer buffer, std::string* result) const {
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
+void ClipboardMac::ReadRTF(ClipboardBuffer buffer,
+                           const ClipboardDataEndpoint* data_dst,
+                           std::string* result) const {
   DCHECK(CalledOnValidThread());
   DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
   RecordRead(ClipboardFormatMetric::kRtf);
 
-  return ReadData(ClipboardFormatType::GetRtfType(), result);
+  return ReadData(ClipboardFormatType::GetRtfType(), data_dst, result);
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardMac::ReadImage(ClipboardBuffer buffer,
+                             const ClipboardDataEndpoint* data_dst,
                              ReadImageCallback callback) const {
   RecordRead(ClipboardFormatMetric::kImage);
   std::move(callback).Run(ReadImageInternal(buffer, GetPasteboard()));
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardMac::ReadCustomData(ClipboardBuffer buffer,
                                   const base::string16& type,
+                                  const ClipboardDataEndpoint* data_dst,
                                   base::string16* result) const {
   DCHECK(CalledOnValidThread());
   DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
@@ -243,7 +273,11 @@
   }
 }
 
-void ClipboardMac::ReadBookmark(base::string16* title, std::string* url) const {
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
+void ClipboardMac::ReadBookmark(const ClipboardDataEndpoint* data_dst,
+                                base::string16* title,
+                                std::string* url) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kBookmark);
   NSPasteboard* pb = GetPasteboard();
@@ -262,7 +296,10 @@
   }
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardMac::ReadData(const ClipboardFormatType& format,
+                            const ClipboardDataEndpoint* data_dst,
                             std::string* result) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kData);
diff --git a/ui/base/clipboard/clipboard_non_backed.cc b/ui/base/clipboard/clipboard_non_backed.cc
index e08aeff..2eddf5f 100644
--- a/ui/base/clipboard/clipboard_non_backed.cc
+++ b/ui/base/clipboard/clipboard_non_backed.cc
@@ -319,8 +319,10 @@
   return clipboard_internal_->sequence_number();
 }
 
-bool ClipboardNonBacked::IsFormatAvailable(const ClipboardFormatType& format,
-                                           ClipboardBuffer buffer) const {
+bool ClipboardNonBacked::IsFormatAvailable(
+    const ClipboardFormatType& format,
+    ClipboardBuffer buffer,
+    const ClipboardDataEndpoint* data_dst) const {
   DCHECK(CalledOnValidThread());
   DCHECK(IsSupportedClipboardBuffer(buffer));
   if (ClipboardFormatType::GetPlainTextType().Equals(format) ||
@@ -351,21 +353,23 @@
 
 void ClipboardNonBacked::ReadAvailableTypes(
     ClipboardBuffer buffer,
+    const ClipboardDataEndpoint* data_dst,
     std::vector<base::string16>* types) const {
   DCHECK(CalledOnValidThread());
   DCHECK(types);
 
   types->clear();
-  if (IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer))
+  if (IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer,
+                        data_dst))
     types->push_back(
         base::UTF8ToUTF16(ClipboardFormatType::GetPlainTextType().GetName()));
-  if (IsFormatAvailable(ClipboardFormatType::GetHtmlType(), buffer))
+  if (IsFormatAvailable(ClipboardFormatType::GetHtmlType(), buffer, data_dst))
     types->push_back(
         base::UTF8ToUTF16(ClipboardFormatType::GetHtmlType().GetName()));
-  if (IsFormatAvailable(ClipboardFormatType::GetRtfType(), buffer))
+  if (IsFormatAvailable(ClipboardFormatType::GetRtfType(), buffer, data_dst))
     types->push_back(
         base::UTF8ToUTF16(ClipboardFormatType::GetRtfType().GetName()));
-  if (IsFormatAvailable(ClipboardFormatType::GetBitmapType(), buffer))
+  if (IsFormatAvailable(ClipboardFormatType::GetBitmapType(), buffer, data_dst))
     types->push_back(base::UTF8ToUTF16(kMimeTypePNG));
 
   if (clipboard_internal_->IsFormatAvailable(
@@ -379,25 +383,28 @@
 
 std::vector<base::string16>
 ClipboardNonBacked::ReadAvailablePlatformSpecificFormatNames(
-    ClipboardBuffer buffer) const {
+    ClipboardBuffer buffer,
+    const ClipboardDataEndpoint* data_dst) const {
   DCHECK(CalledOnValidThread());
 
   std::vector<base::string16> types;
 
   // Includes all non-pickled AvailableTypes.
-  if (IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer)) {
+  if (IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer,
+                        data_dst)) {
     types.push_back(
         base::UTF8ToUTF16(ClipboardFormatType::GetPlainTextType().GetName()));
   }
-  if (IsFormatAvailable(ClipboardFormatType::GetHtmlType(), buffer)) {
+  if (IsFormatAvailable(ClipboardFormatType::GetHtmlType(), buffer, data_dst)) {
     types.push_back(
         base::UTF8ToUTF16(ClipboardFormatType::GetHtmlType().GetName()));
   }
-  if (IsFormatAvailable(ClipboardFormatType::GetRtfType(), buffer)) {
+  if (IsFormatAvailable(ClipboardFormatType::GetRtfType(), buffer, data_dst)) {
     types.push_back(
         base::UTF8ToUTF16(ClipboardFormatType::GetRtfType().GetName()));
   }
-  if (IsFormatAvailable(ClipboardFormatType::GetBitmapType(), buffer)) {
+  if (IsFormatAvailable(ClipboardFormatType::GetBitmapType(), buffer,
+                        data_dst)) {
     types.push_back(base::UTF8ToUTF16(kMimeTypePNG));
   }
 
@@ -405,6 +412,7 @@
 }
 
 void ClipboardNonBacked::ReadText(ClipboardBuffer buffer,
+                                  const ClipboardDataEndpoint* data_dst,
                                   base::string16* result) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kText);
@@ -412,6 +420,7 @@
 }
 
 void ClipboardNonBacked::ReadAsciiText(ClipboardBuffer buffer,
+                                       const ClipboardDataEndpoint* data_dst,
                                        std::string* result) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kText);
@@ -419,6 +428,7 @@
 }
 
 void ClipboardNonBacked::ReadHTML(ClipboardBuffer buffer,
+                                  const ClipboardDataEndpoint* data_dst,
                                   base::string16* markup,
                                   std::string* src_url,
                                   uint32_t* fragment_start,
@@ -429,6 +439,7 @@
 }
 
 void ClipboardNonBacked::ReadRTF(ClipboardBuffer buffer,
+                                 const ClipboardDataEndpoint* data_dst,
                                  std::string* result) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kRtf);
@@ -436,6 +447,7 @@
 }
 
 void ClipboardNonBacked::ReadImage(ClipboardBuffer buffer,
+                                   const ClipboardDataEndpoint* data_dst,
                                    ReadImageCallback callback) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kImage);
@@ -444,13 +456,15 @@
 
 void ClipboardNonBacked::ReadCustomData(ClipboardBuffer buffer,
                                         const base::string16& type,
+                                        const ClipboardDataEndpoint* data_dst,
                                         base::string16* result) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kCustomData);
   clipboard_internal_->ReadCustomData(type, result);
 }
 
-void ClipboardNonBacked::ReadBookmark(base::string16* title,
+void ClipboardNonBacked::ReadBookmark(const ClipboardDataEndpoint* data_dst,
+                                      base::string16* title,
                                       std::string* url) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kBookmark);
@@ -458,6 +472,7 @@
 }
 
 void ClipboardNonBacked::ReadData(const ClipboardFormatType& format,
+                                  const ClipboardDataEndpoint* data_dst,
                                   std::string* result) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kData);
diff --git a/ui/base/clipboard/clipboard_non_backed.h b/ui/base/clipboard/clipboard_non_backed.h
index d3274e9..5b35665 100644
--- a/ui/base/clipboard/clipboard_non_backed.h
+++ b/ui/base/clipboard/clipboard_non_backed.h
@@ -31,28 +31,42 @@
   void OnPreShutdown() override;
   uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
   bool IsFormatAvailable(const ClipboardFormatType& format,
-                         ClipboardBuffer buffer) const override;
+                         ClipboardBuffer buffer,
+                         const ClipboardDataEndpoint* data_dst) const override;
   void Clear(ClipboardBuffer buffer) override;
   void ReadAvailableTypes(ClipboardBuffer buffer,
+                          const ClipboardDataEndpoint* data_dst,
                           std::vector<base::string16>* types) const override;
   std::vector<base::string16> ReadAvailablePlatformSpecificFormatNames(
-      ClipboardBuffer buffer) const override;
-  void ReadText(ClipboardBuffer buffer, base::string16* result) const override;
+      ClipboardBuffer buffer,
+      const ClipboardDataEndpoint* data_dst) const override;
+  void ReadText(ClipboardBuffer buffer,
+                const ClipboardDataEndpoint* data_dst,
+                base::string16* result) const override;
   void ReadAsciiText(ClipboardBuffer buffer,
+                     const ClipboardDataEndpoint* data_dst,
                      std::string* result) const override;
   void ReadHTML(ClipboardBuffer buffer,
+                const ClipboardDataEndpoint* data_dst,
                 base::string16* markup,
                 std::string* src_url,
                 uint32_t* fragment_start,
                 uint32_t* fragment_end) const override;
-  void ReadRTF(ClipboardBuffer buffer, std::string* result) const override;
+  void ReadRTF(ClipboardBuffer buffer,
+               const ClipboardDataEndpoint* data_dst,
+               std::string* result) const override;
   void ReadImage(ClipboardBuffer buffer,
+                 const ClipboardDataEndpoint* data_dst,
                  ReadImageCallback callback) const override;
   void ReadCustomData(ClipboardBuffer buffer,
                       const base::string16& type,
+                      const ClipboardDataEndpoint* data_dst,
                       base::string16* result) const override;
-  void ReadBookmark(base::string16* title, std::string* url) const override;
+  void ReadBookmark(const ClipboardDataEndpoint* data_dst,
+                    base::string16* title,
+                    std::string* url) const override;
   void ReadData(const ClipboardFormatType& format,
+                const ClipboardDataEndpoint* data_dst,
                 std::string* result) const override;
   void WritePortableRepresentations(
       ClipboardBuffer buffer,
diff --git a/ui/base/clipboard/clipboard_ozone.cc b/ui/base/clipboard/clipboard_ozone.cc
index 60cfcb5..2d79025 100644
--- a/ui/base/clipboard/clipboard_ozone.cc
+++ b/ui/base/clipboard/clipboard_ozone.cc
@@ -337,8 +337,11 @@
   return async_clipboard_ozone_->GetSequenceNumber(buffer);
 }
 
-bool ClipboardOzone::IsFormatAvailable(const ClipboardFormatType& format,
-                                       ClipboardBuffer buffer) const {
+// TODO(crbug.com/1103194): |data_dst| should be supported.
+bool ClipboardOzone::IsFormatAvailable(
+    const ClipboardFormatType& format,
+    ClipboardBuffer buffer,
+    const ClipboardDataEndpoint* data_dst) const {
   DCHECK(CalledOnValidThread());
 
   auto available_types = async_clipboard_ozone_->RequestMimeTypes(buffer);
@@ -349,8 +352,10 @@
   async_clipboard_ozone_->Clear(buffer);
 }
 
+// TODO(crbug.com/1103194): |data_dst| should be supported.
 void ClipboardOzone::ReadAvailableTypes(
     ClipboardBuffer buffer,
+    const ClipboardDataEndpoint* data_dst,
     std::vector<base::string16>* types) const {
   DCHECK(CalledOnValidThread());
   DCHECK(types);
@@ -372,9 +377,11 @@
   }
 }
 
+// TODO(crbug.com/1103194): |data_dst| should be supported.
 std::vector<base::string16>
 ClipboardOzone::ReadAvailablePlatformSpecificFormatNames(
-    ClipboardBuffer buffer) const {
+    ClipboardBuffer buffer,
+    const ClipboardDataEndpoint* data_dst) const {
   DCHECK(CalledOnValidThread());
 
   std::vector<std::string> mime_types =
@@ -386,7 +393,9 @@
   return types;
 }
 
+// TODO(crbug.com/1103194): |data_dst| should be supported.
 void ClipboardOzone::ReadText(ClipboardBuffer buffer,
+                              const ClipboardDataEndpoint* data_dst,
                               base::string16* result) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kText);
@@ -397,7 +406,9 @@
       reinterpret_cast<char*>(clipboard_data.data()), clipboard_data.size()));
 }
 
+// TODO(crbug.com/1103194): |data_dst| should be supported.
 void ClipboardOzone::ReadAsciiText(ClipboardBuffer buffer,
+                                   const ClipboardDataEndpoint* data_dst,
                                    std::string* result) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kText);
@@ -407,7 +418,9 @@
   result->assign(clipboard_data.begin(), clipboard_data.end());
 }
 
+// TODO(crbug.com/1103194): |data_dst| should be supported.
 void ClipboardOzone::ReadHTML(ClipboardBuffer buffer,
+                              const ClipboardDataEndpoint* data_dst,
                               base::string16* markup,
                               std::string* src_url,
                               uint32_t* fragment_start,
@@ -429,7 +442,9 @@
   *fragment_end = static_cast<uint32_t>(markup->length());
 }
 
+// TODO(crbug.com/1103194): |data_dst| should be supported.
 void ClipboardOzone::ReadRTF(ClipboardBuffer buffer,
+                             const ClipboardDataEndpoint* data_dst,
                              std::string* result) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kRtf);
@@ -439,14 +454,18 @@
   result->assign(clipboard_data.begin(), clipboard_data.end());
 }
 
+// TODO(crbug.com/1103194): |data_dst| should be supported.
 void ClipboardOzone::ReadImage(ClipboardBuffer buffer,
+                               const ClipboardDataEndpoint* data_dst,
                                ReadImageCallback callback) const {
   RecordRead(ClipboardFormatMetric::kImage);
   std::move(callback).Run(ReadImageInternal(buffer));
 }
 
+// TODO(crbug.com/1103194): |data_dst| should be supported.
 void ClipboardOzone::ReadCustomData(ClipboardBuffer buffer,
                                     const base::string16& type,
+                                    const ClipboardDataEndpoint* data_dst,
                                     base::string16* result) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kCustomData);
@@ -456,14 +475,18 @@
   ReadCustomDataForType(custom_data.data(), custom_data.size(), type, result);
 }
 
-void ClipboardOzone::ReadBookmark(base::string16* title,
+// TODO(crbug.com/1103194): |data_dst| should be supported.
+void ClipboardOzone::ReadBookmark(const ClipboardDataEndpoint* data_dst,
+                                  base::string16* title,
                                   std::string* url) const {
   DCHECK(CalledOnValidThread());
   // TODO(msisov): This was left NOTIMPLEMENTED() in all the Linux platforms.
   NOTIMPLEMENTED();
 }
 
+// TODO(crbug.com/1103194): |data_dst| should be supported.
 void ClipboardOzone::ReadData(const ClipboardFormatType& format,
+                              const ClipboardDataEndpoint* data_dst,
                               std::string* result) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kData);
diff --git a/ui/base/clipboard/clipboard_ozone.h b/ui/base/clipboard/clipboard_ozone.h
index fc8a416f..ca77c5f 100644
--- a/ui/base/clipboard/clipboard_ozone.h
+++ b/ui/base/clipboard/clipboard_ozone.h
@@ -27,28 +27,42 @@
   void OnPreShutdown() override;
   uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
   bool IsFormatAvailable(const ClipboardFormatType& format,
-                         ClipboardBuffer buffer) const override;
+                         ClipboardBuffer buffer,
+                         const ClipboardDataEndpoint* data_dst) const override;
   void Clear(ClipboardBuffer buffer) override;
   void ReadAvailableTypes(ClipboardBuffer buffer,
+                          const ClipboardDataEndpoint* data_dst,
                           std::vector<base::string16>* types) const override;
   std::vector<base::string16> ReadAvailablePlatformSpecificFormatNames(
-      ClipboardBuffer buffer) const override;
-  void ReadText(ClipboardBuffer buffer, base::string16* result) const override;
+      ClipboardBuffer buffer,
+      const ClipboardDataEndpoint* data_dst) const override;
+  void ReadText(ClipboardBuffer buffer,
+                const ClipboardDataEndpoint* data_dst,
+                base::string16* result) const override;
   void ReadAsciiText(ClipboardBuffer buffer,
+                     const ClipboardDataEndpoint* data_dst,
                      std::string* result) const override;
   void ReadHTML(ClipboardBuffer buffer,
+                const ClipboardDataEndpoint* data_dst,
                 base::string16* markup,
                 std::string* src_url,
                 uint32_t* fragment_start,
                 uint32_t* fragment_end) const override;
-  void ReadRTF(ClipboardBuffer buffer, std::string* result) const override;
+  void ReadRTF(ClipboardBuffer buffer,
+               const ClipboardDataEndpoint* data_dst,
+               std::string* result) const override;
   void ReadImage(ClipboardBuffer buffer,
+                 const ClipboardDataEndpoint* data_dst,
                  ReadImageCallback callback) const override;
   void ReadCustomData(ClipboardBuffer buffer,
                       const base::string16& type,
+                      const ClipboardDataEndpoint* data_dst,
                       base::string16* result) const override;
-  void ReadBookmark(base::string16* title, std::string* url) const override;
+  void ReadBookmark(const ClipboardDataEndpoint* data_dst,
+                    base::string16* title,
+                    std::string* url) const override;
   void ReadData(const ClipboardFormatType& format,
+                const ClipboardDataEndpoint* data_dst,
                 std::string* result) const override;
   void WritePortableRepresentations(
       ClipboardBuffer buffer,
diff --git a/ui/base/clipboard/clipboard_test_template.h b/ui/base/clipboard/clipboard_test_template.h
index 279252c..1d7eaf5 100644
--- a/ui/base/clipboard/clipboard_test_template.h
+++ b/ui/base/clipboard/clipboard_test_template.h
@@ -84,7 +84,7 @@
 
   std::vector<base::string16> GetAvailableTypes(ClipboardBuffer buffer) {
     std::vector<base::string16> types;
-    clipboard().ReadAvailableTypes(buffer, &types);
+    clipboard().ReadAvailableTypes(buffer, /* data_dst = */ nullptr, &types);
     return types;
   }
 
@@ -115,10 +115,12 @@
 
   EXPECT_TRUE(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste).empty());
   EXPECT_FALSE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste));
+      ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
 #if defined(OS_WIN)
   EXPECT_FALSE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetPlainTextAType(), ClipboardBuffer::kCopyPaste));
+      ClipboardFormatType::GetPlainTextAType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
 #endif
 }
 
@@ -134,16 +136,20 @@
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
               Contains(ASCIIToUTF16(kMimeTypeText)));
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste));
+      ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
 #if defined(OS_WIN)
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetPlainTextAType(), ClipboardBuffer::kCopyPaste));
+      ClipboardFormatType::GetPlainTextAType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
 #endif
 
-  this->clipboard().ReadText(ClipboardBuffer::kCopyPaste, &text_result);
+  this->clipboard().ReadText(ClipboardBuffer::kCopyPaste,
+                             /* data_dst = */ nullptr, &text_result);
 
   EXPECT_EQ(text, text_result);
-  this->clipboard().ReadAsciiText(ClipboardBuffer::kCopyPaste, &ascii_text);
+  this->clipboard().ReadAsciiText(ClipboardBuffer::kCopyPaste,
+                                  /* data_dst = */ nullptr, &ascii_text);
   EXPECT_EQ(UTF16ToUTF8(text), ascii_text);
 }
 
@@ -161,10 +167,12 @@
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
               Contains(ASCIIToUTF16(kMimeTypeHTML)));
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kCopyPaste));
+      ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
   uint32_t fragment_start;
   uint32_t fragment_end;
-  this->clipboard().ReadHTML(ClipboardBuffer::kCopyPaste, &markup_result,
+  this->clipboard().ReadHTML(ClipboardBuffer::kCopyPaste,
+                             /* data_dst = */ nullptr, &markup_result,
                              &url_result, &fragment_start, &fragment_end);
   EXPECT_LE(markup.size(), fragment_end - fragment_start);
   EXPECT_EQ(markup,
@@ -193,9 +201,11 @@
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
               Contains(ASCIIToUTF16(kMimeTypeRTF)));
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetRtfType(), ClipboardBuffer::kCopyPaste));
+      ClipboardFormatType::GetRtfType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
   std::string result;
-  this->clipboard().ReadRTF(ClipboardBuffer::kCopyPaste, &result);
+  this->clipboard().ReadRTF(ClipboardBuffer::kCopyPaste,
+                            /* data_dst = */ nullptr, &result);
   EXPECT_EQ(rtf, result);
 }
 #endif  // !defined(OS_ANDROID)
@@ -224,22 +234,28 @@
               Contains(ASCIIToUTF16(kMimeTypeHTML)));
 
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste));
+      ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
   EXPECT_FALSE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kSelection));
+      ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kSelection,
+      /* data_dst = */ nullptr));
 
   EXPECT_FALSE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kCopyPaste));
+      ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kSelection));
+      ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kSelection,
+      /* data_dst = */ nullptr));
 
-  this->clipboard().ReadText(ClipboardBuffer::kCopyPaste, &text_result);
+  this->clipboard().ReadText(ClipboardBuffer::kCopyPaste,
+                             /* data_dst = */ nullptr, &text_result);
   EXPECT_EQ(text, text_result);
 
   base::string16 markup_result;
   uint32_t fragment_start;
   uint32_t fragment_end;
-  this->clipboard().ReadHTML(ClipboardBuffer::kSelection, &markup_result,
+  this->clipboard().ReadHTML(ClipboardBuffer::kSelection,
+                             /* data_dst = */ nullptr, &markup_result,
                              &url_result, &fragment_start, &fragment_end);
   EXPECT_LE(markup.size(), fragment_end - fragment_start);
   EXPECT_EQ(markup,
@@ -262,10 +278,12 @@
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
               Contains(ASCIIToUTF16(kMimeTypeHTML)));
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kCopyPaste));
+      ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
   uint32_t fragment_start;
   uint32_t fragment_end;
-  this->clipboard().ReadHTML(ClipboardBuffer::kCopyPaste, &markup_result,
+  this->clipboard().ReadHTML(ClipboardBuffer::kCopyPaste,
+                             /* data_dst = */ nullptr, &markup_result,
                              &url_result, &fragment_start, &fragment_end);
   EXPECT_LE(markup.size(), fragment_end - fragment_start);
   EXPECT_EQ(markup,
@@ -296,10 +314,12 @@
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
               Contains(ASCIIToUTF16(kMimeTypeHTML)));
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kCopyPaste));
+      ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
   uint32_t fragment_start;
   uint32_t fragment_end;
-  this->clipboard().ReadHTML(ClipboardBuffer::kCopyPaste, &markup_result,
+  this->clipboard().ReadHTML(ClipboardBuffer::kCopyPaste,
+                             /* data_dst = */ nullptr, &markup_result,
                              &url_result, &fragment_start, &fragment_end);
   EXPECT_LE(markup.size(), fragment_end - fragment_start);
   EXPECT_EQ(markup,
@@ -321,8 +341,10 @@
   }
 
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetUrlType(), ClipboardBuffer::kCopyPaste));
-  this->clipboard().ReadBookmark(&title_result, &url_result);
+      ClipboardFormatType::GetUrlType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
+  this->clipboard().ReadBookmark(/* data_dst = */ nullptr, &title_result,
+                                 &url_result);
   EXPECT_EQ(title, title_result);
   EXPECT_EQ(url, url_result);
 }
@@ -345,16 +367,20 @@
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
               Contains(ASCIIToUTF16(kMimeTypeText)));
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kCopyPaste));
+      ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste));
+      ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
 #if defined(OS_WIN)
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetPlainTextAType(), ClipboardBuffer::kCopyPaste));
+      ClipboardFormatType::GetPlainTextAType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
 #endif
   uint32_t fragment_start;
   uint32_t fragment_end;
-  this->clipboard().ReadHTML(ClipboardBuffer::kCopyPaste, &markup_result,
+  this->clipboard().ReadHTML(ClipboardBuffer::kCopyPaste,
+                             /* data_dst = */ nullptr, &markup_result,
                              &url_result, &fragment_start, &fragment_end);
   EXPECT_LE(markup.size(), fragment_end - fragment_start);
   EXPECT_EQ(markup,
@@ -364,9 +390,11 @@
   // this.
   EXPECT_EQ(url, url_result);
 #endif  // defined(OS_WIN)
-  this->clipboard().ReadText(ClipboardBuffer::kCopyPaste, &text_result);
+  this->clipboard().ReadText(ClipboardBuffer::kCopyPaste,
+                             /* data_dst = */ nullptr, &text_result);
   EXPECT_EQ(text, text_result);
-  this->clipboard().ReadAsciiText(ClipboardBuffer::kCopyPaste, &ascii_text);
+  this->clipboard().ReadAsciiText(ClipboardBuffer::kCopyPaste,
+                                  /* data_dst = */ nullptr, &ascii_text);
   EXPECT_EQ(UTF16ToUTF8(text), ascii_text);
 }
 
@@ -381,18 +409,22 @@
   EXPECT_THAT(this->GetAvailableTypes(ClipboardBuffer::kCopyPaste),
               Contains(ASCIIToUTF16(kMimeTypeText)));
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste));
+      ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
 #if defined(OS_WIN)
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetPlainTextAType(), ClipboardBuffer::kCopyPaste));
+      ClipboardFormatType::GetPlainTextAType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
 #endif
   base::string16 text_result;
-  this->clipboard().ReadText(ClipboardBuffer::kCopyPaste, &text_result);
+  this->clipboard().ReadText(ClipboardBuffer::kCopyPaste,
+                             /* data_dst = */ nullptr, &text_result);
 
   EXPECT_EQ(text_result, url);
 
   std::string ascii_text;
-  this->clipboard().ReadAsciiText(ClipboardBuffer::kCopyPaste, &ascii_text);
+  this->clipboard().ReadAsciiText(ClipboardBuffer::kCopyPaste,
+                                  /* data_dst = */ nullptr, &ascii_text);
   EXPECT_EQ(UTF16ToUTF8(url), ascii_text);
 
 // TODO(tonikitoo, msisov): enable back for ClipboardOzone implements
@@ -400,7 +432,8 @@
 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) && \
     !defined(OS_CHROMEOS) && !defined(USE_OZONE)
   ascii_text.clear();
-  this->clipboard().ReadAsciiText(ClipboardBuffer::kSelection, &ascii_text);
+  this->clipboard().ReadAsciiText(ClipboardBuffer::kSelection,
+                                  /* data_dst = */ nullptr, &ascii_text);
   EXPECT_EQ(UTF16ToUTF8(url), ascii_text);
 #endif
 }
@@ -425,7 +458,8 @@
   }
 
   EXPECT_TRUE(clipboard->IsFormatAvailable(ClipboardFormatType::GetBitmapType(),
-                                           ClipboardBuffer::kCopyPaste));
+                                           ClipboardBuffer::kCopyPaste,
+                                           /* data_dst = */ nullptr));
   const SkBitmap& image = clipboard_test_util::ReadImage(clipboard);
   ASSERT_EQ(image.info().colorType(), kN32_SkColorType);
   ASSERT_NE(image.info().alphaType(), kUnpremul_SkAlphaType);
@@ -559,10 +593,10 @@
     clipboard_writer.WritePickledData(write_pickle, kFormat);
   }
 
-  ASSERT_TRUE(this->clipboard().IsFormatAvailable(kFormat,
-                                                  ClipboardBuffer::kCopyPaste));
+  ASSERT_TRUE(this->clipboard().IsFormatAvailable(
+      kFormat, ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr));
   std::string output;
-  this->clipboard().ReadData(kFormat, &output);
+  this->clipboard().ReadData(kFormat, /* data_dst = */ nullptr, &output);
   ASSERT_FALSE(output.empty());
 
   base::Pickle read_pickle(output.data(), static_cast<int>(output.size()));
@@ -593,13 +627,13 @@
   }
 
   ASSERT_FALSE(this->clipboard().IsFormatAvailable(
-      kFormat1, ClipboardBuffer::kCopyPaste));
-  ASSERT_TRUE(this->clipboard().IsFormatAvailable(kFormat2,
-                                                  ClipboardBuffer::kCopyPaste));
+      kFormat1, ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr));
+  ASSERT_TRUE(this->clipboard().IsFormatAvailable(
+      kFormat2, ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr));
 
   // Check string 2.
   std::string output2;
-  this->clipboard().ReadData(kFormat2, &output2);
+  this->clipboard().ReadData(kFormat2, /* data_dst = */ nullptr, &output2);
   ASSERT_FALSE(output2.empty());
 
   base::Pickle read_pickle2(output2.data(), static_cast<int>(output2.size()));
@@ -615,14 +649,14 @@
     clipboard_writer.WritePickledData(write_pickle1, kFormat1);
   }
 
-  ASSERT_TRUE(this->clipboard().IsFormatAvailable(kFormat1,
-                                                  ClipboardBuffer::kCopyPaste));
+  ASSERT_TRUE(this->clipboard().IsFormatAvailable(
+      kFormat1, ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr));
   ASSERT_FALSE(this->clipboard().IsFormatAvailable(
-      kFormat2, ClipboardBuffer::kCopyPaste));
+      kFormat2, ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr));
 
   // Check string 1.
   std::string output1;
-  this->clipboard().ReadData(kFormat1, &output1);
+  this->clipboard().ReadData(kFormat1, /* data_dst = */ nullptr, &output1);
   ASSERT_FALSE(output1.empty());
 
   base::Pickle read_pickle1(output1.data(), static_cast<int>(output1.size()));
@@ -646,10 +680,10 @@
                                mojo_base::BigBuffer(payload_span));
   }
 
-  ASSERT_TRUE(this->clipboard().IsFormatAvailable(kFormat,
-                                                  ClipboardBuffer::kCopyPaste));
+  ASSERT_TRUE(this->clipboard().IsFormatAvailable(
+      kFormat, ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr));
   std::string output;
-  this->clipboard().ReadData(kFormat, &output);
+  this->clipboard().ReadData(kFormat, /* data_dst = */ nullptr, &output);
 
   EXPECT_EQ(payload, output);
 }
@@ -686,22 +720,22 @@
 
   // Check format 1.
   EXPECT_THAT(this->clipboard().ReadAvailablePlatformSpecificFormatNames(
-                  ClipboardBuffer::kCopyPaste),
+                  ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr),
               Contains(ASCIIToUTF16(kFormatString1)));
-  EXPECT_TRUE(this->clipboard().IsFormatAvailable(kFormat1,
-                                                  ClipboardBuffer::kCopyPaste));
+  EXPECT_TRUE(this->clipboard().IsFormatAvailable(
+      kFormat1, ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr));
   std::string output1;
-  this->clipboard().ReadData(kFormat1, &output1);
+  this->clipboard().ReadData(kFormat1, /* data_dst = */ nullptr, &output1);
   EXPECT_EQ(payload1, output1);
 
   // Check format 2.
   EXPECT_THAT(this->clipboard().ReadAvailablePlatformSpecificFormatNames(
-                  ClipboardBuffer::kCopyPaste),
+                  ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr),
               Contains(ASCIIToUTF16(kFormatString2)));
-  EXPECT_TRUE(this->clipboard().IsFormatAvailable(kFormat2,
-                                                  ClipboardBuffer::kCopyPaste));
+  EXPECT_TRUE(this->clipboard().IsFormatAvailable(
+      kFormat2, ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr));
   std::string output2;
-  this->clipboard().ReadData(kFormat2, &output2);
+  this->clipboard().ReadData(kFormat2, /* data_dst = */ nullptr, &output2);
   EXPECT_EQ(payload2, output2);
 }
 #endif
@@ -716,7 +750,7 @@
 
   const std::vector<base::string16> raw_types =
       this->clipboard().ReadAvailablePlatformSpecificFormatNames(
-          ClipboardBuffer::kCopyPaste);
+          ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr);
 #if defined(OS_MACOSX)
   EXPECT_THAT(raw_types, Contains(ASCIIToUTF16("public.utf8-plain-text")));
   EXPECT_THAT(raw_types, Contains(ASCIIToUTF16("NSStringPboardType")));
@@ -778,31 +812,37 @@
 
   const std::vector<base::string16> raw_types =
       this->clipboard().ReadAvailablePlatformSpecificFormatNames(
-          ClipboardBuffer::kCopyPaste);
+          ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr);
 
   EXPECT_THAT(raw_types, Contains(ASCIIToUTF16(kFormatString)));
 
 #if defined(OS_WIN)
   // Only Windows ClipboardFormatType recognizes ANSI formats.
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetPlainTextAType(), ClipboardBuffer::kCopyPaste));
+      ClipboardFormatType::GetPlainTextAType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
 #endif  // defined(OS_WIN)
 
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste));
+      ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
 
   std::string text_result;
-  this->clipboard().ReadAsciiText(ClipboardBuffer::kCopyPaste, &text_result);
+  this->clipboard().ReadAsciiText(ClipboardBuffer::kCopyPaste,
+                                  /* data_dst = */ nullptr, &text_result);
   EXPECT_EQ(text_result, text);
   // Note: Windows will automatically convert CF_TEXT to its UNICODE version.
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste));
+      ClipboardFormatType::GetPlainTextType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
   base::string16 text_result16;
-  this->clipboard().ReadText(ClipboardBuffer::kCopyPaste, &text_result16);
+  this->clipboard().ReadText(ClipboardBuffer::kCopyPaste,
+                             /* data_dst = */ nullptr, &text_result16);
   EXPECT_EQ(text_result16, base::ASCIIToUTF16(text));
 
   std::string platform_specific_result;
   this->clipboard().ReadData(ClipboardFormatType::GetType(kFormatString),
+                             /* data_dst = */ nullptr,
                              &platform_specific_result);
   EXPECT_EQ(platform_specific_result, kPlatformSpecificText);
 }
@@ -824,10 +864,12 @@
   }
 
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
-      ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kCopyPaste));
+      ClipboardFormatType::GetHtmlType(), ClipboardBuffer::kCopyPaste,
+      /* data_dst = */ nullptr));
   uint32_t fragment_start;
   uint32_t fragment_end;
-  this->clipboard().ReadHTML(ClipboardBuffer::kCopyPaste, &html_result,
+  this->clipboard().ReadHTML(ClipboardBuffer::kCopyPaste,
+                             /* data_dst = */ nullptr, &html_result,
                              &url_result, &fragment_start, &fragment_end);
   EXPECT_EQ(kExpectedHtml,
             html_result.substr(fragment_end - kExpectedHtml.size(),
@@ -843,7 +885,7 @@
 
   EXPECT_TRUE(this->clipboard().IsFormatAvailable(
       ClipboardFormatType::GetWebKitSmartPasteType(),
-      ClipboardBuffer::kCopyPaste));
+      ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr));
 }
 
 #if defined(OS_WIN)  // Windows only tests.
diff --git a/ui/base/clipboard/clipboard_win.cc b/ui/base/clipboard/clipboard_win.cc
index 83795a0..403670c2 100644
--- a/ui/base/clipboard/clipboard_win.cc
+++ b/ui/base/clipboard/clipboard_win.cc
@@ -246,8 +246,12 @@
   return ::GetClipboardSequenceNumber();
 }
 
-bool ClipboardWin::IsFormatAvailable(const ClipboardFormatType& format,
-                                     ClipboardBuffer buffer) const {
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
+bool ClipboardWin::IsFormatAvailable(
+    const ClipboardFormatType& format,
+    ClipboardBuffer buffer,
+    const ClipboardDataEndpoint* data_dst) const {
   DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
   return ::IsClipboardFormatAvailable(format.ToFormatEtc().cfFormat) != FALSE;
 }
@@ -261,8 +265,11 @@
   ::EmptyClipboard();
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardWin::ReadAvailableTypes(
     ClipboardBuffer buffer,
+    const ClipboardDataEndpoint* data_dst,
     std::vector<base::string16>* types) const {
   DCHECK(types);
 
@@ -293,9 +300,12 @@
   ::GlobalUnlock(hdata);
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 std::vector<base::string16>
 ClipboardWin::ReadAvailablePlatformSpecificFormatNames(
-    ClipboardBuffer buffer) const {
+    ClipboardBuffer buffer,
+    const ClipboardDataEndpoint* data_dst) const {
   int count = ::CountClipboardFormats();
   if (!count)
     return {};
@@ -318,7 +328,10 @@
   return types;
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardWin::ReadText(ClipboardBuffer buffer,
+                            const ClipboardDataEndpoint* data_dst,
                             base::string16* result) const {
   DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
   RecordRead(ClipboardFormatMetric::kText);
@@ -344,7 +357,10 @@
   TrimAfterNull(result);
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardWin::ReadAsciiText(ClipboardBuffer buffer,
+                                 const ClipboardDataEndpoint* data_dst,
                                  std::string* result) const {
   DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
   RecordRead(ClipboardFormatMetric::kText);
@@ -370,7 +386,10 @@
   TrimAfterNull(result);
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardWin::ReadHTML(ClipboardBuffer buffer,
+                            const ClipboardDataEndpoint* data_dst,
                             base::string16* markup,
                             std::string* src_url,
                             uint32_t* fragment_start,
@@ -428,22 +447,32 @@
   *fragment_end = base::checked_cast<uint32_t>(end);
 }
 
-void ClipboardWin::ReadRTF(ClipboardBuffer buffer, std::string* result) const {
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
+void ClipboardWin::ReadRTF(ClipboardBuffer buffer,
+                           const ClipboardDataEndpoint* data_dst,
+                           std::string* result) const {
   DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
   RecordRead(ClipboardFormatMetric::kRtf);
 
-  ReadData(ClipboardFormatType::GetRtfType(), result);
+  ReadData(ClipboardFormatType::GetRtfType(), data_dst, result);
   TrimAfterNull(result);
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardWin::ReadImage(ClipboardBuffer buffer,
+                             const ClipboardDataEndpoint* data_dst,
                              ReadImageCallback callback) const {
   RecordRead(ClipboardFormatMetric::kImage);
   std::move(callback).Run(ReadImageInternal(buffer));
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardWin::ReadCustomData(ClipboardBuffer buffer,
                                   const base::string16& type,
+                                  const ClipboardDataEndpoint* data_dst,
                                   base::string16* result) const {
   DCHECK_EQ(buffer, ClipboardBuffer::kCopyPaste);
   RecordRead(ClipboardFormatMetric::kCustomData);
@@ -462,7 +491,11 @@
   ::GlobalUnlock(hdata);
 }
 
-void ClipboardWin::ReadBookmark(base::string16* title, std::string* url) const {
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
+void ClipboardWin::ReadBookmark(const ClipboardDataEndpoint* data_dst,
+                                base::string16* title,
+                                std::string* url) const {
   RecordRead(ClipboardFormatMetric::kBookmark);
   if (title)
     title->clear();
@@ -488,7 +521,10 @@
   ParseBookmarkClipboardFormat(bookmark, title, url);
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardWin::ReadData(const ClipboardFormatType& format,
+                            const ClipboardDataEndpoint* data_dst,
                             std::string* result) const {
   RecordRead(ClipboardFormatMetric::kData);
   if (!result) {
diff --git a/ui/base/clipboard/clipboard_win.h b/ui/base/clipboard/clipboard_win.h
index 895acba9..7843b1e 100644
--- a/ui/base/clipboard/clipboard_win.h
+++ b/ui/base/clipboard/clipboard_win.h
@@ -37,28 +37,42 @@
   void OnPreShutdown() override;
   uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
   bool IsFormatAvailable(const ClipboardFormatType& format,
-                         ClipboardBuffer buffer) const override;
+                         ClipboardBuffer buffer,
+                         const ClipboardDataEndpoint* data_dst) const override;
   void Clear(ClipboardBuffer buffer) override;
   void ReadAvailableTypes(ClipboardBuffer buffer,
+                          const ClipboardDataEndpoint* data_dst,
                           std::vector<base::string16>* types) const override;
   std::vector<base::string16> ReadAvailablePlatformSpecificFormatNames(
-      ClipboardBuffer buffer) const override;
-  void ReadText(ClipboardBuffer buffer, base::string16* result) const override;
+      ClipboardBuffer buffer,
+      const ClipboardDataEndpoint* data_dst) const override;
+  void ReadText(ClipboardBuffer buffer,
+                const ClipboardDataEndpoint* data_dst,
+                base::string16* result) const override;
   void ReadAsciiText(ClipboardBuffer buffer,
+                     const ClipboardDataEndpoint* data_dst,
                      std::string* result) const override;
   void ReadHTML(ClipboardBuffer buffer,
+                const ClipboardDataEndpoint* data_dst,
                 base::string16* markup,
                 std::string* src_url,
                 uint32_t* fragment_start,
                 uint32_t* fragment_end) const override;
-  void ReadRTF(ClipboardBuffer buffer, std::string* result) const override;
+  void ReadRTF(ClipboardBuffer buffer,
+               const ClipboardDataEndpoint* data_dst,
+               std::string* result) const override;
   void ReadImage(ClipboardBuffer buffer,
+                 const ClipboardDataEndpoint* data_dst,
                  ReadImageCallback callback) const override;
   void ReadCustomData(ClipboardBuffer buffer,
                       const base::string16& type,
+                      const ClipboardDataEndpoint* data_dst,
                       base::string16* result) const override;
-  void ReadBookmark(base::string16* title, std::string* url) const override;
+  void ReadBookmark(const ClipboardDataEndpoint* data_dst,
+                    base::string16* title,
+                    std::string* url) const override;
   void ReadData(const ClipboardFormatType& format,
+                const ClipboardDataEndpoint* data_dst,
                 std::string* result) const override;
   void WritePortableRepresentations(
       ClipboardBuffer buffer,
diff --git a/ui/base/clipboard/clipboard_x11.cc b/ui/base/clipboard/clipboard_x11.cc
index fec81727..898660f 100644
--- a/ui/base/clipboard/clipboard_x11.cc
+++ b/ui/base/clipboard/clipboard_x11.cc
@@ -498,8 +498,12 @@
     return SelectionChangeObserver::GetInstance()->primary_sequence_number();
 }
 
-bool ClipboardX11::IsFormatAvailable(const ClipboardFormatType& format,
-                                     ClipboardBuffer buffer) const {
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
+bool ClipboardX11::IsFormatAvailable(
+    const ClipboardFormatType& format,
+    ClipboardBuffer buffer,
+    const ClipboardDataEndpoint* data_dst) const {
   DCHECK(CalledOnValidThread());
   DCHECK(IsSupportedClipboardBuffer(buffer));
 
@@ -517,8 +521,11 @@
   x11_details_->Clear(buffer);
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardX11::ReadAvailableTypes(
     ClipboardBuffer buffer,
+    const ClipboardDataEndpoint* data_dst,
     std::vector<base::string16>* types) const {
   DCHECK(CalledOnValidThread());
   DCHECK(types);
@@ -543,9 +550,12 @@
     ReadCustomDataTypes(data.GetData(), data.GetSize(), types);
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 std::vector<base::string16>
 ClipboardX11::ReadAvailablePlatformSpecificFormatNames(
-    ClipboardBuffer buffer) const {
+    ClipboardBuffer buffer,
+    const ClipboardDataEndpoint* data_dst) const {
   DCHECK(CalledOnValidThread());
 
   // Copy target_list(), so that XGetAtomNames can get a non-const Atom*.
@@ -569,7 +579,10 @@
   return types;
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardX11::ReadText(ClipboardBuffer buffer,
+                            const ClipboardDataEndpoint* data_dst,
                             base::string16* result) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kText);
@@ -582,7 +595,10 @@
   }
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardX11::ReadAsciiText(ClipboardBuffer buffer,
+                                 const ClipboardDataEndpoint* data_dst,
                                  std::string* result) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kText);
@@ -595,7 +611,10 @@
 
 // TODO(estade): handle different charsets.
 // TODO(port): set *src_url.
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardX11::ReadHTML(ClipboardBuffer buffer,
+                            const ClipboardDataEndpoint* data_dst,
                             base::string16* markup,
                             std::string* src_url,
                             uint32_t* fragment_start,
@@ -620,7 +639,11 @@
   }
 }
 
-void ClipboardX11::ReadRTF(ClipboardBuffer buffer, std::string* result) const {
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
+void ClipboardX11::ReadRTF(ClipboardBuffer buffer,
+                           const ClipboardDataEndpoint* data_dst,
+                           std::string* result) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kRtf);
 
@@ -631,15 +654,21 @@
     data.AssignTo(result);
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardX11::ReadImage(ClipboardBuffer buffer,
+                             const ClipboardDataEndpoint* data_dst,
                              ReadImageCallback callback) const {
   DCHECK(IsSupportedClipboardBuffer(buffer));
   RecordRead(ClipboardFormatMetric::kImage);
   std::move(callback).Run(ReadImageInternal(buffer));
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardX11::ReadCustomData(ClipboardBuffer buffer,
                                   const base::string16& type,
+                                  const ClipboardDataEndpoint* data_dst,
                                   base::string16* result) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kCustomData);
@@ -651,13 +680,20 @@
     ReadCustomDataForType(data.GetData(), data.GetSize(), type, result);
 }
 
-void ClipboardX11::ReadBookmark(base::string16* title, std::string* url) const {
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
+void ClipboardX11::ReadBookmark(const ClipboardDataEndpoint* data_dst,
+                                base::string16* title,
+                                std::string* url) const {
   DCHECK(CalledOnValidThread());
   // TODO(erg): This was left NOTIMPLEMENTED() in the gtk port too.
   NOTIMPLEMENTED();
 }
 
+// |data_dst| is not used. It's only passed to be consistent with other
+// platforms.
 void ClipboardX11::ReadData(const ClipboardFormatType& format,
+                            const ClipboardDataEndpoint* data_dst,
                             std::string* result) const {
   DCHECK(CalledOnValidThread());
   RecordRead(ClipboardFormatMetric::kData);
diff --git a/ui/base/clipboard/clipboard_x11.h b/ui/base/clipboard/clipboard_x11.h
index 891fa79..c0f5146 100644
--- a/ui/base/clipboard/clipboard_x11.h
+++ b/ui/base/clipboard/clipboard_x11.h
@@ -26,28 +26,42 @@
   void OnPreShutdown() override;
   uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
   bool IsFormatAvailable(const ClipboardFormatType& format,
-                         ClipboardBuffer buffer) const override;
+                         ClipboardBuffer buffer,
+                         const ClipboardDataEndpoint* data_dst) const override;
   void Clear(ClipboardBuffer buffer) override;
   void ReadAvailableTypes(ClipboardBuffer buffer,
+                          const ClipboardDataEndpoint* data_dst,
                           std::vector<base::string16>* types) const override;
   std::vector<base::string16> ReadAvailablePlatformSpecificFormatNames(
-      ClipboardBuffer buffer) const override;
-  void ReadText(ClipboardBuffer buffer, base::string16* result) const override;
+      ClipboardBuffer buffer,
+      const ClipboardDataEndpoint* data_dst) const override;
+  void ReadText(ClipboardBuffer buffer,
+                const ClipboardDataEndpoint* data_dst,
+                base::string16* result) const override;
   void ReadAsciiText(ClipboardBuffer buffer,
+                     const ClipboardDataEndpoint* data_dst,
                      std::string* result) const override;
   void ReadHTML(ClipboardBuffer buffer,
+                const ClipboardDataEndpoint* data_dst,
                 base::string16* markup,
                 std::string* src_url,
                 uint32_t* fragment_start,
                 uint32_t* fragment_end) const override;
-  void ReadRTF(ClipboardBuffer buffer, std::string* result) const override;
+  void ReadRTF(ClipboardBuffer buffer,
+               const ClipboardDataEndpoint* data_dst,
+               std::string* result) const override;
   void ReadImage(ClipboardBuffer buffer,
+                 const ClipboardDataEndpoint* data_dst,
                  ReadImageCallback callback) const override;
   void ReadCustomData(ClipboardBuffer buffer,
                       const base::string16& type,
+                      const ClipboardDataEndpoint* data_dst,
                       base::string16* result) const override;
-  void ReadBookmark(base::string16* title, std::string* url) const override;
+  void ReadBookmark(const ClipboardDataEndpoint* data_dst,
+                    base::string16* title,
+                    std::string* url) const override;
   void ReadData(const ClipboardFormatType& format,
+                const ClipboardDataEndpoint* data_dst,
                 std::string* result) const override;
   void WritePortableRepresentations(
       ClipboardBuffer buffer,
diff --git a/ui/base/clipboard/test/clipboard_test_util.cc b/ui/base/clipboard/test/clipboard_test_util.cc
index cc3a67a..fd12f1c5 100644
--- a/ui/base/clipboard/test/clipboard_test_util.cc
+++ b/ui/base/clipboard/test/clipboard_test_util.cc
@@ -24,6 +24,7 @@
     SkBitmap bitmap;
     clipboard->ReadImage(
         ClipboardBuffer::kCopyPaste,
+        /* data_dst = */ nullptr,
         base::BindLambdaForTesting([&](const SkBitmap& result) {
           bitmap = result;
           event.Signal();
diff --git a/ui/base/clipboard/test/test_clipboard.cc b/ui/base/clipboard/test/test_clipboard.cc
index b2629b1..ef56ff195 100644
--- a/ui/base/clipboard/test/test_clipboard.cc
+++ b/ui/base/clipboard/test/test_clipboard.cc
@@ -39,13 +39,17 @@
   return GetStore(buffer).sequence_number;
 }
 
-bool TestClipboard::IsFormatAvailable(const ClipboardFormatType& format,
-                                      ClipboardBuffer buffer) const {
+// TODO(crbug.com/1103215): |data_dst| should be supported.
+bool TestClipboard::IsFormatAvailable(
+    const ClipboardFormatType& format,
+    ClipboardBuffer buffer,
+    const ui::ClipboardDataEndpoint* data_dst) const {
 #if defined(OS_LINUX)
   // The linux clipboard treats the presence of text on the clipboard
   // as the url format being available.
   if (format.Equals(ClipboardFormatType::GetUrlType()))
-    return IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer);
+    return IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer,
+                             data_dst);
 #endif  // OS_LINUX
   const DataStore& store = GetStore(buffer);
   return base::Contains(store.data, format);
@@ -55,26 +59,31 @@
   GetStore(buffer).Clear();
 }
 
+// TODO(crbug.com/1103215): |data_dst| should be supported.
 void TestClipboard::ReadAvailableTypes(
     ClipboardBuffer buffer,
+    const ClipboardDataEndpoint* data_dst,
     std::vector<base::string16>* types) const {
   DCHECK(types);
   types->clear();
 
-  if (IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer))
+  if (IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer,
+                        data_dst))
     types->push_back(base::UTF8ToUTF16(kMimeTypeText));
-  if (IsFormatAvailable(ClipboardFormatType::GetHtmlType(), buffer))
+  if (IsFormatAvailable(ClipboardFormatType::GetHtmlType(), buffer, data_dst))
     types->push_back(base::UTF8ToUTF16(kMimeTypeHTML));
 
-  if (IsFormatAvailable(ClipboardFormatType::GetRtfType(), buffer))
+  if (IsFormatAvailable(ClipboardFormatType::GetRtfType(), buffer, data_dst))
     types->push_back(base::UTF8ToUTF16(kMimeTypeRTF));
-  if (IsFormatAvailable(ClipboardFormatType::GetBitmapType(), buffer))
+  if (IsFormatAvailable(ClipboardFormatType::GetBitmapType(), buffer, data_dst))
     types->push_back(base::UTF8ToUTF16(kMimeTypePNG));
 }
 
+// TODO(crbug.com/1103215): |data_dst| should be supported.
 std::vector<base::string16>
 TestClipboard::ReadAvailablePlatformSpecificFormatNames(
-    ClipboardBuffer buffer) const {
+    ClipboardBuffer buffer,
+    const ui::ClipboardDataEndpoint* data_dst) const {
   const auto& data = GetStore(buffer).data;
   std::vector<base::string16> types;
   types.reserve(data.size());
@@ -83,7 +92,8 @@
 
   // Some platforms add additional raw types to represent text, or offer them
   // as available formats by automatically converting between them.
-  if (IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer)) {
+  if (IsFormatAvailable(ClipboardFormatType::GetPlainTextType(), buffer,
+                        data_dst)) {
 #if defined(USE_X11)
     types.push_back(base::ASCIIToUTF16("TEXT"));
     types.push_back(base::ASCIIToUTF16("STRING"));
@@ -99,14 +109,18 @@
   return types;
 }
 
+// TODO(crbug.com/1103215): |data_dst| should be supported.
 void TestClipboard::ReadText(ClipboardBuffer buffer,
+                             const ClipboardDataEndpoint* data_dst,
                              base::string16* result) const {
   std::string result8;
-  ReadAsciiText(buffer, &result8);
+  ReadAsciiText(buffer, data_dst, &result8);
   *result = base::UTF8ToUTF16(result8);
 }
 
+// TODO(crbug.com/1103215): |data_dst| should be supported.
 void TestClipboard::ReadAsciiText(ClipboardBuffer buffer,
+                                  const ClipboardDataEndpoint* data_dst,
                                   std::string* result) const {
   result->clear();
   const DataStore& store = GetStore(buffer);
@@ -115,7 +129,9 @@
     *result = it->second;
 }
 
+// TODO(crbug.com/1103215): |data_dst| should be supported.
 void TestClipboard::ReadHTML(ClipboardBuffer buffer,
+                             const ClipboardDataEndpoint* data_dst,
                              base::string16* markup,
                              std::string* src_url,
                              uint32_t* fragment_start,
@@ -131,7 +147,10 @@
   *fragment_end = base::checked_cast<uint32_t>(markup->size());
 }
 
-void TestClipboard::ReadRTF(ClipboardBuffer buffer, std::string* result) const {
+// TODO(crbug.com/1103215): |data_dst| should be supported.
+void TestClipboard::ReadRTF(ClipboardBuffer buffer,
+                            const ClipboardDataEndpoint* data_dst,
+                            std::string* result) const {
   result->clear();
   const DataStore& store = GetStore(buffer);
   auto it = store.data.find(ClipboardFormatType::GetRtfType());
@@ -139,16 +158,22 @@
     *result = it->second;
 }
 
+// TODO(crbug.com/1103215): |data_dst| should be supported.
 void TestClipboard::ReadImage(ClipboardBuffer buffer,
+                              const ClipboardDataEndpoint* data_dst,
                               ReadImageCallback callback) const {
   std::move(callback).Run(GetStore(buffer).image);
 }
 
+// TODO(crbug.com/1103215): |data_dst| should be supported.
 void TestClipboard::ReadCustomData(ClipboardBuffer buffer,
                                    const base::string16& type,
+                                   const ClipboardDataEndpoint* data_dst,
                                    base::string16* result) const {}
 
-void TestClipboard::ReadBookmark(base::string16* title,
+// TODO(crbug.com/1103215): |data_dst| should be supported.
+void TestClipboard::ReadBookmark(const ClipboardDataEndpoint* data_dst,
+                                 base::string16* title,
                                  std::string* url) const {
   const DataStore& store = GetDefaultStore();
   if (url) {
@@ -160,7 +185,9 @@
     *title = base::UTF8ToUTF16(store.url_title);
 }
 
+// TODO(crbug.com/1103215): |data_dst| should be supported.
 void TestClipboard::ReadData(const ClipboardFormatType& format,
+                             const ClipboardDataEndpoint* data_dst,
                              std::string* result) const {
   result->clear();
   const DataStore& store = GetDefaultStore();
diff --git a/ui/base/clipboard/test/test_clipboard.h b/ui/base/clipboard/test/test_clipboard.h
index 8b4a8ea..95a3430 100644
--- a/ui/base/clipboard/test/test_clipboard.h
+++ b/ui/base/clipboard/test/test_clipboard.h
@@ -36,28 +36,42 @@
   void OnPreShutdown() override;
   uint64_t GetSequenceNumber(ClipboardBuffer buffer) const override;
   bool IsFormatAvailable(const ClipboardFormatType& format,
-                         ClipboardBuffer buffer) const override;
+                         ClipboardBuffer buffer,
+                         const ClipboardDataEndpoint* data_dst) const override;
   void Clear(ClipboardBuffer buffer) override;
   void ReadAvailableTypes(ClipboardBuffer buffer,
+                          const ClipboardDataEndpoint* data_dst,
                           std::vector<base::string16>* types) const override;
   std::vector<base::string16> ReadAvailablePlatformSpecificFormatNames(
-      ClipboardBuffer buffer) const override;
-  void ReadText(ClipboardBuffer buffer, base::string16* result) const override;
+      ClipboardBuffer buffer,
+      const ClipboardDataEndpoint* data_dst) const override;
+  void ReadText(ClipboardBuffer buffer,
+                const ClipboardDataEndpoint* data_dst,
+                base::string16* result) const override;
   void ReadAsciiText(ClipboardBuffer buffer,
+                     const ClipboardDataEndpoint* data_dst,
                      std::string* result) const override;
   void ReadHTML(ClipboardBuffer buffer,
+                const ClipboardDataEndpoint* data_dst,
                 base::string16* markup,
                 std::string* src_url,
                 uint32_t* fragment_start,
                 uint32_t* fragment_end) const override;
-  void ReadRTF(ClipboardBuffer buffer, std::string* result) const override;
+  void ReadRTF(ClipboardBuffer buffer,
+               const ClipboardDataEndpoint* data_dst,
+               std::string* result) const override;
   void ReadImage(ClipboardBuffer buffer,
+                 const ClipboardDataEndpoint* data_dst,
                  ReadImageCallback callback) const override;
   void ReadCustomData(ClipboardBuffer buffer,
                       const base::string16& type,
+                      const ClipboardDataEndpoint* data_dst,
                       base::string16* result) const override;
-  void ReadBookmark(base::string16* title, std::string* url) const override;
+  void ReadBookmark(const ClipboardDataEndpoint* data_dst,
+                    base::string16* title,
+                    std::string* url) const override;
   void ReadData(const ClipboardFormatType& format,
+                const ClipboardDataEndpoint* data_dst,
                 std::string* result) const override;
   base::Time GetLastModifiedTime() const override;
   void ClearLastModifiedTime() override;
diff --git a/ui/file_manager/file_manager/foreground/js/ui/breadcrumb.js b/ui/file_manager/file_manager/foreground/js/ui/breadcrumb.js
index f4b3a70b..743497f 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/breadcrumb.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/breadcrumb.js
@@ -450,7 +450,7 @@
 
     // Show drop-down below the elider button.
     const menu = this.shadowRoot.querySelector('cr-action-menu');
-    const top = elider.offsetTop + elider.offsetHeight + 4;
+    const top = elider.offsetTop + elider.offsetHeight + 8;
     !window.UNIT_TEST && menu.showAt(elider, {top: top});
 
     // Style drop-down and horizontal position.
diff --git a/ui/gfx/color_space.cc b/ui/gfx/color_space.cc
index 8ebf9197..faf9fd49 100644
--- a/ui/gfx/color_space.cc
+++ b/ui/gfx/color_space.cc
@@ -559,16 +559,6 @@
   return result;
 }
 
-ColorSpace ColorSpace::GetRasterColorSpace() const {
-  // Rasterization doesn't support more than 8 bit unorm values. If the output
-  // space has an extended range, use Display P3 for the rasterization space,
-  // to get a somewhat wider color gamut.
-  if (IsHDR())
-    return CreateDisplayP3D65();
-
-  return *this;
-}
-
 bool ColorSpace::IsSuitableForBlending() const {
   switch (transfer_) {
     case TransferID::SMPTEST2084:
diff --git a/ui/gfx/color_space.h b/ui/gfx/color_space.h
index 63f456c..7f6334d 100644
--- a/ui/gfx/color_space.h
+++ b/ui/gfx/color_space.h
@@ -260,10 +260,6 @@
   // everything will be half as bright in linear lumens.
   ColorSpace GetScaledColorSpace(float factor) const;
 
-  // If |this| is the final output color space, return the color space that
-  // would be appropriate for rasterization.
-  ColorSpace GetRasterColorSpace() const;
-
   // Return true if blending in |this| is close enough to blending in sRGB to
   // be considered acceptable (only PQ and nearly-linear transfer functions
   // return false).
diff --git a/ui/gfx/color_space_unittest.cc b/ui/gfx/color_space_unittest.cc
index ea8cabd..082610c 100644
--- a/ui/gfx/color_space_unittest.cc
+++ b/ui/gfx/color_space_unittest.cc
@@ -179,20 +179,17 @@
   }
 }
 
-TEST(ColorSpace, RasterAndBlend) {
+TEST(ColorSpace, Blending) {
   ColorSpace display_color_space;
 
   // A linear transfer function being used for HDR should be blended using an
   // sRGB-like transfer function.
   display_color_space = ColorSpace::CreateSCRGBLinear();
   EXPECT_FALSE(display_color_space.IsSuitableForBlending());
-  EXPECT_EQ(ColorSpace::CreateDisplayP3D65(),
-            display_color_space.GetRasterColorSpace());
 
   // If not used for HDR, a linear transfer function should be left unchanged.
   display_color_space = ColorSpace::CreateXYZD50();
   EXPECT_TRUE(display_color_space.IsSuitableForBlending());
-  EXPECT_EQ(display_color_space, display_color_space.GetRasterColorSpace());
 }
 
 TEST(ColorSpace, ConversionToAndFromSkColorSpace) {
diff --git a/ui/gfx/display_color_spaces.cc b/ui/gfx/display_color_spaces.cc
index 0723c93..ca302b3 100644
--- a/ui/gfx/display_color_spaces.cc
+++ b/ui/gfx/display_color_spaces.cc
@@ -95,8 +95,7 @@
 }
 
 gfx::ColorSpace DisplayColorSpaces::GetRasterColorSpace() const {
-  return GetOutputColorSpace(ContentColorUsage::kHDR, false /* needs_alpha */)
-      .GetRasterColorSpace();
+  return GetOutputColorSpace(ContentColorUsage::kHDR, false /* needs_alpha */);
 }
 
 gfx::ColorSpace DisplayColorSpaces::GetCompositingColorSpace(
diff --git a/ui/views/animation/ink_drop_impl.cc b/ui/views/animation/ink_drop_impl.cc
index fd36587..635e1dd 100644
--- a/ui/views/animation/ink_drop_impl.cc
+++ b/ui/views/animation/ink_drop_impl.cc
@@ -720,6 +720,11 @@
 void InkDropImpl::DestroyInkDropRipple() {
   if (!ink_drop_ripple_)
     return;
+
+  // Ensures no observer callback happens from removing from |root_layer_|
+  // or destroying |ink_drop_ripple_|. Speculative fix for crashes in
+  // https://crbug.com/1088432 and https://crbug.com/1099844.
+  ink_drop_ripple_->set_observer(nullptr);
   root_layer_->Remove(ink_drop_ripple_->GetRootLayer());
   ink_drop_ripple_.reset();
   RemoveRootLayerFromHostIfNeeded();
@@ -746,8 +751,12 @@
 void InkDropImpl::DestroyInkDropHighlight() {
   if (!highlight_)
     return;
-  root_layer_->Remove(highlight_->layer());
+
+  // Ensures no observer callback happens from removing from |root_layer_|
+  // or destroying |highlight_|. Speculative fix for crashes in
+  // https://crbug.com/1088432 and https://crbug.com/1099844.
   highlight_->set_observer(nullptr);
+  root_layer_->Remove(highlight_->layer());
   highlight_.reset();
   RemoveRootLayerFromHostIfNeeded();
 }
@@ -772,6 +781,9 @@
 // views::InkDropRippleObserver:
 
 void InkDropImpl::AnimationStarted(InkDropState ink_drop_state) {
+  // AnimationStarted should only be called from |ink_drop_ripple_|.
+  DCHECK(ink_drop_ripple_);
+
   highlight_state_->AnimationStarted(ink_drop_state);
   NotifyInkDropAnimationStarted();
 }
diff --git a/ui/views/controls/label_unittest.cc b/ui/views/controls/label_unittest.cc
index 040d4f1..4f23097 100644
--- a/ui/views/controls/label_unittest.cc
+++ b/ui/views/controls/label_unittest.cc
@@ -90,8 +90,8 @@
 
 base::string16 GetClipboardText(ui::ClipboardBuffer clipboard_buffer) {
   base::string16 clipboard_text;
-  ui::Clipboard::GetForCurrentThread()->ReadText(clipboard_buffer,
-                                                 &clipboard_text);
+  ui::Clipboard::GetForCurrentThread()->ReadText(
+      clipboard_buffer, /* data_dst = */ nullptr, &clipboard_text);
   return clipboard_text;
 }
 
diff --git a/ui/views/controls/textfield/textfield.cc b/ui/views/controls/textfield/textfield.cc
index 9c5b4e8..0479effb 100644
--- a/ui/views/controls/textfield/textfield.cc
+++ b/ui/views/controls/textfield/textfield.cc
@@ -1756,7 +1756,7 @@
       return readable && HasSelection();
     case ui::TextEditCommand::PASTE:
       ui::Clipboard::GetForCurrentThread()->ReadText(
-          ui::ClipboardBuffer::kCopyPaste, &result);
+          ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &result);
       return editable && !result.empty();
     case ui::TextEditCommand::SELECT_ALL:
       return !GetText().empty() &&
@@ -1872,7 +1872,8 @@
 base::string16 Textfield::GetSelectionClipboardText() const {
   base::string16 selection_clipboard_text;
   ui::Clipboard::GetForCurrentThread()->ReadText(
-      ui::ClipboardBuffer::kSelection, &selection_clipboard_text);
+      ui::ClipboardBuffer::kSelection, /* data_dst = */ nullptr,
+      &selection_clipboard_text);
   return selection_clipboard_text;
 }
 
diff --git a/ui/views/controls/textfield/textfield_model.cc b/ui/views/controls/textfield/textfield_model.cc
index d3df8334..b7fd268 100644
--- a/ui/views/controls/textfield/textfield_model.cc
+++ b/ui/views/controls/textfield/textfield_model.cc
@@ -621,7 +621,7 @@
 bool TextfieldModel::Paste() {
   base::string16 text;
   ui::Clipboard::GetForCurrentThread()->ReadText(
-      ui::ClipboardBuffer::kCopyPaste, &text);
+      ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr, &text);
   if (text.empty())
     return false;
 
diff --git a/ui/views/controls/textfield/textfield_model_unittest.cc b/ui/views/controls/textfield/textfield_model_unittest.cc
index d9b29c3..41981e1 100644
--- a/ui/views/controls/textfield/textfield_model_unittest.cc
+++ b/ui/views/controls/textfield/textfield_model_unittest.cc
@@ -7,6 +7,7 @@
 #include <stddef.h>
 
 #include <memory>
+#include <string>
 #include <vector>
 
 #include "base/auto_reset.h"
@@ -705,14 +706,16 @@
   // Cut with an empty selection should do nothing.
   model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
   EXPECT_FALSE(model.Cut());
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_text);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &clipboard_text);
   EXPECT_EQ(initial_clipboard_text, clipboard_text);
   EXPECT_STR_EQ("HELLO WORLD", model.text());
   EXPECT_EQ(11U, model.GetCursorPosition());
 
   // Copy with an empty selection should do nothing.
   EXPECT_FALSE(model.Copy());
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_text);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &clipboard_text);
   EXPECT_EQ(initial_clipboard_text, clipboard_text);
   EXPECT_STR_EQ("HELLO WORLD", model.text());
   EXPECT_EQ(11U, model.GetCursorPosition());
@@ -721,7 +724,8 @@
   model.render_text()->SetObscured(true);
   model.SelectAll(false);
   EXPECT_FALSE(model.Cut());
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_text);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &clipboard_text);
   EXPECT_EQ(initial_clipboard_text, clipboard_text);
   EXPECT_STR_EQ("HELLO WORLD", model.text());
   EXPECT_STR_EQ("HELLO WORLD", model.GetSelectedText());
@@ -729,7 +733,8 @@
   // Copy on obscured (password) text should do nothing.
   model.SelectAll(false);
   EXPECT_FALSE(model.Copy());
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_text);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &clipboard_text);
   EXPECT_EQ(initial_clipboard_text, clipboard_text);
   EXPECT_STR_EQ("HELLO WORLD", model.text());
   EXPECT_STR_EQ("HELLO WORLD", model.GetSelectedText());
@@ -739,7 +744,8 @@
   model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
   model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_RETAIN);
   EXPECT_TRUE(model.Cut());
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_text);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &clipboard_text);
   EXPECT_STR_EQ("WORLD", clipboard_text);
   EXPECT_STR_EQ("HELLO ", model.text());
   EXPECT_EQ(6U, model.GetCursorPosition());
@@ -747,7 +753,8 @@
   // Copy with non-empty selection.
   model.SelectAll(false);
   EXPECT_TRUE(model.Copy());
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_text);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &clipboard_text);
   EXPECT_STR_EQ("HELLO ", clipboard_text);
   EXPECT_STR_EQ("HELLO ", model.text());
   EXPECT_EQ(6U, model.GetCursorPosition());
@@ -768,7 +775,8 @@
   model.SetText(base::ASCIIToUTF16("It's time to say goodbye."), 0);
   model.SelectRange({17, 24});
   EXPECT_TRUE(model.Paste());
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_text);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &clipboard_text);
   EXPECT_STR_EQ("HELLO ", clipboard_text);
   EXPECT_STR_EQ("It's time to say HELLO.", model.text());
   EXPECT_EQ(22U, model.GetCursorPosition());
@@ -779,7 +787,8 @@
   ui::Clipboard::GetForCurrentThread()->Clear(ui::ClipboardBuffer::kCopyPaste);
   model.SelectRange({5, 8});
   EXPECT_FALSE(model.Paste());
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_text);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &clipboard_text);
   EXPECT_TRUE(clipboard_text.empty());
   EXPECT_STR_EQ("It's time to say HELLO.", model.text());
   EXPECT_EQ(8U, model.GetCursorPosition());
@@ -802,7 +811,8 @@
   model.SelectRange({0, 5});
   model.SelectRange({13, 17}, false);
   EXPECT_TRUE(model.Cut());
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_text);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &clipboard_text);
   EXPECT_STR_EQ("It's ", clipboard_text);
   EXPECT_STR_EQ("time to HELLO.", model.text());
   EXPECT_EQ(0U, model.GetCursorPosition());
@@ -814,7 +824,8 @@
   model.SelectRange({13, 8});
   model.SelectRange({0, 4}, false);
   EXPECT_TRUE(model.Copy());
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_text);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &clipboard_text);
   EXPECT_STR_EQ("HELLO", clipboard_text);
   EXPECT_STR_EQ("time to HELLO.", model.text());
   EXPECT_EQ(8U, model.GetCursorPosition());
@@ -827,7 +838,8 @@
   model.SelectRange({5, 8}, false);
   model.SelectRange({14, 14}, false);
   EXPECT_TRUE(model.Paste());
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_text);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &clipboard_text);
   EXPECT_STR_EQ("HELLO", clipboard_text);
   EXPECT_STR_EQ("HELLOime HELLO.", model.text());
   EXPECT_EQ(5U, model.GetCursorPosition());
@@ -840,7 +852,8 @@
   model.SelectRange({1, 2});
   model.SelectRange({4, 5}, false);
   EXPECT_FALSE(model.Paste());
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_text);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &clipboard_text);
   EXPECT_TRUE(clipboard_text.empty());
   EXPECT_STR_EQ("HELLOime HELLO.", model.text());
   EXPECT_EQ(2U, model.GetCursorPosition());
@@ -853,7 +866,8 @@
   model.SelectRange({2, 2});
   model.SelectRange({4, 5}, false);
   EXPECT_FALSE(model.Cut());
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_text);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &clipboard_text);
   EXPECT_STR_EQ("initial text", clipboard_text);
   EXPECT_STR_EQ("HELLOime HELLO.", model.text());
   EXPECT_EQ(2U, model.GetCursorPosition());
@@ -862,7 +876,8 @@
   // Copy with an empty primary selection and nonempty secondary selections
   // should not replace the clipboard.
   EXPECT_FALSE(model.Copy());
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_text);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &clipboard_text);
   EXPECT_STR_EQ("initial text", clipboard_text);
   EXPECT_STR_EQ("HELLOime HELLO.", model.text());
   EXPECT_EQ(2U, model.GetCursorPosition());
@@ -872,7 +887,8 @@
   // empty clipboard should change neither the text nor the selections.
   ui::Clipboard::GetForCurrentThread()->Clear(ui::ClipboardBuffer::kCopyPaste);
   EXPECT_FALSE(model.Paste());
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_text);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &clipboard_text);
   EXPECT_TRUE(clipboard_text.empty());
   EXPECT_STR_EQ("HELLOime HELLO.", model.text());
   EXPECT_EQ(2U, model.GetCursorPosition());
@@ -883,7 +899,8 @@
   ui::ScopedClipboardWriter(ui::ClipboardBuffer::kCopyPaste)
       .WriteText(initial_clipboard_text);
   EXPECT_TRUE(model.Paste());
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &clipboard_text);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &clipboard_text);
   EXPECT_STR_EQ("initial text", clipboard_text);
   EXPECT_STR_EQ("HEinitial textLLime HELLO.", model.text());
   EXPECT_EQ(14U, model.GetCursorPosition());
diff --git a/ui/views/controls/textfield/textfield_unittest.cc b/ui/views/controls/textfield/textfield_unittest.cc
index a774fa3..f76f8bc 100644
--- a/ui/views/controls/textfield/textfield_unittest.cc
+++ b/ui/views/controls/textfield/textfield_unittest.cc
@@ -386,7 +386,8 @@
 
 base::string16 GetClipboardText(ui::ClipboardBuffer clipboard_buffer) {
   base::string16 text;
-  ui::Clipboard::GetForCurrentThread()->ReadText(clipboard_buffer, &text);
+  ui::Clipboard::GetForCurrentThread()->ReadText(
+      clipboard_buffer, /* data_dst = */ nullptr, &text);
   return text;
 }
 
diff --git a/ui/views/view_unittest.cc b/ui/views/view_unittest.cc
index 7613c193..4117b104 100644
--- a/ui/views/view_unittest.cc
+++ b/ui/views/view_unittest.cc
@@ -2040,21 +2040,24 @@
   normal->SelectAll(false);
   normal->ExecuteCommand(Textfield::kCut, 0);
   base::string16 result;
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &result);
   EXPECT_EQ(kNormalText, result);
   normal->SetText(kNormalText);  // Let's revert to the original content.
 
   read_only->SelectAll(false);
   read_only->ExecuteCommand(Textfield::kCut, 0);
   result.clear();
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &result);
   // Cut should have failed, so the clipboard content should not have changed.
   EXPECT_EQ(kNormalText, result);
 
   password->SelectAll(false);
   password->ExecuteCommand(Textfield::kCut, 0);
   result.clear();
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &result);
   // Cut should have failed, so the clipboard content should not have changed.
   EXPECT_EQ(kNormalText, result);
 
@@ -2066,19 +2069,22 @@
   read_only->SelectAll(false);
   read_only->ExecuteCommand(Textfield::kCopy, 0);
   result.clear();
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &result);
   EXPECT_EQ(kReadOnlyText, result);
 
   normal->SelectAll(false);
   normal->ExecuteCommand(Textfield::kCopy, 0);
   result.clear();
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &result);
   EXPECT_EQ(kNormalText, result);
 
   password->SelectAll(false);
   password->ExecuteCommand(Textfield::kCopy, 0);
   result.clear();
-  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &result);
+  clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, /* data_dst = */ nullptr,
+                      &result);
   // Text cannot be copied from an obscured field; the clipboard won't change.
   EXPECT_EQ(kNormalText, result);
 
diff --git a/weblayer/browser/android/javatests/skew/expectations.txt b/weblayer/browser/android/javatests/skew/expectations.txt
index fed8bbdf..cdd7c2a 100644
--- a/weblayer/browser/android/javatests/skew/expectations.txt
+++ b/weblayer/browser/android/javatests/skew/expectations.txt
@@ -28,8 +28,6 @@
 # Fixed in https://crrev.com/c/2180022.
 crbug.com/1077243 [ impl_lte_83 ] org.chromium.weblayer.test.FullscreenCallbackTest#testExitFullscreenWhenTabDestroyed [ Skip ]
 
-crbug.com/1079491 [ impl_lte_83 ] org.chromium.weblayer.test.NavigationTest#testSetUserAgentString [ Skip ]
-
 crbug.com/1096570 [ impl_lte_83 ] org.chromium.weblayer.test.ExternalNavigationTest#testExternalIntentWithNoRedirectLaunched [ Skip ]
 
 # -------------------------------------
diff --git a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java
index 098458b..828b48f 100644
--- a/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java
+++ b/weblayer/browser/android/javatests/src/org/chromium/weblayer/test/NavigationTest.java
@@ -735,6 +735,7 @@
 
     @Test
     @SmallTest
+    @MinWebLayerVersion(84)
     public void testSetUserAgentString() throws Exception {
         TestWebServer testServer = TestWebServer.start();
         InstrumentationActivity activity = mActivityTestRule.launchShellWithUrl(null);
diff --git a/weblayer/weblayer_resources.grd b/weblayer/weblayer_resources.grd
index 1dd5006..ded50bb 100644
--- a/weblayer/weblayer_resources.grd
+++ b/weblayer/weblayer_resources.grd
@@ -9,9 +9,9 @@
   <translations />
   <release seq="1">
     <includes>
-      <include name="IDR_WEBLAYER_INTERNALS_HTML" file="browser/resources/weblayer_internals/weblayer_internals.html" flattenhtml="true" allowexternalscript="true" compress="gzip" type="BINDATA" />
-      <include name="IDR_WEBLAYER_INTERNALS_JS" file="browser/resources/weblayer_internals/weblayer_internals.js" flattenhtml="true" compress="gzip" type="BINDATA" />
-      <include name="IDR_WEBLAYER_INTERNALS_MOJO_JS" file="${root_gen_dir}/weblayer/browser/webui/weblayer_internals.mojom-lite.js" use_base_dir="false" type="BINDATA" compress="gzip" />
+      <include name="IDR_WEBLAYER_INTERNALS_HTML" file="browser/resources/weblayer_internals/weblayer_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
+      <include name="IDR_WEBLAYER_INTERNALS_JS" file="browser/resources/weblayer_internals/weblayer_internals.js" flattenhtml="true" type="BINDATA" />
+      <include name="IDR_WEBLAYER_INTERNALS_MOJO_JS" file="${root_gen_dir}/weblayer/browser/webui/weblayer_internals.mojom-lite.js" use_base_dir="false" type="BINDATA" />
     </includes>
   </release>
 </grit>