diff --git a/AUTHORS b/AUTHORS
index 4f13b601..5437b639 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1088,6 +1088,7 @@
 Wojciech Bielawski <wojciech.bielawski@gmail.com>
 Wanming Lin <wanming.lin@intel.com>
 Wei Li <wei.c.li@intel.com>
+Wen Fan <fanwen1@huawei.com>
 Wenxiang Qian <leonwxqian@gmail.com>
 WenSheng He <wensheng.he@samsung.com>
 Wesley Lancel <wesleylancel@gmail.com>
diff --git a/DEPS b/DEPS
index dddde5d..b742ef8 100644
--- a/DEPS
+++ b/DEPS
@@ -199,11 +199,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': 'c8e16bbe32bee288425dc6308f2d55ea3167b1de',
+  'skia_revision': 'ace3f2939f8970c7eb6693c5da0c2ab372c30b87',
   # 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': '81b3d28ad43829f5d3c65e0725a266bb1a8e7340',
+  'v8_revision': '16b9bbbd581c25391981aa03180b76aa60463a3e',
   # 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.
@@ -314,7 +314,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': '7fae6cbf1d370bce5af457ad07f97f290a99cb0d',
+  'dawn_revision': '22eff1eb8c2ff44e1928121d93559fcf0b81f834',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -893,7 +893,7 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '59b0ce20d3e5a64cc0b233ea199f254b136ef7f2',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '9ce03f80a4b507d4b6424c1706069c0d26335b92',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -1266,7 +1266,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '002c03c4b6ed27434ff35dbb31bd8c3288b0ccbd',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '2881d6b22d1eba089a772a15733151b67685cdaf',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1546,7 +1546,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/linux-amd64',
-          'version': '_LOGbVhF_buvk7XI34hbaIYtgbUAkuiM0-VxgWcpwk4C',
+          'version': '1TBlbVMfJAvbrsCVFRL54CvG6OJv660nvwlbVn3QedoC',
         },
       ],
       'dep_type': 'cipd',
@@ -1580,7 +1580,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@767ed2f6b6426300b59e73ba70336ce7bf757607',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@98eb0a70aead159530fe95fb1957dedc677a2eea',
     'condition': 'checkout_src_internal',
   },
 
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index 855c301..f0eb6244 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -968,9 +968,7 @@
 bool AwContentBrowserClient::WillCreateRestrictedCookieManager(
     network::mojom::RestrictedCookieManagerRole role,
     content::BrowserContext* browser_context,
-    const url::Origin& origin,
-    const net::SiteForCookies& site_for_cookies,
-    const url::Origin& top_frame_origin,
+    const net::IsolationInfo& isolation_info,
     bool is_service_worker,
     int process_id,
     int routing_id,
diff --git a/android_webview/browser/aw_content_browser_client.h b/android_webview/browser/aw_content_browser_client.h
index a461116b..dfe839e 100644
--- a/android_webview/browser/aw_content_browser_client.h
+++ b/android_webview/browser/aw_content_browser_client.h
@@ -29,6 +29,10 @@
 class UrlCheckerDelegate;
 }
 
+namespace net {
+class IsolationInfo;
+}
+
 namespace android_webview {
 
 class AwBrowserContext;
@@ -210,9 +214,7 @@
   bool WillCreateRestrictedCookieManager(
       network::mojom::RestrictedCookieManagerRole role,
       content::BrowserContext* browser_context,
-      const url::Origin& origin,
-      const net::SiteForCookies& site_for_cookies,
-      const url::Origin& top_frame_origin,
+      const net::IsolationInfo& isolation_info,
       bool is_service_worker,
       int process_id,
       int routing_id,
diff --git a/ash/BUILD.gn b/ash/BUILD.gn
index 967a755d..cf56d19 100644
--- a/ash/BUILD.gn
+++ b/ash/BUILD.gn
@@ -1969,6 +1969,7 @@
     "ambient/ambient_photo_controller_unittest.cc",
     "ambient/autotest_ambient_api_unittest.cc",
     "ambient/model/ambient_backend_model_unittest.cc",
+    "ambient/ui/ambient_assistant_container_view_unittest.cc",
     "ambient/ui/ambient_container_view_unittest.cc",
     "ambient/ui/media_string_view_unittest.cc",
     "ambient/ui/photo_view_unittest.cc",
diff --git a/ash/ambient/ui/ambient_assistant_container_view.cc b/ash/ambient/ui/ambient_assistant_container_view.cc
index d05bd18..35ff0ca9 100644
--- a/ash/ambient/ui/ambient_assistant_container_view.cc
+++ b/ash/ambient/ui/ambient_assistant_container_view.cc
@@ -24,8 +24,11 @@
 #include "ui/views/background.h"
 #include "ui/views/controls/image_view.h"
 #include "ui/views/controls/label.h"
-#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/flex_layout.h"
+#include "ui/views/layout/flex_layout_types.h"
+#include "ui/views/layout/layout_types.h"
 #include "ui/views/metadata/metadata_impl_macros.h"
+#include "ui/views/view_class_properties.h"
 
 namespace ash {
 
@@ -34,6 +37,8 @@
 // Appearance.
 constexpr int kAvatarImageSizeDip = 32;
 
+constexpr int kAssistantPreferredHeightDip = 128;
+
 // Greeting message.
 base::string16 GetGreetingMessage(const UserSession* user_session) {
   DCHECK(user_session);
@@ -80,25 +85,37 @@
 }
 
 void AmbientAssistantContainerView::InitLayout() {
-  SetPaintToLayer();
-  SetBackground(views::CreateSolidBackground(SK_ColorWHITE));
+  views::FlexLayout* outer_layout =
+      SetLayoutManager(std::make_unique<views::FlexLayout>());
+  outer_layout->SetOrientation(views::LayoutOrientation::kVertical);
+  outer_layout->SetMainAxisAlignment(views::LayoutAlignment::kStart);
+  outer_layout->SetCrossAxisAlignment(views::LayoutAlignment::kStretch);
 
+  auto* container = AddChildView(std::make_unique<views::View>());
+
+  // Set a placeholder value for width. |CrossAxisAlignment::kStretch| will
+  // expand the width to 100% of the parent.
+  container->SetPreferredSize(
+      {/*width=*/1, /*height=*/kAssistantPreferredHeightDip});
+  container->SetPaintToLayer();
+  container->SetBackground(views::CreateSolidBackground(SK_ColorWHITE));
+
+  views::FlexLayout* container_layout =
+      container->SetLayoutManager(std::make_unique<views::FlexLayout>());
   constexpr int kRightPaddingDip = 8;
-  views::BoxLayout* layout_manager =
-      SetLayoutManager(std::make_unique<views::BoxLayout>(
-          views::BoxLayout::Orientation::kHorizontal,
-          gfx::Insets(0, 0, 0, kRightPaddingDip)));
+  container_layout->SetInteriorMargin({0, 0, 0, kRightPaddingDip});
 
-  layout_manager->set_cross_axis_alignment(
-      views::BoxLayout::CrossAxisAlignment::kCenter);
+  container_layout->SetOrientation(views::LayoutOrientation::kHorizontal);
+  container_layout->SetMainAxisAlignment(views::LayoutAlignment::kStart);
+  container_layout->SetCrossAxisAlignment(views::LayoutAlignment::kCenter);
 
   // Mic button and input query view.
-  ambient_assistant_dialog_plate_ =
-      AddChildView(std::make_unique<AmbientAssistantDialogPlate>(delegate_));
+  ambient_assistant_dialog_plate_ = container->AddChildView(
+      std::make_unique<AmbientAssistantDialogPlate>(delegate_));
 
   // Response container view.
-  assistant_response_container_view_ =
-      AddChildView(std::make_unique<AssistantResponseContainerView>(delegate_));
+  assistant_response_container_view_ = container->AddChildView(
+      std::make_unique<AssistantResponseContainerView>(delegate_));
 
   // Greeting label.
   const UserSession* active_user_session =
@@ -106,7 +123,7 @@
   // TODO(meilinw): uses login user info instead as no active user session is
   // available on lock screen.
   if (active_user_session) {
-    greeting_label_ = AddChildView(std::make_unique<views::Label>(
+    greeting_label_ = container->AddChildView(std::make_unique<views::Label>(
         GetGreetingMessage(active_user_session)));
     greeting_label_->SetEnabledColor(kTextColorSecondary);
     greeting_label_->SetFontList(
@@ -118,12 +135,17 @@
   }
 
   // Spacer.
-  views::View* spacer = AddChildView(std::make_unique<views::View>());
-  // Sets the flex weight to be 1 so the spacer view can be resized.
-  layout_manager->SetFlexForView(spacer, 1);
+  views::View* spacer =
+      container->AddChildView(std::make_unique<views::View>());
+  // Allow the spacer to expand to push the avatar image to the end of the
+  // container.
+  spacer->SetProperty(
+      views::kFlexBehaviorKey,
+      views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToZero,
+                               views::MaximumFlexSizeRule::kUnbounded));
 
   // Rounded avatar image view.
-  avatar_view_ = AddChildView(std::make_unique<views::ImageView>());
+  avatar_view_ = container->AddChildView(std::make_unique<views::ImageView>());
   avatar_view_->SetImageSize(
       gfx::Size(kAvatarImageSizeDip, kAvatarImageSizeDip));
   avatar_view_->SetPreferredSize(
diff --git a/ash/ambient/ui/ambient_assistant_container_view_unittest.cc b/ash/ambient/ui/ambient_assistant_container_view_unittest.cc
new file mode 100644
index 0000000..ce2260a
--- /dev/null
+++ b/ash/ambient/ui/ambient_assistant_container_view_unittest.cc
@@ -0,0 +1,66 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ash/ambient/ui/ambient_assistant_container_view.h"
+
+#include "ash/ambient/test/ambient_ash_test_base.h"
+#include "ash/ambient/ui/ambient_container_view.h"
+#include "ash/ambient/ui/ambient_view_ids.h"
+#include "base/test/scoped_feature_list.h"
+#include "chromeos/services/assistant/public/cpp/features.h"
+#include "ui/views/view.h"
+
+namespace ash {
+
+class AmbientAssistantContainerViewTest : public AmbientAshTestBase {
+ public:
+  AmbientAssistantContainerViewTest() : AmbientAshTestBase() {}
+  ~AmbientAssistantContainerViewTest() override = default;
+
+  // AmbientAshTestBase:
+  void SetUp() override {
+    scoped_feature_list_.InitAndEnableFeature(
+        chromeos::assistant::features::kEnableAmbientAssistant);
+    AmbientAshTestBase::SetUp();
+    UpdateDisplay("800x600");
+    ShowAmbientScreen();
+  }
+
+  void TearDown() override {
+    CloseAmbientScreen();
+    AmbientAshTestBase::TearDown();
+  }
+
+  AmbientAssistantContainerView* GetAmbientAssistantContainerView() {
+    return static_cast<AmbientAssistantContainerView*>(
+        GetContainerView()->GetViewByID(
+            AmbientViewID::kAmbientAssistantContainerView));
+  }
+
+  views::View* GetInnerContainer() {
+    const auto& children = GetAmbientAssistantContainerView()->children();
+    EXPECT_EQ(children.size(), 1u);
+    return children.front();
+  }
+
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+TEST_F(AmbientAssistantContainerViewTest, LayoutAmbientContainerView) {
+  GetAmbientAssistantContainerView()->SetVisible(true);
+
+  auto* inner_container = GetInnerContainer();
+
+  // Should be 100% width and fixed height.
+  EXPECT_EQ(inner_container->GetBoundsInScreen(),
+            gfx::Rect(/*x=*/0, /*y=*/0, /*width=*/800, /*height=*/128));
+
+  UpdateDisplay("1920x1080");
+
+  // Should expand to still be 100% width.
+  EXPECT_EQ(inner_container->GetBoundsInScreen(),
+            gfx::Rect(/*x=*/0, /*y=*/0, /*width=*/1920, /*height=*/128));
+}
+
+}  // namespace ash
diff --git a/ash/ambient/ui/ambient_container_view.cc b/ash/ambient/ui/ambient_container_view.cc
index 6e80f17..fc058a8 100644
--- a/ash/ambient/ui/ambient_container_view.cc
+++ b/ash/ambient/ui/ambient_container_view.cc
@@ -17,6 +17,7 @@
 #include "chromeos/services/assistant/public/cpp/features.h"
 #include "ui/aura/window.h"
 #include "ui/views/background.h"
+#include "ui/views/layout/fill_layout.h"
 #include "ui/views/metadata/metadata_impl_macros.h"
 #include "ui/views/view.h"
 #include "ui/views/widget/widget.h"
@@ -27,9 +28,6 @@
 
 using chromeos::assistant::features::IsAmbientAssistantEnabled;
 
-// Appearance.
-constexpr int kAssistantPreferredHeightDip = 128;
-
 }  // namespace
 
 AmbientContainerView::AmbientContainerView(AmbientViewDelegate* delegate)
@@ -40,28 +38,12 @@
 
 AmbientContainerView::~AmbientContainerView() = default;
 
-gfx::Size AmbientContainerView::CalculatePreferredSize() const {
-  // TODO(b/139953389): Handle multiple displays.
-  return GetWidget()->GetNativeWindow()->GetRootWindow()->bounds().size();
-}
-
-void AmbientContainerView::Layout() {
-  // Layout child views first to have proper bounds set for children.
-  LayoutPhotoView();
-
-  // The assistant view may not exist if |kAmbientAssistant| feature is
-  // disabled.
-  if (ambient_assistant_container_view_)
-    LayoutAssistantView();
-
-  View::Layout();
-}
-
 void AmbientContainerView::Init() {
   // TODO(b/139954108): Choose a better dark mode theme color.
   SetBackground(views::CreateSolidBackground(SK_ColorBLACK));
   // Updates focus behavior to receive key press events.
   SetFocusBehavior(views::View::FocusBehavior::ALWAYS);
+  SetLayoutManager(std::make_unique<views::FillLayout>());
 
   photo_view_ = AddChildView(std::make_unique<PhotoView>(delegate_));
 
@@ -72,18 +54,6 @@
   }
 }
 
-void AmbientContainerView::LayoutPhotoView() {
-  // |photo_view_| should have the same size as the widget.
-  photo_view_->SetBoundsRect(GetLocalBounds());
-}
-
-void AmbientContainerView::LayoutAssistantView() {
-  int preferred_width = GetPreferredSize().width();
-  int preferred_height = kAssistantPreferredHeightDip;
-  ambient_assistant_container_view_->SetBoundsRect(
-      gfx::Rect(0, 0, preferred_width, preferred_height));
-}
-
 BEGIN_METADATA(AmbientContainerView, views::View)
 END_METADATA
 
diff --git a/ash/ambient/ui/ambient_container_view.h b/ash/ambient/ui/ambient_container_view.h
index 8748190..e51d4e1 100644
--- a/ash/ambient/ui/ambient_container_view.h
+++ b/ash/ambient/ui/ambient_container_view.h
@@ -26,26 +26,16 @@
   explicit AmbientContainerView(AmbientViewDelegate* delegate);
   ~AmbientContainerView() override;
 
-  gfx::Size CalculatePreferredSize() const override;
-  void Layout() override;
-
  private:
   friend class AmbientAshTestBase;
 
   void Init();
 
-  // Layouts its child views.
-  // TODO(meilinw): Use LayoutManagers to lay out children instead of overriding
-  // Layout(). See b/163170162.
-  void LayoutPhotoView();
-  void LayoutAssistantView();
-
   AmbientViewDelegate* delegate_ = nullptr;
 
   // Owned by view hierarchy.
   PhotoView* photo_view_ = nullptr;
   AmbientAssistantContainerView* ambient_assistant_container_view_ = nullptr;
-
 };
 
 }  // namespace ash
diff --git a/ash/app_list/views/search_box_view.cc b/ash/app_list/views/search_box_view.cc
index 4dcbcd8b..c96ef7c 100644
--- a/ash/app_list/views/search_box_view.cc
+++ b/ash/app_list/views/search_box_view.cc
@@ -219,6 +219,13 @@
   return "SearchBoxView";
 }
 
+void SearchBoxView::OnThemeChanged() {
+  views::View::OnThemeChanged();
+  SetupAssistantButton();
+  SetupCloseButton();
+  OnWallpaperColorsChanged();
+}
+
 // static
 int SearchBoxView::GetFocusRingSpacing() {
   return kSearchBoxFocusRingWidth + kSearchBoxFocusRingPadding;
diff --git a/ash/app_list/views/search_box_view.h b/ash/app_list/views/search_box_view.h
index d202ca6f..98ab7ef1d 100644
--- a/ash/app_list/views/search_box_view.h
+++ b/ash/app_list/views/search_box_view.h
@@ -68,6 +68,7 @@
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   void OnPaintBackground(gfx::Canvas* canvas) override;
   const char* GetClassName() const override;
+  void OnThemeChanged() override;
 
   // Updates the search box's background corner radius and color based on the
   // state of AppListModel.
diff --git a/ash/app_list/views/search_result_suggestion_chip_view.cc b/ash/app_list/views/search_result_suggestion_chip_view.cc
index 055495b..76e1b84 100644
--- a/ash/app_list/views/search_result_suggestion_chip_view.cc
+++ b/ash/app_list/views/search_result_suggestion_chip_view.cc
@@ -145,6 +145,13 @@
   return Button::OnKeyPressed(event);
 }
 
+void SearchResultSuggestionChipView::OnThemeChanged() {
+  views::View::OnThemeChanged();
+  text_view_->SetEnabledColor(
+      AppListColorProvider::Get()->GetSuggestionChipTextColor());
+  SchedulePaint();
+}
+
 std::unique_ptr<views::InkDrop>
 SearchResultSuggestionChipView::CreateInkDrop() {
   std::unique_ptr<views::InkDropImpl> ink_drop =
diff --git a/ash/app_list/views/search_result_suggestion_chip_view.h b/ash/app_list/views/search_result_suggestion_chip_view.h
index 5f3eba4..80ff776 100644
--- a/ash/app_list/views/search_result_suggestion_chip_view.h
+++ b/ash/app_list/views/search_result_suggestion_chip_view.h
@@ -49,6 +49,7 @@
   void OnFocus() override;
   void OnBlur() override;
   bool OnKeyPressed(const ui::KeyEvent& event) override;
+  void OnThemeChanged() override;
 
   // views::InkDropHost:
   std::unique_ptr<views::InkDrop> CreateInkDrop() override;
diff --git a/ash/clipboard/clipboard_history_controller_impl.cc b/ash/clipboard/clipboard_history_controller_impl.cc
index 4c29f6b..1dd5ab9 100644
--- a/ash/clipboard/clipboard_history_controller_impl.cc
+++ b/ash/clipboard/clipboard_history_controller_impl.cc
@@ -70,19 +70,6 @@
   return false;
 }
 
-void SendSyntheticKeyEvent(ui::KeyboardCode key_code, int flags) {
-  ui::KeyEvent key_pressed(/*type=*/ui::ET_KEY_PRESSED, key_code,
-                           /*code=*/static_cast<ui::DomCode>(0), flags);
-  auto* host = GetWindowTreeHostForDisplay(
-      display::Screen::GetScreen()->GetDisplayForNewWindows().id());
-  DCHECK(host);
-  host->DeliverEventToSink(&key_pressed);
-
-  ui::KeyEvent key_released(/*type=*/ui::ET_KEY_RELEASED, key_code,
-                            /*code=*/static_cast<ui::DomCode>(0), flags);
-  host->DeliverEventToSink(&key_released);
-}
-
 }  // namespace
 
 // ClipboardHistoryControllerImpl::AcceleratorTarget ---------------------------
@@ -496,7 +483,28 @@
     original_data = clipboard->WriteClipboardData(std::move(temp_data));
   }
 
-  SendSyntheticKeyEvent(ui::VKEY_V, ui::EF_CONTROL_DOWN);
+  ui::KeyEvent control_press(/*type=*/ui::ET_KEY_PRESSED, ui::VKEY_CONTROL,
+                             /*code=*/static_cast<ui::DomCode>(0), /*flags=*/0);
+  auto* host = GetWindowTreeHostForDisplay(
+      display::Screen::GetScreen()->GetDisplayForNewWindows().id());
+  DCHECK(host);
+  host->DeliverEventToSink(&control_press);
+
+  ui::KeyEvent v_press(/*type=*/ui::ET_KEY_PRESSED, ui::VKEY_V,
+                       /*code=*/static_cast<ui::DomCode>(0),
+                       /*flags=*/ui::EF_CONTROL_DOWN);
+
+  host->DeliverEventToSink(&v_press);
+
+  ui::KeyEvent v_release(/*type=*/ui::ET_KEY_RELEASED, ui::VKEY_V,
+                         /*code=*/static_cast<ui::DomCode>(0),
+                         /*flags=*/ui::EF_CONTROL_DOWN);
+  host->DeliverEventToSink(&v_release);
+
+  ui::KeyEvent control_release(/*type=*/ui::ET_KEY_RELEASED, ui::VKEY_CONTROL,
+                               /*code=*/static_cast<ui::DomCode>(0),
+                               /*flags=*/0);
+  host->DeliverEventToSink(&control_release);
 
   for (auto& observer : observers_)
     observer.OnClipboardHistoryPasted();
diff --git a/ash/public/cpp/ash_features.cc b/ash/public/cpp/ash_features.cc
index 7dc4fd3..d1f173d 100644
--- a/ash/public/cpp/ash_features.cc
+++ b/ash/public/cpp/ash_features.cc
@@ -187,8 +187,7 @@
 }
 
 bool IsHideArcMediaNotificationsEnabled() {
-  return base::FeatureList::IsEnabled(kMediaSessionNotification) &&
-         base::FeatureList::IsEnabled(kHideArcMediaNotifications);
+  return base::FeatureList::IsEnabled(kHideArcMediaNotifications);
 }
 
 bool IsKeyboardBasedDisplayArrangementInSettingsEnabled() {
diff --git a/ash/public/cpp/toast_manager.h b/ash/public/cpp/toast_manager.h
index 6400cf6b..6f543119 100644
--- a/ash/public/cpp/toast_manager.h
+++ b/ash/public/cpp/toast_manager.h
@@ -5,6 +5,8 @@
 #ifndef ASH_PUBLIC_CPP_TOAST_MANAGER_H_
 #define ASH_PUBLIC_CPP_TOAST_MANAGER_H_
 
+#include <string>
+
 #include "ash/public/cpp/ash_public_export.h"
 
 namespace ash {
@@ -20,6 +22,9 @@
   // well, and are shown one by one.
   virtual void Show(const ToastData& data) = 0;
 
+  // Cancels a toast with the provided ID.
+  virtual void Cancel(const std::string& id) = 0;
+
  protected:
   ToastManager();
   virtual ~ToastManager();
diff --git a/ash/shelf/assistant_overlay.cc b/ash/shelf/assistant_overlay.cc
index 6f609fb..a235af5 100644
--- a/ash/shelf/assistant_overlay.cc
+++ b/ash/shelf/assistant_overlay.cc
@@ -207,4 +207,10 @@
   return "AssistantOverlay";
 }
 
+void AssistantOverlay::OnThemeChanged() {
+  views::View::OnThemeChanged();
+  circle_layer_delegate_.set_color(
+      AshColorProvider::Get()->GetRippleAttributes().base_color);
+  SchedulePaint();
+}
 }  // namespace ash
diff --git a/ash/shelf/assistant_overlay.h b/ash/shelf/assistant_overlay.h
index f244b92..3880ed9 100644
--- a/ash/shelf/assistant_overlay.h
+++ b/ash/shelf/assistant_overlay.h
@@ -33,6 +33,7 @@
 
   // views::View:
   const char* GetClassName() const override;
+  void OnThemeChanged() override;
 
  private:
   enum class AnimationState {
diff --git a/ash/shelf/back_button.cc b/ash/shelf/back_button.cc
index cf0e6de..245fefa 100644
--- a/ash/shelf/back_button.cc
+++ b/ash/shelf/back_button.cc
@@ -90,4 +90,9 @@
       GetWidget()->GetNativeWindow()->GetRootWindow());
 }
 
+void BackButton::OnThemeChanged() {
+  ShelfControlButton::OnThemeChanged();
+  SchedulePaint();
+}
+
 }  // namespace ash
diff --git a/ash/shelf/back_button.h b/ash/shelf/back_button.h
index 71489d2c..e3d755ed6 100644
--- a/ash/shelf/back_button.h
+++ b/ash/shelf/back_button.h
@@ -36,6 +36,9 @@
   const char* GetClassName() const override;
   base::string16 GetTooltipText(const gfx::Point& p) const override;
 
+  // views::View:
+  void OnThemeChanged() override;
+
   // ShelfButtonDelegate:
   void OnShelfButtonAboutToRequestFocusFromTabTraversal(ShelfButton* button,
                                                         bool reverse) override;
diff --git a/ash/shelf/drag_handle.cc b/ash/shelf/drag_handle.cc
index 6a6940b..3ee8d33 100644
--- a/ash/shelf/drag_handle.cc
+++ b/ash/shelf/drag_handle.cc
@@ -293,6 +293,11 @@
   node_data->SetName(accessible_name);
 }
 
+void DragHandle::OnThemeChanged() {
+  views::Button::OnThemeChanged();
+  UpdateColor();
+}
+
 void DragHandle::OnOverviewModeStarting() {
   StopDragHandleNudgeShowTimer();
 }
diff --git a/ash/shelf/drag_handle.h b/ash/shelf/drag_handle.h
index 3df75a5..bd1c381 100644
--- a/ash/shelf/drag_handle.h
+++ b/ash/shelf/drag_handle.h
@@ -70,6 +70,7 @@
   void OnGestureEvent(ui::GestureEvent* event) override;
   gfx::Rect GetAnchorBoundsInScreen() const override;
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
+  void OnThemeChanged() override;
 
   // OverviewObserver:
   void OnOverviewModeStarting() override;
diff --git a/ash/shelf/home_button.cc b/ash/shelf/home_button.cc
index fff5731..b75fed3 100644
--- a/ash/shelf/home_button.cc
+++ b/ash/shelf/home_button.cc
@@ -170,6 +170,11 @@
   }
 }
 
+void HomeButton::OnThemeChanged() {
+  ShelfControlButton::OnThemeChanged();
+  SchedulePaint();
+}
+
 bool HomeButton::DoesIntersectRect(const views::View* target,
                                    const gfx::Rect& rect) const {
   DCHECK_EQ(target, this);
diff --git a/ash/shelf/home_button.h b/ash/shelf/home_button.h
index 89ac77cc..9d3323d 100644
--- a/ash/shelf/home_button.h
+++ b/ash/shelf/home_button.h
@@ -64,6 +64,7 @@
  protected:
   // views::Button:
   void PaintButtonContents(gfx::Canvas* canvas) override;
+  void OnThemeChanged() override;
 
  private:
   // views::ViewTargeterDelegate:
diff --git a/ash/shelf/scroll_arrow_view.cc b/ash/shelf/scroll_arrow_view.cc
index 4559792..fe12144 100644
--- a/ash/shelf/scroll_arrow_view.cc
+++ b/ash/shelf/scroll_arrow_view.cc
@@ -56,4 +56,9 @@
   return "ScrollArrowView";
 }
 
+void ScrollArrowView::OnThemeChanged() {
+  ShelfButton::OnThemeChanged();
+  SchedulePaint();
+}
+
 }  // namespace ash
diff --git a/ash/shelf/scroll_arrow_view.h b/ash/shelf/scroll_arrow_view.h
index 2ac7c3c..cc52c71 100644
--- a/ash/shelf/scroll_arrow_view.h
+++ b/ash/shelf/scroll_arrow_view.h
@@ -31,6 +31,7 @@
   // views::View:
   void PaintButtonContents(gfx::Canvas* canvas) override;
   const char* GetClassName() const override;
+  void OnThemeChanged() override;
 
  private:
   ArrowType arrow_type_ = kLeft;
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc
index 173f53f..2d7c8e9 100644
--- a/ash/shelf/shelf_view.cc
+++ b/ash/shelf/shelf_view.cc
@@ -643,6 +643,14 @@
   return "ShelfView";
 }
 
+void ShelfView::OnThemeChanged() {
+  views::AccessiblePaneView::OnThemeChanged();
+  if (!separator_)
+    return;
+  separator_->SetColor(AshColorProvider::Get()->GetContentLayerColor(
+      AshColorProvider::ContentLayerType::kSeparatorColor));
+}
+
 void ShelfView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
   node_data->role = ax::mojom::Role::kToolbar;
   node_data->SetName(l10n_util::GetStringUTF8(IDS_ASH_SHELF_ACCESSIBLE_NAME));
diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h
index c3f716c..2b55e3e 100644
--- a/ash/shelf/shelf_view.h
+++ b/ash/shelf/shelf_view.h
@@ -140,6 +140,7 @@
   bool OnKeyPressed(const ui::KeyEvent& event) override;
   void OnMouseEvent(ui::MouseEvent* event) override;
   const char* GetClassName() const override;
+  void OnThemeChanged() override;
 
   void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
   View* GetTooltipHandlerForPoint(const gfx::Point& point) override;
diff --git a/ash/shelf/shelf_widget.cc b/ash/shelf/shelf_widget.cc
index fc14a5fd..f00a33e 100644
--- a/ash/shelf/shelf_widget.cc
+++ b/ash/shelf/shelf_widget.cc
@@ -133,6 +133,9 @@
   views::Widget* GetWidget() override { return View::GetWidget(); }
   const views::Widget* GetWidget() const override { return View::GetWidget(); }
 
+  // views::View:
+  void OnThemeChanged() override;
+
   bool CanActivate() const override;
   void ReorderChildLayers(ui::Layer* parent_layer) override;
   void OnWidgetInitialized() override;
@@ -262,6 +265,13 @@
   UpdateBackgroundBlur();
 }
 
+void ShelfWidget::DelegateView::OnThemeChanged() {
+  views::AccessiblePaneView::OnThemeChanged();
+  shelf_widget_->background_animator_.PaintBackground(
+      shelf_widget_->shelf_layout_manager()->GetShelfBackgroundType(),
+      AnimationChangeType::IMMEDIATE);
+}
+
 bool ShelfWidget::DelegateView::CanActivate() const {
   // This widget only contains anything interesting to activate in login/lock
   // screen mode. Only allow activation from the focus cycler, not from mouse
diff --git a/ash/system/audio/unified_volume_slider_controller.cc b/ash/system/audio/unified_volume_slider_controller.cc
index a77bb8fd..11ea48f 100644
--- a/ash/system/audio/unified_volume_slider_controller.cc
+++ b/ash/system/audio/unified_volume_slider_controller.cc
@@ -17,15 +17,16 @@
 namespace ash {
 
 UnifiedVolumeSliderController::UnifiedVolumeSliderController(
-    UnifiedVolumeSliderController::Delegate* delegate)
-    : delegate_(delegate) {
+    UnifiedVolumeSliderController::Delegate* delegate,
+    bool in_bubble)
+    : delegate_(delegate), in_bubble_(in_bubble) {
   DCHECK(delegate);
 }
 
 UnifiedVolumeSliderController::~UnifiedVolumeSliderController() = default;
 
 views::View* UnifiedVolumeSliderController::CreateView() {
-  return new UnifiedVolumeView(this, delegate_);
+  return new UnifiedVolumeView(this, delegate_, in_bubble_);
 }
 
 void UnifiedVolumeSliderController::SliderValueChanged(
diff --git a/ash/system/audio/unified_volume_slider_controller.h b/ash/system/audio/unified_volume_slider_controller.h
index b531b55..3bdc28f 100644
--- a/ash/system/audio/unified_volume_slider_controller.h
+++ b/ash/system/audio/unified_volume_slider_controller.h
@@ -18,7 +18,7 @@
     virtual void OnAudioSettingsButtonClicked() = 0;
   };
 
-  explicit UnifiedVolumeSliderController(Delegate* delegate);
+  UnifiedVolumeSliderController(Delegate* delegate, bool in_bubble);
   ~UnifiedVolumeSliderController() override;
 
   // UnifiedSliderListener:
@@ -33,6 +33,9 @@
  private:
   Delegate* const delegate_;
 
+  // Whether the volume slider is in the bubble, as opposed to the system tray.
+  const bool in_bubble_;
+
   DISALLOW_COPY_AND_ASSIGN(UnifiedVolumeSliderController);
 };
 
diff --git a/ash/system/audio/unified_volume_view.cc b/ash/system/audio/unified_volume_view.cc
index 74641e3..be4bcba 100644
--- a/ash/system/audio/unified_volume_view.cc
+++ b/ash/system/audio/unified_volume_view.cc
@@ -228,13 +228,15 @@
 
 UnifiedVolumeView::UnifiedVolumeView(
     UnifiedVolumeSliderController* controller,
-    UnifiedVolumeSliderController::Delegate* delegate)
+    UnifiedVolumeSliderController::Delegate* delegate,
+    bool in_bubble)
     : UnifiedSliderView(base::BindRepeating(
                             &UnifiedVolumeSliderController::SliderButtonPressed,
                             base::Unretained(controller)),
                         controller,
                         kSystemMenuVolumeHighIcon,
                         IDS_ASH_STATUS_TRAY_VOLUME_SLIDER_LABEL),
+      in_bubble_(in_bubble),
       live_caption_button_(new LiveCaptionButton(
           base::BindRepeating(&UnifiedVolumeView::OnLiveCaptionButtonPressed,
                               base::Unretained(this)))),
@@ -277,7 +279,8 @@
       IDS_ASH_STATUS_TRAY_VOLUME, state_tooltip_text));
 
   live_caption_button_->SetVisible(
-      base::FeatureList::IsEnabled(media::kLiveCaption));
+      in_bubble_ &&
+      base::FeatureList::IsEnabled(media::kLiveCaptionSystemWideOnChromeOS));
   live_caption_button_->SetToggled(
       Shell::Get()->session_controller()->GetActivePrefService()->GetBoolean(
           prefs::kLiveCaptionEnabled));
diff --git a/ash/system/audio/unified_volume_view.h b/ash/system/audio/unified_volume_view.h
index 5ca0fed5..eebc4ed 100644
--- a/ash/system/audio/unified_volume_view.h
+++ b/ash/system/audio/unified_volume_view.h
@@ -16,7 +16,8 @@
                           public chromeos::CrasAudioHandler::AudioObserver {
  public:
   UnifiedVolumeView(UnifiedVolumeSliderController* controller,
-                    UnifiedVolumeSliderController::Delegate* delegate);
+                    UnifiedVolumeSliderController::Delegate* delegate,
+                    bool in_bubble);
   ~UnifiedVolumeView() override;
 
   // views::View:
@@ -38,6 +39,9 @@
   // views::Button::PressedCallback
   void OnLiveCaptionButtonPressed();
 
+  // Whether the volume slider is in the bubble, as opposed to the system tray.
+  const bool in_bubble_;
+
   views::ToggleImageButton* const live_caption_button_;
   views::Button* const more_button_;
 
diff --git a/ash/system/toast/toast_manager_impl.h b/ash/system/toast/toast_manager_impl.h
index 3b01992..e5f0335d 100644
--- a/ash/system/toast/toast_manager_impl.h
+++ b/ash/system/toast/toast_manager_impl.h
@@ -28,8 +28,7 @@
 
   // ToastManager overrides:
   void Show(const ToastData& data) override;
-
-  void Cancel(const std::string& id);
+  void Cancel(const std::string& id) override;
 
   // ToastOverlay::Delegate overrides:
   void OnClosed() override;
diff --git a/ash/system/unified/unified_slider_bubble_controller.cc b/ash/system/unified/unified_slider_bubble_controller.cc
index 2a0b680..aab6715 100644
--- a/ash/system/unified/unified_slider_bubble_controller.cc
+++ b/ash/system/unified/unified_slider_bubble_controller.cc
@@ -204,8 +204,8 @@
 void UnifiedSliderBubbleController::CreateSliderController() {
   switch (slider_type_) {
     case SLIDER_TYPE_VOLUME:
-      slider_controller_ =
-          std::make_unique<UnifiedVolumeSliderController>(this);
+      slider_controller_ = std::make_unique<UnifiedVolumeSliderController>(
+          this, true /* in_bubble */);
       return;
     case SLIDER_TYPE_DISPLAY_BRIGHTNESS:
       slider_controller_ =
diff --git a/ash/system/unified/unified_system_tray_controller.cc b/ash/system/unified/unified_system_tray_controller.cc
index c15bfed..068141c 100644
--- a/ash/system/unified/unified_system_tray_controller.cc
+++ b/ash/system/unified/unified_system_tray_controller.cc
@@ -128,8 +128,8 @@
         media_controls_controller_->CreateView());
   }
 
-  volume_slider_controller_ =
-      std::make_unique<UnifiedVolumeSliderController>(this);
+  volume_slider_controller_ = std::make_unique<UnifiedVolumeSliderController>(
+      this, false /* in_bubble */);
   unified_view_->AddSliderView(volume_slider_controller_->CreateView());
 
   brightness_slider_controller_ =
diff --git a/build/android/gyp/bundletool.py b/build/android/gyp/bundletool.py
index 695d3cd..e161c66 100755
--- a/build/android/gyp/bundletool.py
+++ b/build/android/gyp/bundletool.py
@@ -25,7 +25,7 @@
     BUNDLETOOL_DIR, 'bundletool-all-%s.jar' % BUNDLETOOL_VERSION)
 
 
-def RunBundleTool(args, warnings_as_errors=()):
+def RunBundleTool(args, warnings_as_errors=(), print_stdout=False):
   # Use () instead of None because command-line flags are None by default.
   verify = warnings_as_errors == () or warnings_as_errors
   # ASAN builds failed with the default of 1GB (crbug.com/1120202).
@@ -36,10 +36,11 @@
   logging.debug(' '.join(cmd))
   return build_utils.CheckOutput(
       cmd,
+      print_stdout=print_stdout,
       print_stderr=True,
       fail_on_output=False,
       stderr_filter=build_utils.FilterReflectiveAccessJavaWarnings)
 
 
 if __name__ == '__main__':
-  RunBundleTool(sys.argv[1:])
+  RunBundleTool(sys.argv[1:], print_stdout=True)
diff --git a/cc/input/threaded_input_handler.cc b/cc/input/threaded_input_handler.cc
index 3ff2adb..cd33cfe 100644
--- a/cc/input/threaded_input_handler.cc
+++ b/cc/input/threaded_input_handler.cc
@@ -1842,7 +1842,6 @@
                                                   ui::ScrollInputType type) {
   ScrollTree& scroll_tree = GetScrollTree();
   ScrollNode* scroll_node = nullptr;
-  ScrollNode* first_scrollable_node = nullptr;
   for (ScrollNode* cur_node = starting_node; cur_node;
        cur_node = scroll_tree.parent(cur_node)) {
     if (GetViewport().ShouldScroll(*cur_node)) {
@@ -1856,11 +1855,10 @@
     if (!cur_node->scrollable)
       continue;
 
-    if (!first_scrollable_node) {
-      first_scrollable_node = cur_node;
-    }
-
-    if (CanConsumeDelta(*scroll_state, *cur_node)) {
+    // For UX reasons, autoscrolling should always latch to the top-most
+    // scroller, even if it can't scroll in the initial direction.
+    if (type == ui::ScrollInputType::kAutoscroll ||
+        CanConsumeDelta(*scroll_state, *cur_node)) {
       scroll_node = cur_node;
       break;
     }
@@ -1882,13 +1880,6 @@
     }
   }
 
-  // If the root scroller can not consume delta in an autoscroll, latch on
-  // to the top most autoscrollable scroller. See https://crbug.com/969150
-  if ((type == ui::ScrollInputType::kAutoscroll) && first_scrollable_node &&
-      !CanConsumeDelta(*scroll_state, *scroll_node)) {
-    scroll_node = first_scrollable_node;
-  }
-
   return scroll_node;
 }
 
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 29bcf4e5..42a0abb 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -1352,13 +1352,15 @@
   if (raster_contents_scale_ < MinimumContentsScale())
     return true;
 
-  // Don't change the raster scale if any of the following are true:
-  //  - We have an animating transform.
-  //  - The raster scale is already ideal.
-  if (draw_properties().screen_space_transform_is_animating ||
-      raster_source_scale_ == ideal_source_scale_) {
+  // Don't change the raster scale if we have an animating transform, except
+  // when the device viewport rect has changed because the raster scale may
+  // depend on the rect.
+  if (draw_properties().screen_space_transform_is_animating)
+    return layer_tree_impl()->device_viewport_rect_changed();
+
+  // Don't change the raster scale if the raster scale is already ideal.
+  if (raster_source_scale_ == ideal_source_scale_)
     return false;
-  }
 
   // Don't update will-change: transform layers if the raster contents scale is
   // bigger than the minimum scale.
@@ -1496,12 +1498,6 @@
     float preserved_raster_contents_scale) {
   DCHECK(draw_properties().screen_space_transform_is_animating);
 
-  // We will cap the adjusted scale with the viewport area, which is impossible
-  // if the viewport is empty.
-  gfx::Size viewport = layer_tree_impl()->GetDeviceViewport().size();
-  if (viewport.IsEmpty())
-    return;
-
   CombinedAnimationScale animation_scales =
       layer_tree_impl()->property_trees()->GetAnimationScales(
           transform_tree_index(), layer_tree_impl());
@@ -1520,7 +1516,11 @@
 
   // However we want to avoid excessive memory use. Choose a scale at which this
   // layer's rastered content is not larger than the viewport.
-  float max_viewport_dimension = std::max(viewport.width(), viewport.height());
+  gfx::Size viewport = layer_tree_impl()->GetDeviceViewport().size();
+  // To avoid too small scale in a small viewport.
+  constexpr int kMinViewportDimension = 500;
+  float max_viewport_dimension =
+      std::max({viewport.width(), viewport.height(), kMinViewportDimension});
   DCHECK(max_viewport_dimension);
   // Use square to compensate for viewports with different aspect ratios.
   float squared_viewport_area = max_viewport_dimension * max_viewport_dimension;
diff --git a/cc/layers/picture_layer_impl_unittest.cc b/cc/layers/picture_layer_impl_unittest.cc
index 211dcbb..5df101f 100644
--- a/cc/layers/picture_layer_impl_unittest.cc
+++ b/cc/layers/picture_layer_impl_unittest.cc
@@ -2981,6 +2981,47 @@
                  page_scale * device_scale);
 }
 
+TEST_F(LegacySWPictureLayerImplTest, ViewportSizeChangeDuringAnimation) {
+  gfx::Size layer_bounds(100, 100);
+  SetupDefaultTrees(layer_bounds);
+
+  host_impl()->pending_tree()->SetDeviceViewportRect(gfx::Rect());
+
+  float contents_scale = 1.f;
+  float device_scale = 1.f;
+  float page_scale = 1.f;
+  float maximum_animation_scale = 1.f;
+  float starting_animation_scale = kNotScaled;
+  bool animating_transform = false;
+
+  EXPECT_EQ(pending_layer()->HighResTiling()->contents_scale_key(), 1.f);
+
+  animating_transform = true;
+  maximum_animation_scale = 20.f;
+
+  // Starting an animation should cause tiling resolution to get set to the
+  // maximum animation scale factor, clamped by the viewport size (using default
+  // minimum 500x500 as the viewport is empty for now).
+  SetupDrawPropertiesAndUpdateTiles(
+      pending_layer(), contents_scale, device_scale, page_scale,
+      maximum_animation_scale, starting_animation_scale, animating_transform);
+  EXPECT_EQ(pending_layer()->HighResTiling()->contents_scale_key(), 5.f);
+
+  // Setting viewport rect smaller than the minimum won't change raster scale.
+  host_impl()->pending_tree()->SetDeviceViewportRect(gfx::Rect(400, 400));
+  SetupDrawPropertiesAndUpdateTiles(
+      pending_layer(), contents_scale, device_scale, page_scale,
+      maximum_animation_scale, starting_animation_scale, animating_transform);
+  EXPECT_EQ(pending_layer()->HighResTiling()->contents_scale_key(), 5.f);
+
+  // For a larger viewport size, the clamped scale is also larger.
+  host_impl()->pending_tree()->SetDeviceViewportRect(gfx::Rect(1000, 200));
+  SetupDrawPropertiesAndUpdateTiles(
+      pending_layer(), contents_scale, device_scale, page_scale,
+      maximum_animation_scale, starting_animation_scale, animating_transform);
+  EXPECT_EQ(pending_layer()->HighResTiling()->contents_scale_key(), 10.f);
+}
+
 TEST_F(LegacySWPictureLayerImplTest,
        AnimationTilingChangesWithWillChangeTransformHint) {
   gfx::Size viewport_size(1000, 1000);
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index 8ee6279..3988b82 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -2481,8 +2481,7 @@
 
   frame_rate_estimator_.WillDraw(CurrentBeginFrameArgs().frame_time);
 
-  if (settings_.force_preferred_interval_for_video ||
-      enable_frame_rate_throttling_) {
+  if (enable_frame_rate_throttling_) {
     metadata.preferred_frame_interval = viz::BeginFrameArgs::MaxInterval();
   } else {
     metadata.preferred_frame_interval =
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index b4e84cf..efee266f 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -1194,6 +1194,7 @@
   if (device_viewport_rect == device_viewport_rect_)
     return;
   device_viewport_rect_ = device_viewport_rect;
+  device_viewport_rect_changed_ = true;
 
   set_needs_update_draw_properties();
   if (!IsActiveTree())
@@ -1450,6 +1451,8 @@
     image_animation_controller()->UpdateStateFromDrivers();
   }
 
+  device_viewport_rect_changed_ = false;
+
   DCHECK(!needs_update_draw_properties_)
       << "CalcDrawProperties should not set_needs_update_draw_properties()";
   return true;
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index b1638ab1..99fdce1 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -745,6 +745,10 @@
     return events_metrics_from_main_thread_.size();
   }
 
+  bool device_viewport_rect_changed() const {
+    return device_viewport_rect_changed_;
+  }
+
  protected:
   float ClampPageScaleFactorToLimits(float page_scale_factor) const;
   void PushPageScaleFactorAndLimits(const float* page_scale_factor,
@@ -796,6 +800,7 @@
   bool new_local_surface_id_request_ = false;
   // Contains the physical rect of the device viewport, to be used in
   // determining what needs to be drawn.
+  bool device_viewport_rect_changed_ = false;
   gfx::Rect device_viewport_rect_;
 
   scoped_refptr<SyncedElasticOverscroll> elastic_overscroll_;
diff --git a/cc/trees/layer_tree_settings.h b/cc/trees/layer_tree_settings.h
index 3d41141..63f087b 100644
--- a/cc/trees/layer_tree_settings.h
+++ b/cc/trees/layer_tree_settings.h
@@ -196,11 +196,6 @@
   // When enabled, enforces new interoperable semantics for 3D transforms.
   // See crbug.com/1008483.
   bool enable_transform_interop = false;
-
-  // When enabled, the compositor specifies a frame rate preference that would
-  // allow the display to run at a low refresh rate matching the playback rate
-  // for videos updating onscreen.
-  bool force_preferred_interval_for_video = false;
 };
 
 class CC_EXPORT LayerListSettings : public LayerTreeSettings {
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index b910bb3..78afbdf9 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -432,6 +432,7 @@
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java",
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabIncognitoManager.java",
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java",
+  "java/src/org/chromium/chrome/browser/customtabs/CustomTabLaunchCauseMetrics.java",
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabNavigationEventObserver.java",
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabNightModeStateController.java",
   "java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java",
@@ -752,8 +753,8 @@
   "java/src/org/chromium/chrome/browser/language/LanguageAskPrompt.java",
   "java/src/org/chromium/chrome/browser/language/settings/AddLanguageFragment.java",
   "java/src/org/chromium/chrome/browser/language/settings/AvailableUiLanguages.java",
-  "java/src/org/chromium/chrome/browser/language/settings/DetailedLanguageListPreference.java",
   "java/src/org/chromium/chrome/browser/language/settings/LanguageItem.java",
+  "java/src/org/chromium/chrome/browser/language/settings/LanguageItemPickerPreference.java",
   "java/src/org/chromium/chrome/browser/language/settings/LanguageListBaseAdapter.java",
   "java/src/org/chromium/chrome/browser/language/settings/LanguageListPreference.java",
   "java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java",
@@ -790,6 +791,7 @@
   "java/src/org/chromium/chrome/browser/metrics/MainIntentBehaviorMetrics.java",
   "java/src/org/chromium/chrome/browser/metrics/PackageMetrics.java",
   "java/src/org/chromium/chrome/browser/metrics/PageLoadMetrics.java",
+  "java/src/org/chromium/chrome/browser/metrics/TabbedActivityLaunchCauseMetrics.java",
   "java/src/org/chromium/chrome/browser/metrics/UkmRecorder.java",
   "java/src/org/chromium/chrome/browser/metrics/UmaSessionStats.java",
   "java/src/org/chromium/chrome/browser/metrics/VariationsSession.java",
@@ -1500,6 +1502,7 @@
   "java/src/org/chromium/chrome/browser/webapps/WebappIntentDataProvider.java",
   "java/src/org/chromium/chrome/browser/webapps/WebappIntentDataProviderFactory.java",
   "java/src/org/chromium/chrome/browser/webapps/WebappIntentUtils.java",
+  "java/src/org/chromium/chrome/browser/webapps/WebappLaunchCauseMetrics.java",
   "java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java",
   "java/src/org/chromium/chrome/browser/webapps/WebappLocator.java",
   "java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni
index 42a97e3..2fe6723 100644
--- a/chrome/android/chrome_test_java_sources.gni
+++ b/chrome/android/chrome_test_java_sources.gni
@@ -137,6 +137,7 @@
   "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabDeferredStartupTest.java",
   "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabExternalNavigationTest.java",
   "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabFromChromeExternalNavigationTest.java",
+  "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabLaunchCauseMetricsTest.java",
   "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistenceIntegrationTest.java",
   "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicyTest.java",
   "javatests/src/org/chromium/chrome/browser/customtabs/CustomTabTaskDescriptionHelperTest.java",
diff --git a/chrome/android/features/autofill_assistant/BUILD.gn b/chrome/android/features/autofill_assistant/BUILD.gn
index 49b9ffa..acba495c 100644
--- a/chrome/android/features/autofill_assistant/BUILD.gn
+++ b/chrome/android/features/autofill_assistant/BUILD.gn
@@ -51,6 +51,7 @@
     "//components/autofill/android:autofill_java",
     "//components/browser_ui/android/bottomsheet:java",
     "//components/browser_ui/modaldialog/android:java",
+    "//components/browser_ui/settings/android:java",
     "//components/browser_ui/widget/android:java",
     "//components/embedder_support/android:util_java",
     "//components/favicon/android:java",
diff --git a/chrome/android/features/autofill_assistant/java/DEPS b/chrome/android/features/autofill_assistant/java/DEPS
index 93272aa6..99c1a2f 100644
--- a/chrome/android/features/autofill_assistant/java/DEPS
+++ b/chrome/android/features/autofill_assistant/java/DEPS
@@ -4,6 +4,7 @@
   "+chrome/browser/ui/messages/android/java",
   "+chrome/browser/tab/java",
   "+components/autofill/android",
+  "+components/browser_ui/settings/android",
   "+components/browser_ui/widget/android",
   "+components/payments/content/android",
   "+content/public/android/java/src/org/chromium/content_public/browser",
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderViewBinder.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderViewBinder.java
index 15de88d..1a82843 100644
--- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderViewBinder.java
+++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/header/AssistantHeaderViewBinder.java
@@ -19,9 +19,9 @@
 import org.chromium.chrome.browser.autofill_assistant.AssistantTextUtils;
 import org.chromium.chrome.browser.autofill_assistant.AutofillAssistantPreferenceFragment;
 import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChipAdapter;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.util.ChromeAccessibilityUtil;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.widget.textbubble.TextBubble;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 import org.chromium.ui.modelutil.PropertyKey;
diff --git a/chrome/android/java/res/xml/languages_detailed_preferences.xml b/chrome/android/java/res/xml/languages_detailed_preferences.xml
index 6bff063..8eb44c2 100644
--- a/chrome/android/java/res/xml/languages_detailed_preferences.xml
+++ b/chrome/android/java/res/xml/languages_detailed_preferences.xml
@@ -4,16 +4,47 @@
      found in the LICENSE file. -->
 
 <PreferenceScreen
-    xmlns:android="http://schemas.android.com/apk/res/android">
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
 
-    <org.chromium.chrome.browser.language.settings.DetailedLanguageListPreference
-        android:key="preferred_languages"
-        android:layout="@layout/languages_preference"
-        android:widgetLayout="@layout/accept_languages_list" />
+    <PreferenceCategory
+        android:key="app_language_section"
+        android:order="1">
 
-    <org.chromium.components.browser_ui.settings.ChromeSwitchPreference
-        android:key="translate_switch"
-        android:summaryOn="@string/languages_offer_translate_switch"
-        android:summaryOff="@string/languages_offer_translate_switch" />
+        <org.chromium.chrome.browser.language.settings.LanguageItemPickerPreference
+            android:key="app_language_preference" />
+
+    </PreferenceCategory>
+
+    <PreferenceCategory
+      android:key="content_langauges_section"
+      android:title="@string/languages_content_title"
+      android:order="2"
+      app:allowDividerAbove="true">
+
+        <org.chromium.chrome.browser.language.settings.LanguageListPreference
+            android:key="content_languages_preference"
+            android:layout="@layout/languages_preference"
+            android:widgetLayout="@layout/accept_languages_list" />
+
+    </PreferenceCategory>
+
+    <PreferenceCategory
+        android:key="translation_settings_section"
+        android:order="3"
+        android:title="@string/languages_settings_title"
+        app:initialExpandedChildrenCount="1">
+
+        <org.chromium.components.browser_ui.settings.ChromeSwitchPreference
+            android:key="translate_switch"
+            android:summaryOn="@string/languages_send_translate_switch"
+            android:summaryOff="@string/languages_send_translate_switch" />
+
+        <org.chromium.chrome.browser.language.settings.LanguageItemPickerPreference
+            android:key="translate_settings_target_language"
+            android:title="@string/languages_settings_target"
+            app:allowDividerBelow="false" />
+
+    </PreferenceCategory>
 
 </PreferenceScreen>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index 2a0abbae..b09f9b6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -101,8 +101,10 @@
 import org.chromium.chrome.browser.layouts.LayoutStateProvider;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.locale.LocaleManager;
+import org.chromium.chrome.browser.metrics.LaunchCauseMetrics;
 import org.chromium.chrome.browser.metrics.LaunchMetrics;
 import org.chromium.chrome.browser.metrics.MainIntentBehaviorMetrics;
+import org.chromium.chrome.browser.metrics.TabbedActivityLaunchCauseMetrics;
 import org.chromium.chrome.browser.modaldialog.ChromeTabModalPresenter;
 import org.chromium.chrome.browser.modaldialog.TabModalLifetimeHandler;
 import org.chromium.chrome.browser.multiwindow.MultiInstanceChromeTabbedActivity;
@@ -1676,6 +1678,11 @@
     }
 
     @Override
+    protected LaunchCauseMetrics createLaunchCauseMetrics() {
+        return new TabbedActivityLaunchCauseMetrics();
+    }
+
+    @Override
     public AppMenuPropertiesDelegate createAppMenuPropertiesDelegate() {
         return new TabbedAppMenuPropertiesDelegate(this, getActivityTabProvider(),
                 getMultiWindowModeStateDispatcher(), getTabModelSelector(), getToolbarManager(),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
index 081be31..cf2dfbb8 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -132,7 +132,6 @@
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.printing.TabPrinter;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.share.ShareDelegate;
 import org.chromium.chrome.browser.share.ShareDelegateImpl;
@@ -174,6 +173,7 @@
 import org.chromium.components.browser_ui.modaldialog.AppModalPresenter;
 import org.chromium.components.browser_ui.notifications.NotificationManagerProxy;
 import org.chromium.components.browser_ui.notifications.NotificationManagerProxyImpl;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.widget.InsetObserverView;
 import org.chromium.components.browser_ui.widget.MenuOrKeyboardActionController;
 import org.chromium.components.browser_ui.widget.textbubble.TextBubble;
@@ -732,13 +732,9 @@
     }
 
     /**
-     * TODO(mthiesse, https://crbug.com/1163961): Make this function abstract and have derived
-     * classes make their own.
-     * @return The {@link LaunchCauseMetrics} owned by this {@link ChromeActivity}.
+     * @return The {@link LaunchCauseMetrics} to be owned by this {@link ChromeActivity}.
      */
-    protected LaunchCauseMetrics createLaunchCauseMetrics() {
-        return new LaunchCauseMetrics();
-    }
+    protected abstract LaunchCauseMetrics createLaunchCauseMetrics();
 
     private LaunchCauseMetrics getLaunchCauseMetrics() {
         if (mLaunchCauseMetrics == null) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillProfileBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillProfileBridge.java
index 73c4c46..a41a0e3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillProfileBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill/settings/AutofillProfileBridge.java
@@ -14,8 +14,8 @@
 import org.chromium.base.annotations.JNINamespace;
 import org.chromium.base.annotations.NativeMethods;
 import org.chromium.base.metrics.RecordUserAction;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.content_public.browser.WebContents;
 
 import java.lang.annotation.Retention;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferenceFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferenceFragment.java
index 8c26a9e4..5fc1f95 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferenceFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPreferenceFragment.java
@@ -16,12 +16,12 @@
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.signin.services.UnifiedConsentServiceBridge;
 import org.chromium.chrome.browser.sync.settings.GoogleServicesSettings;
 import org.chromium.chrome.browser.sync.settings.SyncAndServicesSettings;
 import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.settings.SettingsUtils;
 import org.chromium.ui.text.NoUnderlineClickableSpan;
 import org.chromium.ui.text.SpanApplier;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java
index 04c22be..c1fd6ad 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkBridge.java
@@ -840,10 +840,9 @@
      * bookmark ID will be returned.
      * @param title The title to be used for the reading list item.
      * @param url The URL of the reading list item.
-     * @return The bookmark ID created after saving the article to the reading list, or null on
-     *         error.
+     * @return The bookmark ID created after saving the article to the reading list.
      */
-    public @Nullable BookmarkId addToReadingList(String title, String url) {
+    public BookmarkId addToReadingList(String title, String url) {
         ThreadUtils.assertOnUiThread();
         assert title != null;
         assert url != null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivitySettingsLauncher.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivitySettingsLauncher.java
index 59bb8a5..f7581c3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivitySettingsLauncher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/TrustedWebActivitySettingsLauncher.java
@@ -11,9 +11,9 @@
 
 import org.chromium.base.Log;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.webapps.ChromeWebApkHost;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.site_settings.AllSiteSettings;
 import org.chromium.components.browser_ui.site_settings.SettingsNavigationSource;
 import org.chromium.components.browser_ui.site_settings.SingleWebsiteSettings;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPromoControl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPromoControl.java
index 2486eb3..ceb955d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPromoControl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPromoControl.java
@@ -23,8 +23,8 @@
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager;
 import org.chromium.chrome.browser.contextualsearch.ContextualSearchPreferenceFragment;
 import org.chromium.chrome.browser.layouts.animation.CompositorAnimator;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.ui.base.LocalizationUtils;
 import org.chromium.ui.resources.dynamics.DynamicResourceLoader;
 import org.chromium.ui.text.NoUnderlineClickableSpan;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
index c574260..c71f3bd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -39,6 +39,7 @@
 import org.chromium.chrome.browser.customtabs.features.CustomTabNavigationBarController;
 import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor;
 import org.chromium.chrome.browser.infobar.InfoBarContainer;
+import org.chromium.chrome.browser.metrics.LaunchCauseMetrics;
 import org.chromium.chrome.browser.night_mode.NightModeStateProvider;
 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
 import org.chromium.chrome.browser.page_info.ChromePageInfoControllerDelegate;
@@ -290,6 +291,11 @@
         return mTwaCoordinator == null ? null : mTwaCoordinator.getTwaPackage();
     }
 
+    @Override
+    protected LaunchCauseMetrics createLaunchCauseMetrics() {
+        return new CustomTabLaunchCauseMetrics(this);
+    }
+
     @VisibleForTesting
     NightModeStateProvider getNightModeStateProviderForTesting() {
         return super.getNightModeStateProvider();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabLaunchCauseMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabLaunchCauseMetrics.java
new file mode 100644
index 0000000..d18c1e6
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabLaunchCauseMetrics.java
@@ -0,0 +1,28 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.customtabs;
+
+import org.chromium.chrome.browser.flags.ActivityType;
+import org.chromium.chrome.browser.metrics.LaunchCauseMetrics;
+
+/**
+ * LaunchCauseMetrics for CustomTabActivity.
+ */
+public class CustomTabLaunchCauseMetrics extends LaunchCauseMetrics {
+    private final CustomTabActivity mActivity;
+
+    public CustomTabLaunchCauseMetrics(CustomTabActivity activity) {
+        mActivity = activity;
+    }
+
+    @Override
+    public @LaunchCause int computeLaunchCause() {
+        if (mActivity.getActivityType() == ActivityType.TRUSTED_WEB_ACTIVITY) {
+            return LaunchCause.TWA;
+        }
+        assert mActivity.getActivityType() == ActivityType.CUSTOM_TAB;
+        return LaunchCause.CUSTOM_TAB;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionMainMenuItem.java b/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionMainMenuItem.java
index 7fa9578f..8882da19 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionMainMenuItem.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/datareduction/DataReductionMainMenuItem.java
@@ -21,8 +21,8 @@
 import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.profiles.ProfileManager;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.feature_engagement.EventConstants;
 import org.chromium.components.feature_engagement.Tracker;
 import org.chromium.third_party.android.datausagechart.ChartDataUsageView;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorFactoryHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorFactoryHelper.java
index 38f57ab8..e430a63 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorFactoryHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorFactoryHelper.java
@@ -12,9 +12,9 @@
 import org.chromium.chrome.browser.download.settings.DownloadSettings;
 import org.chromium.chrome.browser.feature_engagement.TrackerFactory;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.util.GlobalDiscardableReferencePool;
 import org.chromium.components.user_prefs.UserPrefs;
 import org.chromium.ui.modaldialog.ModalDialogManager;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java
index ad1f885a..80706af 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunSignInProcessor.java
@@ -15,7 +15,6 @@
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
 import org.chromium.chrome.browser.signin.services.SigninManager;
@@ -24,6 +23,7 @@
 import org.chromium.chrome.browser.sync.ProfileSyncService;
 import org.chromium.chrome.browser.sync.settings.ManageSyncSettings;
 import org.chromium.chrome.browser.sync.settings.SyncAndServicesSettings;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.signin.AccountManagerFacadeProvider;
 import org.chromium.components.signin.AccountUtils;
 import org.chromium.components.signin.metrics.SigninAccessPoint;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
index 2f43673..387c143 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
@@ -38,7 +38,6 @@
 import org.chromium.chrome.browser.preferences.PrefChangeRegistrar.PrefObserver;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
 import org.chromium.chrome.browser.signin.services.SigninManager.SignInStateObserver;
@@ -48,6 +47,7 @@
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager.SnackbarController;
 import org.chromium.chrome.browser.util.ChromeAccessibilityUtil;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.util.ConversionUtils;
 import org.chromium.components.browser_ui.widget.selectable_list.SelectableListLayout;
 import org.chromium.components.browser_ui.widget.selectable_list.SelectableListToolbar.SearchDelegate;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java b/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java
index de8d957c..15f1ce2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/homepage/HomepageManager.java
@@ -18,8 +18,8 @@
 import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.embedder_support.util.UrlConstants;
 import org.chromium.components.embedder_support.util.UrlUtilities;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/identity_disc/IdentityDiscController.java b/chrome/android/java/src/org/chromium/chrome/browser/identity_disc/IdentityDiscController.java
index 3c7617ab..5106aa9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/identity_disc/IdentityDiscController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/identity_disc/IdentityDiscController.java
@@ -22,7 +22,6 @@
 import org.chromium.chrome.browser.ntp.NewTabPage;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.settings.MainSettings;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
 import org.chromium.chrome.browser.signin.services.ProfileDataCache;
@@ -32,6 +31,7 @@
 import org.chromium.chrome.browser.toolbar.ButtonDataProvider;
 import org.chromium.chrome.browser.user_education.IPHCommandBuilder;
 import org.chromium.chrome.features.start_surface.StartSurfaceState;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.feature_engagement.EventConstants;
 import org.chromium.components.feature_engagement.FeatureConstants;
 import org.chromium.components.feature_engagement.Tracker;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/PermissionInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PermissionInfoBar.java
index a395fb6..9d2048c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/PermissionInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PermissionInfoBar.java
@@ -11,8 +11,8 @@
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.site_settings.SingleCategorySettings;
 import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory;
 import org.chromium.components.infobars.ConfirmInfoBar;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/PreviewsLitePageInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PreviewsLitePageInfoBar.java
index 59c6069..cf48e0f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/PreviewsLitePageInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/PreviewsLitePageInfoBar.java
@@ -9,8 +9,8 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.datareduction.settings.DataReductionPreferenceFragment;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBar;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SearchGeolocationDisclosureInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SearchGeolocationDisclosureInfoBar.java
index c832686d..c5a94f6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SearchGeolocationDisclosureInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SearchGeolocationDisclosureInfoBar.java
@@ -9,8 +9,8 @@
 import org.chromium.base.ContextUtils;
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.site_settings.SingleWebsiteSettings;
 import org.chromium.components.infobars.InfoBar;
 import org.chromium.components.infobars.InfoBarLayout;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SyncErrorInfoBar.java b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SyncErrorInfoBar.java
index e9df671..92fedd9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/infobar/SyncErrorInfoBar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/infobar/SyncErrorInfoBar.java
@@ -19,13 +19,13 @@
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
 import org.chromium.chrome.browser.sync.settings.ManageSyncSettings;
 import org.chromium.chrome.browser.sync.settings.SyncAndServicesSettings;
 import org.chromium.chrome.browser.sync.settings.SyncSettingsUtils;
 import org.chromium.chrome.browser.sync.settings.SyncSettingsUtils.SyncError;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.infobars.ConfirmInfoBar;
 import org.chromium.components.infobars.InfoBar;
 import org.chromium.components.infobars.InfoBarLayout;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/language/AppLocaleUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/language/AppLocaleUtils.java
index 7f22f2b..0b6ed70 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/language/AppLocaleUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/language/AppLocaleUtils.java
@@ -30,6 +30,9 @@
 
     private static final String TAG = "AppLocale";
 
+    // Value of AppLocale preference when the system language is used.
+    public static final String SYSTEM_LANGUAGE_VALUE = null;
+
     /**
      * Return true if languageName is the same as the current application override
      * language stored preference.
@@ -45,7 +48,7 @@
      */
     public static String getAppLanguagePref() {
         return SharedPreferencesManager.getInstance().readString(
-                ChromePreferenceKeys.APPLICATION_OVERRIDE_LANGUAGE, null);
+                ChromePreferenceKeys.APPLICATION_OVERRIDE_LANGUAGE, SYSTEM_LANGUAGE_VALUE);
     }
 
     /**
@@ -58,7 +61,7 @@
     @SuppressWarnings("DefaultSharedPreferencesCheck")
     protected static String getAppLanguagePrefStartUp(Context base) {
         return PreferenceManager.getDefaultSharedPreferences(base).getString(
-                ChromePreferenceKeys.APPLICATION_OVERRIDE_LANGUAGE, null);
+                ChromePreferenceKeys.APPLICATION_OVERRIDE_LANGUAGE, SYSTEM_LANGUAGE_VALUE);
     }
 
     /**
@@ -69,7 +72,7 @@
         SharedPreferencesManager.getInstance().writeString(
                 ChromePreferenceKeys.APPLICATION_OVERRIDE_LANGUAGE, languageName);
         if (BundleUtils.isBundle()) {
-            ensureLaguageSplitInstalled(languageName);
+            ensureLanguageSplitInstalled(languageName);
         }
     }
 
@@ -89,14 +92,14 @@
     }
 
     /**
-     * For bundle builds ensure that the language split for languageName is download.
+     * For bundle builds ensure that the language split for languageName is downloaded.
      */
-    private static void ensureLaguageSplitInstalled(String languageName) {
+    private static void ensureLanguageSplitInstalled(String languageName) {
         SplitInstallManager splitInstallManager =
                 SplitInstallManagerFactory.create(ContextUtils.getApplicationContext());
 
         // TODO(perrier): check if languageName is already installed. https://crbug.com/1103806
-        if (languageName != null) {
+        if (!TextUtils.equals(languageName, SYSTEM_LANGUAGE_VALUE)) {
             SplitInstallRequest installRequest =
                     SplitInstallRequest.newBuilder()
                             .addLanguage(Locale.forLanguageTag(languageName))
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/language/settings/AddLanguageFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/AddLanguageFragment.java
index 84574c0..30a8bc4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/language/settings/AddLanguageFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/AddLanguageFragment.java
@@ -24,6 +24,7 @@
 import androidx.recyclerview.widget.RecyclerView.ViewHolder;
 
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.components.browser_ui.settings.SettingsUtils;
 
 import java.util.ArrayList;
@@ -35,7 +36,14 @@
  * accept languages. There is a {@link SearchView} on its Actionbar to make a quick lookup.
  */
 public class AddLanguageFragment extends Fragment {
-    static final String INTENT_NEW_ACCEPT_LANGUAGE = "AddLanguageFragment.NewLanguage";
+    // Intent key to pass selected language code from AddLanguageFragment.
+    static final String INTENT_SELECTED_LANGUAGE = "AddLanguageFragment.SelectedLanguages";
+    // Intent key to receive type of languages to populate fragment with.
+    static final String INTENT_LANGUAGE_OPTIONS = "AddLanguageFragment.LanguageOptions";
+    // Intent keys to select language options to use.
+    static final int LANGUAGE_OPTIONS_ACCEPT_LANGUAGES = 0; // Default
+    static final int LANGUAGE_OPTIONS_UI_LANGUAGES = 1;
+    static final int LANGUAGE_OPTIONS_TRANSLATE_LANGUAGES = 2;
 
     /**
      * A host to launch AddLanguageFragment and receive the result.
@@ -97,7 +105,11 @@
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        getActivity().setTitle(R.string.add_language);
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.DETAILED_LANGUAGE_SETTINGS)) {
+            getActivity().setTitle(R.string.languages_select);
+        } else {
+            getActivity().setTitle(R.string.add_language);
+        }
         setHasOptionsMenu(true);
         LanguagesManager.recordImpression(
                 LanguagesManager.LanguageSettingsPageType.PAGE_ADD_LANGUAGE);
@@ -117,10 +129,20 @@
         mRecyclerView.addItemDecoration(
                 new DividerItemDecoration(activity, layoutManager.getOrientation()));
 
-        mFullLanguageList = LanguagesManager.getInstance().getLanguageItemsExcludingUserAccept();
+        int languageOption = getActivity().getIntent().getIntExtra(
+                INTENT_LANGUAGE_OPTIONS, LANGUAGE_OPTIONS_ACCEPT_LANGUAGES);
+        if (languageOption == LANGUAGE_OPTIONS_UI_LANGUAGES) {
+            mFullLanguageList = LanguagesManager.getInstance().getAvailableUiLanguageItems();
+            mFullLanguageList.add(0, LanguageItem.makeSystemDefaultLanguageItem());
+        } else if (languageOption == LANGUAGE_OPTIONS_TRANSLATE_LANGUAGES) {
+            mFullLanguageList = LanguagesManager.getInstance().getTranslateLanguageItems();
+        } else {
+            mFullLanguageList =
+                    LanguagesManager.getInstance().getLanguageItemsExcludingUserAccept();
+        }
         mItemClickListener = item -> {
             Intent intent = new Intent();
-            intent.putExtra(INTENT_NEW_ACCEPT_LANGUAGE, item.getCode());
+            intent.putExtra(INTENT_SELECTED_LANGUAGE, item.getCode());
             activity.setResult(Activity.RESULT_OK, intent);
             activity.finish();
         };
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/language/settings/DetailedLanguageListPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/DetailedLanguageListPreference.java
deleted file mode 100644
index a84261c..0000000
--- a/chrome/android/java/src/org/chromium/chrome/browser/language/settings/DetailedLanguageListPreference.java
+++ /dev/null
@@ -1,243 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.chrome.browser.language.settings;
-
-import static org.chromium.components.browser_ui.widget.listmenu.BasicListMenu.buildMenuListItem;
-import static org.chromium.components.browser_ui.widget.listmenu.BasicListMenu.buildMenuListItemWithEndIcon;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.TextView;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceViewHolder;
-import androidx.recyclerview.widget.DividerItemDecoration;
-import androidx.recyclerview.widget.LinearLayoutManager;
-import androidx.recyclerview.widget.RecyclerView;
-import androidx.recyclerview.widget.RecyclerView.ViewHolder;
-
-import org.chromium.base.BuildInfo;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.language.AppLocaleUtils;
-import org.chromium.chrome.browser.language.GlobalAppLocaleController;
-import org.chromium.chrome.browser.preferences.Pref;
-import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.translate.TranslateBridge;
-import org.chromium.components.browser_ui.widget.TintedDrawable;
-import org.chromium.components.browser_ui.widget.listmenu.BasicListMenu;
-import org.chromium.components.browser_ui.widget.listmenu.ListMenu;
-import org.chromium.components.browser_ui.widget.listmenu.ListMenuItemProperties;
-import org.chromium.components.user_prefs.UserPrefs;
-import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
-import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
-import org.chromium.ui.widget.Toast;
-
-/**
- * A preference that displays the current accept language list.
- */
-public class DetailedLanguageListPreference extends Preference {
-    private static class LanguageListAdapter
-            extends LanguageListBaseAdapter implements LanguagesManager.AcceptLanguageObserver {
-        private final Context mContext;
-
-        LanguageListAdapter(Context context) {
-            super(context);
-            mContext = context;
-        }
-
-        @Override
-        public void onBindViewHolder(ViewHolder holder, int position) {
-            super.onBindViewHolder(holder, position);
-
-            final LanguageItem info = getItemByPosition(position);
-
-            showDragIndicatorInRow((LanguageRowViewHolder) holder);
-            ModelList menuItems = new ModelList();
-
-            // Show "Offer to translate" option if "Chrome Translate" is enabled.
-            if (UserPrefs.get(Profile.getLastUsedRegularProfile())
-                            .getBoolean(Pref.OFFER_TRANSLATE_ENABLED)) {
-                // Set this row checked if the language is unblocked.
-                int endIconResId = TranslateBridge.isBlockedLanguage(info.getCode())
-                        ? 0
-                        : R.drawable.ic_check_googblue_24dp;
-                ListItem item = buildMenuListItemWithEndIcon(
-                        R.string.languages_item_option_offer_to_translate, 0, endIconResId,
-                        info.isSupported());
-                item.model.set(
-                        ListMenuItemProperties.TINT_COLOR_ID, R.color.default_icon_color_blue);
-
-                // Add checked icon at the end.
-                menuItems.add(item);
-            }
-
-            // Show "Use as language" and mark as checked if current item is set as language pref.
-            int endIconResId = AppLocaleUtils.isAppLanguagePref(info.getCode())
-                    ? R.drawable.ic_check_googblue_24dp
-                    : 0;
-            ListItem item =
-                    buildMenuListItemWithEndIcon(R.string.languages_set_application_language_prompt,
-                            0, endIconResId, info.isUISupported());
-            item.model.set(ListMenuItemProperties.TINT_COLOR_ID, R.color.default_icon_color_blue);
-
-            menuItems.add(item);
-
-            int languageCount = getItemCount();
-            // Enable "Remove" option if there are multiple accept languages.
-            menuItems.add(buildMenuListItem(R.string.remove, 0, 0, languageCount > 1));
-
-            // Add some appropriate options for moving the language when the list is not
-            // draggable. E.g. in the accessibility mode.
-            if (!mDragStateDelegate.getDragEnabled()) {
-                // Add "Move to top" and "Move up" menu when it's not the first one.
-                if (position > 0) {
-                    menuItems.add(buildMenuListItem(R.string.menu_item_move_to_top, 0, 0));
-                    menuItems.add(buildMenuListItem(R.string.menu_item_move_up, 0, 0));
-                }
-
-                // Add "Move down" menu when it's not the last one.
-                if (position < (languageCount - 1)) {
-                    menuItems.add(buildMenuListItem(R.string.menu_item_move_down, 0, 0));
-                }
-            }
-
-            ListMenu.Delegate delegate = (model) -> {
-                int textId = model.get(ListMenuItemProperties.TITLE_ID);
-                if (textId == R.string.languages_item_option_offer_to_translate) {
-                    // Toggle current blocked state of this language.
-                    boolean state = model.get(ListMenuItemProperties.END_ICON_ID) == 0;
-                    TranslateBridge.setLanguageBlockedState(info.getCode(), !state);
-                    LanguagesManager.recordAction(state
-                                    ? LanguagesManager.LanguageSettingsActionType
-                                              .ENABLE_TRANSLATE_FOR_SINGLE_LANGUAGE
-                                    : LanguagesManager.LanguageSettingsActionType
-                                              .DISABLE_TRANSLATE_FOR_SINGLE_LANGUAGE);
-                } else if (textId == R.string.languages_set_application_language_prompt) {
-                    updateOverrideLanguage(info);
-                } else if (textId == R.string.remove) {
-                    // If the removed language is the override language reset UI to system language.
-                    if (AppLocaleUtils.isAppLanguagePref(info.getCode())) {
-                        resetOverrideLanguage();
-                    }
-                    LanguagesManager.getInstance().removeFromAcceptLanguages(info.getCode());
-                    LanguagesManager.recordAction(
-                            LanguagesManager.LanguageSettingsActionType.LANGUAGE_REMOVED);
-                } else if (textId == R.string.menu_item_move_up) {
-                    LanguagesManager.getInstance().moveLanguagePosition(info.getCode(), -1, true);
-                } else if (textId == R.string.menu_item_move_down) {
-                    LanguagesManager.getInstance().moveLanguagePosition(info.getCode(), 1, true);
-                } else if (textId == R.string.menu_item_move_to_top) {
-                    LanguagesManager.getInstance().moveLanguagePosition(
-                            info.getCode(), -position, true);
-                }
-                // Re-generate list items.
-                if (textId != R.string.remove) {
-                    notifyDataSetChanged();
-                }
-            };
-            ((LanguageRowViewHolder) holder)
-                    .setMenuButtonDelegate(() -> new BasicListMenu(mContext, menuItems, delegate));
-        }
-
-        /**
-         * Updates the app language preference and shows Toast notifing user language
-         * will change after restart. If attempting to set the current app language pref
-         * instead reset override language to use system language.
-         * @param info LanguageItem to update application language to.
-         */
-        private void updateOverrideLanguage(LanguageItem info) {
-            String newLanguageCode = info.getCode();
-            if (AppLocaleUtils.isAppLanguagePref(newLanguageCode)) {
-                resetOverrideLanguage();
-                return;
-            }
-            // Set the language preference value. The UI will not change until a full restart.
-            AppLocaleUtils.setAppLanguagePref(newLanguageCode);
-            showAppLanguageToast(info.getDisplayName());
-        }
-
-        private void resetOverrideLanguage() {
-            AppLocaleUtils.setAppLanguagePref(null);
-            showAppLanguageToast(GlobalAppLocaleController.getInstance()
-                                         .getOriginalSystemLocale()
-                                         .getDisplayName());
-        }
-
-        private void showAppLanguageToast(String languageName) {
-            String appName = BuildInfo.getInstance().hostPackageLabel;
-            String text = mContext.getString(
-                    R.string.languages_set_as_application_language, appName, languageName);
-            Toast.makeText(mContext, text, Toast.LENGTH_LONG).show();
-        }
-
-        @Override
-        public void onDataUpdated() {
-            if (mDragStateDelegate.getDragActive()) {
-                enableDrag();
-            } else {
-                disableDrag();
-            }
-            setDisplayedLanguages(LanguagesManager.getInstance().getUserAcceptLanguageItems());
-        }
-    }
-
-    private TextView mAddLanguageButton;
-    private RecyclerView mRecyclerView;
-    private LanguageListAdapter mAdapter;
-    private AddLanguageFragment.Launcher mLauncher;
-
-    public DetailedLanguageListPreference(Context context, AttributeSet attrs) {
-        super(context, attrs);
-        mAdapter = new LanguageListAdapter(context);
-    }
-
-    @Override
-    public void onBindViewHolder(PreferenceViewHolder holder) {
-        super.onBindViewHolder(holder);
-
-        assert mLauncher != null;
-
-        mAddLanguageButton = (TextView) holder.findViewById(R.id.add_language);
-        mAddLanguageButton.setCompoundDrawablesRelativeWithIntrinsicBounds(
-                TintedDrawable.constructTintedDrawable(
-                        getContext(), R.drawable.plus, R.color.default_control_color_active),
-                null, null, null);
-        mAddLanguageButton.setOnClickListener(view -> {
-            mLauncher.launchAddLanguage();
-            LanguagesManager.recordAction(
-                    LanguagesManager.LanguageSettingsActionType.CLICK_ON_ADD_LANGUAGE);
-        });
-
-        mRecyclerView = (RecyclerView) holder.findViewById(R.id.language_list);
-        LinearLayoutManager layoutMangager = new LinearLayoutManager(getContext());
-        mRecyclerView.setLayoutManager(layoutMangager);
-        mRecyclerView.addItemDecoration(
-                new DividerItemDecoration(getContext(), layoutMangager.getOrientation()));
-
-        // We do not want the RecyclerView to be announced by screen readers every time
-        // the view is bound.
-        if (mRecyclerView.getAdapter() != mAdapter) {
-            mRecyclerView.setAdapter(mAdapter);
-            LanguagesManager.getInstance().setAcceptLanguageObserver(mAdapter);
-            // Initialize accept language list.
-            mAdapter.onDataUpdated();
-        }
-    }
-
-    /**
-     * Register a launcher for AddLanguageFragment. Preference's host fragment should call
-     * this in its onCreate().
-     */
-    void registerActivityLauncher(AddLanguageFragment.Launcher launcher) {
-        mLauncher = launcher;
-    }
-
-    /**
-     * Notify LanguageListAdapter of pref changes to update list items.
-     */
-    void notifyPrefChanged() {
-        mAdapter.onDataUpdated();
-    }
-}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageItem.java b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageItem.java
index 0f2b1200..890e8a01 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageItem.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageItem.java
@@ -4,6 +4,15 @@
 
 package org.chromium.chrome.browser.language.settings;
 
+import android.text.TextUtils;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.language.AppLocaleUtils;
+import org.chromium.chrome.browser.language.GlobalAppLocaleController;
+
+import java.util.Locale;
+
 /**
  * Simple object representing the language item.
  */
@@ -31,7 +40,11 @@
         mDisplayName = displayName;
         mNativeDisplayName = nativeDisplayName;
         mSupportTranslate = supportTranslate;
-        mSupportAppUI = AvailableUiLanguages.isAvailable(mCode);
+        if (TextUtils.equals(code, AppLocaleUtils.SYSTEM_LANGUAGE_VALUE)) {
+            mSupportAppUI = true; // system language is a supported UI language
+        } else {
+            mSupportAppUI = AvailableUiLanguages.isAvailable(mCode);
+        }
     }
 
     /**
@@ -68,4 +81,18 @@
     public boolean isUISupported() {
         return mSupportAppUI;
     }
+
+    /**
+     * Create a LanguageItem representing the system default language.
+     * @return LanguageItem
+     */
+    public static LanguageItem makeSystemDefaultLanguageItem() {
+        String displayName = ContextUtils.getApplicationContext().getResources().getString(
+                R.string.default_lang_subtitle);
+        String nativeName =
+                GlobalAppLocaleController.getInstance().getOriginalSystemLocale().getDisplayName(
+                        Locale.getDefault());
+        return new LanguageItem(
+                AppLocaleUtils.SYSTEM_LANGUAGE_VALUE, displayName, nativeName, true);
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageItemPickerPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageItemPickerPreference.java
new file mode 100644
index 0000000..f9942508
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageItemPickerPreference.java
@@ -0,0 +1,73 @@
+// 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.language.settings;
+
+import android.content.Context;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+
+import org.chromium.chrome.browser.language.AppLocaleUtils;
+import org.chromium.components.browser_ui.settings.ChromeBasePreference;
+
+/**
+ * Chrome Preference that enables selecting a single LanguageItem.
+ */
+public class LanguageItemPickerPreference extends ChromeBasePreference {
+    private LanguageItem mLanguageItem;
+    private boolean mUseLanguageItemForTitle;
+
+    public LanguageItemPickerPreference(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    /**
+     * Set the LanguageItem value.
+     * @param LanguageItem The LanguageItem to use for this preference
+     */
+    public void setLanguageItem(LanguageItem languageItem) {
+        assert languageItem != null;
+        mLanguageItem = languageItem;
+        updateDisplay();
+    }
+
+    /**
+     * Set the LanguageItem value based on the string locale code. If null is used the system
+     * default language is set as the preference's LanguageItem
+     * @param String languageCode The iso639 languageCode for LanguageItem
+     */
+    public void setLanguageItem(String languageCode) {
+        LanguageItem languageItem;
+        if (TextUtils.equals(languageCode, AppLocaleUtils.SYSTEM_LANGUAGE_VALUE)) {
+            languageItem = LanguageItem.makeSystemDefaultLanguageItem();
+        } else {
+            languageItem = LanguagesManager.getInstance().getLanguageItem(languageCode);
+        }
+        setLanguageItem(languageItem);
+    }
+
+    /**
+     * By default only the summary text is synced to the LanguageItem. Enabling this will make the
+     * preference title the display name and summary the native display name.
+     * @param boolean use
+     */
+    public void useLanguageItemForTitle(boolean useForTitle) {
+        mUseLanguageItemForTitle = useForTitle;
+        updateDisplay();
+    }
+
+    /**
+     * Update the title and summary to display
+     */
+    private void updateDisplay() {
+        if (mLanguageItem == null) {
+            return;
+        } else if (mUseLanguageItemForTitle) {
+            setTitle(mLanguageItem.getDisplayName());
+            setSummary(mLanguageItem.getNativeDisplayName());
+        } else {
+            setSummary(mLanguageItem.getDisplayName());
+        }
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java
index a1ccd5fc..e91312a4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguageSettings.java
@@ -10,16 +10,20 @@
 
 import androidx.annotation.VisibleForTesting;
 import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
 import androidx.preference.PreferenceFragmentCompat;
 
+import org.chromium.base.BuildInfo;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.language.AppLocaleUtils;
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
+import org.chromium.chrome.browser.translate.TranslateBridge;
 import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.settings.SettingsUtils;
 import org.chromium.components.prefs.PrefService;
 import org.chromium.components.user_prefs.UserPrefs;
@@ -30,12 +34,22 @@
  */
 public class LanguageSettings
         extends PreferenceFragmentCompat implements AddLanguageFragment.Launcher {
-    private static final int REQUEST_CODE_ADD_LANGUAGES = 1;
+    private static final int REQUEST_CODE_ADD_ACCEPT_LANGUAGE = 1;
+    private static final int REQUEST_CODE_CHANGE_APP_LANGUAGE = 2;
+    private static final int REQUEST_CODE_CHANGE_TARGET_LANGUAGE = 3;
 
     // The keys for each preference shown on the languages page.
+    static final String APP_LANGUAGE_SECTION_KEY = "app_language_section";
+    static final String APP_LANGUAGE_PREFERENCE_KEY = "app_language_preference";
     static final String PREFERRED_LANGUAGES_KEY = "preferred_languages";
+    static final String CONTENT_LANGUAGES_KEY = "content_languages_preference";
     static final String TRANSLATE_SWITCH_KEY = "translate_switch";
 
+    static final String TARGET_LANGUAGE_KEY = "translate_settings_target_language";
+    static final String AUTOMATIC_LANGUAGES_KEY = "translate_settings_automatic_languages";
+    static final String NO_PROMPT_LANGUAGES_KEY = "translate_settings_no_prompt_languages";
+    static final String NO_PROMPT_SITES_KEY = "translate_settings_no_prompt_sites";
+
     @Override
     public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
         getActivity().setTitle(R.string.language_settings);
@@ -50,12 +64,14 @@
         LanguagesManager.recordImpression(LanguagesManager.LanguageSettingsPageType.PAGE_MAIN);
     }
 
-    public void createDetailedPreferences(Bundle savedInstanceState, String rootKey) {
-        SettingsUtils.addPreferencesFromResource(this, R.xml.languages_detailed_preferences);
+    /**
+     * Create the old language and translate settings page.  Delete once no longer used.
+     */
+    private void createBasicPreferences(Bundle savedInstanceState, String rootKey) {
+        SettingsUtils.addPreferencesFromResource(this, R.xml.languages_preferences);
 
-        DetailedLanguageListPreference mLanguageListPref =
-                (DetailedLanguageListPreference) findPreference(PREFERRED_LANGUAGES_KEY);
-
+        LanguageListPreference mLanguageListPref =
+                (LanguageListPreference) findPreference(PREFERRED_LANGUAGES_KEY);
         mLanguageListPref.registerActivityLauncher(this);
 
         ChromeSwitchPreference translateSwitch =
@@ -80,25 +96,63 @@
                 -> getPrefService().isManagedPreference(Pref.OFFER_TRANSLATE_ENABLED));
     }
 
-    public void createBasicPreferences(Bundle savedInstanceState, String rootKey) {
-        SettingsUtils.addPreferencesFromResource(this, R.xml.languages_preferences);
+    /**
+     * Create the new language and translate settings page. With options to change the app language,
+     * translate target language, and detailed translate preferences.
+     */
+    private void createDetailedPreferences(Bundle savedInstanceState, String rootKey) {
+        SettingsUtils.addPreferencesFromResource(this, R.xml.languages_detailed_preferences);
+
+        setupAppLanguageSection();
 
         LanguageListPreference mLanguageListPref =
-                (LanguageListPreference) findPreference(PREFERRED_LANGUAGES_KEY);
-
+                (LanguageListPreference) findPreference(CONTENT_LANGUAGES_KEY);
         mLanguageListPref.registerActivityLauncher(this);
 
+        setupTranslateSection(mLanguageListPref);
+    }
+
+    /**
+     * Setup the App Language section with a title and preference to choose the app language.
+     */
+    private void setupAppLanguageSection() {
+        // Set title to include current app name.
+        PreferenceCategory mAppLanguageTitle =
+                (PreferenceCategory) findPreference(APP_LANGUAGE_SECTION_KEY);
+        String mAppName = BuildInfo.getInstance().hostPackageLabel;
+        mAppLanguageTitle.setTitle(getResources().getString(R.string.app_language_title, mAppName));
+
+        LanguageItemPickerPreference appLanguagePreference =
+                (LanguageItemPickerPreference) findPreference(APP_LANGUAGE_PREFERENCE_KEY);
+        appLanguagePreference.setLanguageItem(AppLocaleUtils.getAppLanguagePref());
+        appLanguagePreference.useLanguageItemForTitle(true);
+        setSelectLanguageLauncher(appLanguagePreference,
+                AddLanguageFragment.LANGUAGE_OPTIONS_UI_LANGUAGES,
+                REQUEST_CODE_CHANGE_APP_LANGUAGE);
+    }
+
+    /**
+     * Setup the translate preferences section.  A switch preferences controls if translate is
+     * enabled/disabled and will hide all advanced settings when disabled.
+     * @param languageListPreference LanguageListPreference reference to update about state changes.
+     */
+    private void setupTranslateSection(LanguageListPreference languageListPreference) {
         ChromeSwitchPreference translateSwitch =
                 (ChromeSwitchPreference) findPreference(TRANSLATE_SWITCH_KEY);
         boolean isTranslateEnabled = getPrefService().getBoolean(Pref.OFFER_TRANSLATE_ENABLED);
         translateSwitch.setChecked(isTranslateEnabled);
 
+        // Get advanced section preference items
+        LanguageItemPickerPreference targetLanguagePreference =
+                (LanguageItemPickerPreference) findPreference(TARGET_LANGUAGE_KEY);
+
         translateSwitch.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
             @Override
             public boolean onPreferenceChange(Preference preference, Object newValue) {
                 boolean enabled = (boolean) newValue;
                 getPrefService().setBoolean(Pref.OFFER_TRANSLATE_ENABLED, enabled);
-                mLanguageListPref.notifyPrefChanged();
+                languageListPreference.notifyPrefChanged();
+                targetLanguagePreference.setVisible(enabled);
                 LanguagesManager.recordAction(enabled ? LanguagesManager.LanguageSettingsActionType
                                                                 .ENABLE_TRANSLATE_GLOBALLY
                                                       : LanguagesManager.LanguageSettingsActionType
@@ -108,6 +162,11 @@
         });
         translateSwitch.setManagedPreferenceDelegate((ChromeManagedPreferenceDelegate) preference
                 -> getPrefService().isManagedPreference(Pref.OFFER_TRANSLATE_ENABLED));
+
+        targetLanguagePreference.setLanguageItem(TranslateBridge.getTargetLanguage());
+        setSelectLanguageLauncher(targetLanguagePreference,
+                AddLanguageFragment.LANGUAGE_OPTIONS_TRANSLATE_LANGUAGES,
+                REQUEST_CODE_CHANGE_TARGET_LANGUAGE);
     }
 
     @Override
@@ -119,21 +178,65 @@
     @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
-        if (requestCode == REQUEST_CODE_ADD_LANGUAGES && resultCode == Activity.RESULT_OK) {
-            String code = data.getStringExtra(AddLanguageFragment.INTENT_NEW_ACCEPT_LANGUAGE);
+        if (requestCode == REQUEST_CODE_ADD_ACCEPT_LANGUAGE && resultCode == Activity.RESULT_OK) {
+            String code = data.getStringExtra(AddLanguageFragment.INTENT_SELECTED_LANGUAGE);
             LanguagesManager.getInstance().addToAcceptLanguages(code);
             LanguagesManager.recordAction(
                     LanguagesManager.LanguageSettingsActionType.LANGUAGE_ADDED);
+        } else if (requestCode == REQUEST_CODE_CHANGE_APP_LANGUAGE
+                && resultCode == Activity.RESULT_OK) {
+            String code = data.getStringExtra(AddLanguageFragment.INTENT_SELECTED_LANGUAGE);
+            LanguageItemPickerPreference appLanguagePreference =
+                    (LanguageItemPickerPreference) findPreference(APP_LANGUAGE_PREFERENCE_KEY);
+            appLanguagePreference.setLanguageItem(code);
+            AppLocaleUtils.setAppLanguagePref(code);
+        } else if (requestCode == REQUEST_CODE_CHANGE_TARGET_LANGUAGE
+                && resultCode == Activity.RESULT_OK) {
+            String code = data.getStringExtra(AddLanguageFragment.INTENT_SELECTED_LANGUAGE);
+            LanguageItemPickerPreference targetLanguagePreference =
+                    (LanguageItemPickerPreference) findPreference(TARGET_LANGUAGE_KEY);
+            targetLanguagePreference.setLanguageItem(code);
+            TranslateBridge.setDefaultTargetLanguage(code);
         }
     }
 
+    /**
+     * Overrides AddLanguageFragment.Launcher.launchAddLanguage to handle click events on the
+     * Add Language button inside the LanguageListPreference.
+     */
     @Override
     public void launchAddLanguage() {
-        // Launch preference activity with AddLanguageFragment.
+        launchSelectLanguage(AddLanguageFragment.LANGUAGE_OPTIONS_ACCEPT_LANGUAGES,
+                REQUEST_CODE_ADD_ACCEPT_LANGUAGE);
+    }
+
+    /**
+     * Set preference's OnPreferenceClickListener to launch the Select Language Fragment.
+     * @param Preference preference The Preference to set listener on.
+     * @param int launchCode The language options code to filter selectable languages.
+     * @param int requestCode The code to return from the select language fragment with.
+     */
+    private void setSelectLanguageLauncher(Preference preference, int launchCode, int requestCode) {
+        preference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
+            @Override
+            public boolean onPreferenceClick(Preference preference) {
+                launchSelectLanguage(launchCode, requestCode);
+                return true;
+            }
+        });
+    }
+
+    /**
+     * Launch the AddLanguageFragment with launch and request codes to select a single language.
+     * @param int launchCode The language options code to filter selectable languages.
+     * @param int requestCode The code to return from the select language fragment with.
+     */
+    private void launchSelectLanguage(int launchCode, int requestCode) {
         SettingsLauncher settingsLauncher = new SettingsLauncherImpl();
         Intent intent = settingsLauncher.createSettingsActivityIntent(
                 getActivity(), AddLanguageFragment.class.getName());
-        startActivityForResult(intent, REQUEST_CODE_ADD_LANGUAGES);
+        intent.putExtra(AddLanguageFragment.INTENT_LANGUAGE_OPTIONS, launchCode);
+        startActivityForResult(intent, requestCode);
     }
 
     @VisibleForTesting
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguagesManager.java b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguagesManager.java
index a0fefa6..2c2f21f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguagesManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/language/settings/LanguagesManager.java
@@ -6,6 +6,7 @@
 
 import androidx.annotation.IntDef;
 
+import org.chromium.base.LocaleUtils;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.chrome.browser.translate.TranslateBridge;
 
@@ -124,6 +125,43 @@
     }
 
     /**
+     * Get a list of LanguageItems that can be Chrome UI languages.
+     * @return List of LanguageItems.
+     */
+    public List<LanguageItem> getAvailableUiLanguageItems() {
+        List<LanguageItem> results = new ArrayList<>();
+        for (LanguageItem item : mLanguagesMap.values()) {
+            if (item.isUISupported()) results.add(item);
+        }
+        return results;
+    }
+
+    /**
+     * Get a list of LanguageItems that are translatable.
+     * @return List of LanguageItems.
+     */
+    public List<LanguageItem> getTranslateLanguageItems() {
+        List<LanguageItem> results = new ArrayList<>();
+        for (LanguageItem item : mLanguagesMap.values()) {
+            if (item.isSupported()) results.add(item);
+        }
+        return results;
+    }
+
+    /**
+     * Get a LanguageItem given the iso639 locale code (e.g. en-US).  If no direct match is found
+     * only the language is checked. If there is still no match null is returned.
+     * @return LanguageItem or null if none found
+     */
+    public LanguageItem getLanguageItem(String localeCode) {
+        LanguageItem result = mLanguagesMap.get(localeCode);
+        if (result != null) return result;
+
+        String baseLanguage = LocaleUtils.toLanguage(localeCode);
+        return mLanguagesMap.get(baseLanguage);
+    }
+
+    /**
      * Add a language to the current user's accept languages.
      * @param code The language code to remove.
      */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/locale/LocaleManager.java b/chrome/android/java/src/org/chromium/chrome/browser/locale/LocaleManager.java
index ab35774..cf802ccf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/locale/LocaleManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/locale/LocaleManager.java
@@ -28,13 +28,13 @@
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
 import org.chromium.chrome.browser.search_engines.settings.SearchEngineSettings;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager.SnackbarController;
 import org.chromium.chrome.browser.vr.OnExitVrRequestListener;
 import org.chromium.chrome.browser.vr.VrModuleProvider;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.widget.PromoDialog;
 import org.chromium.components.search_engines.TemplateUrl;
 import org.chromium.ui.base.PageTransition;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/locale/SogouPromoDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/locale/SogouPromoDialog.java
index 662a21fd..eb02710 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/locale/SogouPromoDialog.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/locale/SogouPromoDialog.java
@@ -23,8 +23,8 @@
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.search_engines.settings.SearchEngineSettings;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.widget.PromoDialog;
 import org.chromium.ui.text.NoUnderlineClickableSpan;
 import org.chromium.ui.text.SpanApplier;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/LaunchCauseMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/LaunchCauseMetrics.java
index 219be09..8a98fc1 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/metrics/LaunchCauseMetrics.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/LaunchCauseMetrics.java
@@ -6,10 +6,11 @@
 
 import androidx.annotation.CallSuper;
 import androidx.annotation.IntDef;
+import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.ApplicationState;
 import org.chromium.base.ApplicationStatus;
-import org.chromium.base.annotations.RemovableInRelease;
+import org.chromium.base.ThreadUtils;
 import org.chromium.base.metrics.RecordHistogram;
 
 import java.lang.annotation.Retention;
@@ -18,22 +19,23 @@
 /**
  * Computes and records metrics for what caused Chrome to be launched.
  */
-public class LaunchCauseMetrics {
+public abstract class LaunchCauseMetrics {
     // Static to avoid recording launch metrics when transitioning between Activities without
     // Chrome leaving the foreground.
     private static boolean sRecordedLaunchCause;
 
-    /* package */ static final String LAUNCH_CAUSE_HISTOGRAM =
-            "MobileStartup.Experimental.LaunchCause";
+    @VisibleForTesting
+    public static final String LAUNCH_CAUSE_HISTOGRAM = "MobileStartup.Experimental.LaunchCause";
 
     // These values are persisted in histograms. Please do not renumber. Append only.
-    @IntDef({LaunchCause.OTHER})
+    @IntDef({LaunchCause.OTHER, LaunchCause.CUSTOM_TAB, LaunchCause.TWA})
     @Retention(RetentionPolicy.SOURCE)
-    /* package */ @interface LaunchCause {
+    public @interface LaunchCause {
         int OTHER = 0;
+        int CUSTOM_TAB = 1;
+        int TWA = 2;
 
-        // A histogram enum cannot have only 1 entry, so while developing this we need to lie.
-        int NUM_ENTRIES = 2;
+        int NUM_ENTRIES = 3;
     }
 
     public LaunchCauseMetrics() {
@@ -53,13 +55,9 @@
     }
 
     /**
-     * TODO(mthiesse, https://crbug.com/1163961): Make this function abstract.
-     *
      * Computes and returns what the cause of the Chrome launch was.
      */
-    protected @LaunchCause int computeLaunchCause() {
-        return LaunchCause.OTHER;
-    }
+    protected abstract @LaunchCause int computeLaunchCause();
 
     /**
      * Called after Chrome has launched and all information necessary to compute why Chrome was
@@ -77,8 +75,9 @@
                 LAUNCH_CAUSE_HISTOGRAM, cause, LaunchCause.NUM_ENTRIES);
     }
 
-    @RemovableInRelease
-    /* package */ static void resetForTests() {
+    @VisibleForTesting
+    public static void resetForTests() {
+        ThreadUtils.assertOnUiThread();
         sRecordedLaunchCause = false;
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/metrics/TabbedActivityLaunchCauseMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/metrics/TabbedActivityLaunchCauseMetrics.java
new file mode 100644
index 0000000..939154b
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/metrics/TabbedActivityLaunchCauseMetrics.java
@@ -0,0 +1,16 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.metrics;
+
+/**
+ * LaunchCauseMetrics for ChromeTabbedActivity.
+ */
+public class TabbedActivityLaunchCauseMetrics extends LaunchCauseMetrics {
+    @Override
+    public @LaunchCause int computeLaunchCause() {
+        // TODO(https://crbug.com/1163961): Implement ChromeTabbedActivity launch cause metrics.
+        return LaunchCause.OTHER;
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
index ede170ca..49b39de 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/notifications/NotificationPlatformBridge.java
@@ -39,7 +39,6 @@
 import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
 import org.chromium.chrome.browser.notifications.channels.SiteChannelsManager;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.usage_stats.NotificationSuspender;
 import org.chromium.chrome.browser.webapps.ChromeWebApkHost;
@@ -49,6 +48,7 @@
 import org.chromium.components.browser_ui.notifications.NotificationMetadata;
 import org.chromium.components.browser_ui.notifications.NotificationWrapper;
 import org.chromium.components.browser_ui.notifications.PendingIntentProvider;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.site_settings.SingleCategorySettings;
 import org.chromium.components.browser_ui.site_settings.SingleWebsiteSettings;
 import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoCookieControlsManager.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoCookieControlsManager.java
index f1b7ee967..157e822 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoCookieControlsManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/IncognitoCookieControlsManager.java
@@ -11,10 +11,10 @@
 
 import org.chromium.base.ObserverList;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.site_settings.CookieControlsServiceBridge;
 import org.chromium.chrome.browser.site_settings.CookieControlsServiceBridge.CookieControlsServiceObserver;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.site_settings.SingleCategorySettings;
 import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory;
 import org.chromium.components.content_settings.CookieControlsEnforcement;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoController.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoController.java
index b4346a4..e4a741f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/promo/enhanced_protection/EnhancedProtectionPromoController.java
@@ -18,8 +18,8 @@
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.safe_browsing.metrics.SettingsAccessPoint;
 import org.chromium.chrome.browser.safe_browsing.settings.SafeBrowsingSettingsFragment;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.widget.promo.PromoCardCoordinator;
 import org.chromium.components.browser_ui.widget.promo.PromoCardProperties;
 import org.chromium.ui.modelutil.PropertyModel;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchedPagesNotifier.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchedPagesNotifier.java
index a98a1de..6a1d4fa 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchedPagesNotifier.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/prefetch/PrefetchedPagesNotifier.java
@@ -21,7 +21,6 @@
 import org.chromium.chrome.browser.notifications.NotificationWrapperBuilderFactory;
 import org.chromium.chrome.browser.notifications.channels.ChromeChannelDefinitions;
 import org.chromium.chrome.browser.notifications.settings.NotificationSettings;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.components.browser_ui.notifications.NotificationManagerProxy;
 import org.chromium.components.browser_ui.notifications.NotificationManagerProxyImpl;
@@ -29,6 +28,7 @@
 import org.chromium.components.browser_ui.notifications.NotificationWrapper;
 import org.chromium.components.browser_ui.notifications.NotificationWrapperBuilder;
 import org.chromium.components.browser_ui.notifications.PendingIntentProvider;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.content_public.browser.BrowserStartupController;
 import org.chromium.content_public.browser.BrowserStartupController.StartupCallback;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUi.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUi.java
index 38c0017..4b0a3d4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUi.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/voice/AssistantVoiceSearchConsentUi.java
@@ -20,12 +20,12 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.autofill_assistant.AutofillAssistantPreferenceFragment;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerProvider;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver;
 import org.chromium.components.browser_ui.bottomsheet.EmptyBottomSheetObserver;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.ui.base.WindowAndroid;
 
 import java.lang.annotation.Retention;
@@ -251,4 +251,4 @@
     public int getSheetClosedAccessibilityStringId() {
         return R.string.avs_consent_ui_closed_description;
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/page_info/SiteSettingsHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/page_info/SiteSettingsHelper.java
index eb8a5751..e79e553 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/page_info/SiteSettingsHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/page_info/SiteSettingsHelper.java
@@ -11,8 +11,8 @@
 import org.chromium.base.StrictModeContext;
 import org.chromium.chrome.browser.offlinepages.OfflinePageUtils;
 import org.chromium.chrome.browser.previews.PreviewsAndroidBridge;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.site_settings.ContentSettingsResources;
 import org.chromium.components.browser_ui.site_settings.SingleCategorySettings;
 import org.chromium.components.browser_ui.site_settings.SingleWebsiteSettings;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordEditingBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordEditingBridge.java
index 901e766..c8ed973 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordEditingBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordEditingBridge.java
@@ -9,8 +9,8 @@
 
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.base.annotations.NativeMethods;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 
 /**
  * This is a bridge between PasswordEntryEditor and the C++ code. The bridge is in charge of
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java
index 2470d6b..28ca9b7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettings.java
@@ -39,12 +39,12 @@
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.webauthn.CableAuthenticatorModuleProvider;
 import org.chromium.components.browser_ui.settings.ChromeBasePreference;
 import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
 import org.chromium.components.browser_ui.settings.SearchUtils;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.settings.TextMessagePreference;
 import org.chromium.components.prefs.PrefService;
 import org.chromium.components.user_prefs.UserPrefs;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUiService.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUiService.java
index 97f3911..c123e2f4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUiService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentUiService.java
@@ -42,7 +42,6 @@
 import org.chromium.chrome.browser.payments.minimal.MinimalUICoordinator.ReadyObserver;
 import org.chromium.chrome.browser.payments.ui.PaymentRequestSection.OptionSection.FocusChangedObserver;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabSelectionType;
@@ -55,6 +54,7 @@
 import org.chromium.components.autofill.Completable;
 import org.chromium.components.autofill.EditableOption;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetControllerProvider;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.payments.AbortReason;
 import org.chromium.components.payments.BasicCardUtils;
 import org.chromium.components.payments.CurrencyFormatter;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/previews/HttpsImageCompressionUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/previews/HttpsImageCompressionUtils.java
index c679f0a..d2d98d9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/previews/HttpsImageCompressionUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/previews/HttpsImageCompressionUtils.java
@@ -11,11 +11,11 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.datareduction.settings.DataReductionPreferenceFragment;
 import org.chromium.chrome.browser.infobar.InfoBarIdentifier;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabUtils;
 import org.chromium.chrome.browser.ui.messages.infobar.SimpleConfirmInfoBarBuilder;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 
 /**
  * Common utility API used in java land.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java b/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java
index 7ea054d..71e9d71 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java
@@ -24,7 +24,6 @@
 import org.chromium.chrome.browser.safe_browsing.metrics.SettingsAccessPoint;
 import org.chromium.chrome.browser.safe_browsing.settings.SafeBrowsingSettingsFragment;
 import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
 import org.chromium.chrome.browser.sync.settings.GoogleServicesSettings;
@@ -33,6 +32,7 @@
 import org.chromium.chrome.browser.usage_stats.UsageStatsConsentDialog;
 import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
 import org.chromium.components.browser_ui.settings.ManagedPreferenceDelegate;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.settings.SettingsUtils;
 import org.chromium.components.prefs.PrefService;
 import org.chromium.components.signin.identitymanager.ConsentLevel;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingSettingsLauncher.java b/chrome/android/java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingSettingsLauncher.java
index 1a90511..1b0567b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingSettingsLauncher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingSettingsLauncher.java
@@ -8,8 +8,8 @@
 import org.chromium.base.annotations.CalledByNative;
 import org.chromium.chrome.browser.safe_browsing.metrics.SettingsAccessPoint;
 import org.chromium.chrome.browser.safe_browsing.settings.SafeBrowsingSettingsFragment;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.base.WindowAndroid;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotification.java b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotification.java
index fe6e6b9..85aec8c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotification.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/SearchEngineChoiceNotification.java
@@ -14,12 +14,12 @@
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.search_engines.settings.SearchEngineSettings;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager.SnackbarController;
 import org.chromium.chrome.browser.version.ChromeVersionInfo;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 
 import java.util.concurrent.TimeUnit;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineAdapter.java b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineAdapter.java
index 81e9128..60ab9cda 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineAdapter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/search_engines/settings/SearchEngineAdapter.java
@@ -32,8 +32,8 @@
 import org.chromium.chrome.browser.locale.LocaleManager;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.site_settings.PermissionInfo;
 import org.chromium.components.browser_ui.site_settings.SingleWebsiteSettings;
 import org.chromium.components.browser_ui.site_settings.WebsitePreferenceBridge;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java
index b081033..4899fee 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java
@@ -44,6 +44,7 @@
 import org.chromium.chrome.browser.tracing.settings.DeveloperSettings;
 import org.chromium.components.browser_ui.settings.ChromeBasePreference;
 import org.chromium.components.browser_ui.settings.ManagedPreferenceDelegate;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.settings.SettingsUtils;
 import org.chromium.components.search_engines.TemplateUrl;
 import org.chromium.components.search_engines.TemplateUrlService;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
index 8ec841c..a13690e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
@@ -46,6 +46,8 @@
 import org.chromium.chrome.browser.safety_check.SafetyCheckUpdatesDelegateImpl;
 import org.chromium.chrome.browser.signin.SigninActivityLauncherImpl;
 import org.chromium.chrome.browser.site_settings.ChromeSiteSettingsDelegate;
+import org.chromium.components.browser_ui.settings.FragmentSettingsLauncher;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.settings.SettingsUtils;
 import org.chromium.components.browser_ui.site_settings.SiteSettingsPreferenceFragment;
 import org.chromium.ui.UiUtils;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsLauncherImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsLauncherImpl.java
index 088a8b7..39078e3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsLauncherImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsLauncherImpl.java
@@ -13,6 +13,7 @@
 import androidx.fragment.app.Fragment;
 
 import org.chromium.base.IntentUtils;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 
 /**
  * Implementation class for launching a {@link SettingsActivity}.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardShareActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardShareActivity.java
index 499d670..5cc953967 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardShareActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardShareActivity.java
@@ -22,12 +22,12 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.init.AsyncInitializationActivity;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.sharing.SharingAdapter;
 import org.chromium.chrome.browser.sharing.SharingServiceProxy;
 import org.chromium.chrome.browser.sharing.SharingServiceProxy.DeviceInfo;
 import org.chromium.chrome.browser.sync.AndroidSyncSettings;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.sync.protocol.SharingSpecificFields;
 import org.chromium.ui.widget.ButtonCompat;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragment.java
index 5a7ce31..4848b58 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninFragment.java
@@ -17,7 +17,6 @@
 import org.chromium.chrome.browser.SyncFirstSetupCompleteSource;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
 import org.chromium.chrome.browser.signin.services.SigninManager;
@@ -26,6 +25,7 @@
 import org.chromium.chrome.browser.sync.ProfileSyncService;
 import org.chromium.chrome.browser.sync.settings.ManageSyncSettings;
 import org.chromium.chrome.browser.sync.settings.SyncAndServicesSettings;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.signin.AccountManagerFacadeProvider;
 import org.chromium.components.signin.AccountUtils;
 import org.chromium.components.signin.metrics.SigninAccessPoint;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncPromoView.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncPromoView.java
index 8ba9374..b6e85e4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncPromoView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SyncPromoView.java
@@ -17,11 +17,11 @@
 
 import org.chromium.base.IntentUtils;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.signin.ui.SigninActivityLauncher.AccessPoint;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
 import org.chromium.chrome.browser.sync.settings.SyncAndServicesSettings;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.signin.metrics.SigninAccessPoint;
 
 /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ManageSpaceActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ManageSpaceActivity.java
index 9f875f7..5a0f4f9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ManageSpaceActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ManageSpaceActivity.java
@@ -37,9 +37,9 @@
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.searchwidget.SearchWidgetProvider;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.version.ChromeVersionInfo;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.site_settings.AllSiteSettings;
 import org.chromium.components.browser_ui.site_settings.SingleCategorySettings;
 import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java
index 65c6a36c..f80b399 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/SyncNotificationController.java
@@ -20,7 +20,6 @@
 import org.chromium.chrome.browser.notifications.NotificationWrapperBuilderFactory;
 import org.chromium.chrome.browser.notifications.channels.ChromeChannelDefinitions;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
 import org.chromium.chrome.browser.sync.settings.SyncAndServicesSettings;
@@ -33,6 +32,7 @@
 import org.chromium.components.browser_ui.notifications.NotificationWrapper;
 import org.chromium.components.browser_ui.notifications.NotificationWrapperBuilder;
 import org.chromium.components.browser_ui.notifications.PendingIntentProvider;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.signin.base.CoreAccountInfo;
 import org.chromium.components.signin.base.GoogleServiceAuthError.State;
 import org.chromium.components.signin.identitymanager.ConsentLevel;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java
index b54f93e5..e9e794f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java
@@ -28,7 +28,6 @@
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.profiles.ProfileAccountManagementMetrics;
 import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.signin.SigninUtils;
 import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
@@ -41,6 +40,7 @@
 import org.chromium.chrome.browser.superviseduser.FilteringBehavior;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
 import org.chromium.components.browser_ui.settings.ChromeBasePreference;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.prefs.PrefService;
 import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.components.signin.AccountManagerFacadeProvider;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java
index 356266f4..b9cc365 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/translate/TranslateBridge.java
@@ -81,6 +81,14 @@
         return TranslateBridgeJni.get().getTargetLanguage();
     }
 
+    /**
+     * Set the default target language the Translate Service will use.
+     * @param String targetLanguage Language code of new target language.
+     */
+    public static void setDefaultTargetLanguage(String targetLanguage) {
+        TranslateBridgeJni.get().setDefaultTargetLanguage(targetLanguage);
+    }
+
     /** @return whether the given string is blocked for translation. */
     public static boolean isBlockedLanguage(String language) {
         return TranslateBridgeJni.get().isBlockedLanguage(language);
@@ -224,6 +232,7 @@
         String getOriginalLanguage(WebContents webContents);
         String getCurrentLanguage(WebContents webContents);
         String getTargetLanguage();
+        void setDefaultTargetLanguage(String targetLanguage);
         boolean isBlockedLanguage(String language);
         void getModelLanguages(LinkedHashSet<String> set);
         void resetAcceptLanguages(String defaultLocale);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
index 802fa30..853cadc0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -19,6 +19,7 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider;
 import org.chromium.chrome.browser.customtabs.BaseCustomTabActivity;
+import org.chromium.chrome.browser.metrics.LaunchCauseMetrics;
 
 /**
  * Displays a webapp in a nearly UI-less Chrome (InfoBars still appear).
@@ -87,4 +88,9 @@
     protected Drawable getBackgroundDrawable() {
         return null;
     }
+
+    @Override
+    protected LaunchCauseMetrics createLaunchCauseMetrics() {
+        return new WebappLaunchCauseMetrics();
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLaunchCauseMetrics.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLaunchCauseMetrics.java
new file mode 100644
index 0000000..2f8502b
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLaunchCauseMetrics.java
@@ -0,0 +1,18 @@
+// 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.webapps;
+
+import org.chromium.chrome.browser.metrics.LaunchCauseMetrics;
+
+/**
+ * LaunchCauseMetrics for WebappActivity.
+ */
+public class WebappLaunchCauseMetrics extends LaunchCauseMetrics {
+    @Override
+    public @LaunchCause int computeLaunchCause() {
+        // TODO(https://crbug.com/1163961): Implement Webapp launch cause metrics.
+        return LaunchCause.OTHER;
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java
index d39bd02..9442632 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/bookmarks/BookmarkBridgeTest.java
@@ -17,15 +17,11 @@
 import org.chromium.base.test.UiThreadTest;
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.Feature;
-import org.chromium.base.test.util.RequiresRestart;
 import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.test.ChromeBrowserTestRule;
 import org.chromium.chrome.test.util.BookmarkTestUtil;
-import org.chromium.chrome.test.util.browser.Features;
 import org.chromium.components.bookmarks.BookmarkId;
-import org.chromium.components.bookmarks.BookmarkType;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
 import java.util.ArrayList;
@@ -318,22 +314,4 @@
                         + "over partner bookmarks",
                 expectedSearchResults, searchResults);
     }
-
-    @Test
-    @SmallTest
-    @UiThreadTest
-    @RequiresRestart("Reading list glue code uses the flag to load a keyed service.")
-    @Features.EnableFeatures({ChromeFeatureList.READ_LATER})
-    public void testAddToReadingList() {
-        Assert.assertNull("Should return null for non http/https URLs.",
-                mBookmarkBridge.addToReadingList("a", "chrome://flags"));
-        BookmarkId readingListId = mBookmarkBridge.addToReadingList("a", "https://www.google.com/");
-        Assert.assertNotNull(readingListId);
-        Assert.assertEquals(BookmarkType.READING_LIST, readingListId.getType());
-        BookmarkItem readingListItem =
-                mBookmarkBridge.getReadingListItem("https://www.google.com/");
-        Assert.assertNotNull(readingListItem);
-        Assert.assertEquals("https://www.google.com/", readingListItem.getUrl());
-        Assert.assertEquals("a", readingListItem.getTitle());
-    }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityTest.java
index e3ce687..97ce316 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/TrustedWebActivityTest.java
@@ -33,6 +33,7 @@
 import org.chromium.base.CommandLine;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.library_loader.LibraryLoader;
+import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Criteria;
 import org.chromium.base.test.util.CriteriaHelper;
@@ -45,6 +46,7 @@
 import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.metrics.LaunchCauseMetrics;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.browser.tab.TabBrowserControlsConstraintsHelper;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -97,6 +99,17 @@
                 ContentSwitches.HOST_RESOLVER_RULES, "MAP * " + mapToUri.getAuthority());
     }
 
+    private void assertLaunchCauseMetrics(boolean launchedTWA) {
+        assertEquals(launchedTWA ? 1 : 0,
+                RecordHistogram.getHistogramValueCountForTesting(
+                        LaunchCauseMetrics.LAUNCH_CAUSE_HISTOGRAM,
+                        LaunchCauseMetrics.LaunchCause.TWA));
+        assertEquals(launchedTWA ? 0 : 1,
+                RecordHistogram.getHistogramValueCountForTesting(
+                        LaunchCauseMetrics.LAUNCH_CAUSE_HISTOGRAM,
+                        LaunchCauseMetrics.LaunchCause.CUSTOM_TAB));
+    }
+
     @Test
     @MediumTest
     public void launchesTwa() throws TimeoutException {
@@ -104,6 +117,7 @@
         launchCustomTabActivity(intent);
 
         assertTrue(isTrustedWebActivity(mCustomTabActivityTestRule.getActivity()));
+        assertLaunchCauseMetrics(true);
     }
 
     @Test
@@ -114,6 +128,7 @@
         launchCustomTabActivity(intent);
 
         assertFalse(isTrustedWebActivity(mCustomTabActivityTestRule.getActivity()));
+        assertLaunchCauseMetrics(false);
     }
 
     @Test
@@ -126,6 +141,7 @@
         mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
 
         assertFalse(isTrustedWebActivity(mCustomTabActivityTestRule.getActivity()));
+        assertLaunchCauseMetrics(true);
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
index 04b6fec..ad3bc38e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -105,6 +105,7 @@
 import org.chromium.chrome.browser.history.HistoryItem;
 import org.chromium.chrome.browser.history.TestBrowsingHistoryObserver;
 import org.chromium.chrome.browser.infobar.InfoBarContainer;
+import org.chromium.chrome.browser.metrics.LaunchCauseMetrics;
 import org.chromium.chrome.browser.metrics.PageLoadMetrics;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.EmptyTabObserver;
@@ -771,6 +772,10 @@
         IntentHandler.setForceIntentSenderChromeToTrue(true);
 
         mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent);
+        assertEquals(1,
+                RecordHistogram.getHistogramValueCountForTesting(
+                        LaunchCauseMetrics.LAUNCH_CAUSE_HISTOGRAM,
+                        LaunchCauseMetrics.LaunchCause.CUSTOM_TAB));
 
         IntentFilter filter = new IntentFilter(Intent.ACTION_VIEW);
         filter.addDataScheme(Uri.parse(mTestServer.getURL("/")).getScheme());
@@ -789,6 +794,10 @@
         });
 
         callbackTriggered.waitForCallback(0);
+        // No additional LaunchCauses should have been recorded.
+        assertEquals(1,
+                RecordHistogram.getHistogramTotalCountForTesting(
+                        LaunchCauseMetrics.LAUNCH_CAUSE_HISTOGRAM));
     }
 
     /**
@@ -798,7 +807,15 @@
     @SmallTest
     public void testTabReparentingBasic() {
         mCustomTabActivityTestRule.startCustomTabActivityWithIntent(createMinimalCustomTabIntent());
+        assertEquals(1,
+                RecordHistogram.getHistogramValueCountForTesting(
+                        LaunchCauseMetrics.LAUNCH_CAUSE_HISTOGRAM,
+                        LaunchCauseMetrics.LaunchCause.CUSTOM_TAB));
         reparentAndVerifyTab();
+        // No additional LaunchCauses should have been recorded.
+        assertEquals(1,
+                RecordHistogram.getHistogramTotalCountForTesting(
+                        LaunchCauseMetrics.LAUNCH_CAUSE_HISTOGRAM));
     }
 
     /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabLaunchCauseMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabLaunchCauseMetricsTest.java
new file mode 100644
index 0000000..94e622e9
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabLaunchCauseMetricsTest.java
@@ -0,0 +1,82 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.customtabs;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.base.test.BaseJUnit4ClassRunner;
+import org.chromium.base.test.UiThreadTest;
+import org.chromium.base.test.util.Batch;
+import org.chromium.chrome.browser.flags.ActivityType;
+import org.chromium.chrome.browser.metrics.LaunchCauseMetrics;
+import org.chromium.content_public.browser.test.NativeLibraryTestUtils;
+
+/**
+ * Tests basic functionality of CustomTabLaunchCauseMetricsTest.
+ */
+@RunWith(BaseJUnit4ClassRunner.class)
+@Batch(Batch.UNIT_TESTS)
+public final class CustomTabLaunchCauseMetricsTest {
+    @Before
+    public void setUp() {
+        NativeLibraryTestUtils.loadNativeLibraryNoBrowserProcess();
+    }
+
+    @After
+    public void tearDown() {
+        ThreadUtils.runOnUiThreadBlocking(() -> LaunchCauseMetrics.resetForTests());
+    }
+
+    private static int histogramCountForValue(int value) {
+        return RecordHistogram.getHistogramValueCountForTesting(
+                LaunchCauseMetrics.LAUNCH_CAUSE_HISTOGRAM, value);
+    }
+
+    // CustomTabActivity can't be mocked, because Mockito can't handle @ApiLevel annotations, and so
+    // can't mock classes that use them because classes can't be found on older API levels.
+    private CustomTabActivity makeActivity(boolean twa) {
+        return new CustomTabActivity() {
+            @Override
+            public int getActivityType() {
+                return twa ? ActivityType.TRUSTED_WEB_ACTIVITY : ActivityType.CUSTOM_TAB;
+            }
+        };
+    }
+
+    @Test
+    @SmallTest
+    @UiThreadTest
+    public void testCCTLaunch() throws Throwable {
+        CustomTabActivity activity = makeActivity(false);
+        int count = histogramCountForValue(LaunchCauseMetrics.LaunchCause.CUSTOM_TAB);
+
+        CustomTabLaunchCauseMetrics metrics = new CustomTabLaunchCauseMetrics(activity);
+        metrics.recordLaunchCause();
+        count++;
+        Assert.assertEquals(
+                count, histogramCountForValue(LaunchCauseMetrics.LaunchCause.CUSTOM_TAB));
+    }
+
+    @Test
+    @SmallTest
+    @UiThreadTest
+    public void testTWALaunch() throws Throwable {
+        CustomTabActivity activity = makeActivity(true);
+        int count = histogramCountForValue(LaunchCauseMetrics.LaunchCause.TWA);
+
+        CustomTabLaunchCauseMetrics metrics = new CustomTabLaunchCauseMetrics(activity);
+        metrics.recordLaunchCause();
+        count++;
+        Assert.assertEquals(count, histogramCountForValue(LaunchCauseMetrics.LaunchCause.TWA));
+    }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/LaunchCauseMetricsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/LaunchCauseMetricsTest.java
index 5c45241..3ca5f83e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/LaunchCauseMetricsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/metrics/LaunchCauseMetricsTest.java
@@ -21,6 +21,7 @@
 
 import org.chromium.base.ActivityState;
 import org.chromium.base.ApplicationStatus;
+import org.chromium.base.ThreadUtils;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.test.BaseJUnit4ClassRunner;
 import org.chromium.base.test.UiThreadTest;
@@ -47,7 +48,7 @@
     @After
     public void tearDown() {
         ApplicationStatus.destroyForJUnitTests();
-        LaunchCauseMetrics.resetForTests();
+        ThreadUtils.runOnUiThreadBlocking(() -> LaunchCauseMetrics.resetForTests());
     }
 
     private static int histogramCountForValue(int value) {
@@ -55,12 +56,19 @@
                 LaunchCauseMetrics.LAUNCH_CAUSE_HISTOGRAM, value);
     }
 
+    private static class TestLaunchCauseMetrics extends LaunchCauseMetrics {
+        @Override
+        protected @LaunchCause int computeLaunchCause() {
+            return LaunchCause.OTHER;
+        }
+    }
+
     @Test
     @SmallTest
     @UiThreadTest
     public void testRecordsOncePerLaunch() throws Throwable {
         int count = histogramCountForValue(LaunchCauseMetrics.LaunchCause.OTHER);
-        LaunchCauseMetrics metrics = new LaunchCauseMetrics();
+        TestLaunchCauseMetrics metrics = new TestLaunchCauseMetrics();
         metrics.recordLaunchCause();
         count++;
         Assert.assertEquals(count, histogramCountForValue(LaunchCauseMetrics.LaunchCause.OTHER));
@@ -86,11 +94,11 @@
     @UiThreadTest
     public void testRecordsOnceWithMultipleInstances() throws Throwable {
         int count = histogramCountForValue(LaunchCauseMetrics.LaunchCause.OTHER);
-        LaunchCauseMetrics metrics = new LaunchCauseMetrics();
+        TestLaunchCauseMetrics metrics = new TestLaunchCauseMetrics();
         metrics.recordLaunchCause();
         count++;
         Assert.assertEquals(count, histogramCountForValue(LaunchCauseMetrics.LaunchCause.OTHER));
-        new LaunchCauseMetrics().recordLaunchCause();
+        new TestLaunchCauseMetrics().recordLaunchCause();
         Assert.assertEquals(count, histogramCountForValue(LaunchCauseMetrics.LaunchCause.OTHER));
     }
 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettingsTest.java
index 80733a1..66f42caf 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettingsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/password_manager/settings/PasswordSettingsTest.java
@@ -104,13 +104,13 @@
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.settings.SettingsActivity;
 import org.chromium.chrome.browser.settings.SettingsActivityTestRule;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.sync.ProfileSyncService;
 import org.chromium.chrome.test.ChromeBrowserTestRule;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.prefs.PrefService;
 import org.chromium.components.sync.ModelType;
 import org.chromium.components.user_prefs.UserPrefs;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/ProfileTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/ProfileTest.java
index 4825765..4af768d8 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/ProfileTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/profiles/ProfileTest.java
@@ -16,11 +16,9 @@
 import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
-import org.chromium.chrome.browser.tab.TabLaunchType;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule;
-import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
 /**
@@ -43,13 +41,7 @@
 
     @Before
     public void setUp() {
-        createRegularProfileOnUiThread();
-    }
-
-    private void createRegularProfileOnUiThread() {
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            sActivityTestRule.getActivity().getTabCreator(false).createNewTab(
-                    new LoadUrlParams("about:blank"), TabLaunchType.FROM_CHROME_UI, null);
             mRegularProfile = sActivityTestRule.getActivity()
                                       .getTabModelSelector()
                                       .getModel(false)
@@ -61,20 +53,21 @@
     @Test
     @LargeTest
     public void testIncognitoProfileConsistency() throws Exception {
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            Assert.assertNull(mRegularProfile.getOTRProfileID());
+        Assert.assertNull(mRegularProfile.getOTRProfileID());
+        // Open an new Incognito Tab page to create a new primary OTR profile.
+        sActivityTestRule.loadUrlInNewTab("about:blank", true);
 
-            Profile incognitoProfile1 = mRegularProfile.getPrimaryOTRProfile();
-            Assert.assertTrue(incognitoProfile1.isOffTheRecord());
-            Assert.assertTrue(incognitoProfile1.isPrimaryOTRProfile());
-            Assert.assertTrue(incognitoProfile1.isNativeInitialized());
-            Assert.assertTrue(mRegularProfile.hasPrimaryOTRProfile());
+        Profile incognitoProfile1 =
+                TestThreadUtils.runOnUiThreadBlocking(() -> mRegularProfile.getPrimaryOTRProfile());
+        Assert.assertTrue(incognitoProfile1.isOffTheRecord());
+        Assert.assertTrue(incognitoProfile1.isPrimaryOTRProfile());
+        Assert.assertTrue(incognitoProfile1.isNativeInitialized());
+        Assert.assertTrue(mRegularProfile.hasPrimaryOTRProfile());
 
-            Profile incognitoProfile2 = mRegularProfile.getPrimaryOTRProfile();
-
-            Assert.assertSame("Two calls to get incognito profile should return the same object.",
-                    incognitoProfile1, incognitoProfile2);
-        });
+        Profile incognitoProfile2 =
+                TestThreadUtils.runOnUiThreadBlocking(() -> mRegularProfile.getPrimaryOTRProfile());
+        Assert.assertSame("Two calls to get incognito profile should return the same object.",
+                incognitoProfile1, incognitoProfile2);
     }
 
     /**
@@ -84,53 +77,52 @@
     @Test
     @LargeTest
     public void testNonPrimaryProfileConsistency() throws Exception {
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            OTRProfileID profileID = new OTRProfileID("test::OTRProfile");
-            Profile nonPrimaryOtrProfile1 = mRegularProfile.getOffTheRecordProfile(profileID);
+        OTRProfileID profileID = new OTRProfileID("test::OTRProfile");
+        Profile nonPrimaryOtrProfile1 = TestThreadUtils.runOnUiThreadBlocking(
+                () -> mRegularProfile.getOffTheRecordProfile(profileID));
 
-            Assert.assertTrue(nonPrimaryOtrProfile1.isOffTheRecord());
-            Assert.assertFalse(nonPrimaryOtrProfile1.isPrimaryOTRProfile());
-            Assert.assertTrue(nonPrimaryOtrProfile1.isNativeInitialized());
-            Assert.assertTrue(mRegularProfile.hasOffTheRecordProfile(profileID));
-            Assert.assertFalse(mRegularProfile.hasPrimaryOTRProfile());
+        Assert.assertTrue(nonPrimaryOtrProfile1.isOffTheRecord());
+        Assert.assertFalse(nonPrimaryOtrProfile1.isPrimaryOTRProfile());
+        Assert.assertTrue(nonPrimaryOtrProfile1.isNativeInitialized());
+        Assert.assertTrue(mRegularProfile.hasOffTheRecordProfile(profileID));
+        Assert.assertFalse(mRegularProfile.hasPrimaryOTRProfile());
 
-            Assert.assertEquals("OTR profile id should be returned as it is set.",
-                    nonPrimaryOtrProfile1.getOTRProfileID(), profileID);
+        Assert.assertEquals("OTR profile id should be returned as it is set.",
+                nonPrimaryOtrProfile1.getOTRProfileID(), profileID);
 
-            Profile nonPrimaryOtrProfile2 =
-                    mRegularProfile.getOffTheRecordProfile(new OTRProfileID("test::OTRProfile"));
+        Profile nonPrimaryOtrProfile2 = TestThreadUtils.runOnUiThreadBlocking(
+                () -> mRegularProfile.getOffTheRecordProfile(new OTRProfileID("test::OTRProfile")));
 
-            Assert.assertSame("Two calls to get non-primary OTR profile with the same ID "
-                            + "should return the same object.",
-                    nonPrimaryOtrProfile1, nonPrimaryOtrProfile2);
-        });
+        Assert.assertSame("Two calls to get non-primary OTR profile with the same ID "
+                        + "should return the same object.",
+                nonPrimaryOtrProfile1, nonPrimaryOtrProfile2);
     }
 
     /** Test if creating two non-primary profiles result in different objects. */
     @Test
     @LargeTest
     public void testCreatingTwoNonPrimaryProfiles() throws Exception {
-        TestThreadUtils.runOnUiThreadBlocking(() -> {
-            OTRProfileID profileID1 = new OTRProfileID("test::OTRProfile-1");
-            Profile nonPrimaryOtrProfile1 = mRegularProfile.getOffTheRecordProfile(profileID1);
+        OTRProfileID profileID1 = new OTRProfileID("test::OTRProfile-1");
+        Profile nonPrimaryOtrProfile1 = TestThreadUtils.runOnUiThreadBlocking(
+                () -> mRegularProfile.getOffTheRecordProfile(profileID1));
 
-            OTRProfileID profileID2 = new OTRProfileID("test::OTRProfile-2");
-            Profile nonPrimaryOtrProfile2 = mRegularProfile.getOffTheRecordProfile(profileID2);
+        OTRProfileID profileID2 = new OTRProfileID("test::OTRProfile-2");
+        Profile nonPrimaryOtrProfile2 = TestThreadUtils.runOnUiThreadBlocking(
+                () -> mRegularProfile.getOffTheRecordProfile(profileID2));
 
-            Assert.assertTrue(nonPrimaryOtrProfile1.isOffTheRecord());
-            Assert.assertFalse(nonPrimaryOtrProfile1.isPrimaryOTRProfile());
-            Assert.assertTrue(nonPrimaryOtrProfile1.isNativeInitialized());
-            Assert.assertTrue(mRegularProfile.hasOffTheRecordProfile(profileID1));
+        Assert.assertTrue(nonPrimaryOtrProfile1.isOffTheRecord());
+        Assert.assertFalse(nonPrimaryOtrProfile1.isPrimaryOTRProfile());
+        Assert.assertTrue(nonPrimaryOtrProfile1.isNativeInitialized());
+        Assert.assertTrue(mRegularProfile.hasOffTheRecordProfile(profileID1));
 
-            Assert.assertTrue(nonPrimaryOtrProfile2.isOffTheRecord());
-            Assert.assertFalse(nonPrimaryOtrProfile2.isPrimaryOTRProfile());
-            Assert.assertTrue(nonPrimaryOtrProfile2.isNativeInitialized());
-            Assert.assertTrue(mRegularProfile.hasOffTheRecordProfile(profileID2));
+        Assert.assertTrue(nonPrimaryOtrProfile2.isOffTheRecord());
+        Assert.assertFalse(nonPrimaryOtrProfile2.isPrimaryOTRProfile());
+        Assert.assertTrue(nonPrimaryOtrProfile2.isNativeInitialized());
+        Assert.assertTrue(mRegularProfile.hasOffTheRecordProfile(profileID2));
 
-            Assert.assertNotSame("Two calls to get non-primary OTR profile with different IDs"
-                            + "should return different objects.",
-                    nonPrimaryOtrProfile1, nonPrimaryOtrProfile2);
-        });
+        Assert.assertNotSame("Two calls to get non-primary OTR profile with different IDs"
+                        + "should return different objects.",
+                nonPrimaryOtrProfile1, nonPrimaryOtrProfile2);
     }
 
     /** Test if creating unique otr profile ids works as expected. */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java
index 8dca458..36d4f18b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTest.java
@@ -38,7 +38,6 @@
 import org.chromium.chrome.browser.permissions.PermissionTestRule.PermissionUpdateWaiter;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.settings.SettingsActivity;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.tab.Tab;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -46,6 +45,7 @@
 import org.chromium.chrome.test.util.browser.LocationSettingsTestUtil;
 import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
 import org.chromium.components.browser_ui.settings.ExpandablePreferenceGroup;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.site_settings.FourStateCookieSettingsPreference;
 import org.chromium.components.browser_ui.site_settings.FourStateCookieSettingsPreference.CookieSettingsState;
 import org.chromium.components.browser_ui.site_settings.R;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTestUtils.java b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTestUtils.java
index 85050f0..3ca4634 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTestUtils.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/site_settings/SiteSettingsTestUtils.java
@@ -9,8 +9,8 @@
 import android.support.test.InstrumentationRegistry;
 
 import org.chromium.chrome.browser.settings.SettingsActivity;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.site_settings.SingleCategorySettings;
 import org.chromium.components.browser_ui.site_settings.SingleWebsiteSettings;
 import org.chromium.components.browser_ui.site_settings.SiteSettings;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncAndServicesSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncAndServicesSettingsTest.java
index 9015642..122bed6 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncAndServicesSettingsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/SyncAndServicesSettingsTest.java
@@ -32,7 +32,6 @@
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.settings.SettingsActivity;
 import org.chromium.chrome.browser.settings.SettingsActivityTestRule;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.sync.settings.SyncAndServicesSettings;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -40,6 +39,7 @@
 import org.chromium.chrome.test.util.browser.Features.EnableFeatures;
 import org.chromium.chrome.test.util.browser.sync.SyncTestUtil;
 import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
 /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/RestoreMigrateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/RestoreMigrateTest.java
index 874eef6..154dc91 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/RestoreMigrateTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/RestoreMigrateTest.java
@@ -9,15 +9,18 @@
 
 import androidx.test.filters.SmallTest;
 
+import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import org.chromium.base.ContextUtils;
+import org.chromium.base.FileUtils;
 import org.chromium.base.StreamUtil;
 import org.chromium.base.test.UiThreadTest;
 import org.chromium.base.test.util.AdvancedMockContext;
+import org.chromium.base.test.util.Batch;
 import org.chromium.base.test.util.Feature;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
@@ -38,7 +41,10 @@
  * Test that migrating the old tab state folder structure to the new one works.
  */
 @RunWith(ChromeJUnit4ClassRunner.class)
+@Batch(Batch.UNIT_TESTS)
 public class RestoreMigrateTest {
+    private static final String TEST_DIR = "test";
+    private Context mAppContextToRestore;
     private Context mAppContext;
 
     private void writeStateFile(final TabModelSelector selector, int index) throws IOException {
@@ -73,12 +79,41 @@
 
     @Before
     public void setUp() {
-        mAppContext = new AdvancedMockContext(InstrumentationRegistry.getInstrumentation()
-                                                      .getTargetContext()
-                                                      .getApplicationContext());
+        mAppContextToRestore = ContextUtils.getApplicationContext();
+        mAppContext =
+                new AdvancedMockContextWithTestDir(InstrumentationRegistry.getInstrumentation()
+                                                           .getTargetContext()
+                                                           .getApplicationContext());
         ContextUtils.initApplicationContextForTests(mAppContext);
     }
 
+    static class AdvancedMockContextWithTestDir extends AdvancedMockContext {
+        private File mFileTestDir;
+
+        AdvancedMockContextWithTestDir(Context base) {
+            super(base);
+            mFileTestDir = new File(super.getFilesDir(), TEST_DIR);
+            mFileTestDir.mkdir();
+        }
+
+        @Override
+        public File getFilesDir() {
+            return mFileTestDir;
+        }
+    }
+
+    @After
+    public void tearDown() {
+        FileUtils.recursivelyDeleteFile(mAppContext.getFilesDir(), null);
+        FileUtils.recursivelyDeleteFile(
+                TabStateDirectory.getOrCreateTabbedModeStateDirectory(), null);
+        TabStateDirectory.resetTabbedModeStateDirectoryForTesting();
+        SharedPreferencesManager.getInstance().writeBoolean(
+                ChromePreferenceKeys.TABMODEL_HAS_RUN_FILE_MIGRATION, false);
+        TabbedModeTabPersistencePolicy.resetMigrationTaskForTesting();
+        ContextUtils.initApplicationContextForTests(mAppContextToRestore);
+    }
+
     private TabPersistentStore buildTabPersistentStore(
             final TabModelSelector selector, final int selectorIndex) {
         return TestThreadUtils.runOnUiThreadBlockingNoException(new Callable<TabPersistentStore>() {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
index 9d03941..3f21e37 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreTest.java
@@ -36,6 +36,7 @@
 import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutHelper;
 import org.chromium.chrome.browser.flags.ActivityType;
 import org.chromium.chrome.browser.fullscreen.BrowserControlsManager;
+import org.chromium.chrome.browser.metrics.LaunchCauseMetrics;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
 import org.chromium.chrome.browser.profiles.Profile;
@@ -255,6 +256,11 @@
                 }
 
                 @Override
+                protected LaunchCauseMetrics createLaunchCauseMetrics() {
+                    return null;
+                }
+
+                @Override
                 @ActivityType
                 public int getActivityType() {
                     return ActivityType.TABBED;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/HomeButtonTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/HomeButtonTest.java
index 5106ea75..a429c0c1 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/HomeButtonTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/toolbar/HomeButtonTest.java
@@ -31,9 +31,9 @@
 import org.chromium.chrome.browser.homepage.HomepageManager;
 import org.chromium.chrome.browser.homepage.HomepageTestRule;
 import org.chromium.chrome.browser.homepage.settings.HomepageSettings;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 import org.chromium.ui.test.util.DummyUiActivityTestCase;
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tracing/settings/TracingSettingsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tracing/settings/TracingSettingsTest.java
index 1051d386..8dfcd4e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tracing/settings/TracingSettingsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tracing/settings/TracingSettingsTest.java
@@ -39,7 +39,6 @@
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.settings.SettingsActivity;
 import org.chromium.chrome.browser.settings.SettingsActivityTestRule;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.tracing.TracingController;
 import org.chromium.chrome.browser.tracing.TracingNotificationManager;
@@ -47,6 +46,7 @@
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.components.browser_ui.notifications.MockNotificationManagerProxy;
 import org.chromium.components.browser_ui.settings.ButtonPreference;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.settings.TextMessagePreference;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
diff --git a/chrome/app/app-Info.plist b/chrome/app/app-Info.plist
index b52af98..76b7c1b 100644
--- a/chrome/app/app-Info.plist
+++ b/chrome/app/app-Info.plist
@@ -53,7 +53,7 @@
 			<string>Viewer</string>
 			<key>LSItemContentTypes</key>
 			<array>
-				<string>com.netscape.javascript-​source</string>
+				<string>com.netscape.javascript-source</string>
 			</array>
 		</dict>
 		<dict>
diff --git a/chrome/app/global_media_controls_strings.grdp b/chrome/app/global_media_controls_strings.grdp
index 271a6c8..59caf85a 100644
--- a/chrome/app/global_media_controls_strings.grdp
+++ b/chrome/app/global_media_controls_strings.grdp
@@ -22,4 +22,7 @@
   <message name="IDS_GLOBAL_MEDIA_CONTROLS_LIVE_CAPTION_DOWNLOAD_PROGRESS" desc="Download progress indicator after Live Caption is enabled. The user needs to download certain files for the feature to work.">
     Downloading... <ph name="PERCENT">$1<ex>17</ex></ph>%
   </message>
+  <message name="IDS_GLOBAL_MEDIA_CONTROLS_LIVE_CAPTION_DOWNLOAD_ERROR" desc="Download progress indicator after Live Caption is enabled. The user needs to download certain files for the feature to work.">
+    Can't download speech files. Try again later.
+  </message>
 </grit-part>
diff --git a/chrome/app/global_media_controls_strings_grdp/IDS_GLOBAL_MEDIA_CONTROLS_LIVE_CAPTION_DOWNLOAD_ERROR.png.sha1 b/chrome/app/global_media_controls_strings_grdp/IDS_GLOBAL_MEDIA_CONTROLS_LIVE_CAPTION_DOWNLOAD_ERROR.png.sha1
new file mode 100644
index 0000000..c811298
--- /dev/null
+++ b/chrome/app/global_media_controls_strings_grdp/IDS_GLOBAL_MEDIA_CONTROLS_LIVE_CAPTION_DOWNLOAD_ERROR.png.sha1
@@ -0,0 +1 @@
+bd1c5dba946a95db5273f4298c943fb30da09848
\ No newline at end of file
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp
index a77b92f..a81a7d8 100644
--- a/chrome/app/settings_strings.grdp
+++ b/chrome/app/settings_strings.grdp
@@ -63,10 +63,10 @@
     Downloading speech recognition files... <ph name="PERCENT">$1<ex>17</ex></ph>%
   </message>
   <message name="IDS_SETTINGS_CAPTIONS_LIVE_CAPTION_DOWNLOAD_COMPLETE" desc="Success message when Live Caption files have completed downloading.">
-    Speech recognition files downloaded
+    Speech files downloaded
   </message>
   <message name="IDS_SETTINGS_CAPTIONS_LIVE_CAPTION_DOWNLOAD_ERROR" desc="Error message when Live Caption files can’t be downloaded.">
-    The required files can't be downloaded. Try again later.
+    Can't download speech files. Try again later.
   </message>
   <message name="IDS_SETTINGS_ENABLE_CARET_BROWSING_TITLE" desc="Name of the setting to enable Caret Browsing, which allows you to move around any web page using a text caret.">
     Navigate pages with a text cursor
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_CAPTIONS_LIVE_CAPTION_DOWNLOAD_COMPLETE.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_CAPTIONS_LIVE_CAPTION_DOWNLOAD_COMPLETE.png.sha1
index 08b5d027..038a659 100644
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_CAPTIONS_LIVE_CAPTION_DOWNLOAD_COMPLETE.png.sha1
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_CAPTIONS_LIVE_CAPTION_DOWNLOAD_COMPLETE.png.sha1
@@ -1 +1 @@
-edd696d0dbddbda2d581b1f9f5f9ae1b3251744b
\ No newline at end of file
+9764dae2056c40ebc3b8dfc25f86ce4fc237b9a9
\ No newline at end of file
diff --git a/chrome/app/settings_strings_grdp/IDS_SETTINGS_CAPTIONS_LIVE_CAPTION_DOWNLOAD_ERROR.png.sha1 b/chrome/app/settings_strings_grdp/IDS_SETTINGS_CAPTIONS_LIVE_CAPTION_DOWNLOAD_ERROR.png.sha1
index 6bdebe1..f92ee07 100644
--- a/chrome/app/settings_strings_grdp/IDS_SETTINGS_CAPTIONS_LIVE_CAPTION_DOWNLOAD_ERROR.png.sha1
+++ b/chrome/app/settings_strings_grdp/IDS_SETTINGS_CAPTIONS_LIVE_CAPTION_DOWNLOAD_ERROR.png.sha1
@@ -1 +1 @@
-de2d4b5a1c4e38d959600ecf346cd349b992f1c5
\ No newline at end of file
+0d66a691ee919d120d9edc83caeb17079b8f4bab
\ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index b37fd092..863f0d67 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -3852,6 +3852,10 @@
      flag_descriptions::kMagnifierNewFocusFollowingName,
      flag_descriptions::kMagnifierNewFocusFollowingDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(features::kMagnifierNewFocusFollowing)},
+    {"enable-magnifier-panning-improvements",
+     flag_descriptions::kMagnifierPanningImprovementsName,
+     flag_descriptions::kMagnifierPanningImprovementsDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(features::kMagnifierPanningImprovements)},
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 #if defined(OS_MAC)
     {"enable-immersive-fullscreen-toolbar",
@@ -4706,17 +4710,6 @@
          kEnableWebAuthenticationChromeOSAuthenticatorDescription,
      kOsCrOS, FEATURE_VALUE_TYPE(device::kWebAuthCrosPlatformAuthenticator)},
 #endif
-
-    {"use-preferred-interval-for-video",
-     flag_descriptions::kUsePreferredIntervalForVideoName,
-     flag_descriptions::kUsePreferredIntervalForVideoDescription, kOsDesktop,
-     FEATURE_VALUE_TYPE(features::kUsePreferredIntervalForVideo)},
-
-    {"force-preferred-interval-for-video",
-     flag_descriptions::kForcePreferredIntervalForVideoName,
-     flag_descriptions::kForcePreferredIntervalForVideoDescription, kOsDesktop,
-     FEATURE_VALUE_TYPE(features::kForcePreferredIntervalForVideo)},
-
 #if BUILDFLAG(ENABLE_PDF)
     {"accessible-pdf-form", flag_descriptions::kAccessiblePDFFormName,
      flag_descriptions::kAccessiblePDFFormDescription, kOsDesktop,
diff --git a/chrome/browser/android/bookmarks/bookmark_bridge.cc b/chrome/browser/android/bookmarks/bookmark_bridge.cc
index 048b4ce7..52ef5096 100644
--- a/chrome/browser/android/bookmarks/bookmark_bridge.cc
+++ b/chrome/browser/android/bookmarks/bookmark_bridge.cc
@@ -828,9 +828,8 @@
   const BookmarkNode* node = reading_list_manager_->Add(
       GURL(base::android::ConvertJavaStringToUTF16(env, j_url)),
       base::android::ConvertJavaStringToUTF8(env, j_title));
-  return node ? JavaBookmarkIdCreateBookmarkId(env, node->id(),
-                                               GetBookmarkType(node))
-              : ScopedJavaLocalRef<jobject>();
+  DCHECK(node);
+  return JavaBookmarkIdCreateBookmarkId(env, node->id(), GetBookmarkType(node));
 }
 
 ScopedJavaLocalRef<jobject> BookmarkBridge::GetReadingListItem(
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 117da8a..4a4a810 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -4922,20 +4922,18 @@
 bool ChromeContentBrowserClient::WillCreateRestrictedCookieManager(
     network::mojom::RestrictedCookieManagerRole role,
     content::BrowserContext* browser_context,
-    const url::Origin& origin,
-    const net::SiteForCookies& site_for_cookies,
-    const url::Origin& top_frame_origin,
+    const net::IsolationInfo& isolation_info,
     bool is_service_worker,
     int process_id,
     int routing_id,
     mojo::PendingReceiver<network::mojom::RestrictedCookieManager>* receiver) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 #if BUILDFLAG(ENABLE_EXTENSIONS)
-  if (origin.scheme() == extensions::kExtensionScheme) {
+  DCHECK(isolation_info.frame_origin());
+  if (isolation_info.frame_origin()->scheme() == extensions::kExtensionScheme) {
     DCHECK_EQ(network::mojom::RestrictedCookieManagerRole::SCRIPT, role);
     extensions::ChromeExtensionCookies::Get(browser_context)
-        ->CreateRestrictedCookieManager(origin, site_for_cookies,
-                                        top_frame_origin, std::move(*receiver));
+        ->CreateRestrictedCookieManager(isolation_info, std::move(*receiver));
     return true;
   }
 #endif
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h
index 8b59398..3ef2329 100644
--- a/chrome/browser/chrome_content_browser_client.h
+++ b/chrome/browser/chrome_content_browser_client.h
@@ -93,6 +93,10 @@
 enum class Channel;
 }
 
+namespace net {
+class IsolationInfo;
+}
+
 class ChromeBluetoothDelegate;
 class ChromeFontAccessDelegate;
 class ChromeHidDelegate;
@@ -517,9 +521,7 @@
   bool WillCreateRestrictedCookieManager(
       network::mojom::RestrictedCookieManagerRole role,
       content::BrowserContext* browser_context,
-      const url::Origin& origin,
-      const net::SiteForCookies& site_for_cookies,
-      const url::Origin& top_frame_origin,
+      const net::IsolationInfo& isolation_info,
       bool is_service_worker,
       int process_id,
       int routing_id,
diff --git a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_apitest.cc b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_apitest.cc
index b48279c..37c4ffb 100644
--- a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_apitest.cc
+++ b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_apitest.cc
@@ -9,6 +9,7 @@
 #include "base/files/scoped_temp_dir.h"
 #include "base/macros.h"
 #include "base/threading/thread_restrictions.h"
+#include "components/version_info/version_info.h"
 #include "content/public/test/browser_test.h"
 #include "extensions/common/features/feature_channel.h"
 #include "net/dns/mock_host_resolver.h"
diff --git a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc
index 036bc55..cf04b335 100644
--- a/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc
+++ b/chrome/browser/extensions/chrome_content_browser_client_extensions_part.cc
@@ -63,7 +63,6 @@
 #include "extensions/browser/view_type_utils.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension_urls.h"
-#include "extensions/common/extensions_client.h"
 #include "extensions/common/manifest_constants.h"
 #include "extensions/common/manifest_handlers/app_isolation_info.h"
 #include "extensions/common/manifest_handlers/background_info.h"
@@ -642,11 +641,8 @@
   host->AddFilter(new ChromeExtensionMessageFilter(profile));
   host->AddFilter(new ExtensionMessageFilter(id, profile));
   host->AddFilter(new ExtensionsGuestViewMessageFilter(id, profile));
-  if (extensions::ExtensionsClient::Get()
-          ->ExtensionAPIEnabledInExtensionServiceWorkers()) {
-    host->AddFilter(new ExtensionServiceWorkerMessageFilter(
-        id, profile, host->GetStoragePartition()->GetServiceWorkerContext()));
-  }
+  host->AddFilter(new ExtensionServiceWorkerMessageFilter(
+      id, profile, host->GetStoragePartition()->GetServiceWorkerContext()));
 }
 
 void ChromeContentBrowserClientExtensionsPart::SiteInstanceGotProcess(
diff --git a/chrome/browser/extensions/chrome_extension_cookies.cc b/chrome/browser/extensions/chrome_extension_cookies.cc
index 5ae0f2a..08e6018 100644
--- a/chrome/browser/extensions/chrome_extension_cookies.cc
+++ b/chrome/browser/extensions/chrome_extension_cookies.cc
@@ -60,9 +60,7 @@
 }
 
 void ChromeExtensionCookies::CreateRestrictedCookieManager(
-    const url::Origin& origin,
-    const net::SiteForCookies& site_for_cookies,
-    const url::Origin& top_frame_origin,
+    const net::IsolationInfo& isolation_info,
     mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!io_data_)
@@ -70,10 +68,9 @@
 
   // Safe since |io_data_| is non-null so no IOData deletion is queued.
   content::GetIOThreadTaskRunner({})->PostTask(
-      FROM_HERE,
-      base::BindOnce(&IOData::CreateRestrictedCookieManager,
-                     base::Unretained(io_data_.get()), origin, site_for_cookies,
-                     top_frame_origin, std::move(receiver)));
+      FROM_HERE, base::BindOnce(&IOData::CreateRestrictedCookieManager,
+                                base::Unretained(io_data_.get()),
+                                isolation_info, std::move(receiver)));
 }
 
 void ChromeExtensionCookies::ClearCookies(const GURL& origin) {
@@ -110,17 +107,14 @@
 }
 
 void ChromeExtensionCookies::IOData::CreateRestrictedCookieManager(
-    const url::Origin& origin,
-    const net::SiteForCookies& site_for_cookies,
-    const url::Origin& top_frame_origin,
+    const net::IsolationInfo& isolation_info,
     mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
   restricted_cookie_managers_.Add(
       std::make_unique<network::RestrictedCookieManager>(
           network::mojom::RestrictedCookieManagerRole::SCRIPT,
-          GetOrCreateCookieStore(), &network_cookie_settings_, origin,
-          site_for_cookies, top_frame_origin,
+          GetOrCreateCookieStore(), &network_cookie_settings_, isolation_info,
           /* null cookies_observer disables logging */
           mojo::NullRemote()),
       std::move(receiver));
diff --git a/chrome/browser/extensions/chrome_extension_cookies.h b/chrome/browser/extensions/chrome_extension_cookies.h
index 882072b9..384ca39 100644
--- a/chrome/browser/extensions/chrome_extension_cookies.h
+++ b/chrome/browser/extensions/chrome_extension_cookies.h
@@ -28,10 +28,7 @@
 
 namespace net {
 class CookieStore;
-}
-
-namespace url {
-class Origin;
+class IsolationInfo;
 }
 
 namespace extensions {
@@ -51,9 +48,7 @@
   // with origin |origin|, bound to |receiver|. Whether this will use disk
   // storage or not depends on the Profile |this| was created for.
   void CreateRestrictedCookieManager(
-      const url::Origin& origin,
-      const net::SiteForCookies& site_for_cookies,
-      const url::Origin& top_frame_origin,
+      const net::IsolationInfo& isolation_info,
       mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver);
 
   // Deletes all cookies matching the host of |origin|.
@@ -75,9 +70,7 @@
     ~IOData();
 
     void CreateRestrictedCookieManager(
-        const url::Origin& origin,
-        const net::SiteForCookies& site_for_cookies,
-        const url::Origin& top_frame_origin,
+        const net::IsolationInfo& isolation_info,
         mojo::PendingReceiver<network::mojom::RestrictedCookieManager>
             receiver);
     void ClearCookies(const GURL& origin);
diff --git a/chrome/browser/extensions/extension_service.h b/chrome/browser/extensions/extension_service.h
index c26ef4b..9927e544 100644
--- a/chrome/browser/extensions/extension_service.h
+++ b/chrome/browser/extensions/extension_service.h
@@ -732,6 +732,8 @@
                            ManagementPolicyProhibitsEnableOnInstalled);
   FRIEND_TEST_ALL_PREFIXES(ExtensionServiceTest,
                            BlockAndUnblockBlocklistedExtension);
+  FRIEND_TEST_ALL_PREFIXES(ExtensionServiceTest,
+                           CanAddDisableReasonToBlocklistedExtension);
   FRIEND_TEST_ALL_PREFIXES(::BlocklistedExtensionSyncServiceTest,
                            SyncBlocklistedExtension);
   friend class ::BlocklistedExtensionSyncServiceTest;
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index c1a2cb5..0ec2fbc4 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -4838,6 +4838,56 @@
   EXPECT_FALSE(prefs->IsExtensionBlocklisted(good_crx));
 }
 
+TEST_F(ExtensionServiceTest, CanAddDisableReasonToBlocklistedExtension) {
+  InitializeGoodInstalledExtensionService();
+  ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
+  TestBlocklist blocklist;
+
+  blocklist.Attach(service()->blocklist_);
+  service()->Init();
+
+  blocklist.SetBlocklistState(good0, BLOCKLISTED_MALWARE, true);
+  blocklist.SetBlocklistState(good1, BLOCKLISTED_MALWARE, true);
+  content::RunAllTasksUntilIdle();
+  EXPECT_TRUE(prefs->IsExtensionBlocklisted(good0));
+  EXPECT_TRUE(prefs->IsExtensionBlocklisted(good1));
+
+  // Test that a disable reason can be added to a blocklisted extension.
+  prefs->AddDisableReason(good0, disable_reason::DISABLE_REMOTELY_FOR_MALWARE);
+  EXPECT_TRUE(prefs->HasDisableReason(
+      good0, disable_reason::DISABLE_REMOTELY_FOR_MALWARE));
+
+  // Test that a blocklisted extension can be disabled.
+  service()->DisableExtension(good1, disable_reason::DISABLE_BLOCKED_BY_POLICY);
+  EXPECT_TRUE(prefs->HasDisableReason(
+      good1, disable_reason::DISABLE_BLOCKED_BY_POLICY));
+  EXPECT_TRUE(prefs->IsExtensionBlocklisted(good1));
+  // Even though the extension was disabled with a new disable reason, it should
+  // remain in the blocklisted set (which can't be re-enabled by the user).
+  EXPECT_TRUE(registry()->blocklisted_extensions().Contains(good1));
+  // Since the extension is blocklisted, it should not be in the disabled set.
+  EXPECT_FALSE(registry()->disabled_extensions().Contains(good1));
+
+  // Extensions should remain in the appropriate sets after being reloaded (as
+  // in a profile restart).
+  service()->ReloadExtensionsForTest();
+  EXPECT_TRUE(prefs->HasDisableReason(
+      good1, disable_reason::DISABLE_BLOCKED_BY_POLICY));
+  EXPECT_TRUE(prefs->IsExtensionBlocklisted(good1));
+  EXPECT_TRUE(registry()->blocklisted_extensions().Contains(good1));
+  EXPECT_FALSE(registry()->disabled_extensions().Contains(good1));
+
+  // Test that the extension is disabled when unblocklisted.
+  blocklist.SetBlocklistState(good1, NOT_BLOCKLISTED, true);
+  content::RunAllTasksUntilIdle();
+  EXPECT_FALSE(prefs->IsExtensionBlocklisted(good1));
+  EXPECT_TRUE(prefs->IsExtensionDisabled(good1));
+  EXPECT_FALSE(registry()->blocklisted_extensions().Contains(good1));
+  EXPECT_TRUE(registry()->disabled_extensions().Contains(good1));
+  EXPECT_TRUE(prefs->HasDisableReason(
+      good1, disable_reason::DISABLE_BLOCKED_BY_POLICY));
+}
+
 TEST_F(ExtensionServiceTest, TerminateExtension) {
   InitializeEmptyExtensionService();
 
diff --git a/chrome/browser/extensions/updater/extension_updater_unittest.cc b/chrome/browser/extensions/updater/extension_updater_unittest.cc
index 14d301c..3fb048f 100644
--- a/chrome/browser/extensions/updater/extension_updater_unittest.cc
+++ b/chrome/browser/extensions/updater/extension_updater_unittest.cc
@@ -56,6 +56,7 @@
 #include "content/public/browser/notification_source.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/test_utils.h"
+#include "extensions/browser/blocklist_state.h"
 #include "extensions/browser/disable_reason.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registry.h"
@@ -2685,6 +2686,8 @@
   ASSERT_EQ(1u, enabled_extensions.size());
   ASSERT_EQ(2u, blocklisted_extensions.size());
   const std::string& remotely_blocklisted_id = blocklisted_extensions[0]->id();
+  service.extension_prefs()->SetExtensionBlocklistState(remotely_blocklisted_id,
+                                                        BLOCKLISTED_MALWARE);
   service.extension_prefs()->AddDisableReason(
       remotely_blocklisted_id, disable_reason::DISABLE_REMOTELY_FOR_MALWARE);
 
diff --git a/chrome/browser/federated_learning/floc_origin_trial_browsertest.cc b/chrome/browser/federated_learning/floc_origin_trial_browsertest.cc
index 0ba1ae4..b185b18 100644
--- a/chrome/browser/federated_learning/floc_origin_trial_browsertest.cc
+++ b/chrome/browser/federated_learning/floc_origin_trial_browsertest.cc
@@ -21,7 +21,10 @@
 
 class FlocOriginTrialBrowserTest : public InProcessBrowserTest {
  public:
-  FlocOriginTrialBrowserTest() = default;
+  FlocOriginTrialBrowserTest() {
+    scoped_feature_list_.InitAndEnableFeature(
+        blink::features::kInterestCohortAPIOriginTrial);
+  }
 
   void SetUpOnMainThread() override {
     InProcessBrowserTest::SetUpOnMainThread();
@@ -71,6 +74,9 @@
     return browser()->tab_strip_model()->GetActiveWebContents();
   }
 
+ protected:
+  base::test::ScopedFeatureList scoped_feature_list_;
+
  private:
   std::unique_ptr<content::URLLoaderInterceptor> url_loader_interceptor_;
 };
@@ -87,4 +93,23 @@
   EXPECT_FALSE(HasInterestCohortApi(web_contents()));
 }
 
+class FlocOriginTrialBrowserTestBaseFeatureDisabled
+    : public FlocOriginTrialBrowserTest {
+ public:
+  FlocOriginTrialBrowserTestBaseFeatureDisabled() {
+    scoped_feature_list_.Reset();
+    scoped_feature_list_.InitAndDisableFeature(
+        blink::features::kInterestCohortAPIOriginTrial);
+  }
+};
+
+IN_PROC_BROWSER_TEST_F(FlocOriginTrialBrowserTestBaseFeatureDisabled,
+                       OriginTrialEnabled) {
+  ui_test_utils::NavigateToURL(browser(), OriginTrialEnabledURL());
+
+  // If the base::Feature is disabled, the OT / API is disabled regardless of
+  // the OT config.
+  EXPECT_FALSE(HasInterestCohortApi(web_contents()));
+}
+
 }  // namespace federated_learning
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index a5b82f04..8f06224e 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -1861,6 +1861,11 @@
     "expiry_milestone": 88
   },
   {
+    "name": "enable-magnifier-panning-improvements",
+    "owners": [ "josiahk", "//ui/accessibility/OWNERS" ],
+    "expiry_milestone": 91
+  },
+  {
     "name": "enable-mark-http-as",
     "owners": [ "cthomp", "estark" ],
     "expiry_milestone": 86
@@ -2730,11 +2735,6 @@
     "expiry_milestone": 90
   },
   {
-    "name": "force-preferred-interval-for-video",
-    "owners": [ "khushalsagar" ],
-    "expiry_milestone": 89
-  },
-  {
     "name": "force-secure-payment-confirmation-dialog",
     "owners": [ "//components/payments/OWNERS" ],
     "expiry_milestone": 90
@@ -4887,11 +4887,6 @@
     "expiry_milestone": 90
   },
   {
-    "name": "use-preferred-interval-for-video",
-    "owners": [ "jiahe.zhang@intel.com", "khushalsagar" ],
-    "expiry_milestone": 85
-  },
-  {
     "name": "use-search-click-for-right-click",
     "owners": [ "zentaro", "cros-peripherals@google.com" ],
     "expiry_milestone": 95
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index b6ab4612..8be99d37 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -432,12 +432,6 @@
     "Forces Chrome to use a specific color profile instead of the color "
     "of the window's current monitor, as specified by the operating system.";
 
-const char kForcePreferredIntervalForVideoName[] =
-    "Force preferred interval for video";
-const char kForcePreferredIntervalForVideoDescription[] =
-    "When enabled, the composition rate is reduced to match the video playback "
-    "rate irrespective of the update frequency of other page content";
-
 const char kDynamicColorGamutName[] = "Dynamic color gamut";
 const char kDynamicColorGamutDescription[] =
     "Displays in wide color when the content is wide. When the content is "
@@ -2432,12 +2426,6 @@
     "flows where a user has to type username first on one page and then "
     "password on another page";
 
-const char kUsePreferredIntervalForVideoName[] =
-    "Use preferred interval for video";
-const char kUsePreferredIntervalForVideoDescription[] =
-    "When enabled, the composition rate will be changed based on the videos' "
-    "actual fps.";
-
 const char kUseSearchClickForRightClickName[] =
     "Use Search+Click for right click";
 const char kUseSearchClickForRightClickDescription[] =
@@ -4239,6 +4227,12 @@
     "Enable feature which allows more comprehensive focus following in"
     "in Magnifier.";
 
+const char kMagnifierPanningImprovementsName[] =
+    "Enable panning improvements in magnifier";
+const char kMagnifierPanningImprovementsDescription[] =
+    "Enable feature which adds additional mouse and keyboard panning "
+    "functionality in Magnifier.";
+
 const char kFilesAppCopyImageName[] = "Enable Copy Images from Files App";
 const char kFilesAppCopyImageDescription[] =
     "Enables the Files App to copy images selected to the system clipboard";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 9c807ac..40fbe6c 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -278,9 +278,6 @@
 extern const char kForceColorProfileName[];
 extern const char kForceColorProfileDescription[];
 
-extern const char kForcePreferredIntervalForVideoName[];
-extern const char kForcePreferredIntervalForVideoDescription[];
-
 extern const char kDynamicColorGamutName[];
 extern const char kDynamicColorGamutDescription[];
 
@@ -1409,9 +1406,6 @@
 extern const char kUseFirstPartySetName[];
 extern const char kUseFirstPartySetDescription[];
 
-extern const char kUsePreferredIntervalForVideoName[];
-extern const char kUsePreferredIntervalForVideoDescription[];
-
 extern const char kUseSearchClickForRightClickName[];
 extern const char kUseSearchClickForRightClickDescription[];
 
@@ -2476,6 +2470,9 @@
 extern const char kMagnifierNewFocusFollowingName[];
 extern const char kMagnifierNewFocusFollowingDescription[];
 
+extern const char kMagnifierPanningImprovementsName[];
+extern const char kMagnifierPanningImprovementsDescription[];
+
 extern const char kFilesAppCopyImageName[];
 extern const char kFilesAppCopyImageDescription[];
 
diff --git a/chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_browsertest.cc b/chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_browsertest.cc
index 5e951f6a..884a1c71 100644
--- a/chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_browsertest.cc
+++ b/chrome/browser/guest_view/mime_handler_view/chrome_mime_handler_view_browsertest.cc
@@ -62,10 +62,6 @@
 using guest_view::TestGuestViewManager;
 using guest_view::TestGuestViewManagerFactory;
 
-namespace {
-constexpr char kTestExtensionId[] = "oickdpebdnfbgkcaoklfcdhjniefkcji";
-}
-
 // Note: This file contains several old WebViewGuest tests which were for
 // certain BrowserPlugin features and no longer made sense for the new
 // WebViewGuest which is based on cross-process frames. Since
@@ -123,7 +119,8 @@
     const extensions::Extension* extension =
         LoadExtension(test_data_dir_.AppendASCII("mime_handler_view"));
     ASSERT_TRUE(extension);
-    CHECK_EQ(kTestExtensionId, extension->id());
+    ASSERT_EQ(std::string(extension_misc::kMimeHandlerPrivateTestExtensionId),
+              extension->id());
 
     extensions::ResultCatcher catcher;
     ui_test_utils::NavigateToURL(browser(), url);
@@ -156,11 +153,13 @@
     transferrable_loader->head->mime_type = "application/pdf";
     transferrable_loader->head->headers =
         base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/2 200 OK");
+    const std::string extension_id =
+        extension_misc::kMimeHandlerPrivateTestExtensionId;
     return std::make_unique<extensions::StreamContainer>(
         0 /* tab_id */, false /* embedded */,
-        GURL(std::string(extensions::kExtensionScheme) +
-             kTestExtensionId) /* handler_url */,
-        kTestExtensionId, std::move(transferrable_loader), url);
+        extensions::Extension::GetBaseURLFromExtensionId(
+            extension_id) /* handler_url */,
+        extension_id, std::move(transferrable_loader), url);
   }
 
  private:
diff --git a/chrome/browser/nearby_sharing/nearby_share_metrics_logger.cc b/chrome/browser/nearby_sharing/nearby_share_metrics_logger.cc
index c5b99098..93686b2 100644
--- a/chrome/browser/nearby_sharing/nearby_share_metrics_logger.cc
+++ b/chrome/browser/nearby_sharing/nearby_share_metrics_logger.cc
@@ -367,7 +367,7 @@
 
   const std::string prefix = "Nearby.Share.Transfer.FinalStatus";
   base::UmaHistogramEnumeration(prefix, final_status);
-  base::UmaHistogramEnumeration(
-      prefix + send_or_receive + share_target_type + contact_or_not,
-      final_status);
+  base::UmaHistogramEnumeration(prefix + send_or_receive, final_status);
+  base::UmaHistogramEnumeration(prefix + share_target_type, final_status);
+  base::UmaHistogramEnumeration(prefix + contact_or_not, final_status);
 }
diff --git a/chrome/browser/paint_preview/paint_preview_browsertest.cc b/chrome/browser/paint_preview/paint_preview_browsertest.cc
index 84be6cb..5ea42d8b 100644
--- a/chrome/browser/paint_preview/paint_preview_browsertest.cc
+++ b/chrome/browser/paint_preview/paint_preview_browsertest.cc
@@ -45,11 +45,16 @@
   NoOpPaintPreviewRecorder(const NoOpPaintPreviewRecorder&) = delete;
   NoOpPaintPreviewRecorder& operator=(const NoOpPaintPreviewRecorder&) = delete;
 
+  void SetRequestedClosure(base::OnceClosure requested) {
+    requested_ = std::move(requested);
+  }
+
   void CapturePaintPreview(
       mojom::PaintPreviewCaptureParamsPtr params,
       mojom::PaintPreviewRecorder::CapturePaintPreviewCallback callback)
       override {
     callback_ = std::move(callback);
+    std::move(requested_).Run();
   }
 
   void BindRequest(mojo::ScopedInterfaceEndpointHandle handle) {
@@ -58,6 +63,7 @@
   }
 
  private:
+  base::OnceClosure requested_;
   mojom::PaintPreviewRecorder::CapturePaintPreviewCallback callback_;
   mojo::AssociatedReceiver<mojom::PaintPreviewRecorder> binding_{this};
 };
@@ -384,7 +390,9 @@
   content::WebContents* web_contents = GetWebContents();
 
   // Override remote interfaces with a no-op.
+  base::RunLoop started_loop;
   NoOpPaintPreviewRecorder noop_recorder;
+  noop_recorder.SetRequestedClosure(started_loop.QuitClosure());
   OverrideInterface(&noop_recorder);
 
   CreateClient();
@@ -395,7 +403,7 @@
 
   // A callback that causes the frame to reload and end up in an invalid state
   // if it is allowed to run during crash handling.
-  base::RunLoop loop;
+  base::RunLoop finished_loop;
   auto params = MakeParams();
   bool did_run = false;
   client->CapturePaintPreview(
@@ -414,7 +422,13 @@
             *did_run_ptr = true;
           },
           web_contents, &did_run)
-          .Then(loop.QuitClosure()));
+          .Then(finished_loop.QuitClosure()));
+  // Wait for the request to execute before crashing the renderer. Otherwise in
+  // the FileSystem variant it is possible there will be a race during creation
+  // of the file with the renderer crash. If this happens the callback for
+  // `finished_loop` will not be run as no request to capture succeeded leading
+  // to a timeout.
+  started_loop.Run();
 
   // Crash the renderer.
   content::RenderProcessHost* process =
@@ -427,7 +441,7 @@
   // The browser would have crashed before the loop exited if the callback was
   // not posted.
   if (!did_run)
-    loop.Run();
+    finished_loop.Run();
 
   // Now navigate away and ensure that the frame unloads successfully.
   LoadPage(http_server_.GetURL("a.com", "/title2.html"));
diff --git a/chrome/browser/password_check/android/BUILD.gn b/chrome/browser/password_check/android/BUILD.gn
index bb6bf3b..52b5cc1 100644
--- a/chrome/browser/password_check/android/BUILD.gn
+++ b/chrome/browser/password_check/android/BUILD.gn
@@ -89,6 +89,7 @@
     "//chrome/browser/password_check/android:public_java",
     "//chrome/browser/settings:java",
     "//chrome/test/android:chrome_java_test_support",
+    "//components/browser_ui/settings/android:java",
     "//third_party/android_deps:androidx_appcompat_appcompat_java",
     "//third_party/hamcrest:hamcrest_java",
     "//third_party/junit",
diff --git a/chrome/browser/password_check/android/internal/BUILD.gn b/chrome/browser/password_check/android/internal/BUILD.gn
index 56b0f11..02b2a55a 100644
--- a/chrome/browser/password_check/android/internal/BUILD.gn
+++ b/chrome/browser/password_check/android/internal/BUILD.gn
@@ -15,6 +15,7 @@
   # These deps will be inherited by the resulting android_library target.
   deps = [
     "//chrome/browser/settings:java",
+    "//components/browser_ui/settings/android:java",
     _public_target,
   ]
 
@@ -28,6 +29,7 @@
     ":internal_java",
     "//chrome/browser/flags:java",
     "//chrome/browser/settings:java",
+    "//components/browser_ui/settings/android:java",
     "//third_party/android_deps:androidx_annotation_annotation_java",
     _public_target,
   ]
@@ -41,6 +43,7 @@
   deps = [
     "//chrome/browser/feedback/android:java",
     "//chrome/browser/settings:java",
+    "//components/browser_ui/settings/android:java",
     "//third_party/android_deps:androidx_fragment_fragment_java",
     "//third_party/android_deps:androidx_preference_preference_java",
     _public_ui_target,
@@ -53,6 +56,7 @@
     ":internal_java",
     "//chrome/browser/feedback/android:java",
     "//chrome/browser/settings:java",
+    "//components/browser_ui/settings/android:java",
     "//third_party/android_deps:androidx_annotation_annotation_java",
     _public_target,
     _public_ui_target,
@@ -75,6 +79,7 @@
     "//chrome/browser/settings:java",
     "//chrome/browser/ui/android/favicon:java",
     "//chrome/browser/ui/android/strings:ui_strings_grd",
+    "//components/browser_ui/settings/android:java",
     "//components/browser_ui/strings/android:browser_ui_strings_grd",
     "//components/browser_ui/styles/android:java_resources",
     "//components/browser_ui/widget/android:java",
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckComponentUiFactory.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckComponentUiFactory.java
index 422ca9f..a440e417 100644
--- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckComponentUiFactory.java
+++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckComponentUiFactory.java
@@ -10,7 +10,7 @@
 import org.chromium.chrome.browser.feedback.HelpAndFeedbackLauncher;
 import org.chromium.chrome.browser.password_check.PasswordCheckComponentUi.CustomTabIntentHelper;
 import org.chromium.chrome.browser.password_check.PasswordCheckComponentUi.TrustedIntentHelper;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 
 /**
  * Use {@link #create()} to instantiate a {@link PasswordCheckComponentUi}.
@@ -53,4 +53,4 @@
     static void setCreationStrategy(CreationStrategy creationStrategy) {
         sCreationStrategy = creationStrategy;
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckCoordinator.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckCoordinator.java
index 2e09728..50cc2d2 100644
--- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckCoordinator.java
+++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckCoordinator.java
@@ -15,7 +15,7 @@
 import org.chromium.chrome.browser.password_check.helper.PasswordCheckReauthenticationHelper;
 import org.chromium.chrome.browser.password_check.internal.R;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.favicon.LargeIconBridge;
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckFactory.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckFactory.java
index 61058c3..8ecc130 100644
--- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckFactory.java
+++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckFactory.java
@@ -7,7 +7,7 @@
 import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
-import org.chromium.chrome.browser.settings.SettingsLauncher;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 
 /**
  * Use {@link #getOrCreate()} to instantiate a {@link PasswordCheckImpl}
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckImpl.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckImpl.java
index bd720d2..424dda6 100644
--- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckImpl.java
+++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckImpl.java
@@ -10,7 +10,7 @@
 
 import org.chromium.base.ObserverList;
 import org.chromium.chrome.browser.password_check.PasswordCheckBridge.PasswordCheckObserver;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 
 /**
  * This class is responsible for managing the saved passwords check for signed-in users.
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java
index 1881aab..9911446 100644
--- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java
+++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/PasswordCheckMediator.java
@@ -33,7 +33,7 @@
 import org.chromium.chrome.browser.password_check.helper.PasswordCheckIconHelper;
 import org.chromium.chrome.browser.password_check.helper.PasswordCheckReauthenticationHelper;
 import org.chromium.chrome.browser.password_check.helper.PasswordCheckReauthenticationHelper.ReauthReason;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 import org.chromium.ui.modelutil.ListModel;
 import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
diff --git a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/helper/PasswordCheckChangePasswordHelper.java b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/helper/PasswordCheckChangePasswordHelper.java
index 17dbad5f..5283757 100644
--- a/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/helper/PasswordCheckChangePasswordHelper.java
+++ b/chrome/browser/password_check/android/internal/java/src/org/chromium/chrome/browser/password_check/helper/PasswordCheckChangePasswordHelper.java
@@ -16,7 +16,7 @@
 import org.chromium.chrome.browser.password_check.CompromisedCredential;
 import org.chromium.chrome.browser.password_check.PasswordCheckComponentUi;
 import org.chromium.chrome.browser.password_check.PasswordCheckEditFragmentView;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 
 import java.util.Objects;
 
@@ -134,4 +134,4 @@
         // TODO(crbug.com/1086114): Also add the following parameters when server side changes is
         // ready: CALLER, SOURCE. That would be useful for metrics.
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckEditViewTest.java b/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckEditViewTest.java
index aee9a6c..727d408 100644
--- a/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckEditViewTest.java
+++ b/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckEditViewTest.java
@@ -54,8 +54,8 @@
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.password_manager.settings.ReauthenticationManager;
 import org.chromium.chrome.browser.settings.SettingsActivityTestRule;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.url.GURL;
 
 import java.util.concurrent.ExecutionException;
diff --git a/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckIntegrationTest.java b/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckIntegrationTest.java
index ac0a62c..d65d45a9 100644
--- a/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckIntegrationTest.java
+++ b/chrome/browser/password_check/android/javatests/src/org/chromium/chrome/browser/password_check/PasswordCheckIntegrationTest.java
@@ -26,9 +26,9 @@
 import org.chromium.base.test.util.JniMocker;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.settings.SettingsActivityTestRule;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 
 /**
  * Integration test for the Password Check component, testing the interaction between sub-components
diff --git a/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java b/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java
index a21bb5f..c640d80 100644
--- a/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java
+++ b/chrome/browser/password_check/android/junit/src/org/chromium/chrome/browser/password_check/PasswordCheckControllerTest.java
@@ -65,7 +65,7 @@
 import org.chromium.chrome.browser.password_check.helper.PasswordCheckIconHelper;
 import org.chromium.chrome.browser.password_check.helper.PasswordCheckReauthenticationHelper;
 import org.chromium.chrome.browser.password_check.helper.PasswordCheckReauthenticationHelper.ReauthReason;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.ui.modelutil.ListModel;
 import org.chromium.ui.modelutil.MVCListAdapter;
 import org.chromium.ui.modelutil.PropertyModel;
diff --git a/chrome/browser/password_manager/android/BUILD.gn b/chrome/browser/password_manager/android/BUILD.gn
index e04d268c..acc62117 100644
--- a/chrome/browser/password_manager/android/BUILD.gn
+++ b/chrome/browser/password_manager/android/BUILD.gn
@@ -9,6 +9,7 @@
     "//base:base_java",
     "//base:jni_java",
     "//chrome/browser/settings:java",
+    "//components/browser_ui/settings/android:java",
     "//components/password_manager/core/browser:password_manager_java_enums",
     "//third_party/android_deps:androidx_annotation_annotation_java",
     "//third_party/android_deps:androidx_fragment_fragment_java",
diff --git a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelper.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelper.java
index ac5ae0c9..e9e6ceb7 100644
--- a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelper.java
+++ b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelper.java
@@ -8,7 +8,7 @@
 import android.os.Bundle;
 
 import org.chromium.base.metrics.RecordHistogram;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 
 /** A helper class for showing PasswordSettings. */
 public class PasswordManagerHelper {
diff --git a/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc b/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc
index e5fc66e..c55b7837 100644
--- a/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc
+++ b/chrome/browser/policy/messaging_layer/upload/record_handler_impl.cc
@@ -74,7 +74,7 @@
 
   void OnStart() override;
 
-  void StartUpload(const EncryptedRecord& encrypted_record);
+  void StartUpload();
   void OnUploadComplete(base::Optional<base::Value> response);
   void HandleFailedUpload();
   void HandleSuccessfulUpload();
@@ -159,26 +159,27 @@
     return;
   }
 
-  // We'll be popping records off the back.
-  std::reverse(records_->begin(), records_->end());
-
-  StartUpload(records_->back());
+  StartUpload();
 }
 
-void RecordHandlerImpl::ReportUploader::StartUpload(
-    const EncryptedRecord& encrypted_record) {
+void RecordHandlerImpl::ReportUploader::StartUpload() {
   auto response_cb =
       base::BindOnce(&RecordHandlerImpl::ReportUploader::OnUploadComplete,
                      base::Unretained(this));
 
-  auto request_result =
-      UploadEncryptedReportingRequestBuilder(need_encryption_key_)
-          .AddRecord(encrypted_record)
-          .Build();
+  UploadEncryptedReportingRequestBuilder request_builder{need_encryption_key_};
+  for (const auto& record : *records_) {
+    request_builder.AddRecord(record);
+  }
+  auto request_result = request_builder.Build();
   if (!request_result.has_value()) {
     std::move(response_cb).Run(base::nullopt);
     return;
   }
+
+  // Records have been captured in the request, safe to clear the vector.
+  records_->clear();
+
   base::Value request = std::move(request_result.value());
 
   base::PostTask(
@@ -208,18 +209,12 @@
 }
 
 void RecordHandlerImpl::ReportUploader::HandleFailedUpload() {
-  Status data_loss = Status(
-      error::DATA_LOSS,
-      base::StrCat({"Record failed uploaded: ",
-                    records_->back().sequencing_information().DebugString()}));
-  LOG(ERROR) << data_loss;
-
   if (highest_sequencing_information_.has_value()) {
     Complete(std::move(highest_sequencing_information_.value()));
     return;
   }
 
-  Complete(data_loss);
+  Complete(Status(error::INTERNAL, "Unable to upload any records"));
 }
 
 void RecordHandlerImpl::ReportUploader::HandleSuccessfulUpload() {
@@ -275,7 +270,7 @@
     }
   }
 
-  // Check if the previous record was unprocessable on the server.
+  // Check if a record was unprocessable on the server.
   const base::Value* failed_uploaded_record = last_response_.FindDictPath(
       "firstFailedUploadedRecord.failedUploadedRecord");
   if (failed_uploaded_record != nullptr) {
@@ -289,20 +284,15 @@
     auto gap_record_result =
         HandleFailedUploadedSequencingInformation(*failed_uploaded_record);
     if (gap_record_result.has_value()) {
-      gap_record_ = std::move(gap_record_result.value());
       LOG(ERROR) << "Data Loss. Record was unprocessable by the server: "
                  << *failed_uploaded_record;
-      StartUpload(gap_record_);
-      return;
+      records_->push_back(std::move(gap_record_result.value()));
     }
   }
 
-  // Pop the last record that was processed.
-  records_->pop_back();
-
   if (!records_->empty()) {
     // Upload the next record but do not request encryption key again.
-    StartUpload(records_->back());
+    StartUpload();
     return;
   }
 
diff --git a/chrome/browser/policy/messaging_layer/upload/record_handler_impl_unittest.cc b/chrome/browser/policy/messaging_layer/upload/record_handler_impl_unittest.cc
index f8234f8..6547c8f 100644
--- a/chrome/browser/policy/messaging_layer/upload/record_handler_impl_unittest.cc
+++ b/chrome/browser/policy/messaging_layer/upload/record_handler_impl_unittest.cc
@@ -55,6 +55,12 @@
   return arg.ValueOrDie().SerializeAsString() == expected.SerializeAsString();
 }
 
+MATCHER_P(StatusOrErrorCodeEquals,
+          expected,
+          "Compares StatusOr<T>.status().error_code() to expected") {
+  return arg.status().error_code() == expected;
+}
+
 class TestCallbackWaiter {
  public:
   TestCallbackWaiter() = default;
@@ -233,10 +239,9 @@
   constexpr uint64_t kGenerationId = 1234;
   auto test_records = BuildTestRecordsVector(kNumTestRecords, kGenerationId);
 
-  TestCallbackWaiterWithCounter client_waiter{kNumTestRecords};
+  TestCallbackWaiter client_waiter;
   EXPECT_CALL(*client_, UploadEncryptedReport(_, _, _))
-      .Times(kNumTestRecords)
-      .WillRepeatedly(WithArgs<0, 2>(
+      .WillOnce(WithArgs<0, 2>(
           Invoke([&client_waiter](
                      base::Value request,
                      policy::CloudPolicyClient::ResponseCallback callback) {
@@ -246,8 +251,6 @@
             client_waiter.Signal();
           })));
 
-  RecordHandlerImpl handler(client_.get());
-
   StrictMock<TestEncryptionKeyAttached> encryption_key_attached;
   StrictMock<TestCompletionResponder> responder;
   TestCallbackWaiter responder_waiter;
@@ -272,6 +275,7 @@
   auto responder_callback = base::BindOnce(&TestCompletionResponder::Call,
                                            base::Unretained(&responder));
 
+  RecordHandlerImpl handler(client_.get());
   handler.HandleRecords(need_encryption_key(), std::move(test_records),
                         std::move(responder_callback),
                         encryption_key_attached_callback);
@@ -280,54 +284,27 @@
   responder_waiter.Wait();
 }
 
-TEST_P(RecordHandlerImplTest, ReportsEarlyFailure) {
-  uint64_t kNumSuccessfulUploads = 5;
+TEST_P(RecordHandlerImplTest, ReportsUploadFailure) {
   uint64_t kNumTestRecords = 10;
   uint64_t kGenerationId = 1234;
   auto test_records = BuildTestRecordsVector(kNumTestRecords, kGenerationId);
 
-  // Wait kNumSuccessfulUploads times + 1 for the failure.
-  TestCallbackWaiterWithCounter client_waiter{kNumSuccessfulUploads + 1};
-
-  {
-    ::testing::InSequence seq;
-    EXPECT_CALL(*client_, UploadEncryptedReport(_, _, _))
-        .Times(kNumSuccessfulUploads)
-        .WillRepeatedly(WithArgs<0, 2>(
-            Invoke([&client_waiter](
-                       base::Value request,
-                       policy::CloudPolicyClient::ResponseCallback callback) {
-              base::Value response{base::Value::Type::DICTIONARY};
-              SucceedResponseFromRequest(request, response);
-              std::move(callback).Run(std::move(response));
-              client_waiter.Signal();
-            })));
-    EXPECT_CALL(*client_, UploadEncryptedReport(_, _, _))
-        .WillOnce(WithArgs<2>(Invoke(
-            [&client_waiter](base::OnceCallback<void(
-                                 base::Optional<base::Value>)> callback) {
-              std::move(callback).Run(base::nullopt);
-              client_waiter.Signal();
-            })));
-  }
-  RecordHandlerImpl handler(client_.get());
+  TestCallbackWaiter client_waiter;
+  EXPECT_CALL(*client_, UploadEncryptedReport(_, _, _))
+      .WillOnce(WithArgs<2>(Invoke(
+          [&client_waiter](
+              base::OnceCallback<void(base::Optional<base::Value>)> callback) {
+            std::move(callback).Run(base::nullopt);
+            client_waiter.Signal();
+          })));
 
   StrictMock<TestCompletionResponder> responder;
   TestCallbackWaiter responder_waiter;
-  EXPECT_CALL(
-      responder,
-      Call(ValueEqualsProto(
-          (*test_records)[kNumSuccessfulUploads - 1].sequencing_information())))
+  EXPECT_CALL(responder, Call(StatusOrErrorCodeEquals(error::INTERNAL)))
       .WillOnce(Invoke([&responder_waiter]() { responder_waiter.Signal(); }));
 
   StrictMock<TestEncryptionKeyAttached> encryption_key_attached;
-  EXPECT_CALL(
-      encryption_key_attached,
-      Call(AllOf(Property(&SignedEncryptionInfo::public_asymmetric_key,
-                          Not(IsEmpty())),
-                 Property(&SignedEncryptionInfo::public_key_id, Gt(0)),
-                 Property(&SignedEncryptionInfo::signature, Not(IsEmpty())))))
-      .Times(need_encryption_key() ? 1 : 0);
+  EXPECT_CALL(encryption_key_attached, Call(_)).Times(0);
 
   auto encryption_key_attached_callback =
       base::BindRepeating(&TestEncryptionKeyAttached::Call,
@@ -336,6 +313,7 @@
   auto responder_callback = base::BindOnce(&TestCompletionResponder::Call,
                                            base::Unretained(&responder));
 
+  RecordHandlerImpl handler(client_.get());
   handler.HandleRecords(need_encryption_key(), std::move(test_records),
                         std::move(responder_callback),
                         encryption_key_attached_callback);
@@ -345,30 +323,15 @@
 }
 
 TEST_P(RecordHandlerImplTest, UploadsGapRecordOnServerFailure) {
-  uint64_t kNumInitialSuccessfulUploads = 5;
   uint64_t kNumTestRecords = 10;
-  uint64_t kNumFinalSuccessfulUploads =
-      kNumTestRecords - kNumInitialSuccessfulUploads;
   uint64_t kGenerationId = 1234;
   auto test_records = BuildTestRecordsVector(kNumTestRecords, kGenerationId);
 
-  // Wait kNumTestRecords times + 1 for the failure.
-  TestCallbackWaiterWithCounter client_waiter{kNumTestRecords + 1};
-
+  // Once for failure, and once for gap.
+  TestCallbackWaiterWithCounter client_waiter{2};
   {
     ::testing::InSequence seq;
     EXPECT_CALL(*client_, UploadEncryptedReport(_, _, _))
-        .Times(kNumInitialSuccessfulUploads)
-        .WillRepeatedly(WithArgs<0, 2>(
-            Invoke([&client_waiter](
-                       base::Value request,
-                       policy::CloudPolicyClient::ResponseCallback callback) {
-              base::Value response{base::Value::Type::DICTIONARY};
-              SucceedResponseFromRequest(request, response);
-              std::move(callback).Run(std::move(response));
-              client_waiter.Signal();
-            })));
-    EXPECT_CALL(*client_, UploadEncryptedReport(_, _, _))
         .WillOnce(WithArgs<0, 2>(
             Invoke([&client_waiter](
                        base::Value request,
@@ -379,8 +342,7 @@
               client_waiter.Signal();
             })));
     EXPECT_CALL(*client_, UploadEncryptedReport(_, _, _))
-        .Times(kNumFinalSuccessfulUploads)
-        .WillRepeatedly(WithArgs<0, 2>(
+        .WillOnce(WithArgs<0, 2>(
             Invoke([&client_waiter](
                        base::Value request,
                        policy::CloudPolicyClient::ResponseCallback callback) {
@@ -391,8 +353,6 @@
             })));
   }
 
-  RecordHandlerImpl handler(client_.get());
-
   StrictMock<TestCallbackWaiter> responder_waiter;
   TestCompletionResponder responder;
   EXPECT_CALL(
@@ -415,6 +375,7 @@
   auto responder_callback = base::BindOnce(&TestCompletionResponder::Call,
                                            base::Unretained(&responder));
 
+  RecordHandlerImpl handler(client_.get());
   handler.HandleRecords(need_encryption_key(), std::move(test_records),
                         std::move(responder_callback),
                         encryption_key_attached_callback);
@@ -431,18 +392,15 @@
   constexpr uint64_t kGenerationId = 1234;
   auto test_records = BuildTestRecordsVector(kNumTestRecords, kGenerationId);
 
-  TestCallbackWaiterWithCounter client_waiter{kNumTestRecords};
+  TestCallbackWaiter client_waiter;
   EXPECT_CALL(*client_, UploadEncryptedReport(_, _, _))
-      .Times(kNumTestRecords)
-      .WillRepeatedly(WithArgs<2>(
+      .WillOnce(WithArgs<2>(
           Invoke([&client_waiter](
                      policy::CloudPolicyClient::ResponseCallback callback) {
             std::move(callback).Run(base::Value{base::Value::Type::DICTIONARY});
             client_waiter.Signal();
           })));
 
-  RecordHandlerImpl handler(client_.get());
-
   StrictMock<TestEncryptionKeyAttached> encryption_key_attached;
   StrictMock<TestCompletionResponder> responder;
   TestCallbackWaiter responder_waiter;
@@ -462,6 +420,7 @@
   auto responder_callback = base::BindOnce(&TestCompletionResponder::Call,
                                            base::Unretained(&responder));
 
+  RecordHandlerImpl handler(client_.get());
   handler.HandleRecords(need_encryption_key(), std::move(test_records),
                         std::move(responder_callback),
                         encryption_key_attached_callback);
diff --git a/chrome/browser/policy/messaging_layer/upload/record_upload_request_builder.h b/chrome/browser/policy/messaging_layer/upload/record_upload_request_builder.h
index cf20c20..5bd498b 100644
--- a/chrome/browser/policy/messaging_layer/upload/record_upload_request_builder.h
+++ b/chrome/browser/policy/messaging_layer/upload/record_upload_request_builder.h
@@ -66,6 +66,8 @@
       bool attach_encryption_settings = false);
   ~UploadEncryptedReportingRequestBuilder();
 
+  // TODO(chromium:1165908) Have AddRecord take ownership of the record that is
+  // passed in.
   UploadEncryptedReportingRequestBuilder& AddRecord(
       const EncryptedRecord& record);
 
diff --git a/chrome/browser/policy/messaging_layer/upload/upload_client_unittest.cc b/chrome/browser/policy/messaging_layer/upload/upload_client_unittest.cc
index befb6e0..d31d7bb 100644
--- a/chrome/browser/policy/messaging_layer/upload/upload_client_unittest.cc
+++ b/chrome/browser/policy/messaging_layer/upload/upload_client_unittest.cc
@@ -242,7 +242,6 @@
     records->push_back(encrypted_record);
   }
 
-  TestCallbackWaiterWithCounter waiter(kExpectedCallTimes);
 
   StrictMock<TestEncryptionKeyAttached> encryption_key_attached;
   EXPECT_CALL(
@@ -260,15 +259,16 @@
   client->SetDMToken(
       policy::DMToken::CreateValidTokenForTesting("FAKE_DM_TOKEN").value());
 
+  TestCallbackWaiter waiter;
   EXPECT_CALL(*client, UploadEncryptedReport(_, _, _))
-      .WillRepeatedly(WithArgs<0, 2>(Invoke(
+      .WillOnce(WithArgs<0, 2>(Invoke(
           [&waiter](base::Value request,
                     policy::CloudPolicyClient::ResponseCallback response_cb) {
             std::move(response_cb)
                 .Run(ValueFromSucceededSequencingInfo(std::move(request)));
             base::ThreadPool::PostTask(
                 FROM_HERE, {base::TaskPriority::BEST_EFFORT},
-                base::BindOnce(&TestCallbackWaiterWithCounter::Signal,
+                base::BindOnce(&TestCallbackWaiter::Signal,
                                base::Unretained(&waiter)));
           })));
 
diff --git a/chrome/browser/reading_list/android/empty_reading_list_manager.cc b/chrome/browser/reading_list/android/empty_reading_list_manager.cc
index d4e4d81a..9376e8f 100644
--- a/chrome/browser/reading_list/android/empty_reading_list_manager.cc
+++ b/chrome/browser/reading_list/android/empty_reading_list_manager.cc
@@ -4,7 +4,6 @@
 
 #include "chrome/browser/reading_list/android/empty_reading_list_manager.h"
 
-#include "base/logging.h"
 #include "components/bookmarks/browser/bookmark_utils.h"
 
 EmptyReadingListManager::EmptyReadingListManager() = default;
@@ -18,7 +17,6 @@
 const bookmarks::BookmarkNode* EmptyReadingListManager::Add(
     const GURL& url,
     const std::string& title) {
-  LOG(ERROR) << "Try to add reading list with empty reading list backend.";
   return nullptr;
 }
 
diff --git a/chrome/browser/reading_list/android/reading_list_manager.h b/chrome/browser/reading_list/android/reading_list_manager.h
index 28b589a3..efa7e53 100644
--- a/chrome/browser/reading_list/android/reading_list_manager.h
+++ b/chrome/browser/reading_list/android/reading_list_manager.h
@@ -47,7 +47,7 @@
   // Adds a reading list article to the unread section, and return the bookmark
   // node representation. The bookmark node is owned by this class. If there is
   // a duplicate URL, a new bookmark node will be created, and the old bookmark
-  // node pointer will be invalidated. May return nullptr on error.
+  // node pointer will be invalidated.
   virtual const bookmarks::BookmarkNode* Add(const GURL& url,
                                              const std::string& title) = 0;
 
diff --git a/chrome/browser/reading_list/android/reading_list_manager_impl.cc b/chrome/browser/reading_list/android/reading_list_manager_impl.cc
index b2bf08d..98b8bcc 100644
--- a/chrome/browser/reading_list/android/reading_list_manager_impl.cc
+++ b/chrome/browser/reading_list/android/reading_list_manager_impl.cc
@@ -132,13 +132,13 @@
 const BookmarkNode* ReadingListManagerImpl::Add(const GURL& url,
                                                 const std::string& title) {
   DCHECK(reading_list_model_->loaded());
-  if (!reading_list_model_->IsUrlSupported(url))
-    return nullptr;
 
   // Add or swap the reading list entry.
   const auto& new_entry = reading_list_model_->AddEntry(
       url, title, reading_list::ADDED_VIA_CURRENT_APP);
   const auto* node = FindBookmarkByURL(new_entry.URL());
+  DCHECK(node)
+      << "Bookmark node should have been create in ReadingListDidAddEntry().";
   return node;
 }
 
diff --git a/chrome/browser/reading_list/android/reading_list_manager_impl_unittest.cc b/chrome/browser/reading_list/android/reading_list_manager_impl_unittest.cc
index 57670f5..1ca6a98 100644
--- a/chrome/browser/reading_list/android/reading_list_manager_impl_unittest.cc
+++ b/chrome/browser/reading_list/android/reading_list_manager_impl_unittest.cc
@@ -32,7 +32,6 @@
 constexpr char kReadStatusKey[] = "read_status";
 constexpr char kReadStatusRead[] = "true";
 constexpr char kReadStatusUnread[] = "false";
-constexpr char kInvalidUTF8[] = "\xc3\x28";
 
 class MockObserver : public ReadingListManager::Observer {
  public:
@@ -229,31 +228,6 @@
   EXPECT_EQ(url, new_node->url());
 }
 
-// If Add() with an invalid title, nullptr will be returned.
-TEST_F(ReadingListManagerImplTest, AddInvalidTitle) {
-  GURL url(kURL);
-
-  // Use an invalid UTF8 string.
-  base::string16 dummy;
-  EXPECT_FALSE(
-      base::UTF8ToUTF16(kInvalidUTF8, base::size(kInvalidUTF8), &dummy));
-  const auto* new_node = Add(url, std::string(kInvalidUTF8));
-  EXPECT_EQ(nullptr, new_node)
-      << "Should return nullptr when failed to parse the title.";
-}
-
-// If Add() with an invalid URL, nullptr will be returned.
-TEST_F(ReadingListManagerImplTest, AddInvalidURL) {
-  GURL invalid_url("chrome://flags");
-  EXPECT_FALSE(reading_list_model()->IsUrlSupported(invalid_url));
-
-  // Use an invalid URL, the observer method ReadingListDidAddEntry() won't be
-  // invoked.
-  const auto* new_node = manager()->Add(invalid_url, kTitle);
-  EXPECT_EQ(nullptr, new_node)
-      << "Should return nullptr when the URL scheme is not supported.";
-}
-
 // Verifes SetReadStatus()/GetReadStatus() API.
 TEST_F(ReadingListManagerImplTest, ReadStatus) {
   GURL url(kURL);
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/options.html b/chrome/browser/resources/chromeos/accessibility/select_to_speak/options.html
index 100122f..09ae31a4 100644
--- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/options.html
+++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/options.html
@@ -108,7 +108,6 @@
       </div>
     </div>
 
-    <script src="prefs_manager.js"></script>
-    <script src="select_to_speak_options.js"></script>
+    <script type="module" src="select_to_speak_options.js"></script>
   </body>
 </html>
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak.js
index 66db632..f9cd195 100644
--- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak.js
+++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak.js
@@ -736,7 +736,6 @@
   stopAll_() {
     chrome.tts.stop();
     this.clearFocusRing_();
-    this.overrideSpeechRate_ = null;  // Reset speech rate to system default
     this.onStateChanged_(SelectToSpeakState.INACTIVE);
   }
 
diff --git a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_navigation_control_test.js b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_navigation_control_test.js
index 8ca7a00e..f340146 100644
--- a/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_navigation_control_test.js
+++ b/chrome/browser/resources/chromeos/accessibility/select_to_speak/select_to_speak_navigation_control_test.js
@@ -481,7 +481,6 @@
           });
     });
 
-// TODO(https://crbug.com/1157817): Fix Flaky Test.
 TEST_F(
     'SelectToSpeakNavigationControlTest', 'ChangeSpeedWhilePlaying',
     function() {
@@ -524,6 +523,31 @@
           });
     });
 
+TEST_F('SelectToSpeakNavigationControlTest', 'RetainsSpeedChange', function() {
+  chrome.settingsPrivate.setPref('settings.tts.speech_rate', 1.2);
+  const bodyHtml = `
+    <p id="p1">Paragraph 1</p>'
+  `;
+  this.runWithLoadedTree(
+      this.generateHtmlWithSelectedElement('p1', bodyHtml), () => {
+        this.triggerReadSelectedText();
+
+        // Changing speed then exit.
+        selectToSpeak.onSelectToSpeakPanelAction_(
+            chrome.accessibilityPrivate.SelectToSpeakPanelAction.CHANGE_SPEED,
+            1.5);
+        selectToSpeak.onSelectToSpeakPanelAction_(
+            chrome.accessibilityPrivate.SelectToSpeakPanelAction.EXIT);
+        assertFalse(this.mockTts.currentlySpeaking());
+        assertEquals(this.mockTts.pendingUtterances().length, 0);
+
+        // Next TTS session should remember previous rate.
+        this.triggerReadSelectedText();
+        assertTrue(this.mockTts.currentlySpeaking());
+        assertEquals(this.mockTts.getOptions().rate, 1.5);
+      });
+});
+
 TEST_F(
     'SelectToSpeakNavigationControlTest', 'ChangeSpeedWhilePaused', function() {
       chrome.settingsPrivate.setPref('settings.tts.speech_rate', 1.2);
diff --git a/chrome/browser/resources/feedback/js/feedback.js b/chrome/browser/resources/feedback/js/feedback.js
index 1859e7f..4db43cec 100644
--- a/chrome/browser/resources/feedback/js/feedback.js
+++ b/chrome/browser/resources/feedback/js/feedback.js
@@ -83,6 +83,14 @@
 const smartLockRegEx = new RegExp('(smart|easy)[ ]?(un)?lock', 'i');
 
 /**
+ * Regular expression to check for keywords related to Nearby Share like
+ * "nearby (share)" or "phone (hub)".
+ * Case insensitive matching.
+ * @type {RegExp}
+ */
+const nearbyShareRegEx = new RegExp('nearby|phone', 'i');
+
+/**
  * The callback used by the sys_info_page to receive the event that the system
  * information is ready.
  * @type {function(sysInfo)}
@@ -172,7 +180,8 @@
   const isRelatedToBluetooth = btRegEx.test(inputEvent.target.value) ||
       cantConnectRegEx.test(inputEvent.target.value) ||
       tetherRegEx.test(inputEvent.target.value) ||
-      smartLockRegEx.test(inputEvent.target.value);
+      smartLockRegEx.test(inputEvent.target.value) ||
+      nearbyShareRegEx.test(inputEvent.target.value);
   $('bluetooth-checkbox-container').hidden = !isRelatedToBluetooth;
 }
 
diff --git a/chrome/browser/resources/pdf/constants.js b/chrome/browser/resources/pdf/constants.js
index 45661bbe..0757ba1 100644
--- a/chrome/browser/resources/pdf/constants.js
+++ b/chrome/browser/resources/pdf/constants.js
@@ -22,6 +22,7 @@
  *   author: string,
  *   canSerializeDocument: boolean,
  *   creator: string,
+ *   keywords: string,
  *   linearized: boolean,
  *   producer: string,
  *   subject: string,
diff --git a/chrome/browser/resources/pdf/elements/viewer-page-selector.html b/chrome/browser/resources/pdf/elements/viewer-page-selector.html
index 0e44e5b..89cae2a 100644
--- a/chrome/browser/resources/pdf/elements/viewer-page-selector.html
+++ b/chrome/browser/resources/pdf/elements/viewer-page-selector.html
@@ -1,5 +1,8 @@
     <style>
-      :host {
+      /* A separate div is used because if the direction CSS property is applied
+       * to the host element, any margins or paddings set by the parent will be
+       * affected and be reversed. */
+      #content {
         align-items: center;
         color: #fff;
         direction: ltr;
@@ -37,8 +40,10 @@
         margin: 0 var(--page-selector-spacing);
       }
     </style>
-    <input part="input" type="text" id="pageselector" value="[[pageNo]]"
-        on-pointerup="select" on-input="onInput_" on-change="pageNoCommitted"
-        aria-label="$i18n{labelPageNumber}">
-    <span id="divider">/</span>
-    <span id="pagelength">[[docLength]]</span>
+    <div id="content">
+      <input part="input" type="text" id="pageselector" value="[[pageNo]]"
+          on-pointerup="select" on-input="onInput_" on-change="pageNoCommitted"
+          aria-label="$i18n{labelPageNumber}">
+      <span id="divider">/</span>
+      <span id="pagelength">[[docLength]]</span>
+    </div>
\ No newline at end of file
diff --git a/chrome/browser/resources/pdf/elements/viewer-properties-dialog.html b/chrome/browser/resources/pdf/elements/viewer-properties-dialog.html
index 31bcc0b8..e87f79b 100644
--- a/chrome/browser/resources/pdf/elements/viewer-properties-dialog.html
+++ b/chrome/browser/resources/pdf/elements/viewer-properties-dialog.html
@@ -25,6 +25,7 @@
   .name {
     color: var(--cr-primary-text-color);
     padding-inline-end: 12px;
+    vertical-align: top;
   }
 
   .value {
@@ -35,6 +36,10 @@
     text-overflow: ellipsis;
     white-space: nowrap;
   }
+
+  #keywords {
+    white-space: normal;
+  }
 </style>
 <cr-dialog show-on-attach>
   <div slot="title">$i18n{propertiesDialogTitle}</div>
@@ -68,7 +73,9 @@
       </tr>
       <tr>
         <td class="name">$i18n{propertiesKeywords}</td>
-        <td class="value" id="keywords">-</td>
+        <td class="value" id="keywords">
+          [[getOrPlaceholder_(documentMetadata.keywords)]]
+        </td>
       </tr>
       <tr>
         <td class="name">$i18n{propertiesCreated}</td>
diff --git a/chrome/browser/resources/print_preview/BUILD.gn b/chrome/browser/resources/print_preview/BUILD.gn
index 0a90d29..7fbe0526 100644
--- a/chrome/browser/resources/print_preview/BUILD.gn
+++ b/chrome/browser/resources/print_preview/BUILD.gn
@@ -186,7 +186,24 @@
   in_folder = "../"
   out_folder = "$target_gen_dir/$preprocess_folder"
   out_manifest = "$target_gen_dir/$preprocess_pdf_manifest"
-  in_files = [ "pdf/index_pp.html" ]
+  in_files = [
+    "pdf/browser_api.js",
+    "pdf/constants.js",
+    "pdf/controller.js",
+    "pdf/gesture_detector.js",
+    "pdf/index.css",
+    "pdf/index_pp.html",
+    "pdf/main.js",
+    "pdf/metrics.js",
+    "pdf/open_pdf_params_parser.js",
+    "pdf/pdf_scripting_api.js",
+    "pdf/pdf_viewer_utils.js",
+    "pdf/pdf_viewer_base.js",
+    "pdf/toolbar_manager.js",
+    "pdf/viewport.js",
+    "pdf/viewport_scroller.js",
+    "pdf/zoom_manager.js",
+  ]
 }
 
 preprocess_if_expr("preprocess_pdf_generated") {
@@ -195,8 +212,14 @@
   out_folder = "$target_gen_dir/$preprocess_folder"
   out_manifest = "$target_gen_dir/$preprocess_pdf_gen_manifest"
   in_files = [
-    "pdf/pdf_viewer_pp.js",
+    "pdf/elements/icons.js",
+    "pdf/elements/shared-vars.js",
+    "pdf/elements/viewer-error-screen.js",
     "pdf/elements/viewer-page-indicator.js",
+    "pdf/elements/viewer-zoom-button.js",
+    "pdf/elements/viewer-zoom-toolbar.js",
+    "pdf/pdf_viewer_pp.js",
+    "pdf/pdf_viewer_shared_style.js",
   ]
 }
 
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn
index 1344575..ac91439 100644
--- a/chrome/browser/resources/settings/BUILD.gn
+++ b/chrome/browser/resources/settings/BUILD.gn
@@ -147,12 +147,14 @@
     ]
   } else {
     if (!is_chromeos_lacros) {
-      in_files += [ "default_browser_page/default_browser_browser_proxy.js" ]
+      in_files += [
+        "default_browser_page/default_browser_browser_proxy.js",
+        "system_page/system_page_browser_proxy.js",
+      ]
     }
     in_files += [
       "people_page/import_data_browser_proxy.js",
       "people_page/manage_profile_browser_proxy.js",
-      "system_page/system_page_browser_proxy.js",
     ]
   }
 }
@@ -329,12 +331,14 @@
     in_files += [ "people_page/account_manager_browser_proxy.m.js" ]
   } else {
     if (!is_chromeos_lacros) {
-      in_files += [ "default_browser_page/default_browser_page.js" ]
+      in_files += [
+        "default_browser_page/default_browser_page.js",
+        "system_page/system_page.js",
+      ]
     }
     in_files += [
       "people_page/import_data_dialog.js",
       "people_page/manage_profile.js",
-      "system_page/system_page.js",
     ]
   }
 }
@@ -465,11 +469,11 @@
     "site_settings:closure_compile_module",
     "site_settings_page:closure_compile_module",
   ]
-  if (!is_chromeos_ash) {
-    if (!is_chromeos_lacros) {
-      deps += [ "default_browser_page:closure_compile_module" ]
-    }
-    deps += [ "system_page:closure_compile_module" ]
+  if (!is_chromeos_ash && !is_chromeos_lacros) {
+    deps += [
+      "default_browser_page:closure_compile_module",
+      "system_page:closure_compile_module",
+    ]
   }
 
   if (is_win) {
@@ -676,11 +680,11 @@
     ":web_components_local",
   ]
 
-  if (!is_chromeos_ash) {
-    if (!is_chromeos_lacros) {
-      public_deps += [ "default_browser_page:web_components" ]
-    }
-    public_deps += [ "system_page:web_components" ]
+  if (!is_chromeos_ash && !is_chromeos_lacros) {
+    public_deps += [
+      "default_browser_page:web_components",
+      "system_page:web_components",
+    ]
   }
 
   if (is_win) {
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.html b/chrome/browser/resources/settings/basic_page/basic_page.html
index c8d4b84..d931291 100644
--- a/chrome/browser/resources/settings/basic_page/basic_page.html
+++ b/chrome/browser/resources/settings/basic_page/basic_page.html
@@ -183,7 +183,7 @@
                 <settings-a11y-page prefs="{{prefs}}"></settings-a11y-page>
               </settings-section>
             </template>
-<if expr="not chromeos">
+<if expr="not chromeos and not lacros">
             <settings-section page-title="$i18n{systemPageTitle}"
                 section="system">
               <settings-system-page prefs="{{prefs}}"></settings-system-page>
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.html b/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.html
index 8f651bd..8cffc49 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.html
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.html
@@ -96,15 +96,17 @@
         deep-link-focus-id$="[[Setting.kFullscreenMagnifier]]">
     </settings-toggle-button>
     <template is="dom-if" if="[[prefs.settings.a11y.screen_magnifier.value]]">
-      <div class="sub-item">
-        <settings-toggle-button
-            class="sub-item"
-            pref="{{prefs.settings.a11y.screen_magnifier_focus_following}}"
-            label="$i18n{screenMagnifierFocusFollowingLabel}"
-            deep-link-focus-id$=
-                "[[Setting.kFullscreenMagnifierFocusFollowing]]">
-        </settings-toggle-button>
-      </div>
+      <template is="dom-if" if="[[isMagnifierPanningImprovementsEnabled_]]">
+        <div class="sub-item">
+          <settings-toggle-button
+              class="sub-item"
+              pref="{{prefs.settings.a11y.screen_magnifier_focus_following}}"
+              label="$i18n{screenMagnifierFocusFollowingLabel}"
+              deep-link-focus-id$=
+                  "[[Setting.kFullscreenMagnifierFocusFollowing]]">
+          </settings-toggle-button>
+        </div>
+      </template>
       <div class="settings-box continuation">
         <div class="start sub-item settings-box-text" aria-hidden="true">
           $i18n{screenMagnifierZoomLabel}
diff --git a/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.js b/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.js
index 234b618..eac72c35 100644
--- a/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.js
+++ b/chrome/browser/resources/settings/chromeos/os_a11y_page/manage_a11y_page.js
@@ -158,6 +158,14 @@
       },
     },
 
+    /** @private */
+    isMagnifierPanningImprovementsEnabled_: {
+      type: Boolean,
+      value() {
+        return loadTimeData.getBoolean('isMagnifierPanningImprovementsEnabled');
+      },
+    },
+
     /**
      * Whether the user is in kiosk mode.
      * @private
diff --git a/chrome/browser/resources/settings/ensure_lazy_loaded.js b/chrome/browser/resources/settings/ensure_lazy_loaded.js
index 4abe470..426fa21 100644
--- a/chrome/browser/resources/settings/ensure_lazy_loaded.js
+++ b/chrome/browser/resources/settings/ensure_lazy_loaded.js
@@ -22,7 +22,7 @@
       // </if>
       'settings-a11y-page', 'settings-downloads-page',
       'settings-languages-page', 'settings-reset-page',
-      // <if expr="not chromeos">
+      // <if expr="not chromeos and not lacros">
       'settings-system-page',
       // </if>
       // <if expr="not is_macosx">
diff --git a/chrome/browser/resources/settings/lazy_load.js b/chrome/browser/resources/settings/lazy_load.js
index 9af0169dc..1c0bdd6 100644
--- a/chrome/browser/resources/settings/lazy_load.js
+++ b/chrome/browser/resources/settings/lazy_load.js
@@ -41,7 +41,7 @@
 import './downloads_page/downloads_page.js';
 import './languages_page/languages_page.js';
 import './reset_page/reset_page.js';
-// <if expr="not chromeos">
+// <if expr="not chromeos and not lacros">
 import './system_page/system_page.js';
 // </if>
 
diff --git a/chrome/browser/resources/settings/route.js b/chrome/browser/resources/settings/route.js
index db9e1701..1ad97e5 100644
--- a/chrome/browser/resources/settings/route.js
+++ b/chrome/browser/resources/settings/route.js
@@ -185,7 +185,7 @@
     }
     // </if>
 
-    // <if expr="not chromeos">
+    // <if expr="not chromeos and not lacros">
     r.SYSTEM = r.ADVANCED.createSection('/system', 'system');
     // </if>
 
diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.html b/chrome/browser/resources/settings/settings_menu/settings_menu.html
index a5a4e6ca..2ecb987 100644
--- a/chrome/browser/resources/settings/settings_menu/settings_menu.html
+++ b/chrome/browser/resources/settings/settings_menu/settings_menu.html
@@ -172,7 +172,7 @@
                 <iron-icon icon="settings:accessibility"></iron-icon>
                 $i18n{a11yPageTitle}
               </a>
-    <if expr="not chromeos">
+    <if expr="not chromeos and not lacros">
               <a role="menuitem" href="/system"
                   disabled$="[[!advancedOpened]]">
                 <iron-icon icon="settings:build"></iron-icon>
diff --git a/chrome/browser/resources/signin/profile_picker/profile_card_menu.html b/chrome/browser/resources/signin/profile_picker/profile_card_menu.html
index 3a9366c..620a0c7 100644
--- a/chrome/browser/resources/signin/profile_picker/profile_card_menu.html
+++ b/chrome/browser/resources/signin/profile_picker/profile_card_menu.html
@@ -107,14 +107,14 @@
 </cr-icon-button>
 
 <cr-action-menu id="actionMenu" role-description="$i18n{menu}">
-  <button class="dropdown-item" on-click="onRemoveButtonClicked_">
-    <iron-icon icon="cr:delete" aria-hidden="true"></iron-icon>
-    $i18n{profileMenuRemoveText}
-  </button>
   <button class="dropdown-item" on-click="onCustomizeButtonClicked_">
     <iron-icon icon="profiles:create" aria-hidden="true"></iron-icon>
     $i18n{profileMenuCustomizeText}
   </button>
+  <button class="dropdown-item" on-click="onRemoveButtonClicked_">
+    <iron-icon icon="cr:delete" aria-hidden="true"></iron-icon>
+    $i18n{profileMenuRemoveText}
+  </button>
 </cr-action-menu>
 
 <cr-action-menu id="removeActionMenu" role-description="$i18n{menu}">
diff --git a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragment.java b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragment.java
index 3bf4e9c..3e0ea8c 100644
--- a/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragment.java
+++ b/chrome/browser/safe_browsing/android/java/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragment.java
@@ -19,9 +19,9 @@
 import org.chromium.chrome.browser.safe_browsing.metrics.SettingsAccessPoint;
 import org.chromium.chrome.browser.safe_browsing.metrics.UserAction;
 import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate;
-import org.chromium.chrome.browser.settings.FragmentSettingsLauncher;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
+import org.chromium.components.browser_ui.settings.FragmentSettingsLauncher;
 import org.chromium.components.browser_ui.settings.ManagedPreferenceDelegate;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.settings.TextMessagePreference;
 
 /**
diff --git a/chrome/browser/safe_browsing/android/javatests/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragmentTest.java b/chrome/browser/safe_browsing/android/javatests/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragmentTest.java
index 492ea63..2dc6920 100644
--- a/chrome/browser/safe_browsing/android/javatests/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragmentTest.java
+++ b/chrome/browser/safe_browsing/android/javatests/src/org/chromium/chrome/browser/safe_browsing/settings/SafeBrowsingSettingsFragmentTest.java
@@ -31,9 +31,9 @@
 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.browser.settings.SettingsLauncher;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.settings.TextMessagePreference;
 import org.chromium.components.browser_ui.widget.RadioButtonWithDescription;
 import org.chromium.components.browser_ui.widget.RadioButtonWithDescriptionAndAuxButton;
diff --git a/chrome/browser/safety_check/android/BUILD.gn b/chrome/browser/safety_check/android/BUILD.gn
index 6ca54da4..e3f0ab4 100644
--- a/chrome/browser/safety_check/android/BUILD.gn
+++ b/chrome/browser/safety_check/android/BUILD.gn
@@ -113,6 +113,7 @@
     "//chrome/browser/settings:java",
     "//chrome/browser/signin/ui/android:java",
     "//chrome/test/android:chrome_java_test_support",
+    "//components/browser_ui/settings/android:java",
     "//third_party/android_deps:robolectric_all_java",
     "//third_party/junit:junit",
     "//third_party/mockito:mockito_java",
diff --git a/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckCoordinator.java b/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckCoordinator.java
index 6ed4fb9..8c54d43 100644
--- a/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckCoordinator.java
+++ b/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckCoordinator.java
@@ -11,8 +11,8 @@
 
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.password_manager.PasswordScriptsFetcherBridge;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.signin.ui.SigninActivityLauncher;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.ui.modelutil.PropertyModel;
 import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
 
diff --git a/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediator.java b/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediator.java
index 0d28c58a..db5f118 100644
--- a/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediator.java
+++ b/chrome/browser/safety_check/android/java/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediator.java
@@ -36,8 +36,8 @@
 import org.chromium.chrome.browser.safety_check.SafetyCheckProperties.PasswordsState;
 import org.chromium.chrome.browser.safety_check.SafetyCheckProperties.SafeBrowsingState;
 import org.chromium.chrome.browser.safety_check.SafetyCheckProperties.UpdatesState;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.signin.ui.SigninActivityLauncher;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.signin.metrics.SigninAccessPoint;
 import org.chromium.content_public.common.ContentUrlConstants;
 import org.chromium.ui.modelutil.PropertyModel;
diff --git a/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediatorTest.java b/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediatorTest.java
index 414294a..95821fd 100644
--- a/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediatorTest.java
+++ b/chrome/browser/safety_check/android/javatests/src/org/chromium/chrome/browser/safety_check/SafetyCheckMediatorTest.java
@@ -40,9 +40,9 @@
 import org.chromium.chrome.browser.safety_check.SafetyCheckProperties.PasswordsState;
 import org.chromium.chrome.browser.safety_check.SafetyCheckProperties.SafeBrowsingState;
 import org.chromium.chrome.browser.safety_check.SafetyCheckProperties.UpdatesState;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.signin.ui.SigninActivityLauncher;
 import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.ui.modelutil.PropertyModel;
 
 import java.lang.ref.WeakReference;
diff --git a/chrome/browser/search/instant_service.cc b/chrome/browser/search/instant_service.cc
index 76f6246..9357ef1 100644
--- a/chrome/browser/search/instant_service.cc
+++ b/chrome/browser/search/instant_service.cc
@@ -375,7 +375,10 @@
   // user has never customized their shortcuts.
   //
   // For more details, see custom_links_mananger.h and most_visited_sites.h.
-  if (!was_initialized && !most_visited_sites_->IsCustomLinksInitialized()) {
+  if ((!was_initialized && !most_visited_sites_->IsCustomLinksInitialized()) ||
+      // Ensure that the add shortcut button status is correct when there is no
+      // custom link.
+      most_visited_sites_->GetCustomLinkNum() == 0) {
     NotifyAboutMostVisitedInfo();
   }
 
diff --git a/chrome/browser/search_engines/template_url_service_unittest.cc b/chrome/browser/search_engines/template_url_service_unittest.cc
index 0a169bf..c5e50237 100644
--- a/chrome/browser/search_engines/template_url_service_unittest.cc
+++ b/chrome/browser/search_engines/template_url_service_unittest.cc
@@ -37,11 +37,13 @@
 #include "components/search_engines/template_url_prepopulate_data.h"
 #include "components/sync_preferences/testing_pref_service_syncable.h"
 #include "content/public/test/browser_task_environment.h"
+#include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using base::ASCIIToUTF16;
 using base::Time;
 using base::TimeDelta;
+using testing::NotNull;
 
 namespace {
 
@@ -933,6 +935,38 @@
   AssertEquals(*cloned_url, *model()->GetDefaultSearchProvider());
 }
 
+TEST_F(TemplateURLServiceTest,
+       DefaultSearchProviderShouldBeProtectedFromKeywordConflictDuringLoad) {
+  // Start with the model unloaded, with the DSE provided purely from prefs.
+  ASSERT_FALSE(model()->loaded());
+  const TemplateURL* initial_default_search_provider =
+      model()->GetDefaultSearchProvider();
+  ASSERT_THAT(initial_default_search_provider, NotNull());
+
+  // Now simulate loading from the keyword table, where the DSE is added as a
+  // a TemplateURL to the vector.
+  TemplateURL* in_vector_dse_engine = model()->Add(
+      std::make_unique<TemplateURL>(initial_default_search_provider->data()));
+  ASSERT_THAT(in_vector_dse_engine, NotNull());
+  ASSERT_EQ(in_vector_dse_engine,
+            model()->GetTemplateURLForGUID(
+                initial_default_search_provider->sync_guid()));
+
+  // Then simulate loading a conflicting user engine with the same keyword.
+  TemplateURL* user_engine = AddKeywordWithDate(
+      "user_engine",
+      base::UTF16ToUTF8(initial_default_search_provider->keyword()),
+      "http://test2", std::string(), std::string(), std::string(), false,
+      "UTF-8", base::Time::FromTimeT(20));
+  EXPECT_THAT(user_engine, NotNull());
+
+  // Now verify that the in-vector DSE entry was not removed due to the keyword
+  // conflict. It should be protected by virtue of matching the initial DSE.
+  EXPECT_EQ(in_vector_dse_engine,
+            model()->GetTemplateURLForGUID(
+                initial_default_search_provider->sync_guid()));
+}
+
 TEST_F(TemplateURLServiceTest, RepairPrepopulatedSearchEngines) {
   test_util()->VerifyLoad();
 
diff --git a/chrome/browser/settings/BUILD.gn b/chrome/browser/settings/BUILD.gn
index deaf3d4c..1ecaf3ba 100644
--- a/chrome/browser/settings/BUILD.gn
+++ b/chrome/browser/settings/BUILD.gn
@@ -5,18 +5,13 @@
 import("//build/config/android/rules.gni")
 
 android_library("java") {
-  sources = [
-    "android/java/src/org/chromium/chrome/browser/settings/ChromeManagedPreferenceDelegate.java",
-    "android/java/src/org/chromium/chrome/browser/settings/FragmentSettingsLauncher.java",
-    "android/java/src/org/chromium/chrome/browser/settings/SettingsLauncher.java",
-  ]
+  sources = [ "android/java/src/org/chromium/chrome/browser/settings/ChromeManagedPreferenceDelegate.java" ]
   deps = [
     "//chrome/browser/preferences:java",
     "//chrome/browser/profiles/android:java",
     "//components/browser_ui/settings/android:java",
     "//components/prefs/android:java",
     "//components/user_prefs/android:java",
-    "//third_party/android_deps:androidx_annotation_annotation_java",
     "//third_party/android_deps:androidx_fragment_fragment_java",
   ]
 }
@@ -61,6 +56,7 @@
     "//base:base_java_test_support",
     "//chrome/android:chrome_java",
     "//chrome/browser/settings:java",
+    "//components/browser_ui/settings/android:java",
     "//content/public/test/android:content_java_test_support",
     "//third_party/android_deps:androidx_preference_preference_java",
     "//third_party/android_support_test_runner:rules_java",
diff --git a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/ChromeImageViewPreferenceTest.java b/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/ChromeImageViewPreferenceTest.java
index 6fdde6a..9ea9484 100644
--- a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/ChromeImageViewPreferenceTest.java
+++ b/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/ChromeImageViewPreferenceTest.java
@@ -31,6 +31,7 @@
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.components.browser_ui.settings.ChromeImageViewPreference;
 import org.chromium.components.browser_ui.settings.R;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 
 /**
  * Tests of {@link ChromeImageViewPreference}.
diff --git a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/ManagedPreferencesUtilsTest.java b/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/ManagedPreferencesUtilsTest.java
index 645b326..4e898ee 100644
--- a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/ManagedPreferencesUtilsTest.java
+++ b/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/ManagedPreferencesUtilsTest.java
@@ -31,6 +31,7 @@
 import org.chromium.components.browser_ui.settings.ManagedPreferenceDelegate;
 import org.chromium.components.browser_ui.settings.ManagedPreferencesUtils;
 import org.chromium.components.browser_ui.settings.R;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
 
 /**
diff --git a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/SettingsActivityTestRule.java b/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/SettingsActivityTestRule.java
index 22bcb58..5ddacb76 100644
--- a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/SettingsActivityTestRule.java
+++ b/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/SettingsActivityTestRule.java
@@ -16,6 +16,7 @@
 
 import org.chromium.base.test.BaseActivityTestRule;
 import org.chromium.base.test.util.ApplicationTestUtils;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 
 /**
  * Activity test rule that launch {@link SettingsActivity} in tests.
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/DevicePickerBottomSheetContent.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/DevicePickerBottomSheetContent.java
index ef6e7f4e..3b49c22 100644
--- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/DevicePickerBottomSheetContent.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/DevicePickerBottomSheetContent.java
@@ -18,10 +18,10 @@
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.share.send_tab_to_self.SendTabToSelfMetrics.SendTabToSelfShareClickResult;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.ui.widget.ButtonCompat;
 import org.chromium.ui.widget.Toast;
 
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinator.java
index fb1c8fc7..de8cd44 100644
--- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinator.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/send_tab_to_self/SendTabToSelfCoordinator.java
@@ -8,9 +8,9 @@
 
 import androidx.annotation.VisibleForTesting;
 
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 
 /**
  * Coordinator for displaying the send tab to self feature.
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 bbb08b31..9f613b7 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
@@ -21,7 +21,6 @@
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.preferences.Pref;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.share.ChromeShareExtras;
 import org.chromium.chrome.browser.share.link_to_text.LinkToTextCoordinator;
 import org.chromium.chrome.browser.share.long_screenshots.LongScreenshotsCoordinator;
@@ -35,6 +34,7 @@
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.SheetState;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver;
 import org.chromium.components.browser_ui.bottomsheet.EmptyBottomSheetObserver;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.share.ShareParams;
 import org.chromium.components.user_prefs.UserPrefs;
 import org.chromium.ui.base.Clipboard;
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java
index 858ffc9..6a914a4 100644
--- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java
+++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/share_sheet/ShareSheetCoordinator.java
@@ -19,7 +19,6 @@
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
 import org.chromium.chrome.browser.lifecycle.ConfigurationChangedObserver;
-import org.chromium.chrome.browser.settings.SettingsLauncher;
 import org.chromium.chrome.browser.share.ChromeShareExtras;
 import org.chromium.chrome.browser.share.ShareHelper;
 import org.chromium.chrome.browser.tab.Tab;
@@ -28,6 +27,7 @@
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver;
 import org.chromium.components.browser_ui.bottomsheet.EmptyBottomSheetObserver;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.share.ShareParams;
 import org.chromium.components.favicon.LargeIconBridge;
 import org.chromium.ui.base.WindowAndroid;
diff --git a/chrome/browser/signin/dice_web_signin_interceptor.cc b/chrome/browser/signin/dice_web_signin_interceptor.cc
index cfadff0..a6e1c1dc 100644
--- a/chrome/browser/signin/dice_web_signin_interceptor.cc
+++ b/chrome/browser/signin/dice_web_signin_interceptor.cc
@@ -553,8 +553,8 @@
       kProfileCreationInterceptionDeclinedPref);
   base::Optional<int> declined_count =
       pref_data->FindIntKey(GetPersistentEmailHash(email));
-  // Check if the user declined 3 times.
-  constexpr int kMaxProfileCreationDeclinedCount = 3;
+  // Check if the user declined 2 times.
+  constexpr int kMaxProfileCreationDeclinedCount = 2;
   return declined_count &&
          declined_count.value() >= kMaxProfileCreationDeclinedCount;
 }
diff --git a/chrome/browser/signin/dice_web_signin_interceptor.h b/chrome/browser/signin/dice_web_signin_interceptor.h
index 7c29c17c..5465468 100644
--- a/chrome/browser/signin/dice_web_signin_interceptor.h
+++ b/chrome/browser/signin/dice_web_signin_interceptor.h
@@ -294,7 +294,7 @@
   // cannot be reversed.
   void RecordProfileCreationDeclined(const std::string& email);
 
-  // Checks if the user previously declined 3 times creating a new profile for
+  // Checks if the user previously declined 2 times creating a new profile for
   // this account.
   bool HasUserDeclinedProfileCreation(const std::string& email) const;
 
diff --git a/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc b/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc
index a12a04a..c3ba70e 100644
--- a/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc
+++ b/chrome/browser/signin/dice_web_signin_interceptor_unittest.cc
@@ -493,11 +493,12 @@
   account_info.hosted_domain = "example.com";
   identity_test_env()->UpdateAccountInfoForAccount(account_info);
 
-  // Decline the interception three times.
+  const int kMaxProfileCreationDeclinedCount = 2;
+  // Decline the interception kMaxProfileCreationDeclinedCount times.
   DiceWebSigninInterceptor::Delegate::BubbleParameters expected_parameters = {
       DiceWebSigninInterceptor::SigninInterceptionType::kEnterprise,
       account_info, primary_account_info, SkColor()};
-  for (int i = 0; i < 3; ++i) {
+  for (int i = 0; i < kMaxProfileCreationDeclinedCount; ++i) {
     EXPECT_CALL(*mock_delegate(),
                 ShowSigninInterceptionBubble(
                     web_contents(), MatchBubbleParameters(expected_parameters),
@@ -514,7 +515,7 @@
         SigninInterceptionHeuristicOutcome::kInterceptEnterprise, i + 1);
   }
 
-  // Fourth time the interception is not shown again.
+  // Next time the interception is not shown again.
   MaybeIntercept(account_info.account_id);
   EXPECT_EQ(interceptor()->is_interception_in_progress(), false);
   histogram_tester.ExpectBucketCount(
@@ -544,7 +545,8 @@
   MaybeIntercept(account_info.account_id);
   histogram_tester.ExpectBucketCount(
       "Signin.Intercept.HeuristicOutcome",
-      SigninInterceptionHeuristicOutcome::kInterceptEnterprise, 4);
+      SigninInterceptionHeuristicOutcome::kInterceptEnterprise,
+      kMaxProfileCreationDeclinedCount + 1);
   EXPECT_EQ(interceptor()->is_interception_in_progress(), true);
 }
 
diff --git a/chrome/browser/tabpersistence/android/java/src/org/chromium/chrome/browser/tabpersistence/TabStateDirectory.java b/chrome/browser/tabpersistence/android/java/src/org/chromium/chrome/browser/tabpersistence/TabStateDirectory.java
index d732e251..7268c09 100644
--- a/chrome/browser/tabpersistence/android/java/src/org/chromium/chrome/browser/tabpersistence/TabStateDirectory.java
+++ b/chrome/browser/tabpersistence/android/java/src/org/chromium/chrome/browser/tabpersistence/TabStateDirectory.java
@@ -108,4 +108,9 @@
     public static void setBaseStateDirectoryForTests(File directory) {
         BaseStateDirectoryHolder.sDirectory = directory;
     }
+
+    @VisibleForTesting
+    public static void resetTabbedModeStateDirectoryForTesting() {
+        sTabbedModeStateDirectory = null;
+    }
 }
diff --git a/chrome/browser/translate/android/translate_bridge.cc b/chrome/browser/translate/android/translate_bridge.cc
index 376fabba..e2067e7 100644
--- a/chrome/browser/translate/android/translate_bridge.cc
+++ b/chrome/browser/translate/android/translate_bridge.cc
@@ -184,6 +184,16 @@
   return j_target_language;
 }
 
+// Set the default target language to translate into for this user.
+static void JNI_TranslateBridge_SetDefaultTargetLanguage(
+    JNIEnv* env,
+    const JavaParamRef<jstring>& j_target_language) {
+  std::unique_ptr<translate::TranslatePrefs> translate_prefs =
+      ChromeTranslateClient::CreateTranslatePrefs(GetPrefService());
+  std::string target_language(ConvertJavaStringToUTF8(env, j_target_language));
+  translate_prefs->SetRecentTargetLanguage(target_language);
+}
+
 // Determines whether the given language is blocked for translation.
 static jboolean JNI_TranslateBridge_IsBlockedLanguage(
     JNIEnv* env,
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
index c7da0af..8e22eac 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -1187,12 +1187,6 @@
       <message name="IDS_LANGUAGES_ITEM_OPTION_OFFER_TO_TRANSLATE" desc="Option in language item menu. User can click the 'Offer to translate' option to toggle whether they want Chrome to translate pages in this language. [CHAR-LIMIT=32]">
         Offer to translate
       </message>
-      <message name="IDS_LANGUAGES_SET_APPLICATION_LANGUAGE_PROMPT" desc="Option in language item menu. User can click the 'App Language' option to toggle whether or not the Chrome user interface should be displayed in this language. [CHAR-LIMIT=32]">
-        Use as Chrome’s language
-      </message>
-      <message name="IDS_LANGUAGES_SET_AS_APPLICATION_LANGUAGE" desc="Toast to display after selecting language to use for Chrome's user interface.">
-        <ph name="APP_NAME">%1$s<ex>Chrome</ex></ph> will use <ph name="language">%2$s<ex>Hindi</ex></ph> on restart.
-      </message>
       <message name="IDS_LANGUAGES_EXPLICIT_ASK_TITLE" desc="Title of the dialog that explicitly asks the user which languages they can read.">
         What languages do you read?
       </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_LANGUAGES_SET_APPLICATION_LANGUAGE_PROMPT.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_LANGUAGES_SET_APPLICATION_LANGUAGE_PROMPT.png.sha1
deleted file mode 100644
index c74c1dec..0000000
--- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_LANGUAGES_SET_APPLICATION_LANGUAGE_PROMPT.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a06a8a932e9e708294c314558f6e1ec468967cb4
\ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_LANGUAGES_SET_AS_APPLICATION_LANGUAGE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_LANGUAGES_SET_AS_APPLICATION_LANGUAGE.png.sha1
deleted file mode 100644
index ee6ed33..0000000
--- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_LANGUAGES_SET_AS_APPLICATION_LANGUAGE.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-1b9eb3ffd36ca1e5fcd298fdd008adee701e88bb
\ No newline at end of file
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.cc b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
index 70bacc0..e7e62869 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_utils.cc
+++ b/chrome/browser/ui/app_list/arc/arc_app_utils.cc
@@ -10,6 +10,7 @@
 #include <tuple>
 #include <utility>
 
+#include "base/check.h"
 #include "base/containers/contains.h"
 #include "base/json/json_writer.h"
 #include "base/metrics/histogram_macros.h"
@@ -705,8 +706,10 @@
 
 std::string ArcPackageNameToAppId(const std::string& package_name,
                                   Profile* profile) {
+  DCHECK(profile);
   ArcAppListPrefs* arc_prefs = ArcAppListPrefs::Get(profile);
-  return arc_prefs->GetAppIdByPackageName(package_name);
+  return arc_prefs ? arc_prefs->GetAppIdByPackageName(package_name)
+                   : std::string();
 }
 
 void AddAppLaunchObserver(content::BrowserContext* context,
diff --git a/chrome/browser/ui/app_list/arc/arc_app_utils.h b/chrome/browser/ui/app_list/arc/arc_app_utils.h
index 3384e31c..45f8aee5 100644
--- a/chrome/browser/ui/app_list/arc/arc_app_utils.h
+++ b/chrome/browser/ui/app_list/arc/arc_app_utils.h
@@ -206,7 +206,7 @@
 std::string AppIdToArcPackageName(const std::string& app_id, Profile* profile);
 
 // Returns the AppID for the specified package_name, which must be the package
-// name of an ARC app.
+// name of an ARC app or an empty string if name not found.
 std::string ArcPackageNameToAppId(const std::string& package_name,
                                   Profile* profile);
 
diff --git a/chrome/browser/ui/ash/media_client_impl.cc b/chrome/browser/ui/ash/media_client_impl.cc
index 833b53a..4386052 100644
--- a/chrome/browser/ui/ash/media_client_impl.cc
+++ b/chrome/browser/ui/ash/media_client_impl.cc
@@ -319,13 +319,12 @@
 
 void MediaClientImpl::OnCameraPrivacySwitchStatusChanged(
     cros::mojom::CameraPrivacySwitchState state) {
-  camera_privacy_switch_state_ = state;
-
   // Show camera privacy switch toast.
   switch (state) {
     case cros::mojom::CameraPrivacySwitchState::UNKNOWN:
       break;
     case cros::mojom::CameraPrivacySwitchState::ON: {
+      ash::ToastManager::Get()->Cancel(kCameraPrivacySwitchOffToastId);
       ash::ToastData toast(
           kCameraPrivacySwitchOnToastId,
           l10n_util::GetStringUTF16(IDS_CAMERA_PRIVACY_SWITCH_ON_TOAST),
@@ -336,6 +335,13 @@
       break;
     }
     case cros::mojom::CameraPrivacySwitchState::OFF: {
+      // Only show the "Camera is on" toast if the privacy switch state changed
+      // from ON (avoiding the toast when the state changes from UNKNOWN).
+      if (camera_privacy_switch_state_ !=
+          cros::mojom::CameraPrivacySwitchState::ON) {
+        break;
+      }
+      ash::ToastManager::Get()->Cancel(kCameraPrivacySwitchOnToastId);
       ash::ToastData toast(
           kCameraPrivacySwitchOffToastId,
           l10n_util::GetStringUTF16(IDS_CAMERA_PRIVACY_SWITCH_OFF_TOAST),
@@ -347,11 +353,12 @@
     }
   }
 
-  if (camera_privacy_switch_state_ ==
-      cros::mojom::CameraPrivacySwitchState::OFF) {
+  if (state == cros::mojom::CameraPrivacySwitchState::OFF) {
     SystemNotificationHelper::GetInstance()->Close(
         kCameraPrivacySwitchOnNotificationId);
   }
+
+  camera_privacy_switch_state_ = state;
 }
 
 void MediaClientImpl::OnActiveClientChange(cros::mojom::CameraClientType type,
diff --git a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarView.java b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarView.java
index 38ffe37..bdebb92 100644
--- a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarView.java
+++ b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarView.java
@@ -206,9 +206,16 @@
      * the mMessageView content description is read aloud if accessibility is enabled.
      */
     public void announceforAccessibility() {
-        mMessageView.announceForAccessibility(mMessageView.getContentDescription() + ". "
-                + mActionButtonView.getContentDescription() + ". "
-                + mContainerView.getResources().getString(R.string.bottom_bar_screen_position));
+        StringBuilder accessibilityText = new StringBuilder(mMessageView.getContentDescription());
+        if (mActionButtonView.getContentDescription() != null) {
+            accessibilityText.append(". ")
+                    .append(mActionButtonView.getContentDescription())
+                    .append(". ")
+                    .append(mContainerView.getResources().getString(
+                            R.string.bottom_bar_screen_position));
+        }
+
+        mMessageView.announceForAccessibility(accessibilityText);
     }
 
     /**
diff --git a/chrome/browser/ui/profile_picker.cc b/chrome/browser/ui/profile_picker.cc
index d5800f2..f0d6d2f 100644
--- a/chrome/browser/ui/profile_picker.cc
+++ b/chrome/browser/ui/profile_picker.cc
@@ -7,7 +7,6 @@
 #include <algorithm>
 #include <string>
 
-#include "base/feature_list.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/time/time.h"
 #include "chrome/browser/browser_process.h"
@@ -50,6 +49,9 @@
 
 }  // namespace
 
+const base::Feature kEnableProfilePickerOnStartupFeature{
+    "EnableProfilePickerOnStartup", base::FEATURE_ENABLED_BY_DEFAULT};
+
 // static
 bool ProfilePicker::ShouldShowAtLaunch() {
   AvailabilityOnStartup availability_on_startup = GetAvailabilityOnStartup();
@@ -57,6 +59,12 @@
   if (!base::FeatureList::IsEnabled(features::kNewProfilePicker))
     return false;
 
+  if (!base::FeatureList::IsEnabled(kEnableProfilePickerOnStartupFeature))
+    return false;
+
+  if (availability_on_startup == AvailabilityOnStartup::kDisabled)
+    return false;
+
   // TODO (crbug/1155158): Move this over the urls check (in
   // startup_browser_creator.cc) once the profile picker can forward urls
   // specified in command line.
diff --git a/chrome/browser/ui/profile_picker.h b/chrome/browser/ui/profile_picker.h
index a9bea828..1edd972 100644
--- a/chrome/browser/ui/profile_picker.h
+++ b/chrome/browser/ui/profile_picker.h
@@ -8,6 +8,7 @@
 #include <vector>
 
 #include "base/callback_forward.h"
+#include "base/feature_list.h"
 #include "base/time/time.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "url/gurl.h"
@@ -27,6 +28,10 @@
 class WebView;
 }  // namespace views
 
+// Kill switch to disable showing the picker on startup. Has no effect if
+// features::kNewProfilePicker is disabled.
+extern const base::Feature kEnableProfilePickerOnStartupFeature;
+
 class ProfilePicker {
  public:
   // An entry point that triggers the profile picker window to open.
diff --git a/chrome/browser/ui/profile_picker_unittest.cc b/chrome/browser/ui/profile_picker_unittest.cc
index e531160..f26cf1f 100644
--- a/chrome/browser/ui/profile_picker_unittest.cc
+++ b/chrome/browser/ui/profile_picker_unittest.cc
@@ -66,6 +66,18 @@
   task_environment()->FastForwardBy(base::TimeDelta::FromDays(27));
   EXPECT_TRUE(ProfilePicker::ShouldShowAtLaunch());
 }
+TEST_F(ProfilePickerTest, ShouldShowAtLaunch_KillSwitch) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndDisableFeature(kEnableProfilePickerOnStartupFeature);
+
+  TestingProfile* profile1 =
+      testing_profile_manager()->CreateTestingProfile("profile1");
+  GetProfileAttributes(profile1)->SetActiveTimeToNow();
+  TestingProfile* profile2 =
+      testing_profile_manager()->CreateTestingProfile("profile2");
+  GetProfileAttributes(profile2)->SetActiveTimeToNow();
+  EXPECT_FALSE(ProfilePicker::ShouldShowAtLaunch());
+}
 
 TEST_F(ProfilePickerTest,
        ShouldShowAtLaunch_MultipleProfiles_Inactive_SeenPicker) {
diff --git a/chrome/browser/ui/thumbnails/background_thumbnail_video_capturer.cc b/chrome/browser/ui/thumbnails/background_thumbnail_video_capturer.cc
index 58bf412..b3d427d3 100644
--- a/chrome/browser/ui/thumbnails/background_thumbnail_video_capturer.cc
+++ b/chrome/browser/ui/thumbnails/background_thumbnail_video_capturer.cc
@@ -9,6 +9,7 @@
 
 #include "base/metrics/histogram_macros.h"
 #include "base/trace_event/trace_event.h"
+#include "base/trace_event/trace_id_helper.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host.h"
@@ -128,6 +129,10 @@
                        num_received_frames_);
   ++num_received_frames_;
 
+  uint64_t frame_id = base::trace_event::GetNextGlobalTraceId();
+  TRACE_EVENT_WITH_FLOW0("ui", "Tab.Preview.ProcessVideoCaptureFrame", frame_id,
+                         TRACE_EVENT_FLAG_FLOW_OUT);
+
   // The SkBitmap's pixels will be marked as immutable, but the installPixels()
   // API requires a non-const pointer. So, cast away the const.
   void* const pixels = const_cast<void*>(mapping.memory());
@@ -172,15 +177,18 @@
   frame.setImmutable();
 
   SkBitmap cropped_frame;
-  if (frame.extractSubset(&cropped_frame,
-                          gfx::RectToSkIRect(effective_content_rect))) {
-    UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
-        "Tab.Preview.TimeToStoreAfterFrameReceived",
-        base::TimeTicks::Now() - time_of_call,
-        base::TimeDelta::FromMicroseconds(10),
-        base::TimeDelta::FromMilliseconds(10), 50);
-    got_frame_callback_.Run(cropped_frame);
+  if (!frame.extractSubset(&cropped_frame,
+                           gfx::RectToSkIRect(effective_content_rect))) {
+    return;
   }
+
+  UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
+      "Tab.Preview.TimeToStoreAfterFrameReceived",
+      base::TimeTicks::Now() - time_of_call,
+      base::TimeDelta::FromMicroseconds(10),
+      base::TimeDelta::FromMilliseconds(10), 50);
+
+  got_frame_callback_.Run(cropped_frame, frame_id);
 }
 
 void BackgroundThumbnailVideoCapturer::OnStopped() {}
diff --git a/chrome/browser/ui/thumbnails/background_thumbnail_video_capturer.h b/chrome/browser/ui/thumbnails/background_thumbnail_video_capturer.h
index f373ff5..06780a0 100644
--- a/chrome/browser/ui/thumbnails/background_thumbnail_video_capturer.h
+++ b/chrome/browser/ui/thumbnails/background_thumbnail_video_capturer.h
@@ -24,7 +24,11 @@
     : public BackgroundThumbnailCapturer,
       public viz::mojom::FrameSinkVideoConsumer {
  public:
-  using GotFrameCallback = base::RepeatingCallback<void(const SkBitmap&)>;
+  // Client receives `SkBitmap` frames and `uin64_t` unique IDs for each
+  // frame. IDs are globally unique for a given browser process and are
+  // used for TRACE_EVENT_FLOW_* macros
+  using GotFrameCallback =
+      base::RepeatingCallback<void(const SkBitmap&, uint64_t)>;
   BackgroundThumbnailVideoCapturer(content::WebContents* contents,
                                    GotFrameCallback got_frame_callback);
   ~BackgroundThumbnailVideoCapturer() override;
diff --git a/chrome/browser/ui/thumbnails/thumbnail_image.cc b/chrome/browser/ui/thumbnails/thumbnail_image.cc
index 171f1df..6a9ac4f 100644
--- a/chrome/browser/ui/thumbnails/thumbnail_image.cc
+++ b/chrome/browser/ui/thumbnails/thumbnail_image.cc
@@ -13,6 +13,7 @@
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
 #include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
 #include "chrome/browser/ui/thumbnails/thumbnail_stats_tracker.h"
 #include "ui/gfx/codec/jpeg_codec.h"
 #include "ui/gfx/skia_util.h"
@@ -58,14 +59,17 @@
   return subscription;
 }
 
-void ThumbnailImage::AssignSkBitmap(SkBitmap bitmap) {
+void ThumbnailImage::AssignSkBitmap(SkBitmap bitmap,
+                                    base::Optional<uint64_t> frame_id) {
   base::ThreadPool::PostTaskAndReplyWithResult(
       FROM_HERE,
       {base::TaskPriority::USER_VISIBLE,
        base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
-      base::BindOnce(&ThumbnailImage::CompressBitmap, std::move(bitmap)),
+      base::BindOnce(&ThumbnailImage::CompressBitmap, std::move(bitmap),
+                     frame_id),
       base::BindOnce(&ThumbnailImage::AssignJPEGData,
-                     weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now()));
+                     weak_ptr_factory_.GetWeakPtr(), base::TimeTicks::Now(),
+                     frame_id));
 }
 
 void ThumbnailImage::ClearData() {
@@ -101,16 +105,34 @@
 }
 
 void ThumbnailImage::AssignJPEGData(base::TimeTicks assign_sk_bitmap_time,
+                                    base::Optional<uint64_t> frame_id,
                                     std::vector<uint8_t> data) {
   data_ = base::MakeRefCounted<base::RefCountedData<std::vector<uint8_t>>>(
       std::move(data));
+
   UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES(
       "Tab.Preview.TimeToNotifyObserversAfterCaptureReceived",
       base::TimeTicks::Now() - assign_sk_bitmap_time,
       base::TimeDelta::FromMicroseconds(100),
       base::TimeDelta::FromMilliseconds(100), 50);
-  NotifyCompressedDataObservers(data_);
-  ConvertJPEGDataToImageSkiaAndNotifyObservers();
+
+  // We select a TRACE_EVENT_* macro based on |frame_id|'s presence.
+  // Since these are scoped traces, the macro invocation must be in the
+  // enclosing scope of these operations. Extract them into a common
+  // function.
+  auto notify = [&]() {
+    NotifyCompressedDataObservers(data_);
+    ConvertJPEGDataToImageSkiaAndNotifyObservers();
+  };
+
+  if (frame_id) {
+    TRACE_EVENT_WITH_FLOW0("ui", "Tab.Preview.JPEGReceivedOnUIThreadWithFlow",
+                           *frame_id, TRACE_EVENT_FLAG_FLOW_IN);
+    notify();
+  } else {
+    TRACE_EVENT0("ui", "Tab.Preview.JPEGReceivedOnUIThread");
+    notify();
+  }
 }
 
 bool ThumbnailImage::ConvertJPEGDataToImageSkiaAndNotifyObservers() {
@@ -153,12 +175,30 @@
 }
 
 // static
-std::vector<uint8_t> ThumbnailImage::CompressBitmap(SkBitmap bitmap) {
+std::vector<uint8_t> ThumbnailImage::CompressBitmap(
+    SkBitmap bitmap,
+    base::Optional<uint64_t> frame_id) {
   constexpr int kCompressionQuality = 97;
   std::vector<uint8_t> data;
-  const bool result =
-      gfx::JPEGCodec::Encode(bitmap, kCompressionQuality, &data);
-  DCHECK(result);
+
+  // Similar to above, extract logic into function so we can select a
+  // TRACE_EVENT_* macro.
+  auto compress = [&]() {
+    const bool result =
+        gfx::JPEGCodec::Encode(bitmap, kCompressionQuality, &data);
+    DCHECK(result);
+  };
+
+  if (frame_id) {
+    TRACE_EVENT_WITH_FLOW0(
+        "ui", "Tab.Preview.CompressJPEGWithFlow", *frame_id,
+        TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
+    compress();
+  } else {
+    TRACE_EVENT0("ui", "Tab.Preview.CompressJPEG");
+    compress();
+  }
+
   return data;
 }
 
diff --git a/chrome/browser/ui/thumbnails/thumbnail_image.h b/chrome/browser/ui/thumbnails/thumbnail_image.h
index 20646d41..0ea860b 100644
--- a/chrome/browser/ui/thumbnails/thumbnail_image.h
+++ b/chrome/browser/ui/thumbnails/thumbnail_image.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_UI_THUMBNAILS_THUMBNAIL_IMAGE_H_
 #define CHROME_BROWSER_UI_THUMBNAILS_THUMBNAIL_IMAGE_H_
 
+#include <stdint.h>
 #include <memory>
 #include <utility>
 #include <vector>
@@ -113,7 +114,8 @@
   std::unique_ptr<Subscription> Subscribe();
 
   // Sets the SkBitmap data and notifies observers with the resulting image.
-  void AssignSkBitmap(SkBitmap bitmap);
+  void AssignSkBitmap(SkBitmap bitmap,
+                      base::Optional<uint64_t> frame_id = base::nullopt);
 
   // Clears the currently set |data_|, for when the current thumbnail is no
   // longer valid to display.
@@ -148,12 +150,14 @@
   virtual ~ThumbnailImage();
 
   void AssignJPEGData(base::TimeTicks assign_sk_bitmap_time,
+                      base::Optional<uint64_t> frame_id,
                       std::vector<uint8_t> data);
   bool ConvertJPEGDataToImageSkiaAndNotifyObservers();
   void NotifyUncompressedDataObservers(gfx::ImageSkia image);
   void NotifyCompressedDataObservers(CompressedThumbnailData data);
 
-  static std::vector<uint8_t> CompressBitmap(SkBitmap bitmap);
+  static std::vector<uint8_t> CompressBitmap(SkBitmap bitmap,
+                                             base::Optional<uint64_t> frame_id);
   static gfx::ImageSkia UncompressImage(CompressedThumbnailData compressed);
 
   // Crops and returns a preview from a thumbnail of an entire web page. Uses
diff --git a/chrome/browser/ui/thumbnails/thumbnail_image_unittest.cc b/chrome/browser/ui/thumbnails/thumbnail_image_unittest.cc
index f97c137..e529184 100644
--- a/chrome/browser/ui/thumbnails/thumbnail_image_unittest.cc
+++ b/chrome/browser/ui/thumbnails/thumbnail_image_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/bind.h"
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/scoped_observer.h"
 #include "base/test/task_environment.h"
@@ -89,7 +90,7 @@
   }
 
   std::vector<uint8_t> Compress(SkBitmap bitmap) const {
-    return ThumbnailImage::CompressBitmap(bitmap);
+    return ThumbnailImage::CompressBitmap(bitmap, base::nullopt);
   }
 
   bool is_being_observed() const { return is_being_observed_; }
@@ -149,7 +150,7 @@
       IgnoreArgs<gfx::ImageSkia>(waiter2.callback()));
 
   SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight);
-  image->AssignSkBitmap(bitmap);
+  image->AssignSkBitmap(bitmap, base::nullopt);
 
   waiter1.Wait();
   waiter2.Wait();
@@ -172,7 +173,7 @@
       IgnoreArgs<gfx::ImageSkia>(waiter2.callback()));
 
   SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight);
-  image->AssignSkBitmap(bitmap);
+  image->AssignSkBitmap(bitmap, base::nullopt);
 
   waiter1.Wait();
   waiter2.Wait();
@@ -182,7 +183,7 @@
   waiter1.Reset();
   waiter2.Reset();
 
-  image->AssignSkBitmap(bitmap);
+  image->AssignSkBitmap(bitmap, base::nullopt);
 
   waiter1.Wait();
   waiter2.Wait();
@@ -205,7 +206,7 @@
       IgnoreArgs<ThumbnailImage::CompressedThumbnailData>(waiter2.callback()));
 
   SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight);
-  image->AssignSkBitmap(bitmap);
+  image->AssignSkBitmap(bitmap, base::nullopt);
 
   waiter1.Wait();
   waiter2.Wait();
@@ -228,7 +229,7 @@
       IgnoreArgs<ThumbnailImage::CompressedThumbnailData>(waiter2.callback()));
 
   SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight);
-  image->AssignSkBitmap(bitmap);
+  image->AssignSkBitmap(bitmap, base::nullopt);
 
   waiter1.Wait();
   waiter2.Wait();
@@ -238,7 +239,7 @@
   waiter1.Reset();
   waiter2.Reset();
 
-  image->AssignSkBitmap(bitmap);
+  image->AssignSkBitmap(bitmap, base::nullopt);
 
   waiter1.Wait();
   waiter2.Wait();
@@ -256,7 +257,7 @@
       IgnoreArgs<gfx::ImageSkia>(waiter1.callback()));
 
   SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight);
-  image->AssignSkBitmap(bitmap);
+  image->AssignSkBitmap(bitmap, base::nullopt);
   waiter1.Wait();
   EXPECT_TRUE(waiter1.called());
   waiter1.Reset();
@@ -284,7 +285,7 @@
       IgnoreArgs<ThumbnailImage::CompressedThumbnailData>(waiter.callback()));
 
   SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight);
-  image->AssignSkBitmap(bitmap);
+  image->AssignSkBitmap(bitmap, base::nullopt);
   waiter.Wait();
   EXPECT_TRUE(waiter.called());
   waiter.Reset();
@@ -304,7 +305,7 @@
       IgnoreArgs<gfx::ImageSkia>(waiter.callback()));
 
   SkBitmap bitmap = CreateBitmap(kTestBitmapWidth, kTestBitmapHeight);
-  image->AssignSkBitmap(bitmap);
+  image->AssignSkBitmap(bitmap, base::nullopt);
   waiter.Wait();
   EXPECT_TRUE(waiter.called());
   waiter.Reset();
diff --git a/chrome/browser/ui/thumbnails/thumbnail_tab_helper.cc b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.cc
index 3f8eb9d..45d52d8 100644
--- a/chrome/browser/ui/thumbnails/thumbnail_tab_helper.cc
+++ b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ui/thumbnails/thumbnail_tab_helper.h"
 
+#include <stdint.h>
 #include <algorithm>
 #include <set>
 #include <utility>
@@ -12,6 +13,7 @@
 #include "base/check_op.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/no_destructor.h"
+#include "base/optional.h"
 #include "base/task/post_task.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
@@ -217,9 +219,9 @@
     : state_(std::make_unique<TabStateTracker>(this, contents)),
       background_capturer_(std::make_unique<BackgroundThumbnailVideoCapturer>(
           contents,
-          base::BindRepeating(&ThumbnailTabHelper::StoreThumbnail,
-                              base::Unretained(this),
-                              CaptureType::kVideoFrame))),
+          base::BindRepeating(
+              &ThumbnailTabHelper::StoreThumbnailForBackgroundCapture,
+              base::Unretained(this)))),
       thumbnail_(base::MakeRefCounted<ThumbnailImage>(state_.get())) {}
 
 ThumbnailTabHelper::~ThumbnailTabHelper() {
@@ -274,11 +276,18 @@
                              base::TimeTicks::Now() - start_time,
                              base::TimeDelta::FromMilliseconds(1),
                              base::TimeDelta::FromSeconds(1), 50);
-  StoreThumbnail(CaptureType::kCopyFromView, bitmap);
+  StoreThumbnail(CaptureType::kCopyFromView, bitmap, base::nullopt);
+}
+
+void ThumbnailTabHelper::StoreThumbnailForBackgroundCapture(
+    const SkBitmap& bitmap,
+    uint64_t frame_id) {
+  StoreThumbnail(CaptureType::kVideoFrame, bitmap, frame_id);
 }
 
 void ThumbnailTabHelper::StoreThumbnail(CaptureType type,
-                                        const SkBitmap& bitmap) {
+                                        const SkBitmap& bitmap,
+                                        base::Optional<uint64_t> frame_id) {
   // Failed requests will return an empty bitmap. In tests this can be triggered
   // on threads other than the UI thread.
   if (bitmap.drawsNothing())
@@ -288,7 +297,7 @@
 
   RecordCaptureType(type);
   state_->OnFrameCaptured(type);
-  thumbnail_->AssignSkBitmap(bitmap);
+  thumbnail_->AssignSkBitmap(bitmap, frame_id);
 }
 
 void ThumbnailTabHelper::ClearData() {
diff --git a/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h
index 435a0b11..0c04b03 100644
--- a/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h
+++ b/chrome/browser/ui/thumbnails/thumbnail_tab_helper.h
@@ -9,6 +9,7 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "base/optional.h"
 #include "base/scoped_observer.h"
 #include "base/time/time.h"
 #include "chrome/browser/ui/thumbnails/thumbnail_capture_info.h"
@@ -48,9 +49,15 @@
   void StartVideoCapture();
   void StopVideoCapture();
   void CaptureThumbnailOnTabHidden();
+
   void StoreThumbnailForTabSwitch(base::TimeTicks start_time,
                                   const SkBitmap& bitmap);
-  void StoreThumbnail(CaptureType type, const SkBitmap& bitmap);
+  void StoreThumbnailForBackgroundCapture(const SkBitmap& bitmap,
+                                          uint64_t frame_id);
+  void StoreThumbnail(CaptureType type,
+                      const SkBitmap& bitmap,
+                      base::Optional<uint64_t> frame_id);
+
   // Clears the data associated to the currently set thumbnail. For when the
   // thumbnail is no longer valid.
   void ClearData();
diff --git a/chrome/browser/ui/views/drag_and_drop_interactive_uitest.cc b/chrome/browser/ui/views/drag_and_drop_interactive_uitest.cc
index 142afff..598f570 100644
--- a/chrome/browser/ui/views/drag_and_drop_interactive_uitest.cc
+++ b/chrome/browser/ui/views/drag_and_drop_interactive_uitest.cc
@@ -1250,9 +1250,10 @@
                    {"dragstart", "dragleave", "dragenter", "dragend"}));
 }
 
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_LINUX)
 // There is no known way to execute test-controlled tasks during
 // a drag-and-drop loop run by Windows OS.
+// Also disable the test on Linux due to flaky: crbug.com/1164442
 #define MAYBE_DragImageFromDisappearingFrame \
   DISABLED_DragImageFromDisappearingFrame
 #else
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
index 14b129d..7eef082 100644
--- a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
+++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
@@ -318,9 +318,8 @@
 
 void MediaDialogView::OnSodaError() {
   ToggleLiveCaption(false);
-  live_caption_title_->SetText(
-      l10n_util::GetStringUTF16(IDS_GLOBAL_MEDIA_CONTROLS_LIVE_CAPTION));
-  // TODO(crbug.com/1055150): Show an error message as a toast.
+  live_caption_title_->SetText(l10n_util::GetStringUTF16(
+      IDS_GLOBAL_MEDIA_CONTROLS_LIVE_CAPTION_DOWNLOAD_ERROR));
 }
 
 void MediaDialogView::OnSodaProgress(int progress) {
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
index ac1fc3f..ce69256 100644
--- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
+++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -49,7 +49,6 @@
 #include "chrome/grit/browser_resources.h"
 #include "chrome/grit/chromium_strings.h"
 #include "chrome/grit/generated_resources.h"
-#include "chrome/grit/pdf_resources.h"
 #include "chrome/grit/print_preview_resources.h"
 #include "chrome/grit/print_preview_resources_map.h"
 #include "chromeos/constants/chromeos_features.h"
@@ -409,34 +408,6 @@
 }
 
 void SetupPrintPreviewPlugin(content::WebUIDataSource* source) {
-  static constexpr webui::ResourcePath kPdfResources[] = {
-      {"pdf/browser_api.js", IDR_PDF_BROWSER_API_JS},
-      {"pdf/constants.js", IDR_PDF_CONSTANTS_JS},
-      {"pdf/controller.js", IDR_PDF_CONTROLLER_JS},
-      {"pdf/elements/icons.js", IDR_PDF_ELEMENTS_ICONS_JS},
-      {"pdf/elements/shared-vars.js", IDR_PDF_ELEMENTS_SHARED_VARS_JS},
-      {"pdf/elements/viewer-error-screen.js",
-       IDR_PDF_ELEMENTS_VIEWER_ERROR_SCREEN_JS},
-      {"pdf/elements/viewer-zoom-button.js",
-       IDR_PDF_ELEMENTS_VIEWER_ZOOM_BUTTON_JS},
-      {"pdf/elements/viewer-zoom-toolbar.js",
-       IDR_PDF_ELEMENTS_VIEWER_ZOOM_TOOLBAR_JS},
-      {"pdf/gesture_detector.js", IDR_PDF_GESTURE_DETECTOR_JS},
-      {"pdf/index.css", IDR_PDF_INDEX_CSS},
-      {"pdf/main.js", IDR_PDF_MAIN_JS},
-      {"pdf/metrics.js", IDR_PDF_METRICS_JS},
-      {"pdf/open_pdf_params_parser.js", IDR_PDF_OPEN_PDF_PARAMS_PARSER_JS},
-      {"pdf/pdf_scripting_api.js", IDR_PDF_PDF_SCRIPTING_API_JS},
-      {"pdf/pdf_viewer_base.js", IDR_PDF_PDF_VIEWER_BASE_JS},
-      {"pdf/pdf_viewer_shared_style.js", IDR_PDF_PDF_VIEWER_SHARED_STYLE_JS},
-      {"pdf/pdf_viewer_utils.js", IDR_PDF_PDF_VIEWER_UTILS_JS},
-      {"pdf/toolbar_manager.js", IDR_PDF_TOOLBAR_MANAGER_JS},
-      {"pdf/viewport.js", IDR_PDF_VIEWPORT_JS},
-      {"pdf/viewport_scroller.js", IDR_PDF_VIEWPORT_SCROLLER_JS},
-      {"pdf/zoom_manager.js", IDR_PDF_ZOOM_MANAGER_JS},
-  };
-  webui::AddResourcePathsBulk(source, kPdfResources);
-
   source->SetRequestFilter(base::BindRepeating(&ShouldHandleRequestCallback),
                            base::BindRepeating(&HandleRequestCallback));
   source->OverrideContentSecurityPolicy(
diff --git a/chrome/browser/ui/webui/settings/chromeos/accessibility_section.cc b/chrome/browser/ui/webui/settings/chromeos/accessibility_section.cc
index 5d861f94..79d131d 100644
--- a/chrome/browser/ui/webui/settings/chromeos/accessibility_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/accessibility_section.cc
@@ -196,12 +196,6 @@
        mojom::SearchResultDefaultRank::kMedium,
        mojom::SearchResultType::kSetting,
        {.setting = mojom::Setting::kFullscreenMagnifier}},
-      {IDS_OS_SETTINGS_TAG_A11Y_FULLSCREEN_MAGNIFIER_FOCUS_FOLLOWING,
-       mojom::kManageAccessibilitySubpagePath,
-       mojom::SearchResultIcon::kA11y,
-       mojom::SearchResultDefaultRank::kMedium,
-       mojom::SearchResultType::kSetting,
-       {.setting = mojom::Setting::kFullscreenMagnifierFocusFollowing}},
       {IDS_OS_SETTINGS_TAG_A11Y_ENABLE_SWITCH_ACCESS,
        mojom::kManageAccessibilitySubpagePath,
        mojom::SearchResultIcon::kA11y,
@@ -321,6 +315,19 @@
   return *tags;
 }
 
+const std::vector<SearchConcept>&
+GetA11yFullscreenMagnifierFocusFollowingSearchConcepts() {
+  static const base::NoDestructor<std::vector<SearchConcept>> tags({
+      {IDS_OS_SETTINGS_TAG_A11Y_FULLSCREEN_MAGNIFIER_FOCUS_FOLLOWING,
+       mojom::kManageAccessibilitySubpagePath,
+       mojom::SearchResultIcon::kA11y,
+       mojom::SearchResultDefaultRank::kMedium,
+       mojom::SearchResultType::kSetting,
+       {.setting = mojom::Setting::kFullscreenMagnifierFocusFollowing}},
+  });
+  return *tags;
+}
+
 bool AreExperimentalA11yLabelsAllowed() {
   return base::FeatureList::IsEnabled(
       ::features::kExperimentalAccessibilityLabels);
@@ -334,6 +341,10 @@
   return features::IsAccessibilityCursorColorEnabled();
 }
 
+bool IsMagnifierPanningImprovementsEnabled() {
+  return features::IsMagnifierPanningImprovementsEnabled();
+}
+
 bool IsSwitchAccessTextAllowed() {
   return base::CommandLine::ForCurrentProcess()->HasSwitch(
       ::switches::kEnableExperimentalAccessibilitySwitchAccessText);
@@ -644,6 +655,9 @@
   html_source->AddBoolean("showExperimentalAccessibilityCursorColor",
                           IsCursorColorAllowed());
 
+  html_source->AddBoolean("isMagnifierPanningImprovementsEnabled",
+                          IsMagnifierPanningImprovementsEnabled());
+
   ::settings::AddCaptionSubpageStrings(html_source);
 }
 
@@ -831,6 +845,14 @@
     updater.RemoveSearchTags(GetA11yCursorColorSearchConcepts());
   }
 
+  if (IsMagnifierPanningImprovementsEnabled()) {
+    updater.AddSearchTags(
+        GetA11yFullscreenMagnifierFocusFollowingSearchConcepts());
+  } else {
+    updater.RemoveSearchTags(
+        GetA11yFullscreenMagnifierFocusFollowingSearchConcepts());
+  }
+
   if (!pref_service_->GetBoolean(
           ash::prefs::kAccessibilitySwitchAccessEnabled)) {
     return;
diff --git a/chrome/browser/ui/webui/signin/profile_picker_ui.cc b/chrome/browser/ui/webui/signin/profile_picker_ui.cc
index 7e790be..16da9bb 100644
--- a/chrome/browser/ui/webui/signin/profile_picker_ui.cc
+++ b/chrome/browser/ui/webui/signin/profile_picker_ui.cc
@@ -129,9 +129,11 @@
       static_cast<ProfilePicker::AvailabilityOnStartup>(
           g_browser_process->local_state()->GetInteger(
               prefs::kBrowserProfilePickerAvailabilityOnStartup));
-  html_source->AddBoolean("disableAskOnStartup",
-                          availability_on_startup !=
-                              ProfilePicker::AvailabilityOnStartup::kEnabled);
+  bool disable_ask_on_startup =
+      availability_on_startup !=
+          ProfilePicker::AvailabilityOnStartup::kEnabled ||
+      !base::FeatureList::IsEnabled(kEnableProfilePickerOnStartupFeature);
+  html_source->AddBoolean("disableAskOnStartup", disable_ask_on_startup);
   html_source->AddBoolean("askOnStartup",
                           g_browser_process->local_state()->GetBoolean(
                               prefs::kBrowserShowProfilePickerOnStartup));
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 724fbda..dcdf088 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-master-1610452567-fdff272b709a6fb84edf0325fafb43e63f345a7e.profdata
+chrome-linux-master-1610474333-25cc4688b5885ba387e87620f7adfe156a967401.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 136543f13..7e608c9 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-master-1610452567-9a68a195870106cae6c4ac4841f20ff7b185cdf9.profdata
+chrome-mac-master-1610474333-6e9ea86fde1168dfc05bd82ef581aacfe157db52.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index e100ab3..a081a0a 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-master-1610452567-971e6bfbeacac133e734933b87972f0e8c85e431.profdata
+chrome-win32-master-1610474333-c40f8988181199af819c164a2a0a3aef267d7bde.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 7aa58eb2..c978b2c 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-master-1610463436-2052566ba20716214eb6d7caa0887c28794c37bd.profdata
+chrome-win64-master-1610474333-dd150f7e1f8853577c8d1e97bbf4737322a5d0b4.profdata
diff --git a/chrome/common/extensions/chrome_extensions_client.cc b/chrome/common/extensions/chrome_extensions_client.cc
index 70e950a..db156f0 100644
--- a/chrome/common/extensions/chrome_extensions_client.cc
+++ b/chrome/common/extensions/chrome_extensions_client.cc
@@ -19,7 +19,6 @@
 #include "chrome/common/url_constants.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/grit/chromium_strings.h"
-#include "components/version_info/version_info.h"
 #include "content/public/common/url_constants.h"
 #include "extensions/common/api/extension_action/action_info.h"
 #include "extensions/common/constants.h"
@@ -28,7 +27,6 @@
 #include "extensions/common/extension_api.h"
 #include "extensions/common/extension_icon_set.h"
 #include "extensions/common/extension_urls.h"
-#include "extensions/common/features/feature_channel.h"
 #include "extensions/common/manifest.h"
 #include "extensions/common/manifest_constants.h"
 #include "extensions/common/manifest_handlers/icons_handler.h"
@@ -218,12 +216,6 @@
   return image_paths;
 }
 
-bool ChromeExtensionsClient::ExtensionAPIEnabledInExtensionServiceWorkers()
-    const {
-  return GetCurrentChannel() <=
-         extension_misc::kMinChannelForServiceWorkerBasedExtension;
-}
-
 void ChromeExtensionsClient::AddOriginAccessPermissions(
     const Extension& extension,
     bool is_extension_active,
diff --git a/chrome/common/extensions/chrome_extensions_client.h b/chrome/common/extensions/chrome_extensions_client.h
index c6d19ad..914816f 100644
--- a/chrome/common/extensions/chrome_extensions_client.h
+++ b/chrome/common/extensions/chrome_extensions_client.h
@@ -43,7 +43,6 @@
   bool IsBlacklistUpdateURL(const GURL& url) const override;
   std::set<base::FilePath> GetBrowserImagePaths(
       const Extension* extension) override;
-  bool ExtensionAPIEnabledInExtensionServiceWorkers() const override;
   void AddOriginAccessPermissions(
       const Extension& extension,
       bool is_extension_active,
diff --git a/chrome/renderer/extensions/chrome_extensions_renderer_client.cc b/chrome/renderer/extensions/chrome_extensions_renderer_client.cc
index 31ff2ef..acdd320 100644
--- a/chrome/renderer/extensions/chrome_extensions_renderer_client.cc
+++ b/chrome/renderer/extensions/chrome_extensions_renderer_client.cc
@@ -30,7 +30,6 @@
 #include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
 #include "extensions/common/extension_set.h"
-#include "extensions/common/extensions_client.h"
 #include "extensions/common/manifest_handlers/background_info.h"
 #include "extensions/common/permissions/permissions_data.h"
 #include "extensions/common/switches.h"
@@ -118,10 +117,6 @@
   if (!script_url.SchemeIs(extensions::kExtensionScheme))
     return false;
 
-  if (!extensions::ExtensionsClient::Get()
-           ->ExtensionAPIEnabledInExtensionServiceWorkers())
-    return false;
-
   const Extension* extension =
       extensions::RendererExtensionRegistry::Get()->GetExtensionOrAppByURL(
           script_url);
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/batch/BlankCTATabInitialStateRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/batch/BlankCTATabInitialStateRule.java
index 8a8903d..6f6ada94 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/batch/BlankCTATabInitialStateRule.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/batch/BlankCTATabInitialStateRule.java
@@ -11,7 +11,9 @@
 import org.chromium.base.test.util.Batch;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.firstrun.FirstRunStatus;
+import org.chromium.chrome.browser.incognito.IncognitoUtils;
 import org.chromium.chrome.browser.tab.TabLaunchType;
+import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.tabmodel.TabModelUtils;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.content_public.browser.test.util.TestThreadUtils;
@@ -81,9 +83,12 @@
     // quickly, at the cost of thoroughness. This should be adequate for most tests.
     private void resetTabStateFast() {
         TestThreadUtils.runOnUiThreadBlocking(() -> {
-            // Close all but the first tab as these tests expect to start with a single
+            IncognitoUtils.closeAllIncognitoTabs();
+            // Close all but the first regular tab as these tests expect to start with a single
             // tab.
-            while (TabModelUtils.closeTabByIndex(sActivity.getCurrentTabModel(), 1)) {
+            TabModel regularTabModel =
+                    sActivity.getTabModelSelector().getModel(/*incognito=*/false);
+            while (TabModelUtils.closeTabByIndex(regularTabModel, 1)) {
             }
         });
         mActivityTestRule.loadUrl("about:blank");
diff --git a/chrome/test/data/extensions/api_test/mime_handler_view/manifest.json b/chrome/test/data/extensions/api_test/mime_handler_view/manifest.json
index 754a917..29e535b 100644
--- a/chrome/test/data/extensions/api_test/mime_handler_view/manifest.json
+++ b/chrome/test/data/extensions/api_test/mime_handler_view/manifest.json
@@ -1,4 +1,6 @@
 {
+  // This extension's id is allowed to handle mime types.
+  // chrome-extension://oickdpebdnfbgkcaoklfcdhjniefkcji
   "name": "Test MIMEHandlerView",
   "version": "1",
   "manifest_version": 2,
diff --git a/chrome/test/data/pdf/viewer_properties_dialog_test.js b/chrome/test/data/pdf/viewer_properties_dialog_test.js
index f177425..513a4f5 100644
--- a/chrome/test/data/pdf/viewer_properties_dialog_test.js
+++ b/chrome/test/data/pdf/viewer_properties_dialog_test.js
@@ -55,7 +55,7 @@
      ['title', 'Sample PDF Document Info'],
      ['author', 'Chromium Authors'],
      ['subject', 'Testing'],
-     ['keywords', '-'],
+     ['keywords', 'testing,chromium,pdfium,document,info'],
      ['created', '-'],
      ['modified', '-'],
      ['application', 'Your Preferred Text Editor'],
diff --git a/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn b/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn
index 792a3c8..a07515ec 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn
+++ b/chrome/test/data/webui/chromeos/diagnostics/BUILD.gn
@@ -241,6 +241,7 @@
     "//chromeos/components/diagnostics_ui/resources:routine_result_entry",
     "//chromeos/components/diagnostics_ui/resources:routine_section",
     "//chromeos/components/diagnostics_ui/resources:text_badge",
+    "//third_party/polymer/v3_0/components-chromium/iron-collapse:iron-collapse",
     "//ui/webui/resources/cr_elements/cr_button:cr_button.m",
   ]
 }
diff --git a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_test_utils.js b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_test_utils.js
index dbc5aed..ca8f0a0b 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/diagnostics_test_utils.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/diagnostics_test_utils.js
@@ -96,19 +96,6 @@
 }
 
 /**
- * Helper function for getting the Show/Hide Tests Report button from a
- * routine-section.
- * @param {?RoutineSectionElement} element
- * @return {!CrButtonElement}
- */
-export function getLearnMoreButtonFromSection(element) {
-  const button =
-      /** @type {!CrButtonElement} */ (element.$$('#learnMoreButton'));
-  assertTrue(!!button);
-  return button;
-}
-
-/**
  * Helper function to check if a substring exists in an element.
  * @param {?Element} element
  * @param {string} text substring to check
diff --git a/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js b/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js
index 42dd4bfa..d35594b5 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/routine_result_entry_test.js
@@ -10,7 +10,9 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 
 import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
-import {flushTasks} from '../../test_util.m.js';
+import {flushTasks, isVisible} from '../../test_util.m.js';
+
+import * as dx_utils from './diagnostics_test_utils.js';
 
 export function routineResultEntryTestSuite() {
   /** @type {?RoutineResultEntryElement} */
@@ -124,9 +126,12 @@
               'routineEntryText',
               loadTimeData.getString('cpuStressRoutineText')));
 
-      // Status should be empty if the test is not started.
-      // TODO(joonbug): Utilize isVisible util function.
-      assertTrue(getStatusBadge().hidden);
+      // Status should be queued if the test is not started.
+      assertTrue(isVisible(getStatusBadge()));
+      assertEquals(getStatusBadge().badgeType, BadgeType.QUEUED);
+      dx_utils.assertTextContains(
+          getStatusBadge().value,
+          loadTimeData.getString('testQueuedBadgeText'));
     });
   });
 
@@ -142,8 +147,10 @@
               loadTimeData.getString('cpuStressRoutineText')));
 
       // Status should be running.
-      assertEquals(getStatusBadge().value, 'RUNNING');
-      assertEquals(getStatusBadge().badgeType, BadgeType.DEFAULT);
+      dx_utils.assertTextContains(
+          getStatusBadge().value,
+          loadTimeData.getString('testRunningBadgeText'));
+      assertEquals(getStatusBadge().badgeType, BadgeType.RUNNING);
     });
   });
 
diff --git a/chrome/test/data/webui/chromeos/diagnostics/routine_section_test.js b/chrome/test/data/webui/chromeos/diagnostics/routine_section_test.js
index a3e646c..bda4ec7 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/routine_section_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/routine_section_test.js
@@ -14,7 +14,7 @@
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 
 import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
-import {flushTasks} from '../../test_util.m.js';
+import {flushTasks, isVisible} from '../../test_util.m.js';
 
 import * as dx_utils from './diagnostics_test_utils.js';
 
@@ -106,14 +106,6 @@
   }
 
   /**
-   * Returns the learn more help button.
-   * @return {!CrButtonElement}
-   */
-  function getLearnMoreButton() {
-    return dx_utils.getLearnMoreButtonFromSection(routineSectionElement);
-  }
-
-  /**
    * Returns the status badge.
    * @return {!TextBadgeElement}
    */
@@ -124,11 +116,14 @@
 
   /**
    * Returns the status text.
-   * TODO(joonbug): Update this type for use with assertElementContainsText
-   * @return {?Element}
+   * @return {!HTMLElement}
    */
   function getStatusTextElement() {
-    return routineSectionElement.$$('#testStatusText');
+    const statusText =
+        /** @type {!HTMLElement} */ (
+            routineSectionElement.$$('#testStatusText'));
+    assertTrue(!!statusText);
+    return statusText;
   }
 
   /**
@@ -165,6 +160,14 @@
     return dx_utils.getResultEntries(getResultList());
   }
 
+  /**
+   * Returns whether the "result list" section is expanded or not.
+   * @return {boolean}
+   */
+  function isIronCollapseOpen() {
+    return routineSectionElement.$.collapse.opened;
+  }
+
   test('ElementRenders', () => {
     return initializeRoutineSection([]).then(() => {
       // Verify the element rendered.
@@ -198,32 +201,29 @@
       chromeos.diagnostics.mojom.RoutineType.kCpuFloatingPoint,
     ];
 
-    // TODO(joonbug): Use visibility assert over testing .hidden attr.
     return initializeRoutineSection(routines)
         .then(() => {
           // Hidden by default.
-          assertTrue(getResultList().hidden);
-          assertTrue(getToggleTestReportButton().hidden);
+          assertFalse(isIronCollapseOpen());
+          assertFalse(isVisible(getToggleTestReportButton()));
           return clickRunTestsButton();
         })
         .then(() => {
           // Report is still hidden by default, but toggle button is visible.
-          assertTrue(getResultList().hidden);
-          assertFalse(getToggleTestReportButton().hidden);
+          assertFalse(isIronCollapseOpen());
+          assertTrue(isVisible(getToggleTestReportButton()));
           return clickToggleTestReportButton();
         })
         .then(() => {
           // Report is visible when button is clicked.
-          assertFalse(getResultList().hidden);
-          assertFalse(getToggleTestReportButton().hidden);
-          assertFalse(getLearnMoreButton().hidden);
+          assertTrue(isIronCollapseOpen());
+          assertTrue(isVisible(getToggleTestReportButton()));
           return clickToggleTestReportButton();
         })
         .then(() => {
           // Report is hidden when button is clicked again.
-          assertTrue(getResultList().hidden);
-          assertTrue(getLearnMoreButton().hidden);
-          assertFalse(getToggleTestReportButton().hidden);
+          assertFalse(isIronCollapseOpen());
+          assertTrue(isVisible(getToggleTestReportButton()));
         });
   });
 
@@ -233,18 +233,17 @@
       chromeos.diagnostics.mojom.RoutineType.kBatteryCharge,
     ];
 
-    // TODO(joonbug): Use visibility assert over testing .hidden attr.
     return initializeRoutineSection(routines)
         .then(() => {
           // Hidden by default.
-          assertTrue(getResultList().hidden);
-          assertTrue(getToggleTestReportButton().hidden);
+          assertFalse(isIronCollapseOpen());
+          assertFalse(isVisible(getToggleTestReportButton()));
           return clickRunTestsButton();
         })
         .then(() => {
           // Report is hidden by default and so is toggle button.
-          assertTrue(getResultList().hidden);
-          assertTrue(getToggleTestReportButton().hidden);
+          assertFalse(isIronCollapseOpen());
+          assertFalse(isVisible(getToggleTestReportButton()));
         });
   });
 
@@ -365,15 +364,16 @@
     return initializeRoutineSection(routines)
         .then(() => {
           // Hidden by default.
-          assertTrue(getStatusBadge().hidden);
-          assertTrue(getStatusTextElement().hidden);
+          assertFalse(isVisible(getStatusBadge()));
+          assertFalse(isVisible(getStatusTextElement()));
           return clickRunTestsButton();
         })
         .then(() => {
           // Badge is visible with test running.
           assertFalse(getStatusBadge().hidden);
-          assertEquals(getStatusBadge().badgeType, BadgeType.DEFAULT);
-          assertEquals(getStatusBadge().value, 'Test running');
+          assertEquals(getStatusBadge().badgeType, BadgeType.RUNNING);
+          dx_utils.assertTextContains(
+              getStatusBadge().value, loadTimeData.getString('testRunning'));
 
           // Text is visible describing which test is being run.
           assertFalse(getStatusTextElement().hidden);
@@ -424,8 +424,9 @@
         .then(() => {
           // Badge is visible with test running.
           assertFalse(getStatusBadge().hidden);
-          assertEquals(getStatusBadge().badgeType, BadgeType.DEFAULT);
-          assertEquals(getStatusBadge().value, 'Test running');
+          assertEquals(getStatusBadge().badgeType, BadgeType.RUNNING);
+          dx_utils.assertTextContains(
+              getStatusBadge().value, loadTimeData.getString('testRunning'));
 
           // Text is visible describing which test is being run.
           assertFalse(getStatusTextElement().hidden);
@@ -443,8 +444,9 @@
           // Badge is still visible with "test running", even though first one
           // failed.
           assertFalse(getStatusBadge().hidden);
-          assertEquals(getStatusBadge().badgeType, BadgeType.DEFAULT);
-          assertEquals(getStatusBadge().value, 'Test running');
+          assertEquals(getStatusBadge().badgeType, BadgeType.RUNNING);
+          dx_utils.assertTextContains(
+              getStatusBadge().value, loadTimeData.getString('testRunning'));
 
           // Text is visible describing which test is being run.
           assertFalse(getStatusTextElement().hidden);
diff --git a/chrome/test/data/webui/chromeos/diagnostics/text_badge_test.js b/chrome/test/data/webui/chromeos/diagnostics/text_badge_test.js
index 121505e..307d306 100644
--- a/chrome/test/data/webui/chromeos/diagnostics/text_badge_test.js
+++ b/chrome/test/data/webui/chromeos/diagnostics/text_badge_test.js
@@ -9,6 +9,8 @@
 import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
 import {flushTasks} from '../../test_util.m.js';
 
+import * as dx_utils from './diagnostics_test_utils.js';
+
 export function textBadgeTestSuite() {
   /** @type {?TextBadgeElement} */
   let textBadgeElement = null;
@@ -27,9 +29,8 @@
   /**
    * @param {!BadgeType} badgeType
    * @param {string} value
-   * @param {boolean=} hidden
    */
-  function initializeBadge(badgeType, value, hidden = false) {
+  function initializeBadge(badgeType, value) {
     assertFalse(!!textBadgeElement);
 
     textBadgeElement =
@@ -37,29 +38,18 @@
     assertTrue(!!textBadgeElement);
     textBadgeElement.badgeType = badgeType;
     textBadgeElement.value = value;
-    textBadgeElement.hidden = hidden || false;
     document.body.appendChild(textBadgeElement);
 
     return flushTasks();
   }
 
   test('InitializeBadge', () => {
-    const badgeType = BadgeType.DEFAULT;
+    const badgeType = BadgeType.QUEUED;
     const value = 'Test value';
     return initializeBadge(badgeType, value).then(() => {
       const textBadge = textBadgeElement.$$('#textBadge');
       assertEquals(badgeType, textBadge.getAttribute('class'));
-      assertEquals(value, textBadge.textContent.trim());
-      assertFalse(textBadge.hidden);
-    });
-  });
-
-  test('InitializeBadgeHidden', () => {
-    const badgeType = BadgeType.DEFAULT;
-    const value = 'Test value';
-    const hidden = true;
-    return initializeBadge(badgeType, value, hidden).then(() => {
-      assertTrue(textBadgeElement.$$('#textBadge').hidden);
+      dx_utils.assertTextContains(textBadge.textContent, value);
     });
   });
 }
diff --git a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/esim_flow_ui_test.js b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/esim_flow_ui_test.js
index fd815a6..550194d 100644
--- a/chrome/test/data/webui/cr_components/chromeos/cellular_setup/esim_flow_ui_test.js
+++ b/chrome/test/data/webui/cr_components/chromeos/cellular_setup/esim_flow_ui_test.js
@@ -37,7 +37,6 @@
 
     eSimPage = document.createElement('esim-flow-ui');
     eSimPage.delegate = new cellular_setup.FakeCellularSetupDelegate();
-    eSimPage.initSubflow();
     document.body.appendChild(eSimPage);
     Polymer.dom.flush();
 
@@ -60,307 +59,268 @@
     assertEquals(ironPages.selected, page.id);
   }
 
-  test('No eSIM profile flow invalid activation code', async function() {
-    eSimManagerRemote.addEuiccForTest(0);
-    const availableEuiccs = await eSimManagerRemote.getAvailableEuiccs();
-    availableEuiccs.euiccs[0].setProfileInstallResultForTest(
-        chromeos.cellularSetup.mojom.ProfileInstallResult
-            .kErrorInvalidActivationCode);
+  suite('No eSIM profiles flow', function() {
+    let euicc;
 
-    // Loading page should be showing.
-    assertSelectedPage(
-        cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage);
+    setup(async function() {
+      eSimManagerRemote.addEuiccForTest(0);
+      const availableEuiccs = await eSimManagerRemote.getAvailableEuiccs();
+      euicc = availableEuiccs.euiccs[0];
+      eSimPage.initSubflow();
 
-    await flushAsync();
+      // Loading page should be showing.
+      assertSelectedPage(
+          cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage);
 
-    // Should now be at the activation code page.
-    assertSelectedPage(
-        cellular_setup.ESimPageName.ACTIVATION_CODE, activationCodePage);
-    // Insert an activation code.
-    activationCodePage.$$('#activationCode').value = 'ACTIVATION_CODE';
+      await flushAsync();
 
-    // Next button should now be enabled.
-    assertTrue(
-        eSimPage.buttonState.next ===
-        cellularSetup.ButtonState.SHOWN_AND_ENABLED);
+      // Should now be at the activation code page.
+      assertSelectedPage(
+          cellular_setup.ESimPageName.ACTIVATION_CODE, activationCodePage);
+      // Insert an activation code.
+      activationCodePage.$$('#activationCode').value = 'ACTIVATION_CODE';
 
-    eSimPage.navigateForward();
+      // Next button should now be enabled.
+      assertTrue(
+          eSimPage.buttonState.next ===
+          cellularSetup.ButtonState.SHOWN_AND_ENABLED);
+    });
 
-    await flushAsync();
+    test('Invalid activation code', async function() {
+      euicc.setProfileInstallResultForTest(
+          chromeos.cellularSetup.mojom.ProfileInstallResult
+              .kErrorInvalidActivationCode);
 
-    // Install should fail and still be at activation code page.
-    assertSelectedPage(
-        cellular_setup.ESimPageName.ACTIVATION_CODE, activationCodePage);
-    assertTrue(activationCodePage.$$('#scanSuccessContainer').hidden);
-    assertFalse(activationCodePage.$$('#scanFailureContainer').hidden);
+      eSimPage.navigateForward();
+
+      await flushAsync();
+
+      // Install should fail and still be at activation code page.
+      assertSelectedPage(
+          cellular_setup.ESimPageName.ACTIVATION_CODE, activationCodePage);
+      assertTrue(activationCodePage.$$('#scanSuccessContainer').hidden);
+      assertFalse(activationCodePage.$$('#scanFailureContainer').hidden);
+    });
+
+    test('Valid activation code', async function() {
+      eSimPage.navigateForward();
+
+      await flushAsync();
+
+      // Should go to final page.
+      assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage);
+    });
+
+    test('Valid confirmation code', async function() {
+      euicc.setProfileInstallResultForTest(
+          chromeos.cellularSetup.mojom.ProfileInstallResult
+              .kErrorNeedsConfirmationCode);
+
+      eSimPage.navigateForward();
+
+      await flushAsync();
+
+      // Confirmation code page should be showing.
+      assertSelectedPage(
+          cellular_setup.ESimPageName.CONFIRMATION_CODE, confirmationCodePage);
+
+      euicc.setProfileInstallResultForTest(
+          chromeos.cellularSetup.mojom.ProfileInstallResult.kSuccess);
+      confirmationCodePage.$$('#confirmationCode').value = 'CONFIRMATION_CODE';
+
+      // Next button should now be enabled.
+      assertTrue(
+          eSimPage.buttonState.next ===
+          cellularSetup.ButtonState.SHOWN_AND_ENABLED);
+
+      eSimPage.navigateForward();
+
+      await flushAsync();
+
+      // Should go to final page.
+      assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage);
+    });
   });
 
-  test('No eSIM profile flow valid activation code', async function() {
-    eSimManagerRemote.addEuiccForTest(0);
+  suite('Single eSIM profile flow', function() {
+    let profile;
 
-    // Loading page should be showing.
-    assertSelectedPage(
-        cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage);
+    setup(async function() {
+      eSimManagerRemote.addEuiccForTest(1);
+      const availableEuiccs = await eSimManagerRemote.getAvailableEuiccs();
+      const profileList = await availableEuiccs.euiccs[0].getProfileList();
+      profile = profileList.profiles[0];
+      eSimPage.initSubflow();
+    });
 
-    await flushAsync();
+    test('Successful install', async function() {
+      // Loading page should be showing.
+      assertSelectedPage(
+          cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage);
 
-    // Should now be at the activation code page.
-    assertSelectedPage(
-        cellular_setup.ESimPageName.ACTIVATION_CODE, activationCodePage);
-    // Insert an activation code.
-    activationCodePage.$$('#activationCode').value = 'ACTIVATION_CODE';
+      await flushAsync();
 
-    // Next button should now be enabled.
-    assertTrue(
-        eSimPage.buttonState.next ===
-        cellularSetup.ButtonState.SHOWN_AND_ENABLED);
+      // Should go directly to final page.
+      assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage);
+      assertFalse(!!finalPage.$$('.error'));
+    });
 
-    eSimPage.navigateForward();
+    test('Unsuccessful install', async function() {
+      profile.setProfileInstallResultForTest(
+          chromeos.cellularSetup.mojom.ProfileInstallResult.kFailure);
 
-    await flushAsync();
+      // Loading page should be showing.
+      assertSelectedPage(
+          cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage);
 
-    // Should go to final page.
-    assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage);
+      await flushAsync();
+
+      // Should go directly to final page.
+      assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage);
+      assertTrue(!!finalPage.$$('.error'));
+    });
+
+    test('Valid confirmation code', async function() {
+      profile.setProfileInstallResultForTest(
+          chromeos.cellularSetup.mojom.ProfileInstallResult
+              .kErrorNeedsConfirmationCode);
+
+      // Loading page should be showing.
+      assertSelectedPage(
+          cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage);
+
+      await flushAsync();
+
+      // Confirmation code page should be showing.
+      assertSelectedPage(
+          cellular_setup.ESimPageName.CONFIRMATION_CODE, confirmationCodePage);
+
+      profile.setProfileInstallResultForTest(
+          chromeos.cellularSetup.mojom.ProfileInstallResult.kSuccess);
+      confirmationCodePage.$$('#confirmationCode').value = 'CONFIRMATION_CODE';
+
+      // Next button should now be enabled.
+      assertTrue(
+          eSimPage.buttonState.next ===
+          cellularSetup.ButtonState.SHOWN_AND_ENABLED);
+
+      eSimPage.navigateForward();
+
+      await flushAsync();
+
+      // Should go to final page.
+      assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage);
+    });
   });
 
-  test(
-      'No eSIM profile flow valid activation code confirmation code required successful install',
-      async function() {
-        eSimManagerRemote.addEuiccForTest(0);
-        const availableEuiccs = await eSimManagerRemote.getAvailableEuiccs();
-        availableEuiccs.euiccs[0].setProfileInstallResultForTest(
-            chromeos.cellularSetup.mojom.ProfileInstallResult
-                .kErrorNeedsConfirmationCode);
+  suite('Multiple eSIM profiles flow', function() {
+    setup(async function() {
+      eSimManagerRemote.addEuiccForTest(2);
+      eSimPage.initSubflow();
 
-        // Loading page should be showing.
-        assertSelectedPage(
-            cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage);
+      // Loading page should be showing.
+      assertSelectedPage(
+          cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage);
 
-        await flushAsync();
+      await flushAsync();
 
-        // Should now be at the activation code page.
-        assertSelectedPage(
-            cellular_setup.ESimPageName.ACTIVATION_CODE, activationCodePage);
-        // Insert an activation code.
-        activationCodePage.$$('#activationCode').value = 'ACTIVATION_CODE';
+      // Should go to profile discovery page.
+      assertSelectedPage(
+          cellular_setup.ESimPageName.PROFILE_DISCOVERY, profileDiscoveryPage);
+    });
 
-        // Next button should now be enabled.
-        assertTrue(
-            eSimPage.buttonState.next ===
-            cellularSetup.ButtonState.SHOWN_AND_ENABLED);
+    test('Skip discovery flow', async function() {
+      // Simulate pressing 'Skip'.
+      assertTrue(
+          eSimPage.buttonState.skipDiscovery ===
+          cellularSetup.ButtonState.SHOWN_AND_ENABLED);
+      eSimPage.navigateForward();
+      Polymer.dom.flush();
 
-        eSimPage.navigateForward();
+      // Should now be at the activation code page.
+      assertSelectedPage(
+          cellular_setup.ESimPageName.ACTIVATION_CODE, activationCodePage);
 
-        await flushAsync();
+      // Insert an activation code.
+      activationCodePage.$$('#activationCode').value = 'ACTIVATION_CODE';
 
-        // Confirmation code page should be showing.
-        assertSelectedPage(
-            cellular_setup.ESimPageName.CONFIRMATION_CODE,
-            confirmationCodePage);
+      // Simulate pressing 'Next'.
+      assertTrue(
+          eSimPage.buttonState.next ===
+          cellularSetup.ButtonState.SHOWN_AND_ENABLED);
+      eSimPage.navigateForward();
+      await flushAsync();
 
-        availableEuiccs.euiccs[0].setProfileInstallResultForTest(
-            chromeos.cellularSetup.mojom.ProfileInstallResult.kSuccess);
-        confirmationCodePage.$$('#confirmationCode').value =
-            'CONFIRMATION_CODE';
+      // Should now be at the final page.
+      assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage);
+    });
 
-        // Next button should now be enabled.
-        assertTrue(
-            eSimPage.buttonState.next ===
-            cellularSetup.ButtonState.SHOWN_AND_ENABLED);
+    test('Select profile flow', async function() {
+      // Select the first profile on the list.
+      const profileList = profileDiscoveryPage.$$('#profileList');
+      profileList.selectItem(profileList.items[0]);
+      Polymer.dom.flush();
 
-        eSimPage.navigateForward();
+      // The 'Next' button should now be enabled.
+      assertTrue(
+          eSimPage.buttonState.next ===
+          cellularSetup.ButtonState.SHOWN_AND_ENABLED);
+      assertTrue(
+          eSimPage.buttonState.skipDiscovery ===
+          cellularSetup.ButtonState.HIDDEN);
 
-        await flushAsync();
+      // Simulate pressing 'Next'.
+      eSimPage.navigateForward();
+      await flushAsync();
 
-        // Should go to final page.
-        assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage);
-      });
+      // Should now be at the final page.
+      assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage);
+      assertFalse(!!finalPage.$$('.error'));
+    });
 
-  test('Single eSIM profile flow successful install', async function() {
-    eSimManagerRemote.addEuiccForTest(1);
+    test('Select profile with valid confirmation code flow', async function() {
+      const availableEuiccs = await eSimManagerRemote.getAvailableEuiccs();
+      const profileList = await availableEuiccs.euiccs[0].getProfileList();
+      profileList.profiles[0].setProfileInstallResultForTest(
+          chromeos.cellularSetup.mojom.ProfileInstallResult
+              .kErrorNeedsConfirmationCode);
 
-    // Loading page should be showing.
-    assertSelectedPage(
-        cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage);
+      // Select the first profile on the list.
+      const profileListUI = profileDiscoveryPage.$$('#profileList');
+      profileListUI.selectItem(profileListUI.items[0]);
+      Polymer.dom.flush();
 
-    await flushAsync();
+      // The 'Next' button should now be enabled.
+      assertTrue(
+          eSimPage.buttonState.next ===
+          cellularSetup.ButtonState.SHOWN_AND_ENABLED);
+      assertTrue(
+          eSimPage.buttonState.skipDiscovery ===
+          cellularSetup.ButtonState.HIDDEN);
 
-    // Should go directly to final page.
-    assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage);
-    assertFalse(!!finalPage.$$('.error'));
+      // Simulate pressing 'Next'.
+      eSimPage.navigateForward();
+      await flushAsync();
+
+      // Confirmation code page should be showing.
+      assertSelectedPage(
+          cellular_setup.ESimPageName.CONFIRMATION_CODE, confirmationCodePage);
+
+      profileList.profiles[0].setProfileInstallResultForTest(
+          chromeos.cellularSetup.mojom.ProfileInstallResult.kSuccess);
+      confirmationCodePage.$$('#confirmationCode').value = 'CONFIRMATION_CODE';
+
+      // Next button should now be enabled.
+      assertTrue(
+          eSimPage.buttonState.next ===
+          cellularSetup.ButtonState.SHOWN_AND_ENABLED);
+
+      eSimPage.navigateForward();
+
+      await flushAsync();
+
+      // Should go to final page.
+      assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage);
+    });
   });
-
-  test('Single eSIM profile flow unsuccessful install', async function() {
-    eSimManagerRemote.addEuiccForTest(1);
-    const availableEuiccs = await eSimManagerRemote.getAvailableEuiccs();
-    const profileList = await availableEuiccs.euiccs[0].getProfileList();
-    profileList.profiles[0].setProfileInstallResultForTest(
-        chromeos.cellularSetup.mojom.ProfileInstallResult.kFailure);
-
-    // Loading page should be showing.
-    assertSelectedPage(
-        cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage);
-
-    await flushAsync();
-
-    // Should go directly to final page.
-    assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage);
-    assertTrue(!!finalPage.$$('.error'));
-  });
-
-  test(
-      'Single eSIM profile flow confirmation code required successful install',
-      async function() {
-        eSimManagerRemote.addEuiccForTest(1);
-        const availableEuiccs = await eSimManagerRemote.getAvailableEuiccs();
-        const profileList = await availableEuiccs.euiccs[0].getProfileList();
-        profileList.profiles[0].setProfileInstallResultForTest(
-            chromeos.cellularSetup.mojom.ProfileInstallResult
-                .kErrorNeedsConfirmationCode);
-
-        // Loading page should be showing.
-        assertSelectedPage(
-            cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage);
-
-        await flushAsync();
-
-        // Confirmation code page should be showing.
-        assertSelectedPage(
-            cellular_setup.ESimPageName.CONFIRMATION_CODE,
-            confirmationCodePage);
-
-        profileList.profiles[0].setProfileInstallResultForTest(
-            chromeos.cellularSetup.mojom.ProfileInstallResult.kSuccess);
-        confirmationCodePage.$$('#confirmationCode').value =
-            'CONFIRMATION_CODE';
-
-        // Next button should now be enabled.
-        assertTrue(
-            eSimPage.buttonState.next ===
-            cellularSetup.ButtonState.SHOWN_AND_ENABLED);
-
-        eSimPage.navigateForward();
-
-        await flushAsync();
-
-        // Should go to final page.
-        assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage);
-      });
-
-  test('Multiple eSIM profiles skip discovery flow', async function() {
-    eSimManagerRemote.addEuiccForTest(2);
-
-    // Loading page should be showing.
-    assertSelectedPage(
-        cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage);
-
-    await flushAsync();
-
-    // Should go to profile discovery page.
-    assertSelectedPage(
-        cellular_setup.ESimPageName.PROFILE_DISCOVERY, profileDiscoveryPage);
-
-    // Simulate pressing 'Skip'.
-    assertTrue(
-        eSimPage.buttonState.skipDiscovery ===
-        cellularSetup.ButtonState.SHOWN_AND_ENABLED);
-    eSimPage.navigateForward();
-    Polymer.dom.flush();
-
-    // Should now be at the activation code page.
-    assertSelectedPage(
-        cellular_setup.ESimPageName.ACTIVATION_CODE, activationCodePage);
-
-    // Insert an activation code.
-    activationCodePage.$$('#activationCode').value = 'ACTIVATION_CODE';
-
-    // Simulate pressing 'Next'.
-    assertTrue(
-        eSimPage.buttonState.next ===
-        cellularSetup.ButtonState.SHOWN_AND_ENABLED);
-    eSimPage.navigateForward();
-    await flushAsync();
-
-    // Should now be at the final page.
-    assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage);
-  });
-
-  test('Multiple eSIM profiles select flow', async function() {
-    eSimManagerRemote.addEuiccForTest(2);
-
-    // Loading page should be showing.
-    assertSelectedPage(
-        cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage);
-
-    await flushAsync();
-
-    // Should go to profile discovery page.
-    assertSelectedPage(
-        cellular_setup.ESimPageName.PROFILE_DISCOVERY, profileDiscoveryPage);
-
-    // Select the first profile on the list.
-    const profileList = profileDiscoveryPage.$$('#profileList');
-    profileList.selectItem(profileList.items[0]);
-    Polymer.dom.flush();
-
-    // The 'Next' button should now be enabled.
-    assertTrue(
-        eSimPage.buttonState.next ===
-        cellularSetup.ButtonState.SHOWN_AND_ENABLED);
-    assertTrue(
-        eSimPage.buttonState.skipDiscovery ===
-        cellularSetup.ButtonState.HIDDEN);
-
-    // Simulate pressing 'Next'.
-    eSimPage.navigateForward();
-    await flushAsync();
-
-    // Should now be at the final page.
-    assertSelectedPage(cellular_setup.ESimPageName.FINAL, finalPage);
-    assertFalse(!!finalPage.$$('.error'));
-  });
-
-  test(
-      'Multiple eSIM profiles select flow confirmation code required',
-      async function() {
-        eSimManagerRemote.addEuiccForTest(2);
-        const availableEuiccs = await eSimManagerRemote.getAvailableEuiccs();
-        const profileList = await availableEuiccs.euiccs[0].getProfileList();
-        profileList.profiles[0].setProfileInstallResultForTest(
-            chromeos.cellularSetup.mojom.ProfileInstallResult
-                .kErrorNeedsConfirmationCode);
-
-        // Loading page should be showing.
-        assertSelectedPage(
-            cellular_setup.ESimPageName.PROFILE_LOADING, profileLoadingPage);
-
-        await flushAsync();
-
-        // Should go to profile discovery page.
-        assertSelectedPage(
-            cellular_setup.ESimPageName.PROFILE_DISCOVERY,
-            profileDiscoveryPage);
-
-        // Select the first profile on the list.
-        const profileListUI = profileDiscoveryPage.$$('#profileList');
-        profileListUI.selectItem(profileListUI.items[0]);
-        Polymer.dom.flush();
-
-        // The 'Next' button should now be enabled.
-        assertTrue(
-            eSimPage.buttonState.next ===
-            cellularSetup.ButtonState.SHOWN_AND_ENABLED);
-        assertTrue(
-            eSimPage.buttonState.skipDiscovery ===
-            cellularSetup.ButtonState.HIDDEN);
-
-        // Simulate pressing 'Next'.
-        eSimPage.navigateForward();
-        await flushAsync();
-
-        // Confirmation code page should be showing.
-        assertSelectedPage(
-            cellular_setup.ESimPageName.CONFIRMATION_CODE,
-            confirmationCodePage);
-      });
 });
diff --git a/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js b/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js
index 0b479ea2..68dd57f 100644
--- a/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js
+++ b/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js
@@ -545,13 +545,13 @@
 
 GEN('#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS)');
 [['DefaultBrowser', 'default_browser_browsertest.js'],
+ ['SystemPage', 'system_page_tests.js'],
 ].forEach(test => registerTest(...test));
 GEN('#endif  // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_CHROMEOS_LACROS)');
 
 GEN('#if !defined(OS_CHROMEOS)');
 [['ImportDataDialog', 'import_data_dialog_test.js'],
  ['PeoplePageManageProfile', 'people_page_manage_profile_test.js'],
- ['SystemPage', 'system_page_tests.js'],
 ].forEach(test => registerTest(...test));
 GEN('#endif  // !defined(OS_CHROMEOS)');
 
diff --git a/chrome/tools/build/linux/FILES.cfg b/chrome/tools/build/linux/FILES.cfg
index ef00a14b..22438ea 100644
--- a/chrome/tools/build/linux/FILES.cfg
+++ b/chrome/tools/build/linux/FILES.cfg
@@ -459,27 +459,22 @@
   },
   # MojoJS support data (WebBluetooth):
   {
-    'filename': 'gen/content/test/data/mojo_web_test_helper_test.mojom.js',
+    'filename': 'gen/device/bluetooth/public/mojom/uuid.mojom.m.js',
     'buildtype': ['dev', 'official'],
     'archive': 'mojojs.zip',
   },
   {
-    'filename': 'gen/device/bluetooth/public/mojom/uuid.mojom.js',
+    'filename': 'gen/url/mojom/origin.mojom.m.js',
     'buildtype': ['dev', 'official'],
     'archive': 'mojojs.zip',
   },
   {
-    'filename': 'gen/url/mojom/origin.mojom.js',
+    'filename': 'gen/device/bluetooth/public/mojom/test/fake_bluetooth.mojom.m.js',
     'buildtype': ['dev', 'official'],
     'archive': 'mojojs.zip',
   },
   {
-    'filename': 'gen/device/bluetooth/public/mojom/test/fake_bluetooth.mojom.js',
-    'buildtype': ['dev', 'official'],
-    'archive': 'mojojs.zip',
-  },
-  {
-    'filename': 'gen/content/web_test/common/fake_bluetooth_chooser.mojom.js',
+    'filename': 'gen/content/web_test/common/fake_bluetooth_chooser.mojom.m.js',
     'buildtype': ['dev', 'official'],
     'archive': 'mojojs.zip',
   },
diff --git a/chrome/updater/BUILD.gn b/chrome/updater/BUILD.gn
index 7a8085b..b6477455 100644
--- a/chrome/updater/BUILD.gn
+++ b/chrome/updater/BUILD.gn
@@ -166,7 +166,6 @@
         "app/server/win/service_main.cc",
         "app/server/win/service_main.h",
         "external_constants_win.cc",
-        "installer_win.cc",
         "lib_util_win.cc",
         "prefs_win.cc",
         "service_factory_win.cc",
@@ -181,7 +180,6 @@
       ":version_header",
       "//base",
       "//base:i18n",
-      "//chrome/updater/device_management",
       "//components/crash/core/common:crash_key",
       "//components/crx_file:crx_file",
       "//components/prefs",
@@ -192,13 +190,17 @@
     ]
 
     if (is_win) {
+      # //chrome/updater:lib and //chrome/updater/win:lib behave as one unit
+      # for linking purposes. Targets depending on the latter must use
+      # the former as a dependency.
+      allow_circular_includes_from = [ "//chrome/updater/win:lib" ]
       deps += [
         "//chrome/updater/app/server/win:updater_idl_idl",
         "//chrome/updater/app/server/win:updater_internal_idl_idl",
         "//chrome/updater/app/server/win:updater_legacy_idl_idl",
         "//chrome/updater/win:constants",
-        "//chrome/updater/win:lib",
       ]
+      public_deps = [ "//chrome/updater/win:lib" ]
     }
 
     if (is_mac) {
@@ -370,7 +372,6 @@
         "//chrome/updater/app/server/win:updater_internal_idl_idl",
         "//chrome/updater/app/server/win:updater_legacy_idl_idl",
         "//chrome/updater/win:constants",
-        "//chrome/updater/win:lib",
         "//chrome/updater/win:updater_tests",
       ]
 
diff --git a/chrome/updater/device_management/BUILD.gn b/chrome/updater/device_management/BUILD.gn
index 66957b7..c3dce30 100644
--- a/chrome/updater/device_management/BUILD.gn
+++ b/chrome/updater/device_management/BUILD.gn
@@ -45,8 +45,8 @@
   if (is_win) {
     sources += [ "dm_storage_win.cc" ]
     deps += [
+      "//chrome/updater:lib",
       "//chrome/updater/win:constants",
-      "//chrome/updater/win:lib",
     ]
   }
 }
@@ -81,6 +81,6 @@
   }
 
   if (is_win) {
-    deps += [ "//chrome/updater/win:lib" ]
+    deps += [ "//chrome/updater:lib" ]
   }
 }
diff --git a/chrome/updater/test/test_app/BUILD.gn b/chrome/updater/test/test_app/BUILD.gn
index 1dea265b..2c70d29 100644
--- a/chrome/updater/test/test_app/BUILD.gn
+++ b/chrome/updater/test/test_app/BUILD.gn
@@ -87,8 +87,8 @@
       "update_client_win.h",
     ]
     deps += [
+      "//chrome/updater:lib",
       "//chrome/updater/app/server/win:updater_idl_idl",
-      "//chrome/updater/win:lib",
     ]
   }
 }
diff --git a/chrome/updater/win/BUILD.gn b/chrome/updater/win/BUILD.gn
index 87c0a12..8123880b 100644
--- a/chrome/updater/win/BUILD.gn
+++ b/chrome/updater/win/BUILD.gn
@@ -34,7 +34,6 @@
 
   deps = [
     ":app_install_controller",
-    ":lib",
     ":version_resources",
     "//build/win:default_exe_manifest",
     "//chrome/updater:lib",
@@ -74,10 +73,15 @@
 }
 
 source_set("lib") {
+  # This build target and "//chrome/updater:lib" act as a unit. Depending
+  # targets must use "//chrome/updater:lib" as a dependency.
+  visibility = [ "//chrome/updater:lib" ]
+
   sources = [
     "action_handler.cc",
     "group_policy_manager.cc",
     "group_policy_manager.h",
+    "installer.cc",
     "net/net_util.cc",
     "net/net_util.h",
     "net/network.h",
@@ -153,25 +157,22 @@
 # compilation units outside the UI itself.
 # TODO(sorin): https://crbug.com/1014311
 source_set("app_install_controller") {
-  if (is_win) {
-    visibility = [ "//chrome/updater/win/*" ]
-    allow_circular_includes_from = [ "//chrome/updater:lib" ]
+  visibility = [ "//chrome/updater/win/*" ]
 
-    cflags_cc = [ "-Wno-missing-braces" ]
+  cflags_cc = [ "-Wno-missing-braces" ]
 
-    sources = [ "app_install_controller.cc" ]
+  sources = [ "app_install_controller.cc" ]
 
-    deps = [
-      ":install_progress_observer",
-      ":lib",
-      "//base",
-      "//base:i18n",
-      "//chrome/updater:base",
-      "//chrome/updater:lib",
-      "//chrome/updater:version_header",
-      "//chrome/updater/win/ui",
-    ]
-  }
+  allow_circular_includes_from = [ "//chrome/updater:lib" ]
+  deps = [
+    ":install_progress_observer",
+    "//base",
+    "//base:i18n",
+    "//chrome/updater:base",
+    "//chrome/updater:lib",
+    "//chrome/updater:version_header",
+    "//chrome/updater/win/ui",
+  ]
 }
 
 source_set("tag_extractor") {
@@ -208,9 +209,9 @@
   deps = [
     ":app_install_controller",
     ":constants",
-    ":lib",
     ":tag_extractor",
     "//base/test:test_support",
+    "//chrome/updater:lib",
     "//testing/gtest",
     "//url:url",
   ]
@@ -241,10 +242,10 @@
 
   deps = [
     ":app_install_controller",
-    ":lib",
     "//base",
     "//base/test:test_support",
     "//chrome/updater:branding_header",
+    "//chrome/updater:lib",
     "//chrome/updater/win/test:test_executables",
     "//chrome/updater/win/test:test_strings",
     "//testing/gtest",
diff --git a/chrome/updater/installer_win.cc b/chrome/updater/win/installer.cc
similarity index 100%
rename from chrome/updater/installer_win.cc
rename to chrome/updater/win/installer.cc
diff --git a/chrome/updater/win/test/BUILD.gn b/chrome/updater/win/test/BUILD.gn
index a964ea9..fd7f1dc 100644
--- a/chrome/updater/win/test/BUILD.gn
+++ b/chrome/updater/win/test/BUILD.gn
@@ -26,8 +26,8 @@
   deps = [
     "//base",
     "//chrome/updater:base",
+    "//chrome/updater:lib",
     "//chrome/updater/win:app_install_controller",
-    "//chrome/updater/win:lib",
   ]
 }
 
diff --git a/chrome/updater/win/ui/BUILD.gn b/chrome/updater/win/ui/BUILD.gn
index e105be4..d6f92e7 100644
--- a/chrome/updater/win/ui/BUILD.gn
+++ b/chrome/updater/win/ui/BUILD.gn
@@ -41,8 +41,8 @@
     "//base:i18n",
     "//chrome/updater:base",
     "//chrome/updater:branding_header",
+    "//chrome/updater:lib",
     "//chrome/updater/win:install_progress_observer",
-    "//chrome/updater/win:lib",
     "//third_party/wtl",
   ]
 
diff --git a/chromecast/browser/webview/web_content_controller.cc b/chromecast/browser/webview/web_content_controller.cc
index d5043dd..422f990f 100644
--- a/chromecast/browser/webview/web_content_controller.cc
+++ b/chromecast/browser/webview/web_content_controller.cc
@@ -338,17 +338,24 @@
       if (ev.has_key()) {
         ui::DomKey dom_key =
             ui::KeycodeConverter::KeyStringToDomKey(ev.key().key_string());
-        bool is_char = dom_key.IsCharacter();
-        int32_t key_code = is_char ? dom_key.ToCharacter()
-                                   : NonPrintableDomKeyToKeyboardCode(dom_key);
+
+        // Backspace, delete, and tab have to be treated specially as they are
+        // characters according to DomKey, but they are non-printable.
+        bool is_printable_character =
+            dom_key.IsCharacter() && dom_key != ui::DomKey::TAB &&
+            dom_key != ui::DomKey::BACKSPACE && dom_key != ui::DomKey::DEL;
+
         ui::KeyboardCode keyboard_code =
-            static_cast<ui::KeyboardCode>(key_code);
+            is_printable_character
+                ? static_cast<ui::KeyboardCode>(dom_key.ToCharacter())
+                : NonPrintableDomKeyToKeyboardCode(dom_key);
         ui::KeyEvent evt(type, keyboard_code,
                          UsLayoutKeyboardCodeToDomCode(keyboard_code),
                          ev.flags() | ui::EF_IS_SYNTHESIZED, dom_key,
                          base::TimeTicks() +
                              base::TimeDelta::FromMicroseconds(ev.timestamp()),
-                         is_char);
+                         is_printable_character);
+
         // Marks the simulated key event is from a Virtual Keyboard.
         ui::Event::Properties properties;
         properties[ui::kPropertyFromVK] =
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd
index 27ec272..3149f820 100644
--- a/chromeos/chromeos_strings.grd
+++ b/chromeos/chromeos_strings.grd
@@ -552,7 +552,7 @@
         More settings
       </message>
       <message name="IDS_SCANNING_APP_SCAN_PREVIEW_HELPER_TEXT" desc="The text displayed in the scan preview that explains how to scan a document.">
-        Place your document on the scanner and select <ph name="SPAN_BEGIN">&lt;span id="boldHelperText"&gt;</ph>Scan<ph name="SPAN_END">&lt;/span&gt;</ph> to get started
+        Place your document on the scanner and select Scan to get started
       </message>
       <message name="IDS_SCANNING_APP_SCAN_BUTTON_TEXT" desc="The text displayed for the button that starts a scan.">
         Scan
@@ -681,7 +681,7 @@
         <ph name="TEMPERATURE_C">$1<ex>25</ex></ph>° C
       </message>
       <message name="IDS_DIANOSTICS_LEARN_MORE_LABEL" desc="The label for the button that links to a help support article to learn more about the test routines being run.">
-        Learn more in the Help Center
+        Learn more in Help Center
       </message>
       <message name="IDS_DIAGNOSTICS_LEARN_MORE_LABEL_SHORT" desc="The label for the text link that leads to a help support article to learn more about the test routines being run.">
         Learn more
@@ -746,6 +746,9 @@
       <message name="IDS_DIAGNOSTICS_TEST_SUCCESS_BADGE_TEXT" desc="The text displayed to indicate that a test passed.">
         SUCCESS
       </message>
+      <message name="IDS_DIAGNOSTICS_TEST_QUEUED_BADGE_TEXT" desc="The text displayed to indicate that a test is currently queued.">
+        QUEUED
+      </message>
       <message name="IDS_DIAGNOSTICS_TEST_RUNNING_TEXT" desc="The text displayed while a test is running.">
         Test running
       </message>
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_QUEUED_BADGE_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_QUEUED_BADGE_TEXT.png.sha1
new file mode 100644
index 0000000..814c3e7
--- /dev/null
+++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_TEST_QUEUED_BADGE_TEXT.png.sha1
@@ -0,0 +1 @@
+d96a5f3d329ed440bd46454f60530a8c4da01611
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIANOSTICS_LEARN_MORE_LABEL.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIANOSTICS_LEARN_MORE_LABEL.png.sha1
index 454aa40..814c3e7 100644
--- a/chromeos/chromeos_strings_grd/IDS_DIANOSTICS_LEARN_MORE_LABEL.png.sha1
+++ b/chromeos/chromeos_strings_grd/IDS_DIANOSTICS_LEARN_MORE_LABEL.png.sha1
@@ -1 +1 @@
-99d733189f12c848ba779e277aa6ea9f7c9557b7
\ No newline at end of file
+d96a5f3d329ed440bd46454f60530a8c4da01611
\ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_SCANNING_APP_SCAN_PREVIEW_HELPER_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_SCANNING_APP_SCAN_PREVIEW_HELPER_TEXT.png.sha1
index 30df8bf3..5320376 100644
--- a/chromeos/chromeos_strings_grd/IDS_SCANNING_APP_SCAN_PREVIEW_HELPER_TEXT.png.sha1
+++ b/chromeos/chromeos_strings_grd/IDS_SCANNING_APP_SCAN_PREVIEW_HELPER_TEXT.png.sha1
@@ -1 +1 @@
-4b8ecf2d7f66be15b9fa575ac0aa89f45e48eb3f
\ No newline at end of file
+26b1bb2792084260e7b26c255613440b00eb6751
\ No newline at end of file
diff --git a/chromeos/components/diagnostics_ui/diagnostics_ui.cc b/chromeos/components/diagnostics_ui/diagnostics_ui.cc
index 164dfe5..e9f18e0c 100644
--- a/chromeos/components/diagnostics_ui/diagnostics_ui.cc
+++ b/chromeos/components/diagnostics_ui/diagnostics_ui.cc
@@ -89,6 +89,7 @@
       {"stopTestButtonText", IDS_DIAGNOSTICS_STOP_TEST_BUTTON_TEXT},
       {"testFailure", IDS_DIAGNOSTICS_TEST_FAILURE_TEXT},
       {"testFailedBadgeText", IDS_DIAGNOSTICS_TEST_FAILURE_BADGE_TEXT},
+      {"testQueuedBadgeText", IDS_DIAGNOSTICS_TEST_QUEUED_BADGE_TEXT},
       {"testRunning", IDS_DIAGNOSTICS_TEST_RUNNING_TEXT},
       {"testRunningBadgeText", IDS_DIAGNOSTICS_TEST_RUNNING_BADGE_TEXT},
       {"testSuccess", IDS_DIAGNOSTICS_TEST_SUCCESS_TEXT},
diff --git a/chromeos/components/diagnostics_ui/resources/battery_status_card.js b/chromeos/components/diagnostics_ui/resources/battery_status_card.js
index a20356b1..eb32d5a 100644
--- a/chromeos/components/diagnostics_ui/resources/battery_status_card.js
+++ b/chromeos/components/diagnostics_ui/resources/battery_status_card.js
@@ -81,6 +81,7 @@
     /** @type {boolean} */
     isTestRunning: {
       type: Boolean,
+      value: false,
       notify: true,
     },
   },
diff --git a/chromeos/components/diagnostics_ui/resources/cpu_card.js b/chromeos/components/diagnostics_ui/resources/cpu_card.js
index 50aea2e..2dab37d 100644
--- a/chromeos/components/diagnostics_ui/resources/cpu_card.js
+++ b/chromeos/components/diagnostics_ui/resources/cpu_card.js
@@ -67,6 +67,7 @@
     /** @type {boolean} */
     isTestRunning: {
       type: Boolean,
+      value: false,
       notify: true,
     },
 
diff --git a/chromeos/components/diagnostics_ui/resources/diagnostics_card.html b/chromeos/components/diagnostics_ui/resources/diagnostics_card.html
index 560b7f2..07c9bf1 100644
--- a/chromeos/components/diagnostics_ui/resources/diagnostics_card.html
+++ b/chromeos/components/diagnostics_ui/resources/diagnostics_card.html
@@ -47,9 +47,9 @@
   }
 
   .spacing {
-    margin: 14px 0px;
-    padding-inline-end: 15px;
-    padding-inline-start: 15px;
+    margin-bottom: 16px;
+    margin-top: 12px;
+    padding-inline: 20px;
   }
 
   .top-section {
diff --git a/chromeos/components/diagnostics_ui/resources/diagnostics_fonts_css.html b/chromeos/components/diagnostics_ui/resources/diagnostics_fonts_css.html
index 9614c6f..a9799d4f 100644
--- a/chromeos/components/diagnostics_ui/resources/diagnostics_fonts_css.html
+++ b/chromeos/components/diagnostics_ui/resources/diagnostics_fonts_css.html
@@ -5,6 +5,8 @@
       --diagnostics-header-font-family: Roboto, sans-serif;
       --diagnostics-data-point-font-family: Roboto, sans-serif;
       --diagnostics-overview-font-family: Roboto, sans-serif;
+      --diagnostics-text-badge-font-family: Roboto, sans-serif;
+      --diagnostics-routine-name-font-family: Roboto, sans-serif;
 
       --diagnostics-default-font-size: 14px;
       --diagnostics-header-font-size: 22px;
@@ -14,6 +16,8 @@
       --diagnostics-chart-label-font-size: 15px;
       --diagnostics-chart-tick-font-size: 12px;
       --diagnostics-chart-legend-font-size: 12px;
+      --diagnostics-text-badge-font-size: 11px;
+      --diagnostics-routine-name-font-size: 13px;
 
       --diagnostics-default-font-weight: 500;
       --diagnostics-header-font-weight: 600;
@@ -26,6 +30,7 @@
       --diagnostics-overview-text-color: var(--google-grey-900);
       --diagnostics-data-point-title-color: var(--google-grey-900);
       --diagnostics-data-point-subtitle-color: var(--google-grey-700);
+      --diagnostics-routine-name-color: var(--google-grey-900);
 
       --diagnostics-default-font: {
           font-family: var(--diagnostics-default-font-family);
@@ -69,6 +74,14 @@
           font-family: var(--diagnostics-header-font-family);
           font-size: var(--diagnostics-chart-legend-font-size);
       };
+      --diagnostics-text-badge-font: {
+          font-family: var(--diagnostics-text-badge-font-family);
+          font-size: var(--diagnostics-text-badge-font-size);
+      };
+      --diagnostics-routine-name-font: {
+          font-family: var(--diagnostics-routine-name-font-family);
+          font-size: var(--diagnostics-routine-name-font-size);
+      };
     }
   </style>
 </template>
\ No newline at end of file
diff --git a/chromeos/components/diagnostics_ui/resources/memory_card.js b/chromeos/components/diagnostics_ui/resources/memory_card.js
index b74353e..fedd8de 100644
--- a/chromeos/components/diagnostics_ui/resources/memory_card.js
+++ b/chromeos/components/diagnostics_ui/resources/memory_card.js
@@ -61,6 +61,7 @@
     /** @type {boolean} */
     isTestRunning: {
       type: Boolean,
+      value: false,
       notify: true,
     }
   },
diff --git a/chromeos/components/diagnostics_ui/resources/realtime_cpu_chart.js b/chromeos/components/diagnostics_ui/resources/realtime_cpu_chart.js
index 9a40960..29b9339 100644
--- a/chromeos/components/diagnostics_ui/resources/realtime_cpu_chart.js
+++ b/chromeos/components/diagnostics_ui/resources/realtime_cpu_chart.js
@@ -152,7 +152,7 @@
   ready() {
     this.setScaling_();
     this.initializeChart_();
-    window.addEventListener('resize', (e) => this.updateChartWidth_());
+    window.addEventListener('resize', () => this.updateChartWidth_());
 
     // Set the initial chart width.
     this.updateChartWidth_();
@@ -208,6 +208,19 @@
         d3.scaleLinear().domain([0, this.numDataPoints_ - 2]).range([
           0, this.graphWidth_
         ]);
+
+    // Draw the y-axis legend and also draw the horizontal gridlines by
+    // reversing the ticks back into the chart body.
+    const chartGroup = d3.select(this.$$('#chartGroup'));
+    chartGroup.select('#gridLines')
+        .call(
+            d3.axisLeft(/** @type {!d3.LinearScale} */ (this.yAxisScaleFn_))
+                .tickValues(this.yAxisTicks_)
+                .tickFormat((y) => this.getPercentageLabel_(y))
+                .tickPadding(this.padding_.tick)
+                .tickSize(-this.graphWidth_)  // Extend the ticks into the
+                                              // entire graph as gridlines.
+        );
   },
 
   /** @private */
@@ -219,18 +232,6 @@
         'transform',
         'translate(' + this.padding_.left + ',' + this.padding_.top + ')');
 
-    // Draw the y-axis legend and also draw the horizontal gridlines by
-    // reversing the ticks back into the chart body.
-    chartGroup.select('#gridLines')
-        .call(
-            d3.axisLeft(/** @type {!d3.LinearScale} */ (this.yAxisScaleFn_))
-                .tickValues(this.yAxisTicks_)
-                .tickFormat((y) => this.getPercentageLabel_(y))
-                .tickPadding(this.padding_.tick)
-                .tickSize(-this.graphWidth_)  // Extend the ticks into the
-                                              // entire graph as gridlines.
-        );
-
     const plotGroup = d3.select(this.$$('#plotGroup'));
 
     // Feed data array to the plot group.
diff --git a/chromeos/components/diagnostics_ui/resources/routine_result_entry.html b/chromeos/components/diagnostics_ui/resources/routine_result_entry.html
index 87c91fd..1b4e4a3d 100644
--- a/chromeos/components/diagnostics_ui/resources/routine_result_entry.html
+++ b/chromeos/components/diagnostics_ui/resources/routine_result_entry.html
@@ -1,15 +1,20 @@
 <style include="diagnostics-shared">
   .entryRow {
-    display: flex;
-    flex-direction: row;
-    justify-content: space-between;
+    align-items: center;
+    column-gap: 15px;
+    display: grid;
+    grid-template-columns: auto 1fr;
+    height: 40px;
+  }
+
+  #routine {
+    @apply --diagnostics-routine-name-font;
+    color: var(--diagnostics-routine-name-color);
   }
 </style>
 
 <div class="entryRow">
-  <div id="routine">[[routineType_]]</div>
-  <text-badge id="status" badge-type="[[getBadgeType_(item.progress, item.result)]]"
-  		value="[[getBadgeText_(item.progress, item.result)]]"
-  		hidden="[[!isTestStarted_(item.progress)]]">
+  <text-badge id="status" badge-type="[[badgeType_]]" value="[[badgeText_]]">
   </text-badge>
+  <div id="routine">[[routineType_]]</div>
 </div>
diff --git a/chromeos/components/diagnostics_ui/resources/routine_result_entry.js b/chromeos/components/diagnostics_ui/resources/routine_result_entry.js
index 09415631..746598b 100644
--- a/chromeos/components/diagnostics_ui/resources/routine_result_entry.js
+++ b/chromeos/components/diagnostics_ui/resources/routine_result_entry.js
@@ -86,8 +86,22 @@
       type: String,
       computed: 'getRunningRoutineString_(item.routine)',
     },
+
+    /** @private {!BadgeType} */
+    badgeType_: {
+      type: String,
+      value: BadgeType.QUEUED,
+    },
+
+    /** @private {string} */
+    badgeText_: {
+      type: String,
+      value: '',
+    },
   },
 
+  observers: ['entryStatusChanged_(item.progress, item.result)'],
+
   /**
    * Get the localized string name for the routine.
    * @param {!RoutineType} routine
@@ -98,44 +112,40 @@
   },
 
   /**
-   * @protected
+   * @private
    */
-  getBadgeText_() {
-    if (this.item.progress === ExecutionProgress.kRunning) {
-      return loadTimeData.getString('testRunningBadgeText');
+  entryStatusChanged_() {
+    // TODO(michaelcheco): Display "STOPPED" state when routines are cancelled.
+    switch (this.item.progress) {
+      case ExecutionProgress.kNotStarted:
+        this.setBadgeTypeAndText_(
+            BadgeType.QUEUED, loadTimeData.getString('testQueuedBadgeText'));
+        break;
+      case ExecutionProgress.kRunning:
+        this.setBadgeTypeAndText_(
+            BadgeType.RUNNING, loadTimeData.getString('testRunningBadgeText'));
+        break;
+      case ExecutionProgress.kCompleted:
+        const testPassed = this.item.result &&
+            getSimpleResult(this.item.result) ===
+                chromeos.diagnostics.mojom.StandardRoutineResult.kTestPassed;
+        const badgeType = testPassed ? BadgeType.SUCCESS : BadgeType.ERROR;
+        const badgeText = loadTimeData.getString(
+            testPassed ? 'testSucceededBadgeText' : 'testFailedBadgeText');
+        this.setBadgeTypeAndText_(badgeType, badgeText);
+        break;
+      default:
+        assertNotReached();
     }
-
-    if (this.item.result &&
-        getSimpleResult(this.item.result) ===
-            chromeos.diagnostics.mojom.StandardRoutineResult.kTestPassed) {
-      return loadTimeData.getString('testSucceededBadgeText');
-    }
-
-    return loadTimeData.getString('testFailedBadgeText');
   },
 
   /**
-   * @protected
+   * @param {!BadgeType} badgeType
+   * @param {string} badgeText
+   * @private
    */
-  getBadgeType_() {
-    if (this.item.progress === ExecutionProgress.kRunning) {
-      return BadgeType.DEFAULT;
-    }
-
-    if (this.item.result &&
-        getSimpleResult(this.item.result) ===
-            chromeos.diagnostics.mojom.StandardRoutineResult.kTestPassed) {
-      return BadgeType.SUCCESS;
-    }
-    return BadgeType.ERROR;
-  },
-
-  /**
-   * @protected
-   * @return {boolean}
-   */
-  isTestStarted_() {
-    return this.item.progress !== ExecutionProgress.kNotStarted;
+  setBadgeTypeAndText_(badgeType, badgeText) {
+    this.setProperties({badgeType_: badgeType, badgeText_: badgeText});
   },
 
   /** @override */
diff --git a/chromeos/components/diagnostics_ui/resources/routine_result_list.html b/chromeos/components/diagnostics_ui/resources/routine_result_list.html
index 9ac0d5a..201c4cc 100644
--- a/chromeos/components/diagnostics_ui/resources/routine_result_list.html
+++ b/chromeos/components/diagnostics_ui/resources/routine_result_list.html
@@ -1,6 +1,6 @@
 <style include="diagnostics-shared">
   #resultListContainer {
-    background-color: var(--google-grey-100);
+    background-color: rgba(var(--google-grey-200-rgb), .38);
     border-radius: 20px;
     padding: 15px;
   }
diff --git a/chromeos/components/diagnostics_ui/resources/routine_section.html b/chromeos/components/diagnostics_ui/resources/routine_section.html
index 765a1ca8..1f609f1 100644
--- a/chromeos/components/diagnostics_ui/resources/routine_section.html
+++ b/chromeos/components/diagnostics_ui/resources/routine_section.html
@@ -1,40 +1,87 @@
 <style include="diagnostics-shared">
   .learn-more-button {
     background-color: rgba(var(--google-blue-600), .06);
-    border-radius: 5x;
+    border-radius: 5px;
     height: 40px;
-    padding: 5px 10px;
+    margin-top: 12px;
+    padding: 6px 8px;
   }
 
   #learnMoreText {
     color: var(--google-blue-600);
     cursor: pointer;
   }
+
+  .result-list {
+    border-radius: 8px;
+    margin: 8px 0;
+  }
+
+  .routine-container {
+    display: flex;
+    justify-content: space-between;
+  }
+
+  .routine-section-container {
+    display: flex;
+    flex-direction: column;
+  }
+
+  .routine-status-container {
+    display: flex;
+    flex-direction: column;
+  }
+
+  #testStatusBadge {
+    margin-bottom: 4px;
+  }
+
+  #testStatusText {
+    @apply --diagnostics-routine-name-font;
+    color: var(--google-grey-700);
+  }
+
+  #toggleReportButton {
+    margin-right: 8px;
+  }
 </style>
 
-<div id="routineSection">
-  <cr-button id="runTestsButton" class="action-button" on-click="onRunTestsClicked_"
-      disabled="[[isTestRunning]]">
-    [[runTestsButtonText]]
-  </cr-button>
-  <cr-button id="toggleReportButton" class="action-button" on-click="onToggleReportClicked_"
-      hidden="[[isResultButtonHidden_(executionStatus_)]]">
-    [[getReportToggleButtonText_(isReportListHidden_)]]
-  </cr-button>
-  <text-badge id="testStatusBadge" badge-type="[[getBadgeType_(executionStatus_)]]"
-      hidden="[[isStatusHidden_(executionStatus_)]]"
-      value="[[getBadgeText_(executionStatus_)]]">
-  </text-badge>
-  <span id="testStatusText" hidden$="[[isStatusHidden_(executionStatus_)]]">
-    [[getTextStatus_(executionStatus_, currentTestName_)]]
-  </span>
-  <span id="learnMoreText" hidden$="[[isLearnMoreHidden_(executionStatus_)]]"
-      on-click="onLearnMoreClicked_">
-    [[i18n('learnMoreShort')]]
-  </span>
-  <routine-result-list id="resultList" hidden="[[isReportListHidden_]]"></routine-result-list>
-  <cr-button id="learnMoreButton" class="learn-more-button" on-click="onLearnMoreClicked_"
-      hidden="[[isReportListHidden_]]">
-      [[i18n('learnMore')]]
-  </cr-button>
+<div class="routine-section-container">
+  <div id="routineSection" class="routine-container">
+    <div class="routine-status-container">
+      <text-badge id="testStatusBadge"
+          badge-type="[[getBadgeType_(executionStatus_)]]"
+          hidden="[[isStatusHidden_(executionStatus_)]]"
+          value="[[getBadgeText_(executionStatus_)]]">
+      </text-badge>
+      <span id="testStatusText"
+          hidden$="[[isStatusHidden_(executionStatus_)]]">
+        [[getTextStatus_(executionStatus_, currentTestName_)]]
+      </span>
+      <span id="learnMoreText"
+          hidden$="[[isLearnMoreHidden_(executionStatus_)]]"
+          on-click="onLearnMoreClicked_">
+        [[i18n('learnMoreShort')]]
+      </span>
+    </div>
+    <div>
+      <cr-button id="toggleReportButton" on-click="onToggleReportClicked_"
+          hidden="[[isResultButtonHidden_(executionStatus_)]]">
+        [[getReportToggleButtonText_(opened)]]
+      </cr-button>
+      <cr-button id="runTestsButton" on-click="onRunTestsClicked_"
+          disabled="[[isTestRunning]]">
+          [[runTestsButtonText]]
+      </cr-button>
+    </div>
+  </div>
+  <iron-collapse id="collapse" opened="{{opened}}">
+    <div class="result-list">
+      <routine-result-list id="resultList"></routine-result-list>
+    </div>
+    <cr-button id="learnMoreButton" class="learn-more-button"
+        on-click="onLearnMoreClicked_">
+        [[i18n('learnMore')]]
+    </cr-button>
+  </iron-collapse>
 </div>
diff --git a/chromeos/components/diagnostics_ui/resources/routine_section.js b/chromeos/components/diagnostics_ui/resources/routine_section.js
index cb63380..948c7665 100644
--- a/chromeos/components/diagnostics_ui/resources/routine_section.js
+++ b/chromeos/components/diagnostics_ui/resources/routine_section.js
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'chrome://resources/polymer/v3_0/iron-collapse/iron-collapse.js';
 import './diagnostics_card.js';
 import './diagnostics_shared_css.js';
 import './routine_result_list.js';
@@ -79,12 +80,6 @@
       notify: true,
     },
 
-    /** @private {boolean} */
-    isReportListHidden_: {
-      type: Boolean,
-      value: true,
-    },
-
     /** @type {boolean} */
     isPowerRoutine: {
       type: Boolean,
@@ -166,7 +161,7 @@
   /** @private */
   onToggleReportClicked_() {
     // Toggle report list visibility
-    this.isReportListHidden_ = !this.isReportListHidden_;
+    this.$.collapse.toggle();
   },
 
   /** @private */
@@ -192,10 +187,13 @@
     return this.executionStatus_ === ExecutionProgress.kNotStarted;
   },
 
-  /** @protected */
-  getReportToggleButtonText_() {
-    return loadTimeData.getString(
-        this.isReportListHidden_ ? 'seeReportText' : 'hideReportText');
+  /**
+   * @param {boolean} opened Whether the section is expanded or not.
+   * @return {string} button text.
+   * @protected
+   */
+  getReportToggleButtonText_(opened) {
+    return loadTimeData.getString(opened ? 'hideReportText' : 'seeReportText');
   },
 
   /** @protected */
@@ -206,7 +204,7 @@
       }
       return BadgeType.SUCCESS;
     }
-    return BadgeType.DEFAULT;
+    return BadgeType.RUNNING;
   },
 
   /** @protected */
diff --git a/chromeos/components/diagnostics_ui/resources/text_badge.html b/chromeos/components/diagnostics_ui/resources/text_badge.html
index e6fcc26b..b63e8c75 100644
--- a/chromeos/components/diagnostics_ui/resources/text_badge.html
+++ b/chromeos/components/diagnostics_ui/resources/text_badge.html
@@ -1,22 +1,32 @@
 <style include="diagnostics-shared">
-  #textBadge {
-    padding: 3px 5px;
-    border-radius: 3px;
+  .error {
+    background-color: var(--google-red-50);
+    color: var(--google-red-600);
+    margin-right: 14px;
   }
 
-  .default {
-    background-color: var(--google-blue-100);
-    color: var(--google-blue-500);
+  .queued {
+    background-color: var(--google-grey-200);
+    color: var(--google-grey-600);
+    margin-right: 7px;
+  }
+
+  .running {
+    background-color: var(--google-blue-50);
+    color: var(--google-blue-600);
   }
 
   .success {
-    background-color: var(--google-green-100);
-    color: var(--google-green-500);
+    background-color: var(--google-green-50);
+    color: var(--google-green-600);
   }
 
-  .error {
-    background-color: var(--google-red-100);
-    color: var(--google-red-500);
+  #textBadge {
+    @apply --diagnostics-text-badge-font;
+    border-radius: 4px;
+    height: 20px;
+    padding: 2px 6px;
+    text-transform: uppercase;
   }
 </style>
 
diff --git a/chromeos/components/diagnostics_ui/resources/text_badge.js b/chromeos/components/diagnostics_ui/resources/text_badge.js
index 03d96ab..a5e618a9 100644
--- a/chromeos/components/diagnostics_ui/resources/text_badge.js
+++ b/chromeos/components/diagnostics_ui/resources/text_badge.js
@@ -12,8 +12,9 @@
  * @enum {string}
  */
 export const BadgeType = {
-  DEFAULT: 'default',
   ERROR: 'error',
+  QUEUED: 'queued',
+  RUNNING: 'running',
   SUCCESS: 'success',
 };
 
@@ -30,7 +31,7 @@
     /** @type {!BadgeType} */
     badgeType: {
       type: String,
-      value: BadgeType.DEFAULT,
+      value: BadgeType.QUEUED,
     },
 
     /** @type {string} */
diff --git a/chromeos/components/scanning/resources/scan_preview.html b/chromeos/components/scanning/resources/scan_preview.html
index bee743e..e365c060 100644
--- a/chromeos/components/scanning/resources/scan_preview.html
+++ b/chromeos/components/scanning/resources/scan_preview.html
@@ -1,9 +1,4 @@
 <style include="scanning-shared scanning-fonts">
-  /* Styles part of the string returned by getHelperTextHtml_(). */
-  #boldHelperText {
-    font-weight: var(--scanning-medium-font-weight);
-  }
-
   #helperText {
     @apply --scanning-helper-text-font;
     color: var(--scanning-helper-text-color);
@@ -89,7 +84,7 @@
   <div id="helpOrProgress" class="preview-item" hidden$="[[showScannedImages_]]"
       aria-hidden="true">
     <div id="helperText" hidden$="[[!showHelperText_]]">
-      <span inner-h-t-m-l="[[getHelperTextHtml_()]]"></span>
+      [[i18n('scanPreviewHelperText')]]
     </div>
     <div id="scanProgress" hidden$="[[!showScanProgress_]]">
       <span id="progressText">[[progressTextString_]]</span>
diff --git a/chromeos/components/scanning/resources/scan_preview.js b/chromeos/components/scanning/resources/scan_preview.js
index 6963c4f..d65d059 100644
--- a/chromeos/components/scanning/resources/scan_preview.js
+++ b/chromeos/components/scanning/resources/scan_preview.js
@@ -100,16 +100,6 @@
     this.browserProxy_ = ScanningBrowserProxyImpl.getInstance();
   },
 
-  /**
-   * Returns the translated helper text string with the id attribute. The id is
-   * used to selectively style parts of the string.
-   * @return {string}
-   * @private
-   */
-  getHelperTextHtml_() {
-    return this.i18nAdvanced('scanPreviewHelperText', {attrs: ['id']});
-  },
-
   /** @private */
   onAppStateChange_() {
     this.showScannedImages_ = this.appState === AppState.DONE;
@@ -148,12 +138,7 @@
     }
 
     if (this.showHelperText_) {
-      // We can't directly use the 'scanPreviewHelperText' string because it
-      // conatains HTML. So instead wait for the page to render then use its
-      // text as the ARIA label.
-      afterNextRender(this, () => {
-        this.previewAriaLabel_ = this.$.helperText.innerText;
-      });
+      this.previewAriaLabel_ = this.i18n('scanPreviewHelperText');
       return;
     }
   },
diff --git a/chromeos/components/scanning/resources/scanning_app.html b/chromeos/components/scanning/resources/scanning_app.html
index 53783cf..2b66a465 100644
--- a/chromeos/components/scanning/resources/scanning_app.html
+++ b/chromeos/components/scanning/resources/scanning_app.html
@@ -96,10 +96,17 @@
 
   #container {
     flex: 1;
-    max-height: 445px;
     overflow: overlay;
   }
 
+  :host([opened_]) #container {
+    max-height: 445px;
+  }
+
+  :host(:not([opened_])) #container {
+    max-height: 277px;
+  }
+
   .scan-button-container {
     display: flex;
     justify-content: flex-end;
@@ -185,13 +192,13 @@
                 selected-file-type="{{selectedFileType}}"></file-type-select>
             <div id="more-settings-line-separator"></div>
             <cr-button id="moreSettingsButton" on-click="toggleClicked_"
-                aria-expanded="[[opened]]"
+                aria-expanded="[[opened_]]"
                 disabled="[[settingsDisabled_]]">
               <span>[[i18n('moreSettings')]]</span>
-              <iron-icon icon="[[getArrowIcon_(opened)]]">
+              <iron-icon icon="[[getArrowIcon_(opened_)]]">
               </iron-icon>
             </cr-button>
-            <iron-collapse id="collapse" opened="{{opened}}">
+            <iron-collapse id="collapse" opened="{{opened_}}">
               <color-mode-select id="colorModeSelect"
                   color-modes="[[capabilities_.colorModes]]"
                   disabled="[[settingsDisabled_]]"
diff --git a/chromeos/components/scanning/resources/scanning_app.js b/chromeos/components/scanning/resources/scanning_app.js
index 0438a4c..c2b58833 100644
--- a/chromeos/components/scanning/resources/scanning_app.js
+++ b/chromeos/components/scanning/resources/scanning_app.js
@@ -207,6 +207,16 @@
       type: Boolean,
       value: false,
     },
+
+    /**
+     * Indicates whether the More settings section is expanded.
+     * @private {boolean}
+     */
+    opened_: {
+      type: Boolean,
+      value: false,
+      reflectToAttribute: true,
+    },
   },
 
   /** @override */
@@ -421,12 +431,11 @@
   },
 
   /**
-   * @param {boolean} opened Whether the section is expanded or not.
    * @return {string} Icon name.
    * @private
    */
-  getArrowIcon_(opened) {
-    return opened ? 'cr:expand-less' : 'cr:expand-more';
+  getArrowIcon_() {
+    return this.opened_ ? 'cr:expand-less' : 'cr:expand-more';
   },
 
   /**
diff --git a/chromeos/components/scanning/resources/scanning_fonts_css.html b/chromeos/components/scanning/resources/scanning_fonts_css.html
index d99f55f..fa395f9 100644
--- a/chromeos/components/scanning/resources/scanning_fonts_css.html
+++ b/chromeos/components/scanning/resources/scanning_fonts_css.html
@@ -3,7 +3,7 @@
     :host {
       --scanning-done-section-title-font-family: "Google Sans", Roboto, sans-serif;
       --scanning-done-section-option-font-family: Roboto;
-      --scanning-helper-text-font-family: "Google Sans", Roboto, sans-serif;
+      --scanning-helper-text-font-family: Roboto;
       --scanning-more-settings-font-family: Roboto;
       --scanning-no-scanners-help-text-font-family: Roboto;
       --scanning-progress-text-font-family: "Google Sans", Roboto, sans-serif;
@@ -12,7 +12,7 @@
 
       --scanning-done-section-title-font-size: 22px;
       --scanning-done-section-option-font-size: 13px;
-      --scanning-helper-text-font-size: 16px;
+      --scanning-helper-text-font-size: 13px;
       --scanning-more-settings-font-size: 12px;
       --scanning-no-scanners-help-text-font-size: 10px;
       --scanning-progress-text-font-size: 16px;
@@ -21,7 +21,7 @@
 
       --scanning-done-section-title-line-height: 28px;
       --scanning-done-section-option-line-height: 20px;
-      --scanning-helper-text-line-height: 24px;
+      --scanning-helper-text-line-height: 20px;
       --scanning-more-settings-line-height: 18px;
       --scanning-no-scanners-help-text-line-height: 10px;
       --scanning-progress-text-line-height: 24px;
diff --git a/chromeos/profiles/atom.afdo.newest.txt b/chromeos/profiles/atom.afdo.newest.txt
index a5f2ee1..3779b31 100644
--- a/chromeos/profiles/atom.afdo.newest.txt
+++ b/chromeos/profiles/atom.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-atom-89-4380.0-1610362181-benchmark-89.0.4385.0-r1-redacted.afdo.xz
+chromeos-chrome-amd64-atom-89-4380.0-1610362181-benchmark-89.0.4386.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt
index 4d7151f..f66dae6 100644
--- a/chromeos/profiles/bigcore.afdo.newest.txt
+++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-bigcore-89-4374.0-1610361443-benchmark-89.0.4385.0-r1-redacted.afdo.xz
+chromeos-chrome-amd64-bigcore-89-4374.0-1610361443-benchmark-89.0.4386.0-r1-redacted.afdo.xz
diff --git a/chromeos/services/device_sync/device_sync_impl.cc b/chromeos/services/device_sync/device_sync_impl.cc
index f48c80f..a26354cd 100644
--- a/chromeos/services/device_sync/device_sync_impl.cc
+++ b/chromeos/services/device_sync/device_sync_impl.cc
@@ -783,14 +783,20 @@
   clock_ = nullptr;
 }
 
-void DeviceSyncImpl::OnUnconsentedPrimaryAccountChanged(
-    const CoreAccountInfo& primary_account_info) {
-  PA_LOG(VERBOSE) << "DeviceSyncImpl: OnUnconsentedPrimaryAccountChanged";
-  // We're only interested when the account is set.
-  if (primary_account_info.account_id.empty())
-    return;
-  identity_manager_->RemoveObserver(this);
-  ProcessPrimaryAccountInfo(primary_account_info);
+void DeviceSyncImpl::OnPrimaryAccountChanged(
+    const signin::PrimaryAccountChangeEvent& event) {
+  PA_LOG(VERBOSE) << "DeviceSyncImpl: OnPrimaryAccountChanged";
+  switch (event.GetEventTypeFor(signin::ConsentLevel::kNotRequired)) {
+    case signin::PrimaryAccountChangeEvent::Type::kSet:
+      identity_manager_->RemoveObserver(this);
+      ProcessPrimaryAccountInfo(event.GetCurrentState().primary_account);
+      break;
+    case signin::PrimaryAccountChangeEvent::Type::kCleared:
+      FALLTHROUGH;
+    case signin::PrimaryAccountChangeEvent::Type::kNone:
+      // Ignored
+      break;
+  }
 }
 
 void DeviceSyncImpl::RunNextInitializationStep() {
diff --git a/chromeos/services/device_sync/device_sync_impl.h b/chromeos/services/device_sync/device_sync_impl.h
index c1afbc70..bcfafde 100644
--- a/chromeos/services/device_sync/device_sync_impl.h
+++ b/chromeos/services/device_sync/device_sync_impl.h
@@ -219,8 +219,8 @@
   void Shutdown() override;
 
   // signin::IdentityManager::Observer:
-  void OnUnconsentedPrimaryAccountChanged(
-      const CoreAccountInfo& primary_account_info) override;
+  void OnPrimaryAccountChanged(
+      const signin::PrimaryAccountChangeEvent& event) override;
 
   // Initialization functions.
   void RunNextInitializationStep();
diff --git a/components/browser_ui/settings/android/BUILD.gn b/components/browser_ui/settings/android/BUILD.gn
index 64ee977..6547dc5 100644
--- a/components/browser_ui/settings/android/BUILD.gn
+++ b/components/browser_ui/settings/android/BUILD.gn
@@ -6,9 +6,11 @@
 
 android_library("java") {
   sources = [
+    "java/src/org/chromium/components/browser_ui/settings/FragmentSettingsLauncher.java",
     "java/src/org/chromium/components/browser_ui/settings/ManagedPreferenceDelegate.java",
     "java/src/org/chromium/components/browser_ui/settings/ManagedPreferencesUtils.java",
     "java/src/org/chromium/components/browser_ui/settings/SearchUtils.java",
+    "java/src/org/chromium/components/browser_ui/settings/SettingsLauncher.java",
     "java/src/org/chromium/components/browser_ui/settings/SettingsUtils.java",
     "widget/java/src/org/chromium/components/browser_ui/settings/ButtonPreference.java",
     "widget/java/src/org/chromium/components/browser_ui/settings/ChromeBaseCheckBoxPreference.java",
diff --git a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/FragmentSettingsLauncher.java b/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/FragmentSettingsLauncher.java
similarity index 91%
rename from chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/FragmentSettingsLauncher.java
rename to components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/FragmentSettingsLauncher.java
index 4f6a054..2ce5db53 100644
--- a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/FragmentSettingsLauncher.java
+++ b/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/FragmentSettingsLauncher.java
@@ -2,7 +2,7 @@
 // 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.settings;
+package org.chromium.components.browser_ui.settings;
 
 /**
  * Interface for injecting SettingsLauncher to a fragment. It is useful for modularized fragments
diff --git a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/SettingsLauncher.java b/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/SettingsLauncher.java
similarity index 97%
rename from chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/SettingsLauncher.java
rename to components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/SettingsLauncher.java
index 8a213c0..356f30d8 100644
--- a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/SettingsLauncher.java
+++ b/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/SettingsLauncher.java
@@ -2,7 +2,7 @@
 // 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.settings;
+package org.chromium.components.browser_ui.settings;
 
 import android.content.Context;
 import android.content.Intent;
diff --git a/components/ntp_tiles/most_visited_sites.cc b/components/ntp_tiles/most_visited_sites.cc
index f2125d1..71c718f 100644
--- a/components/ntp_tiles/most_visited_sites.cc
+++ b/components/ntp_tiles/most_visited_sites.cc
@@ -392,6 +392,10 @@
     BuildCurrentTiles();
 }
 
+size_t MostVisitedSites::GetCustomLinkNum() {
+  return custom_links_->GetLinks().size();
+}
+
 void MostVisitedSites::AddOrRemoveBlockedUrl(const GURL& url, bool add_url) {
   if (add_url) {
     base::RecordAction(base::UserMetricsAction("Suggestions.Site.Removed"));
diff --git a/components/ntp_tiles/most_visited_sites.h b/components/ntp_tiles/most_visited_sites.h
index 4e1f4f3..b59b82d0 100644
--- a/components/ntp_tiles/most_visited_sites.h
+++ b/components/ntp_tiles/most_visited_sites.h
@@ -215,6 +215,8 @@
   // must be enabled.
   void UndoCustomLinkAction();
 
+  size_t GetCustomLinkNum();
+
   void AddOrRemoveBlockedUrl(const GURL& url, bool add_url);
   void ClearBlockedUrls();
 
diff --git a/components/search_engines/template_url_service.cc b/components/search_engines/template_url_service.cc
index 124bd48..717c765 100644
--- a/components/search_engines/template_url_service.cc
+++ b/components/search_engines/template_url_service.cc
@@ -480,7 +480,25 @@
 }
 
 void TemplateURLService::Remove(const TemplateURL* template_url) {
-  DCHECK_NE(template_url, default_search_provider_);
+  // CHECK that we aren't trying to Remove() the default search provider.
+  // This has happened before, and causes permanent damage to the user Profile,
+  // which can then be Synced to other installations. It's better to crash
+  // immediately, and that's why this isn't a DCHECK. https://crbug.com/1164024
+  {
+    const TemplateURL* default_provider = GetDefaultSearchProvider();
+
+    // TODO(tommycli): Once we are sure this never happens in practice, we can
+    // remove this CrashKeyString, but we should keep the CHECK.
+    static base::debug::CrashKeyString* crash_key =
+        base::debug::AllocateCrashKeyString("removed_turl_keyword",
+                                            base::debug::CrashKeySize::Size256);
+    base::debug::ScopedCrashKeyString auto_clear(
+        crash_key, base::UTF16ToUTF8(template_url->keyword()));
+
+    CHECK_NE(template_url, default_provider);
+    if (default_provider)
+      CHECK_NE(template_url->sync_guid(), default_provider->sync_guid());
+  }
 
   auto i = FindTemplateURL(&template_urls_, template_url);
   if (i == template_urls_.end())
@@ -2175,6 +2193,14 @@
     best = candidate;
   }
 
+  // Use a GUID comparison rather than a pointer comparison, because while the
+  // model is being loaded, the DSE may be sourced from prefs, and we still want
+  // to protect the corresponding database entry from deletion.
+  // https://crbug.com/1164024
+  const TemplateURL* default_provider = GetDefaultSearchProvider();
+  std::string default_provider_guid =
+      default_provider ? default_provider->sync_guid() : "";
+
   // Remove all the replaceable TemplateURLs that are not the best.
   for (TemplateURL* turl : replaceable_turls) {
     DCHECK_NE(turl, candidate);
@@ -2182,7 +2208,7 @@
     // Never actually remove the DSE during this phase. This handling defers
     // deleting the DSE until it's no longer set as the DSE, analagous to how
     // we handle ACTION_DELETE of the DSE in ProcessSyncChanges().
-    if (turl != best && turl != default_search_provider_) {
+    if (turl != best && turl->sync_guid() != default_provider_guid) {
       Remove(turl);
     }
   }
diff --git a/components/search_engines/template_url_service.h b/components/search_engines/template_url_service.h
index 8c8213c..e04dbf27 100644
--- a/components/search_engines/template_url_service.h
+++ b/components/search_engines/template_url_service.h
@@ -730,6 +730,11 @@
 
   // Once loaded, the default search provider.  This is a pointer to a
   // TemplateURL owned by |template_urls_|.
+  //
+  // TODO(tommycli): Can we combine this with initial_default_search_provider_?
+  // Essentially all direct usages of this variable need to first check that
+  // |loading_| is true, and should call GetDefaultSearchProvider() instead.
+  // Example of a regression due to this mistake: https://crbug.com/1164024.
   TemplateURL* default_search_provider_ = nullptr;
 
   // A temporary location for the DSE until Web Data has been loaded and it can
diff --git a/components/signin/ios/browser/account_consistency_service.h b/components/signin/ios/browser/account_consistency_service.h
index a5ab951..3b0ceef0 100644
--- a/components/signin/ios/browser/account_consistency_service.h
+++ b/components/signin/ios/browser/account_consistency_service.h
@@ -113,9 +113,8 @@
   void ResetInternalState();
 
   // IdentityManager::Observer implementation.
-  void OnPrimaryAccountSet(const CoreAccountInfo& account_info) override;
-  void OnPrimaryAccountCleared(
-      const CoreAccountInfo& previous_account_info) override;
+  void OnPrimaryAccountChanged(
+      const signin::PrimaryAccountChangeEvent& event) override;
   void OnAccountsInCookieUpdated(
       const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
       const GoogleServiceAuthError& error) override;
diff --git a/components/signin/ios/browser/account_consistency_service.mm b/components/signin/ios/browser/account_consistency_service.mm
index 18899b4..7b1b98e 100644
--- a/components/signin/ios/browser/account_consistency_service.mm
+++ b/components/signin/ios/browser/account_consistency_service.mm
@@ -556,14 +556,20 @@
   identity_manager_->GetAccountsCookieMutator()->ForceTriggerOnCookieChange();
 }
 
-void AccountConsistencyService::OnPrimaryAccountSet(
-    const CoreAccountInfo& account_info) {
-  AddChromeConnectedCookies();
-}
-
-void AccountConsistencyService::OnPrimaryAccountCleared(
-    const CoreAccountInfo& previous_account_info) {
-  RemoveAllChromeConnectedCookies(base::OnceClosure());
+void AccountConsistencyService::OnPrimaryAccountChanged(
+    const signin::PrimaryAccountChangeEvent& event) {
+  switch (event.GetEventTypeFor(signin::ConsentLevel::kSync)) {
+    case signin::PrimaryAccountChangeEvent::Type::kSet:
+      AddChromeConnectedCookies();
+      break;
+    case signin::PrimaryAccountChangeEvent::Type::kCleared:
+      RemoveAllChromeConnectedCookies(base::OnceClosure());
+      break;
+    case signin::PrimaryAccountChangeEvent::Type::kNone:
+      NOTREACHED() << "ConsentLevel::kNotRequired is not yet supported on iOS. "
+                      "This code needs to be updated when it is supported.";
+      break;
+  }
 }
 
 void AccountConsistencyService::OnAccountsInCookieUpdated(
diff --git a/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h b/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h
index 288840530..aded67f 100644
--- a/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h
+++ b/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.h
@@ -47,10 +47,8 @@
   ~IdentityManagerObserverBridge() override;
 
   // IdentityManager::Observer.
-  void OnPrimaryAccountSet(
-      const CoreAccountInfo& primary_account_info) override;
-  void OnPrimaryAccountCleared(
-      const CoreAccountInfo& previous_primary_account_info) override;
+  void OnPrimaryAccountChanged(
+      const signin::PrimaryAccountChangeEvent& event) override;
   void OnRefreshTokenUpdatedForAccount(
       const CoreAccountInfo& account_info) override;
   void OnRefreshTokenRemovedForAccount(
diff --git a/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.mm b/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.mm
index 991030ec..c311ceda 100644
--- a/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.mm
+++ b/components/signin/public/identity_manager/objc/identity_manager_observer_bridge.mm
@@ -21,17 +21,24 @@
   identity_manager_->RemoveObserver(this);
 }
 
-void IdentityManagerObserverBridge::OnPrimaryAccountSet(
-    const CoreAccountInfo& primary_account_info) {
-  if ([delegate_ respondsToSelector:@selector(onPrimaryAccountSet:)]) {
-    [delegate_ onPrimaryAccountSet:primary_account_info];
-  }
-}
-
-void IdentityManagerObserverBridge::OnPrimaryAccountCleared(
-    const CoreAccountInfo& previous_primary_account_info) {
-  if ([delegate_ respondsToSelector:@selector(onPrimaryAccountCleared:)]) {
-    [delegate_ onPrimaryAccountCleared:previous_primary_account_info];
+void IdentityManagerObserverBridge::OnPrimaryAccountChanged(
+    const signin::PrimaryAccountChangeEvent& event) {
+  switch (event.GetEventTypeFor(signin::ConsentLevel::kSync)) {
+    case signin::PrimaryAccountChangeEvent::Type::kSet:
+      if ([delegate_ respondsToSelector:@selector(onPrimaryAccountSet:)]) {
+        [delegate_ onPrimaryAccountSet:event.GetCurrentState().primary_account];
+      }
+      break;
+    case signin::PrimaryAccountChangeEvent::Type::kCleared:
+      if ([delegate_ respondsToSelector:@selector(onPrimaryAccountCleared:)]) {
+        [delegate_
+            onPrimaryAccountCleared:event.GetPreviousState().primary_account];
+      }
+      break;
+    case signin::PrimaryAccountChangeEvent::Type::kNone:
+      NOTREACHED() << "ConsentLevel::kNotRequired is not yet supported on iOS. "
+                      "This code needs to be updated when it is supported.";
+      break;
   }
 }
 
diff --git a/components/translate/core/browser/translate_browser_metrics.cc b/components/translate/core/browser/translate_browser_metrics.cc
index fcfd767..41323cb 100644
--- a/components/translate/core/browser/translate_browser_metrics.cc
+++ b/components/translate/core/browser/translate_browser_metrics.cc
@@ -22,8 +22,6 @@
     "Translate.LanguageDetection.ContentLength";
 const char kTranslateLocalesOnDisabledByPrefs[] =
     "Translate.LocalesOnDisabledByPrefs";
-const char kTranslateUndisplayableLanguage[] =
-    "Translate.UndisplayableLanguage";
 const char kTranslateUnsupportedLanguageAtInitiation[] =
     "Translate.UnsupportedLanguageAtInitiation";
 const char kTranslateSourceLanguage[] = "Translate.SourceLanguage";
@@ -65,11 +63,6 @@
       language::LanguageUsageMetrics::ToLanguageCode(locale));
 }
 
-void ReportUndisplayableLanguage(base::StringPiece language) {
-  int language_code = language::LanguageUsageMetrics::ToLanguageCode(language);
-  base::UmaHistogramSparse(kTranslateUndisplayableLanguage, language_code);
-}
-
 void ReportUnsupportedLanguageAtInitiation(base::StringPiece language) {
   int language_code = language::LanguageUsageMetrics::ToLanguageCode(language);
   base::UmaHistogramSparse(kTranslateUnsupportedLanguageAtInitiation,
diff --git a/components/translate/core/browser/translate_browser_metrics.h b/components/translate/core/browser/translate_browser_metrics.h
index dff7aa4..b5817e5 100644
--- a/components/translate/core/browser/translate_browser_metrics.h
+++ b/components/translate/core/browser/translate_browser_metrics.h
@@ -116,10 +116,6 @@
 
 void ReportLocalesOnDisabledByPrefs(base::StringPiece locale);
 
-// Called when Chrome Translate server sends the language list which includes
-// a undisplayable language in the user's locale.
-void ReportUndisplayableLanguage(base::StringPiece language);
-
 void ReportUnsupportedLanguageAtInitiation(base::StringPiece language);
 
 // Called when a request is sent to the translate server to report the source
diff --git a/components/translate/core/browser/translate_browser_metrics_unittest.cc b/components/translate/core/browser/translate_browser_metrics_unittest.cc
index 79accd6..0cb1f13 100644
--- a/components/translate/core/browser/translate_browser_metrics_unittest.cc
+++ b/components/translate/core/browser/translate_browser_metrics_unittest.cc
@@ -372,15 +372,6 @@
   EXPECT_EQ(1, recorder.GetCount(ENGLISH));
 }
 
-TEST(TranslateBrowserMetricsTest, ReportedUndisplayableLanguage) {
-  const int ENGLISH = 25966;
-
-  MetricsRecorder recorder("Translate.UndisplayableLanguage");
-  EXPECT_EQ(0, recorder.GetTotalCount());
-  translate::TranslateBrowserMetrics::ReportUndisplayableLanguage("en");
-  EXPECT_EQ(1, recorder.GetCount(ENGLISH));
-}
-
 TEST(TranslateBrowserMetricsTest, ReportedUnsupportedLanguageAtInitiation) {
   const int ENGLISH = 25966;
 
diff --git a/components/translate/core/browser/translate_language_list.cc b/components/translate/core/browser/translate_language_list.cc
index 48b72e0..e586664 100644
--- a/components/translate/core/browser/translate_language_list.cc
+++ b/components/translate/core/browser/translate_language_list.cc
@@ -341,7 +341,7 @@
   for (const auto& kv_pair : target_languages->DictItems()) {
     const std::string& lang = kv_pair.first;
     if (!l10n_util::IsLocaleNameTranslated(lang.c_str(), locale)) {
-      TranslateBrowserMetrics::ReportUndisplayableLanguage(lang);
+      // Don't include languages not displayable in current UI language.
       continue;
     }
     supported_languages_.push_back(lang);
diff --git a/components/viz/common/features.cc b/components/viz/common/features.cc
index 7a0ed0c..5746b04 100644
--- a/components/viz/common/features.cc
+++ b/components/viz/common/features.cc
@@ -29,9 +29,6 @@
 #endif
 };
 
-const base::Feature kForcePreferredIntervalForVideo{
-    "ForcePreferredIntervalForVideo", base::FEATURE_DISABLED_BY_DEFAULT};
-
 // Use the SkiaRenderer.
 const base::Feature kUseSkiaRenderer {
   "UseSkiaRenderer",
@@ -98,10 +95,6 @@
 const base::Feature kWebRtcLogCapturePipeline{
     "WebRtcLogCapturePipeline", base::FEATURE_DISABLED_BY_DEFAULT};
 
-// The number of frames to wait before toggling to a lower frame rate.
-const base::FeatureParam<int> kNumOfFramesToToggleInterval{
-    &kUsePreferredIntervalForVideo, "NumOfFramesToToggleInterval", 6};
-
 #if defined(OS_WIN)
 // Enables swap chains to call SetPresentDuration to request DWM/OS to reduce
 // vsync.
@@ -124,10 +117,6 @@
   return base::FeatureList::IsEnabled(kEnableOverlayPrioritization);
 }
 
-bool IsForcePreferredIntervalForVideoEnabled() {
-  return base::FeatureList::IsEnabled(kForcePreferredIntervalForVideo);
-}
-
 bool IsVizHitTestingDebugEnabled() {
   return base::CommandLine::ForCurrentProcess()->HasSwitch(
       switches::kEnableVizHitTestDebug);
@@ -193,12 +182,7 @@
 }
 
 bool IsUsingPreferredIntervalForVideo() {
-  return IsForcePreferredIntervalForVideoEnabled() ||
-         base::FeatureList::IsEnabled(kUsePreferredIntervalForVideo);
-}
-
-int NumOfFramesToToggleInterval() {
-  return kNumOfFramesToToggleInterval.Get();
+  return base::FeatureList::IsEnabled(kUsePreferredIntervalForVideo);
 }
 
 bool ShouldUseRealBuffersForPageFlipTest() {
diff --git a/components/viz/common/features.h b/components/viz/common/features.h
index fb32e0a..569421d 100644
--- a/components/viz/common/features.h
+++ b/components/viz/common/features.h
@@ -14,7 +14,6 @@
 namespace features {
 
 VIZ_COMMON_EXPORT extern const base::Feature kEnableOverlayPrioritization;
-VIZ_COMMON_EXPORT extern const base::Feature kForcePreferredIntervalForVideo;
 VIZ_COMMON_EXPORT extern const base::Feature kUseSkiaRenderer;
 VIZ_COMMON_EXPORT extern const base::Feature kRecordSkPicture;
 VIZ_COMMON_EXPORT extern const base::Feature kDisableDeJelly;
@@ -38,7 +37,6 @@
 #endif
 VIZ_COMMON_EXPORT extern const base::Feature kWebViewVulkanIntermediateBuffer;
 
-VIZ_COMMON_EXPORT bool IsForcePreferredIntervalForVideoEnabled();
 VIZ_COMMON_EXPORT bool IsVizHitTestingDebugEnabled();
 VIZ_COMMON_EXPORT bool IsUsingSkiaRenderer();
 #if defined(OS_ANDROID)
@@ -49,7 +47,6 @@
 VIZ_COMMON_EXPORT bool IsUsingVizForWebView();
 VIZ_COMMON_EXPORT bool IsUsingVizFrameSubmissionForWebView();
 VIZ_COMMON_EXPORT bool IsUsingPreferredIntervalForVideo();
-VIZ_COMMON_EXPORT int NumOfFramesToToggleInterval();
 VIZ_COMMON_EXPORT bool ShouldUseRealBuffersForPageFlipTest();
 VIZ_COMMON_EXPORT bool ShouldWebRtcLogCapturePipeline();
 #if defined(OS_WIN)
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc
index dbe6608..0fde006 100644
--- a/components/viz/service/display/display.cc
+++ b/components/viz/service/display/display.cc
@@ -364,8 +364,7 @@
 void Display::Initialize(DisplayClient* client,
                          SurfaceManager* surface_manager,
                          bool enable_shared_images,
-                         bool hw_support_for_multiple_refresh_rates,
-                         size_t num_of_frames_to_toggle_interval) {
+                         bool hw_support_for_multiple_refresh_rates) {
   DCHECK(client);
   DCHECK(surface_manager);
   gpu::ScopedAllowScheduleGpuTask allow_schedule_gpu_task;
@@ -378,8 +377,7 @@
 
   frame_rate_decider_ = std::make_unique<FrameRateDecider>(
       surface_manager_, this, hw_support_for_multiple_refresh_rates,
-      SupportsSetFrameRate(output_surface_.get()),
-      num_of_frames_to_toggle_interval);
+      SupportsSetFrameRate(output_surface_.get()));
 
   InitializeRenderer(enable_shared_images);
 
diff --git a/components/viz/service/display/display.h b/components/viz/service/display/display.h
index 525b0f0..7c6e818 100644
--- a/components/viz/service/display/display.h
+++ b/components/viz/service/display/display.h
@@ -111,8 +111,7 @@
   void Initialize(DisplayClient* client,
                   SurfaceManager* surface_manager,
                   bool enable_shared_images = kEnableSharedImages,
-                  bool hw_support_for_multiple_refresh_rates = false,
-                  size_t num_of_frames_to_toggle_interval = 60);
+                  bool hw_support_for_multiple_refresh_rates = false);
 
   void AddObserver(DisplayObserver* observer);
   void RemoveObserver(DisplayObserver* observer);
diff --git a/components/viz/service/display/frame_rate_decider.cc b/components/viz/service/display/frame_rate_decider.cc
index 624ca8f..b283c41 100644
--- a/components/viz/service/display/frame_rate_decider.cc
+++ b/components/viz/service/display/frame_rate_decider.cc
@@ -14,6 +14,12 @@
 namespace viz {
 namespace {
 
+// The minimum number of frames for which a frame interval preference should
+// persist before we toggle to it. This is only applied when lowering the frame
+// rate. If the new preference is higher than the current setting, it is applied
+// immediately.
+constexpr size_t kMinNumOfFramesToToggleInterval = 6;
+
 bool AreAlmostEqual(base::TimeDelta a, base::TimeDelta b) {
   if (a.is_min() || b.is_min() || a.is_max() || b.is_max())
     return a == b;
@@ -36,10 +42,9 @@
 FrameRateDecider::FrameRateDecider(SurfaceManager* surface_manager,
                                    Client* client,
                                    bool hw_support_for_multiple_refresh_rates,
-                                   bool supports_set_frame_rate,
-                                   size_t num_of_frames_to_toggle_interval)
+                                   bool supports_set_frame_rate)
     : supported_intervals_{BeginFrameArgs::DefaultInterval()},
-      min_num_of_frames_to_toggle_interval_(num_of_frames_to_toggle_interval),
+      min_num_of_frames_to_toggle_interval_(kMinNumOfFramesToToggleInterval),
       surface_manager_(surface_manager),
       client_(client),
       hw_support_for_multiple_refresh_rates_(
diff --git a/components/viz/service/display/frame_rate_decider.h b/components/viz/service/display/frame_rate_decider.h
index 638fe62..818374a 100644
--- a/components/viz/service/display/frame_rate_decider.h
+++ b/components/viz/service/display/frame_rate_decider.h
@@ -61,8 +61,7 @@
   FrameRateDecider(SurfaceManager* surface_manager,
                    Client* client,
                    bool hw_support_for_multiple_refresh_rates,
-                   bool supports_set_frame_rate,
-                   size_t num_of_frames_to_toggle_interval);
+                   bool supports_set_frame_rate);
   ~FrameRateDecider() override;
 
   void SetSupportedFrameIntervals(
diff --git a/components/viz/service/display/frame_rate_decider_unittest.cc b/components/viz/service/display/frame_rate_decider_unittest.cc
index 1e357a47..e4d902a 100644
--- a/components/viz/service/display/frame_rate_decider_unittest.cc
+++ b/components/viz/service/display/frame_rate_decider_unittest.cc
@@ -30,7 +30,9 @@
     bool hw_support_for_multiple_refresh_rates = true;
     frame_rate_decider_ = std::make_unique<FrameRateDecider>(
         surface_manager_.get(), this, hw_support_for_multiple_refresh_rates,
-        false, 0);
+        false);
+    frame_rate_decider_->set_min_num_of_frames_to_toggle_interval_for_testing(
+        0u);
   }
 
   void TearDown() override {
@@ -326,8 +328,9 @@
 TEST_F(FrameRateDeciderTest, TogglesWithSyntheticBFS) {
   bool hw_support_for_multiple_refresh_rate = false;
   frame_rate_decider_ = std::make_unique<FrameRateDecider>(
-      surface_manager_.get(), this, hw_support_for_multiple_refresh_rate, false,
-      0);
+      surface_manager_.get(), this, hw_support_for_multiple_refresh_rate,
+      false);
+  frame_rate_decider_->set_min_num_of_frames_to_toggle_interval_for_testing(0u);
   base::TimeDelta min_supported_interval = base::TimeDelta::FromSeconds(1);
   const std::vector<base::TimeDelta> supported_intervals = {
       min_supported_interval * 2, min_supported_interval};
@@ -431,8 +434,9 @@
 TEST_F(FrameRateDeciderTest, NoHwSupportForMultiRefreshRates) {
   bool hw_support_for_multiple_refresh_rate = false;
   frame_rate_decider_ = std::make_unique<FrameRateDecider>(
-      surface_manager_.get(), this, hw_support_for_multiple_refresh_rate, false,
-      0);
+      surface_manager_.get(), this, hw_support_for_multiple_refresh_rate,
+      false);
+  frame_rate_decider_->set_min_num_of_frames_to_toggle_interval_for_testing(0u);
   base::TimeDelta min_supported_interval = base::TimeDelta::FromSeconds(1);
   const std::vector<base::TimeDelta> supported_intervals = {
       min_supported_interval * 3, min_supported_interval * 2,
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc
index dd1e031..b5b629f 100644
--- a/components/viz/service/display/skia_renderer.cc
+++ b/components/viz/service/display/skia_renderer.cc
@@ -413,6 +413,20 @@
 
 // Parameters needed to draw a CompositorRenderPassDrawQuad.
 struct SkiaRenderer::DrawRPDQParams {
+  struct BypassGeometry {
+    // The additional matrix to concatenate to the SkCanvas after image filters
+    // have been configured so that the DrawQuadParams geometry is properly
+    // mapped (i.e. when set, |visible_rect| and |draw_region| must be
+    // pre-transformed by this before |content_device_transform|).
+    SkMatrix transform;
+
+    // `rect` from the bypassed RenderPassDrawQuad.
+    gfx::RectF rect;
+
+    // `visible_rect` from the bypassed RenderPassDrawQuad.
+    gfx::RectF visible_rect;
+  };
+
   explicit DrawRPDQParams(const gfx::RectF& visible_rect);
 
   // Root of the calculated image filter DAG to be applied to the render pass.
@@ -430,15 +444,9 @@
   // The content space bounds that includes any filtered extents. If empty,
   // the draw can be skipped.
   gfx::Rect filter_bounds;
-  // The additional matrix to concatenate to the SkCanvas after image filters
-  // have been configured so that the DrawQuadParams geometry is properly mapped
-  // (i.e. when set, |visible_rect| and |draw_region| must be pre-transformed by
-  // this before |content_device_transform|).
-  base::Optional<SkMatrix> bypass_transform;
-  // The pre-filter clip to apply to the bypassed content of the RenderPass.
-  // This limits the bypassed content to the output rect of the RenderPass; it
-  // is in the same space as |backdrop_filter_bounds| and |filter_bounds|.
-  base::Optional<gfx::RectF> bypass_clip;
+
+  // Geometry from the bypassed RenderPassDrawQuad.
+  base::Optional<BypassGeometry> bypass_geometry;
 
   // True when there is an |image_filter| and it's not equivalent to
   // |color_filter|.
@@ -449,14 +457,13 @@
   // True if the RenderPass's output rect would clip the visible contents that
   // are bypassing the renderpass' offscreen buffer.
   bool needs_bypass_clip(const gfx::RectF& content_rect) const {
-    if (bypass_clip.has_value()) {
-      DCHECK(bypass_transform.has_value());
-      SkRect content_bounds =
-          bypass_transform->mapRect(gfx::RectFToSkRect(content_rect));
-      return !bypass_clip->Contains(gfx::SkRectToRectF(content_bounds));
-    } else {
+    if (!bypass_geometry)
       return false;
-    }
+
+    SkRect content_bounds =
+        bypass_geometry->transform.mapRect(gfx::RectFToSkRect(content_rect));
+    return !bypass_geometry->visible_rect.Contains(
+        gfx::SkRectToRectF(content_bounds));
   }
 };
 
@@ -468,6 +475,7 @@
 struct SkiaRenderer::DrawQuadParams {
   DrawQuadParams() = default;
   DrawQuadParams(const gfx::Transform& cdt,
+                 const gfx::RectF& rect,
                  const gfx::RectF& visible_rect,
                  unsigned aa_flags,
                  SkBlendMode blend_mode,
@@ -479,6 +487,8 @@
   // or quad_to_target_transform if the remaining device transform is held in
   // the DrawRPDQParams for a bypass quad.
   gfx::Transform content_device_transform;
+  // The DrawQuad's rect.
+  gfx::RectF rect;
   // The DrawQuad's visible_rect, possibly explicitly clipped by the scissor
   gfx::RectF visible_rect;
   // Initialized to the visible_rect, relevant quad types should updated based
@@ -517,6 +527,7 @@
 };
 
 SkiaRenderer::DrawQuadParams::DrawQuadParams(const gfx::Transform& cdt,
+                                             const gfx::RectF& rect,
                                              const gfx::RectF& visible_rect,
                                              unsigned aa_flags,
                                              SkBlendMode blend_mode,
@@ -524,6 +535,7 @@
                                              SkFilterQuality filter_quality,
                                              const gfx::QuadF* draw_region)
     : content_device_transform(cdt),
+      rect(rect),
       visible_rect(visible_rect),
       vis_tex_coords(visible_rect),
       aa_flags(aa_flags),
@@ -1049,9 +1061,18 @@
   if (backdrop_bounds_type != gfx::RRectF::Type::kEmpty) {
     DCHECK(backdrop_filter);
 
-    gfx::Rect crop_rect =
-        gfx::ToEnclosingRect(rpdq_params.backdrop_filter_bounds->rect());
-    SkIRect sk_crop_rect = gfx::RectToSkIRect(crop_rect);
+    gfx::RectF crop_rect = rpdq_params.backdrop_filter_bounds->rect();
+
+    // Only sample from pixels behind the RPDQ for backdrop filters to avoid
+    // color bleeding with pixel-moving filters.
+    // TODO(crbug.com/1165868): Add web platform test to verify this clip is
+    // done correctly.
+    if (rpdq_params.bypass_geometry) {
+      crop_rect.Intersect(rpdq_params.bypass_geometry->rect);
+    } else {
+      crop_rect.Intersect(params->rect);
+    }
+    SkIRect sk_crop_rect = gfx::RectToSkIRect(gfx::ToEnclosingRect(crop_rect));
 
     SkIRect sk_src_rect = backdrop_filter->filterBounds(
         sk_crop_rect, SkMatrix::I(), SkImageFilter::kReverse_MapDirection,
@@ -1076,13 +1097,13 @@
       // completely match bounds)
       post_backdrop_filter_clear_needed |=
           backdrop_bounds_type != gfx::RRectF::Type::kRect ||
-          gfx::RectF(crop_rect) != rpdq_params.backdrop_filter_bounds->rect();
+          crop_rect != rpdq_params.backdrop_filter_bounds->rect();
     }
   }
 
-  SkRect bounds = gfx::RectFToSkRect(rpdq_params.bypass_clip.has_value()
-                                         ? *rpdq_params.bypass_clip
-                                         : params->visible_rect);
+  SkRect bounds = gfx::RectFToSkRect(
+      rpdq_params.bypass_geometry ? rpdq_params.bypass_geometry->visible_rect
+                                  : params->visible_rect);
   current_canvas_->saveLayer(
       SkCanvas::SaveLayerRec(&bounds, &layer_paint, backdrop_filter.get(), 0));
 
@@ -1098,8 +1119,8 @@
     if (params->draw_region.has_value()) {
       SkPath clipPath;
       clipPath.addPoly(params->draw_region->points, 4, true /* close */);
-      if (rpdq_params.bypass_transform.has_value()) {
-        clipPath.transform(*rpdq_params.bypass_transform);
+      if (rpdq_params.bypass_geometry) {
+        clipPath.transform(rpdq_params.bypass_geometry->transform);
       }
       current_canvas_->clipPath(clipPath, SkClipOp::kDifference, aa);
     }
@@ -1168,8 +1189,9 @@
 
   // Whether or not we saved a layer, clip the bypassed RenderPass's content
   if (needs_bypass_clip) {
-    current_canvas_->clipRect(gfx::RectFToSkRect(*rpdq_params.bypass_clip),
-                              params->aa_flags != SkCanvas::kNone_QuadAAFlags);
+    current_canvas_->clipRect(
+        gfx::RectFToSkRect(rpdq_params.bypass_geometry->visible_rect),
+        params->aa_flags != SkCanvas::kNone_QuadAAFlags);
   }
 }
 
@@ -1198,8 +1220,9 @@
   // directly (so no explicit save layer), the draw may need to be clipped to
   // the output rect of the renderpass it is bypassing.
   if (rpdq_params.needs_bypass_clip(params->visible_rect)) {
-    current_canvas_->clipRect(gfx::RectFToSkRect(*rpdq_params.bypass_clip),
-                              params->aa_flags != SkCanvas::kNone_QuadAAFlags);
+    current_canvas_->clipRect(
+        gfx::RectFToSkRect(rpdq_params.bypass_geometry->visible_rect),
+        params->aa_flags != SkCanvas::kNone_QuadAAFlags);
   }
 }
 
@@ -1210,9 +1233,9 @@
     const gfx::QuadF* draw_region) const {
   DrawQuadParams params(
       target_to_device * quad->shared_quad_state->quad_to_target_transform,
-      gfx::RectF(quad->visible_rect), SkCanvas::kNone_QuadAAFlags,
-      quad->shared_quad_state->blend_mode, quad->shared_quad_state->opacity,
-      GetFilterQuality(quad), draw_region);
+      gfx::RectF(quad->rect), gfx::RectF(quad->visible_rect),
+      SkCanvas::kNone_QuadAAFlags, quad->shared_quad_state->blend_mode,
+      quad->shared_quad_state->opacity, GetFilterQuality(quad), draw_region);
 
   params.content_device_transform.FlattenTo2d();
 
@@ -1436,13 +1459,14 @@
       gfx::Transform() /* identity */, nullptr, bypass_quad, nullptr);
 
   // |params| already holds the correct |draw_region|, but must be updated to
-  // use the bypassed transform and geometry
-  rpdq_params->bypass_transform = bypass_to_rpdq;
-  rpdq_params->bypass_clip = params->visible_rect;
+  // use the bypassed transform and geometry.
+  rpdq_params->bypass_geometry = DrawRPDQParams::BypassGeometry{
+      bypass_to_rpdq, params->rect, params->visible_rect};
+
   // NOTE: params |content_device_transform| remains that of the RPDQ to prepare
   // the canvas' CTM to match what any image filters require. The above
-  // bypass_transform is then applied when drawing so that these updated
-  // coordinates are correctly transformed to device space.
+  // BypassGeometry::transform is then applied when drawing so that these
+  // updated coordinates are correctly transformed to device space.
   params->visible_rect = bypass_params.visible_rect;
   params->vis_tex_coords = bypass_params.vis_tex_coords;
 
@@ -1631,10 +1655,10 @@
     // This will modify the provided content color as needed for the RP effects,
     // or it will make an explicit save layer on the current canvas
     PrepareColorOrCanvasForRPDQ(*rpdq_params, params, &color);
-    if (rpdq_params->bypass_transform.has_value()) {
+    if (rpdq_params->bypass_geometry) {
       // Concatenate the bypass'ed quad's transform after all the RPDQ state
       // has been pushed to the canvas.
-      current_canvas_->concat(*rpdq_params->bypass_transform);
+      current_canvas_->concat(rpdq_params->bypass_geometry->transform);
     }
   }
 
@@ -1672,14 +1696,14 @@
     // This will modify the provided content paint as needed for the RP effects,
     // or it will make an explicit save layer on the current canvas
     PreparePaintOrCanvasForRPDQ(*rpdq_params, params, paint);
-    if (rpdq_params->bypass_transform.has_value()) {
+    if (rpdq_params->bypass_geometry) {
       // Incorporate the bypass transform, but unlike for solid color quads, do
       // not modify the SkCanvas's CTM. This is because the RPDQ's filters may
       // have been optimally placed on the SkPaint of the draw, which means the
       // canvas' transform must match that of the RenderPass. The pre-CTM matrix
       // of the image set entry can be used instead to modify the drawn geometry
       // without impacting the filter's coordinate space.
-      bypass_transform = &(*rpdq_params->bypass_transform);
+      bypass_transform = &rpdq_params->bypass_geometry->transform;
       matrix_index = 0;
     }
   }
@@ -2753,7 +2777,6 @@
     color_space = backing->color_space;
   }
 
-
   // Adjust the overlay |buffer_size| to reduce memory fragmentation. It also
   // increases buffer reusing possibilities.
   constexpr int kBufferMultiple = 64;
diff --git a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
index da3445e..8112abf 100644
--- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
+++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
@@ -161,8 +161,7 @@
       std::move(synthetic_begin_frame_source),
       std::move(external_begin_frame_source), std::move(display),
       params->use_preferred_interval_for_video,
-      hw_support_for_multiple_refresh_rates,
-      params->num_of_frames_to_toggle_interval));
+      hw_support_for_multiple_refresh_rates));
 
 #if !defined(OS_APPLE)
   // On Mac vsync parameter updates come from the browser process. We don't need
@@ -397,8 +396,7 @@
     std::unique_ptr<ExternalBeginFrameSource> external_begin_frame_source,
     std::unique_ptr<Display> display,
     bool use_preferred_interval_for_video,
-    bool hw_support_for_multiple_refresh_rates,
-    size_t num_of_frames_to_toggle_interval)
+    bool hw_support_for_multiple_refresh_rates)
     : compositor_frame_sink_client_(std::move(frame_sink_client)),
       compositor_frame_sink_receiver_(this, std::move(frame_sink_receiver)),
       display_client_(std::move(display_client)),
@@ -417,8 +415,7 @@
                                                support_->frame_sink_id());
   display_->Initialize(this, support_->frame_sink_manager()->surface_manager(),
                        Display::kEnableSharedImages,
-                       hw_support_for_multiple_refresh_rates,
-                       num_of_frames_to_toggle_interval);
+                       hw_support_for_multiple_refresh_rates);
   support_->SetUpHitTest(display_.get());
   if (use_preferred_interval_for_video &&
       !hw_support_for_multiple_refresh_rates) {
diff --git a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h
index 7a78da37..6fb1bd7 100644
--- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h
+++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h
@@ -113,8 +113,7 @@
       std::unique_ptr<ExternalBeginFrameSource> external_begin_frame_source,
       std::unique_ptr<Display> display,
       bool use_preferred_interval_for_video,
-      bool hw_support_for_multiple_refresh_rates,
-      size_t num_of_frames_to_toggle_interval);
+      bool hw_support_for_multiple_refresh_rates);
 
   // DisplayClient:
   void DisplayOutputSurfaceLost() override;
diff --git a/content/browser/compositor/viz_process_transport_factory.cc b/content/browser/compositor/viz_process_transport_factory.cc
index d22a77a..11ac164 100644
--- a/content/browser/compositor/viz_process_transport_factory.cc
+++ b/content/browser/compositor/viz_process_transport_factory.cc
@@ -438,8 +438,6 @@
 
   root_params->use_preferred_interval_for_video =
       features::IsUsingPreferredIntervalForVideo();
-  root_params->num_of_frames_to_toggle_interval =
-      features::NumOfFramesToToggleInterval();
 #if defined(OS_WIN)
   root_params->set_present_duration_allowed =
       features::ShouldUseSetPresentDuration();
diff --git a/content/browser/conversions/conversion_policy.cc b/content/browser/conversions/conversion_policy.cc
index 59aecba..4df9ed7 100644
--- a/content/browser/conversions/conversion_policy.cc
+++ b/content/browser/conversions/conversion_policy.cc
@@ -7,7 +7,7 @@
 #include "base/format_macros.h"
 #include "base/memory/ptr_util.h"
 #include "base/rand_util.h"
-#include "base/strings/string_number_conversions.h"
+#include "base/strings/stringprintf.h"
 #include "base/time/time.h"
 
 namespace content {
@@ -59,14 +59,18 @@
   if (noise_provider_)
     conversion_data = noise_provider_->GetNoisedConversionData(conversion_data);
 
-  // Allow at most 3 bits of entropy in conversion data.
-  return base::NumberToString(conversion_data % kMaxAllowedConversionValues);
+  // Allow at most 3 bits of entropy in conversion data. base::StringPrintf() is
+  // used over base::HexEncode() because HexEncode() returns a hex string with
+  // little-endian ordering. Big-endian ordering is expected here because the
+  // API assumes big-endian when parsing attributes.
+  return base::StringPrintf("%" PRIx64,
+                            conversion_data % kMaxAllowedConversionValues);
 }
 
 std::string ConversionPolicy::GetSanitizedImpressionData(
     uint64_t impression_data) const {
   // Impression data is allowed the full 64 bits.
-  return base::NumberToString(impression_data);
+  return base::StringPrintf("%" PRIx64, impression_data);
 }
 
 base::Time ConversionPolicy::GetExpiryTimeForImpression(
diff --git a/content/browser/conversions/conversion_policy.h b/content/browser/conversions/conversion_policy.h
index c7c2f62..79f86a7 100644
--- a/content/browser/conversions/conversion_policy.h
+++ b/content/browser/conversions/conversion_policy.h
@@ -49,7 +49,7 @@
       uint64_t conversion_data) const;
 
   // Gets the sanitized impression data for an impression. Returns the decoded
-  // number as a base 10 string.
+  // number as a hexadecimal string.
   virtual std::string GetSanitizedImpressionData(
       uint64_t impression_data) const;
 
diff --git a/content/browser/conversions/conversion_policy_unittest.cc b/content/browser/conversions/conversion_policy_unittest.cc
index 27625ff..15ff3505 100644
--- a/content/browser/conversions/conversion_policy_unittest.cc
+++ b/content/browser/conversions/conversion_policy_unittest.cc
@@ -51,9 +51,9 @@
 TEST_F(ConversionPolicyTest, SanitizeHighEntropyImpressionData_Unchanged) {
   uint64_t impression_data = 256LU;
 
-  // The policy should not alter the impression data, and return the base 10
+  // The policy should not alter the impression data, and return the hexadecimal
   // representation.
-  EXPECT_EQ("256",
+  EXPECT_EQ("100",
             ConversionPolicy().GetSanitizedImpressionData(impression_data));
 }
 
diff --git a/content/browser/conversions/conversion_storage_sql.cc b/content/browser/conversions/conversion_storage_sql.cc
index 985a55d..cfae07d 100644
--- a/content/browser/conversions/conversion_storage_sql.cc
+++ b/content/browser/conversions/conversion_storage_sql.cc
@@ -685,9 +685,6 @@
 
 bool ConversionStorageSql::InitializeSchema() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  // TODO(https://crbug.com/1163599): Convert impression data and conversion
-  // data fields to integers.
-  //
   // TODO(johnidel, csharrison): Many impressions will share a target origin and
   // a reporting origin, so it makes sense to make a "shared string" table for
   // these to save disk / memory. However, this complicates the schema a lot, so
diff --git a/content/browser/conversions/impression_declaration_browsertest.cc b/content/browser/conversions/impression_declaration_browsertest.cc
index 6d7c485..ca25e8f 100644
--- a/content/browser/conversions/impression_declaration_browsertest.cc
+++ b/content/browser/conversions/impression_declaration_browsertest.cc
@@ -245,12 +245,12 @@
       web_contents(),
       https_server()->GetURL("b.test", "/page_with_impression_creator.html")));
 
-  // The provided data underflows an unsigned 64 bit int, and should be handled
+  // The provided data overflows an unsigned 64 bit int, and should be handled
   // properly.
   EXPECT_TRUE(ExecJs(web_contents(), R"(
     createImpressionTag("link",
                         "page_with_conversion_redirect.html",
-                        "-1" /* impression data */,
+                        "FFFFFFFFFFFFFFFFFFFFFF" /* impression data */,
                         "https://a.com" /* conversion_destination */);)"));
   EXPECT_TRUE(ExecJs(shell(), "simulateClick(\'link\');"));
 
@@ -476,7 +476,7 @@
   content::UntrustworthyContextMenuParams params =
       context_menu_filter->get_params();
   EXPECT_TRUE(params.impression);
-  EXPECT_EQ(10UL, params.impression->impression_data);
+  EXPECT_EQ(16UL, params.impression->impression_data);
   EXPECT_EQ(url::Origin::Create(GURL("https://dest.com")),
             params.impression->conversion_destination);
 }
diff --git a/content/browser/cookie_store/cookie_store_manager.cc b/content/browser/cookie_store/cookie_store_manager.cc
index c7e21ac..ab5ec2a 100644
--- a/content/browser/cookie_store/cookie_store_manager.cc
+++ b/content/browser/cookie_store/cookie_store_manager.cc
@@ -18,6 +18,7 @@
 #include "content/browser/service_worker/service_worker_version.h"
 #include "content/public/browser/browser_context.h"
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "services/network/public/cpp/is_potentially_trustworthy.h"
 #include "third_party/blink/public/common/service_worker/service_worker_scope_match.h"
 #include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h"
@@ -49,6 +50,11 @@
     const url::Origin& origin) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
+  if (!network::IsOriginPotentiallyTrustworthy(origin)) {
+    mojo::ReportBadMessage("Cookie Store access from an insecure origin");
+    return;
+  }
+
   receivers_.Add(std::make_unique<CookieStoreHost>(this, origin),
                  std::move(receiver));
 }
diff --git a/content/browser/cookie_store/cookie_store_manager_unittest.cc b/content/browser/cookie_store/cookie_store_manager_unittest.cc
index d5c84f4..7e88f36 100644
--- a/content/browser/cookie_store/cookie_store_manager_unittest.cc
+++ b/content/browser/cookie_store/cookie_store_manager_unittest.cc
@@ -19,6 +19,7 @@
 #include "content/browser/storage_partition_impl.h"
 #include "content/public/test/browser_task_environment.h"
 #include "content/public/test/test_browser_context.h"
+#include "content/test/fake_mojo_message_dispatch_context.h"
 #include "mojo/public/cpp/test_support/test_utils.h"
 #include "net/base/features.h"
 #include "net/cookies/cookie_access_result.h"
@@ -1757,6 +1758,23 @@
   EXPECT_EQ("Invalid service worker", bad_mesage_observer.WaitForBadMessage());
 }
 
+TEST_F(CookieStoreManagerTest, UnTrustworthyOrigin) {
+  mojo::Remote<blink::mojom::CookieStore> untrustworthy_service_remote;
+
+  // Create a fake dispatch context to trigger a bad message in.
+  FakeMojoMessageDispatchContext fake_dispatch_context;
+  mojo::test::BadMessageObserver bad_mesage_observer;
+
+  cookie_store_context_->CreateServiceForTesting(
+      url::Origin::Create(GURL("http://insecure.com")),
+      untrustworthy_service_remote.BindNewPipeAndPassReceiver());
+
+  untrustworthy_service_remote.FlushForTesting();
+  EXPECT_FALSE(untrustworthy_service_remote.is_connected());
+  EXPECT_EQ("Cookie Store access from an insecure origin",
+            bad_mesage_observer.WaitForBadMessage());
+}
+
 INSTANTIATE_TEST_SUITE_P(All,
                          CookieStoreManagerTest,
                          testing::Bool() /* reset_context_during_test */);
diff --git a/content/browser/form_controls_browsertest.cc b/content/browser/form_controls_browsertest.cc
index 6b293446..609b954 100644
--- a/content/browser/form_controls_browsertest.cc
+++ b/content/browser/form_controls_browsertest.cc
@@ -101,7 +101,7 @@
     // - Slight differences in radio and checkbox rendering in 10.15
     cc::FuzzyPixelComparator comparator(
         /* discard_alpha */ true,
-        /* error_pixels_percentage_limit */ 11.f,
+        /* error_pixels_percentage_limit */ 9.f,
         /* small_error_pixels_percentage_limit */ 0.f,
         /* avg_abs_error_limit */ 20.f,
         /* max_abs_error_limit */ 79.f,
@@ -158,25 +158,6 @@
           /* screenshot_height */ 40);
 }
 
-IN_PROC_BROWSER_TEST_F(FormControlsBrowserTest, Input) {
-  RunTest("form_controls_browsertest_input",
-          "<!-- text inputs -->"
-          "<style>input {width: 150px;}</style>"
-          "<input type=\"text\" /><br><br>"
-          "<input type=\"number\" /><br><br>"
-          "<input type=\"search\" /><br><br>"
-          "<input type=\"email\" /><br><br>"
-          "<input type=\"password\" /><br><br>"
-          "<!-- border -->"
-          "<input type=\"text\" style=\"border: 3px solid lime;\"/><br><br>"
-          "<!-- shadow -->"
-          "<input type=\"text\" style=\"box-shadow: 4px 4px 10px rgba(255,0,0,0.5), inset 4px 4px 4px rgba(0,255,0,0.5);\"/><br><br>"
-          "<!-- disabled -->"
-          "<input type=\"text\" disabled/>",
-          /* screenshot_width */ 200,
-          /* screenshot_height */ 330);
-}
-
 // TODO(jarhar): Add tests for other elements from
 //   https://concrete-hardboard.glitch.me
 
diff --git a/content/browser/media/android/media_resource_getter_impl.cc b/content/browser/media/android/media_resource_getter_impl.cc
index 470d65b8..c7821a5 100644
--- a/content/browser/media/android/media_resource_getter_impl.cc
+++ b/content/browser/media/android/media_resource_getter_impl.cc
@@ -23,6 +23,7 @@
 #include "media/base/android/media_url_interceptor.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "net/base/auth.h"
+#include "net/base/isolation_info.h"
 #include "net/base/network_isolation_key.h"
 #include "net/http/http_auth.h"
 #include "services/network/public/mojom/network_context.mojom.h"
@@ -50,11 +51,22 @@
   StoragePartition* storage_partition =
       BrowserContext::GetDefaultStoragePartition(browser_context);
 
+  net::IsolationInfo isolation_info =
+      render_frame_host
+          ? render_frame_host->GetIsolationInfoForSubresources()
+          : net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther,
+                                       top_frame_origin, origin,
+                                       site_for_cookies, base::nullopt);
+  DCHECK_EQ(origin, isolation_info.frame_origin().value());
+  DCHECK_EQ(top_frame_origin, isolation_info.top_frame_origin().value());
+  // TODO(https://crbug.com/911299): Check `site_for_cookies` and
+  // `isolation_info.site_for_cookies` are equivalent.
+
   mojo::PendingRemote<network::mojom::RestrictedCookieManager> pipe;
   static_cast<StoragePartitionImpl*>(storage_partition)
       ->CreateRestrictedCookieManager(
-          network::mojom::RestrictedCookieManagerRole::NETWORK, origin,
-          site_for_cookies, top_frame_origin,
+          network::mojom::RestrictedCookieManagerRole::NETWORK,
+          std::move(isolation_info),
           /* is_service_worker = */ false,
           render_frame_host ? render_frame_host->GetProcess()->GetID() : -1,
           render_frame_host ? render_frame_host->GetRoutingID()
diff --git a/content/browser/net/trust_token_browsertest.cc b/content/browser/net/trust_token_browsertest.cc
index 76fc82b7..d249e1c 100644
--- a/content/browser/net/trust_token_browsertest.cc
+++ b/content/browser/net/trust_token_browsertest.cc
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/base64.h"
+#include "base/strings/strcat.h"
 #include "base/strings/string_piece.h"
 #include "base/test/bind.h"
 #include "base/test/scoped_feature_list.h"
@@ -1698,6 +1699,8 @@
 
 IN_PROC_BROWSER_TEST_F(TrustTokenBrowsertestWithPlatformIssuance,
                        EndToEndAndroidPlatformIssuance) {
+  base::HistogramTester histograms;
+
   TrustTokenRequestHandler::Options options;
   options.specify_platform_issuance_on = {
       network::mojom::TrustTokenKeyCommitmentResult::Os::kAndroid};
@@ -1732,10 +1735,18 @@
   EXPECT_EQ(
       "Success",
       EvalJs(shell(), JsReplace(command, IssuanceOriginFromHost("a.test"))));
+
+  content::FetchHistogramsFromChildProcesses();
+  histograms.ExpectTotalCount(
+      base::StrCat({"Net.TrustTokens.OperationBeginTime.Success.Issuance."
+                    "PlatformProvided"}),
+      1);
 }
 
 IN_PROC_BROWSER_TEST_F(TrustTokenBrowsertestWithPlatformIssuance,
                        PlatformIssuanceWithoutEmbedderSupport) {
+  base::HistogramTester histograms;
+
   TrustTokenRequestHandler::Options options;
   options.specify_platform_issuance_on = {
       network::mojom::TrustTokenKeyCommitmentResult::Os::kAndroid};
@@ -1776,6 +1787,12 @@
   // We use EvalJs here, not ExecJs, because EvalJs waits for promises to
   // resolve.
   EXPECT_EQ("OperationError", EvalJs(shell(), command));
+
+  content::FetchHistogramsFromChildProcesses();
+  histograms.ExpectTotalCount(
+      base::StrCat({"Net.TrustTokens.OperationBeginTime.Failure.Issuance."
+                    "PlatformProvided"}),
+      1);
 }
 #endif  // defined(OS_ANDROID)
 #if !defined(OS_ANDROID)
@@ -1822,6 +1839,8 @@
 IN_PROC_BROWSER_TEST_F(
     TrustTokenBrowsertestWithPlatformIssuance,
     IssuanceOnOsNotSpecifiedInKeyCommitmentsFallsBackToWebIssuanceIfSpecified) {
+  base::HistogramTester histograms;
+
   TrustTokenRequestHandler::Options options;
   options.specify_platform_issuance_on = {
       network::mojom::TrustTokenKeyCommitmentResult::Os::kAndroid};
@@ -1860,6 +1879,12 @@
   EXPECT_EQ(
       "Success",
       EvalJs(shell(), JsReplace(command, IssuanceOriginFromHost("a.test"))));
+
+  content::FetchHistogramsFromChildProcesses();
+  histograms.ExpectTotalCount(
+      base::StrCat({"Net.TrustTokens.OperationBeginTime.Failure.Issuance."
+                    "PlatformProvided"}),
+      0);  // No platform-provided operation was attempted.
 }
 #endif  // !defined(OS_ANDROID)
 
diff --git a/content/browser/renderer_host/cookie_browsertest.cc b/content/browser/renderer_host/cookie_browsertest.cc
index 3f80eb0..8520c7f 100644
--- a/content/browser/renderer_host/cookie_browsertest.cc
+++ b/content/browser/renderer_host/cookie_browsertest.cc
@@ -334,9 +334,7 @@
   bool WillCreateRestrictedCookieManager(
       network::mojom::RestrictedCookieManagerRole role,
       content::BrowserContext* browser_context,
-      const url::Origin& origin,
-      const net::SiteForCookies& site_for_cookies,
-      const url::Origin& top_frame_origin,
+      const net::IsolationInfo& isolation_info,
       bool is_service_worker,
       int process_id,
       int routing_id,
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 8227ea9..4b68268 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -147,7 +147,6 @@
 #include "content/common/render_message_filter.mojom.h"
 #include "content/common/renderer.mojom.h"
 #include "content/common/state_transitions.h"
-#include "content/common/unfreezable_frame_messages.h"
 #include "content/public/browser/ax_event_notification_details.h"
 #include "content/public/browser/browser_accessibility_state.h"
 #include "content/public/browser/browser_context.h"
@@ -1247,9 +1246,9 @@
   //    flight.
   // 3. The RenderFrame can be detached, as part of removing a subtree (due to
   //    navigation, unload, or DOM mutation). In this case, the browser sends
-  //    a UnfreezableFrameMsg_Delete for the RenderFrame to detach itself and
-  //    release its associated resources. If the subframe contains an unload
-  //    handler, |lifecycle_state_| is advanced to
+  //    a mojom::FrameNavigationControl::Delete message for the RenderFrame
+  //    to detach itself and release its associated resources. If the subframe
+  //    contains an unload handler, |lifecycle_state_| is advanced to
   //    LifeCycleState::kRunningUnloadHandlers to track that the detach is in
   //    progress; otherwise, it is advanced directly to
   //    LifeCycleState::kReadyToBeDeleted.
@@ -1277,9 +1276,9 @@
   //
   // TODO(dcheng): Due to how frame detach is signalled today, there are some
   // bugs in this area. In particular, subtree detach is reported from the
-  // bottom up, so the replicated UnfreezableFrameMsg_Delete messages actually
-  // operate on a node-by-node basis rather than detaching an entire subtree at
-  // once...
+  // bottom up, so the replicated mojom::FrameNavigationControl::Delete
+  // messages actually operate on a node-by-node basis rather than detaching an
+  // entire subtree at once...
   //
   // Note that this logic is fairly subtle. It needs to include all subframes
   // and all speculative frames, but it should exclude case #1 (a main
@@ -2440,7 +2439,8 @@
   return true;
 }
 
-void RenderFrameHostImpl::DeleteRenderFrame(FrameDeleteIntention intent) {
+void RenderFrameHostImpl::DeleteRenderFrame(
+    mojom::FrameDeleteIntention intent) {
   if (IsPendingDeletion())
     return;
 
@@ -2450,7 +2450,7 @@
       has_unload_handlers() && !IsInBackForwardCache();
 
   if (is_render_frame_created()) {
-    Send(new UnfreezableFrameMsg_Delete(routing_id_, intent));
+    GetNavigationControl()->Delete(intent);
 
     if (!frame_tree_node_->IsMainFrame() && IsCurrent()) {
       DCHECK_NE(lifecycle_state(), LifecycleState::kSpeculative);
@@ -2750,6 +2750,14 @@
   frame_tree_node_->SetCurrentURL(params.url);
   SetLastCommittedOrigin(params.origin);
 
+  // TODO(https://crbug.com/1164508): Remove this check once origin is computed
+  // correctly by the browser side.
+  if (!GetLastCommittedOrigin().IsSameOriginWith(
+          GetIsolationInfoForSubresources().frame_origin().value())) {
+    isolation_info_ = ComputeIsolationInfoInternal(
+        GetLastCommittedOrigin(), isolation_info_.request_type());
+  }
+
   // Separately, update the frame's last successful URL except for net error
   // pages, since those do not end up in the correct process after transfers
   // (see https://crbug.com/560511).  Instead, the next cross-process navigation
@@ -2986,10 +2994,10 @@
       std::unique_ptr<FrameTreeNode> node_to_delete(std::move(*iter));
       children_.erase(iter);
       node_to_delete->current_frame_host()->DeleteRenderFrame(
-          FrameDeleteIntention::kNotMainFrame);
+          mojom::FrameDeleteIntention::kNotMainFrame);
       // Speculative RenderFrameHosts are deleted by the FrameTreeNode's
-      // RenderFrameHostManager's destructor. RenderFrameProxyHosts send
-      // UnfreezableFrameMsg_Delete automatically in the destructor.
+      // RenderFrameHostManager's destructor. RenderFrameProxyHosts disconnect
+      // the mojo channel automatically in the destructor.
       // TODO(dcheng): This is horribly confusing. Refactor this logic so it's
       // more understandable.
       node_to_delete.reset();
@@ -3010,7 +3018,7 @@
   // than messaging each child's current frame host...
   for (auto& child : children)
     child->current_frame_host()->DeleteRenderFrame(
-        FrameDeleteIntention::kNotMainFrame);
+        mojom::FrameDeleteIntention::kNotMainFrame);
 }
 
 void RenderFrameHostImpl::SetLastCommittedUrl(const GURL& url) {
@@ -3339,7 +3347,8 @@
 
     // The unload handlers already ran for this document during the
     // local<->local swap. Hence, there is no need to send
-    // mojo::FrameNavigationControl::Unload here. It can be marked at completed.
+    // mojom::FrameNavigationControl::Unload here. It can be marked at
+    // completed.
     SetLifecycleState(LifecycleState::kReadyToBeDeleted);
   }
 
@@ -3366,7 +3375,7 @@
     return;
 
   // Start pending deletion on this frame and its children.
-  DeleteRenderFrame(FrameDeleteIntention::kNotMainFrame);
+  DeleteRenderFrame(mojom::FrameDeleteIntention::kNotMainFrame);
   StartPendingDeletionOnSubtree();
   frame_tree()->FrameUnloading(frame_tree_node_);
 
@@ -6130,7 +6139,8 @@
           local_ancestor = rfh;
       }
 
-      local_ancestor->DeleteRenderFrame(FrameDeleteIntention::kNotMainFrame);
+      local_ancestor->DeleteRenderFrame(
+          mojom::FrameDeleteIntention::kNotMainFrame);
       if (local_ancestor != child) {
         // In case of BackForwardCache, page is evicted directly from the cache
         // and deleted immediately, without waiting for unload handlers.
@@ -8056,8 +8066,7 @@
   static_cast<StoragePartitionImpl*>(GetProcess()->GetStoragePartition())
       ->CreateRestrictedCookieManager(
           network::mojom::RestrictedCookieManagerRole::SCRIPT,
-          GetLastCommittedOrigin(), isolation_info_.site_for_cookies(),
-          ComputeTopFrameOrigin(GetLastCommittedOrigin()),
+          GetIsolationInfoForSubresources(),
           /* is_service_worker = */ false, GetProcess()->GetID(), routing_id(),
           std::move(receiver), CreateCookieAccessObserver());
 }
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h
index 3640a44..ad68264 100644
--- a/content/browser/renderer_host/render_frame_host_impl.h
+++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -53,7 +53,6 @@
 #include "content/common/content_navigation_policy.h"
 #include "content/common/dom_automation_controller.mojom.h"
 #include "content/common/frame.mojom.h"
-#include "content/common/frame_delete_intention.h"
 #include "content/common/frame_replication_state.h"
 #include "content/common/input/input_injector.mojom-forward.h"
 #include "content/common/navigation_client.mojom-forward.h"
@@ -497,7 +496,7 @@
 
   // Deletes the RenderFrame in the renderer process.
   // Postcondition: |IsPendingDeletion()| is true.
-  void DeleteRenderFrame(FrameDeleteIntention intent);
+  void DeleteRenderFrame(mojom::FrameDeleteIntention intent);
 
   // Track whether the RenderFrame for this RenderFrameHost has been created in
   // or destroyed in the renderer process.
@@ -2053,6 +2052,7 @@
                            AttemptDuplicateRenderWidgetHost);
   FRIEND_TEST_ALL_PREFIXES(RenderDocumentHostUserDataTest,
                            CheckInPendingDeletionState);
+  FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest, FrozenAndUnfrozenIPC);
 
   class DroppedInterfaceRequestLogger;
 
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc
index 1e74340..c1bf1f9 100644
--- a/content/browser/renderer_host/render_frame_host_manager.cc
+++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -1005,8 +1005,9 @@
   speculative_render_frame_host_->GetProcess()->RemovePendingView();
   speculative_render_frame_host_->DeleteRenderFrame(
       frame_tree_node_->parent()
-          ? FrameDeleteIntention::kNotMainFrame
-          : FrameDeleteIntention::kSpeculativeMainFrameForNavigationCancelled);
+          ? mojom::FrameDeleteIntention::kNotMainFrame
+          : mojom::FrameDeleteIntention::
+                kSpeculativeMainFrameForNavigationCancelled);
   return std::move(speculative_render_frame_host_);
 }
 
diff --git a/content/browser/renderer_host/render_frame_proxy_host.cc b/content/browser/renderer_host/render_frame_proxy_host.cc
index 49546be..24cc67b 100644
--- a/content/browser/renderer_host/render_frame_proxy_host.cc
+++ b/content/browser/renderer_host/render_frame_proxy_host.cc
@@ -9,8 +9,10 @@
 #include <vector>
 
 #include "base/callback.h"
+#include "base/containers/circular_deque.h"
 #include "base/hash/hash.h"
 #include "base/lazy_instance.h"
+#include "base/no_destructor.h"
 #include "content/browser/bad_message.h"
 #include "content/browser/blob_storage/chrome_blob_storage_context.h"
 #include "content/browser/child_process_security_policy_impl.h"
@@ -27,7 +29,6 @@
 #include "content/browser/scoped_active_url.h"
 #include "content/browser/site_instance_impl.h"
 #include "content/common/frame_messages.h"
-#include "content/common/unfreezable_frame_messages.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_features.h"
@@ -72,6 +73,35 @@
 base::LazyInstance<TokenFrameMap>::Leaky g_token_frame_proxy_map =
     LAZY_INSTANCE_INITIALIZER;
 
+// Maintains a list of the most recently recorded (source, target) pairs for the
+// PostMessage.Incoming.Page UKM event, in order to partially deduplicate
+// logged events. Its size is limited to 20. See RouteMessageEvent() where
+// this UKM is logged.
+// TODO(crbug.com/1112491): Remove when no longer needed.
+bool ShouldRecordPostMessageIncomingPageUkmEvent(
+    ukm::SourceId source_page_ukm_source_id,
+    ukm::SourceId target_page_ukm_source_id) {
+  constexpr size_t kMaxPostMessageUkmAlreadyRecordedPairsSize = 20;
+  static base::NoDestructor<
+      base::circular_deque<std::pair<ukm::SourceId, ukm::SourceId>>>
+      s_post_message_ukm_already_recorded_pairs;
+
+  DCHECK_LE(s_post_message_ukm_already_recorded_pairs->size(),
+            kMaxPostMessageUkmAlreadyRecordedPairsSize);
+  std::pair<ukm::SourceId, ukm::SourceId> new_pair =
+      std::make_pair(source_page_ukm_source_id, target_page_ukm_source_id);
+
+  if (base::Contains(*s_post_message_ukm_already_recorded_pairs, new_pair))
+    return false;
+
+  if (s_post_message_ukm_already_recorded_pairs->size() ==
+      kMaxPostMessageUkmAlreadyRecordedPairsSize) {
+    s_post_message_ukm_already_recorded_pairs->pop_back();
+  }
+  s_post_message_ukm_already_recorded_pairs->push_front(new_pair);
+  return true;
+}
+
 }  // namespace
 
 // static
@@ -596,11 +626,15 @@
   }
 
   // Record UKM metrics for the postMessage event.
-  ukm::builders::PostMessage_Incoming_Page ukm_builder(
-      target_rfh->GetPageUkmSourceId());
-  if (source_page_ukm_source_id != ukm::kInvalidSourceId)
-    ukm_builder.SetSourcePageSourceId(source_page_ukm_source_id);
-  ukm_builder.Record(ukm::UkmRecorder::Get());
+  ukm::SourceId target_page_ukm_source_id = target_rfh->GetPageUkmSourceId();
+  if (ShouldRecordPostMessageIncomingPageUkmEvent(source_page_ukm_source_id,
+                                                  target_page_ukm_source_id)) {
+    ukm::builders::PostMessage_Incoming_Page ukm_builder(
+        target_page_ukm_source_id);
+    if (source_page_ukm_source_id != ukm::kInvalidSourceId)
+      ukm_builder.SetSourcePageSourceId(source_page_ukm_source_id);
+    ukm_builder.Record(ukm::UkmRecorder::Get());
+  }
 
   target_rfh->PostMessageEvent(translated_source_token, source_origin,
                                target_origin, std::move(message));
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 85aaafea..69c62ce 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -2029,8 +2029,8 @@
   StoragePartitionImpl* storage_partition =
       static_cast<StoragePartitionImpl*>(GetStoragePartition());
   storage_partition->CreateRestrictedCookieManager(
-      network::mojom::RestrictedCookieManagerRole::SCRIPT, origin,
-      net::SiteForCookies::FromOrigin(origin), origin,
+      network::mojom::RestrictedCookieManagerRole::SCRIPT,
+      net::IsolationInfo::ToDoUseTopFrameOriginAsWell(origin),
       true /* is_service_worker */, GetID(), MSG_ROUTING_NONE,
       std::move(receiver),
       storage_partition->CreateCookieAccessObserverForServiceWorker());
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
index a23458b..f0d0726 100644
--- a/content/browser/storage_partition_impl.cc
+++ b/content/browser/storage_partition_impl.cc
@@ -1404,9 +1404,7 @@
 
 void StoragePartitionImpl::CreateRestrictedCookieManager(
     network::mojom::RestrictedCookieManagerRole role,
-    const url::Origin& origin,
-    const net::SiteForCookies& site_for_cookies,
-    const url::Origin& top_frame_origin,
+    const net::IsolationInfo& isolation_info,
     bool is_service_worker,
     int process_id,
     int routing_id,
@@ -1414,11 +1412,10 @@
     mojo::PendingRemote<network::mojom::CookieAccessObserver> cookie_observer) {
   DCHECK(initialized_);
   if (!GetContentClient()->browser()->WillCreateRestrictedCookieManager(
-          role, browser_context_, origin, site_for_cookies, top_frame_origin,
-          is_service_worker, process_id, routing_id, &receiver)) {
+          role, browser_context_, isolation_info, is_service_worker, process_id,
+          routing_id, &receiver)) {
     GetNetworkContext()->GetRestrictedCookieManager(
-        std::move(receiver), role, origin, site_for_cookies, top_frame_origin,
-        std::move(cookie_observer));
+        std::move(receiver), role, isolation_info, std::move(cookie_observer));
   }
 }
 
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h
index c6abbb1..35fde8f4 100644
--- a/content/browser/storage_partition_impl.h
+++ b/content/browser/storage_partition_impl.h
@@ -69,6 +69,10 @@
 class ProtoDatabaseProvider;
 }
 
+namespace net {
+class IsolationInfo;
+}
+
 namespace content {
 
 class BackgroundFetchContext;
@@ -342,9 +346,7 @@
   // makes some decision based on that.
   void CreateRestrictedCookieManager(
       network::mojom::RestrictedCookieManagerRole role,
-      const url::Origin& origin,
-      const net::SiteForCookies& site_for_cookies,
-      const url::Origin& top_frame_origin,
+      const net::IsolationInfo& isolation_info,
       bool is_service_worker,
       int process_id,
       int routing_id,
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 7b357722..0515258 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -944,7 +944,7 @@
   frame_tree_.root()->ResetNavigationRequest(true);
   if (root->speculative_frame_host()) {
     root->speculative_frame_host()->DeleteRenderFrame(
-        FrameDeleteIntention::kSpeculativeMainFrameForShutdown);
+        mojom::FrameDeleteIntention::kSpeculativeMainFrameForShutdown);
     root->speculative_frame_host()->RenderFrameDeleted();
     root->speculative_frame_host()->ResetNavigationRequests();
   }
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index 6ab89de..5ce270d 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -38,7 +38,6 @@
 #include "content/common/frame.mojom-test-utils.h"
 #include "content/common/frame.mojom.h"
 #include "content/common/frame_messages.h"
-#include "content/common/unfreezable_frame_messages.h"
 #include "content/public/browser/back_forward_cache.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/file_select_listener.h"
@@ -3201,8 +3200,8 @@
   RenderFrameDeletedObserver delete_rfh_c(rfh_c);
 
   // Delete an iframe when the page is active(not frozen), which should succeed.
-  rfh_b->Send(new UnfreezableFrameMsg_Delete(
-      rfh_b->routing_id(), FrameDeleteIntention::kNotMainFrame));
+  rfh_b->GetNavigationControl()->Delete(
+      mojom::FrameDeleteIntention::kNotMainFrame);
   delete_rfh_b.WaitUntilDeleted();
   EXPECT_TRUE(delete_rfh_b.deleted());
   EXPECT_FALSE(delete_rfh_c.deleted());
@@ -3212,8 +3211,8 @@
   shell()->web_contents()->SetPageFrozen(true);
 
   // Try to delete an iframe, and succeeds because the message is unfreezable.
-  rfh_c->Send(new UnfreezableFrameMsg_Delete(
-      rfh_c->routing_id(), FrameDeleteIntention::kNotMainFrame));
+  rfh_c->GetNavigationControl()->Delete(
+      mojom::FrameDeleteIntention::kNotMainFrame);
   delete_rfh_c.WaitUntilDeleted();
   EXPECT_TRUE(delete_rfh_c.deleted());
 }
@@ -3748,27 +3747,18 @@
   // While there is a speculative RenderFrameHost in the root FrameTreeNode...
   ASSERT_TRUE(root->render_manager()->speculative_frame_host());
 
-  auto* frame_process = static_cast<RenderProcessHostImpl*>(
-      root->render_manager()->speculative_frame_host()->GetProcess());
-  int frame_routing_id =
-      root->render_manager()->speculative_frame_host()->GetRoutingID();
-
-  std::vector<int> deleted_routing_ids;
-  auto watcher = base::BindRepeating(
-      [](std::vector<int>* deleted_routing_ids, const IPC::Message& message) {
-        if (message.type() == UnfreezableFrameMsg_Delete::ID) {
-          deleted_routing_ids->push_back(message.routing_id());
-        }
-      },
-      &deleted_routing_ids);
-  frame_process->SetIpcSendWatcherForTesting(watcher);
+  // Add an observer to ensure that the speculative RenderFrameHost gets
+  // deleted.
+  RenderFrameDeletedObserver frame_deletion_observer(
+      root->render_manager()->speculative_frame_host());
 
   // ...shutdown the WebContents.
   public_web_contents.reset();
 
   // What should have happened is the speculative RenderFrameHost deletes the
-  // provisional RenderFrame. The |watcher| verifies that this happened.
-  EXPECT_THAT(deleted_routing_ids, testing::Contains(frame_routing_id));
+  // provisional RenderFrame. The |frame_deletion_observer| verifies that this
+  // happened.
+  EXPECT_TRUE(frame_deletion_observer.deleted());
 }
 
 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, MouseButtonsNavigate) {
diff --git a/content/browser/webid/federated_auth_request_impl.cc b/content/browser/webid/federated_auth_request_impl.cc
index 7366e180..fe24889 100644
--- a/content/browser/webid/federated_auth_request_impl.cc
+++ b/content/browser/webid/federated_auth_request_impl.cc
@@ -129,8 +129,7 @@
   }
 
   idp_endpoint_url_ = GURL(base::StringPiece(idp_endpoint));
-  // TODO(kenrb): Do we have to check that this URL is same-origin with the
-  // provider, or is that not a requirement?
+  // TODO(kenrb): This has to be same-origin with the provider.
   // https://crbug.com/1141125
   if (!IdpUrlIsValid(idp_endpoint_url_)) {
     CompleteRequest(RequestIdTokenStatus::kError, "");
diff --git a/content/browser/webid/idp_network_request_manager.cc b/content/browser/webid/idp_network_request_manager.cc
index 5f0d5cc..4f4ce2dc 100644
--- a/content/browser/webid/idp_network_request_manager.cc
+++ b/content/browser/webid/idp_network_request_manager.cc
@@ -5,7 +5,6 @@
 #include "content/browser/webid/idp_network_request_manager.h"
 
 #include "base/base64url.h"
-#include "content/public/browser/browser_context.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/storage_partition.h"
 #include "mojo/public/cpp/bindings/remote.h"
@@ -76,9 +75,7 @@
 
 scoped_refptr<network::SharedURLLoaderFactory> GetUrlLoaderFactory(
     content::RenderFrameHost* host) {
-  return content::BrowserContext::GetDefaultStoragePartition(
-             host->GetBrowserContext())
-      ->GetURLLoaderFactoryForBrowserProcess();
+  return host->GetStoragePartition()->GetURLLoaderFactoryForBrowserProcess();
 }
 
 }  // namespace
@@ -107,8 +104,8 @@
 
   idp_well_known_callback_ = std::move(callback);
 
-  const url::Origin& idp = url::Origin::Create(provider_);
-  GURL target_url = idp.GetURL().Resolve(kWellKnownFilePath);
+  const url::Origin& idp_origin = url::Origin::Create(provider_);
+  GURL target_url = idp_origin.GetURL().Resolve(kWellKnownFilePath);
 
   net::NetworkTrafficAnnotationTag traffic_annotation =
       CreateTrafficAnnotation();
@@ -124,18 +121,23 @@
       network::mojom::CredentialsMode::kInclude;
   resource_request->headers.SetHeader(net::HttpRequestHeaders::kAccept,
                                       kAcceptMimeType);
+  // TODO(kenrb): Not following redirects is important for security because
+  // this bypasses CORB. Ensure there is a test added.
+  // https://crbug.com/1155312.
+  resource_request->redirect_mode = network::mojom::RedirectMode::kError;
   resource_request->request_initiator =
       render_frame_host_->GetLastCommittedOrigin();
+  resource_request->trusted_params = network::ResourceRequest::TrustedParams();
+  resource_request->trusted_params->isolation_info =
+      net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther,
+                                 idp_origin, idp_origin, net::SiteForCookies());
 
   url_loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
                                                  traffic_annotation);
 
-  // This creates a new URLLoaderFactory that matches the RP's factory for
-  // the early uncredentialed request, which serves to minimize cross-site
-  // tracking risk in the case that the flow does not proceed any further.
-  mojo::Remote<network::mojom::URLLoaderFactory> loader_factory;
-  render_frame_host_->CreateNetworkServiceDefaultFactory(
-      loader_factory.BindNewPipeAndPassReceiver());
+  // Use the browser process URL loader factory because it has cross-origin
+  // read blocking disabled.
+  auto loader_factory = GetUrlLoaderFactory(render_frame_host_);
 
   url_loader_->DownloadToString(
       loader_factory.get(),
diff --git a/content/child/webthemeengine_impl_android.cc b/content/child/webthemeengine_impl_android.cc
index 8e6ddcc1..a6be4c16 100644
--- a/content/child/webthemeengine_impl_android.cc
+++ b/content/child/webthemeengine_impl_android.cc
@@ -59,8 +59,6 @@
           extra_params->text_field.is_listbox;
       native_theme_extra_params->text_field.background_color =
           extra_params->text_field.background_color;
-      native_theme_extra_params->text_field.has_border =
-          extra_params->text_field.has_border;
       break;
     case WebThemeEngine::kPartMenuList:
       native_theme_extra_params->menu_list.has_border =
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index 7c434cc..c874288 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -83,7 +83,6 @@
     "font_list.cc",
     "font_list.h",
     "font_list_fontconfig.cc",
-    "frame_delete_intention.h",
     "frame_messages.h",
     "frame_replication_state.cc",
     "frame_replication_state.h",
@@ -151,7 +150,6 @@
     "thread_pool_util.cc",
     "thread_pool_util.h",
     "trace_utils.h",
-    "unfreezable_frame_messages.h",
     "url_schemes.cc",
     "url_schemes.h",
     "user_agent.cc",
diff --git a/content/common/content_message_generator.h b/content/common/content_message_generator.h
index e4c89b64..22d78dd 100644
--- a/content/common/content_message_generator.h
+++ b/content/common/content_message_generator.h
@@ -26,11 +26,6 @@
 #ifndef CONTENT_COMMON_RESOURCE_MESSAGES_H_
 #error "Failed to include content/common/resource_messages.h"
 #endif
-#undef CONTENT_COMMON_UNFREEZABLE_FRAME_MESSAGES_H_
-#include "content/common/unfreezable_frame_messages.h"
-#ifndef CONTENT_COMMON_UNFREEZABLE_FRAME_MESSAGES_H_
-#error "Failed to include content/common/unfreezable_frame_messages.h"
-#endif
 #include "media/media_buildflags.h"
 
 #if defined(OS_ANDROID)
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
index d14891f..99db7be 100644
--- a/content/common/frame.mojom
+++ b/content/common/frame.mojom
@@ -112,6 +112,20 @@
           pending_remote<FrameHTMLSerializerHandler> handler_remote);
 };
 
+// An enumeration specifying the reason of the frame deletion.
+enum FrameDeleteIntention {
+  // The frame being deleted isn't a (speculative) main frame.
+  kNotMainFrame,
+  // The frame being deleted is a speculative main frame, and it is being
+  // deleted as part of the shutdown for that WebContents. The entire RenderView
+  // etc will be destroyed by a separate IPC sent later.
+  kSpeculativeMainFrameForShutdown,
+  // The frame being deleted is a speculative main frame, and it is being
+  // deleted because the speculative navigation was cancelled. This is not part
+  // of shutdown.
+  kSpeculativeMainFrameForNavigationCancelled,
+};
+
 // Implemented by the frame provider and currently must be associated with the
 // legacy IPC channel.
 // KEEP THE COMMIT FUNCTIONS IN SYNC in content/common/navigation_client.mojom.
@@ -221,6 +235,12 @@
          bool is_loading,
          FrameReplicationState new_remote_frame_replication_state,
          mojo_base.mojom.UnguessableToken new_remote_frame_token);
+
+  // Delete the frame. This is only called for child frames that the browser
+  // wants to detach, or for speculative main frames which are owned by the
+  // browser process. Committed main frames are owned by the renderer's WebView
+  // and can not be deleted directly.
+  Delete(FrameDeleteIntention intention);
 };
 
 // Implemented by the frame (e.g. renderer processes).
diff --git a/content/common/frame_delete_intention.h b/content/common/frame_delete_intention.h
deleted file mode 100644
index f30103c3..0000000
--- a/content/common/frame_delete_intention.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_FRAME_DELETE_INTENTION_H_
-#define CONTENT_COMMON_FRAME_DELETE_INTENTION_H_
-
-namespace content {
-
-enum class FrameDeleteIntention {
-  // The frame being deleted isn't a (speculative) main frame.
-  kNotMainFrame,
-  // The frame being deleted is a speculative main frame, and it is being
-  // deleted as part of the shutdown for that WebContents. The entire RenderView
-  // etc will be destroyed by a separate IPC sent later.
-  kSpeculativeMainFrameForShutdown,
-  // The frame being deleted is a speculative main frame, and it is being
-  // deleted because the speculative navigation was cancelled. This is not part
-  // of shutdown.
-  kSpeculativeMainFrameForNavigationCancelled,
-
-  kMaxValue = kSpeculativeMainFrameForNavigationCancelled
-};
-
-}  // namespace content
-
-#endif  // CONTENT_COMMON_FRAME_DELETE_INTENTION_H_
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 4e730e5e..d2dab89 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -25,7 +25,6 @@
 #include "content/common/common_param_traits_macros.h"
 #include "content/common/content_export.h"
 #include "content/common/content_param_traits.h"
-#include "content/common/frame_delete_intention.h"
 #include "content/common/frame_replication_state.h"
 #include "content/common/navigation_gesture.h"
 #include "content/common/navigation_params.h"
@@ -82,8 +81,6 @@
 #define IPC_MESSAGE_EXPORT CONTENT_EXPORT
 
 #define IPC_MESSAGE_START FrameMsgStart
-IPC_ENUM_TRAITS_MAX_VALUE(content::FrameDeleteIntention,
-                          content::FrameDeleteIntention::kMaxValue)
 IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::FrameOwnerElementType,
                           blink::mojom::FrameOwnerElementType::kMaxValue)
 IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::AdFrameType,
diff --git a/content/common/unfreezable_frame_messages.h b/content/common/unfreezable_frame_messages.h
deleted file mode 100644
index 86efcf5..0000000
--- a/content/common/unfreezable_frame_messages.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_UNFREEZABLE_FRAME_MESSAGES_H_
-#define CONTENT_COMMON_UNFREEZABLE_FRAME_MESSAGES_H_
-
-#include "ipc/ipc_message_macros.h"
-
-// IPC messages for frames which should be executed and not be frozen even when
-// the frame is frozen.
-// Currently most IPC messages to the renderer are executed on freezable
-// per-frame task runners, but messages in this class will be handled as an
-// exception and will be posted on an unfreezable task runner and will be
-// guaranteed to run regardless of the frame's status.
-// These messages are primarily intended to support bfcache functionality.
-
-#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
-
-#define IPC_MESSAGE_START UnfreezableFrameMsgStart
-
-// Instructs the renderer to delete the RenderFrame.
-IPC_MESSAGE_ROUTED1(UnfreezableFrameMsg_Delete, content::FrameDeleteIntention)
-
-#endif  // CONTENT_COMMON_UNFREEZABLE_FRAME_MESSAGES_H_
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
index 96b405fd..4438e04 100644
--- a/content/public/browser/content_browser_client.cc
+++ b/content/public/browser/content_browser_client.cc
@@ -789,9 +789,7 @@
 bool ContentBrowserClient::WillCreateRestrictedCookieManager(
     network::mojom::RestrictedCookieManagerRole role,
     BrowserContext* browser_context,
-    const url::Origin& origin,
-    const net::SiteForCookies& site_for_cookies,
-    const url::Origin& top_frame_origin,
+    const net::IsolationInfo& isolation_info,
     bool is_service_worker,
     int process_id,
     int frame_id,
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 03f8c36..df6e463 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -70,6 +70,7 @@
 namespace net {
 class AuthCredentials;
 class SiteForCookies;
+class IsolationInfo;
 }  // namespace net
 
 class GURL;
@@ -1454,9 +1455,7 @@
   virtual bool WillCreateRestrictedCookieManager(
       network::mojom::RestrictedCookieManagerRole role,
       BrowserContext* browser_context,
-      const url::Origin& origin,
-      const net::SiteForCookies& site_for_cookies,
-      const url::Origin& top_frame_origin,
+      const net::IsolationInfo& isolation_info,
       bool is_service_worker,
       int process_id,
       int routing_id,
@@ -1504,16 +1503,13 @@
   // BrowserContext's StoragePartition. StoragePartition will use the
   // NetworkService to create a new NetworkContext using these params.
   //
+  // Embedders wishing to modify the initial configuration of the CertVerifier
+  // should edit |cert_verifier_creation_params| rather than
+  // |network_context_params->cert_verifier_params|, which will be discarded.
+  //
   // By default the |network_context_params| is populated with |user_agent|
   // based on the value returned by GetUserAgent(), and with a fixed legacy
   // "accept-language" header value of "en-us,en".
-  //
-  // If the CertVerifierService is enabled, the CertVerifierCreationParams will
-  // be used to create a new CertVerifierService, which will be passed to the
-  // network service in NetworkContextParams. Otherwise, the
-  // CertVerifierCreationParams will be placed in the NetworkContextParams and
-  // sent directly to the NetworkService for in-process CertVerifier creation.
-  //
   // If |in_memory| is true, |relative_partition_path| is still a path that
   // uniquely identifies the storage partition, though nothing should be written
   // to it.
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index f17e769..2b35456 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -65,7 +65,6 @@
 #include "content/common/navigation_params_utils.h"
 #include "content/common/render_accessibility.mojom.h"
 #include "content/common/renderer_host.mojom.h"
-#include "content/common/unfreezable_frame_messages.h"
 #include "content/common/web_package/signed_exchange_utils.h"
 #include "content/public/common/bindings_policy.h"
 #include "content/public/common/content_constants.h"
@@ -2181,7 +2180,6 @@
     IPC_MESSAGE_HANDLER(FrameMsg_ContextMenuClosed, OnContextMenuClosed)
     IPC_MESSAGE_HANDLER(FrameMsg_CustomContextMenuAction,
                         OnCustomContextMenuAction)
-    IPC_MESSAGE_HANDLER(UnfreezableFrameMsg_Delete, OnDeleteFrame)
   IPC_END_MESSAGE_MAP()
 
   return handled;
@@ -2342,7 +2340,7 @@
   task_runner->PostTask(FROM_HERE, std::move(send_unload_ack));
 }
 
-void RenderFrameImpl::OnDeleteFrame(FrameDeleteIntention intent) {
+void RenderFrameImpl::Delete(mojom::FrameDeleteIntention intent) {
   // The main frame (when not provisional) is owned by the renderer's frame tree
   // via WebViewImpl. When a provisional main frame is swapped in, the ownership
   // moves from the browser to the renderer, but this happens in the renderer
@@ -2351,13 +2349,13 @@
   // it, the browser may request to delete |this|, thinking it has ownership
   // of it, but the renderer has already taken ownership via SwapIn().
   switch (intent) {
-    case FrameDeleteIntention::kNotMainFrame:
+    case mojom::FrameDeleteIntention::kNotMainFrame:
       // The frame was not a main frame, so the browser should always have
       // ownership of it and we can just proceed with deleting it on
       // request.
       DCHECK(!is_main_frame_);
       break;
-    case FrameDeleteIntention::kSpeculativeMainFrameForShutdown:
+    case mojom::FrameDeleteIntention::kSpeculativeMainFrameForShutdown:
       // In this case the renderer has taken ownership of the provisional main
       // frame but the browser did not know yet and is shutting down. We can
       // ignore this request as the frame will be destroyed when the RenderView
@@ -2366,7 +2364,8 @@
       if (in_frame_tree_)
         return;
       break;
-    case FrameDeleteIntention::kSpeculativeMainFrameForNavigationCancelled:
+    case mojom::FrameDeleteIntention::
+        kSpeculativeMainFrameForNavigationCancelled:
       // In this case the browser was navigating and cancelled the speculative
       // navigation. The renderer *should* undo the SwapIn() but the old state
       // has already been destroyed. Both ignoring the message or handling it
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 306e88f..e003c6e 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -35,7 +35,6 @@
 #include "content/common/buildflags.h"
 #include "content/common/download/mhtml_file_writer.mojom.h"
 #include "content/common/frame.mojom.h"
-#include "content/common/frame_delete_intention.h"
 #include "content/common/navigation_params.mojom.h"
 #include "content/common/render_accessibility.mojom.h"
 #include "content/common/renderer.mojom.h"
@@ -166,7 +165,7 @@
       public blink::mojom::ResourceLoadInfoNotifier,
       blink::mojom::AutoplayConfigurationClient,
       mojom::Frame,
-      mojom::FrameNavigationControl,
+      public mojom::FrameNavigationControl,
       mojom::FrameBindingsControl,
       mojom::MhtmlFileWriter,
       public blink::WebLocalFrameClient,
@@ -487,46 +486,6 @@
       mojom::NavigationClient::CommitFailedNavigationCallback
           per_navigation_mojo_interface_callback);
 
-  // mojom::FrameNavigationControl implementation:
-  void CommitSameDocumentNavigation(
-      mojom::CommonNavigationParamsPtr common_params,
-      mojom::CommitNavigationParamsPtr commit_params,
-      CommitSameDocumentNavigationCallback callback) override;
-  void HandleRendererDebugURL(const GURL& url) override;
-  void UpdateSubresourceLoaderFactories(
-      std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
-          subresource_loader_factories) override;
-  void BindDevToolsAgent(
-      mojo::PendingAssociatedRemote<blink::mojom::DevToolsAgentHost> host,
-      mojo::PendingAssociatedReceiver<blink::mojom::DevToolsAgent> receiver)
-      override;
-  void JavaScriptMethodExecuteRequest(
-      const base::string16& object_name,
-      const base::string16& method_name,
-      base::Value arguments,
-      bool wants_result,
-      JavaScriptMethodExecuteRequestCallback callback) override;
-  void JavaScriptExecuteRequest(
-      const base::string16& javascript,
-      bool wants_result,
-      JavaScriptExecuteRequestCallback callback) override;
-  void JavaScriptExecuteRequestForTests(
-      const base::string16& javascript,
-      bool wants_result,
-      bool has_user_gesture,
-      int32_t world_id,
-      JavaScriptExecuteRequestForTestsCallback callback) override;
-  void JavaScriptExecuteRequestInIsolatedWorld(
-      const base::string16& javascript,
-      bool wants_result,
-      int32_t world_id,
-      JavaScriptExecuteRequestInIsolatedWorldCallback callback) override;
-  void SetWantErrorMessageStackTrace() override;
-  void Unload(int proxy_routing_id,
-              bool is_loading,
-              const FrameReplicationState& replicated_frame_state,
-              const base::UnguessableToken& frame_token) override;
-
   // mojom::MhtmlFileWriter implementation:
   void SerializeAsMHTML(const mojom::SerializeAsMHTMLParamsPtr params,
                         SerializeAsMHTMLCallback callback) override;
@@ -882,11 +841,51 @@
   // Checks whether accessibility support for this frame is currently enabled.
   bool IsAccessibilityEnabled() const;
 
+  // mojom::FrameNavigationControl implementation:
+  void CommitSameDocumentNavigation(
+      mojom::CommonNavigationParamsPtr common_params,
+      mojom::CommitNavigationParamsPtr commit_params,
+      CommitSameDocumentNavigationCallback callback) override;
+  void HandleRendererDebugURL(const GURL& url) override;
+  void UpdateSubresourceLoaderFactories(
+      std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
+          subresource_loader_factories) override;
+  void BindDevToolsAgent(
+      mojo::PendingAssociatedRemote<blink::mojom::DevToolsAgentHost> host,
+      mojo::PendingAssociatedReceiver<blink::mojom::DevToolsAgent> receiver)
+      override;
+  void JavaScriptMethodExecuteRequest(
+      const base::string16& object_name,
+      const base::string16& method_name,
+      base::Value arguments,
+      bool wants_result,
+      JavaScriptMethodExecuteRequestCallback callback) override;
+  void JavaScriptExecuteRequest(
+      const base::string16& javascript,
+      bool wants_result,
+      JavaScriptExecuteRequestCallback callback) override;
+  void JavaScriptExecuteRequestForTests(
+      const base::string16& javascript,
+      bool wants_result,
+      bool has_user_gesture,
+      int32_t world_id,
+      JavaScriptExecuteRequestForTestsCallback callback) override;
+  void JavaScriptExecuteRequestInIsolatedWorld(
+      const base::string16& javascript,
+      bool wants_result,
+      int32_t world_id,
+      JavaScriptExecuteRequestInIsolatedWorldCallback callback) override;
+  void SetWantErrorMessageStackTrace() override;
+  void Unload(int proxy_routing_id,
+              bool is_loading,
+              const FrameReplicationState& replicated_frame_state,
+              const base::UnguessableToken& frame_token) override;
+  void Delete(mojom::FrameDeleteIntention intent) override;
+
   // IPC message handlers ------------------------------------------------------
   //
   // The documentation for these functions should be in
   // content/common/*_messages.h for the message that the function is handling.
-  void OnDeleteFrame(FrameDeleteIntention intent);
   void OnShowContextMenu(const gfx::Point& location);
   void OnContextMenuClosed(const CustomContextMenuContext& custom_context);
   void OnCustomContextMenuAction(const CustomContextMenuContext& custom_context,
diff --git a/content/renderer/render_frame_impl_browsertest.cc b/content/renderer/render_frame_impl_browsertest.cc
index dcd9f47..eee60aa 100644
--- a/content/renderer/render_frame_impl_browsertest.cc
+++ b/content/renderer/render_frame_impl_browsertest.cc
@@ -22,7 +22,6 @@
 #include "content/common/frame_messages.h"
 #include "content/common/navigation_params_mojom_traits.h"
 #include "content/common/renderer.mojom.h"
-#include "content/common/unfreezable_frame_messages.h"
 #include "content/public/common/content_features.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/renderer/content_renderer_client.h"
@@ -363,9 +362,8 @@
       true /* new_session */, true /* force */, false /* wrap_within_frame */,
       false /* async */);
 
-  UnfreezableFrameMsg_Delete delete_message(
-      0, FrameDeleteIntention::kNotMainFrame);
-  frame()->OnMessageReceived(delete_message);
+  static_cast<mojom::FrameNavigationControl*>(frame())->Delete(
+      mojom::FrameDeleteIntention::kNotMainFrame);
 }
 
 TEST_F(RenderFrameImplTest, AutoplayFlags) {
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc
index 9fb5c49c..76195c95 100644
--- a/content/renderer/render_frame_proxy.cc
+++ b/content/renderer/render_frame_proxy.cc
@@ -16,7 +16,6 @@
 #include "content/common/content_switches_internal.h"
 #include "content/common/frame_replication_state.h"
 #include "content/common/input_messages.h"
-#include "content/common/unfreezable_frame_messages.h"
 #include "content/public/common/content_client.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/common/impression.h"
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
index 5c7bba51..77b13bd 100644
--- a/content/renderer/render_thread_impl.cc
+++ b/content/renderer/render_thread_impl.cc
@@ -601,9 +601,6 @@
 
   vc_manager_.reset(new blink::WebVideoCaptureImplManager());
 
-  unfreezable_message_filter_ = new UnfreezableMessageFilter(this);
-  AddFilter(unfreezable_message_filter_.get());
-
   GetContentClient()->renderer()->RenderThreadStarted();
   ExposeRendererInterfacesToBrowser(weak_factory_.GetWeakPtr(), &binders);
   ExposeInterfacesToBrowser(std::move(binders));
@@ -840,18 +837,12 @@
       routing_id,
       frame->GetTaskRunner(blink::TaskType::kInternalNavigationAssociated));
 
-  unfreezable_message_filter_->AddListenerUnfreezableTaskRunner(
-      routing_id,
-      frame->GetTaskRunner(
-          blink::TaskType::kInternalNavigationAssociatedUnfreezable));
-
   frame->BindFrame(std::move(it->second));
   pending_frames_.erase(it);
 }
 
 void RenderThreadImpl::RemoveRoute(int32_t routing_id) {
   ChildThreadImpl::GetRouter()->RemoveRoute(routing_id);
-  unfreezable_message_filter_->RemoveListenerUnfreezableTaskRunner(routing_id);
   GetChannel()->RemoveListenerTaskRunner(routing_id);
   pending_frames_.erase(routing_id);
 }
@@ -1976,59 +1967,4 @@
   }
 }
 
-RenderThreadImpl::UnfreezableMessageFilter::UnfreezableMessageFilter(
-    RenderThreadImpl* render_thread_impl)
-    : render_thread_impl_(render_thread_impl) {}
-
-// Called on the I/O thread.
-bool RenderThreadImpl::UnfreezableMessageFilter::OnMessageReceived(
-    const IPC::Message& message) {
-  if ((IPC_MESSAGE_CLASS(message) == UnfreezableFrameMsgStart)) {
-    auto task_runner = GetUnfreezableTaskRunner(message.routing_id());
-    if (task_runner) {
-      return task_runner->PostTask(
-          FROM_HERE,
-          base::BindOnce(
-              base::IgnoreResult(&RenderThreadImpl::OnMessageReceived),
-              base::Unretained(render_thread_impl_), message));
-    }
-  }
-  // If unfreezable task runner is not found or the message class is not
-  // UnfreezableFrameMsgStart, return false so that this filter is skipped and
-  // other handlers can continue executing and handle this message.
-  return false;
-}
-
-// Called on the listener thread.
-void RenderThreadImpl::UnfreezableMessageFilter::
-    AddListenerUnfreezableTaskRunner(
-        int32_t routing_id,
-        scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner) {
-  DCHECK(unfreezable_task_runner);
-  base::AutoLock lock(unfreezable_task_runners_lock_);
-  DCHECK(!base::Contains(unfreezable_task_runners_, routing_id));
-  unfreezable_task_runners_.emplace(routing_id,
-                                    std::move(unfreezable_task_runner));
-}
-
-// Called on the listener thread.
-void RenderThreadImpl::UnfreezableMessageFilter::
-    RemoveListenerUnfreezableTaskRunner(int32_t routing_id) {
-  base::AutoLock lock(unfreezable_task_runners_lock_);
-  unfreezable_task_runners_.erase(routing_id);
-}
-
-// Called on the I/O thread.
-scoped_refptr<base::SingleThreadTaskRunner>
-RenderThreadImpl::UnfreezableMessageFilter::GetUnfreezableTaskRunner(
-    int32_t routing_id) {
-  base::AutoLock lock(unfreezable_task_runners_lock_);
-  auto it = unfreezable_task_runners_.find(routing_id);
-  if (it != unfreezable_task_runners_.end())
-    return it->second;
-  return nullptr;
-}
-
-RenderThreadImpl::UnfreezableMessageFilter::~UnfreezableMessageFilter() {}
-
 }  // namespace content
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h
index 7dfd467..2ab10e9 100644
--- a/content/renderer/render_thread_impl.h
+++ b/content/renderer/render_thread_impl.h
@@ -300,34 +300,6 @@
   scoped_refptr<viz::ContextProviderCommandBuffer>
   SharedMainThreadContextProvider();
 
-  class UnfreezableMessageFilter : public IPC::MessageFilter {
-   public:
-    explicit UnfreezableMessageFilter(RenderThreadImpl* render_thread_impl);
-    bool OnMessageReceived(const IPC::Message& message) override;
-
-    // Adds |unfreezable_task_runner| for the task to be executed later.
-    void AddListenerUnfreezableTaskRunner(
-        int32_t routing_id,
-        scoped_refptr<base::SingleThreadTaskRunner> unfreezable_task_runner);
-
-    // Removes |unfreezable_task_runner| for the task to be executed later.
-    void RemoveListenerUnfreezableTaskRunner(
-        int32_t routing_id);
-
-    // Called on the I/O thread.
-    // Returns the unfreezable task runner associated with |routing_id|.
-    scoped_refptr<base::SingleThreadTaskRunner> GetUnfreezableTaskRunner(
-        int32_t routing_id);
-
-   private:
-    ~UnfreezableMessageFilter() override;
-    RenderThreadImpl* render_thread_impl_;
-    base::Lock unfreezable_task_runners_lock_;
-    // Map of routing_id and listener's thread unfreezable task runner.
-    std::map<int32_t, scoped_refptr<base::SingleThreadTaskRunner>>
-        unfreezable_task_runners_ GUARDED_BY(unfreezable_task_runners_lock_);
-  };
-
   // For producing custom V8 histograms. Custom histograms are produced if all
   // RenderViews share the same host, and the host is in the pre-specified set
   // of hosts we want to produce custom diagrams for. The name for a custom
@@ -354,7 +326,6 @@
     FRIEND_TEST_ALL_PREFIXES(RenderThreadImplUnittest,
                              IdentifyAlexaTop10NonGoogleSite);
     friend class RenderThreadImplUnittest;
-    friend class UnfreezableMessageFilter;
 
     // Converts a host name to a suffix for histograms
     std::string HostToCustomHistogramSuffix(const std::string& host);
@@ -510,9 +481,6 @@
   std::unique_ptr<ResourceDispatcher> resource_dispatcher_;
   std::unique_ptr<URLLoaderThrottleProvider> url_loader_throttle_provider_;
 
-  // Filter out unfreezable messages and pass it to unfreezable task runners.
-  scoped_refptr<UnfreezableMessageFilter> unfreezable_message_filter_;
-
   // Used on the render thread.
   std::unique_ptr<blink::WebVideoCaptureImplManager> vc_manager_;
 
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 17f5a74..7557af0a 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -30,7 +30,6 @@
 #include "content/common/frame_messages.h"
 #include "content/common/frame_replication_state.h"
 #include "content/common/renderer.mojom.h"
-#include "content/common/unfreezable_frame_messages.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/native_web_keyboard_event.h"
 #include "content/public/browser/web_ui_controller.h"
@@ -638,9 +637,10 @@
       static_cast<TestRenderFrame*>(RenderFrame::FromWebFrame(
           root_web_frame->FirstChild()->NextSibling()->ToWebLocalFrame()));
   ASSERT_TRUE(child_frame_2);
-  child_frame_1->Unload(kProxyRoutingId, true,
-                        ReconstructReplicationStateForTesting(child_frame_1),
-                        base::UnguessableToken::Create());
+  static_cast<mojom::FrameNavigationControl*>(child_frame_1)
+      ->Unload(kProxyRoutingId, true,
+               ReconstructReplicationStateForTesting(child_frame_1),
+               base::UnguessableToken::Create());
   EXPECT_TRUE(root_web_frame->FirstChild()->IsWebRemoteFrame());
   RenderFrameProxy* child_proxy_1 = RenderFrameProxy::FromWebFrame(
       root_web_frame->FirstChild()->ToWebRemoteFrame());
@@ -662,9 +662,10 @@
   // Create a new remote child, and get its proxy. Unloading will force creation
   // and registering of a new RenderFrameProxy, which should pick up the
   // existing setting.
-  child_frame_2->Unload(kProxyRoutingId + 1, true,
-                        ReconstructReplicationStateForTesting(child_frame_2),
-                        base::UnguessableToken::Create());
+  static_cast<mojom::FrameNavigationControl*>(child_frame_2)
+      ->Unload(kProxyRoutingId + 1, true,
+               ReconstructReplicationStateForTesting(child_frame_2),
+               base::UnguessableToken::Create());
   EXPECT_TRUE(root_web_frame->FirstChild()->NextSibling()->IsWebRemoteFrame());
   RenderFrameProxy* child_proxy_2 = RenderFrameProxy::FromWebFrame(
       root_web_frame->FirstChild()->NextSibling()->ToWebRemoteFrame());
@@ -1113,9 +1114,10 @@
       RenderFrame::FromWebFrame(web_frame->FirstChild()->ToWebLocalFrame()));
   ASSERT_TRUE(child_frame);
 
-  child_frame->Unload(kProxyRoutingId + 1, true,
-                      ReconstructReplicationStateForTesting(child_frame),
-                      base::UnguessableToken::Create());
+  static_cast<mojom::FrameNavigationControl*>(child_frame)
+      ->Unload(kProxyRoutingId + 1, true,
+               ReconstructReplicationStateForTesting(child_frame),
+               base::UnguessableToken::Create());
   EXPECT_TRUE(web_frame->FirstChild()->IsWebRemoteFrame());
   RenderFrameProxy* child_proxy = RenderFrameProxy::FromWebFrame(
       web_frame->FirstChild()->ToWebRemoteFrame());
@@ -1158,8 +1160,9 @@
   content::FrameReplicationState replication_state =
       ReconstructReplicationStateForTesting(child_frame);
   replication_state.origin = url::Origin::Create(GURL("http://foo.com"));
-  child_frame->Unload(kProxyRoutingId, true, replication_state,
-                      base::UnguessableToken::Create());
+  static_cast<mojom::FrameNavigationControl*>(child_frame)
+      ->Unload(kProxyRoutingId, true, replication_state,
+               base::UnguessableToken::Create());
 
   // The child frame should now be a WebRemoteFrame.
   EXPECT_TRUE(web_frame->FirstChild()->IsWebRemoteFrame());
@@ -1176,8 +1179,9 @@
   TestRenderFrame* child_frame2 =
       static_cast<TestRenderFrame*>(RenderFrame::FromWebFrame(
           web_frame->FirstChild()->NextSibling()->ToWebLocalFrame()));
-  child_frame2->Unload(kProxyRoutingId + 1, true, replication_state,
-                       base::UnguessableToken::Create());
+  static_cast<mojom::FrameNavigationControl*>(child_frame2)
+      ->Unload(kProxyRoutingId + 1, true, replication_state,
+               base::UnguessableToken::Create());
   EXPECT_TRUE(web_frame->FirstChild()->NextSibling()->IsWebRemoteFrame());
   EXPECT_TRUE(
       web_frame->FirstChild()->NextSibling()->GetSecurityOrigin().IsOpaque());
@@ -1204,8 +1208,9 @@
   content::FrameReplicationState replication_state =
       ReconstructReplicationStateForTesting(frame());
   // replication_state.origin = url::Origin(GURL("http://foo.com"));
-  frame()->Unload(kProxyRoutingId, true, replication_state,
-                  base::UnguessableToken::Create());
+  static_cast<mojom::FrameNavigationControl*>(frame())->Unload(
+      kProxyRoutingId, true, replication_state,
+      base::UnguessableToken::Create());
   EXPECT_TRUE(view()->GetWebView()->MainFrame()->IsWebRemoteFrame());
 
   // Do the remote-to-local transition for the proxy, which is to create a
@@ -1298,8 +1303,9 @@
   // Unload the child frame.
   FrameReplicationState replication_state =
       ReconstructReplicationStateForTesting(child_frame);
-  child_frame->Unload(kProxyRoutingId, true, replication_state,
-                      base::UnguessableToken::Create());
+  static_cast<mojom::FrameNavigationControl*>(child_frame)
+      ->Unload(kProxyRoutingId, true, replication_state,
+               base::UnguessableToken::Create());
   EXPECT_TRUE(web_frame->FirstChild()->IsWebRemoteFrame());
 
   // Do the first step of a remote-to-local transition for the child proxy,
@@ -1350,9 +1356,10 @@
   // Unload the main frame after which it should become a WebRemoteFrame.
   TestRenderFrame* main_frame =
       static_cast<TestRenderFrame*>(view()->GetMainRenderFrame());
-  main_frame->Unload(kProxyRoutingId, true,
-                     ReconstructReplicationStateForTesting(main_frame),
-                     base::UnguessableToken::Create());
+  static_cast<mojom::FrameNavigationControl*>(main_frame)
+      ->Unload(kProxyRoutingId, true,
+               ReconstructReplicationStateForTesting(main_frame),
+               base::UnguessableToken::Create());
   EXPECT_TRUE(view()->GetWebView()->MainFrame()->IsWebRemoteFrame());
 }
 
@@ -2960,8 +2967,9 @@
         EXPECT_EQ(base::UTF8ToUTF16("OnBeforeUnload called"), msg);
 
         // Unloads the main frame.
-        frame()->Unload(1, false, FrameReplicationState(),
-                        base::UnguessableToken::Create());
+        static_cast<mojom::FrameNavigationControl*>(frame())->Unload(
+            1, false, FrameReplicationState(),
+            base::UnguessableToken::Create());
 
         was_callback_run = true;
         run_loop.Quit();
diff --git a/content/test/data/forms/form_controls_browsertest_input.png b/content/test/data/forms/form_controls_browsertest_input.png
deleted file mode 100644
index 677bdaf..0000000
--- a/content/test/data/forms/form_controls_browsertest_input.png
+++ /dev/null
Binary files differ
diff --git a/content/test/data/forms/form_controls_browsertest_input_android.png b/content/test/data/forms/form_controls_browsertest_input_android.png
deleted file mode 100644
index 77bdeae..0000000
--- a/content/test/data/forms/form_controls_browsertest_input_android.png
+++ /dev/null
Binary files differ
diff --git a/content/test/data/forms/form_controls_browsertest_input_mac.png b/content/test/data/forms/form_controls_browsertest_input_mac.png
deleted file mode 100644
index a58c8f14..0000000
--- a/content/test/data/forms/form_controls_browsertest_input_mac.png
+++ /dev/null
Binary files differ
diff --git a/content/test/data/forms/form_controls_browsertest_input_win.png b/content/test/data/forms/form_controls_browsertest_input_win.png
deleted file mode 100644
index a58c8f14..0000000
--- a/content/test/data/forms/form_controls_browsertest_input_win.png
+++ /dev/null
Binary files differ
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index 1c65f1a3..9e2aee0ce 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -207,6 +207,9 @@
 crbug.com/1136231 [ win ] conformance/extensions/s3tc-and-rgtc.html [ Failure ]
 crbug.com/1136231 [ linux ] conformance/extensions/s3tc-and-rgtc.html [ Failure ]
 
+# TODO(kbr): Lift this once upstream test is updated.
+crbug.com/angleproject/5499 conformance/glsl/misc/shaders-with-name-conflicts.html [ Skip ]
+
 # Skipping new tests
 crbug.com/angleproject/5038 conformance/extensions/ext-color-buffer-half-float.html [ Skip ]
 
diff --git a/extensions/browser/extension_function_dispatcher.cc b/extensions/browser/extension_function_dispatcher.cc
index a544a3c..5901eba 100644
--- a/extensions/browser/extension_function_dispatcher.cc
+++ b/extensions/browser/extension_function_dispatcher.cc
@@ -42,7 +42,6 @@
 #include "extensions/common/extension_api.h"
 #include "extensions/common/extension_messages.h"
 #include "extensions/common/extension_set.h"
-#include "extensions/common/extensions_client.h"
 #include "ipc/ipc_message.h"
 #include "ipc/ipc_message_macros.h"
 
@@ -131,9 +130,6 @@
         observer_(this),
         render_process_host_(render_process_host) {
     observer_.Add(render_process_host_);
-
-    DCHECK(ExtensionsClient::Get()
-               ->ExtensionAPIEnabledInExtensionServiceWorkers());
   }
 
   ~WorkerResponseCallbackWrapper() override = default;
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc
index bd26e97..7a90eee 100644
--- a/extensions/browser/extension_prefs.cc
+++ b/extensions/browser/extension_prefs.cc
@@ -964,17 +964,13 @@
 void ExtensionPrefs::AddDisableReason(
     const std::string& extension_id,
     disable_reason::DisableReason disable_reason) {
-  // TODO(https://crbug.com/1073570): Extensions can be blocklisted but in
-  // enabled state. This checks the kPrefState which is the state of the
-  // extension.
-  DCHECK(!DoesExtensionHaveState(extension_id, Extension::ENABLED) ||
-         disable_reason == disable_reason::DISABLE_REMOTELY_FOR_MALWARE);
-  ModifyDisableReasons(extension_id, disable_reason, DISABLE_REASON_ADD);
+  AddDisableReasons(extension_id, disable_reason);
 }
 
 void ExtensionPrefs::AddDisableReasons(const std::string& extension_id,
                                        int disable_reasons) {
-  DCHECK(!DoesExtensionHaveState(extension_id, Extension::ENABLED));
+  DCHECK(!DoesExtensionHaveState(extension_id, Extension::ENABLED) ||
+         IsExtensionBlocklisted(extension_id));
   ModifyDisableReasons(extension_id, disable_reasons, DISABLE_REASON_ADD);
 }
 
diff --git a/extensions/browser/extension_registrar.cc b/extensions/browser/extension_registrar.cc
index f7dd29fd..0df0130 100644
--- a/extensions/browser/extension_registrar.cc
+++ b/extensions/browser/extension_registrar.cc
@@ -228,17 +228,6 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
   DCHECK_NE(disable_reason::DISABLE_NONE, disable_reasons);
 
-  if (extension_prefs_->IsExtensionBlocklisted(extension_id))
-    return;
-
-  // The extension may have been disabled already. Just add the disable reasons.
-  // TODO(michaelpg): Move this after the policy check, below, to ensure that
-  // disable reasons disallowed by policy are not added here.
-  if (!IsExtensionEnabled(extension_id)) {
-    extension_prefs_->AddDisableReasons(extension_id, disable_reasons);
-    return;
-  }
-
   scoped_refptr<const Extension> extension =
       registry_->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING);
 
@@ -262,6 +251,12 @@
       return;
   }
 
+  // The extension may have been disabled already. Just add the disable reasons.
+  if (!IsExtensionEnabled(extension_id)) {
+    extension_prefs_->AddDisableReasons(extension_id, disable_reasons);
+    return;
+  }
+
   extension_prefs_->SetExtensionDisabled(extension_id, disable_reasons);
 
   int include_mask =
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_browsertest.cc b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_browsertest.cc
index 12df799..b8548ad3 100644
--- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_browsertest.cc
+++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_browsertest.cc
@@ -38,6 +38,7 @@
 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
 #include "extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.h"
 #include "extensions/browser/process_manager.h"
+#include "extensions/common/constants.h"
 #include "extensions/common/guest_view/extensions_guest_view_messages.h"
 #include "extensions/common/mojom/guest_view.mojom.h"
 #include "extensions/test/result_catcher.h"
@@ -58,9 +59,6 @@
 using guest_view::TestGuestViewManager;
 using guest_view::TestGuestViewManagerFactory;
 
-// The test extension id is set by the key value in the manifest.
-const char kExtensionId[] = "oickdpebdnfbgkcaoklfcdhjniefkcji";
-
 class MimeHandlerViewTest : public extensions::ExtensionApiTest {
  public:
   MimeHandlerViewTest() {
@@ -117,7 +115,8 @@
     if (!extension)
       return nullptr;
 
-    CHECK_EQ(std::string(kExtensionId), extension->id());
+    EXPECT_EQ(std::string(extension_misc::kMimeHandlerPrivateTestExtensionId),
+              extension->id());
 
     return extension;
   }
diff --git a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_interactive_uitest.cc b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_interactive_uitest.cc
index 64364c0..5345f7f 100644
--- a/extensions/browser/guest_view/mime_handler_view/mime_handler_view_interactive_uitest.cc
+++ b/extensions/browser/guest_view/mime_handler_view/mime_handler_view_interactive_uitest.cc
@@ -30,6 +30,7 @@
 #include "extensions/browser/guest_view/extensions_guest_view_manager_delegate.h"
 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
 #include "extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.h"
+#include "extensions/common/constants.h"
 #include "extensions/test/result_catcher.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "third_party/blink/public/common/input/web_pointer_properties.h"
@@ -41,9 +42,6 @@
 
 namespace extensions {
 
-// The test extension id is set by the key value in the manifest.
-const char kExtensionId[] = "oickdpebdnfbgkcaoklfcdhjniefkcji";
-
 // Counts the number of URL requests made for a given URL.
 class MimeHandlerViewTest : public ExtensionApiTest {
  public:
@@ -88,7 +86,8 @@
     if (!extension)
       return nullptr;
 
-    CHECK_EQ(std::string(kExtensionId), extension->id());
+    EXPECT_EQ(std::string(extension_misc::kMimeHandlerPrivateTestExtensionId),
+              extension->id());
 
     return extension;
   }
diff --git a/extensions/common/constants.h b/extensions/common/constants.h
index c2c88ee..f65699e9 100644
--- a/extensions/common/constants.h
+++ b/extensions/common/constants.h
@@ -9,7 +9,6 @@
 #include "base/strings/string_piece_forward.h"
 #include "build/chromeos_buildflags.h"
 #include "components/services/app_service/public/mojom/types.mojom.h"
-#include "components/version_info/channel.h"
 #include "ui/base/layout.h"
 
 namespace extensions {
@@ -289,10 +288,6 @@
 // The minimum severity of a log or error in order to report it to the browser.
 extern const logging::LogSeverity kMinimumSeverityToReportError;
 
-// The minimum channel where Service Worker based extensions can run.
-constexpr version_info::Channel kMinChannelForServiceWorkerBasedExtension =
-    version_info::Channel::STABLE;
-
 // IDs for the Media Router Component Extension.
 extern const char kCastExtensionIdRelease[];
 extern const char kCastExtensionIdDev[];
diff --git a/extensions/common/extensions_client.cc b/extensions/common/extensions_client.cc
index 08ed63f..c691944 100644
--- a/extensions/common/extensions_client.cc
+++ b/extensions/common/extensions_client.cc
@@ -102,10 +102,6 @@
   return paths;
 }
 
-bool ExtensionsClient::ExtensionAPIEnabledInExtensionServiceWorkers() const {
-  return false;
-}
-
 void ExtensionsClient::AddOriginAccessPermissions(
     const Extension& extension,
     bool is_extension_active,
diff --git a/extensions/common/extensions_client.h b/extensions/common/extensions_client.h
index 5631a92a..759b4d80 100644
--- a/extensions/common/extensions_client.h
+++ b/extensions/common/extensions_client.h
@@ -134,13 +134,6 @@
   virtual std::set<base::FilePath> GetBrowserImagePaths(
       const Extension* extension);
 
-  // Returns whether or not extension APIs are allowed in extension service
-  // workers.
-  // This is currently disallowed as the code to support this is work in
-  // progress.
-  // Can be overridden in tests.
-  virtual bool ExtensionAPIEnabledInExtensionServiceWorkers() const;
-
   // Adds client specific permitted origins to |origin_patterns| for
   // cross-origin communication for an extension context.
   virtual void AddOriginAccessPermissions(
diff --git a/extensions/renderer/native_extension_bindings_system.cc b/extensions/renderer/native_extension_bindings_system.cc
index 69dd930..bd09e935 100644
--- a/extensions/renderer/native_extension_bindings_system.cc
+++ b/extensions/renderer/native_extension_bindings_system.cc
@@ -569,10 +569,6 @@
       is_webpage = true;
       break;
     case Feature::BLESSED_EXTENSION_CONTEXT:
-      if (context->IsForServiceWorker())
-        DCHECK(ExtensionsClient::Get()
-                   ->ExtensionAPIEnabledInExtensionServiceWorkers());
-      FALLTHROUGH;
     case Feature::LOCK_SCREEN_EXTENSION_CONTEXT:
     case Feature::UNBLESSED_EXTENSION_CONTEXT:
     case Feature::CONTENT_SCRIPT_CONTEXT:
diff --git a/infra/config/console-header.star b/infra/config/console-header.star
index 2e531a86..50b6162 100644
--- a/infra/config/console-header.star
+++ b/infra/config/console-header.star
@@ -20,7 +20,7 @@
         show_primary_secondary_labels = show_primary_secondary_labels,
     ))
 
-def _link(*, url, text, alt, branch_selector = branches.MAIN):
+def _link(*, url, text, alt = None, branch_selector = branches.MAIN):
     if not branches.matches(branch_selector):
         return None
     return _remove_none_values(dict(
@@ -275,7 +275,6 @@
                 _link(
                     text = milestone,
                     url = "/p/{}/g/main/console".format(details.project),
-                    alt = "{} branch console".format(details.channel),
                 )
                 for milestone, details in sorted(ACTIVE_MILESTONES.items())
             ] + [
diff --git a/infra/config/generated/commit-queue.cfg b/infra/config/generated/commit-queue.cfg
index fd8f7c2..c0a0be7 100644
--- a/infra/config/generated/commit-queue.cfg
+++ b/infra/config/generated/commit-queue.cfg
@@ -1139,17 +1139,6 @@
         includable_only: true
       }
       builders {
-        name: "chromium/try/linux-warmed"
-        includable_only: true
-      }
-      builders {
-        name: "chromium/try/linux-warmed-orchestrator"
-        experiment_percentage: 5
-        location_regexp: ".*"
-        location_regexp_exclude: ".+/[+]/docs/.+"
-        location_regexp_exclude: ".+/[+]/infra/config/.+"
-      }
-      builders {
         name: "chromium/try/linux-webkit-msan-rel"
         includable_only: true
       }
diff --git a/infra/config/generated/cq-builders.md b/infra/config/generated/cq-builders.md
index 9e3bc856..d268c94 100644
--- a/infra/config/generated/cq-builders.md
+++ b/infra/config/generated/cq-builders.md
@@ -386,6 +386,3 @@
 * [linux-rel-builderful](https://ci.chromium.org/p/chromium/builders/try/linux-rel-builderful) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+linux-rel-builderful)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+linux-rel-builderful))
   * Experiment percentage: 5
 
-* [linux-warmed-orchestrator](https://ci.chromium.org/p/chromium/builders/try/linux-warmed-orchestrator) ([definition](https://cs.chromium.org/search?q=package:%5Echromium$+file:/cq.star$+-file:/beta/+-file:/stable/+linux-warmed-orchestrator)) ([matching builders](https://cs.chromium.org/search?q=+file:trybots.py+linux-warmed-orchestrator))
-  * Experiment percentage: 5
-
diff --git a/infra/config/generated/cr-buildbucket.cfg b/infra/config/generated/cr-buildbucket.cfg
index e157ed56..856ff2b 100644
--- a/infra/config/generated/cr-buildbucket.cfg
+++ b/infra/config/generated/cr-buildbucket.cfg
@@ -24893,60 +24893,6 @@
       }
     }
     builders {
-      name: "try-warmer"
-      swarming_host: "chromium-swarm.appspot.com"
-      swarming_tags: "vpython:native-python-wrapper"
-      dimensions: "builder:try-warmer"
-      dimensions: "cores:8"
-      dimensions: "cpu:x86-64"
-      dimensions: "os:Ubuntu-16.04"
-      dimensions: "pool:luci.chromium.ci"
-      exe {
-        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
-        cipd_version: "refs/heads/master"
-        cmd: "recipes"
-      }
-      properties: "{\"$build/goma\":{\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"chromium.fyi\",\"builder_to_warm\":\"linux-warmed\",\"recipe\":\"chromium/try_warmer\",\"trigger_count\":2}"
-      execution_timeout_secs: 300
-      build_numbers: YES
-      service_account: "chromium-led-tot-warmer@chops-service-accounts.iam.gserviceaccount.com"
-      experiments {
-        key: "chromium.resultdb.result_sink"
-        value: 100
-      }
-      experiments {
-        key: "chromium.resultdb.result_sink.gtests_local"
-        value: 100
-      }
-      experiments {
-        key: "chromium.resultdb.result_sink.junit_tests"
-        value: 100
-      }
-      experiments {
-        key: "luci.use_realms"
-        value: 100
-      }
-      resultdb {
-        enable: true
-        bq_exports {
-          project: "luci-resultdb"
-          dataset: "chromium"
-          table: "ci_test_results"
-          test_results {}
-        }
-        bq_exports {
-          project: "luci-resultdb"
-          dataset: "chromium"
-          table: "gpu_ci_test_results"
-          test_results {
-            predicate {
-              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
-            }
-          }
-        }
-      }
-    }
-    builders {
       name: "win-angle-chromium-x64-builder"
       swarming_host: "chromium-swarm.appspot.com"
       swarming_tags: "vpython:native-python-wrapper"
@@ -41367,123 +41313,6 @@
       }
     }
     builders {
-      name: "linux-warmed"
-      swarming_host: "chromium-swarm.appspot.com"
-      swarming_tags: "vpython:native-python-wrapper"
-      dimensions: "builder:linux-warmed"
-      dimensions: "cores:8"
-      dimensions: "cpu:x86-64"
-      dimensions: "os:Ubuntu-16.04"
-      dimensions: "pool:luci.chromium.try"
-      exe {
-        cipd_package: "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build"
-        cipd_version: "refs/heads/master"
-        cmd: "recipes"
-      }
-      properties: "{\"$build/code_coverage\":{\"use_clang_coverage\":true},\"$build/goma\":{\"enable_ats\":true,\"jobs\":150,\"rpc_extra_params\":\"?prod\",\"server_host\":\"goma.chromium.org\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"tryserver.chromium.linux\",\"recipe\":\"chromium_trybot\"}"
-      execution_timeout_secs: 14400
-      expiration_secs: 7200
-      caches {
-        name: "win_toolchain"
-        path: "win_toolchain"
-      }
-      build_numbers: YES
-      service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
-      task_template_canary_percentage {
-        value: 5
-      }
-      experiments {
-        key: "chromium.resultdb.result_sink"
-        value: 100
-      }
-      experiments {
-        key: "chromium.resultdb.result_sink.junit_tests"
-        value: 100
-      }
-      experiments {
-        key: "luci.use_realms"
-        value: 100
-      }
-      resultdb {
-        enable: true
-        bq_exports {
-          project: "luci-resultdb"
-          dataset: "chromium"
-          table: "try_test_results"
-          test_results {}
-        }
-        bq_exports {
-          project: "luci-resultdb"
-          dataset: "chromium"
-          table: "gpu_try_test_results"
-          test_results {
-            predicate {
-              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
-            }
-          }
-        }
-      }
-    }
-    builders {
-      name: "linux-warmed-orchestrator"
-      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.try"
-      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\",\"use_luci_auth\":true},\"$kitchen\":{\"devshell\":true,\"git_auth\":true},\"$recipe_engine/isolated\":{\"server\":\"https://isolateserver.appspot.com\"},\"builder_group\":\"tryserver.chromium.linux\",\"builder_to_trigger\":{\"builder_group\":\"tryserver.chromium.linux\",\"buildername\":\"linux-warmed\"},\"recipe\":\"chromium/mini_orchestrator\"}"
-      execution_timeout_secs: 14400
-      expiration_secs: 7200
-      caches {
-        name: "win_toolchain"
-        path: "win_toolchain"
-      }
-      build_numbers: YES
-      service_account: "chromium-mini-orchestrator@chops-service-accounts.iam.gserviceaccount.com"
-      task_template_canary_percentage {
-        value: 5
-      }
-      experiments {
-        key: "chromium.resultdb.result_sink"
-        value: 100
-      }
-      experiments {
-        key: "chromium.resultdb.result_sink.junit_tests"
-        value: 100
-      }
-      experiments {
-        key: "luci.use_realms"
-        value: 100
-      }
-      resultdb {
-        enable: true
-        bq_exports {
-          project: "luci-resultdb"
-          dataset: "chromium"
-          table: "try_test_results"
-          test_results {}
-        }
-        bq_exports {
-          project: "luci-resultdb"
-          dataset: "chromium"
-          table: "gpu_try_test_results"
-          test_results {
-            predicate {
-              test_id_regexp: "ninja://(chrome/test:|content/test:fuchsia_)telemetry_gpu_integration_test/.+"
-            }
-          }
-        }
-      }
-    }
-    builders {
       name: "linux-webkit-msan-rel"
       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 4674acfc..d26d870 100644
--- a/infra/config/generated/luci-milo.cfg
+++ b/infra/config/generated/luci-milo.cfg
@@ -690,17 +690,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -1405,17 +1402,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -1725,17 +1719,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -2195,17 +2186,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -2550,17 +2538,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -3049,17 +3034,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -3384,17 +3366,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -3864,17 +3843,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -4214,17 +4190,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -4709,17 +4682,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -5119,17 +5089,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -5558,17 +5525,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -5827,11 +5791,6 @@
     short_name: "sdk14"
   }
   builders {
-    name: "buildbucket/luci.chromium.ci/try-warmer"
-    category: "infra"
-    short_name: "warmer"
-  }
-  builders {
     name: "buildbucket/luci.chromium.ci/VR Linux"
     category: "linux"
   }
@@ -6222,17 +6181,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -6604,17 +6560,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -6995,17 +6948,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -7341,17 +7291,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -8041,17 +7988,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -8441,17 +8385,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -8791,17 +8732,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -9176,17 +9114,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -9485,17 +9420,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -9845,17 +9777,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -10255,17 +10184,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -10590,17 +10516,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -10965,17 +10888,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -11310,17 +11230,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -11722,17 +11639,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -12040,17 +11954,14 @@
       links {
         text: "m86"
         url: "/p/chromium-m86/g/main/console"
-        alt: "LTS-C branch console"
       }
       links {
         text: "m87"
         url: "/p/chromium-m87/g/main/console"
-        alt: "Stable branch console"
       }
       links {
         text: "m88"
         url: "/p/chromium-m88/g/main/console"
-        alt: "Beta branch console"
       }
       links {
         text: "trunk"
@@ -12737,12 +12648,6 @@
     name: "buildbucket/luci.chromium.try/linux-viz-rel"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/linux-warmed"
-  }
-  builders {
-    name: "buildbucket/luci.chromium.try/linux-warmed-orchestrator"
-  }
-  builders {
     name: "buildbucket/luci.chromium.try/linux-webkit-msan-rel"
   }
   builders {
@@ -13597,12 +13502,6 @@
     name: "buildbucket/luci.chromium.try/linux-viz-rel"
   }
   builders {
-    name: "buildbucket/luci.chromium.try/linux-warmed"
-  }
-  builders {
-    name: "buildbucket/luci.chromium.try/linux-warmed-orchestrator"
-  }
-  builders {
     name: "buildbucket/luci.chromium.try/linux-webkit-msan-rel"
   }
   builders {
diff --git a/infra/config/generated/luci-scheduler.cfg b/infra/config/generated/luci-scheduler.cfg
index 2abad2a..1b876b5 100644
--- a/infra/config/generated/luci-scheduler.cfg
+++ b/infra/config/generated/luci-scheduler.cfg
@@ -6281,17 +6281,6 @@
   }
 }
 job {
-  id: "try-warmer"
-  realm: "ci"
-  schedule: "with 2m interval"
-  acl_sets: "ci"
-  buildbucket {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "luci.chromium.ci"
-    builder: "try-warmer"
-  }
-}
-job {
   id: "win-angle-chromium-x64-builder"
   realm: "ci"
   acl_sets: "ci"
diff --git a/infra/config/generated/realms.cfg b/infra/config/generated/realms.cfg
index 96aada3..239e8d3 100644
--- a/infra/config/generated/realms.cfg
+++ b/infra/config/generated/realms.cfg
@@ -57,7 +57,6 @@
     principals: "user:chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
     principals: "user:chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
     principals: "user:chromium-cipd-builder@chops-service-accounts.iam.gserviceaccount.com"
-    principals: "user:chromium-led-tot-warmer@chops-service-accounts.iam.gserviceaccount.com"
     principals: "user:component-mapping-updater@chops-service-accounts.iam.gserviceaccount.com"
   }
   bindings {
@@ -190,7 +189,6 @@
     principals: "project:chromium-m86"
     principals: "project:chromium-m87"
     principals: "project:chromium-m88"
-    principals: "user:chromium-led-tot-warmer@chops-service-accounts.iam.gserviceaccount.com"
     principals: "user:infra-try-recipes-tester@chops-service-accounts.iam.gserviceaccount.com"
   }
 }
@@ -209,7 +207,6 @@
   name: "try"
   bindings {
     role: "role/buildbucket.builderServiceAccount"
-    principals: "user:chromium-mini-orchestrator@chops-service-accounts.iam.gserviceaccount.com"
     principals: "user:chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com"
     principals: "user:chromium-try-gpu-builder@chops-service-accounts.iam.gserviceaccount.com"
   }
@@ -239,7 +236,6 @@
     principals: "group:chromium-led-users"
     principals: "group:project-chromium-mac-arm64-tests-access"
     principals: "group:project-chromium-tryjob-access"
-    principals: "user:chromium-led-tot-warmer@chops-service-accounts.iam.gserviceaccount.com"
     principals: "user:infra-try-recipes-tester@chops-service-accounts.iam.gserviceaccount.com"
   }
 }
diff --git a/infra/config/project.star b/infra/config/project.star
index 744a0c5..bf9609b 100644
--- a/infra/config/project.star
+++ b/infra/config/project.star
@@ -64,7 +64,7 @@
 
 lucicfg.generator(_generate_project_pyl)
 
-def _milestone_details(*, project, ref, channel):
+def _milestone_details(*, project, ref):
     """Define the details for an active milestone.
 
     Args:
@@ -72,13 +72,10 @@
         milestone.
       * ref - The ref in the git repository that contains the code for the
         milestone.
-      * channel - The name of the release channel the milestone is in (used for
-        identifying the milestone in the console header).
     """
     return struct(
         project = project,
         ref = ref,
-        channel = channel,
     )
 
 # The milestone names and branch numbers of branches that we have builders
@@ -91,16 +88,13 @@
     "m86": _milestone_details(
         project = "chromium-m86",
         ref = "refs/branch-heads/4240",
-        channel = "LTS-C",
     ),
     "m87": _milestone_details(
         project = "chromium-m87",
         ref = "refs/branch-heads/4280",
-        channel = "Stable",
     ),
     "m88": _milestone_details(
         project = "chromium-m88",
         ref = "refs/branch-heads/4324",
-        channel = "Beta",
     ),
 }
diff --git a/infra/config/recipes.star b/infra/config/recipes.star
index a394b62..e0d73d95 100644
--- a/infra/config/recipes.star
+++ b/infra/config/recipes.star
@@ -118,14 +118,6 @@
 )
 
 build_recipe(
-    name = "recipe:chromium/mini_orchestrator",
-)
-
-build_recipe(
-    name = "recipe:chromium/try_warmer",
-)
-
-build_recipe(
     name = "recipe:presubmit",
 )
 
diff --git a/infra/config/subprojects/chromium/ci.star b/infra/config/subprojects/chromium/ci.star
index 3698c2c..ff783ef 100644
--- a/infra/config/subprojects/chromium/ci.star
+++ b/infra/config/subprojects/chromium/ci.star
@@ -2861,25 +2861,6 @@
 )
 
 ci.fyi_builder(
-    name = "try-warmer",
-    builderless = False,
-    console_view_entry = consoles.console_view_entry(
-        category = "infra",
-        short_name = "warmer",
-    ),
-    executable = "recipe:chromium/try_warmer",
-    execution_timeout = 5 * time.minute,
-    goma_backend = None,
-    properties = {
-        "builder_to_warm": "linux-warmed",
-        "trigger_count": 2,
-    },
-    schedule = "with 2m interval",
-    service_account = "chromium-led-tot-warmer@chops-service-accounts.iam.gserviceaccount.com",
-    triggered_by = [],
-)
-
-ci.fyi_builder(
     name = "linux-annotator-rel",
     console_view_entry = consoles.console_view_entry(
         category = "network|traffic|annotations",
diff --git a/infra/config/subprojects/chromium/try.star b/infra/config/subprojects/chromium/try.star
index ca78e6c..e6ba275a 100644
--- a/infra/config/subprojects/chromium/try.star
+++ b/infra/config/subprojects/chromium/try.star
@@ -1058,28 +1058,6 @@
     name = "linux-viz-rel",
 )
 
-# crbug.com/1149606: Experimental builder to test pre-warming
-try_.chromium_linux_builder(
-    name = "linux-warmed",
-    builderless = False,
-    goma_jobs = goma.jobs.J150,
-    use_clang_coverage = True,
-)
-
-# crbug.com/1149606: Experimental builder to test pre-warming
-try_.chromium_linux_builder(
-    name = "linux-warmed-orchestrator",
-    executable = "recipe:chromium/mini_orchestrator",
-    properties = {
-        "builder_to_trigger": {
-            "builder_group": "tryserver.chromium.linux",
-            "buildername": "linux-warmed",
-        },
-    },
-    service_account = "chromium-mini-orchestrator@chops-service-accounts.iam.gserviceaccount.com",
-    tryjob = try_.job(experiment_percentage = 5),
-)
-
 try_.chromium_linux_builder(
     name = "linux-webkit-msan-rel",
 )
diff --git a/infra/config/swarming.star b/infra/config/swarming.star
index 9ad0265..ece8877 100644
--- a/infra/config/swarming.star
+++ b/infra/config/swarming.star
@@ -91,10 +91,6 @@
         # An account used by "Build Recipes Tester" builder infra/try bucket
         # used to tests changes to Chromium recipes using LED before commit.
         "infra-try-recipes-tester@chops-service-accounts.iam.gserviceaccount.com",
-
-        # crbug.com/1149606: Used for experimental pre-warming. This account will
-        # run the led-tot-warmer builder in chromium.ci.
-        "chromium-led-tot-warmer@chops-service-accounts.iam.gserviceaccount.com",
     ],
 )
 
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm b/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm
index cd50915..a9937f7 100644
--- a/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm
+++ b/ios/chrome/browser/ui/ntp/new_tab_page_view_controller.mm
@@ -8,6 +8,7 @@
 
 #import "base/check.h"
 #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizing.h"
+#import "ios/chrome/browser/ui/content_suggestions/ntp_home_constant.h"
 #import "ios/chrome/browser/ui/ntp/discover_feed_wrapper_view_controller.h"
 #import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h"
 #import "ios/chrome/browser/ui/util/uikit_ui_util.h"
@@ -96,6 +97,8 @@
       setStyle:OverscrollStyle::NTP_NON_INCOGNITO];
   self.overscrollActionsController.delegate = self.overscrollDelegate;
   [self updateOverscrollActionsState];
+
+  self.view.backgroundColor = ntp_home::kNTPBackgroundColor();
 }
 
 - (void)viewDidLayoutSubviews {
diff --git a/ipc/ipc_message_start.h b/ipc/ipc_message_start.h
index e401b61..22b0088 100644
--- a/ipc/ipc_message_start.h
+++ b/ipc/ipc_message_start.h
@@ -34,7 +34,6 @@
   MediaPlayerDelegateMsgStart,
   ExtensionWorkerMsgStart,
   SubresourceFilterMsgStart,
-  UnfreezableFrameMsgStart,
   LastIPCMsgStart  // Must come last.
 };
 
diff --git a/ipc/trace_ipc_message.cc b/ipc/trace_ipc_message.cc
index 27686aa..31cfeb0 100644
--- a/ipc/trace_ipc_message.cc
+++ b/ipc/trace_ipc_message.cc
@@ -83,9 +83,6 @@
     case ExtensionWorkerMsgStart:
       message_class = ChromeLegacyIpc::CLASS_EXTENSION_WORKER;
       break;
-    case UnfreezableFrameMsgStart:
-      message_class = ChromeLegacyIpc::CLASS_UNFREEZABLE_FRAME;
-      break;
   }
   legacy_ipc->set_message_class(message_class);
   legacy_ipc->set_message_line(IPC_MESSAGE_ID_LINE(message_id));
diff --git a/media/gpu/ipc/service/picture_buffer_manager.cc b/media/gpu/ipc/service/picture_buffer_manager.cc
index 8e32c71..04981b8e 100644
--- a/media/gpu/ipc/service/picture_buffer_manager.cc
+++ b/media/gpu/ipc/service/picture_buffer_manager.cc
@@ -13,6 +13,7 @@
 #include "base/logging.h"
 #include "base/synchronization/lock.h"
 #include "base/thread_annotations.h"
+#include "components/viz/common/resources/resource_format_utils.h"
 #include "gpu/command_buffer/common/mailbox_holder.h"
 #include "media/base/video_util.h"
 
@@ -83,13 +84,11 @@
     DCHECK(planes);
     DCHECK_LE(planes, static_cast<uint32_t>(VideoFrame::kMaxPlanes));
 
-    if (!use_shared_image) {
-      // TODO(sandersd): Consider requiring that CreatePictureBuffers() is
-      // called with the context current.
-      if (!command_buffer_helper_->MakeContextCurrent()) {
-        DVLOG(1) << "Failed to make context current";
-        return std::vector<PictureBuffer>();
-      }
+    // TODO(sandersd): Consider requiring that CreatePictureBuffers() is
+    // called with the context current.
+    if (!command_buffer_helper_->MakeContextCurrent()) {
+      DVLOG(1) << "Failed to make context current";
+      return std::vector<PictureBuffer>();
     }
 
     std::vector<PictureBuffer> picture_buffers;
@@ -97,25 +96,34 @@
       PictureBufferData picture_data = {pixel_format, texture_size,
                                         use_shared_image};
 
-      if (!use_shared_image) {
-        for (uint32_t j = 0; j < planes; j++) {
-          // Create a texture for this plane.
-          GLuint service_id = command_buffer_helper_->CreateTexture(
-              texture_target, GL_RGBA, texture_size.width(),
-              texture_size.height(), GL_RGBA, GL_UNSIGNED_BYTE);
-          DCHECK(service_id);
-          picture_data.service_ids.push_back(service_id);
+      for (uint32_t j = 0; j < planes; j++) {
+        // Use the plane size for texture-backed shared and non-shared images.
+        // Adjust the size by the subsampling factor.
+        const size_t width =
+            VideoFrame::Columns(j, pixel_format, texture_size.width());
+        const size_t height =
+            VideoFrame::Rows(j, pixel_format, texture_size.height());
 
-          // The texture is not cleared yet, but it will be before the VDA
-          // outputs it. Rather than requiring output to happen on the GPU
-          // thread, mark the texture as cleared immediately.
-          command_buffer_helper_->SetCleared(service_id);
+        picture_data.texture_sizes.emplace_back(width, height);
 
-          // Generate a mailbox while we are still on the GPU thread.
-          picture_data.mailbox_holders[j] = gpu::MailboxHolder(
-              command_buffer_helper_->CreateMailbox(service_id),
-              gpu::SyncToken(), texture_target);
-        }
+        // Create a texture for this plane.
+        // When using shared images, the VDA might not require GL textures to
+        // exist.
+        // TODO(crbug.com/1011555): Do not allocate GL textures when unused.
+        GLuint service_id = command_buffer_helper_->CreateTexture(
+            texture_target, GL_RGBA, width, height, GL_RGBA, GL_UNSIGNED_BYTE);
+        DCHECK(service_id);
+        picture_data.service_ids.push_back(service_id);
+
+        // The texture is not cleared yet, but it will be before the VDA
+        // outputs it. Rather than requiring output to happen on the GPU
+        // thread, mark the texture as cleared immediately.
+        command_buffer_helper_->SetCleared(service_id);
+
+        // Generate a mailbox while we are still on the GPU thread.
+        picture_data.mailbox_holders[j] = gpu::MailboxHolder(
+            command_buffer_helper_->CreateMailbox(service_id), gpu::SyncToken(),
+            texture_target);
       }
 
       // Generate a picture buffer ID and record the picture buffer.
@@ -132,8 +140,9 @@
       // TODO(sandersd): Refactor the bind image callback to use service IDs so
       // that we can get rid of the client IDs altogether.
       picture_buffers.emplace_back(
-          picture_buffer_id, texture_size, picture_data.service_ids,
-          picture_data.service_ids, texture_target, pixel_format);
+          picture_buffer_id, texture_size, picture_data.texture_sizes,
+          picture_data.service_ids, picture_data.service_ids, texture_target,
+          pixel_format);
     }
     return picture_buffers;
   }
@@ -216,12 +225,12 @@
 
     // If this |picture| has a SharedImage, then keep a reference to the
     // SharedImage in |picture_buffer_data| and update the gpu::MailboxHolder.
-    DCHECK_EQ(picture_buffer_data.use_shared_image,
-              !!picture.scoped_shared_image());
-    if (auto scoped_shared_image = picture.scoped_shared_image()) {
-      picture_buffer_data.scoped_shared_image = scoped_shared_image;
-      picture_buffer_data.mailbox_holders[0] =
-          scoped_shared_image->GetMailboxHolder();
+    for (uint32_t i = 0; i < VideoFrame::kMaxPlanes; i++) {
+      if (auto scoped_shared_image = picture.scoped_shared_image(i)) {
+        picture_buffer_data.scoped_shared_images.push_back(scoped_shared_image);
+        picture_buffer_data.mailbox_holders[i] =
+            scoped_shared_image->GetMailboxHolder();
+      }
     }
 
     // Create and return a VideoFrame for the picture buffer.
@@ -313,7 +322,6 @@
     DCHECK(gpu_task_runner_->BelongsToCurrentThread());
 
     std::vector<GLuint> service_ids;
-    scoped_refptr<Picture::ScopedSharedImage> scoped_shared_image;
     {
       base::AutoLock lock(picture_buffers_lock_);
       const auto& it = picture_buffers_.find(picture_buffer_id);
@@ -321,16 +329,9 @@
       DCHECK(it->second.dismissed);
       DCHECK(!it->second.IsInUse());
       service_ids = std::move(it->second.service_ids);
-      scoped_shared_image = std::move(it->second.scoped_shared_image);
       picture_buffers_.erase(it);
     }
 
-    // If this PictureBuffer is using a SharedImage, let it fall out of scope.
-    if (scoped_shared_image) {
-      DCHECK(service_ids.empty());
-      return;
-    }
-
     if (!command_buffer_helper_->MakeContextCurrent())
       return;
 
@@ -351,7 +352,8 @@
     bool use_shared_image = false;
     std::vector<GLuint> service_ids;
     gpu::MailboxHolder mailbox_holders[VideoFrame::kMaxPlanes];
-    scoped_refptr<Picture::ScopedSharedImage> scoped_shared_image;
+    std::vector<gfx::Size> texture_sizes;
+    std::vector<scoped_refptr<Picture::ScopedSharedImage>> scoped_shared_images;
     bool dismissed = false;
 
     // The same picture buffer can be output from the VDA multiple times
diff --git a/media/gpu/ipc/service/vda_video_decoder.cc b/media/gpu/ipc/service/vda_video_decoder.cc
index 820ab74a..c2616e19 100644
--- a/media/gpu/ipc/service/vda_video_decoder.cc
+++ b/media/gpu/ipc/service/vda_video_decoder.cc
@@ -768,6 +768,10 @@
   return command_buffer_helper_->GetSharedImageStub();
 }
 
+CommandBufferHelper* VdaVideoDecoder::GetCommandBufferHelper() const {
+  return command_buffer_helper_.get();
+}
+
 void VdaVideoDecoder::NotifyErrorOnParentThread(
     VideoDecodeAccelerator::Error error) {
   DVLOG(1) << __func__ << "(" << error << ")";
diff --git a/media/gpu/ipc/service/vda_video_decoder.h b/media/gpu/ipc/service/vda_video_decoder.h
index 37746ca..138cc57 100644
--- a/media/gpu/ipc/service/vda_video_decoder.h
+++ b/media/gpu/ipc/service/vda_video_decoder.h
@@ -129,6 +129,7 @@
   void NotifyResetDone() override;
   void NotifyError(VideoDecodeAccelerator::Error error) override;
   gpu::SharedImageStub* GetSharedImageStub() const override;
+  CommandBufferHelper* GetCommandBufferHelper() const override;
 
   // Tasks and thread hopping.
   static void CleanupOnGpuThread(std::unique_ptr<VdaVideoDecoder>);
diff --git a/media/gpu/windows/dxva_picture_buffer_win.cc b/media/gpu/windows/dxva_picture_buffer_win.cc
index e3452d2..aee9e03 100644
--- a/media/gpu/windows/dxva_picture_buffer_win.cc
+++ b/media/gpu/windows/dxva_picture_buffer_win.cc
@@ -494,6 +494,8 @@
   DCHECK_EQ(BOUND, state_);
   state_ = IN_CLIENT;
 
+  shared_images_.resize(picture_buffer_.service_texture_ids().size());
+
   current_d3d_sample_ = sample;
   EGLDisplay egl_display = gl::GLSurfaceEGL::GetHardwareDisplay();
 
diff --git a/media/gpu/windows/dxva_picture_buffer_win.h b/media/gpu/windows/dxva_picture_buffer_win.h
index 891e763..c14b3c8 100644
--- a/media/gpu/windows/dxva_picture_buffer_win.h
+++ b/media/gpu/windows/dxva_picture_buffer_win.h
@@ -68,6 +68,31 @@
     color_space_ = color_space;
   }
 
+  const std::vector<scoped_refptr<Picture::ScopedSharedImage>>& shared_images()
+      const {
+    return shared_images_;
+  }
+
+  void set_shared_image(
+      size_t plane,
+      scoped_refptr<Picture::ScopedSharedImage> shared_image) {
+    DCHECK(plane < shared_images_.size());
+    shared_images_[plane] = std::move(shared_image);
+  }
+
+  // Picture buffer data used to create a shared image backing.
+  const PictureBuffer::TextureIds& service_texture_ids() const {
+    return picture_buffer_.service_texture_ids();
+  }
+
+  gfx::Size texture_size(size_t plane) {
+    return picture_buffer_.texture_size(plane);
+  }
+
+  VideoPixelFormat pixel_format() const {
+    return picture_buffer_.pixel_format();
+  }
+
   // Returns true if these could in theory be used as an overlay. May
   // still be drawn using GL depending on the scene and precise hardware
   // support.
@@ -96,6 +121,8 @@
   gfx::ColorSpace color_space_;
   scoped_refptr<gl::GLImage> gl_image_;
 
+  std::vector<scoped_refptr<Picture::ScopedSharedImage>> shared_images_;
+
   DISALLOW_COPY_AND_ASSIGN(DXVAPictureBuffer);
 };
 
diff --git a/media/gpu/windows/dxva_video_decode_accelerator_win.cc b/media/gpu/windows/dxva_video_decode_accelerator_win.cc
index 6a88f172..a2768d85 100644
--- a/media/gpu/windows/dxva_video_decode_accelerator_win.cc
+++ b/media/gpu/windows/dxva_video_decode_accelerator_win.cc
@@ -21,6 +21,7 @@
 #include "base/atomicops.h"
 #include "base/base_paths_win.h"
 #include "base/bind.h"
+#include "base/bind_post_task.h"
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/file_version_info.h"
@@ -38,12 +39,19 @@
 #include "base/win/scoped_co_mem.h"
 #include "base/win/windows_version.h"
 #include "build/build_config.h"
+#include "components/viz/common/resources/resource_format_utils.h"
+#include "gpu/command_buffer/common/shared_image_usage.h"
+#include "gpu/command_buffer/service/shared_image_backing_d3d.h"
+#include "gpu/command_buffer/service/shared_image_factory.h"
 #include "gpu/config/gpu_driver_bug_workarounds.h"
 #include "gpu/config/gpu_preferences.h"
+#include "gpu/ipc/service/shared_image_stub.h"
 #include "media/base/media_log.h"
 #include "media/base/media_switches.h"
+#include "media/base/video_frame.h"
 #include "media/base/win/mf_helpers.h"
 #include "media/filters/vp9_parser.h"
+#include "media/gpu/command_buffer_helper.h"
 #include "media/gpu/windows/d3d11_video_device_format_support.h"
 #include "media/gpu/windows/dxva_picture_buffer_win.h"
 #include "media/gpu/windows/supported_profile_helpers.h"
@@ -59,6 +67,7 @@
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_fence.h"
+#include "ui/gl/gl_image_dxgi.h"
 #include "ui/gl/gl_surface_egl.h"
 #include "ui/gl/gl_switches.h"
 
@@ -172,6 +181,36 @@
 
 namespace media {
 
+bool VideoPixelFormatToVizFormat(
+    VideoPixelFormat pixel_format,
+    size_t textures_per_picture,
+    std::array<viz::ResourceFormat, VideoFrame::kMaxPlanes>& texture_formats) {
+  switch (pixel_format) {
+    case PIXEL_FORMAT_ARGB:
+    case PIXEL_FORMAT_XRGB:
+    case PIXEL_FORMAT_ABGR:
+    case PIXEL_FORMAT_BGRA:
+      DCHECK_EQ(textures_per_picture, 1u);
+      texture_formats[0] =
+          (pixel_format == PIXEL_FORMAT_ABGR) ? viz::RGBA_8888 : viz::BGRA_8888;
+      return true;
+    case PIXEL_FORMAT_NV12:
+      DCHECK_EQ(textures_per_picture, 2u);
+      texture_formats[0] = viz::RED_8;  // Y
+      texture_formats[1] = viz::RG_88;  // UV
+      return true;
+    case PIXEL_FORMAT_P016LE:
+      // TODO(crbug.com/1011555): P010 formats are not fully supported.
+      // The required Viz formats (viz::R16_EXT and viz::RG16_EXT) are not yet
+      // supported.
+      DCHECK_EQ(textures_per_picture, 2u);
+      return false;
+    default:  // Unsupported
+      NOTREACHED();
+      return false;
+  }
+}
+
 constexpr VideoCodecProfile kSupportedProfiles[] = {
     H264PROFILE_BASELINE,    H264PROFILE_MAIN,        H264PROFILE_HIGH,
     VP8PROFILE_ANY,          VP9PROFILE_PROFILE0,     VP9PROFILE_PROFILE2,
@@ -1325,6 +1364,13 @@
   return GL_BGRA_EXT;
 }
 
+bool DXVAVideoDecodeAccelerator::SupportsSharedImagePictureBuffers() const {
+  // Shared image is needed to display overlays which can be used directly
+  // by the video processor.
+  // TODO(crbug.com/1011555): Support for non-bind cases.
+  return GetPictureBufferMechanism() == PictureBufferMechanism::BIND;
+}
+
 // static
 VideoDecodeAccelerator::SupportedProfiles
 DXVAVideoDecodeAccelerator::GetSupportedProfiles(
@@ -2118,12 +2164,18 @@
     int input_buffer_id,
     const gfx::Rect& visible_rect,
     const gfx::ColorSpace& color_space,
-    bool allow_overlay) {
+    bool allow_overlay,
+    std::vector<scoped_refptr<Picture::ScopedSharedImage>> shared_images) {
   DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
   // This task could execute after the decoder has been torn down.
   if (GetState() != kUninitialized && client_) {
     Picture picture(picture_buffer_id, input_buffer_id, visible_rect,
                     color_space, allow_overlay);
+
+    for (uint32_t i = 0; i < shared_images.size(); i++) {
+      picture.set_scoped_shared_image(shared_images[i], i);
+    }
+
     client_->PictureReady(picture);
   }
 }
@@ -2591,13 +2643,100 @@
 
   DCHECK(!output_picture_buffers_.empty());
 
+  // BindSampleToTexture configures GLImage with the DX11 output texture.
+  // The DX11 texture is then accessed through the GLImage to create a shared
+  // image backing below.
   bool result = picture_buffer->BindSampleToTexture(this, sample);
-  RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface",
+  RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to bind sample to texture",
                                PLATFORM_FAILURE, );
 
+  // Create the DX11 texture backed shared images (texture per plane).
+  std::vector<scoped_refptr<Picture::ScopedSharedImage>> scoped_shared_images;
+  if (SupportsSharedImagePictureBuffers()) {
+    gl::GLImageDXGI* gl_image_dxgi =
+        gl::GLImageDXGI::FromGLImage(picture_buffer->gl_image().get());
+    DCHECK(gl_image_dxgi);
+
+    const size_t textures_per_picture =
+        picture_buffer->service_texture_ids().size();
+
+    // Get the viz resource format per texture.
+    std::array<viz::ResourceFormat, VideoFrame::kMaxPlanes> viz_formats;
+    {
+      const bool result = VideoPixelFormatToVizFormat(
+          picture_buffer->pixel_format(), textures_per_picture, viz_formats);
+      RETURN_AND_NOTIFY_ON_FAILURE(
+          result, "Could not convert pixel format to viz format",
+          PLATFORM_FAILURE, );
+    }
+
+    CommandBufferHelper* helper = client_->GetCommandBufferHelper();
+    DCHECK(helper);
+
+    for (uint32_t texture_idx = 0; texture_idx < textures_per_picture;
+         texture_idx++) {
+      // Usage flags to allow the display compositor to draw from it, video
+      // to decode, and allow webgl/canvas access.
+      constexpr uint32_t shared_image_usage =
+          gpu::SHARED_IMAGE_USAGE_VIDEO_DECODE | gpu::SHARED_IMAGE_USAGE_GLES2 |
+          gpu::SHARED_IMAGE_USAGE_RASTER | gpu::SHARED_IMAGE_USAGE_DISPLAY |
+          gpu::SHARED_IMAGE_USAGE_SCANOUT;
+
+      // Create a shared image
+      // TODO(crbug.com/1011555): Need key shared mutex if shared image is ever
+      // used by another device.
+      scoped_refptr<gpu::gles2::TexturePassthrough> gl_texture =
+          gpu::gles2::TexturePassthrough::CheckedCast(helper->GetTexture(
+              picture_buffer->service_texture_ids()[texture_idx]));
+
+      // Create a new shared image mailbox. The existing mailbox belonging to
+      // this |picture_buffer| will be updated when the video frame is created.
+      const auto& mailbox = gpu::Mailbox::GenerateForSharedImage();
+
+      auto shared_image = std::make_unique<gpu::SharedImageBackingD3D>(
+          mailbox, viz_formats[texture_idx],
+          picture_buffer->texture_size(texture_idx),
+          picture_buffer->color_space(), kTopLeft_GrSurfaceOrigin,
+          kPremul_SkAlphaType, shared_image_usage,
+          /*swap_chain=*/nullptr, std::move(gl_texture),
+          picture_buffer->gl_image(),
+          /*buffer_index=*/0, gl_image_dxgi->texture(),
+          base::win::ScopedHandle(),
+          /*dxgi_keyed_mutex=*/nullptr);
+
+      // Caller is assumed to provide cleared d3d textures.
+      shared_image->SetCleared();
+
+      gpu::SharedImageStub* shared_image_stub = client_->GetSharedImageStub();
+      DCHECK(shared_image_stub);
+      const bool success = shared_image_stub->factory()->RegisterBacking(
+          std::move(shared_image), /* legacy_mailbox */ true);
+      if (!success) {
+        RETURN_AND_NOTIFY_ON_FAILURE(false, "Failed to register shared image",
+                                     PLATFORM_FAILURE, );
+      }
+
+      auto destroy_shared_image_callback = base::BindPostTask(
+          main_thread_task_runner_,
+          base::BindOnce(
+              shared_image_stub->GetSharedImageDestructionCallback(mailbox),
+              gpu::SyncToken()));
+
+      // Wrap the factory ref with a scoped shared image. The factory ref
+      // is used instead of requiring a destruction call-back.
+      auto scoped_shared_image =
+          base::MakeRefCounted<Picture::ScopedSharedImage>(
+              mailbox, GetTextureTarget(),
+              std::move(destroy_shared_image_callback));
+
+      scoped_shared_images.push_back(std::move(scoped_shared_image));
+    }
+  }
+
   NotifyPictureReady(
       picture_buffer->id(), input_buffer_id, picture_buffer->visible_rect(),
-      picture_buffer->color_space(), picture_buffer->AllowOverlay());
+      picture_buffer->color_space(), picture_buffer->AllowOverlay(),
+      std::move(scoped_shared_images));
 
   {
     base::AutoLock lock(decoder_lock_);
diff --git a/media/gpu/windows/dxva_video_decode_accelerator_win.h b/media/gpu/windows/dxva_video_decode_accelerator_win.h
index 3cb1047..30d7d6e 100644
--- a/media/gpu/windows/dxva_video_decode_accelerator_win.h
+++ b/media/gpu/windows/dxva_video_decode_accelerator_win.h
@@ -112,6 +112,7 @@
       const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner)
       override;
   GLenum GetSurfaceInternalFormat() const override;
+  bool SupportsSharedImagePictureBuffers() const override;
 
   static VideoDecodeAccelerator::SupportedProfiles GetSupportedProfiles(
       const gpu::GpuPreferences& gpu_preferences,
@@ -248,7 +249,9 @@
                           int input_buffer_id,
                           const gfx::Rect& visible_rect,
                           const gfx::ColorSpace& color_space,
-                          bool allow_overlay);
+                          bool allow_overlay,
+                          std::vector<scoped_refptr<Picture::ScopedSharedImage>>
+                              shared_images = {});
 
   // Sends pending input buffer processed acks to the client if we don't have
   // output samples waiting to be processed.
diff --git a/media/video/picture.cc b/media/video/picture.cc
index 5763f3b..8e19158 100644
--- a/media/video/picture.cc
+++ b/media/video/picture.cc
@@ -53,17 +53,37 @@
   DCHECK_EQ(client_texture_ids.size(), texture_mailboxes.size());
 }
 
+PictureBuffer::PictureBuffer(int32_t id,
+                             const gfx::Size& size,
+                             const TextureSizes& texture_sizes,
+                             const TextureIds& client_texture_ids,
+                             const TextureIds& service_texture_ids,
+                             uint32_t texture_target,
+                             VideoPixelFormat pixel_format)
+    : id_(id),
+      size_(size),
+      texture_sizes_(texture_sizes),
+      client_texture_ids_(client_texture_ids),
+      service_texture_ids_(service_texture_ids),
+      texture_target_(texture_target),
+      pixel_format_(pixel_format) {
+  // We either not have client texture ids at all, or if we do, then their
+  // number must be the same as the number of service texture ids.
+  DCHECK(client_texture_ids_.empty() ||
+         client_texture_ids_.size() == service_texture_ids_.size());
+}
+
 PictureBuffer::PictureBuffer(const PictureBuffer& other) = default;
 
 PictureBuffer::~PictureBuffer() = default;
 
-gpu::Mailbox PictureBuffer::texture_mailbox(size_t plane) const {
-  if (plane >= texture_mailboxes_.size()) {
-    LOG(ERROR) << "No mailbox for plane " << plane;
-    return gpu::Mailbox();
+gfx::Size PictureBuffer::texture_size(size_t plane) const {
+  if (plane >= texture_sizes_.size()) {
+    LOG(ERROR) << "Missing texture size for plane " << plane;
+    return gfx::Size();
   }
 
-  return texture_mailboxes_[plane];
+  return texture_sizes_[plane];
 }
 
 Picture::Picture(int32_t picture_buffer_id,
diff --git a/media/video/picture.h b/media/video/picture.h
index 3ec0a1f8..0b2173d 100644
--- a/media/video/picture.h
+++ b/media/video/picture.h
@@ -13,6 +13,7 @@
 #include "base/memory/ref_counted.h"
 #include "gpu/command_buffer/common/mailbox_holder.h"
 #include "media/base/media_export.h"
+#include "media/base/video_frame.h"
 #include "media/base/video_types.h"
 #include "ui/gfx/color_space.h"
 #include "ui/gfx/geometry/rect.h"
@@ -25,6 +26,7 @@
 class MEDIA_EXPORT PictureBuffer {
  public:
   using TextureIds = std::vector<uint32_t>;
+  using TextureSizes = std::vector<gfx::Size>;
 
   PictureBuffer(int32_t id, const gfx::Size& size);
   PictureBuffer(int32_t id,
@@ -42,6 +44,13 @@
                 const std::vector<gpu::Mailbox>& texture_mailboxes,
                 uint32_t texture_target,
                 VideoPixelFormat pixel_format);
+  PictureBuffer(int32_t id,
+                const gfx::Size& size,
+                const TextureSizes& texture_sizes,
+                const TextureIds& client_texture_ids,
+                const TextureIds& service_texture_ids,
+                uint32_t texture_target,
+                VideoPixelFormat pixel_format);
   PictureBuffer(const PictureBuffer& other);
   ~PictureBuffer();
 
@@ -64,11 +73,12 @@
 
   VideoPixelFormat pixel_format() const { return pixel_format_; }
 
-  gpu::Mailbox texture_mailbox(size_t plane) const;
+  gfx::Size texture_size(size_t plane) const;
 
  private:
   int32_t id_;
   gfx::Size size_;
+  TextureSizes texture_sizes_;
   TextureIds client_texture_ids_;
   TextureIds service_texture_ids_;
   std::vector<gpu::Mailbox> texture_mailboxes_;
@@ -151,11 +161,16 @@
   }
 
   void set_scoped_shared_image(
-      scoped_refptr<ScopedSharedImage> scoped_shared_image) {
-    scoped_shared_image_ = scoped_shared_image;
+      scoped_refptr<ScopedSharedImage> scoped_shared_image,
+      uint32_t plane = 0) {
+    DCHECK(plane < scoped_shared_images_.size());
+    scoped_shared_images_[plane] = scoped_shared_image;
   }
-  scoped_refptr<ScopedSharedImage> scoped_shared_image() const {
-    return scoped_shared_image_;
+
+  scoped_refptr<ScopedSharedImage> scoped_shared_image(
+      uint32_t plane = 0) const {
+    DCHECK(plane < scoped_shared_images_.size());
+    return scoped_shared_images_[plane];
   }
 
  private:
@@ -168,7 +183,8 @@
   bool size_changed_;
   bool texture_owner_;
   bool wants_promotion_hint_;
-  scoped_refptr<ScopedSharedImage> scoped_shared_image_;
+  std::array<scoped_refptr<ScopedSharedImage>, VideoFrame::kMaxPlanes>
+      scoped_shared_images_;
 };
 
 }  // namespace media
diff --git a/media/video/video_decode_accelerator.cc b/media/video/video_decode_accelerator.cc
index b15a8aa..c7a506de 100644
--- a/media/video/video_decode_accelerator.cc
+++ b/media/video/video_decode_accelerator.cc
@@ -71,6 +71,11 @@
   return nullptr;
 }
 
+CommandBufferHelper* VideoDecodeAccelerator::Client::GetCommandBufferHelper()
+    const {
+  return nullptr;
+}
+
 VideoDecodeAccelerator::~VideoDecodeAccelerator() = default;
 
 void VideoDecodeAccelerator::Decode(scoped_refptr<DecoderBuffer> buffer,
diff --git a/media/video/video_decode_accelerator.h b/media/video/video_decode_accelerator.h
index 8f712d8..3d86134 100644
--- a/media/video/video_decode_accelerator.h
+++ b/media/video/video_decode_accelerator.h
@@ -38,6 +38,8 @@
 
 namespace media {
 
+class CommandBufferHelper;
+
 // Video decoder interface.
 // This interface is extended by the various components that ultimately
 // implement the backend of PPB_VideoDecoder_Dev.
@@ -262,6 +264,10 @@
     // Default implementation returns nullptr.
     virtual gpu::SharedImageStub* GetSharedImageStub() const;
 
+    // Return the CommandBufferHelper through which GL passthrough textures may
+    // be created. Default implementation returns nullptr.
+    virtual CommandBufferHelper* GetCommandBufferHelper() const;
+
    protected:
     virtual ~Client() {}
   };
diff --git a/net/base/isolation_info.cc b/net/base/isolation_info.cc
index 86f431e..e51644b2 100644
--- a/net/base/isolation_info.cc
+++ b/net/base/isolation_info.cc
@@ -209,6 +209,16 @@
           party_context_ == other.party_context_);
 }
 
+IsolationInfo IsolationInfo::ToDoUseTopFrameOriginAsWell(
+    const url::Origin& incorrectly_used_frame_origin) {
+  return IsolationInfo(
+      RequestType::kOther, incorrectly_used_frame_origin,
+      incorrectly_used_frame_origin,
+      SiteForCookies::FromOrigin(incorrectly_used_frame_origin),
+      false /* opaque_and_non_transient */,
+      std::set<SchemefulSite>() /* party_context */);
+}
+
 IsolationInfo::IsolationInfo(
     RequestType request_type,
     const base::Optional<url::Origin>& top_frame_origin,
diff --git a/net/base/isolation_info.h b/net/base/isolation_info.h
index 86a6a52..28d6b1c 100644
--- a/net/base/isolation_info.h
+++ b/net/base/isolation_info.h
@@ -148,6 +148,14 @@
   // unmodified.
   IsolationInfo CreateForRedirect(const url::Origin& new_origin) const;
 
+  // Intended for temporary use in locations that should be using main frame and
+  // frame origin, but are currently only using frame origin, because the
+  // creating object may be shared across main frame objects. Having a special
+  // constructor for these methods makes it easier to keep track of locating
+  // callsites that need to have their IsolationInfo filled in.
+  static IsolationInfo ToDoUseTopFrameOriginAsWell(
+      const url::Origin& incorrectly_used_frame_origin);
+
   RequestType request_type() const { return request_type_; }
 
   bool IsEmpty() const { return !top_frame_origin_; }
diff --git a/pdf/document_metadata.h b/pdf/document_metadata.h
index e1ad46d..c1af1bb 100644
--- a/pdf/document_metadata.h
+++ b/pdf/document_metadata.h
@@ -30,8 +30,8 @@
 // dictionary (see section 14.3.3 "Document Information Dictionary" of the ISO
 // 32000-1 standard), as well as other properties about the file.
 // TODO(crbug.com/93619): Finish adding information dictionary fields like
-// `keywords`, `creation_date`, and `mod_date`. Also add fields like
-// `size_bytes` and `is_encrypted`.
+// `creation_date` and `mod_date`. Also add fields like `size_bytes` and
+// `is_encrypted`.
 struct DocumentMetadata {
   DocumentMetadata();
   DocumentMetadata(const DocumentMetadata&) = delete;
@@ -53,6 +53,9 @@
   // The document's subject.
   std::string subject;
 
+  // The document's keywords.
+  std::string keywords;
+
   // The name of the application that created the original document.
   std::string creator;
 
diff --git a/pdf/out_of_process_instance.cc b/pdf/out_of_process_instance.cc
index 6acb5e0..7bcc606 100644
--- a/pdf/out_of_process_instance.cc
+++ b/pdf/out_of_process_instance.cc
@@ -136,6 +136,7 @@
 constexpr char kJSTitle[] = "title";
 constexpr char kJSAuthor[] = "author";
 constexpr char kJSSubject[] = "subject";
+constexpr char kJSKeywords[] = "keywords";
 constexpr char kJSCreator[] = "creator";
 constexpr char kJSProducer[] = "producer";
 constexpr char kJSCanSerializeDocument[] = "canSerializeDocument";
@@ -2442,6 +2443,11 @@
   if (!document_metadata.subject.empty())
     metadata_data.Set(pp::Var(kJSSubject), pp::Var(document_metadata.subject));
 
+  if (!document_metadata.keywords.empty()) {
+    metadata_data.Set(pp::Var(kJSKeywords),
+                      pp::Var(document_metadata.keywords));
+  }
+
   if (!document_metadata.creator.empty())
     metadata_data.Set(pp::Var(kJSCreator), pp::Var(document_metadata.creator));
 
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc
index 465d70da..12f34d4b 100644
--- a/pdf/pdfium/pdfium_engine.cc
+++ b/pdf/pdfium/pdfium_engine.cc
@@ -3957,6 +3957,7 @@
   doc_metadata_.title = GetTrimmedMetadataByField("Title");
   doc_metadata_.author = GetTrimmedMetadataByField("Author");
   doc_metadata_.subject = GetTrimmedMetadataByField("Subject");
+  doc_metadata_.keywords = GetTrimmedMetadataByField("Keywords");
   doc_metadata_.creator = GetTrimmedMetadataByField("Creator");
   doc_metadata_.producer = GetTrimmedMetadataByField("Producer");
 }
diff --git a/pdf/pdfium/pdfium_engine_unittest.cc b/pdf/pdfium/pdfium_engine_unittest.cc
index f6a47b3..e0aedc04 100644
--- a/pdf/pdfium/pdfium_engine_unittest.cc
+++ b/pdf/pdfium/pdfium_engine_unittest.cc
@@ -353,6 +353,7 @@
   EXPECT_EQ("Sample PDF Document Info", doc_metadata.title);
   EXPECT_EQ("Chromium Authors", doc_metadata.author);
   EXPECT_EQ("Testing", doc_metadata.subject);
+  EXPECT_EQ("testing,chromium,pdfium,document,info", doc_metadata.keywords);
   EXPECT_EQ("Your Preferred Text Editor", doc_metadata.creator);
   EXPECT_EQ("fixup_pdf_template.py", doc_metadata.producer);
 }
@@ -370,6 +371,7 @@
   EXPECT_THAT(doc_metadata.title, IsEmpty());
   EXPECT_THAT(doc_metadata.author, IsEmpty());
   EXPECT_THAT(doc_metadata.subject, IsEmpty());
+  EXPECT_THAT(doc_metadata.keywords, IsEmpty());
   EXPECT_THAT(doc_metadata.creator, IsEmpty());
   EXPECT_THAT(doc_metadata.producer, IsEmpty());
 }
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
index afaf375..fb5b459 100644
--- a/services/network/network_context.cc
+++ b/services/network/network_context.cc
@@ -605,9 +605,7 @@
 void NetworkContext::GetRestrictedCookieManager(
     mojo::PendingReceiver<mojom::RestrictedCookieManager> receiver,
     mojom::RestrictedCookieManagerRole role,
-    const url::Origin& origin,
-    const net::SiteForCookies& site_for_cookies,
-    const url::Origin& top_frame_origin,
+    const net::IsolationInfo& isolation_info,
     mojo::PendingRemote<mojom::CookieAccessObserver> cookie_observer) {
   mojom::NetworkServiceClient* network_service_client = nullptr;
   if (network_service())
@@ -616,8 +614,8 @@
   restricted_cookie_manager_receivers_.Add(
       std::make_unique<RestrictedCookieManager>(
           role, url_request_context_->cookie_store(),
-          &cookie_manager_->cookie_settings(), origin, site_for_cookies,
-          top_frame_origin, std::move(cookie_observer)),
+          &cookie_manager_->cookie_settings(), isolation_info,
+          std::move(cookie_observer)),
       std::move(receiver));
 }
 
diff --git a/services/network/network_context.h b/services/network/network_context.h
index 90391023..0b9c2c4 100644
--- a/services/network/network_context.h
+++ b/services/network/network_context.h
@@ -73,6 +73,7 @@
 class CertNetFetcherURLRequest;
 class CertVerifier;
 class HostPortPair;
+class IsolationInfo;
 class NetworkIsolationKey;
 class ReportSender;
 class StaticHttpUserAgentSettings;
@@ -199,9 +200,7 @@
   void GetRestrictedCookieManager(
       mojo::PendingReceiver<mojom::RestrictedCookieManager> receiver,
       mojom::RestrictedCookieManagerRole role,
-      const url::Origin& origin,
-      const net::SiteForCookies& site_for_cookies,
-      const url::Origin& top_frame_origin,
+      const net::IsolationInfo& isolation_info,
       mojo::PendingRemote<mojom::CookieAccessObserver> observer) override;
   void GetHasTrustTokensAnswerer(
       mojo::PendingReceiver<mojom::HasTrustTokensAnswerer> receiver,
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc
index fb79ebe..1ad562c 100644
--- a/services/network/network_context_unittest.cc
+++ b/services/network/network_context_unittest.cc
@@ -954,13 +954,14 @@
 TEST_F(DiskCacheSizeTest, DiskCacheSize) {
   int64_t max_file_size = VerifyDiskCacheSize();
 
-  // Scale to 200%. The size should be twice of |max_file_size| but
-  // since max size is capped on 20% of available size, checking for the size to
-  // be between max_file_size and max_file_size*2.
   int64_t max_file_size_scaled = VerifyDiskCacheSize(200);
 
+  // After scaling to 200%, the size will in most cases be twice of
+  // |max_file_size| but it is dependent on the available size, and since we
+  // cannot guarantee available size to be the same between the 2 runs to
+  // VerifyDiskCacheSize(), only checking for the scaled size to be >=
+  // max_file_size.
   EXPECT_GE(max_file_size_scaled, max_file_size);
-  EXPECT_LE(max_file_size_scaled, 2 * max_file_size);
 }
 
 // This makes sure that network_session_configurator::ChooseCacheType is
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom
index 5103b20..fc39ed2 100644
--- a/services/network/public/mojom/network_context.mojom
+++ b/services/network/public/mojom/network_context.mojom
@@ -907,12 +907,8 @@
   // Gets a RestrictedCookieManager scoped to a given origin, and applying
   // settings configured on the CookieManager associated with this domain.
   //
-  // |site_for_cookies| represents which domains (perhaps none) the cookie
-  // manager should consider to be first-party, for purposes of SameSite cookies
-  // and any third-party cookie blocking the embedder may implement.
-  //
-  // |top_frame_origin| represents the domain for top-level frame, and can be
-  // used to look up preferences that are dependent on that.
+  // |isolation_info| contains info for SameSite and SameParty cookie queries.
+  // Must be fully populated.
   //
   // If |role| == SCRIPT, this interface can be safely handed out to a process
   // that is known to represent the given origin, such as a renderer process.
@@ -922,9 +918,7 @@
   GetRestrictedCookieManager(
       pending_receiver<RestrictedCookieManager> restricted_cookie_manager,
       RestrictedCookieManagerRole role,
-      url.mojom.Origin origin,
-      SiteForCookies site_for_cookies,
-      url.mojom.Origin top_frame_origin,
+      IsolationInfo isolation_info,
       pending_remote<CookieAccessObserver>? cookie_observer);
 
   // Provides a HasTrustTokensAnswerer scoped to the given top-frame origin
diff --git a/services/network/restricted_cookie_manager.cc b/services/network/restricted_cookie_manager.cc
index e972176..af0eeb6 100644
--- a/services/network/restricted_cookie_manager.cc
+++ b/services/network/restricted_cookie_manager.cc
@@ -194,16 +194,14 @@
     const mojom::RestrictedCookieManagerRole role,
     net::CookieStore* cookie_store,
     const CookieSettings* cookie_settings,
-    const url::Origin& origin,
-    const net::SiteForCookies& site_for_cookies,
-    const url::Origin& top_frame_origin,
+    const net::IsolationInfo& isolation_info,
     mojo::PendingRemote<mojom::CookieAccessObserver> cookie_observer)
     : role_(role),
       cookie_store_(cookie_store),
       cookie_settings_(cookie_settings),
-      origin_(origin),
-      site_for_cookies_(site_for_cookies),
-      top_frame_origin_(top_frame_origin),
+      origin_(isolation_info.frame_origin().value()),
+      site_for_cookies_(isolation_info.site_for_cookies()),
+      top_frame_origin_(isolation_info.top_frame_origin().value()),
       cookie_observer_(std::move(cookie_observer)) {
   DCHECK(cookie_store);
 }
diff --git a/services/network/restricted_cookie_manager.h b/services/network/restricted_cookie_manager.h
index 9c89588..9e14d0b0 100644
--- a/services/network/restricted_cookie_manager.h
+++ b/services/network/restricted_cookie_manager.h
@@ -14,11 +14,11 @@
 #include "base/sequence_checker.h"
 #include "base/threading/sequenced_task_runner_handle.h"
 #include "mojo/public/cpp/bindings/remote.h"
+#include "net/base/isolation_info.h"
 #include "net/cookies/canonical_cookie.h"
 #include "net/cookies/cookie_change_dispatcher.h"
 #include "net/cookies/cookie_inclusion_status.h"
 #include "net/cookies/cookie_store.h"
-#include "net/cookies/site_for_cookies.h"
 #include "services/network/public/mojom/cookie_access_observer.mojom.h"
 #include "services/network/public/mojom/restricted_cookie_manager.mojom.h"
 #include "url/gurl.h"
@@ -40,14 +40,12 @@
     : public mojom::RestrictedCookieManager {
  public:
   // All the pointers passed to the constructor are expected to point to
-  // objects that will outlive |this|.
+  // objects that will outlive |this|. |isolation_info| must be fully populated.
   RestrictedCookieManager(
       mojom::RestrictedCookieManagerRole role,
       net::CookieStore* cookie_store,
       const CookieSettings* cookie_settings,
-      const url::Origin& origin,
-      const net::SiteForCookies& site_for_cookies,
-      const url::Origin& top_frame_origin,
+      const net::IsolationInfo& isolation_info,
       mojo::PendingRemote<mojom::CookieAccessObserver> cookie_observer);
 
   ~RestrictedCookieManager() override;
diff --git a/services/network/restricted_cookie_manager_unittest.cc b/services/network/restricted_cookie_manager_unittest.cc
index 9971d10..ef088aec 100644
--- a/services/network/restricted_cookie_manager_unittest.cc
+++ b/services/network/restricted_cookie_manager_unittest.cc
@@ -18,6 +18,7 @@
 #include "mojo/public/cpp/bindings/remote.h"
 #include "mojo/public/cpp/system/functions.h"
 #include "net/base/features.h"
+#include "net/base/isolation_info.h"
 #include "net/cookies/canonical_cookie_test_helpers.h"
 #include "net/cookies/cookie_constants.h"
 #include "net/cookies/cookie_monster.h"
@@ -175,13 +176,13 @@
  public:
   RestrictedCookieManagerTest()
       : cookie_monster_(nullptr, nullptr /* netlog */),
+        isolation_info_(net::IsolationInfo::CreateForInternalRequest(
+            url::Origin::Create(GURL("https://example.com")))),
         service_(std::make_unique<RestrictedCookieManager>(
             GetParam(),
             &cookie_monster_,
             &cookie_settings_,
-            url::Origin::Create(GURL("https://example.com")),
-            net::SiteForCookies::FromUrl(GURL("https://example.com")),
-            url::Origin::Create(GURL("https://example.com")),
+            isolation_info_,
             recording_client_.GetRemote())),
         receiver_(service_.get(),
                   service_remote_.BindNewPipeAndPassReceiver()) {
@@ -268,6 +269,7 @@
       base::test::SingleThreadTaskEnvironment::MainThreadType::IO};
   net::CookieMonster cookie_monster_;
   CookieSettings cookie_settings_;
+  net::IsolationInfo isolation_info_;
   RecordingCookieObserver recording_client_;
   std::unique_ptr<RestrictedCookieManager> service_;
   mojo::Remote<mojom::RestrictedCookieManager> service_remote_;
diff --git a/services/network/test/test_network_context.h b/services/network/test/test_network_context.h
index d02c338ff..9b6f5af 100644
--- a/services/network/test/test_network_context.h
+++ b/services/network/test/test_network_context.h
@@ -6,6 +6,7 @@
 #define SERVICES_NETWORK_TEST_TEST_NETWORK_CONTEXT_H_
 
 #include <cstdint>
+#include <set>
 #include <string>
 #include <vector>
 
@@ -17,6 +18,7 @@
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "net/base/address_list.h"
 #include "net/base/ip_endpoint.h"
+#include "net/base/isolation_info.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 #include "services/network/public/cpp/network_service_buildflags.h"
 #include "services/network/public/mojom/cookie_access_observer.mojom.h"
@@ -57,9 +59,7 @@
       mojo::PendingReceiver<mojom::RestrictedCookieManager>
           restricted_cookie_manager,
       mojom::RestrictedCookieManagerRole role,
-      const url::Origin& origin,
-      const net::SiteForCookies& site_for_cookies,
-      const url::Origin& top_frame_origin,
+      const net::IsolationInfo& isolation_info,
       mojo::PendingRemote<mojom::CookieAccessObserver> observer) override {}
   void GetHasTrustTokensAnswerer(
       mojo::PendingReceiver<mojom::HasTrustTokensAnswerer> receiver,
diff --git a/services/network/trust_tokens/trust_token_operation_metrics_recorder.cc b/services/network/trust_tokens/trust_token_operation_metrics_recorder.cc
index 3ec3a9ea..b02eb08e 100644
--- a/services/network/trust_tokens/trust_token_operation_metrics_recorder.cc
+++ b/services/network/trust_tokens/trust_token_operation_metrics_recorder.cc
@@ -54,6 +54,23 @@
 
 const char kHistogramPartsSeparator[] = ".";
 
+// If |operation_is_platform_provided| indicates that the Trust Tokens operation
+// corresponding to the metric name in |pieces| is platform-provided, adds an
+// element to |pieces| mentioning this fact.
+//
+// Note: As of writing during the initial platform-provided issuance
+// implementation, issuance is the only platform-provided operation and its
+// control flow never enters TrustTokenRequestHelper::Finalize call, so the only
+// metrics this is expected (initially) to affect are
+// OperationBeginTime.Issuance.Success and OperationBeginTime.Issuance.Failure.
+std::vector<base::StringPiece> MaybeAppendPlatformProvidedIndicator(
+    std::vector<base::StringPiece> pieces,
+    bool operation_is_platform_provided) {
+  if (operation_is_platform_provided)
+    pieces.push_back("PlatformProvided");
+  return pieces;
+}
+
 }  // namespace
 
 TrustTokenOperationMetricsRecorder::TrustTokenOperationMetricsRecorder(
@@ -71,9 +88,12 @@
   begin_end_ = base::TimeTicks::Now();
 
   base::UmaHistogramTimes(
-      base::JoinString({internal::kTrustTokenBeginTimeHistogramNameBase,
-                        StatusToSuccessOrFailure(status), TypeToString(type_)},
-                       kHistogramPartsSeparator),
+      base::JoinString(
+          MaybeAppendPlatformProvidedIndicator(
+              {internal::kTrustTokenBeginTimeHistogramNameBase,
+               StatusToSuccessOrFailure(status), TypeToString(type_)},
+              operation_is_platform_provided_),
+          kHistogramPartsSeparator),
       begin_end_ - begin_start_);
 }
 
@@ -88,24 +108,38 @@
   base::TimeTicks finalize_end = base::TimeTicks::Now();
 
   base::UmaHistogramTimes(
-      base::JoinString({internal::kTrustTokenServerTimeHistogramNameBase,
-                        StatusToSuccessOrFailure(status), TypeToString(type_)},
-                       kHistogramPartsSeparator),
+      base::JoinString(
+          MaybeAppendPlatformProvidedIndicator(
+              {internal::kTrustTokenServerTimeHistogramNameBase,
+               StatusToSuccessOrFailure(status), TypeToString(type_)},
+              operation_is_platform_provided_),
+          kHistogramPartsSeparator),
       finalize_start_ - begin_end_);
 
   base::UmaHistogramTimes(
-      base::JoinString({internal::kTrustTokenTotalTimeHistogramNameBase,
-                        StatusToSuccessOrFailure(status), TypeToString(type_)},
-                       kHistogramPartsSeparator),
+      base::JoinString(
+          MaybeAppendPlatformProvidedIndicator(
+              {internal::kTrustTokenTotalTimeHistogramNameBase,
+               StatusToSuccessOrFailure(status), TypeToString(type_)},
+              operation_is_platform_provided_),
+          kHistogramPartsSeparator),
       finalize_end - begin_start_);
 
   base::UmaHistogramTimes(
-      base::JoinString({internal::kTrustTokenFinalizeTimeHistogramNameBase,
-                        StatusToSuccessOrFailure(status), TypeToString(type_)},
-                       kHistogramPartsSeparator),
+      base::JoinString(
+          MaybeAppendPlatformProvidedIndicator(
+              {internal::kTrustTokenFinalizeTimeHistogramNameBase,
+               StatusToSuccessOrFailure(status), TypeToString(type_)},
+              operation_is_platform_provided_),
+          kHistogramPartsSeparator),
       finalize_end - finalize_start_);
 }
 
+void TrustTokenOperationMetricsRecorder::
+    WillExecutePlatformProvidedOperation() {
+  operation_is_platform_provided_ = true;
+}
+
 void HistogramTrustTokenOperationNetError(
     network::mojom::TrustTokenOperationType type,
     network::mojom::TrustTokenOperationStatus status,
diff --git a/services/network/trust_tokens/trust_token_operation_metrics_recorder.h b/services/network/trust_tokens/trust_token_operation_metrics_recorder.h
index ec1b2ce..edbb65a 100644
--- a/services/network/trust_tokens/trust_token_operation_metrics_recorder.h
+++ b/services/network/trust_tokens/trust_token_operation_metrics_recorder.h
@@ -28,11 +28,12 @@
 // part finishes; if the Begin part was successful, call BeginFinalize and
 // FinishFinalize analogously during the Finalize (inbound) part of the
 // operation.
-class TrustTokenOperationMetricsRecorder final {
+class TrustTokenOperationMetricsRecorder final
+    : public TrustTokenRequestIssuanceHelper::MetricsDelegate {
  public:
   explicit TrustTokenOperationMetricsRecorder(
       mojom::TrustTokenOperationType type);
-  ~TrustTokenOperationMetricsRecorder();
+  ~TrustTokenOperationMetricsRecorder() override;
 
   TrustTokenOperationMetricsRecorder(
       const TrustTokenOperationMetricsRecorder&) = delete;
@@ -45,6 +46,9 @@
   void BeginFinalize();
   void FinishFinalize(mojom::TrustTokenOperationStatus status);
 
+  // TrustTokenRequestIssuanceHelper::MetricsDelegate:
+  void WillExecutePlatformProvidedOperation() override;
+
  private:
   mojom::TrustTokenOperationType type_;
 
@@ -54,6 +58,11 @@
 
   // Start time for the Finalize part of the operation:
   base::TimeTicks finalize_start_;
+
+  // If true, inserts a histogram suffix indicating that the Trust Tokens
+  // operation being measured is "platform-provided": executed against a
+  // device-local provider, rather than against an issuer's server.
+  bool operation_is_platform_provided_ = false;
 };
 
 // HistogramTrustTokenOperationNetError logs a //net error code corresponding to
diff --git a/services/network/trust_tokens/trust_token_operation_metrics_recorder_unittest.cc b/services/network/trust_tokens/trust_token_operation_metrics_recorder_unittest.cc
index adbdd1e..bca9145 100644
--- a/services/network/trust_tokens/trust_token_operation_metrics_recorder_unittest.cc
+++ b/services/network/trust_tokens/trust_token_operation_metrics_recorder_unittest.cc
@@ -57,6 +57,52 @@
       /*expected_count=*/1);
 }
 
+TEST(TrustTokenOperationMetricsRecorder, SuccessPlatformProvided) {
+  base::test::TaskEnvironment env(
+      base::test::TaskEnvironment::TimeSource::MOCK_TIME);
+  TrustTokenOperationMetricsRecorder recorder(
+      mojom::TrustTokenOperationType::kIssuance);
+  recorder.WillExecutePlatformProvidedOperation();
+  base::HistogramTester histograms;
+
+  recorder.BeginBegin();
+  env.FastForwardBy(base::TimeDelta::FromSeconds(1));
+  recorder.FinishBegin(mojom::TrustTokenOperationStatus::kOk);
+
+  env.FastForwardBy(base::TimeDelta::FromSeconds(2));
+  recorder.BeginFinalize();
+  env.FastForwardBy(base::TimeDelta::FromSeconds(3));
+  recorder.FinishFinalize(mojom::TrustTokenOperationStatus::kOk);
+
+  histograms.ExpectUniqueTimeSample(
+      base::JoinString({internal::kTrustTokenBeginTimeHistogramNameBase,
+                        "Success", "Issuance", "PlatformProvided"},
+                       "."),
+      base::TimeDelta::FromSeconds(1),
+      /*expected_count=*/1);
+
+  histograms.ExpectUniqueTimeSample(
+      base::JoinString({internal::kTrustTokenServerTimeHistogramNameBase,
+                        "Success", "Issuance", "PlatformProvided"},
+                       "."),
+      base::TimeDelta::FromSeconds(2),
+      /*expected_count=*/1);
+
+  histograms.ExpectUniqueTimeSample(
+      base::JoinString({internal::kTrustTokenFinalizeTimeHistogramNameBase,
+                        "Success", "Issuance", "PlatformProvided"},
+                       "."),
+      base::TimeDelta::FromSeconds(3),
+      /*expected_count=*/1);
+
+  histograms.ExpectUniqueTimeSample(
+      base::JoinString({internal::kTrustTokenTotalTimeHistogramNameBase,
+                        "Success", "Issuance", "PlatformProvided"},
+                       "."),
+      base::TimeDelta::FromSeconds(1 + 2 + 3),
+      /*expected_count=*/1);
+}
+
 TEST(TrustTokenOperationMetricsRecorder, BeginFailure) {
   base::test::TaskEnvironment env(
       base::test::TaskEnvironment::TimeSource::MOCK_TIME);
diff --git a/services/network/trust_tokens/trust_token_request_helper_factory.cc b/services/network/trust_tokens/trust_token_request_helper_factory.cc
index 8c76ded..1499e72 100644
--- a/services/network/trust_tokens/trust_token_request_helper_factory.cc
+++ b/services/network/trust_tokens/trust_token_request_helper_factory.cc
@@ -154,7 +154,8 @@
           std::make_unique<BoringsslTrustTokenIssuanceCryptographer>(),
           std::make_unique<LocalTrustTokenOperationDelegateImpl>(
               context_client_provider_),
-          base::BindRepeating(&IsCurrentOperatingSystem), std::move(net_log));
+          base::BindRepeating(&IsCurrentOperatingSystem),
+          metrics_recorder.get(), std::move(net_log));
       std::move(done).Run(TrustTokenStatusOrRequestHelper(
           std::make_unique<OperationTimingRequestHelperWrapper>(
               std::move(metrics_recorder), std::move(helper))));
diff --git a/services/network/trust_tokens/trust_token_request_issuance_helper.cc b/services/network/trust_tokens/trust_token_request_issuance_helper.cc
index 5dfe0982..5c463fe7 100644
--- a/services/network/trust_tokens/trust_token_request_issuance_helper.cc
+++ b/services/network/trust_tokens/trust_token_request_issuance_helper.cc
@@ -96,6 +96,7 @@
     std::unique_ptr<LocalTrustTokenOperationDelegate> local_operation_delegate,
     base::RepeatingCallback<bool(mojom::TrustTokenKeyCommitmentResult::Os)>
         is_current_os_callback,
+    MetricsDelegate* metrics_delegate,
     net::NetLogWithSource net_log)
     : top_level_origin_(std::move(top_level_origin)),
       token_store_(token_store),
@@ -103,6 +104,7 @@
       cryptographer_(std::move(cryptographer)),
       local_operation_delegate_(std::move(local_operation_delegate)),
       is_current_os_callback_(std::move(is_current_os_callback)),
+      metrics_delegate_(metrics_delegate),
       net_log_(std::move(net_log)) {
   DCHECK(token_store_);
   DCHECK(key_commitment_getter_);
@@ -238,6 +240,7 @@
     auto fulfill_request = mojom::FulfillTrustTokenIssuanceRequest::New();
     fulfill_request->issuer = url::Origin::Create(request->url());
     fulfill_request->request = std::move(*maybe_blinded_tokens);
+    metrics_delegate_->WillExecutePlatformProvidedOperation();
     local_operation_delegate_->FulfillIssuance(
         std::move(fulfill_request),
         base::BindOnce(&TrustTokenRequestIssuanceHelper::
diff --git a/services/network/trust_tokens/trust_token_request_issuance_helper.h b/services/network/trust_tokens/trust_token_request_issuance_helper.h
index 24e13b3..48218137 100644
--- a/services/network/trust_tokens/trust_token_request_issuance_helper.h
+++ b/services/network/trust_tokens/trust_token_request_issuance_helper.h
@@ -106,6 +106,16 @@
         base::StringPiece response_header) = 0;
   };
 
+  class MetricsDelegate {
+   public:
+    virtual ~MetricsDelegate() = default;
+
+    // Indicates that this delegate is about to attempt to execute its
+    // issuance operation through a call to the provided
+    // LocalTrustTokenOperationDelegate.
+    virtual void WillExecutePlatformProvidedOperation() = 0;
+  };
+
   // Creates a new issuance helper.
   //
   // - |top_level_origin| is the top-level origin of the request subsequently
@@ -124,9 +134,13 @@
   // present in the issuer's "request_issuance_locally_on" field in its key
   // commitment, the issuance helper should attempt to forward requests to the
   // local operation delegate.
+  // - |metrics_delegate|, which must outlive this object, will learn about
+  // certain aspects of this operation's execution in order to slice the metrics
+  // that it reports.
   //
   // REQUIRES: |token_store|, |key_commitment_getter|, |cryptographer|,
-  // |local_operation_delegate|, and |is_current_os_callback| must be non-null.
+  // |local_operation_delegate|, |is_current_os_callback|, and
+  // |metrics_delegate|  must be non-null.
   TrustTokenRequestIssuanceHelper(
       SuitableTrustTokenOrigin top_level_origin,
       TrustTokenStore* token_store,
@@ -136,6 +150,7 @@
           local_operation_delegate,
       base::RepeatingCallback<bool(mojom::TrustTokenKeyCommitmentResult::Os)>
           is_current_os_callback,
+      MetricsDelegate* metrics_delegate,
       net::NetLogWithSource net_log = net::NetLogWithSource());
   ~TrustTokenRequestIssuanceHelper() override;
 
@@ -278,6 +293,8 @@
   base::RepeatingCallback<bool(mojom::TrustTokenKeyCommitmentResult::Os)>
       is_current_os_callback_;
 
+  MetricsDelegate* const metrics_delegate_;
+
   net::NetLogWithSource net_log_;
   base::Optional<size_t> num_obtained_tokens_;
   base::WeakPtrFactory<TrustTokenRequestIssuanceHelper> weak_ptr_factory_{this};
diff --git a/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc b/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc
index d949df57..a044f43 100644
--- a/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc
+++ b/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc
@@ -104,6 +104,20 @@
                done));
 };
 
+class MockMetricsDelegate
+    : public TrustTokenRequestIssuanceHelper::MetricsDelegate {
+ public:
+  MOCK_METHOD0(WillExecutePlatformProvidedOperation, void());
+};
+
+class FakeMetricsDelegate
+    : public TrustTokenRequestIssuanceHelper::MetricsDelegate {
+ public:
+  void WillExecutePlatformProvidedOperation() override {}
+};
+
+base::NoDestructor<FakeMetricsDelegate> g_metrics_delegate{};
+
 // Returns a key commitment result with reasonable values for all parameters.
 mojom::TrustTokenKeyCommitmentResultPtr ReasonableKeyCommitmentResult() {
   auto key_commitment_result = mojom::TrustTokenKeyCommitmentResult::New();
@@ -150,7 +164,7 @@
       toplevel, store.get(), g_fixed_key_commitment_getter.get(),
       std::make_unique<MockCryptographer>(),
       std::make_unique<MockLocalOperationDelegate>(),
-      base::BindRepeating(&IsCurrentOperatingSystem));
+      base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -176,7 +190,7 @@
       store.get(), g_fixed_key_commitment_getter.get(),
       std::make_unique<MockCryptographer>(),
       std::make_unique<MockLocalOperationDelegate>(),
-      base::BindRepeating(&IsCurrentOperatingSystem));
+      base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -198,7 +212,7 @@
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
       store.get(), getter.get(), std::make_unique<MockCryptographer>(),
       std::make_unique<MockLocalOperationDelegate>(),
-      base::BindRepeating(&IsCurrentOperatingSystem));
+      base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(
@@ -223,7 +237,7 @@
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
       store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
       std::make_unique<MockLocalOperationDelegate>(),
-      base::BindRepeating(&IsCurrentOperatingSystem));
+      base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -247,7 +261,7 @@
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
       store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
       std::make_unique<MockLocalOperationDelegate>(),
-      base::BindRepeating(&IsCurrentOperatingSystem));
+      base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -275,7 +289,7 @@
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
       store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
       std::make_unique<MockLocalOperationDelegate>(),
-      base::BindRepeating(&IsCurrentOperatingSystem));
+      base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -308,7 +322,7 @@
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
       store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
       std::make_unique<MockLocalOperationDelegate>(),
-      base::BindRepeating(&IsCurrentOperatingSystem));
+      base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -348,7 +362,7 @@
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
       store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
       std::make_unique<MockLocalOperationDelegate>(),
-      base::BindRepeating(&IsCurrentOperatingSystem));
+      base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -377,7 +391,7 @@
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
       store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
       std::make_unique<MockLocalOperationDelegate>(),
-      base::BindRepeating(&IsCurrentOperatingSystem));
+      base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -411,7 +425,7 @@
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
       store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
       std::make_unique<MockLocalOperationDelegate>(),
-      base::BindRepeating(&IsCurrentOperatingSystem));
+      base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -456,7 +470,7 @@
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
       store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
       std::make_unique<MockLocalOperationDelegate>(),
-      base::BindRepeating(&IsCurrentOperatingSystem));
+      base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -500,7 +514,7 @@
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
       store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
       std::make_unique<MockLocalOperationDelegate>(),
-      base::BindRepeating(&IsCurrentOperatingSystem));
+      base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -542,7 +556,7 @@
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
       store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
       std::make_unique<MockLocalOperationDelegate>(),
-      base::BindRepeating(&IsCurrentOperatingSystem));
+      base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -585,7 +599,7 @@
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
       store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
       std::make_unique<MockLocalOperationDelegate>(),
-      base::BindRepeating(&IsCurrentOperatingSystem));
+      base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -619,7 +633,7 @@
       store.get(), g_fixed_key_commitment_getter.get(),
       std::make_unique<MockCryptographer>(),
       std::make_unique<MockLocalOperationDelegate>(),
-      base::BindRepeating(&IsCurrentOperatingSystem));
+      base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get());
 
   auto request = MakeURLRequest("http://insecure-issuer.com/");
 
@@ -635,7 +649,7 @@
       store.get(), g_fixed_key_commitment_getter.get(),
       std::make_unique<MockCryptographer>(),
       std::make_unique<MockLocalOperationDelegate>(),
-      base::BindRepeating(&IsCurrentOperatingSystem));
+      base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get());
 
   auto request = MakeURLRequest("file:///non-https-issuer.txt");
 
@@ -663,7 +677,7 @@
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
       store.get(), ReasonableKeyCommitmentGetter(), std::move(cryptographer),
       std::make_unique<MockLocalOperationDelegate>(),
-      base::BindRepeating(&IsCurrentOperatingSystem));
+      base::BindRepeating(&IsCurrentOperatingSystem), g_metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -748,7 +762,8 @@
       std::move(local_operation_delegate),
       base::BindRepeating([](mojom::TrustTokenKeyCommitmentResult::Os os) {
         return os == mojom::TrustTokenKeyCommitmentResult::Os::kAndroid;
-      }));
+      }),
+      g_metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -817,7 +832,8 @@
       std::move(local_operation_delegate),
       base::BindRepeating([](mojom::TrustTokenKeyCommitmentResult::Os os) {
         return os == mojom::TrustTokenKeyCommitmentResult::Os::kAndroid;
-      }));
+      }),
+      g_metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -852,7 +868,8 @@
       std::make_unique<MockLocalOperationDelegate>(),
       // Fail to match to the current OS...
       base::BindLambdaForTesting(
-          [](mojom::TrustTokenKeyCommitmentResult::Os) { return false; }));
+          [](mojom::TrustTokenKeyCommitmentResult::Os) { return false; }),
+      g_metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -895,7 +912,8 @@
       std::make_unique<MockLocalOperationDelegate>(),
       // Fail to match to the current OS...
       base::BindLambdaForTesting(
-          [](mojom::TrustTokenKeyCommitmentResult::Os) { return false; }));
+          [](mojom::TrustTokenKeyCommitmentResult::Os) { return false; }),
+      g_metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
@@ -930,10 +948,11 @@
 
   auto cryptographer = std::make_unique<MockCryptographer>();
 
-  // Use a strict mock to make the test fail if the delegate gets called on
+  // Use strict mocks to make the test fail if the delegates get called on
   // non-Android platforms:
   auto local_operation_delegate =
       std::make_unique<StrictMock<MockLocalOperationDelegate>>();
+  auto metrics_delegate = std::make_unique<StrictMock<MockMetricsDelegate>>();
 #if defined(OS_ANDROID)
   EXPECT_CALL(*cryptographer, Initialize(_, _)).WillOnce(Return(true));
   EXPECT_CALL(*cryptographer, AddKey(_)).WillOnce(Return(true));
@@ -951,13 +970,14 @@
               callback) { std::move(callback).Run(std::move(answer)); };
   EXPECT_CALL(*local_operation_delegate, FulfillIssuance(_, _))
       .WillOnce(WithArgs<1>(Invoke(receive_answer)));
+  EXPECT_CALL(*metrics_delegate, WillExecutePlatformProvidedOperation());
 #endif  // defined(OS_ANDROID)
 
   TrustTokenRequestIssuanceHelper helper(
       *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com/")),
       store.get(), getter.get(), std::move(cryptographer),
       std::move(local_operation_delegate),
-      base::BindRepeating(&IsCurrentOperatingSystem));
+      base::BindRepeating(&IsCurrentOperatingSystem), metrics_delegate.get());
 
   auto request = MakeURLRequest("https://issuer.com/");
   request->set_initiator(issuer);
diff --git a/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom b/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom
index 4afc007..a0b8792 100644
--- a/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom
+++ b/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom
@@ -30,7 +30,6 @@
   // Disables begin frame rate limiting for the display compositor.
   bool disable_frame_rate_limit = false;
   bool use_preferred_interval_for_video = false;
-  uint32 num_of_frames_to_toggle_interval = 60;
 
   [EnableIf=is_android]
   float refresh_rate;
diff --git a/testing/xvfb.py b/testing/xvfb.py
index e65c8fa..043cfda 100755
--- a/testing/xvfb.py
+++ b/testing/xvfb.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env vpython
 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
@@ -8,6 +8,7 @@
 
 import os
 import os.path
+import psutil
 import random
 import re
 import signal
@@ -17,12 +18,6 @@
 import time
 import test_env
 
-try:
-  import psutil
-except ImportError:
-  raise Exception(
-        'Failed to import psutil. Run under vpython or install psutil.')
-
 class _XvfbProcessError(Exception):
   """Exception raised when Xvfb cannot start."""
   pass
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index 261c7c4..544654a 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -859,5 +859,11 @@
     "SendCnameAliasesToSubresourceFilterFromRenderer",
     base::FEATURE_DISABLED_BY_DEFAULT};
 
+// Kill switch for the InterestCohort API origin trial, i.e. if disabled, the
+// API exposure will be disabled regardless of the OT config.
+// (See https://github.com/WICG/floc.)
+const base::Feature kInterestCohortAPIOriginTrial{
+    "InterestCohortAPIOriginTrial", base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace features
 }  // namespace blink
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 47f9269..4de0ff39 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -354,6 +354,8 @@
 BLINK_COMMON_EXPORT extern const base::Feature
     kSendCnameAliasesToSubresourceFilterFromRenderer;
 
+BLINK_COMMON_EXPORT extern const base::Feature kInterestCohortAPIOriginTrial;
+
 }  // namespace features
 }  // namespace blink
 
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 00728f7..a0dc535 100644
--- a/third_party/blink/public/mojom/web_feature/web_feature.mojom
+++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -2679,7 +2679,7 @@
   kV8PointerEvent_AltitudeAngle_AttributeGetter = 3352,
   kCrossBrowsingContextGroupMainFrameNulledNonEmptyNameAccessed = 3353,
   kPositionSticky = 3354,
-  kCommaSeparatorInAllowAttribute = 3355,
+  kOBSOLETE_CommaSeparatorInAllowAttribute = 3355,
   kMainFrameCSPViaHTTP = 3359,
   kMainFrameCSPViaMeta = 3360,
   kMainFrameCSPViaOriginPolicy = 3361,
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h
index 7a49661d..5cf7f698 100644
--- a/third_party/blink/renderer/core/dom/element.h
+++ b/third_party/blink/renderer/core/dom/element.h
@@ -666,7 +666,9 @@
       Element* new_focused_element,
       InputDeviceCapabilities* source_capabilities = nullptr);
 
-  // The implementation of |innerText()| is found in "element_inner_text.cc".
+  // The implementations of |innerText()| and |GetInnerTextWithoutUpdate()| are
+  // found in "element_inner_text.cc".
+  String GetInnerTextWithoutUpdate();  // Avoids layout update.
   String innerText();
   String outerText();
 
diff --git a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
index e8004f2..04f2643 100644
--- a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
+++ b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
@@ -38,7 +38,7 @@
 #include "third_party/blink/renderer/core/dom/events/window_event_context.h"
 #include "third_party/blink/renderer/core/events/keyboard_event.h"
 #include "third_party/blink/renderer/core/events/mouse_event.h"
-#include "third_party/blink/renderer/core/events/pointer_event.h"
+#include "third_party/blink/renderer/core/events/simulated_event_util.h"
 #include "third_party/blink/renderer/core/frame/ad_tracker.h"
 #include "third_party/blink/renderer/core/frame/deprecation.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
@@ -53,27 +53,6 @@
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
 
 namespace blink {
-namespace {
-Event* CreateEvent(const AtomicString& event_type,
-                   Node& node,
-                   const Event* underlying_event,
-                   SimulatedClickCreationScope creation_scope) {
-  DCHECK(event_type == event_type_names::kClick ||
-         event_type == event_type_names::kMousedown ||
-         event_type == event_type_names::kMouseup);
-  if (RuntimeEnabledFeatures::ClickPointerEventEnabled() &&
-      event_type == event_type_names::kClick) {
-    // TODO(crbug.com/1150979): Should we also fire pointer events for
-    // mousedown/mouseup events?  These mouse events are used for accessibility.
-    return PointerEvent::Create(event_type_names::kClick,
-                                node.GetDocument().domWindow(),
-                                underlying_event, creation_scope);
-  } else {
-    return MouseEvent::Create(event_type, node.GetDocument().domWindow(),
-                              underlying_event, creation_scope);
-  }
-}
-}  // namespace
 
 DispatchEventResult EventDispatcher::DispatchEvent(Node& node, Event& event) {
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("blink.debug"),
@@ -120,14 +99,20 @@
   nodes_dispatching_simulated_clicks->insert(&node);
 
   Element* element = DynamicTo<Element>(node);
+  LocalDOMWindow* dom_window = node.GetDocument().domWindow();
+
+  // TODO(crbug.com/1150979): Should we also fire pointer events for
+  // mousedown/mouseup events?  These mouse events are used for accessibility.
   if (mouse_event_options != kSendNoEvents) {
-    EventDispatcher(node, *CreateEvent(event_type_names::kMousedown, node,
-                                       underlying_event, creation_scope))
+    EventDispatcher(node, *SimulatedEventUtil::CreateEvent(
+                              event_type_names::kMousedown, dom_window,
+                              underlying_event, creation_scope))
         .Dispatch();
     if (element)
       element->SetActive(true);
-    EventDispatcher(node, *CreateEvent(event_type_names::kMouseup, node,
-                                       underlying_event, creation_scope))
+    EventDispatcher(node, *SimulatedEventUtil::CreateEvent(
+                              event_type_names::kMouseup, dom_window,
+                              underlying_event, creation_scope))
         .Dispatch();
   }
   // Some elements (e.g. the color picker) may set active state to true before
@@ -135,9 +120,10 @@
   if (element)
     element->SetActive(false);
 
-  // always send click
-  EventDispatcher(node, *CreateEvent(event_type_names::kClick, node,
-                                     underlying_event, creation_scope))
+  // Always send click.
+  EventDispatcher(node, *SimulatedEventUtil::CreateEvent(
+                            event_type_names::kClick, dom_window,
+                            underlying_event, creation_scope))
       .Dispatch();
 
   nodes_dispatching_simulated_clicks->erase(&node);
diff --git a/third_party/blink/renderer/core/dom/node.cc b/third_party/blink/renderer/core/dom/node.cc
index 162f482..43eb9408 100644
--- a/third_party/blink/renderer/core/dom/node.cc
+++ b/third_party/blink/renderer/core/dom/node.cc
@@ -1598,7 +1598,8 @@
 }
 
 void Node::DetachLayoutTree(bool performing_reattach) {
-  DCHECK(GetDocument().Lifecycle().StateAllowsDetach());
+  DCHECK(GetDocument().Lifecycle().StateAllowsDetach() ||
+         GetDocument().GetStyleEngine().InContainerQueryStyleRecalc());
   DCHECK(!performing_reattach ||
          GetDocument().GetStyleEngine().InRebuildLayoutTree());
   DocumentLifecycle::DetachScope will_detach(GetDocument().Lifecycle());
diff --git a/third_party/blink/renderer/core/editing/element_inner_text.cc b/third_party/blink/renderer/core/editing/element_inner_text.cc
index 9e8dbef..5c5ada9b 100644
--- a/third_party/blink/renderer/core/editing/element_inner_text.cc
+++ b/third_party/blink/renderer/core/editing/element_inner_text.cc
@@ -464,6 +464,22 @@
   // boxes in the layout tree.
   GetDocument().UpdateStyleAndLayoutForNode(this,
                                             DocumentUpdateReason::kJavaScript);
+  return GetInnerTextWithoutUpdate();
+}
+
+// Used for callers that must ensure no document lifecycle rewind.
+String Element::GetInnerTextWithoutUpdate() {
+  // TODO(https:://crbug.com/1165850) Layout should always be clean here, but
+  // the lifecycle does not report the correctly updated value unless servicing
+  // animations. Fix the UpdateStyleAndLayout() to correctly advance the
+  // lifecycle, and then update the following DCHECK to always require clean
+  // layout in active documents.
+  DCHECK(!GetDocument().IsActive() || !GetDocument().GetPage() ||
+         !GetDocument().GetPage()->Animator().IsServicingAnimations() ||
+         GetDocument().Lifecycle().GetState() >=
+             DocumentLifecycle::kLayoutClean)
+      << "If GetInnerTextWithoutUpdate() is called while servicing animations, "
+         "then layout must be clean.";
   return ElementInnerTextCollector().RunOn(*this);
 }
 
diff --git a/third_party/blink/renderer/core/editing/element_inner_text_test.cc b/third_party/blink/renderer/core/editing/element_inner_text_test.cc
index a85ce97..941da596c 100644
--- a/third_party/blink/renderer/core/editing/element_inner_text_test.cc
+++ b/third_party/blink/renderer/core/editing/element_inner_text_test.cc
@@ -60,4 +60,12 @@
   EXPECT_EQ("foo", target.innerText());
 }
 
+// https://crbug.com/1164747
+TEST_P(ElementInnerTest, GetInnerTextWithoutUpdate) {
+  SetBodyContent("<div id=target>ab<span>c</span></div>");
+  Element& target = *GetDocument().getElementById("target");
+  EXPECT_EQ("abc", target.innerText());
+  EXPECT_EQ("abc", target.GetInnerTextWithoutUpdate());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/events/build.gni b/third_party/blink/renderer/core/events/build.gni
index a111c9f..aaf379a2 100644
--- a/third_party/blink/renderer/core/events/build.gni
+++ b/third_party/blink/renderer/core/events/build.gni
@@ -67,6 +67,8 @@
   "resource_progress_event.h",
   "security_policy_violation_event.cc",
   "security_policy_violation_event.h",
+  "simulated_event_util.cc",
+  "simulated_event_util.h",
   "text_event.cc",
   "text_event.h",
   "text_event_input_type.h",
diff --git a/third_party/blink/renderer/core/events/mouse_event.cc b/third_party/blink/renderer/core/events/mouse_event.cc
index c2ef281..fe3c4ef6 100644
--- a/third_party/blink/renderer/core/events/mouse_event.cc
+++ b/third_party/blink/renderer/core/events/mouse_event.cc
@@ -128,63 +128,6 @@
       menu_source_type);
 }
 
-void MouseEvent::PopulateMouseEventInit(
-    const AtomicString& event_type,
-    AbstractView* view,
-    const Event* underlying_event,
-    MouseEventInit* initializer) {
-  WebInputEvent::Modifiers modifiers = WebInputEvent::kNoModifiers;
-  if (const UIEventWithKeyState* key_state_event =
-          FindEventWithKeyState(underlying_event)) {
-    modifiers = key_state_event->GetModifiers();
-  }
-
-  if (const auto* mouse_event = DynamicTo<MouseEvent>(underlying_event)) {
-    initializer->setScreenX(mouse_event->screen_location_.X());
-    initializer->setScreenY(mouse_event->screen_location_.Y());
-    initializer->setSourceCapabilities(
-        view ? view->GetInputDeviceCapabilities()->FiresTouchEvents(false)
-             : nullptr);
-  }
-
-  initializer->setBubbles(true);
-  initializer->setCancelable(true);
-  initializer->setView(view);
-  initializer->setComposed(true);
-  UIEventWithKeyState::SetFromWebInputEventModifiers(initializer, modifiers);
-  initializer->setButtons(
-      MouseEvent::WebInputEventModifiersToButtons(modifiers));
-}
-
-MouseEvent* MouseEvent::Create(const AtomicString& event_type,
-                               AbstractView* view,
-                               const Event* underlying_event,
-                               SimulatedClickCreationScope creation_scope) {
-  MouseEventInit* initializer = MouseEventInit::Create();
-  MouseEvent::PopulateMouseEventInit(event_type, view, underlying_event,
-                                     initializer);
-  SyntheticEventType synthetic_type = kPositionless;
-  if (const auto* mouse_event = DynamicTo<MouseEvent>(underlying_event)) {
-    synthetic_type = kRealOrIndistinguishable;
-  }
-  base::TimeTicks timestamp = underlying_event
-                                  ? underlying_event->PlatformTimeStamp()
-                                  : base::TimeTicks::Now();
-  MouseEvent* created_event = MakeGarbageCollected<MouseEvent>(
-      event_type, initializer, timestamp, synthetic_type);
-
-  created_event->SetTrusted(creation_scope ==
-                            SimulatedClickCreationScope::kFromUserAgent);
-  created_event->SetUnderlyingEvent(underlying_event);
-  if (synthetic_type == kRealOrIndistinguishable) {
-    auto* mouse_event = To<MouseEvent>(created_event->UnderlyingEvent());
-    created_event->InitCoordinates(mouse_event->client_location_.X(),
-                                   mouse_event->client_location_.Y());
-  }
-
-  return created_event;
-}
-
 MouseEvent::MouseEvent()
     : position_type_(PositionType::kPosition),
       button_(0),
diff --git a/third_party/blink/renderer/core/events/mouse_event.h b/third_party/blink/renderer/core/events/mouse_event.h
index c4a9d65..61d48fb 100644
--- a/third_party/blink/renderer/core/events/mouse_event.h
+++ b/third_party/blink/renderer/core/events/mouse_event.h
@@ -29,7 +29,6 @@
 #include "third_party/blink/renderer/core/dom/events/simulated_click_options.h"
 #include "third_party/blink/renderer/core/events/ui_event_with_key_state.h"
 #include "third_party/blink/renderer/platform/geometry/double_point.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 
 namespace blink {
@@ -67,16 +66,6 @@
                             const AtomicString& event_type,
                             const MouseEventInit*);
 
-  static MouseEvent* Create(const AtomicString& event_type,
-                            AbstractView*,
-                            const Event* underlying_event,
-                            SimulatedClickCreationScope);
-
-  static void PopulateMouseEventInit(const AtomicString& event_type,
-                                     AbstractView* view,
-                                     const Event* underlying_event,
-                                     MouseEventInit* initializer);
-
   MouseEvent(const AtomicString& type,
              const MouseEventInit*,
              base::TimeTicks platform_time_stamp = base::TimeTicks::Now(),
@@ -189,6 +178,8 @@
 
   DispatchEventResult DispatchEvent(EventDispatcher&) override;
 
+  void InitCoordinates(const double client_x, const double client_y);
+
   void Trace(Visitor*) const override;
 
   DoublePoint screen_location_;
@@ -203,8 +194,6 @@
 
   void ComputeRelativePosition();
 
-  void InitCoordinates(const double client_x, const double client_y);
-
   bool has_cached_relative_position_ = false;
 
  private:
diff --git a/third_party/blink/renderer/core/events/pointer_event.cc b/third_party/blink/renderer/core/events/pointer_event.cc
index a7a24ee..3b3e1bd 100644
--- a/third_party/blink/renderer/core/events/pointer_event.cc
+++ b/third_party/blink/renderer/core/events/pointer_event.cc
@@ -13,34 +13,6 @@
 
 namespace blink {
 
-PointerEvent* PointerEvent::Create(const AtomicString& event_type,
-                                   AbstractView* view,
-                                   const Event* underlying_event,
-                                   SimulatedClickCreationScope creation_scope) {
-  PointerEventInit* initializer = PointerEventInit::Create();
-  MouseEvent::PopulateMouseEventInit(event_type, view, underlying_event,
-                                     initializer);
-  base::TimeTicks timestamp = underlying_event
-                                  ? underlying_event->PlatformTimeStamp()
-                                  : base::TimeTicks::Now();
-  SyntheticEventType synthetic_type = kPositionless;
-  if (const auto* mouse_event = DynamicTo<MouseEvent>(underlying_event)) {
-    synthetic_type = kRealOrIndistinguishable;
-  }
-  PointerEvent* created_event = MakeGarbageCollected<PointerEvent>(
-      event_type, initializer, timestamp, synthetic_type);
-  created_event->SetTrusted(creation_scope ==
-                            SimulatedClickCreationScope::kFromUserAgent);
-  created_event->SetUnderlyingEvent(underlying_event);
-  if (synthetic_type == kRealOrIndistinguishable) {
-    auto* mouse_event = To<MouseEvent>(created_event->UnderlyingEvent());
-    created_event->InitCoordinates(mouse_event->client_location_.X(),
-                                   mouse_event->client_location_.Y());
-  }
-
-  return created_event;
-}
-
 PointerEvent::PointerEvent(const AtomicString& type,
                            const PointerEventInit* initializer,
                            base::TimeTicks platform_time_stamp,
diff --git a/third_party/blink/renderer/core/events/pointer_event.h b/third_party/blink/renderer/core/events/pointer_event.h
index a605d39..ce41f9a 100644
--- a/third_party/blink/renderer/core/events/pointer_event.h
+++ b/third_party/blink/renderer/core/events/pointer_event.h
@@ -7,7 +7,6 @@
 
 #include "third_party/blink/public/common/input/pointer_id.h"
 #include "third_party/blink/renderer/core/events/mouse_event.h"
-#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 
 namespace blink {
@@ -29,10 +28,6 @@
         type, initializer, platform_time_stamp, synthetic_event_type,
         menu_source_type);
   }
-  static PointerEvent* Create(const AtomicString& event_type,
-                              AbstractView*,
-                              const Event* underlying_event,
-                              SimulatedClickCreationScope);
 
   PointerEvent(const AtomicString&,
                const PointerEventInit*,
diff --git a/third_party/blink/renderer/core/events/simulated_event_util.cc b/third_party/blink/renderer/core/events/simulated_event_util.cc
new file mode 100644
index 0000000..3dc81a5
--- /dev/null
+++ b/third_party/blink/renderer/core/events/simulated_event_util.cc
@@ -0,0 +1,122 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/events/simulated_event_util.h"
+
+#include "base/time/time.h"
+#include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/dom/events/simulated_click_options.h"
+#include "third_party/blink/renderer/core/event_type_names.h"
+#include "third_party/blink/renderer/core/events/mouse_event.h"
+#include "third_party/blink/renderer/core/events/mouse_event_init.h"
+#include "third_party/blink/renderer/core/events/pointer_event.h"
+#include "third_party/blink/renderer/core/events/pointer_event_init.h"
+#include "third_party/blink/renderer/core/events/ui_event.h"
+#include "third_party/blink/renderer/core/events/ui_event_with_key_state.h"
+#include "third_party/blink/renderer/core/input/input_device_capabilities.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
+#include "third_party/blink/renderer/platform/wtf/casting.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+
+namespace blink {
+
+namespace {
+
+void PopulateSimulatedMouseEventInit(const AtomicString& event_type,
+                                     AbstractView* view,
+                                     const Event* underlying_event,
+                                     MouseEventInit* initializer) {
+  WebInputEvent::Modifiers modifiers = WebInputEvent::kNoModifiers;
+  if (const UIEventWithKeyState* key_state_event =
+          FindEventWithKeyState(underlying_event)) {
+    modifiers = key_state_event->GetModifiers();
+  }
+
+  if (const auto* mouse_event = DynamicTo<MouseEvent>(underlying_event)) {
+    initializer->setScreenX(mouse_event->screen_location_.X());
+    initializer->setScreenY(mouse_event->screen_location_.Y());
+    initializer->setSourceCapabilities(
+        view ? view->GetInputDeviceCapabilities()->FiresTouchEvents(false)
+             : nullptr);
+  }
+
+  initializer->setBubbles(true);
+  initializer->setCancelable(true);
+  initializer->setView(view);
+  initializer->setComposed(true);
+  UIEventWithKeyState::SetFromWebInputEventModifiers(initializer, modifiers);
+  initializer->setButtons(
+      MouseEvent::WebInputEventModifiersToButtons(modifiers));
+}
+
+enum class EventClassType { kMouse, kPointer };
+
+MouseEvent* CreateMouseOrPointerEvent(
+    EventClassType event_class_type,
+    const AtomicString& event_type,
+    AbstractView* view,
+    const Event* underlying_event,
+    SimulatedClickCreationScope creation_scope) {
+  // We picked |PointerEventInit| object to be able to create either
+  // |MouseEvent| or |PointerEvent| below.  When a |PointerEvent| is created,
+  // any event attributes not initialized in the |PointerEventInit| below get
+  // their default values, all of which are appropriate for a simulated
+  // |PointerEvent|.
+  //
+  // TODO(mustaq): Set |pointerId| to -1 after we have a spec change to fix the
+  // issue https://github.com/w3c/pointerevents/issues/343.
+  PointerEventInit* initializer = PointerEventInit::Create();
+  PopulateSimulatedMouseEventInit(event_type, view, underlying_event,
+                                  initializer);
+
+  base::TimeTicks timestamp = underlying_event
+                                  ? underlying_event->PlatformTimeStamp()
+                                  : base::TimeTicks::Now();
+  MouseEvent::SyntheticEventType synthetic_type = MouseEvent::kPositionless;
+  if (const auto* mouse_event = DynamicTo<MouseEvent>(underlying_event)) {
+    synthetic_type = MouseEvent::kRealOrIndistinguishable;
+  }
+
+  MouseEvent* created_event;
+  if (event_class_type == EventClassType::kPointer) {
+    created_event = MakeGarbageCollected<PointerEvent>(
+        event_type, initializer, timestamp, synthetic_type);
+  } else {
+    created_event = MakeGarbageCollected<MouseEvent>(event_type, initializer,
+                                                     timestamp, synthetic_type);
+  }
+
+  created_event->SetTrusted(creation_scope ==
+                            SimulatedClickCreationScope::kFromUserAgent);
+  created_event->SetUnderlyingEvent(underlying_event);
+  if (synthetic_type == MouseEvent::kRealOrIndistinguishable) {
+    auto* mouse_event = To<MouseEvent>(created_event->UnderlyingEvent());
+    created_event->InitCoordinates(mouse_event->client_location_.X(),
+                                   mouse_event->client_location_.Y());
+  }
+
+  return created_event;
+}
+
+}  // namespace
+
+Event* SimulatedEventUtil::CreateEvent(
+    const AtomicString& event_type,
+    AbstractView* view,
+    const Event* underlying_event,
+    SimulatedClickCreationScope creation_scope) {
+  DCHECK(event_type == event_type_names::kClick ||
+         event_type == event_type_names::kMousedown ||
+         event_type == event_type_names::kMouseup);
+
+  EventClassType event_class_type = EventClassType::kMouse;
+  if (RuntimeEnabledFeatures::ClickPointerEventEnabled() &&
+      event_type == event_type_names::kClick) {
+    event_class_type = EventClassType::kPointer;
+  }
+  return CreateMouseOrPointerEvent(event_class_type, event_type, view,
+                                   underlying_event, creation_scope);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/events/simulated_event_util.h b/third_party/blink/renderer/core/events/simulated_event_util.h
new file mode 100644
index 0000000..6a53b71
--- /dev/null
+++ b/third_party/blink/renderer/core/events/simulated_event_util.h
@@ -0,0 +1,28 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.sy
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_SIMULATED_EVENT_UTIL_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_SIMULATED_EVENT_UTIL_H_
+
+#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/dom/events/simulated_click_options.h"
+#include "third_party/blink/renderer/core/events/ui_event.h"
+#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
+
+namespace blink {
+
+class CORE_EXPORT SimulatedEventUtil {
+ public:
+  SimulatedEventUtil() = delete;
+
+  static Event* CreateEvent(const AtomicString& event_type,
+                            AbstractView* view,
+                            const Event* underlying_event,
+                            SimulatedClickCreationScope creation_scope);
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_EVENTS_SIMULATED_EVENT_UTIL_H_
diff --git a/third_party/blink/renderer/core/feature_policy/feature_policy_parser.cc b/third_party/blink/renderer/core/feature_policy/feature_policy_parser.cc
index 60f14297..0a988a6 100644
--- a/third_party/blink/renderer/core/feature_policy/feature_policy_parser.cc
+++ b/third_party/blink/renderer/core/feature_policy/feature_policy_parser.cc
@@ -407,12 +407,19 @@
     return {};
   }
 
-  // RFC2616, section 4.2 specifies that headers appearing multiple times can be
-  // combined with a comma. Walk the header string, and parse each comma
-  // separated chunk as a separate header.
   Vector<String> policy_items;
-  // policy_items = [ policy *( "," [ policy ] ) ]
-  policy.Split(',', policy_items);
+
+  if (src_origin_) {
+    // Attribute parsing.
+    policy_items.push_back(policy);
+  } else {
+    // Header parsing.
+    // RFC2616, section 4.2 specifies that headers appearing multiple times can
+    // be combined with a comma. Walk the header string, and parse each comma
+    // separated chunk as a separate header.
+    // policy_items = [ policy *( "," [ policy ] ) ]
+    policy.Split(',', policy_items);
+  }
 
   if (policy_items.size() > 1) {
     UseCounter::Count(
diff --git a/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc b/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc
index 49d7198..0a4e241 100644
--- a/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc
+++ b/third_party/blink/renderer/core/feature_policy/feature_policy_test.cc
@@ -34,7 +34,7 @@
 
 namespace {
 
-const char* const kValidPolicies[] = {
+const char* const kValidHeaderPolicies[] = {
     "",      // An empty policy.
     " ",     // An empty policy.
     ";;",    // Empty policies.
@@ -44,8 +44,7 @@
     ",;,",   // Empty policies.
     "geolocation 'none'",
     "geolocation 'self'",
-    "geolocation 'src'",  // Only valid for iframe allow attribute.
-    "geolocation",        // Only valid for iframe allow attribute.
+    "geolocation",
     "geolocation; fullscreen; payment",
     "geolocation *",
     "geolocation " ORIGIN_A "",
@@ -58,10 +57,11 @@
     "fullscreen  " ORIGIN_A "; payment 'self'",
     "fullscreen " ORIGIN_A "; payment *, geolocation 'self'"};
 
-const char* const kInvalidPolicies[] = {
+const char* const kInvalidHeaderPolicies[] = {
     "badfeaturename",
     "badfeaturename 'self'",
     "1.0",
+    "geolocation 'src'",  // Only valid for iframe allow attribute.
     "geolocation data://badorigin",
     "geolocation https://bad;origin",
     "geolocation https:/bad,origin",
@@ -301,7 +301,7 @@
         /* test_name */ "MultiplePoliciesIncludingBadFeatureName",
         /* feature_policy_string */
         "geolocation * " ORIGIN_B "; "
-        "fullscreen " ORIGIN_B " bad_feature_name " ORIGIN_C ","
+        "fullscreen " ORIGIN_B " bad_feature_name " ORIGIN_C ";"
         "payment 'self' badorigin",
         /* permissions_policy_string */
         "geolocation=(* \"" ORIGIN_B "\"),"
@@ -680,23 +680,50 @@
       });
 }
 
-TEST_F(FeaturePolicyParserTest, ParseValidPolicy) {
-  for (const char* policy_string : kValidPolicies) {
+TEST_F(FeaturePolicyParserParsingTest, CommaSeparatorInAttribute) {
+  PolicyParserMessageBuffer logger;
+
+  CheckParsedPolicy(
+      FeaturePolicyParser::ParseAttribute(
+          "geolocation 'none', fullscreen 'self'",
+          /* self_origin */ origin_a_.get(),
+          /* src_origin */ origin_a_.get(), logger, /* context */ nullptr),
+      {
+          {
+              mojom::blink::FeaturePolicyFeature::kGeolocation,
+              /* matches_all_origins */ false,
+              /* matches_opaque_src */ false,
+              {ORIGIN_A},
+          },
+      });
+
+  EXPECT_EQ(logger.GetMessages().size(), 2u)
+      << "Parser should report parsing error.";
+
+  EXPECT_EQ(logger.GetMessages().front().content.Ascii(),
+            "Unrecognized origin: ''none','.")
+      << "\"'none',\" should be treated as an invalid allowlist item ";
+
+  EXPECT_EQ(logger.GetMessages().back().content.Ascii(),
+            "Unrecognized origin: 'fullscreen'.")
+      << "\"fullscreen\" should be treated as an invalid allowlist item";
+}
+
+TEST_F(FeaturePolicyParserTest, ParseValidHeaderPolicy) {
+  for (const char* policy_string : kValidHeaderPolicies) {
     PolicyParserMessageBuffer logger;
     FeaturePolicyParser::ParseFeaturePolicyForTest(
-        policy_string, origin_a_.get(), origin_b_.get(), logger,
-        test_feature_name_map);
+        policy_string, origin_a_.get(), nullptr, logger, test_feature_name_map);
     EXPECT_EQ(0UL, logger.GetMessages().size())
         << "Should parse " << policy_string;
   }
 }
 
-TEST_F(FeaturePolicyParserTest, ParseInvalidPolicy) {
-  for (const char* policy_string : kInvalidPolicies) {
+TEST_F(FeaturePolicyParserTest, ParseInvalidHeaderPolicy) {
+  for (const char* policy_string : kInvalidHeaderPolicies) {
     PolicyParserMessageBuffer logger;
     FeaturePolicyParser::ParseFeaturePolicyForTest(
-        policy_string, origin_a_.get(), origin_b_.get(), logger,
-        test_feature_name_map);
+        policy_string, origin_a_.get(), nullptr, logger, test_feature_name_map);
     EXPECT_LT(0UL, logger.GetMessages().size())
         << "Should fail to parse " << policy_string;
   }
@@ -891,26 +918,18 @@
 
 const AllowlistHistogramData FeaturePolicyAllowlistHistogramTest::kCases[] = {
     {"Empty", "fullscreen", 1, {FeaturePolicyAllowlistType::kEmpty}},
-    {"Empty_MultipleDirectivesComma",
-     "fullscreen, geolocation, payment",
-     1,
-     {FeaturePolicyAllowlistType::kEmpty}},
     {"Empty_MultipleDirectivesSemicolon",
      "fullscreen; payment",
      1,
      {FeaturePolicyAllowlistType::kEmpty}},
     {"Star", "fullscreen *", 1, {FeaturePolicyAllowlistType::kStar}},
-    {"Star_MultipleDirectivesComma",
-     "fullscreen *, payment *",
-     1,
-     {FeaturePolicyAllowlistType::kStar}},
     {"Star_MultipleDirectivesSemicolon",
      "fullscreen *; payment *",
      1,
      {FeaturePolicyAllowlistType::kStar}},
     {"Self", "fullscreen 'self'", 1, {FeaturePolicyAllowlistType::kSelf}},
     {"Self_MultipleDirectives",
-     "fullscreen 'self', geolocation 'self', payment 'self'",
+     "fullscreen 'self'; geolocation 'self'; payment 'self'",
      1,
      {FeaturePolicyAllowlistType::kSelf}},
     {"None", "fullscreen 'none'", 1, {FeaturePolicyAllowlistType::kNone}},
@@ -922,10 +941,6 @@
      "fullscreen " ORIGIN_A,
      1,
      {FeaturePolicyAllowlistType::kOrigins}},
-    {"Origins_MultipleDirectivesComma",
-     "fullscreen " ORIGIN_A ", payment " ORIGIN_A,
-     1,
-     {FeaturePolicyAllowlistType::kOrigins}},
     {"Origins_MultipleDirectivesSemicolon",
      "fullscreen " ORIGIN_A "; payment " ORIGIN_A " " ORIGIN_B,
      1,
@@ -935,7 +950,7 @@
      1,
      {FeaturePolicyAllowlistType::kMixed}},
     {"Mixed_MultipleDirectives",
-     "fullscreen 'self' " ORIGIN_A ", payment 'none' " ORIGIN_A " " ORIGIN_B,
+     "fullscreen 'self' " ORIGIN_A "; payment 'none' " ORIGIN_A " " ORIGIN_B,
      1,
      {FeaturePolicyAllowlistType::kMixed}},
     {"KeywordsOnly",
@@ -954,11 +969,7 @@
      "fullscreen *; geolocation 'none' " ORIGIN_A,
      2,
      {FeaturePolicyAllowlistType::kStar, FeaturePolicyAllowlistType::kMixed}},
-    {"MultipleDirectives_SeparateTypes_Comma",
-     "fullscreen *, geolocation 'none', payment " ORIGIN_A " " ORIGIN_B,
-     3,
-     {FeaturePolicyAllowlistType::kStar, FeaturePolicyAllowlistType::kNone,
-      FeaturePolicyAllowlistType::kOrigins}}};
+};
 
 INSTANTIATE_TEST_SUITE_P(
     All,
diff --git a/third_party/blink/renderer/core/frame/deprecation.cc b/third_party/blink/renderer/core/frame/deprecation.cc
index cb4b28a..05c3c483 100644
--- a/third_party/blink/renderer/core/frame/deprecation.cc
+++ b/third_party/blink/renderer/core/frame/deprecation.cc
@@ -540,11 +540,6 @@
                   "RTCConfiguration.encodedInsertableStreams", kM88,
                   "6321945865879552")};
 
-    case WebFeature::kCommaSeparatorInAllowAttribute:
-      return {"CommaSeparatorInAllowAttribute", kM89,
-              ReplacedWillBeRemoved("Comma separator in iframe allow attribute",
-                                    "semicolons", kM89, "5740835259809792")};
-
     case WebFeature::kRTCConstraintEnableRtpDataChannelsTrue:
       return {"RTP data channel", kM88,
               ReplacedWillBeRemoved("RTP data channels",
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 f1e2b20..a4d7ca05 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -137,6 +137,31 @@
 
 namespace blink {
 
+namespace {
+
+constexpr size_t kMaxPostMessageUkmRecordedSourceIdsSize = 20;
+
+bool ShouldRecordPostMessageIncomingFrameUkmEvent(
+    ukm::SourceId source_frame_ukm_source_id,
+    Deque<ukm::SourceId>& already_recorded_source_frame_ids) {
+  DCHECK_LE(already_recorded_source_frame_ids.size(),
+            kMaxPostMessageUkmRecordedSourceIdsSize);
+
+  if (base::Contains(already_recorded_source_frame_ids,
+                     source_frame_ukm_source_id)) {
+    return false;
+  }
+
+  if (already_recorded_source_frame_ids.size() ==
+      kMaxPostMessageUkmRecordedSourceIdsSize) {
+    already_recorded_source_frame_ids.pop_back();
+  }
+  already_recorded_source_frame_ids.push_front(source_frame_ukm_source_id);
+  return true;
+}
+
+}  // namespace
+
 LocalDOMWindow::LocalDOMWindow(LocalFrame& frame, WindowAgent* agent)
     : DOMWindow(frame),
       ExecutionContext(V8PerIsolateData::MainThreadIsolate(), agent),
@@ -945,9 +970,13 @@
     scoped_refptr<const SecurityOrigin> target,
     LocalDOMWindow* source) {
   // Record UKM metrics for postMessage event.
-  ukm::builders::PostMessage_Incoming_Frame(UkmSourceID())
-      .SetSourceFrameSourceId(source->UkmSourceID())
-      .Record(UkmRecorder());
+  ukm::SourceId source_frame_ukm_source_id = source->UkmSourceID();
+  if (ShouldRecordPostMessageIncomingFrameUkmEvent(
+          source_frame_ukm_source_id, post_message_ukm_recorded_source_ids_)) {
+    ukm::builders::PostMessage_Incoming_Frame(UkmSourceID())
+        .SetSourceFrameSourceId(source_frame_ukm_source_id)
+        .Record(UkmRecorder());
+  }
 
   // Allowing unbounded amounts of messages to build up for a suspended context
   // is problematic; consider imposing a limit or other restriction if this
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 4e028a6..66195a8 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.h
+++ b/third_party/blink/renderer/core/frame/local_dom_window.h
@@ -531,6 +531,13 @@
   // this document, to avoid reporting duplicates. The value stored comes
   // from |DocumentPolicyViolationReport::MatchId()|.
   mutable HashSet<unsigned> document_policy_violation_reports_sent_;
+
+  // A list of the most recently recorded source frame UKM source IDs for the
+  // PostMessage.Incoming.Frame UKM event, in order to partially deduplicate
+  // logged events. Its size is limited to 20. See SchedulePostMessage() where
+  // this UKM is logged.
+  // TODO(crbug.com/1112491): Remove when no longer needed.
+  Deque<ukm::SourceId> post_message_ukm_recorded_source_ids_;
 };
 
 template <>
diff --git a/third_party/blink/renderer/core/html/conversion_measurement_parsing.cc b/third_party/blink/renderer/core/html/conversion_measurement_parsing.cc
index a2165c74..f2a1eb8 100644
--- a/third_party/blink/renderer/core/html/conversion_measurement_parsing.cc
+++ b/third_party/blink/renderer/core/html/conversion_measurement_parsing.cc
@@ -72,7 +72,7 @@
 
   bool impression_data_is_valid = false;
   uint64_t impression_data =
-      impression_data_string.ToUInt64Strict(&impression_data_is_valid);
+      impression_data_string.HexToUInt64Strict(&impression_data_is_valid);
 
   // Provide a default of 0 if the impression data was not valid.
   impression_data = impression_data_is_valid ? impression_data : 0UL;
diff --git a/third_party/blink/renderer/core/html/html_iframe_element.cc b/third_party/blink/renderer/core/html/html_iframe_element.cc
index d5ef5c36..420308b 100644
--- a/third_party/blink/renderer/core/html/html_iframe_element.cc
+++ b/third_party/blink/renderer/core/html/html_iframe_element.cc
@@ -39,7 +39,6 @@
 #include "third_party/blink/renderer/core/feature_policy/iframe_policy.h"
 #include "third_party/blink/renderer/core/fetch/trust_token_issuance_authorization.h"
 #include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
-#include "third_party/blink/renderer/core/frame/deprecation.h"
 #include "third_party/blink/renderer/core/html/html_document.h"
 #include "third_party/blink/renderer/core/html/trust_token_attribute_parsing.h"
 #include "third_party/blink/renderer/core/html_names.h"
@@ -229,11 +228,6 @@
         UseCounter::Count(GetDocument(),
                           WebFeature::kFeaturePolicyAllowAttribute);
       }
-      if (value.Contains(',')) {
-        Deprecation::CountDeprecation(
-            GetDocument().GetExecutionContext(),
-            WebFeature::kCommaSeparatorInAllowAttribute);
-      }
     }
   } else if (name == html_names::kDisallowdocumentaccessAttr &&
              RuntimeEnabledFeatures::DisallowDocumentAccessEnabled()) {
diff --git a/third_party/blink/renderer/core/html/html_iframe_element_test.cc b/third_party/blink/renderer/core/html/html_iframe_element_test.cc
index e3dc8b5b..32d553b 100644
--- a/third_party/blink/renderer/core/html/html_iframe_element_test.cc
+++ b/third_party/blink/renderer/core/html/html_iframe_element_test.cc
@@ -324,26 +324,4 @@
       << ConsoleMessages().front();
 }
 
-TEST_F(HTMLIFrameElementSimTest, CommaSeparatorIsDeprecated) {
-  EXPECT_FALSE(
-      GetDocument().Loader()->GetUseCounterHelper().HasRecordedMeasurement(
-          WebFeature::kCommaSeparatorInAllowAttribute));
-  SimRequest main_resource("https://example.com", "text/html");
-  LoadURL("https://example.com");
-  main_resource.Complete(R"(
-    <iframe
-      allow="fullscreen, geolocation"></iframe>
-  )");
-
-  EXPECT_EQ(ConsoleMessages().size(), 1u)
-      << "Comma separator in allow attribute should log a deprecation message "
-         "to the console.";
-  EXPECT_TRUE(ConsoleMessages().front().Contains("5740835259809792"))
-      << "Console message should mention the chromestatus entry.";
-
-  EXPECT_TRUE(
-      GetDocument().Loader()->GetUseCounterHelper().HasRecordedMeasurement(
-          WebFeature::kCommaSeparatorInAllowAttribute));
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/input/event_handler.cc b/third_party/blink/renderer/core/input/event_handler.cc
index ee21abd..9f34353 100644
--- a/third_party/blink/renderer/core/input/event_handler.cc
+++ b/third_party/blink/renderer/core/input/event_handler.cc
@@ -300,10 +300,8 @@
   AutoscrollController* controller = scroll_manager_->GetAutoscrollController();
   if (!controller)
     return;
-
   LayoutBox* scrollable = LayoutBox::FindAutoscrollable(
       layout_object, /*is_middle_click_autoscroll*/ true);
-
   controller->StartMiddleClickAutoscroll(
       layout_object->GetFrame(), scrollable,
       LastKnownMousePositionInRootFrame(),
diff --git a/third_party/blink/renderer/core/input/scroll_manager.cc b/third_party/blink/renderer/core/input/scroll_manager.cc
index 03f663a..8fb4fb4 100644
--- a/third_party/blink/renderer/core/input/scroll_manager.cc
+++ b/third_party/blink/renderer/core/input/scroll_manager.cc
@@ -133,20 +133,8 @@
   return nullptr;
 }
 
-ScrollPropagationDirection ScrollManager::ComputePropagationDirection(
-    const ScrollState& scroll_state) {
-  if (scroll_state.deltaXHint() == 0 && scroll_state.deltaYHint() != 0)
-    return ScrollPropagationDirection::kVertical;
-  if (scroll_state.deltaXHint() != 0 && scroll_state.deltaYHint() == 0)
-    return ScrollPropagationDirection::kHorizontal;
-  if (scroll_state.deltaXHint() != 0 && scroll_state.deltaYHint() != 0)
-    return ScrollPropagationDirection::kBoth;
-  return ScrollPropagationDirection::kNone;
-}
-
-bool ScrollManager::CanPropagate(const LayoutBox* layout_box,
-                                 ScrollPropagationDirection direction) {
-  ScrollableArea* scrollable_area = layout_box->GetScrollableArea();
+static bool CanPropagate(const ScrollState& scroll_state, const Node& node) {
+  ScrollableArea* scrollable_area = node.GetLayoutBox()->GetScrollableArea();
   if (!scrollable_area)
     return true;
 
@@ -154,106 +142,54 @@
       !scrollable_area->UserInputScrollable(kVerticalScrollbar))
     return true;
 
-  switch (direction) {
-    case ScrollPropagationDirection::kBoth:
-      return ((layout_box->StyleRef().OverscrollBehaviorX() ==
-               EOverscrollBehavior::kAuto) &&
-              (layout_box->StyleRef().OverscrollBehaviorY() ==
-               EOverscrollBehavior::kAuto));
-    case ScrollPropagationDirection::kVertical:
-      return layout_box->StyleRef().OverscrollBehaviorY() ==
-             EOverscrollBehavior::kAuto;
-    case ScrollPropagationDirection::kHorizontal:
-      return layout_box->StyleRef().OverscrollBehaviorX() ==
-             EOverscrollBehavior::kAuto;
-    case ScrollPropagationDirection::kNone:
-      return true;
-    default:
-      NOTREACHED();
-  }
+  return (scroll_state.deltaXHint() == 0 ||
+          node.GetComputedStyle()->OverscrollBehaviorX() ==
+              EOverscrollBehavior::kAuto) &&
+         (scroll_state.deltaYHint() == 0 ||
+          node.GetComputedStyle()->OverscrollBehaviorY() ==
+              EOverscrollBehavior::kAuto);
 }
 
 void ScrollManager::RecomputeScrollChain(const Node& start_node,
                                          const ScrollState& scroll_state,
-                                         Deque<DOMNodeId>& scroll_chain,
-                                         bool is_autoscroll) {
+                                         Deque<DOMNodeId>& scroll_chain) {
   DCHECK(scroll_chain.IsEmpty());
   scroll_chain.clear();
 
   DCHECK(start_node.GetLayoutObject());
+  LayoutBox* cur_box = start_node.GetLayoutObject()->EnclosingBox();
 
-  if (is_autoscroll) {
-    // Propagate the autoscroll along the layout object chain, and
-    // append only the first node which is able to consume the scroll delta.
-    // The scroll node is computed differently to regular scrolls in order to
-    // maintain consistency with the autoscroll controller.
-    LayoutBox* autoscrollable = LayoutBox::FindAutoscrollable(
-        start_node.GetLayoutObject(), is_autoscroll);
-    if (autoscrollable) {
-      Node* cur_node = autoscrollable->GetNode();
-      LayoutObject* layout_object = cur_node->GetLayoutObject();
-      while (layout_object &&
-             !CanScroll(scroll_state, *cur_node, is_autoscroll)) {
-        ScrollPropagationDirection direction =
-            ComputePropagationDirection(scroll_state);
+  // Scrolling propagates along the containing block chain and ends at the
+  // RootScroller node. The RootScroller node will have a custom applyScroll
+  // callback that performs scrolling as well as associated "root" actions like
+  // browser control movement and overscroll glow.
+  while (cur_box) {
+    Node* cur_node = cur_box->GetNode();
 
-        if (!CanPropagate(cur_node->GetLayoutBox(), direction))
-          break;
+    if (cur_node) {
+      if (CanScroll(scroll_state, *cur_node))
+        scroll_chain.push_front(DOMNodeIds::IdForNode(cur_node));
 
-        if (!layout_object->Parent() &&
-            layout_object->GetNode() == layout_object->GetDocument() &&
-            layout_object->GetDocument().LocalOwner()) {
-          layout_object =
-              layout_object->GetDocument().LocalOwner()->GetLayoutObject();
-        } else {
-          layout_object = layout_object->Parent();
-        }
-        LayoutBox* new_autoscrollable =
-            LayoutBox::FindAutoscrollable(layout_object, is_autoscroll);
-        if (new_autoscrollable)
-          cur_node = new_autoscrollable->GetNode();
-      }
-      scroll_chain.push_front(DOMNodeIds::IdForNode(cur_node));
-    }
-  } else {
-    LayoutBox* cur_box = start_node.GetLayoutObject()->EnclosingBox();
+      if (cur_node->IsEffectiveRootScroller())
+        break;
 
-    // Scrolling propagates along the containing block chain and ends at the
-    // RootScroller node. The RootScroller node will have a custom applyScroll
-    // callback that performs scrolling as well as associated "root" actions
-    // like browser control movement and overscroll glow.
-    while (cur_box) {
-      Node* cur_node = cur_box->GetNode();
-
-      if (cur_node) {
-        if (CanScroll(scroll_state, *cur_node, /* for_autoscroll */ false))
+      if (!CanPropagate(scroll_state, *cur_node)) {
+        // We should add the first node with non-auto overscroll-behavior to
+        // the scroll chain regardlessly, as it's the only node we can latch to.
+        if (scroll_chain.empty() ||
+            scroll_chain.front() != DOMNodeIds::IdForNode(cur_node)) {
           scroll_chain.push_front(DOMNodeIds::IdForNode(cur_node));
-
-        if (cur_node->IsEffectiveRootScroller())
-          break;
-
-        ScrollPropagationDirection direction =
-            ComputePropagationDirection(scroll_state);
-        if (!CanPropagate(cur_node->GetLayoutBox(), direction)) {
-          // We should add the first node with non-auto overscroll-behavior to
-          // the scroll chain regardlessly, as it's the only node we can latch
-          // to.
-          if (scroll_chain.empty() ||
-              scroll_chain.front() != DOMNodeIds::IdForNode(cur_node)) {
-            scroll_chain.push_front(DOMNodeIds::IdForNode(cur_node));
-          }
-          break;
         }
+        break;
       }
-
-      cur_box = cur_box->ContainingBlock();
     }
+
+    cur_box = cur_box->ContainingBlock();
   }
 }
 
 bool ScrollManager::CanScroll(const ScrollState& scroll_state,
-                              const Node& current_node,
-                              bool for_autoscroll) {
+                              const Node& current_node) {
   LayoutBox* scrolling_box = current_node.GetLayoutBox();
   if (auto* element = DynamicTo<Element>(current_node))
     scrolling_box = element->GetLayoutBoxForScrolling();
@@ -262,9 +198,8 @@
 
   // We need to always add the global root scroller even if it isn't scrollable
   // since we can always pinch-zoom and scroll as well as for overscroll
-  // effects. If autoscrolling, ignore this condition because we latch on
-  // to the deepest autoscrollable node.
-  if (scrolling_box->IsGlobalRootScroller() && !for_autoscroll)
+  // effects.
+  if (scrolling_box->IsGlobalRootScroller())
     return true;
 
   // If this is the main LayoutView, and it's not the root scroller, that means
@@ -272,10 +207,9 @@
   // scroll the LayoutView should cause panning of the visual viewport as well
   // so ensure it gets added to the scroll chain. See LTHI::ApplyScroll for the
   // equivalent behavior in CC. Node::NativeApplyScroll contains a special
-  // handler for this case. If autoscrolling, ignore this condition because we
-  // latch on to the deepest autoscrollable node.
+  // handler for this case.
   if (IsA<LayoutView>(scrolling_box) &&
-      current_node.GetDocument().GetFrame()->IsMainFrame() && !for_autoscroll) {
+      current_node.GetDocument().GetFrame()->IsMainFrame()) {
     return true;
   }
 
@@ -339,8 +273,7 @@
       std::make_unique<ScrollStateData>();
   auto* scroll_state =
       MakeGarbageCollected<ScrollState>(std::move(scroll_state_data));
-  RecomputeScrollChain(*node, *scroll_state, scroll_chain,
-                       /* is_autoscroll */ false);
+  RecomputeScrollChain(*node, *scroll_state, scroll_chain);
 
   while (!scroll_chain.IsEmpty()) {
     Node* scroll_chain_node = DOMNodeIds::NodeForId(scroll_chain.TakeLast());
@@ -564,11 +497,21 @@
       delta_consumed_for_scroll_sequence_;
   auto* scroll_state =
       MakeGarbageCollected<ScrollState>(std::move(scroll_state_data));
-
-  RecomputeScrollChain(
-      *scroll_gesture_handling_node_.Get(), *scroll_state,
-      current_scroll_chain_,
-      gesture_event.SourceDevice() == WebGestureDevice::kSyntheticAutoscroll);
+  // For middle click autoscroll, only scrollable area for
+  // |scroll_gesture_handling_node_| should receive and handle all scroll
+  // events. It should not bubble up to the ancestor.
+  if (gesture_event.SourceDevice() == WebGestureDevice::kSyntheticAutoscroll) {
+    LayoutBox* scrollable = LayoutBox::FindAutoscrollable(
+        scroll_gesture_handling_node_->GetLayoutObject(),
+        /*is_middle_click_autoscroll*/ true);
+    if (scrollable) {
+      Node* scrollable_node = scrollable->GetNode();
+      current_scroll_chain_.push_back(DOMNodeIds::IdForNode(scrollable_node));
+    }
+  } else {
+    RecomputeScrollChain(*scroll_gesture_handling_node_.Get(), *scroll_state,
+                         current_scroll_chain_);
+  }
 
   TRACE_EVENT_INSTANT1("input", "Computed Scroll Chain",
                        TRACE_EVENT_SCOPE_THREAD, "length",
diff --git a/third_party/blink/renderer/core/input/scroll_manager.h b/third_party/blink/renderer/core/input/scroll_manager.h
index 7ea7463..dd372e74 100644
--- a/third_party/blink/renderer/core/input/scroll_manager.h
+++ b/third_party/blink/renderer/core/input/scroll_manager.h
@@ -34,10 +34,6 @@
 class ScrollState;
 class WebGestureEvent;
 
-// Scroll directions used to check whether propagation is possible in a given
-// direction. Used in CanPropagate.
-enum class ScrollPropagationDirection { kHorizontal, kVertical, kBoth, kNone };
-
 // This class takes care of scrolling and resizing and the related states. The
 // user action that causes scrolling or resizing is determined in other *Manager
 // classes and they call into this class for doing the work.
@@ -112,13 +108,6 @@
 
   void AnimateSnapFling(base::TimeTicks monotonic_time);
 
-  // Determines whether the scroll-chain should be propagated upwards given a
-  // scroll direction.
-  static bool CanPropagate(const LayoutBox* layout_box,
-                           ScrollPropagationDirection direction);
-  static ScrollPropagationDirection ComputePropagationDirection(
-      const ScrollState&);
-
  private:
   Node* NodeTargetForScrollableAreaElementId(
       CompositorElementId scrollable_area_element_id) const;
@@ -144,11 +133,8 @@
 
   void RecomputeScrollChain(const Node& start_node,
                             const ScrollState&,
-                            Deque<DOMNodeId>& scroll_chain,
-                            bool is_autoscroll);
-  bool CanScroll(const ScrollState&,
-                 const Node& current_node,
-                 bool for_autoscroll);
+                            Deque<DOMNodeId>& scroll_chain);
+  bool CanScroll(const ScrollState&, const Node& current_node);
 
   // scroller_size is set only when scrolling non root scroller.
   void ComputeScrollRelatedMetrics(
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc
index 1ca7b06..ae58ea6 100644
--- a/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc
+++ b/third_party/blink/renderer/core/intersection_observer/intersection_observation.cc
@@ -105,13 +105,15 @@
     return false;
 
   // If we're processing post-layout deliveries only and we don't have a
-  // post-layout delivery observer, then return early.
-  if (flags & kPostLayoutDeliveryOnly) {
-    if (Observer()->GetDeliveryBehavior() !=
-        IntersectionObserver::kDeliverDuringPostLayoutSteps) {
-      return false;
-    }
-  }
+  // post-layout delivery observer, then return early. Likewise, return if we
+  // need to compute non-post-layout-delivery observations but the observer
+  // behavior is post-layout.
+  bool post_layout_delivery_only = flags & kPostLayoutDeliveryOnly;
+  bool is_post_layout_delivery_observer =
+      Observer()->GetDeliveryBehavior() ==
+      IntersectionObserver::kDeliverDuringPostLayoutSteps;
+  if (post_layout_delivery_only != is_post_layout_delivery_observer)
+    return false;
 
   if (flags &
       (observer_->RootIsImplicit() ? kImplicitRootObserversNeedUpdate
diff --git a/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc b/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc
index 3f75b6e..3df5c5b 100644
--- a/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc
+++ b/third_party/blink/renderer/core/intersection_observer/intersection_observer.cc
@@ -445,11 +445,16 @@
     return false;
 
   // If we're processing post-layout deliveries only and we're not a post-layout
-  // delivery observer, then return early.
-  if (flags & IntersectionObservation::kPostLayoutDeliveryOnly) {
-    if (GetDeliveryBehavior() != kDeliverDuringPostLayoutSteps)
-      return false;
-  }
+  // delivery observer, then return early. Likewise, return if we need to
+  // compute non-post-layout-delivery observations but the observer behavior is
+  // post-layout.
+  bool post_layout_delivery_only =
+      flags & IntersectionObservation::kPostLayoutDeliveryOnly;
+  bool is_post_layout_delivery_observer =
+      GetDeliveryBehavior() ==
+      IntersectionObserver::kDeliverDuringPostLayoutSteps;
+  if (post_layout_delivery_only != is_post_layout_delivery_observer)
+    return false;
 
   IntersectionGeometry::RootGeometry root_geometry(
       IntersectionGeometry::GetRootLayoutObjectForTarget(root(), nullptr,
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index c68d6bb..1881c64 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -4523,7 +4523,8 @@
 }
 
 bool LayoutObject::IsAllowedToModifyLayoutTreeStructure(Document& document) {
-  return document.Lifecycle().StateAllowsLayoutTreeMutations();
+  return document.Lifecycle().StateAllowsLayoutTreeMutations() ||
+         document.GetStyleEngine().InContainerQueryStyleRecalc();
 }
 
 void LayoutObject::SetSubtreeShouldDoFullPaintInvalidation(
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
index 705b9d8..82ee0ad 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
@@ -64,18 +64,12 @@
 
   // Place grid and out of flow items.
   LayoutUnit intrinsic_block_size;
+  LayoutUnit block_size;
   PlaceItems(grid_items, algorithm_column_track_collection,
              algorithm_row_track_collection, &out_of_flow_items,
-             &intrinsic_block_size);
+             &intrinsic_block_size, &block_size);
 
-  intrinsic_block_size =
-      ClampIntrinsicBlockSize(ConstraintSpace(), Node(),
-                              BorderScrollbarPadding(), intrinsic_block_size);
   container_builder_.SetIntrinsicBlockSize(intrinsic_block_size);
-
-  LayoutUnit block_size = ComputeBlockSizeForFragment(
-      ConstraintSpace(), Style(), BorderPadding(), intrinsic_block_size,
-      border_box_size_.inline_size);
   container_builder_.SetFragmentsTotalBlockSize(block_size);
 
   NGOutOfFlowLayoutPart(Node(), ConstraintSpace(), &container_builder_).Run();
@@ -1252,8 +1246,10 @@
     const NGGridLayoutAlgorithmTrackCollection& column_track_collection,
     const NGGridLayoutAlgorithmTrackCollection& row_track_collection,
     Vector<GridItemData>* out_of_flow_items,
-    LayoutUnit* intrinsic_block_size) {
+    LayoutUnit* intrinsic_block_size,
+    LayoutUnit* block_size) {
   DCHECK(intrinsic_block_size);
+  DCHECK(block_size);
   LayoutUnit column_grid_gap =
       GridGap(kForColumns, ChildAvailableSize().inline_size);
   LayoutUnit row_grid_gap = GridGap(kForRows, ChildAvailableSize().block_size);
@@ -1269,20 +1265,35 @@
       (row_set_offsets.size() == 1 ? LayoutUnit() : row_grid_gap) +
       BorderScrollbarPadding().block_end;
 
+  *intrinsic_block_size =
+      ClampIntrinsicBlockSize(ConstraintSpace(), Node(),
+                              BorderScrollbarPadding(), *intrinsic_block_size);
+
+  *block_size = ComputeBlockSizeForFragment(
+      ConstraintSpace(), Style(), BorderPadding(), *intrinsic_block_size,
+      border_box_size_.inline_size);
+
   // If the row gap is percent or calc, it should be computed now that the
   // intrinsic size is known. However, the gap should not be added to the
   // intrinsic block size.
-  if (IsRowGridGapUnresolvable(ChildAvailableSize().block_size)) {
-    row_grid_gap = GridGap(kForRows, *intrinsic_block_size);
+  const bool is_row_gap_unresolvable =
+      Style().RowGap() && Style().RowGap()->IsPercentOrCalc() &&
+      ChildAvailableSize().block_size == kIndefiniteSize;
+  if (is_row_gap_unresolvable) {
+    const LayoutUnit resolved_available_block_size =
+        (*block_size - BorderScrollbarPadding().BlockSum())
+            .ClampNegativeToZero();
+
+    row_grid_gap = GridGap(kForRows, resolved_available_block_size);
     row_set_offsets = ComputeSetOffsets(row_track_collection, row_grid_gap);
   }
 
-  PlaceGridItems(grid_items, column_set_offsets, row_set_offsets,
-                 *intrinsic_block_size, column_grid_gap, row_grid_gap);
+  PlaceGridItems(grid_items, column_set_offsets, row_set_offsets, *block_size,
+                 column_grid_gap, row_grid_gap);
 
   PlaceOutOfFlowItems(column_set_offsets, row_set_offsets,
                       column_track_collection, row_track_collection,
-                      *intrinsic_block_size, column_grid_gap, row_grid_gap,
+                      *block_size, column_grid_gap, row_grid_gap,
                       out_of_flow_items);
 }
 
@@ -1292,10 +1303,14 @@
   const base::Optional<Length>& gap =
       track_direction == kForColumns ? Style().ColumnGap() : Style().RowGap();
 
+  if (!gap)
+    return LayoutUnit();
+
   // TODO(ansollan): Update behavior based on outcome of working group
   // discussions. See https://github.com/w3c/csswg-drafts/issues/5566.
-  if (!gap || IsRowGridGapUnresolvable(available_size))
-    return LayoutUnit();
+  if (available_size == kIndefiniteSize)
+    available_size = LayoutUnit();
+
   return MinimumValueForLength(*gap, available_size);
 }
 
@@ -1316,13 +1331,6 @@
   return set_offsets;
 }
 
-bool NGGridLayoutAlgorithm::IsRowGridGapUnresolvable(
-    LayoutUnit available_size) const {
-  const base::Optional<Length>& row_gap = Style().RowGap();
-  return row_gap && row_gap->IsPercentOrCalc() &&
-         available_size == kIndefiniteSize;
-}
-
 namespace {
 
 // Returns the alignment offset for either the inline or block direction.
@@ -1390,7 +1398,7 @@
     const Vector<GridItemData>& grid_items,
     const Vector<LayoutUnit>& column_set_offsets,
     const Vector<LayoutUnit>& row_set_offsets,
-    LayoutUnit intrinsic_block_size,
+    LayoutUnit block_size,
     LayoutUnit column_grid_gap,
     LayoutUnit row_grid_gap) {
   for (const GridItemData& grid_item : grid_items) {
@@ -1400,7 +1408,7 @@
                          &offset.inline_offset, &size.inline_size);
     ComputeOffsetAndSize(grid_item, row_set_offsets, row_grid_gap,
                          &offset.block_offset, &size.block_size, kForRows,
-                         intrinsic_block_size);
+                         block_size);
     const auto& item_style = grid_item.node.Style();
     NGConstraintSpaceBuilder builder(ConstraintSpace(),
                                      item_style.GetWritingDirection(),
@@ -1439,7 +1447,7 @@
     const Vector<LayoutUnit>& row_set_offsets,
     const NGGridLayoutAlgorithmTrackCollection& column_track_collection,
     const NGGridLayoutAlgorithmTrackCollection& row_track_collection,
-    LayoutUnit intrinsic_block_size,
+    LayoutUnit block_size,
     LayoutUnit column_grid_gap,
     LayoutUnit row_grid_gap,
     Vector<GridItemData>* out_of_flow_items) {
@@ -1455,7 +1463,7 @@
     ComputeOffsetAndSize(out_of_flow_item, row_set_offsets, row_grid_gap,
                          &containing_block_rect.offset.block_offset,
                          &containing_block_rect.size.block_size, kForRows,
-                         intrinsic_block_size);
+                         block_size);
     NGLogicalStaticPosition::InlineEdge inline_edge;
     NGLogicalStaticPosition::BlockEdge block_edge;
     LogicalOffset child_offset = containing_block_rect.offset;
@@ -1477,7 +1485,7 @@
     LayoutUnit* start_offset,
     LayoutUnit* size,
     GridTrackSizingDirection track_direction,
-    LayoutUnit intrinsic_block_size) const {
+    LayoutUnit block_size) const {
   wtf_size_t start_index, end_index;
   LayoutUnit border;
   // The default padding box value of the |size| will only be used in out of
@@ -1493,7 +1501,7 @@
     end_index = item.rows_end_set_index;
     border = container_builder_.Borders().block_start;
     *size = border_box_size_.block_size == kIndefiniteSize
-                ? intrinsic_block_size
+                ? block_size
                 : border_box_size_.block_size;
     *size -= container_builder_.Borders().BlockSum();
   }
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h
index 1d2273e..5996dea 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h
@@ -225,7 +225,8 @@
       const NGGridLayoutAlgorithmTrackCollection& column_track_collection,
       const NGGridLayoutAlgorithmTrackCollection& row_track_collection,
       Vector<GridItemData>* out_of_flow_items,
-      LayoutUnit* intrinsic_block_size);
+      LayoutUnit* intrinsic_block_size,
+      LayoutUnit* block_size);
 
   // Gets the row or column gap of the grid.
   LayoutUnit GridGap(GridTrackSizingDirection track_direction,
@@ -236,10 +237,6 @@
       const NGGridLayoutAlgorithmTrackCollection& track_collection,
       LayoutUnit grid_gap) const;
 
-  // Tests whether the row gap is unresolvable based on its type and the
-  // available size.
-  bool IsRowGridGapUnresolvable(LayoutUnit available_size) const;
-
   // Layout the |grid_items| based on the offsets provided.
   void PlaceGridItems(const Vector<GridItemData>& grid_items,
                       const Vector<LayoutUnit>& column_set_offsets,
@@ -255,7 +252,7 @@
       const Vector<LayoutUnit>& row_set_offsets,
       const NGGridLayoutAlgorithmTrackCollection& column_track_collection,
       const NGGridLayoutAlgorithmTrackCollection& row_track_collection,
-      LayoutUnit intrinsic_block_size,
+      LayoutUnit block_size,
       LayoutUnit column_grid_gap,
       LayoutUnit row_grid_gap,
       Vector<GridItemData>* out_of_flow_items);
@@ -268,7 +265,7 @@
       LayoutUnit* start_offset,
       LayoutUnit* size,
       GridTrackSizingDirection track_direction = kForColumns,
-      const LayoutUnit intrinsic_block_size = LayoutUnit()) const;
+      const LayoutUnit block_size = LayoutUnit()) const;
 
   // Determines the position of the out of flow item's container.
   void DeterminePositionOfOutOfFlowContainer(
diff --git a/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc b/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc
index a2d2cbb..54a93a6 100644
--- a/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc
+++ b/third_party/blink/renderer/core/origin_trials/origin_trial_context.cc
@@ -384,7 +384,10 @@
       !base::FeatureList::IsEnabled(network::features::kTrustTokens)) {
     return false;
   }
-
+  if (trial_name == "InterestCohortAPI" &&
+      !base::FeatureList::IsEnabled(features::kInterestCohortAPIOriginTrial)) {
+    return false;
+  }
   return true;
 }
 
diff --git a/third_party/blink/renderer/core/page/autoscroll_controller.cc b/third_party/blink/renderer/core/page/autoscroll_controller.cc
index d1dc0dc..84e4f01 100644
--- a/third_party/blink/renderer/core/page/autoscroll_controller.cc
+++ b/third_party/blink/renderer/core/page/autoscroll_controller.cc
@@ -29,13 +29,11 @@
 
 #include "third_party/blink/renderer/core/page/autoscroll_controller.h"
 
-#include "third_party/blink/renderer/core/dom/node_computed_style.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
 #include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
 #include "third_party/blink/renderer/core/input/event_handler.h"
-#include "third_party/blink/renderer/core/input/scroll_manager.h"
 #include "third_party/blink/renderer/core/layout/hit_test_result.h"
 #include "third_party/blink/renderer/core/layout/layout_box.h"
 #include "third_party/blink/renderer/core/page/chrome_client.h"
@@ -145,18 +143,6 @@
   if (pressed_layout_object_ == layout_object)
     pressed_layout_object_ = nullptr;
 
-  if (horizontal_autoscroll_layout_box_ == layout_object)
-    horizontal_autoscroll_layout_box_ = nullptr;
-
-  if (vertical_autoscroll_layout_box_ == layout_object)
-    vertical_autoscroll_layout_box_ = nullptr;
-
-  if (MiddleClickAutoscrollInProgress() && !horizontal_autoscroll_layout_box_ &&
-      !vertical_autoscroll_layout_box_) {
-    page_->GetChromeClient().AutoscrollEnd(layout_object->GetFrame());
-    autoscroll_type_ = kNoAutoscroll;
-  }
-
   if (autoscroll_layout_object_ != layout_object)
     return;
   autoscroll_layout_object_ = nullptr;
@@ -264,16 +250,7 @@
   if (!MiddleClickAutoscrollInProgress())
     return;
 
-  bool horizontal_autoscroll_possible =
-      horizontal_autoscroll_layout_box_ &&
-      horizontal_autoscroll_layout_box_->GetNode();
-  bool vertical_autoscroll_possible =
-      vertical_autoscroll_layout_box_ &&
-      vertical_autoscroll_layout_box_->GetNode();
-  if (horizontal_autoscroll_possible &&
-      !horizontal_autoscroll_layout_box_->CanBeScrolledAndHasScrollableArea() &&
-      vertical_autoscroll_possible &&
-      !vertical_autoscroll_layout_box_->CanBeScrolledAndHasScrollableArea()) {
+  if (!autoscroll_layout_object_->CanBeScrolledAndHasScrollableArea()) {
     StopMiddleClickAutoscroll(frame);
     return;
   }
@@ -300,17 +277,11 @@
       pow(fabs(distance.Height()), kExponent) * kMultiplier * y_signum);
 
   bool can_scroll_vertically =
-      vertical_autoscroll_possible
-          ? CanScrollDirection(vertical_autoscroll_layout_box_,
-                               frame->GetPage(),
-                               ScrollOrientation::kVerticalScroll)
-          : false;
+      CanScrollDirection(autoscroll_layout_object_, frame->GetPage(),
+                         ScrollOrientation::kVerticalScroll);
   bool can_scroll_horizontally =
-      horizontal_autoscroll_possible
-          ? CanScrollDirection(horizontal_autoscroll_layout_box_,
-                               frame->GetPage(),
-                               ScrollOrientation::kHorizontalScroll)
-          : false;
+      CanScrollDirection(autoscroll_layout_object_, frame->GetPage(),
+                         ScrollOrientation::kHorizontalScroll);
 
   if (velocity != last_velocity_) {
     last_velocity_ = velocity;
@@ -348,8 +319,7 @@
   autoscroll_type_ = kNoAutoscroll;
   page_->GetChromeClient().SetCursorOverridden(false);
   frame->LocalFrameRoot().GetEventHandler().UpdateCursor();
-  horizontal_autoscroll_layout_box_ = nullptr;
-  vertical_autoscroll_layout_box_ = nullptr;
+  autoscroll_layout_object_ = nullptr;
 }
 
 bool AutoscrollController::MiddleClickAutoscrollInProgress() const {
@@ -368,68 +338,17 @@
   if (autoscroll_type_ != kNoAutoscroll)
     return;
 
+  autoscroll_layout_object_ = scrollable;
   autoscroll_type_ = kAutoscrollForMiddleClick;
   middle_click_mode_ = kMiddleClickInitial;
   middle_click_autoscroll_start_pos_global_ = position_global;
 
-  bool can_scroll_vertically = false;
-  bool can_scroll_horizontally = false;
-
-  // Scroll propagation can be prevented in either direction independently.
-  // We check whether autoscroll can be prevented in either direction after
-  // checking whether the layout box can be scrolled. If propagation is not
-  // allowed, we do not perform further checks for whether parents can be
-  // scrolled in that direction.
-  bool can_propagate_vertically = true;
-  bool can_propagate_horizontally = true;
-
-  LayoutObject* layout_object = scrollable->GetNode()->GetLayoutObject();
-
-  while (layout_object && !(can_scroll_horizontally && can_scroll_vertically)) {
-    LayoutBox* layout_box;
-
-    if (layout_object->IsBox()) {
-      layout_box = To<LayoutBox>(layout_object);
-      // Check whether the layout box can be scrolled and has horizontal
-      // scrollable area.
-      if (can_propagate_vertically &&
-          CanScrollDirection(layout_box, frame->GetPage(),
-                             ScrollOrientation::kVerticalScroll) &&
-          !vertical_autoscroll_layout_box_) {
-        vertical_autoscroll_layout_box_ = layout_box;
-        can_scroll_vertically = true;
-      }
-      // Check whether the layout box can be scrolled and has vertical
-      // scrollable area.
-      if (can_propagate_horizontally &&
-          CanScrollDirection(layout_box, frame->GetPage(),
-                             ScrollOrientation::kHorizontalScroll) &&
-          !horizontal_autoscroll_layout_box_) {
-        horizontal_autoscroll_layout_box_ = layout_box;
-        can_scroll_horizontally = true;
-      }
-    }
-
-    can_propagate_vertically = ScrollManager::CanPropagate(
-        layout_box, ScrollPropagationDirection::kVertical);
-    can_propagate_horizontally = ScrollManager::CanPropagate(
-        layout_box, ScrollPropagationDirection::kHorizontal);
-
-    // Exit loop if we can't propagate to the parent in any direction or if
-    // layout boxes have been found for both directions.
-    if ((!can_propagate_vertically && !can_propagate_horizontally) ||
-        (can_scroll_horizontally && can_scroll_vertically))
-      break;
-
-    if (!layout_object->Parent() &&
-        layout_object->GetNode() == layout_object->GetDocument() &&
-        layout_object->GetDocument().LocalOwner()) {
-      layout_object =
-          layout_object->GetDocument().LocalOwner()->GetLayoutObject();
-    } else {
-      layout_object = layout_object->Parent();
-    }
-  }
+  bool can_scroll_vertically =
+      CanScrollDirection(autoscroll_layout_object_, frame->GetPage(),
+                         ScrollOrientation::kVerticalScroll);
+  bool can_scroll_horizontally =
+      CanScrollDirection(autoscroll_layout_object_, frame->GetPage(),
+                         ScrollOrientation::kHorizontalScroll);
 
   UseCounter::Count(frame->GetDocument(),
                     WebFeature::kMiddleClickAutoscrollStart);
diff --git a/third_party/blink/renderer/core/page/autoscroll_controller.h b/third_party/blink/renderer/core/page/autoscroll_controller.h
index 0b0a711..7e04c41 100644
--- a/third_party/blink/renderer/core/page/autoscroll_controller.h
+++ b/third_party/blink/renderer/core/page/autoscroll_controller.h
@@ -84,7 +84,7 @@
 
   // Middle-click autoscroll.
   void StartMiddleClickAutoscroll(LocalFrame*,
-                                  LayoutBox* scrollable,
+                                  LayoutBox*,
                                   const FloatPoint& position,
                                   const FloatPoint& position_global);
   void HandleMouseMoveForMiddleClickAutoscroll(
@@ -102,17 +102,15 @@
 
   Member<Page> page_;
   AutoscrollType autoscroll_type_ = kNoAutoscroll;
+  LayoutBox* autoscroll_layout_object_ = nullptr;
 
   // Selection and drag-and-drop autoscroll.
   void ScheduleMainThreadAnimation();
-  LayoutBox* autoscroll_layout_object_ = nullptr;
   LayoutBox* pressed_layout_object_ = nullptr;
   PhysicalOffset drag_and_drop_autoscroll_reference_position_;
   base::TimeTicks drag_and_drop_autoscroll_start_time_;
 
   // Middle-click autoscroll.
-  LayoutBox* horizontal_autoscroll_layout_box_ = nullptr;
-  LayoutBox* vertical_autoscroll_layout_box_ = nullptr;
   FloatPoint middle_click_autoscroll_start_pos_global_;
   gfx::Vector2dF last_velocity_;
   MiddleClickMode middle_click_mode_ = kMiddleClickInitial;
@@ -122,9 +120,6 @@
   FRIEND_TEST_ALL_PREFIXES(AutoscrollControllerTest,
                            ContinueAutoscrollAfterMouseLeaveEvent);
   FRIEND_TEST_ALL_PREFIXES(AutoscrollControllerTest, StopAutoscrollOnResize);
-  FRIEND_TEST_ALL_PREFIXES(AutoscrollControllerTest, AutoscrollIsNotPropagated);
-  FRIEND_TEST_ALL_PREFIXES(AutoscrollControllerTest,
-                           AutoscrollIsPropagatedInYDirection);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/page/autoscroll_controller_test.cc b/third_party/blink/renderer/core/page/autoscroll_controller_test.cc
index ddd6816..d24da0e 100644
--- a/third_party/blink/renderer/core/page/autoscroll_controller_test.cc
+++ b/third_party/blink/renderer/core/page/autoscroll_controller_test.cc
@@ -182,102 +182,4 @@
   EXPECT_TRUE(controller.IsAutoscrolling());
 }
 
-// Ensure that middle click autoscroll is not propagated in a direction when
-// propagation is not allowed.
-TEST_F(AutoscrollControllerTest, AutoscrollIsNotPropagated) {
-  SimRequest request("https://example.com/test.html", "text/html");
-  LoadURL("https://example.com/test.html");
-  request.Complete(R"HTML(
-    <!DOCTYPE html>
-    <html>
-      <head>
-        <style>
-          #scrollable {
-            width: 820px;
-            height: 620px;
-            overflow: auto;
-            overscroll-behavior: contain;
-          }
-          #inner {
-            width: 2500px;
-            background-color: aqua;
-            height: 100px;
-          }
-        </style>
-      </head>
-      <body style='width: 3000px; height: 3000px;'>
-        <div id="scrollable">
-          <div id="inner"></div>
-        </div>
-      </body>
-    </html>
-  )HTML");
-
-  Compositor().BeginFrame();
-
-  AutoscrollController& controller = GetAutoscrollController();
-
-  EXPECT_FALSE(controller.IsAutoscrolling());
-
-  LocalFrame* frame = GetDocument().GetFrame();
-  LayoutBox* scrollable =
-      GetDocument().getElementById("scrollable")->GetLayoutBox();
-
-  controller.StartMiddleClickAutoscroll(
-      frame, scrollable, FloatPoint(15.0, 15.0), FloatPoint(15.0, 15.0));
-
-  EXPECT_TRUE(controller.IsAutoscrolling());
-  EXPECT_TRUE(controller.horizontal_autoscroll_layout_box_);
-  EXPECT_FALSE(controller.vertical_autoscroll_layout_box_);
-}
-
-// Ensure that middle click autoscroll is propagated in a direction when
-// overscroll-behavior is set to auto for a that direction.
-TEST_F(AutoscrollControllerTest, AutoscrollIsPropagatedInYDirection) {
-  SimRequest request("https://example.com/test.html", "text/html");
-  LoadURL("https://example.com/test.html");
-  request.Complete(R"HTML(
-    <!DOCTYPE html>
-    <html>
-      <head>
-        <style>
-          #scrollable {
-            width: 820px;
-            height: 620px;
-            overflow: auto;
-            overscroll-behavior-x: contain;
-          }
-          #inner {
-            width: 1000px;
-            background-color: aqua;
-            height: 100px;
-          }
-        </style>
-      </head>
-      <body style='width: 3000px; height: 3000px;'>
-        <div id="scrollable">
-          <div id="inner"></div>
-        </div>
-      </body>
-    </html>
-  )HTML");
-
-  Compositor().BeginFrame();
-
-  AutoscrollController& controller = GetAutoscrollController();
-
-  EXPECT_FALSE(controller.IsAutoscrolling());
-
-  LocalFrame* frame = GetDocument().GetFrame();
-  LayoutBox* scrollable =
-      GetDocument().getElementById("scrollable")->GetLayoutBox();
-
-  controller.StartMiddleClickAutoscroll(
-      frame, scrollable, FloatPoint(15.0, 15.0), FloatPoint(15.0, 15.0));
-
-  EXPECT_TRUE(controller.IsAutoscrolling());
-  EXPECT_TRUE(controller.vertical_autoscroll_layout_box_);
-  EXPECT_TRUE(controller.horizontal_autoscroll_layout_box_);
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/svg/svg_length.cc b/third_party/blink/renderer/core/svg/svg_length.cc
index fc137aa..ff760af 100644
--- a/third_party/blink/renderer/core/svg/svg_length.cc
+++ b/third_party/blink/renderer/core/svg/svg_length.cc
@@ -179,15 +179,6 @@
   return value_->GetFloatValue();
 }
 
-float SVGLength::ValueAsPercentage100() const {
-  // LengthTypePercentage is represented with 100% = 100.0. Good for accuracy
-  // but could eventually be changed.
-  if (value_->IsPercentage())
-    return value_->GetFloatValue();
-
-  return value_->GetFloatValue() * 100;
-}
-
 float SVGLength::ScaleByPercentage(float input) const {
   float result = input * value_->GetFloatValue();
   if (value_->IsPercentage()) {
diff --git a/third_party/blink/renderer/core/svg/svg_length.h b/third_party/blink/renderer/core/svg/svg_length.h
index 8fbdf7e..d23594f3 100644
--- a/third_party/blink/renderer/core/svg/svg_length.h
+++ b/third_party/blink/renderer/core/svg/svg_length.h
@@ -92,9 +92,6 @@
   // value is 1.0).
   float ValueAsPercentage() const;
 
-  // Returns a number to be used as percentage (so full value is 100)
-  float ValueAsPercentage100() const;
-
   // Scale the input value by this SVGLength. Higher precision than input *
   // valueAsPercentage().
   float ScaleByPercentage(float) const;
diff --git a/third_party/blink/renderer/core/svg/svg_length_context.cc b/third_party/blink/renderer/core/svg/svg_length_context.cc
index bcff118..b4d12cd 100644
--- a/third_party/blink/renderer/core/svg/svg_length_context.cc
+++ b/third_party/blink/renderer/core/svg/svg_length_context.cc
@@ -50,11 +50,10 @@
   return 0;
 }
 
-static float ConvertValueFromPercentageToUserUnits(
-    const SVGLength& value,
-    const FloatSize& viewport_size) {
-  return CSSPrimitiveValue::ClampToCSSLengthRange(value.ScaleByPercentage(
-      DimensionForLengthMode(value.UnitMode(), viewport_size)));
+static float ConvertValueFromPercentageToUserUnits(const SVGLength& value,
+                                                   float viewport_dimension) {
+  return CSSPrimitiveValue::ClampToCSSLengthRange(
+      value.ScaleByPercentage(viewport_dimension));
 }
 
 static const ComputedStyle* ComputedStyleForLengthResolving(
@@ -168,12 +167,13 @@
                                              const SVGLength& height) {
   DCHECK_NE(SVGUnitTypes::kSvgUnitTypeUnknown, type);
   if (type != SVGUnitTypes::kSvgUnitTypeUserspaceonuse) {
-    const FloatSize& viewport_size = viewport.Size();
     return FloatRect(
-        ConvertValueFromPercentageToUserUnits(x, viewport_size) + viewport.X(),
-        ConvertValueFromPercentageToUserUnits(y, viewport_size) + viewport.Y(),
-        ConvertValueFromPercentageToUserUnits(width, viewport_size),
-        ConvertValueFromPercentageToUserUnits(height, viewport_size));
+        ConvertValueFromPercentageToUserUnits(x, viewport.Width()) +
+            viewport.X(),
+        ConvertValueFromPercentageToUserUnits(y, viewport.Height()) +
+            viewport.Y(),
+        ConvertValueFromPercentageToUserUnits(width, viewport.Width()),
+        ConvertValueFromPercentageToUserUnits(height, viewport.Height()));
   }
 
   SVGLengthContext length_context(context);
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
index a3c15ce..931603f 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -1349,8 +1349,11 @@
     NOTREACHED();
   }
 
-  if (IsTextControl())
+  if (IsTextControl()) {
+    // TODO(https://crbug.com/1165853) For contenteditable, compute on browser
+    // side instead.
     return GetText();
+  }
 
   if (layout_object_->IsFileUploadControl())
     return To<LayoutFileUploadControl>(layout_object_)->FileTextValue();
@@ -1379,11 +1382,6 @@
     return TextFromDescendants(visited, false);
   }
 
-  // FIXME: We might need to implement a value here for more types
-  // FIXME: It would be better not to advertise a value at all for the types for
-  // which we don't implement one; this would require subclassing or making
-  // accessibilityAttributeNames do something other than return a single static
-  // array.
   return String();
 }
 
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
index fe11414..4b8da9d 100644
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
@@ -1822,7 +1822,7 @@
   }
 
   auto* element = DynamicTo<Element>(node);
-  return element ? element->innerText() : String();
+  return element ? element->GetInnerTextWithoutUpdate() : String();
 }
 
 ax::mojom::blink::TextAlign AXNodeObject::GetTextAlign() const {
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_request.h b/third_party/blink/renderer/modules/indexeddb/idb_request.h
index b7df7ced..96f761b2 100644
--- a/third_party/blink/renderer/modules/indexeddb/idb_request.h
+++ b/third_party/blink/renderer/modules/indexeddb/idb_request.h
@@ -276,10 +276,6 @@
       mojo::PendingReceiver<mojom::blink::IDBDatabaseGetAllResultSink>
           receiver);
 
-  // Only used in webkitGetDatabaseNames(), which is deprecated and hopefully
-  // going away soon.
-  void EnqueueResponse(const Vector<String>&);
-
   // Only IDBOpenDBRequest instances should receive these:
   virtual void EnqueueBlocked(int64_t old_version) { NOTREACHED(); }
   virtual void EnqueueUpgradeNeeded(int64_t old_version,
diff --git a/third_party/blink/renderer/platform/heap/BUILD.gn b/third_party/blink/renderer/platform/heap/BUILD.gn
index e7419b5..19b912a 100644
--- a/third_party/blink/renderer/platform/heap/BUILD.gn
+++ b/third_party/blink/renderer/platform/heap/BUILD.gn
@@ -103,7 +103,7 @@
       "v8_wrapper/garbage_collected.h",
       "v8_wrapper/gc_task_runner.h",
       "v8_wrapper/heap.h",
-      "v8_wrapper/heap_allocator.h",
+      "v8_wrapper/heap_allocator_impl.h",
       "v8_wrapper/heap_stats_collector.h",
       "v8_wrapper/heap_traits.h",
       "v8_wrapper/member.h",
diff --git a/third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h b/third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h
index 0d37a73..740ea72 100644
--- a/third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h
+++ b/third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_HASH_MAP_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_HASH_MAP_H_
 
+#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
 #include "third_party/blink/renderer/platform/heap/heap.h"
 #include "third_party/blink/renderer/platform/heap/heap_allocator_impl.h"
 #include "third_party/blink/renderer/platform/heap/visitor.h"
diff --git a/third_party/blink/renderer/platform/heap/collection_support/heap_list_hash_set.h b/third_party/blink/renderer/platform/heap/collection_support/heap_list_hash_set.h
index 3b0764ca..ad79143 100644
--- a/third_party/blink/renderer/platform/heap/collection_support/heap_list_hash_set.h
+++ b/third_party/blink/renderer/platform/heap/collection_support/heap_list_hash_set.h
@@ -6,6 +6,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_COLLECTION_SUPPORT_HEAP_LIST_HASH_SET_H_
 
 #include "third_party/blink/renderer/platform/heap/heap.h"
+#include "third_party/blink/renderer/platform/heap/member.h"
 #include "third_party/blink/renderer/platform/wtf/list_hash_set.h"
 #include "third_party/blink/renderer/platform/wtf/type_traits.h"
 
diff --git a/third_party/blink/renderer/platform/heap/collection_support/heap_vector.h b/third_party/blink/renderer/platform/heap/collection_support/heap_vector.h
index 71ea2a6..cf341607 100644
--- a/third_party/blink/renderer/platform/heap/collection_support/heap_vector.h
+++ b/third_party/blink/renderer/platform/heap/collection_support/heap_vector.h
@@ -69,10 +69,6 @@
   }
 };
 
-template <typename T, wtf_size_t inlineCapacity>
-struct GCInfoTrait<HeapVector<T, inlineCapacity>>
-    : public GCInfoTrait<Vector<T, inlineCapacity, HeapAllocator>> {};
-
 }  // namespace blink
 
 namespace WTF {
diff --git a/third_party/blink/renderer/platform/heap/heap_allocator_impl.h b/third_party/blink/renderer/platform/heap/heap_allocator_impl.h
index 05a45a6..e05ca5d 100644
--- a/third_party/blink/renderer/platform/heap/heap_allocator_impl.h
+++ b/third_party/blink/renderer/platform/heap/heap_allocator_impl.h
@@ -8,7 +8,7 @@
 #include "third_party/blink/renderer/platform/wtf/buildflags.h"
 
 #if BUILDFLAG(USE_V8_OILPAN)
-// TODO(1056170): Add wrapper version.
+#include "third_party/blink/renderer/platform/heap/v8_wrapper/heap_allocator_impl.h"
 #else  // !USE_V8_OILPAN
 #include "third_party/blink/renderer/platform/heap/impl/heap_allocator_impl.h"
 #endif  // !USE_V8_OILPAN
diff --git a/third_party/blink/renderer/platform/heap/impl/member.h b/third_party/blink/renderer/platform/heap/impl/member.h
index f9c8fe7..0ffb6f7e 100644
--- a/third_party/blink/renderer/platform/heap/impl/member.h
+++ b/third_party/blink/renderer/platform/heap/impl/member.h
@@ -488,53 +488,6 @@
 
 namespace WTF {
 
-// PtrHash is the default hash for hash tables with Member<>-derived elements.
-template <typename T>
-struct MemberHash : PtrHash<T> {
-  STATIC_ONLY(MemberHash);
-  template <typename U>
-  static unsigned GetHash(const U& key) {
-    return PtrHash<T>::GetHash(key);
-  }
-  template <typename U, typename V>
-  static bool Equal(const U& a, const V& b) {
-    return a == b;
-  }
-};
-
-template <typename T>
-struct DefaultHash<blink::Member<T>> {
-  STATIC_ONLY(DefaultHash);
-  using Hash = MemberHash<T>;
-};
-
-template <typename T>
-struct DefaultHash<blink::WeakMember<T>> {
-  STATIC_ONLY(DefaultHash);
-  using Hash = MemberHash<T>;
-};
-
-template <typename T>
-struct DefaultHash<blink::UntracedMember<T>> {
-  STATIC_ONLY(DefaultHash);
-  using Hash = MemberHash<T>;
-};
-
-template <typename T>
-struct IsTraceable<blink::Member<T>> {
-  STATIC_ONLY(IsTraceable);
-  static const bool value = true;
-};
-
-template <typename T>
-struct IsWeak<blink::WeakMember<T>> : std::true_type {};
-
-template <typename T>
-struct IsTraceable<blink::WeakMember<T>> {
-  STATIC_ONLY(IsTraceable);
-  static const bool value = true;
-};
-
 template <typename T, typename Traits, typename Allocator>
 class MemberConstructTraits {
   STATIC_ONLY(MemberConstructTraits);
diff --git a/third_party/blink/renderer/platform/heap/impl/persistent.h b/third_party/blink/renderer/platform/heap/impl/persistent.h
index 09ef3bc1..0c12b71 100644
--- a/third_party/blink/renderer/platform/heap/impl/persistent.h
+++ b/third_party/blink/renderer/platform/heap/impl/persistent.h
@@ -808,17 +808,6 @@
 #define WrapPersistent(value) WrapPersistentInternal(value)
 #endif  // BUILDFLAG(RAW_HEAP_SNAPSHOTS)
 
-template <typename T,
-          typename = std::enable_if_t<WTF::IsGarbageCollectedType<T>::value>>
-Persistent<T> WrapPersistentIfNeeded(T* value) {
-  return Persistent<T>(value);
-}
-
-template <typename T>
-T& WrapPersistentIfNeeded(T& value) {
-  return value;
-}
-
 template <typename T>
 WeakPersistent<T> WrapWeakPersistent(T* value) {
   return WeakPersistent<T>(value);
diff --git a/third_party/blink/renderer/platform/heap/member.h b/third_party/blink/renderer/platform/heap/member.h
index 0bf9d7e..5337c74 100644
--- a/third_party/blink/renderer/platform/heap/member.h
+++ b/third_party/blink/renderer/platform/heap/member.h
@@ -6,7 +6,9 @@
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_MEMBER_H_
 
 #include "third_party/blink/renderer/platform/wtf/buildflags.h"
+#include "third_party/blink/renderer/platform/wtf/hash_functions.h"
 #include "third_party/blink/renderer/platform/wtf/hash_traits.h"
+#include "third_party/blink/renderer/platform/wtf/type_traits.h"
 
 #if BUILDFLAG(USE_V8_OILPAN)
 #include "third_party/blink/renderer/platform/heap/v8_wrapper/member.h"
@@ -25,6 +27,53 @@
 
 namespace WTF {
 
+// PtrHash is the default hash for hash tables with Member<>-derived elements.
+template <typename T>
+struct MemberHash : PtrHash<T> {
+  STATIC_ONLY(MemberHash);
+  template <typename U>
+  static unsigned GetHash(const U& key) {
+    return PtrHash<T>::GetHash(key);
+  }
+  template <typename U, typename V>
+  static bool Equal(const U& a, const V& b) {
+    return a == b;
+  }
+};
+
+template <typename T>
+struct DefaultHash<blink::Member<T>> {
+  STATIC_ONLY(DefaultHash);
+  using Hash = MemberHash<T>;
+};
+
+template <typename T>
+struct DefaultHash<blink::WeakMember<T>> {
+  STATIC_ONLY(DefaultHash);
+  using Hash = MemberHash<T>;
+};
+
+template <typename T>
+struct DefaultHash<blink::UntracedMember<T>> {
+  STATIC_ONLY(DefaultHash);
+  using Hash = MemberHash<T>;
+};
+
+template <typename T>
+struct IsTraceable<blink::Member<T>> {
+  STATIC_ONLY(IsTraceable);
+  static const bool value = true;
+};
+
+template <typename T>
+struct IsWeak<blink::WeakMember<T>> : std::true_type {};
+
+template <typename T>
+struct IsTraceable<blink::WeakMember<T>> {
+  STATIC_ONLY(IsTraceable);
+  static const bool value = true;
+};
+
 template <typename T>
 struct HashTraits<blink::Member<T>> : SimpleClassHashTraits<blink::Member<T>> {
   STATIC_ONLY(HashTraits);
diff --git a/third_party/blink/renderer/platform/heap/persistent.h b/third_party/blink/renderer/platform/heap/persistent.h
index ff2311d3..78b1fb7 100644
--- a/third_party/blink/renderer/platform/heap/persistent.h
+++ b/third_party/blink/renderer/platform/heap/persistent.h
@@ -5,7 +5,10 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_PERSISTENT_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_PERSISTENT_H_
 
+#include "third_party/blink/renderer/platform/heap/member.h"
 #include "third_party/blink/renderer/platform/wtf/buildflags.h"
+#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h"
+#include "third_party/blink/renderer/platform/wtf/type_traits.h"
 
 #if BUILDFLAG(USE_V8_OILPAN)
 #include "third_party/blink/renderer/platform/heap/v8_wrapper/persistent.h"
@@ -13,25 +16,45 @@
 #include "third_party/blink/renderer/platform/heap/impl/persistent.h"
 #endif  // !USE_V8_OILPAN
 
+namespace blink {
+
+template <typename T,
+          typename = std::enable_if_t<WTF::IsGarbageCollectedType<T>::value>>
+Persistent<T> WrapPersistentIfNeeded(T* value) {
+  return Persistent<T>(value);
+}
+
+template <typename T>
+T& WrapPersistentIfNeeded(T& value) {
+  return value;
+}
+
+}  // namespace blink
+
 namespace WTF {
 
-template <
-    typename T,
-    blink::WeaknessPersistentConfiguration weaknessConfiguration,
-    blink::CrossThreadnessPersistentConfiguration crossThreadnessConfiguration>
-struct VectorTraits<blink::PersistentBase<T,
-                                          weaknessConfiguration,
-                                          crossThreadnessConfiguration>>
-    : VectorTraitsBase<blink::PersistentBase<T,
-                                             weaknessConfiguration,
-                                             crossThreadnessConfiguration>> {
-  STATIC_ONLY(VectorTraits);
-  static const bool kNeedsDestruction = true;
+template <typename T>
+struct PersistentVectorTraitsBase : VectorTraitsBase<T> {
+  STATIC_ONLY(PersistentVectorTraitsBase);
   static const bool kCanInitializeWithMemset = true;
-  static const bool kCanClearUnusedSlotsWithMemset = false;
-  static const bool kCanMoveWithMemcpy = true;
 };
 
+template <typename T>
+struct VectorTraits<blink::Persistent<T>>
+    : PersistentVectorTraitsBase<blink::Persistent<T>> {};
+
+template <typename T>
+struct VectorTraits<blink::WeakPersistent<T>>
+    : PersistentVectorTraitsBase<blink::WeakPersistent<T>> {};
+
+template <typename T>
+struct VectorTraits<blink::CrossThreadPersistent<T>>
+    : PersistentVectorTraitsBase<blink::CrossThreadPersistent<T>> {};
+
+template <typename T>
+struct VectorTraits<blink::CrossThreadWeakPersistent<T>>
+    : PersistentVectorTraitsBase<blink::CrossThreadWeakPersistent<T>> {};
+
 template <typename T, typename H>
 struct HandleHashTraits : SimpleClassHashTraits<H> {
   STATIC_ONLY(HandleHashTraits);
diff --git a/third_party/blink/renderer/platform/heap/v8_wrapper/blink_gc.h b/third_party/blink/renderer/platform/heap/v8_wrapper/blink_gc.h
index bf86021..47d6f7b 100644
--- a/third_party/blink/renderer/platform/heap/v8_wrapper/blink_gc.h
+++ b/third_party/blink/renderer/platform/heap/v8_wrapper/blink_gc.h
@@ -5,6 +5,22 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_BLINK_GC_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_BLINK_GC_H_
 
-// TODO(chromium:1056170): Implement wrapper.
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+
+namespace blink {
+
+class PLATFORM_EXPORT BlinkGC final {
+  STATIC_ONLY(BlinkGC);
+
+ public:
+  // When garbage collecting we need to know whether or not there can be
+  // pointers to Oilpan-managed objects on the stack for each thread. When
+  // threads reach a safe point they record whether or not they have pointers on
+  // the stack.
+  enum StackState { kNoHeapPointersOnStack, kHeapPointersOnStack };
+};
+
+}  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_BLINK_GC_H_
diff --git a/third_party/blink/renderer/platform/heap/v8_wrapper/heap_allocator.h b/third_party/blink/renderer/platform/heap/v8_wrapper/heap_allocator.h
deleted file mode 100644
index 7c5cd8d..0000000
--- a/third_party/blink/renderer/platform/heap/v8_wrapper/heap_allocator.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2020 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_HEAP_ALLOCATOR_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_HEAP_ALLOCATOR_H_
-
-// TODO(chromium:1056170): Implement wrapper.
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_HEAP_ALLOCATOR_H_
diff --git a/third_party/blink/renderer/platform/heap/v8_wrapper/heap_allocator_impl.h b/third_party/blink/renderer/platform/heap/v8_wrapper/heap_allocator_impl.h
new file mode 100644
index 0000000..06bcc8a
--- /dev/null
+++ b/third_party/blink/renderer/platform/heap/v8_wrapper/heap_allocator_impl.h
@@ -0,0 +1,22 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_HEAP_ALLOCATOR_IMPL_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_HEAP_ALLOCATOR_IMPL_H_
+
+#include "third_party/blink/renderer/platform/platform_export.h"
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+
+namespace blink {
+
+class PLATFORM_EXPORT HeapAllocator {
+  STATIC_ONLY(HeapAllocator);
+
+ public:
+  static constexpr bool kIsGarbageCollected = true;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_HEAP_ALLOCATOR_IMPL_H_
diff --git a/third_party/blink/renderer/platform/heap/v8_wrapper/persistent.h b/third_party/blink/renderer/platform/heap/v8_wrapper/persistent.h
index 28398f5..e46f0f8d 100644
--- a/third_party/blink/renderer/platform/heap/v8_wrapper/persistent.h
+++ b/third_party/blink/renderer/platform/heap/v8_wrapper/persistent.h
@@ -56,17 +56,6 @@
   return CrossThreadWeakPersistent<T>(value, loc);
 }
 
-template <typename T,
-          typename = std::enable_if_t<WTF::IsGarbageCollectedType<T>::value>>
-Persistent<T> WrapPersistentIfNeeded(T* value) {
-  return Persistent<T>(value);
-}
-
-template <typename T>
-T& WrapPersistentIfNeeded(T& value) {
-  return value;
-}
-
 #if BUILDFLAG(RAW_HEAP_SNAPSHOTS)
 #define PERSISTENT_FROM_HERE PersistentLocation::Current()
 #else
@@ -75,21 +64,4 @@
 
 }  // namespace blink
 
-namespace base {
-
-template <typename T>
-struct IsWeakReceiver<blink::WeakPersistent<T>> : std::true_type {};
-
-template <typename T>
-struct IsWeakReceiver<blink::CrossThreadWeakPersistent<T>> : std::true_type {};
-
-template <typename T>
-struct BindUnwrapTraits<blink::CrossThreadWeakPersistent<T>> {
-  static blink::CrossThreadPersistent<T> Unwrap(
-      const blink::CrossThreadWeakPersistent<T>& wrapped) {
-    return blink::CrossThreadPersistent<T>(wrapped);
-  }
-};
-}  // namespace base
-
 #endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_HEAP_V8_WRAPPER_PERSISTENT_H_
diff --git a/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h b/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h
index fd5d6bba..35438e8 100644
--- a/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h
+++ b/third_party/blink/renderer/platform/heap/v8_wrapper/thread_state.h
@@ -7,6 +7,7 @@
 
 #include "base/compiler_specific.h"
 #include "base/lazy_instance.h"
+#include "third_party/blink/renderer/platform/heap/blink_gc.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 #include "third_party/blink/renderer/platform/wtf/thread_specific.h"
 #include "third_party/blink/renderer/platform/wtf/threading.h"
@@ -76,6 +77,15 @@
     return nullptr;
   }
 
+  // Forced garbage collection for testing:
+  //
+  // Collects garbage as long as live memory decreases (capped at 5).
+  void CollectAllGarbageForTesting(
+      BlinkGC::StackState stack_state =
+          BlinkGC::StackState::kNoHeapPointersOnStack) {
+    // TODO(1056170): Implement.
+  }
+
  private:
   // Main-thread ThreadState avoids TLS completely by using a regular global.
   // The object is manually managed and should not rely on global ctor/dtor.
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 37bbbeb9..e72f782 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1035,6 +1035,7 @@
     {
       name: "InterestCohortAPI",
       origin_trial_feature_name: "InterestCohortAPI",
+      origin_trial_allows_third_party: true,
     },
     {
       name: "IntersectionObserverDocumentScrollingElementRoot",
@@ -2117,7 +2118,7 @@
     },
     {
       name: "WebAuthenticationResidentKeyRequirement",
-      status: "experimental",
+      status: "stable",
     },
     // WebBluetooth is enabled by default on Android, ChromeOS and Mac.
     // It is also supported in Windows 10 which is handled in runtime_features.cc
diff --git a/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc b/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
index 85f6220..2c8e7445 100644
--- a/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
+++ b/third_party/blink/renderer/platform/widget/compositing/layer_tree_settings.cc
@@ -158,8 +158,6 @@
   const base::CommandLine& cmd = *base::CommandLine::ForCurrentProcess();
   cc::LayerTreeSettings settings;
 
-  settings.force_preferred_interval_for_video =
-      ::features::IsForcePreferredIntervalForVideoEnabled();
   settings.enable_synchronized_scrolling =
       base::FeatureList::IsEnabled(::features::kSynchronizedScrolling);
   Platform* platform = Platform::Current();
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests
index fb46f17e..2483984 100644
--- a/third_party/blink/web_tests/SlowTests
+++ b/third_party/blink/web_tests/SlowTests
@@ -271,11 +271,6 @@
 # Tests where |3s <= slowest_run < 10s| on flakiness dashboard for site_per_process_blink_web_tests
 crbug.com/874695 accessibility/is-ignored-change-sends-notification.html [ Slow ]
 crbug.com/874695 animations/svg/animated-filter-svg-element.html [ Slow ]
-crbug.com/874695 bluetooth/server/connect/garbage-collection-ran-during-error.html [ Slow ]
-crbug.com/874695 bluetooth/server/disconnect/disconnect-fires-event.html [ Slow ]
-crbug.com/874695 bluetooth/server/getPrimaryService/gen-device-goes-out-of-range.html [ Slow ]
-crbug.com/874695 bluetooth/server/getPrimaryService/gen-reconnect-during-error.html [ Slow ]
-crbug.com/874695 bluetooth/server/getPrimaryServices/gen-delayed-discovery-service-found-with-uuid.html [ Slow ]
 crbug.com/874695 compositing/animation/busy-indicator.html [ Slow ]
 crbug.com/874695 compositing/culling/filter-occlusion-blur.html [ Slow ]
 crbug.com/874695 compositing/lots-of-img-layers-with-opacity.html [ Slow ]
@@ -463,6 +458,11 @@
 crbug.com/874695 virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchpad-zoom-in-slow.html [ Slow ]
 crbug.com/874695 virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen-zoom-in-slow-desktop.html [ Slow ]
 crbug.com/874695 virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchscreen-zoom-in-slow.html [ Slow ]
+crbug.com/874695 wpt_internal/bluetooth/server/connect/garbage-collection-ran-during-error.html [ Slow ]
+crbug.com/874695 wpt_internal/bluetooth/server/disconnect/disconnect-fires-event.html [ Slow ]
+crbug.com/874695 wpt_internal/bluetooth/server/getPrimaryService/gen-device-goes-out-of-range.html [ Slow ]
+crbug.com/874695 wpt_internal/bluetooth/server/getPrimaryService/gen-reconnect-during-error.html [ Slow ]
+crbug.com/874695 wpt_internal/bluetooth/server/getPrimaryServices/gen-delayed-discovery-service-found-with-uuid.html [ Slow ]
 
 crbug.com/868956 virtual/gpu/fast/canvas/canvas-composite-video-shadow.html [ Slow ]
 
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index a318fd5..c1704ae9 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -3471,8 +3471,6 @@
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-content-distribution-with-collapsed-tracks-023.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-content-distribution-with-collapsed-tracks-024.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-fit-content-tracks-dont-stretch-001.html [ Failure ]
-crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-gutters-009.html [ Failure ]
-crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-gutters-010.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-gutters-013.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-gutters-014.html [ Failure ]
 crbug.com/1045599 virtual/layout-ng-grid/external/wpt/css/css-grid/alignment/grid-gutters-and-alignment.html [ Failure ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 733d9af..1664bfa 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -714,7 +714,7 @@
   },
   {
     "prefix": "web-bluetooth-new-permissions-backend",
-    "bases": ["bluetooth", "external/wpt/bluetooth"],
+    "bases": ["wpt_internal/bluetooth", "external/wpt/bluetooth"],
     "args": ["--enable-features=WebBluetoothNewPermissionsBackend"]
   },
   {
@@ -769,6 +769,11 @@
     "args": [ "--enable-features=BackForwardCacheABExperimentControl" ]
   },
   {
+    "prefix": "interest-cohort-api-origin-trial",
+    "bases": [ "http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces.html" ],
+    "args": [ "--enable-features=InterestCohortAPIOriginTrial" ]
+  },
+  {
     "prefix": "threaded-composited-iframes",
     "bases": ["external/wpt/is-input-pending"],
     "args": ["--enable-threaded-compositing",
diff --git a/third_party/blink/web_tests/bluetooth/PRESUBMIT.py b/third_party/blink/web_tests/bluetooth/PRESUBMIT.py
deleted file mode 100644
index d0abf4a..0000000
--- a/third_party/blink/web_tests/bluetooth/PRESUBMIT.py
+++ /dev/null
@@ -1,25 +0,0 @@
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-"""Chromium presubmit script for Web Bluetooth layout tests.
-
-See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts.
-"""
-
-
-def CheckGeneratedFiles(input_api, output_api):
-  test_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
-                                     'generate_test.py')
-  cmd_name = 'generate_test'
-  cmd = [input_api.python_executable, test_path]
-
-  test_cmd = input_api.Command(
-      name=cmd_name, cmd=cmd, kwargs={}, message=output_api.PresubmitError)
-  if input_api.verbose:
-    print('Running ' + cmd_name)
-
-  return input_api.RunTests([test_cmd])
-
-
-def CheckChangeOnUpload(input_api, output_api):
-  return CheckGeneratedFiles(input_api, output_api)
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/blocklisted-descriptors-not-present.html b/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/blocklisted-descriptors-not-present.html
deleted file mode 100644
index d101c22..0000000
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/blocklisted-descriptors-not-present.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-const test_desc = 'Make sure blocklisted descriptors are not reported.';
-
-bluetooth_test(() => getBlocklistExcludeWritesCharacteristic()
-    .then(({characteristic}) => characteristic.getDescriptors())
-    .then(descriptors => descriptors.forEach(descriptor =>
-        // |blocklist_test_descriptor_uuid| is a blocklisted UUID. It should
-        // never be present in a getDescriptors() result.
-        assert_true(descriptor.uuid !== blocklist_test_descriptor_uuid))),
-    test_desc);
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/stop-twice.html b/third_party/blink/web_tests/bluetooth/characteristic/notifications/stop-twice.html
deleted file mode 100644
index 2c349b9..0000000
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/stop-twice.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(() => {
-  return setBluetoothFakeAdapter('HeartRateAdapter')
-    .then(() => requestDeviceWithTrustedClick({
-      filters: [{services: ['heart_rate']}]}))
-    .then(device => device.gatt.connect())
-    .then(gattServer => gattServer.getPrimaryService('heart_rate'))
-    .then(service => service.getCharacteristic('heart_rate_measurement'))
-    .then(characteristic => {
-      return characteristic.startNotifications()
-        .then(() => characteristic.stopNotifications())
-        .then(() => characteristic.stopNotifications());
-    });
-}, "Stopping twice.");
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/stop-without-starting.html b/third_party/blink/web_tests/bluetooth/characteristic/notifications/stop-without-starting.html
deleted file mode 100644
index c3720267..0000000
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/stop-without-starting.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(() => {
-  return setBluetoothFakeAdapter('HeartRateAdapter')
-    .then(() => requestDeviceWithTrustedClick({
-      filters: [{services: ['heart_rate']}]}))
-    .then(device => device.gatt.connect())
-    .then(gattServer => gattServer.getPrimaryService('heart_rate'))
-    .then(service => service.getCharacteristic('heart_rate_measurement'))
-    .then(characteristic => characteristic.stopNotifications());
-}, "Stop without starting.");
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/value-too-long.html b/third_party/blink/web_tests/bluetooth/characteristic/writeValue/value-too-long.html
deleted file mode 100644
index b43d1292..0000000
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/value-too-long.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-const test_desc = 'Trying to write more than 512 bytes should return an error.'
-let characteristic;
-
-bluetooth_test(() => getMeasurementIntervalCharacteristic()
-    .then(({characteristic}) => assert_promise_rejects_with_message(
-        characteristic.writeValue(new Uint8Array(513 /* length */)),
-        new DOMException(
-            'Failed to execute \'writeValue\' on ' +
-            '\'BluetoothRemoteGATTCharacteristic\': ' +
-            'Value can\'t exceed 512 bytes.',
-            'InvalidModificationError'
-        ), 'Value passed was too long.')),
-    test_desc);
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/value-too-long.html b/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/value-too-long.html
deleted file mode 100644
index cbcba77..0000000
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/value-too-long.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-const test_desc = 'Trying to write more than 512 bytes should return an error.'
-
-bluetooth_test(async () => {
-  const {characteristic} = await getMeasurementIntervalCharacteristic();
-  await assert_promise_rejects_with_message(
-      characteristic.writeValueWithResponse(new Uint8Array(513 /* length */)),
-      new DOMException(
-          'Failed to execute \'writeValueWithResponse\' on ' +
-          '\'BluetoothRemoteGATTCharacteristic\': ' +
-          'Value can\'t exceed 512 bytes.',
-          'InvalidModificationError'
-      ), 'Value passed was too long.');
-}, test_desc);
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/readValue/read-updates-value.html b/third_party/blink/web_tests/bluetooth/descriptor/readValue/read-updates-value.html
deleted file mode 100644
index 18ef61c..0000000
--- a/third_party/blink/web_tests/bluetooth/descriptor/readValue/read-updates-value.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-const test_desc = 'Successful read should update descriptor\'s value.';
-const value = new TextEncoder('utf-8').encode(user_description.name);
-let descriptor, fake_descriptor;
-
-bluetooth_test(() => getUserDescriptionDescriptor()
-    .then(_ => ({descriptor, fake_descriptor} = _))
-    .then(() => fake_descriptor.setNextReadResponse(GATT_SUCCESS, value))
-    .then(() => descriptor.readValue())
-    .then(() => assert_array_equals(new Uint8Array(descriptor.value.buffer),
-                                    value)),
-    test_desc);
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/value-too-long.html b/third_party/blink/web_tests/bluetooth/descriptor/writeValue/value-too-long.html
deleted file mode 100644
index 6334e64..0000000
--- a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/value-too-long.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-const test_desc = 'Trying to write more than 512 bytes should return an error.';
-const expected = new DOMException(
-    'Failed to execute \'writeValue\' on \'BluetoothRemoteGATTDescriptor\': ' +
-    'Value can\'t exceed 512 bytes.', 'InvalidModificationError');
-
-bluetooth_test(() => getUserDescriptionDescriptor()
-    .then(({descriptor}) => assert_promise_rejects_with_message(
-        descriptor.writeValue(new Uint8Array(513 /* length */)),
-        expected,
-        'Value passed was too long.')),
-    test_desc);
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/generate_test.py b/third_party/blink/web_tests/bluetooth/generate_test.py
deleted file mode 100755
index c4e24a5..0000000
--- a/third_party/blink/web_tests/bluetooth/generate_test.py
+++ /dev/null
@@ -1,55 +0,0 @@
-#!/usr/bin/python
-
-# Copyright 2016 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-#
-# TODO(509038): Delete this file after generate.py has been deleted, as it will
-# no longer be needed. There is a copy of this file in wpt/ that tests the
-# generate.py file in that directory.
-"""Test that the set of gen-* files is the same as the generated files."""
-
-import fnmatch
-import os
-import sys
-import generate
-
-UPDATE_TIP = ('To update the generated tests, run:\n'
-              '$ python third_party/blink/web_tests/bluetooth/generate.py')
-
-
-def main():
-  generated_files = set()
-  # Tests data in gen-* files is the same as the data generated.
-  for generated_test in generate.GetGeneratedTests():
-    generated_files.add(generated_test.path)
-    try:
-      with open(generated_test.path) as f:
-        data = f.read().decode('utf-8')
-        if data != generated_test.data:
-          print generated_test.path + ' does not match template.'
-          print UPDATE_TIP
-          return -1
-    except IOError, e:
-      if e.errno == 2:
-        print 'Missing generated test:\n{}\nFor template:\n{}'.format(
-            generated_test.path, generated_test.template)
-        print UPDATE_TIP
-        return -1
-
-  # Tests that there are no obsolete generated files.
-  previous_generated_files = set()
-  current_path = os.path.dirname(os.path.realpath(__file__))
-  for root, _, filenames in os.walk(current_path):
-    for filename in fnmatch.filter(filenames, 'gen-*.html'):
-      previous_generated_files.add(os.path.join(root, filename))
-
-  if previous_generated_files != generated_files:
-    print 'There are extra generated tests. Please remove them.'
-    for test_path in previous_generated_files - generated_files:
-      print test_path
-    return -1
-
-
-if __name__ == '__main__':
-  sys.exit(main())
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/acceptAllDevices/device-with-no-name.html b/third_party/blink/web_tests/bluetooth/requestDevice/acceptAllDevices/device-with-no-name.html
deleted file mode 100644
index a5a2ae1..0000000
--- a/third_party/blink/web_tests/bluetooth/requestDevice/acceptAllDevices/device-with-no-name.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(() => {
-  return setBluetoothFakeAdapter('NoNameDeviceAdapter')
-    .then(() => requestDeviceWithTrustedClick({acceptAllDevices: true}))
-    .then(device => {
-      assert_true(device.name === null);
-    });
-}, 'Device with no name or UUIDs nearby. Should be found if ' +
-   'acceptAllDevices is true.');
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/acceptAllDevices/device-with-uuids.html b/third_party/blink/web_tests/bluetooth/requestDevice/acceptAllDevices/device-with-uuids.html
deleted file mode 100644
index 28cf8d8..0000000
--- a/third_party/blink/web_tests/bluetooth/requestDevice/acceptAllDevices/device-with-uuids.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(() => {
-  return setBluetoothFakeAdapter('NoNameHeartRateAdapter')
-    .then(() => requestDeviceWithTrustedClick({acceptAllDevices: true}))
-    .then(device => {
-      assert_true(device.name === null);
-    });
-}, 'Device with only UUIDs nearby. Should be found if ' +
-   'acceptAllDevices is true.');
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/name-empty-device-from-name-prefix-filter.html b/third_party/blink/web_tests/bluetooth/requestDevice/name-empty-device-from-name-prefix-filter.html
deleted file mode 100644
index 4e33e37..0000000
--- a/third_party/blink/web_tests/bluetooth/requestDevice/name-empty-device-from-name-prefix-filter.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(t => {
-  return setBluetoothFakeAdapter('EmptyNameHeartRateAdapter')
-      .then(
-          () => promise_rejects_dom(
-              t, 'NotFoundError',
-              requestDeviceWithTrustedClick(
-                  {filters: [{namePrefix: 'a', services: ['heart_rate']}]})));
-}, 'An empty name device is not matched by a filter with a namePrefix.');
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/name-empty-device-from-name-wrong-filter.html b/third_party/blink/web_tests/bluetooth/requestDevice/name-empty-device-from-name-wrong-filter.html
deleted file mode 100644
index 27e0660..0000000
--- a/third_party/blink/web_tests/bluetooth/requestDevice/name-empty-device-from-name-wrong-filter.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(t => {
-  return setBluetoothFakeAdapter('EmptyNameHeartRateAdapter')
-      .then(
-          () => promise_rejects_dom(
-              t, 'NotFoundError',
-              requestDeviceWithTrustedClick(
-                  {filters: [{name: 'a', services: ['heart_rate']}]})));
-}, 'An empty name device is not matched by a filter with a name.');
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/name-empty-device-from-service-filter.html b/third_party/blink/web_tests/bluetooth/requestDevice/name-empty-device-from-service-filter.html
deleted file mode 100644
index 6729119..0000000
--- a/third_party/blink/web_tests/bluetooth/requestDevice/name-empty-device-from-service-filter.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(
-    () => {return setBluetoothFakeAdapter('EmptyNameHeartRateAdapter')
-               .then(
-                   () => requestDeviceWithTrustedClick(
-                       {filters: [{services: ['heart_rate']}]}))
-               .then(device => {
-                 assert_equals(device.name, '');
-               })},
-    'An empty name device can be obtained by advertised service UUID.');
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/name-empty-filter.html b/third_party/blink/web_tests/bluetooth/requestDevice/name-empty-filter.html
deleted file mode 100644
index 1f92911..0000000
--- a/third_party/blink/web_tests/bluetooth/requestDevice/name-empty-filter.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(t => {
-  return setBluetoothFakeAdapter('HeartRateAdapter')
-      .then(
-          () => promise_rejects_dom(
-              t, 'NotFoundError',
-              requestDeviceWithTrustedClick(
-                  {filters: [{name: '', services: ['heart_rate']}]})));
-}, 'A named device is not matched by a filter with an empty name.');
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/name-missing-device-from-name-empty-filter.html b/third_party/blink/web_tests/bluetooth/requestDevice/name-missing-device-from-name-empty-filter.html
deleted file mode 100644
index 524a39c..0000000
--- a/third_party/blink/web_tests/bluetooth/requestDevice/name-missing-device-from-name-empty-filter.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(t => {
-  return setBluetoothFakeAdapter('NoNameHeartRateAdapter')
-      .then(
-          () => promise_rejects_dom(
-              t, 'NotFoundError',
-              requestDeviceWithTrustedClick(
-                  {filters: [{name: '', services: ['heart_rate']}]})));
-}, 'An unnamed device can not be obtained by empty name filter.');
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/name-missing-device-from-name-prefix-filter.html b/third_party/blink/web_tests/bluetooth/requestDevice/name-missing-device-from-name-prefix-filter.html
deleted file mode 100644
index c00f1844..0000000
--- a/third_party/blink/web_tests/bluetooth/requestDevice/name-missing-device-from-name-prefix-filter.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(t => {
-  return setBluetoothFakeAdapter('NoNameHeartRateAdapter')
-      .then(
-          () => promise_rejects_dom(
-              t, 'NotFoundError',
-              requestDeviceWithTrustedClick(
-                  {filters: [{namePrefix: 'a', services: ['heart_rate']}]})));
-}, 'An unnamed device can not be obtained by namePrefix filter.');
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/name-missing-device-from-name-wrong-filter.html b/third_party/blink/web_tests/bluetooth/requestDevice/name-missing-device-from-name-wrong-filter.html
deleted file mode 100644
index 42f89991..0000000
--- a/third_party/blink/web_tests/bluetooth/requestDevice/name-missing-device-from-name-wrong-filter.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(t => {
-  return setBluetoothFakeAdapter('NoNameHeartRateAdapter')
-      .then(
-          () => promise_rejects_dom(
-              t, 'NotFoundError',
-              requestDeviceWithTrustedClick(
-                  {filters: [{name: 'a', services: ['heart_rate']}]})));
-}, 'An unnamed device can not be obtained by name filter.');
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/name-missing-device-from-service-filter.html b/third_party/blink/web_tests/bluetooth/requestDevice/name-missing-device-from-service-filter.html
deleted file mode 100644
index c8cc17a..0000000
--- a/third_party/blink/web_tests/bluetooth/requestDevice/name-missing-device-from-service-filter.html
+++ /dev/null
@@ -1,19 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(
-    () => {return setBluetoothFakeAdapter('NoNameHeartRateAdapter')
-               .then(
-                   () => requestDeviceWithTrustedClick(
-                       {filters: [{services: ['heart_rate']}]}))
-               .then(device => {
-                 assert_equals(device.name, null);
-               })},
-    'An unnamed device can be obtained by advertised service UUID.');
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/no-devices.html b/third_party/blink/web_tests/bluetooth/requestDevice/no-devices.html
deleted file mode 100644
index 342da1e..0000000
--- a/third_party/blink/web_tests/bluetooth/requestDevice/no-devices.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(() => {
-  return setBluetoothFakeAdapter('EmptyAdapter')
-      .then(
-          () => assert_promise_rejects_with_message(
-              requestDeviceWithTrustedClick(
-                  {filters: [{services: ['generic_access']}]}),
-              new DOMException(
-                  'User cancelled the requestDevice() chooser.',
-                  'NotFoundError'),
-              'No Bluetooth devices in range.'));
-}, 'Reject with NotFoundError if there are no devices around.');
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/single-filter-two-services-fails.html b/third_party/blink/web_tests/bluetooth/requestDevice/single-filter-two-services-fails.html
deleted file mode 100644
index 59f3bed..0000000
--- a/third_party/blink/web_tests/bluetooth/requestDevice/single-filter-two-services-fails.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(t => {
-  // Both devices support the Heart Rate service, but things need to
-  // support both services to pass the filter, and neither has a Battery
-  // service.
-  return setBluetoothFakeAdapter('GlucoseHeartRateAdapter')
-      .then(
-          () => promise_rejects_dom(
-              t, 'NotFoundError',
-              requestDeviceWithTrustedClick(
-                  {filters: [{services: ['heart_rate', 'battery_service']}]})));
-}, 'Too-strict filters do prevent matching.');
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/single-filter-two-services-succeeds.html b/third_party/blink/web_tests/bluetooth/requestDevice/single-filter-two-services-succeeds.html
deleted file mode 100644
index eb5f347..0000000
--- a/third_party/blink/web_tests/bluetooth/requestDevice/single-filter-two-services-succeeds.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(() => {
-  return setBluetoothFakeAdapter('GlucoseHeartRateAdapter')
-      .then(
-          () => requestDeviceWithTrustedClick(
-              {filters: [{services: ['glucose', 'tx_power']}]}))
-      .then(device => assert_equals(device.name, 'Glucose Device'));
-}, 'Filter with 2 services returns a matching device.');
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/two-filters.html b/third_party/blink/web_tests/bluetooth/requestDevice/two-filters.html
deleted file mode 100644
index c5f3293..0000000
--- a/third_party/blink/web_tests/bluetooth/requestDevice/two-filters.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(() => {
-  return setBluetoothFakeAdapter('GlucoseHeartRateAdapter')
-      .then(() => requestDeviceWithTrustedClick({
-              filters:
-                  [{services: ['battery_service']}, {services: ['heart_rate']}]
-            }))
-      .then(device => assert_equals(device.name, 'Heart Rate Device'));
-}, 'An extra filter doesn\'t prevent matching.');
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/requestLEScan/accept-all-with-filter-throws.https.html b/third_party/blink/web_tests/bluetooth/requestLEScan/accept-all-with-filter-throws.https.html
deleted file mode 100644
index 9831c1a..0000000
--- a/third_party/blink/web_tests/bluetooth/requestLEScan/accept-all-with-filter-throws.https.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
-<script>
-'use strict';
-const test_desc = 'requestLEScan scan options should have exactly one of ' +
-    '\'filters\' or \'acceptAllAdvertisements:true\'. Reject with TypeError if not.';
-const expected = new DOMException(
-    'Failed to execute \'requestLEScan\' on \'Bluetooth\': ' +
-        'Either \'filters\' should be present or ' +
-        '\'acceptAllAdvertisements\' should be true, but not both.',
-    new TypeError());
-
-bluetooth_test(() => {
-  return assert_promise_rejects_with_message(
-      requestLEScanWithTrustedClick(
-          {filters: [], acceptAllAdvertisements: true}),
-      expected);
-}, test_desc);
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/requestLEScan/le-not-supported.https.html b/third_party/blink/web_tests/bluetooth/requestLEScan/le-not-supported.https.html
deleted file mode 100644
index 56b2e65..0000000
--- a/third_party/blink/web_tests/bluetooth/requestLEScan/le-not-supported.https.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-const test_desc =
-    'requestLEScan reject with NotFoundError if Bluetooth is not supported.';
-const expected =
-    new DOMException('Bluetooth Low Energy not available.', 'NotFoundError');
-
-bluetooth_test(
-    () => navigator.bluetooth.test.setLESupported(false).then(
-        () => assert_promise_rejects_with_message(
-            requestLEScanWithTrustedClick({acceptAllAdvertisements: true}),
-            expected, 'Bluetooth Low Energy is not supported.')),
-    test_desc);
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/base_test_template.html b/third_party/blink/web_tests/bluetooth/script-tests/base_test_template.html
deleted file mode 100644
index 5959599..0000000
--- a/third_party/blink/web_tests/bluetooth/script-tests/base_test_template.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
-<!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-TEST
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/server/connect/device-goes-out-of-range.html b/third_party/blink/web_tests/bluetooth/server/connect/device-goes-out-of-range.html
deleted file mode 100644
index d69d1c3..0000000
--- a/third_party/blink/web_tests/bluetooth/server/connect/device-goes-out-of-range.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(() => {
-  return setBluetoothFakeAdapter('HeartRateAdapter')
-    .then(() => requestDeviceWithTrustedClick({
-      filters: [{services: ['heart_rate']}]}))
-    .then(device => {
-      return setBluetoothFakeAdapter('EmptyAdapter')
-        .then(() => assert_promise_rejects_with_message(
-          device.gatt.connect(),
-          new DOMException('Bluetooth Device is no longer in range.',
-                           'NetworkError'),
-          'Device went out of range.'));
-    });
-}, 'Device goes out of range. Reject with NetworkError.');
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/server/connect/garbage-collection-ran-during-error.html b/third_party/blink/web_tests/bluetooth/server/connect/garbage-collection-ran-during-error.html
deleted file mode 100644
index f740671..0000000
--- a/third_party/blink/web_tests/bluetooth/server/connect/garbage-collection-ran-during-error.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(t => {
-  return setBluetoothFakeAdapter('FailingConnectionsAdapter')
-    .then(() => requestDeviceWithTrustedClick({
-      filters: [{services: [errorUUID(0x1) /* in progress error */]}]}))
-    .then(device => {
-      promise_rejects_dom(t, 'NetworkError', device.gatt.connect());
-    })
-    .then(runGarbageCollection);
-}, 'Garbage collection ran during a connect call that fails. ' +
-   'Should not crash.');
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/server/disconnect/disconnect-once.html b/third_party/blink/web_tests/bluetooth/server/disconnect/disconnect-once.html
deleted file mode 100644
index 0ef216b4..0000000
--- a/third_party/blink/web_tests/bluetooth/server/disconnect/disconnect-once.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-// TODO(ortuno): Write tests to check that "Disconnect" was actually
-// called on the device.
-// http://crbug.com/569716
-bluetooth_test(() => {
-  return setBluetoothFakeAdapter('HeartRateAdapter')
-    .then(() => requestDeviceWithTrustedClick({
-      filters: [{services: ['heart_rate']}]}))
-    .then(device => device.gatt.connect())
-    .then(gattServer => {
-      gattServer.disconnect();
-      assert_false(gattServer.connected);
-    });
-}, '\'connected\' is set to false after disconnect is called.');
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/delayed-discovery-no-permission-present-service.html b/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/delayed-discovery-no-permission-present-service.html
deleted file mode 100644
index 2280a25b..0000000
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/delayed-discovery-no-permission-present-service.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(() => {
-  return setBluetoothFakeAdapter('DelayedServicesDiscoveryAdapter')
-    .then(() => requestDeviceWithTrustedClick({
-      filters: [{name: 'Heart Rate Device'}],
-      optionalServices: ['battery_service']}))
-    .then(device => device.gatt.connect())
-    .then(gattServer => assert_promise_rejects_with_message(
-      gattServer.getPrimaryServices(),
-      new DOMException('No Services found in device.', 'NotFoundError')));
-}, 'Delayed service discovery, request for present service without permission for that service. Reject with NotFoundError.');
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/delayed-discovery-service-not-found.html b/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/delayed-discovery-service-not-found.html
deleted file mode 100644
index 473fd07..0000000
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/delayed-discovery-service-not-found.html
+++ /dev/null
@@ -1,21 +0,0 @@
-<!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(() => {
-  return setBluetoothFakeAdapter('DelayedServicesDiscoveryAdapter')
-    .then(() => requestDeviceWithTrustedClick({
-      filters: [{name: 'Heart Rate Device'}],
-      optionalServices: ['battery_service']}))
-    .then(device => device.gatt.connect())
-    .then(gattServer => assert_promise_rejects_with_message(
-      gattServer.getPrimaryServices(),
-      new DOMException('No Services found in device.', 'NotFoundError')));
-}, 'Request for absent service. Must reject with NotFoundError even when the ' +
-   'services are not immediately discovered');
-</script>
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/no-permission-present-service.html b/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/no-permission-present-service.html
deleted file mode 100644
index 1b982d81..0000000
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/no-permission-present-service.html
+++ /dev/null
@@ -1,20 +0,0 @@
-<!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script>
-'use strict';
-bluetooth_test(() => {
-  return setBluetoothFakeAdapter('HeartRateAdapter')
-    .then(() => requestDeviceWithTrustedClick({
-      filters: [{name: 'Heart Rate Device'}],
-      optionalServices: ['battery_service']}))
-    .then(device => device.gatt.connect())
-    .then(gattServer => assert_promise_rejects_with_message(
-        gattServer.getPrimaryServices(),
-      new DOMException('No Services found in device.', 'NotFoundError')));
-}, 'Request for present service without permission for that service. Reject with NotFoundError.');
-</script>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index e55bbfe..4353c29 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -102312,6 +102312,19 @@
         {}
        ]
       ],
+      "intrinsic-size-009.html": [
+       "139c4de6447a7e59145a969f0c0e2b21e383b3f2",
+       [
+        null,
+        [
+         [
+          "/css/reference/ref-filled-green-100px-square.xht",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "percentage-resolution-001.html": [
        "d606bfc65e340f95fbbc355b764a7de5e7aeb6a1",
        [
@@ -173853,7 +173866,7 @@
      []
     ],
     "beacon-common.sub.js": [
-     "3635da73b75400ed3699576e2eac6329c39bba1b",
+     "279ad2229ba3e9f4c343733809c60e31fcd492e9",
      []
     ],
     "headers": {
@@ -201411,6 +201424,10 @@
        ]
       },
       "support": {
+       "100x100-green.png": [
+        "25b76c3c6f216793a36b1f29287dafd993898c67",
+        []
+       ],
        "1x1-green.png": [
         "b98ca0ba0a03c580ac339e4a3653539cfa8edc71",
         []
@@ -238349,7 +238366,7 @@
      []
     ],
     "README.md": [
-     "953611f93037cfebe0459d5f67599b727539ae40",
+     "d80c0e067f965e241f9ee652cb0eb6563c7939b8",
      []
     ],
     "detached.https.window.js.headers": [
diff --git a/third_party/blink/web_tests/external/wpt/beacon/beacon-common.sub.js b/third_party/blink/web_tests/external/wpt/beacon/beacon-common.sub.js
index 3635da7..279ad22 100644
--- a/third_party/blink/web_tests/external/wpt/beacon/beacon-common.sub.js
+++ b/third_party/blink/web_tests/external/wpt/beacon/beacon-common.sub.js
@@ -98,8 +98,7 @@
     return formData;
 }
 
-// Schedules async_test's for each of the test cases, treating them as a single session,
-// and wires up the continueAfterSendingBeacon() and waitForResults() calls.
+// Schedules promise_test's for each of the test cases.
 // Parameters:
 //     testCases: An array of test cases.
 //     suffix [optional]: A string used for the suffix for each test case name.
@@ -108,10 +107,10 @@
 function runTests(testCases, suffix = '', buildUrl = self.buildUrl, sendData = self.sendData) {
     for (const testCase of testCases) {
         const id = token();
-        async_test((test) => {
+        promise_test((test) => {
             const url = buildUrl(id);
             assert_true(sendData(url, testCase.data), 'sendBeacon should succeed');
-            waitForResult(id).then(() => test.done(), test.step_func((e) => {throw e;}));
+            return waitForResult(id);
         }, `Verify 'navigator.sendbeacon()' successfully sends for variant: ${testCase.name}${suffix}`);
     };
 }
diff --git a/third_party/blink/web_tests/external/wpt/bluetooth/resources/bluetooth-test.js b/third_party/blink/web_tests/external/wpt/bluetooth/resources/bluetooth-test.js
index b99564b..f6e5fd0 100644
--- a/third_party/blink/web_tests/external/wpt/bluetooth/resources/bluetooth-test.js
+++ b/third_party/blink/web_tests/external/wpt/bluetooth/resources/bluetooth-test.js
@@ -29,24 +29,13 @@
  * @returns {Promise<void>} Resolves when Chromium specific setup is complete.
  */
 async function performChromiumSetup() {
-  const chromiumResources = [
-    '/gen/content/test/data/mojo_web_test_helper_test.mojom.js',
-    '/gen/device/bluetooth/public/mojom/uuid.mojom.js',
-    '/gen/url/mojom/origin.mojom.js',
-    '/gen/device/bluetooth/public/mojom/test/fake_bluetooth.mojom.js',
-    '/gen/content/web_test/common/fake_bluetooth_chooser.mojom.js',
-  ];
   // Determine path prefixes.
   let resPrefix = '/resources';
-  let extra = ['/resources/chromium/web-bluetooth-test.js'];
+  const chromiumResources = ['/resources/chromium/web-bluetooth-test.js'];
   const pathname = window.location.pathname;
-  if (pathname.includes('/web_tests/')) {
-    let root = pathname.match(/.*(?:web_tests)/);
-    resPrefix = `${root}/external/wpt/resources`;
-    extra = [
-      `${root}/external/wpt/resources/chromium/web-bluetooth-test.js`,
-      `${root}/resources/bluetooth/bluetooth-fake-adapter.js`,
-    ];
+  if (pathname.includes('/wpt_internal/')) {
+    chromiumResources.push(
+        '/wpt_internal/bluetooth/resources/bluetooth-fake-adapter.js');
   }
 
   await loadScript(`${resPrefix}/test-only-api.js`);
@@ -54,11 +43,12 @@
     return;
   }
 
-  await loadMojoResources(chromiumResources);
-  for (const path of extra) {
+  for (const path of chromiumResources) {
     await loadScript(path);
   }
 
+  await initializeChromiumResources();
+
   // Call setBluetoothFakeAdapter() to clean up any fake adapters left over by
   // legacy tests. Legacy tests that use setBluetoothFakeAdapter() sometimes
   // fail to clean their fake adapter. This is not a problem for these tests
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/positioned-grid-items-018.html b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/positioned-grid-items-018.html
new file mode 100644
index 0000000..0c9d216
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/abspos/positioned-grid-items-018.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css-grid/#abspos">
+<link rel="match" href="../../reference/ref-filled-green-100px-square-only.html">
+<p>Test passes if there is a filled green square.</p>
+<div style="display: grid; grid-template-columns: 200px; grid-template-rows: 200px; max-width: 100px; max-height: 100px; position: relative;">
+  <div style="background: green; position: absolute; width: 100%; height: 100%;"></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-gutters-015-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-gutters-015-ref.html
new file mode 100644
index 0000000..dd4d8daf
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-gutters-015-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<style>
+.grid {
+  display: grid;
+  padding: 10px;
+  grid-template-columns: 40px 40px;
+  grid-template-rows: 40px 40px;
+  border: solid;
+  width: 80px;
+  height: 80px;
+  gap: 16px;
+}
+.grid > div {
+  background: green;
+}
+</style>
+<div class="grid">
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-gutters-015.html b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-gutters-015.html
new file mode 100644
index 0000000..ed1048f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-gutters-015.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<link rel="help" href="https://www.w3.org/TR/css-grid-1/#gutters">
+<link rel="help" href="https://www.w3.org/TR/css-align-3/#gaps">
+<link rel="match" href="grid-gutters-015-ref.html">
+<style>
+.grid {
+  display: inline-grid;
+  padding: 10px;
+  grid-template-columns: 40px 40px;
+  grid-template-rows: 40px 40px;
+  border: solid;
+  gap: 20%;
+}
+.grid > div {
+  background: green;
+}
+</style>
+<div class="grid">
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-gutters-016-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-gutters-016-ref.html
new file mode 100644
index 0000000..a56ab07
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-gutters-016-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<style>
+.grid {
+  display: grid;
+  padding: 10px;
+  grid-template-columns: 40px 40px;
+  grid-template-rows: 40px 40px;
+  border: solid;
+  width: 140px;
+  height: 140px;
+  gap: 28px;
+}
+.grid > div {
+  background: green;
+}
+</style>
+<div class="grid">
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-gutters-016.html b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-gutters-016.html
new file mode 100644
index 0000000..163787c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-grid/alignment/grid-gutters-016.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<link rel="help" href="https://www.w3.org/TR/css-grid-1/#gutters">
+<link rel="help" href="https://www.w3.org/TR/css-align-3/#gaps">
+<link rel="match" href="grid-gutters-016-ref.html">
+<style>
+.grid {
+  display: inline-grid;
+  padding: 10px;
+  grid-template-columns: 40px 40px;
+  grid-template-rows: 40px 40px;
+  border: solid;
+  gap: 20%;
+  min-width: 140px;
+  min-height: 140px;
+}
+.grid > div {
+  background: green;
+}
+</style>
+<div class="grid">
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/lint.ignore b/third_party/blink/web_tests/external/wpt/lint.ignore
index 27ba549..65d307e4 100644
--- a/third_party/blink/web_tests/external/wpt/lint.ignore
+++ b/third_party/blink/web_tests/external/wpt/lint.ignore
@@ -716,13 +716,13 @@
 # Tests that depend on resources in /gen/ in Chromium:
 # https://github.com/web-platform-tests/wpt/issues/16455
 # Please consult with ecosystem-infra@chromium.org before adding more.
-MISSING DEPENDENCY: bluetooth/resources/bluetooth-test.js
 MISSING DEPENDENCY: contacts/resources/helpers.js
 MISSING DEPENDENCY: credential-management/support/otpcredential-helper.js
 MISSING DEPENDENCY: generic-sensor/resources/generic-sensor-helpers.js
 MISSING DEPENDENCY: idle-detection/resources/idle-detection-helper.js
 MISSING DEPENDENCY: mediacapture-image/resources/imagecapture-helpers.js
 MISSING DEPENDENCY: orientation-event/resources/orientation-event-helpers.js
+MISSING DEPENDENCY: resources/chromium/web-bluetooth-test.js
 MISSING DEPENDENCY: resources/chromium/webusb-test.js
 MISSING DEPENDENCY: resources/test-only-api.js
 MISSING DEPENDENCY: screen_enumeration/resources/screenenumeration-helpers.js
diff --git a/third_party/blink/web_tests/external/wpt/resources/chromium/web-bluetooth-test.js b/third_party/blink/web_tests/external/wpt/resources/chromium/web-bluetooth-test.js
index aa4b80d2..ee835c2 100644
--- a/third_party/blink/web_tests/external/wpt/resources/chromium/web-bluetooth-test.js
+++ b/third_party/blink/web_tests/external/wpt/resources/chromium/web-bluetooth-test.js
@@ -1,5 +1,9 @@
 'use strict';
 
+const content = {};
+const bluetooth = {};
+const MOJO_CHOOSER_EVENT_TYPE_MAP = {};
+
 function toMojoCentralState(state) {
   switch (state) {
     case 'absent':
@@ -54,58 +58,16 @@
   return map;
 }
 
-// Mapping of the property names of
-// BluetoothCharacteristicProperties defined in
-// https://webbluetoothcg.github.io/web-bluetooth/#characteristicproperties
-// to property names of the CharacteristicProperties mojo struct.
-const CHARACTERISTIC_PROPERTIES_WEB_TO_MOJO = {
-  broadcast: 'broadcast',
-  read: 'read',
-  write_without_response: 'write_without_response',
-  write: 'write',
-  notify: 'notify',
-  indicate: 'indicate',
-  authenticatedSignedWrites: 'authenticated_signed_writes',
-  extended_properties: 'extended_properties',
-};
-
-// Mapping of the Mojo ChooserEventType enum to a string.
-const MOJO_CHOOSER_EVENT_TYPE_MAP = (() => {
-  const ChooserEventType = content.mojom.ChooserEventType;
-  return {
-    [ChooserEventType.CHOOSER_OPENED]: 'chooser-opened',
-    [ChooserEventType.CHOOSER_CLOSED]: 'chooser-closed',
-    [ChooserEventType.ADAPTER_REMOVED]: 'adapter-removed',
-    [ChooserEventType.ADAPTER_DISABLED]: 'adapter-disabled',
-    [ChooserEventType.ADAPTER_ENABLED]: 'adapter-enabled',
-    [ChooserEventType.DISCOVERY_FAILED_TO_START]: 'discovery-failed-to-start',
-    [ChooserEventType.DISCOVERING]: 'discovering',
-    [ChooserEventType.DISCOVERY_IDLE]: 'discovery-idle',
-    [ChooserEventType.ADD_OR_UPDATE_DEVICE]: 'add-or-update-device',
-  }
-})();
-
 function ArrayToMojoCharacteristicProperties(arr) {
-  let struct = new bluetooth.mojom.CharacteristicProperties();
-
-  arr.forEach(val => {
-    let mojo_property =
-      CHARACTERISTIC_PROPERTIES_WEB_TO_MOJO[val];
-
-    if (struct.hasOwnProperty(mojo_property))
-      struct[mojo_property] = true;
-    else
-      throw `Invalid member '${val}' for CharacteristicProperties`;
-  });
-
+  const struct = {};
+  arr.forEach(property => { struct[property] = true; });
   return struct;
 }
 
 class FakeBluetooth {
   constructor() {
-    this.fake_bluetooth_ptr_ = new bluetooth.mojom.FakeBluetoothPtr();
-    Mojo.bindInterface(bluetooth.mojom.FakeBluetooth.name,
-        mojo.makeRequest(this.fake_bluetooth_ptr_).handle, 'process');
+    this.fake_bluetooth_ptr_ = new bluetooth.mojom.FakeBluetoothRemote();
+    this.fake_bluetooth_ptr_.$.bindNewPipeAndPassReceiver().bindInBrowser('process');
     this.fake_central_ = null;
   }
 
@@ -232,7 +194,7 @@
     }
 
     await this.fake_central_ptr_.simulateAdvertisementReceived(
-        new bluetooth.mojom.ScanResult(clonedScanResult));
+        clonedScanResult);
 
     return this.fetchOrCreatePeripheral_(clonedScanResult.deviceAddress);
   }
@@ -572,21 +534,17 @@
 // and records the events produced by the Bluetooth chooser.
 class FakeChooser {
   constructor() {
-    let fakeBluetoothChooserFactoryPtr =
-        new content.mojom.FakeBluetoothChooserFactoryPtr();
-    Mojo.bindInterface(content.mojom.FakeBluetoothChooserFactory.name,
-        mojo.makeRequest(fakeBluetoothChooserFactoryPtr).handle, 'process');
+    let fakeBluetoothChooserFactoryRemote =
+        new content.mojom.FakeBluetoothChooserFactoryRemote();
+    fakeBluetoothChooserFactoryRemote.$.bindNewPipeAndPassReceiver().bindInBrowser('process');
 
     this.fake_bluetooth_chooser_ptr_ =
-        new content.mojom.FakeBluetoothChooserPtr();
-
-    let clientPtrInfo = new mojo.AssociatedInterfacePtrInfo();
-    this.fake_bluetooth_chooser_client_binding_ =
-        new mojo.AssociatedBinding(content.mojom.FakeBluetoothChooserClient,
-            this, mojo.makeRequest(clientPtrInfo));
-
-    fakeBluetoothChooserFactoryPtr.createFakeBluetoothChooser(
-        mojo.makeRequest(this.fake_bluetooth_chooser_ptr_), clientPtrInfo);
+        new content.mojom.FakeBluetoothChooserRemote();
+    this.fake_bluetooth_chooser_client_receiver_ =
+        new content.mojom.FakeBluetoothChooserClientReceiver(this);
+    fakeBluetoothChooserFactoryRemote.createFakeBluetoothChooser(
+        this.fake_bluetooth_chooser_ptr_.$.bindNewPipeAndPassReceiver(),
+        this.fake_bluetooth_chooser_client_receiver_.$.associateAndPassRemote());
 
     this.events_ = new Array();
     this.event_listener_ = null;
@@ -639,12 +597,31 @@
   }
 }
 
-// If this line fails, it means that current environment does not support the
-// Web Bluetooth Test API.
-try {
-  navigator.bluetooth.test = new FakeBluetooth();
-} catch {
+async function initializeChromiumResources() {
+  content.mojom = await import(
+      '/gen/content/web_test/common/fake_bluetooth_chooser.mojom.m.js');
+  bluetooth.mojom = await import(
+      '/gen/device/bluetooth/public/mojom/test/fake_bluetooth.mojom.m.js');
+
+  const map = MOJO_CHOOSER_EVENT_TYPE_MAP;
+  const types = content.mojom.ChooserEventType;
+  map[types.CHOOSER_OPENED] = 'chooser-opened';
+  map[types.CHOOSER_CLOSED] = 'chooser-closed';
+  map[types.ADAPTER_REMOVED] = 'adapter-removed';
+  map[types.ADAPTER_DISABLED] = 'adapter-disabled';
+  map[types.ADAPTER_ENABLED] = 'adapter-enabled';
+  map[types.DISCOVERY_FAILED_TO_START] = 'discovery-failed-to-start';
+  map[types.DISCOVERING] = 'discovering';
+  map[types.DISCOVERY_IDLE] = 'discovery-idle';
+  map[types.ADD_OR_UPDATE_DEVICE] = 'add-or-update-device';
+
+  // If this line fails, it means that current environment does not support the
+  // Web Bluetooth Test API.
+  try {
+    navigator.bluetooth.test = new FakeBluetooth();
+  } catch {
     throw 'Web Bluetooth Test API is not implemented on this ' +
         'environment. See the bluetooth README at ' +
         'https://github.com/web-platform-tests/wpt/blob/master/bluetooth/README.md#web-bluetooth-testing';
+  }
 }
diff --git a/third_party/blink/web_tests/fast/scroll-behavior/middleclick-autoscroll-nested-elements.html b/third_party/blink/web_tests/fast/scroll-behavior/middleclick-autoscroll-nested-elements.html
deleted file mode 100644
index aa82bb54..0000000
--- a/third_party/blink/web_tests/fast/scroll-behavior/middleclick-autoscroll-nested-elements.html
+++ /dev/null
@@ -1,71 +0,0 @@
-<!DOCTYPE HTML>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src='../../resources/gesture-util.js'></script>
-<style>
-
-body {
-  height: 2000px;
-  width: 2000px;
-  background: repeating-linear-gradient(
-    45deg,
-    #606dbc,
-    #606dbc 40px,
-    #465298 40px,
-    #465298 80px
-  ) local;
-}
-
-#scroller {
-  width: 90px;
-  border: 2px solid black;
-  height: 90px;
-  position: absolute;
-  top: 50px;
-  overflow: auto;
-  background: repeating-linear-gradient(
-    135deg,
-    #bc6d60,
-    #bc6d60 40px,
-    #985246 40px,
-    #985246 80px
-  ) local;
-}
-
-#contents {
-  height: 200px;
-}
-
-</style>
-
-<div id="scroller">
-	<div id="contents"></div>
-</div>
-
-<script>
-
-var scroller = document.getElementById('scroller');
-
-promise_test(async () => {
-  assert_equals(scroller.scrollTop, 0);
-  await waitForCompositorCommit();
-  await mouseClickOn(12, 60, 1);
-  await mouseMoveTo(12, 260);
-  await mouseClickOn(12, 260, 1);
-  await waitFor(() => {
-    return scroller.scrollTop > 0;
-  }, "failed to scroll scroller vertically");
-}, "Middle click autoscroll should scroll child if child delta can be consumed.");
-
-promise_test(async () => {
-  assert_equals(document.scrollingElement.scrollLeft, 0)
-  await waitForCompositorCommit();
-  await mouseClickOn(12, 60, 1);
-  await mouseMoveTo(212, 60);
-  await mouseClickOn(212, 60, 1);
-  await waitFor(() => {
-    return document.scrollingElement.scrollLeft > 0;
-  }, "failed to scroll document body horizontally");
-}, "Middle click autoscroll should scroll parent if child delta can not be consumed.");
-
-</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/scrolling/autoscroll-iframe-no-scrolling.html b/third_party/blink/web_tests/fast/scrolling/autoscroll-iframe-no-scrolling.html
index 1d68352..7e76fbf 100644
--- a/third_party/blink/web_tests/fast/scrolling/autoscroll-iframe-no-scrolling.html
+++ b/third_party/blink/web_tests/fast/scrolling/autoscroll-iframe-no-scrolling.html
@@ -86,14 +86,15 @@
       // Autoscroll over the inner scroller.
       await autoScroll(startX, startY, endX, endY);
       await waitForAnimationEndTimeBased( () => { return window.scrollY; } );
-      assert_equals(frames[0].window.scrollY, 0, "Iframe frame should not scroll");
+      assert_equals(window.scrollY, 0, "Main frame should not scroll");
 
       // Autoscroll over the iframe.
       startX = rect.right - 20;
       endX = startX;
       await autoScroll(startX, startY, endX, endY);
       await waitForAnimationEndTimeBased( () => { return window.scrollY; } );
-      assert_true(window.scrollY > 0, "Main frame should not scroll");
+      assert_equals(window.scrollY, 0, "Main frame should not scroll");
+
       assert_equals(frames[0].window.scrollY, 0, "IFrame must NOT scroll.");
     });
 });
diff --git a/third_party/blink/web_tests/fast/scrolling/autoscroll-latch-clicked-node-if-parent-unscrollable.html b/third_party/blink/web_tests/fast/scrolling/autoscroll-latch-clicked-node-if-parent-unscrollable.html
deleted file mode 100644
index 2e5a335..0000000
--- a/third_party/blink/web_tests/fast/scrolling/autoscroll-latch-clicked-node-if-parent-unscrollable.html
+++ /dev/null
@@ -1,49 +0,0 @@
-<!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/gesture-util.js"></script>
-
-<style>
-  #container {
-    width:500px;
-    height:100px;
-    overflow:auto;
-    border:2px solid red;
-    padding:0px;
-  }
-  #spacer {
-    height:200px;
-  }
-</style>
-
-<ol>
-  <li>Middle-click inside the &lt;div&gt; with the red border below to activate autoscroll.</li>
-  <li>First, move the mouse such that you scroll the &lt;div&gt; in unavailable scroll direction and then in scrollable direction.</li>
-  <li>If bug repros, it won't scroll in available direction.</li>
-</ol>
-<div id="container">
-  <div id="spacer"></div>
-</div>
-
-<script>
-
-window.onload = async function()
-{
-    const container = document.getElementById("container");
-    const leftButton = 0;
-    const middleButton = 1;
-
-    promise_test (async (t) => {
-      await waitForCompositorCommit();
-      await mouseClickOn(container.offsetLeft + 10, container.offsetTop + 10, middleButton);
-      //Move mouse in unavailable direction first.
-      await mouseMoveTo(container.offsetLeft + (container.offsetWidth/2), container.offsetTop + 10);
-      //Move mouse in available direction to scroll the content.
-      await mouseMoveTo(container.offsetLeft + (container.offsetWidth/2), container.offsetTop + container.offsetHeight);
-
-      await waitFor(() => {
-        return container.scrollTop === container.scrollHeight - container.clientHeight;
-      }, "Failed to scroll container with middle-click autoscroll.");
-    }, "Container scrolled in available direction.");
-}
-</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces-expected.txt b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces-expected.txt
new file mode 100644
index 0000000..e14ba67
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces-expected.txt
@@ -0,0 +1,3 @@
+Test that the API exists with origin trial token
+
+FAILURE
diff --git a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces.html b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces.html
index ce9ce30..96afbc7 100644
--- a/third_party/blink/web_tests/http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces.html
+++ b/third_party/blink/web_tests/http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces.html
@@ -5,14 +5,20 @@
 -->
 <meta http-equiv="origin-trial" content="A1q7Ss8yaDaFBy5/0JLZCpLDbCD0o4uPIJkE9YEkUUuOBdvmdJiBcoNSy9OvLuRh+XsWnW3zP+0UcWI2T1vP1AwAAABZeyJvcmlnaW4iOiAiaHR0cDovLzEyNy4wLjAuMTo4MDAwIiwgImZlYXR1cmUiOiAiSW50ZXJlc3RDb2hvcnRBUEkiLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0=" />
 <title>Interest Cohort API - interfaces exposed by origin trial</title>
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="/resources/origin-trials-helper.js"></script>
+<body>
+<p>Test that the API exists with origin trial token</p>
+<div id="result"></div>
 <script>
 'use strict'
 
-test(t => {
-  assert_true(document.interestCohort instanceof Function, 'interestCohort function can be accessed on document');
-}, 'Interest Cohort API entry point in Origin-Trial enabled document.');
+if (window.testRunner) {
+  testRunner.dumpAsText();
+}
 
+if (document.interestCohort instanceof Function) {
+  document.getElementById("result").innerHTML += "SUCCESS";
+} else {
+  document.getElementById("result").innerHTML += "FAILURE";
+}
 </script>
+</body>
diff --git a/third_party/blink/web_tests/virtual/interest-cohort-api-origin-trial/README.md b/third_party/blink/web_tests/virtual/interest-cohort-api-origin-trial/README.md
new file mode 100644
index 0000000..d260d11
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/interest-cohort-api-origin-trial/README.md
@@ -0,0 +1,2 @@
+*This suite runs the tests with**
+`--enable-features=InterestCohortAPIOriginTrial`
diff --git a/third_party/blink/web_tests/virtual/interest-cohort-api-origin-trial/http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces-expected.txt b/third_party/blink/web_tests/virtual/interest-cohort-api-origin-trial/http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces-expected.txt
new file mode 100644
index 0000000..710fa8f
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/interest-cohort-api-origin-trial/http/tests/origin_trials/webexposed/interest-cohort-origin-trial-interfaces-expected.txt
@@ -0,0 +1,3 @@
+Test that the API exists with origin trial token
+
+SUCCESS
diff --git a/third_party/blink/web_tests/bluetooth/DIR_METADATA b/third_party/blink/web_tests/wpt_internal/bluetooth/DIR_METADATA
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/DIR_METADATA
rename to third_party/blink/web_tests/wpt_internal/bluetooth/DIR_METADATA
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/PRESUBMIT.py b/third_party/blink/web_tests/wpt_internal/bluetooth/PRESUBMIT.py
new file mode 100644
index 0000000..9ac92fc
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/PRESUBMIT.py
@@ -0,0 +1,27 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Chromium presubmit script for Web Bluetooth layout tests.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts.
+"""
+
+
+def CheckGeneratedFiles(input_api, output_api):
+    test_path = input_api.os_path.join(input_api.PresubmitLocalPath(),
+                                       'generate_test.py')
+    cmd_name = 'generate_test'
+    cmd = [input_api.python_executable, test_path]
+
+    test_cmd = input_api.Command(name=cmd_name,
+                                 cmd=cmd,
+                                 kwargs={},
+                                 message=output_api.PresubmitError)
+    if input_api.verbose:
+        print('Running ' + cmd_name)
+
+    return input_api.RunTests([test_cmd])
+
+
+def CheckChangeOnUpload(input_api, output_api):
+    return CheckGeneratedFiles(input_api, output_api)
diff --git a/third_party/blink/web_tests/bluetooth/README.md b/third_party/blink/web_tests/wpt_internal/bluetooth/README.md
similarity index 96%
rename from third_party/blink/web_tests/bluetooth/README.md
rename to third_party/blink/web_tests/wpt_internal/bluetooth/README.md
index 7cef7911..6ad3ef3 100644
--- a/third_party/blink/web_tests/bluetooth/README.md
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/README.md
@@ -84,14 +84,14 @@
 source root:
 
 ```sh
-$ python third_party/blink/web_tests/bluetooth/generate.py
+$ python third_party/blink/web_tests/wpt_internal/bluetooth/generate.py
 ```
 
 To check that generated tests are correct and that there are no obsolete tests,
 or tests for which a template does not exist anymore, run:
 
 ```sh
-$ python third_party/blink/web_tests/bluetooth/generate_test.py
+$ python third_party/blink/web_tests/wpt_internal/bluetooth/generate_test.py
 ```
 
 More details can be found in `generate.py` and `generate_test.py`.
@@ -108,4 +108,4 @@
 * [Web Bluetooth Test API Dependencies]
 * [web-platform-tests Bluetooth README]
 
-[Blink>Bluetooth]: https://bugs.chromium.org/p/chromium/issues/list?q=component%3ABlink%3EBluetooth&can=2
\ No newline at end of file
+[Blink>Bluetooth]: https://bugs.chromium.org/p/chromium/issues/list?q=component%3ABlink%3EBluetooth&can=2
diff --git a/third_party/blink/web_tests/bluetooth/__init__.py b/third_party/blink/web_tests/wpt_internal/bluetooth/__init__.py
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/__init__.py
rename to third_party/blink/web_tests/wpt_internal/bluetooth/__init__.py
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/descriptor-not-found.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/descriptor-not-found.https.html
similarity index 69%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/descriptor-not-found.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/descriptor-not-found.https.html
index c4f169c..fad5e81b 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/descriptor-not-found.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/descriptor-not-found.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
  let descriptorUUID = '00002906-0000-1000-8000-00805f9b34fb';
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-blocklisted.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-blocklisted.https.html
similarity index 66%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-blocklisted.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-blocklisted.https.html
index 35365c2..e175dce 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-blocklisted.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-blocklisted.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'Make sure that getDescriptor can not access blocklisted ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-before.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-before.https.html
index a4088f1..771e6a9 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'Device disconnects before getDescriptor. ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-error.https.html
similarity index 77%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-error.https.html
index ee081d0..619a4f8c 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-success.https.html
similarity index 77%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-success.https.html
index c880f5b..f8d2a25 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-device-disconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-before.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-before.https.html
index 2207a63..0d6a2ab 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'disconnect() called before getDescriptor. ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-error.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-error.https.html
index 40b6b5f..fde9ee50 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-success.https.html
similarity index 75%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-success.https.html
index 917da6b..f54a652 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-disconnect-called-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-error.https.html
similarity index 75%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-error.https.html
index 166b76a..e6bb963 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-success.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-success.https.html
index 8e7bfcd..d58bd4d 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-garbage-collection-ran-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-invalid-name.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-invalid-name.https.html
similarity index 76%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-invalid-name.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-invalid-name.https.html
index 3407915..84db2e1d 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-descriptor-invalid-name.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-descriptor-invalid-name.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-device-out-of-range.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-device-out-of-range.https.html
similarity index 70%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-device-out-of-range.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-device-out-of-range.https.html
index d333db4..42863cf 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptor/gen-device-out-of-range.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptor/gen-device-out-of-range.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 // TODO(672127) Use this test case to test the rest of characteristic functions.
 'use strict';
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/blocklisted-descriptors-not-present.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/blocklisted-descriptors-not-present.https.html
new file mode 100644
index 0000000..9e4951e
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/blocklisted-descriptors-not-present.https.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+const test_desc = 'Make sure blocklisted descriptors are not reported.';
+
+bluetooth_test(() => getBlocklistExcludeWritesCharacteristic()
+    .then(({characteristic}) => characteristic.getDescriptors())
+    .then(descriptors => descriptors.forEach(descriptor =>
+        // |blocklist_test_descriptor_uuid| is a blocklisted UUID. It should
+        // never be present in a getDescriptors() result.
+        assert_true(descriptor.uuid !== blocklist_test_descriptor_uuid))),
+    test_desc);
+</script>
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-blocklisted.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-blocklisted.https.html
similarity index 66%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-blocklisted.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-blocklisted.https.html
index 0bbbc22..54c282cfc 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-blocklisted.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-blocklisted.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'Make sure that getDescriptors can not access blocklisted ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before-with-uuid.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before-with-uuid.https.html
index 6633ac2b..e08aae2 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'Device disconnects before getDescriptors. ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before.https.html
index 46ca3a5..e224dc0b 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'Device disconnects before getDescriptors. ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error-with-uuid.https.html
similarity index 77%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error-with-uuid.https.html
index 56b35820..3e8da2c 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error.https.html
similarity index 77%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error.https.html
index d1f2670..041e6c9 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success-with-uuid.https.html
similarity index 77%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success-with-uuid.https.html
index 04f540e..9406b8f5 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success.https.html
similarity index 77%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success.https.html
index 5a5a497..3307ec0 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-device-disconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before-with-uuid.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before-with-uuid.https.html
index f3981bd3..9e3bb74 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'disconnect() called before getDescriptors. ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before.https.html
similarity index 67%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before.https.html
index dc3a560..566f453 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'disconnect() called before getDescriptors. ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error-with-uuid.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error-with-uuid.https.html
index d65c74f1..45aa8e8 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error.https.html
index 98cc15b1..513c1cd 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success-with-uuid.https.html
similarity index 75%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success-with-uuid.https.html
index 7a89da1..4b6441a6 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success.https.html
similarity index 75%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success.https.html
index 8215ee43..271f8c4 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-disconnect-called-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error-with-uuid.https.html
similarity index 75%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error-with-uuid.https.html
index e1a8da87..627cd482 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error.https.html
similarity index 75%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error.https.html
index f847105f..308d7b0 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success-with-uuid.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success-with-uuid.https.html
index acbe4eb..830eea7 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success.https.html
index 9c2c4e2..b8bb7c11 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-garbage-collection-ran-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-invalid-name.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-invalid-name.https.html
similarity index 76%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-invalid-name.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-invalid-name.https.html
index 3ed1fb6d..a71ea64 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-descriptor-invalid-name.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-descriptor-invalid-name.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-device-out-of-range-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-device-out-of-range-with-uuid.https.html
similarity index 70%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-device-out-of-range-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-device-out-of-range-with-uuid.https.html
index d219378..f8c3edb 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-device-out-of-range-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-device-out-of-range-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 // TODO(672127) Use this test case to test the rest of characteristic functions.
 'use strict';
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-device-out-of-range.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-device-out-of-range.https.html
similarity index 70%
rename from third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-device-out-of-range.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-device-out-of-range.https.html
index 3665f3ad..7ccd367 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/getDescriptors/gen-device-out-of-range.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/getDescriptors/gen-device-out-of-range.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 // TODO(672127) Use this test case to test the rest of characteristic functions.
 'use strict';
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/add-listener-after-promise.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/add-listener-after-promise.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/characteristic/notifications/add-listener-after-promise.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/add-listener-after-promise.https.html
index d1cfca5..343835dc 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/add-listener-after-promise.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/add-listener-after-promise.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/add-multiple-event-listeners.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/add-multiple-event-listeners.https.html
similarity index 69%
rename from third_party/blink/web_tests/bluetooth/characteristic/notifications/add-multiple-event-listeners.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/add-multiple-event-listeners.https.html
index 84ae3e0..6e21a68 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/add-multiple-event-listeners.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/add-multiple-event-listeners.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/characteristic-does-not-support-notifications.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/characteristic-does-not-support-notifications.https.html
similarity index 64%
rename from third_party/blink/web_tests/bluetooth/characteristic/notifications/characteristic-does-not-support-notifications.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/characteristic-does-not-support-notifications.https.html
index 7a44b2d..4e2a5c5 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/characteristic-does-not-support-notifications.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/characteristic-does-not-support-notifications.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/concurrent-starts-and-receive-notification.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/concurrent-starts-and-receive-notification.https.html
similarity index 69%
rename from third_party/blink/web_tests/bluetooth/characteristic/notifications/concurrent-starts-and-receive-notification.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/concurrent-starts-and-receive-notification.https.html
index 4ea146b..80478f7 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/concurrent-starts-and-receive-notification.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/concurrent-starts-and-receive-notification.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 let char;
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/concurrent-starts.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/concurrent-starts.https.html
similarity index 62%
rename from third_party/blink/web_tests/bluetooth/characteristic/notifications/concurrent-starts.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/concurrent-starts.https.html
index 7c2dadb..fe08ec98 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/concurrent-starts.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/concurrent-starts.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/concurrent-stops.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/concurrent-stops.https.html
similarity index 63%
rename from third_party/blink/web_tests/bluetooth/characteristic/notifications/concurrent-stops.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/concurrent-stops.https.html
index 4b9f4f9..88305e7f 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/concurrent-stops.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/concurrent-stops.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/device-goes-out-of-range.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/device-goes-out-of-range.https.html
similarity index 65%
rename from third_party/blink/web_tests/bluetooth/characteristic/notifications/device-goes-out-of-range.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/device-goes-out-of-range.https.html
index da3ed95..f6f0264 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/device-goes-out-of-range.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/device-goes-out-of-range.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/event-after-starting.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/event-after-starting.https.html
similarity index 67%
rename from third_party/blink/web_tests/bluetooth/characteristic/notifications/event-after-starting.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/event-after-starting.https.html
index 138b2a4..281b7bb 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/event-after-starting.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/event-after-starting.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/gc-with-event-listener.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/gc-with-event-listener.https.html
similarity index 75%
rename from third_party/blink/web_tests/bluetooth/characteristic/notifications/gc-with-event-listener.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/gc-with-event-listener.https.html
index ca4fa15..2fb9231 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/gc-with-event-listener.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/gc-with-event-listener.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(async () => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/gc-with-pending-start.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/gc-with-pending-start.https.html
similarity index 71%
rename from third_party/blink/web_tests/bluetooth/characteristic/notifications/gc-with-pending-start.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/gc-with-pending-start.https.html
index d300105..27544c84 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/gc-with-pending-start.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/gc-with-pending-start.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/gc-with-pending-stop.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/gc-with-pending-stop.https.html
similarity index 70%
rename from third_party/blink/web_tests/bluetooth/characteristic/notifications/gc-with-pending-stop.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/gc-with-pending-stop.https.html
index db23cbe7..76e0ce7d 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/gc-with-pending-stop.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/gc-with-pending-stop.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/notification-after-disconnection.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/notification-after-disconnection.https.html
similarity index 82%
rename from third_party/blink/web_tests/bluetooth/characteristic/notifications/notification-after-disconnection.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/notification-after-disconnection.https.html
index c47d629..db74ae72a 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/notification-after-disconnection.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/notification-after-disconnection.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
@@ -32,7 +32,7 @@
   return setBluetoothFakeAdapter('HeartRateAdapter')
     .then(() => {
       let iframe = document.createElement('iframe');
-      iframe.src = '../../../resources/bluetooth/heart-rate-iframe.html';
+      iframe.src = 'resources/heart-rate-iframe.html';
       document.body.appendChild(iframe);
 
       return iframe_connected
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/parallel-start-stop.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/parallel-start-stop.https.html
similarity index 60%
rename from third_party/blink/web_tests/bluetooth/characteristic/notifications/parallel-start-stop.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/parallel-start-stop.https.html
index 7e944f9..a83076a 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/parallel-start-stop.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/parallel-start-stop.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/resources/bluetooth/heart-rate-iframe.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/resources/heart-rate-iframe.html
similarity index 100%
rename from third_party/blink/web_tests/resources/bluetooth/heart-rate-iframe.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/resources/heart-rate-iframe.html
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/start-before-stop-resolves.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/start-before-stop-resolves.https.html
similarity index 64%
rename from third_party/blink/web_tests/bluetooth/characteristic/notifications/start-before-stop-resolves.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/start-before-stop-resolves.https.html
index ea70c1c..09bed67 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/start-before-stop-resolves.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/start-before-stop-resolves.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/start-fails.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/start-fails.https.html
similarity index 65%
rename from third_party/blink/web_tests/bluetooth/characteristic/notifications/start-fails.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/start-fails.https.html
index 99609e7..07cc86e 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/start-fails.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/start-fails.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/start-stop-start-stop.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/start-stop-start-stop.https.html
similarity index 70%
rename from third_party/blink/web_tests/bluetooth/characteristic/notifications/start-stop-start-stop.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/start-stop-start-stop.https.html
index 32f808f2..011e301 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/start-stop-start-stop.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/start-stop-start-stop.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'The characteristic should be able to start and stop ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/start-succeeds.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/start-succeeds.https.html
similarity index 65%
rename from third_party/blink/web_tests/bluetooth/characteristic/notifications/start-succeeds.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/start-succeeds.https.html
index b0add6f8..09273bd6 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/start-succeeds.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/start-succeeds.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/start-twice-in-a-row.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/start-twice-in-a-row.https.html
similarity index 62%
rename from third_party/blink/web_tests/bluetooth/characteristic/notifications/start-twice-in-a-row.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/start-twice-in-a-row.https.html
index 9d70483..1bba2d2 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/start-twice-in-a-row.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/start-twice-in-a-row.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/notifications/stop-after-start-succeeds.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/stop-after-start-succeeds.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/characteristic/notifications/stop-after-start-succeeds.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/stop-after-start-succeeds.https.html
index b21d061..e293295d0 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/notifications/stop-after-start-succeeds.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/stop-after-start-succeeds.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/stop-twice.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/stop-twice.https.html
new file mode 100644
index 0000000..8fa6292
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/stop-twice.https.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(() => {
+  return setBluetoothFakeAdapter('HeartRateAdapter')
+    .then(() => requestDeviceWithTrustedClick({
+      filters: [{services: ['heart_rate']}]}))
+    .then(device => device.gatt.connect())
+    .then(gattServer => gattServer.getPrimaryService('heart_rate'))
+    .then(service => service.getCharacteristic('heart_rate_measurement'))
+    .then(characteristic => {
+      return characteristic.startNotifications()
+        .then(() => characteristic.stopNotifications())
+        .then(() => characteristic.stopNotifications());
+    });
+}, "Stopping twice.");
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/stop-without-starting.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/stop-without-starting.https.html
new file mode 100644
index 0000000..5d47273c
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/notifications/stop-without-starting.https.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(() => {
+  return setBluetoothFakeAdapter('HeartRateAdapter')
+    .then(() => requestDeviceWithTrustedClick({
+      filters: [{services: ['heart_rate']}]}))
+    .then(device => device.gatt.connect())
+    .then(gattServer => gattServer.getPrimaryService('heart_rate'))
+    .then(service => service.getCharacteristic('heart_rate_measurement'))
+    .then(characteristic => characteristic.stopNotifications());
+}, "Stop without starting.");
+</script>
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/readValue/blocklisted-characteristic.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/blocklisted-characteristic.https.html
similarity index 67%
rename from third_party/blink/web_tests/bluetooth/characteristic/readValue/blocklisted-characteristic.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/blocklisted-characteristic.https.html
index 13eee1c..5b051edf 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/readValue/blocklisted-characteristic.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/blocklisted-characteristic.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'Characteristic with exclude-reads fullfills write and ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/readValue/device-goes-out-of-range.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/device-goes-out-of-range.https.html
similarity index 66%
rename from third_party/blink/web_tests/bluetooth/characteristic/readValue/device-goes-out-of-range.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/device-goes-out-of-range.https.html
index cee197f6..e33b7abd 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/readValue/device-goes-out-of-range.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/device-goes-out-of-range.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-before.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-before.https.html
index 4d506028..ea7f56e 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'Device disconnects before readValue. ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-error.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-error.https.html
index 79fb4df0..dda1bac4 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-success.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-success.https.html
index da7e73c..95a83eb 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-device-disconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-error.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-error.https.html
index 898760a..aefd362 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-success.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-success.https.html
index 1e2cced..67acab2 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-device-reconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-before.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-before.https.html
index 1751b88a..aa96ab7 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'disconnect() called before readValue. ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-error.https.html
similarity index 71%
rename from third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-error.https.html
index a4ef96c..b3d20c4 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-success.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-success.https.html
index e6b61d0..559ad039 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-disconnect-called-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-error.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-error.https.html
index b777a91f..a4dd7118 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-success.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-success.https.html
index 506c521..f227f4c 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-garbage-collection-ran-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-error.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-error.https.html
index c4e3fbde..c088a4ea 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-success.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-success.https.html
index 2b2309f..61ea75c9 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/gen-gatt-op-reconnect-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/readValue/read-fails.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/read-fails.https.html
similarity index 65%
rename from third_party/blink/web_tests/bluetooth/characteristic/readValue/read-fails.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/read-fails.https.html
index 3ba27562..4265e52f 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/readValue/read-fails.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/readValue/read-fails.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-before.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-before.https.html
index 980463d..d4385374 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'Device disconnects before startNotifications. ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-error.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-error.https.html
index d42f640a..de35e0a 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-success.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-success.https.html
index feaf5205..580aaf3 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-device-disconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-error.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-error.https.html
index a845ea7..8dbc32f 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-success.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-success.https.html
index 23b660f..5cc19c6 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-device-reconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-before.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-before.https.html
index 14005cc..da29e6d 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'disconnect() called before startNotifications. ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-error.https.html
similarity index 71%
rename from third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-error.https.html
index d065c5e..14038b9a 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-success.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-success.https.html
index 831278e..afd8273 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-disconnect-called-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-error.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-error.https.html
index f122300..ebe5fcb 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-success.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-success.https.html
index 899d58f..a7f0b27 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-garbage-collection-ran-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-error.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-error.https.html
index 7b50f5b6..5d4f548 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-success.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-success.https.html
index 358efa3..b1bece9 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/startNotifications/gen-gatt-op-reconnect-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/device-reconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/device-reconnects-during-success.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/device-reconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/device-reconnects-during-success.https.html
index 106b4cfb..4c98db0 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/device-reconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/device-reconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-before.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-before.https.html
index cb8b8d5..f67961c3 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'Device disconnects before stopNotifications. ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-during-success.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-during-success.https.html
index 86020bc..0f12ccc 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/gen-gatt-op-device-disconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-before.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-before.https.html
index 6b64eb87..2f84f1e5 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'disconnect() called before stopNotifications. ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-during-success.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-during-success.https.html
index 65e7b657..3899af2 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/gen-gatt-op-disconnect-called-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/gen-gatt-op-garbage-collection-ran-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/gen-gatt-op-garbage-collection-ran-during-success.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/gen-gatt-op-garbage-collection-ran-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/gen-gatt-op-garbage-collection-ran-during-success.https.html
index 9b94330..b31ace52 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/gen-gatt-op-garbage-collection-ran-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/gen-gatt-op-garbage-collection-ran-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/reconnect-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/reconnect-during-success.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/reconnect-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/reconnect-during-success.https.html
index 8112c7e..1c03d491 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/stopNotifications/reconnect-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/stopNotifications/reconnect-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/WebKit/LayoutTests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/blocklisted-characteristic.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/blocklisted-characteristic.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValue/blocklisted-characteristic.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/blocklisted-characteristic.https.html
index a5bc673..dea1a0b2 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/blocklisted-characteristic.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/blocklisted-characteristic.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'Characteristic with exclude-writes fullfills read and ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/device-goes-out-of-range.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/device-goes-out-of-range.https.html
similarity index 66%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValue/device-goes-out-of-range.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/device-goes-out-of-range.https.html
index 93b2091..3be0f77 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/device-goes-out-of-range.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/device-goes-out-of-range.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-before.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-before.https.html
index 5f8ca9b..ab7b1581 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'Device disconnects before writeValue. ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-error.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-error.https.html
index 8ca18fda..7c81198 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-success.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-success.https.html
index a6a1d566..bd743e9 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-device-disconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-error.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-error.https.html
index e3a45d5..bf7c285 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-success.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-success.https.html
index 7219d8c0..b85c89e 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-device-reconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-before.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-before.https.html
index 0ac0e77..25f15ee0 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'disconnect() called before writeValue. ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-error.https.html
similarity index 71%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-error.https.html
index cec5863..9c90965 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-success.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-success.https.html
index 771360a..da7c69d 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-disconnect-called-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-error.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-error.https.html
index 3b3dc5d..2e69696 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-success.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-success.https.html
index ebbe9d1a..3ca80db 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-garbage-collection-ran-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-error.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-error.https.html
index c793441..c6783af 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-success.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-success.https.html
index 2dcdfb3..83f6da4 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/gen-gatt-op-reconnect-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/value-too-long.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/value-too-long.https.html
new file mode 100644
index 0000000..42ade1a
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/value-too-long.https.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+const test_desc = 'Trying to write more than 512 bytes should return an error.'
+let characteristic;
+
+bluetooth_test(() => getMeasurementIntervalCharacteristic()
+    .then(({characteristic}) => assert_promise_rejects_with_message(
+        characteristic.writeValue(new Uint8Array(513 /* length */)),
+        new DOMException(
+            'Failed to execute \'writeValue\' on ' +
+            '\'BluetoothRemoteGATTCharacteristic\': ' +
+            'Value can\'t exceed 512 bytes.',
+            'InvalidModificationError'
+        ), 'Value passed was too long.')),
+    test_desc);
+</script>
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/write-fails.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/write-fails.https.html
similarity index 64%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValue/write-fails.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/write-fails.https.html
index 116005a..ab0b6edb 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/write-fails.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/write-fails.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/write-updates-value.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/write-updates-value.https.html
similarity index 67%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValue/write-updates-value.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/write-updates-value.https.html
index fd6d267c..0fde4ebf 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValue/write-updates-value.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValue/write-updates-value.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'A regular write request to a writable characteristic ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/blocklisted-characteristic.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/blocklisted-characteristic.https.html
similarity index 66%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/blocklisted-characteristic.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/blocklisted-characteristic.https.html
index 819e78b..ad3d093 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/blocklisted-characteristic.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/blocklisted-characteristic.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'Characteristic with exclude-writes fullfills read and ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/device-goes-out-of-range.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/device-goes-out-of-range.https.html
similarity index 66%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/device-goes-out-of-range.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/device-goes-out-of-range.https.html
index 0371f714..f63f5f95 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/device-goes-out-of-range.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/device-goes-out-of-range.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(async () => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-disconnects-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-disconnects-before.https.html
similarity index 69%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-disconnects-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-disconnects-before.https.html
index d51beaf..024e961 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-disconnects-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-disconnects-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'Device disconnects before writeValueWithResponse. ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-disconnects-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-disconnects-during-error.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-disconnects-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-disconnects-during-error.https.html
index 044e388..47291b8 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-disconnects-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-disconnects-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-disconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-disconnects-during-success.https.html
similarity index 75%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-disconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-disconnects-during-success.https.html
index 7172f60..cf83c37b 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-disconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-disconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-reconnects-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-reconnects-during-error.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-reconnects-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-reconnects-during-error.https.html
index edfa6cd..8183edc 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-reconnects-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-reconnects-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-reconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-reconnects-during-success.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-reconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-reconnects-during-success.https.html
index 65fbdcb..976319c 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-reconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-device-reconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-disconnect-called-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-disconnect-called-before.https.html
similarity index 69%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-disconnect-called-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-disconnect-called-before.https.html
index bf36a50..a173193 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-disconnect-called-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-disconnect-called-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'disconnect() called before writeValueWithResponse. ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-disconnect-called-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-disconnect-called-during-error.https.html
similarity index 71%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-disconnect-called-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-disconnect-called-during-error.https.html
index 8f862db..9b297fa 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-disconnect-called-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-disconnect-called-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-disconnect-called-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-disconnect-called-during-success.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-disconnect-called-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-disconnect-called-during-success.https.html
index 926312e..a432cd3 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-disconnect-called-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-disconnect-called-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-garbage-collection-ran-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-garbage-collection-ran-during-error.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-garbage-collection-ran-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-garbage-collection-ran-during-error.https.html
index fbc01cc2..fec86283 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-garbage-collection-ran-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-garbage-collection-ran-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-garbage-collection-ran-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-garbage-collection-ran-during-success.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-garbage-collection-ran-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-garbage-collection-ran-during-success.https.html
index 97b2148..601c6ac 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-garbage-collection-ran-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-garbage-collection-ran-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-reconnect-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-reconnect-during-error.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-reconnect-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-reconnect-during-error.https.html
index eb5873d..a093ff84 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-reconnect-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-reconnect-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-reconnect-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-reconnect-during-success.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-reconnect-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-reconnect-during-success.https.html
index 133da95a..f149ab5 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-reconnect-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/gen-gatt-op-reconnect-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/value-too-long.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/value-too-long.https.html
new file mode 100644
index 0000000..abf613a
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/value-too-long.https.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+const test_desc = 'Trying to write more than 512 bytes should return an error.'
+
+bluetooth_test(async () => {
+  const {characteristic} = await getMeasurementIntervalCharacteristic();
+  await assert_promise_rejects_with_message(
+      characteristic.writeValueWithResponse(new Uint8Array(513 /* length */)),
+      new DOMException(
+          'Failed to execute \'writeValueWithResponse\' on ' +
+          '\'BluetoothRemoteGATTCharacteristic\': ' +
+          'Value can\'t exceed 512 bytes.',
+          'InvalidModificationError'
+      ), 'Value passed was too long.');
+}, test_desc);
+</script>
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/write-fails.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/write-fails.https.html
similarity index 61%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/write-fails.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/write-fails.https.html
index 15bb9c1..6f439f9b 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/write-fails.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/write-fails.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(async () => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/write-updates-value.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/write-updates-value.https.html
similarity index 64%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/write-updates-value.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/write-updates-value.https.html
index 8b6c7b7a..c72b65e 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithResponse/write-updates-value.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithResponse/write-updates-value.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'A regular write request to a writable characteristic ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/blocklisted-characteristic.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/blocklisted-characteristic.https.html
similarity index 67%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/blocklisted-characteristic.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/blocklisted-characteristic.https.html
index dc5ea88..83b6222 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/blocklisted-characteristic.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/blocklisted-characteristic.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'Characteristic with exclude-writes fullfills read and ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/device-goes-out-of-range.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/device-goes-out-of-range.https.html
similarity index 66%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/device-goes-out-of-range.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/device-goes-out-of-range.https.html
index 8d06ecb..bdaedcf 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/device-goes-out-of-range.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/device-goes-out-of-range.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(async () => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-disconnects-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-disconnects-before.https.html
similarity index 69%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-disconnects-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-disconnects-before.https.html
index ee3e2f36..5078eb7 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-disconnects-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-disconnects-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'Device disconnects before writeValueWithoutResponse. ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-disconnects-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-disconnects-during-error.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-disconnects-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-disconnects-during-error.https.html
index a6428b6..17873ee 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-disconnects-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-disconnects-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-disconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-disconnects-during-success.https.html
similarity index 75%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-disconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-disconnects-during-success.https.html
index 0ba05f7..3a432984 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-disconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-disconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-reconnects-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-reconnects-during-error.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-reconnects-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-reconnects-during-error.https.html
index 3c21917..9d91214 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-reconnects-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-reconnects-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-reconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-reconnects-during-success.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-reconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-reconnects-during-success.https.html
index 801b3040..de998146 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-reconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-device-reconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-disconnect-called-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-disconnect-called-before.https.html
similarity index 69%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-disconnect-called-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-disconnect-called-before.https.html
index de2ce0eb..055806ba 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-disconnect-called-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-disconnect-called-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'disconnect() called before writeValueWithoutResponse. ' +
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-disconnect-called-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-disconnect-called-during-error.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-disconnect-called-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-disconnect-called-during-error.https.html
index 3fa0f92..e906907 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-disconnect-called-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-disconnect-called-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-disconnect-called-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-disconnect-called-during-success.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-disconnect-called-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-disconnect-called-during-success.https.html
index 07dae7a..7c4915d 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-disconnect-called-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-disconnect-called-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-garbage-collection-ran-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-garbage-collection-ran-during-error.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-garbage-collection-ran-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-garbage-collection-ran-during-error.https.html
index 5f301d8..ec60625 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-garbage-collection-ran-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-garbage-collection-ran-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-garbage-collection-ran-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-garbage-collection-ran-during-success.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-garbage-collection-ran-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-garbage-collection-ran-during-success.https.html
index a9df9a2..9474324 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-garbage-collection-ran-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-garbage-collection-ran-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-reconnect-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-reconnect-during-error.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-reconnect-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-reconnect-during-error.https.html
index 479d802..6754d20 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-reconnect-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-reconnect-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-reconnect-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-reconnect-during-success.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-reconnect-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-reconnect-during-success.https.html
index da8a45a4..1cebe193 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-reconnect-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/gen-gatt-op-reconnect-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(() => {
   let val = new Uint8Array([1]);
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/value-too-long.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/value-too-long.https.html
similarity index 60%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/value-too-long.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/value-too-long.https.html
index 56dd1c74..220910f 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/value-too-long.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/value-too-long.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'Trying to write more than 512 bytes should return an error.'
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/write-fails.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/write-fails.https.html
similarity index 61%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/write-fails.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/write-fails.https.html
index 25c4ef2a..d25ccd9e23 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/write-fails.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/write-fails.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(async () => {
diff --git a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/write-updates-value.html b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/write-updates-value.https.html
similarity index 63%
rename from third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/write-updates-value.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/write-updates-value.https.html
index becfbd9b..d7e60915 100644
--- a/third_party/blink/web_tests/bluetooth/characteristic/writeValueWithoutResponse/write-updates-value.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/characteristic/writeValueWithoutResponse/write-updates-value.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'A regular write request to a writable characteristic ' +
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/characteristic-same-from-2-descriptors.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/characteristic-same-from-2-descriptors.https.html
similarity index 67%
rename from third_party/blink/web_tests/bluetooth/descriptor/characteristic-same-from-2-descriptors.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/characteristic-same-from-2-descriptors.https.html
index 140f0952..123609b 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/characteristic-same-from-2-descriptors.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/characteristic-same-from-2-descriptors.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/characteristic-same-object.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/characteristic-same-object.https.html
similarity index 63%
rename from third_party/blink/web_tests/bluetooth/descriptor/characteristic-same-object.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/characteristic-same-object.https.html
index 07ba832..a0df550 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/characteristic-same-object.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/characteristic-same-object.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/readValue/descriptor-is-blocklisted.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/descriptor-is-blocklisted.https.html
similarity index 67%
rename from third_party/blink/web_tests/bluetooth/descriptor/readValue/descriptor-is-blocklisted.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/descriptor-is-blocklisted.https.html
index 54214a7b..a9627df 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/readValue/descriptor-is-blocklisted.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/descriptor-is-blocklisted.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'An attempt to call readValue on a blocked descriptor must ' +
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-descriptor-is-removed.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-descriptor-is-removed.https.html
similarity index 64%
rename from third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-descriptor-is-removed.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-descriptor-is-removed.https.html
index f7f5fefa..8683d26 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-descriptor-is-removed.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-descriptor-is-removed.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'Descriptor gets removed. Reject with InvalidStateError.';
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-device-goes-out-of-range.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-device-goes-out-of-range.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-device-goes-out-of-range.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-device-goes-out-of-range.https.html
index 5e04e23..137b15f 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-device-goes-out-of-range.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-device-goes-out-of-range.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-before.https.html
similarity index 78%
rename from third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-before.https.html
index 0f8b9d02..6e7280e 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func) {
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-error.https.html
similarity index 78%
rename from third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-error.https.html
index 253aa048..1e544fb 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-success.https.html
similarity index 78%
rename from third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-success.https.html
index 4ec2097f..39af933c 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-device-disconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-error.https.html
similarity index 78%
rename from third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-error.https.html
index 8cf36b9..14d704b 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(
     () => {
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-success.https.html
similarity index 78%
rename from third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-success.https.html
index 292fab9..474e61f 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-device-reconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(
     () => {
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-before.https.html
similarity index 65%
rename from third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-before.https.html
index 482232d..53f1079 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'disconnect() called before readValue. Reject with ' +
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-error.https.html
similarity index 71%
rename from third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-error.https.html
index bbc40f0..48a92b0 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'disconnect() called during a readValue call that ' +
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-success.https.html
similarity index 71%
rename from third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-success.https.html
index 26f6ac1..2b44a51 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-disconnect-called-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'disconnect() called during a readValue call that ' +
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-fails.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-fails.https.html
similarity index 78%
rename from third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-fails.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-fails.https.html
index 7eb291c1..961a53b 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-fails.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-fails.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-error.https.html
similarity index 77%
rename from third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-error.https.html
index a53d3d9..020cc72 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-success.https.html
similarity index 77%
rename from third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-success.https.html
index 8942a39..42bedb72 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-garbage-collection-ran-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-error.https.html
similarity index 76%
rename from third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-error.https.html
index 3812821..988c628 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(
     () => {
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-success.https.html
similarity index 76%
rename from third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-success.https.html
index 81d7235..a47e8c9 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/gen-io-op-reconnect-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(
     () => {
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/read-updates-value.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/read-updates-value.https.html
new file mode 100644
index 0000000..88f81f6
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/readValue/read-updates-value.https.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+const test_desc = 'Successful read should update descriptor\'s value.';
+const value = new TextEncoder('utf-8').encode(user_description.name);
+let descriptor, fake_descriptor;
+
+bluetooth_test(() => getUserDescriptionDescriptor()
+    .then(_ => ({descriptor, fake_descriptor} = _))
+    .then(() => fake_descriptor.setNextReadResponse(GATT_SUCCESS, value))
+    .then(() => descriptor.readValue())
+    .then(() => assert_array_equals(new Uint8Array(descriptor.value.buffer),
+                                    value)),
+    test_desc);
+</script>
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/descriptor-is-blocklisted.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/descriptor-is-blocklisted.https.html
similarity index 67%
rename from third_party/blink/web_tests/bluetooth/descriptor/writeValue/descriptor-is-blocklisted.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/descriptor-is-blocklisted.https.html
index 53cec1d..2bb1521 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/descriptor-is-blocklisted.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/descriptor-is-blocklisted.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'An attempt to call writeValue on a blocked descriptor ' +
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-descriptor-is-removed.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-descriptor-is-removed.https.html
similarity index 65%
rename from third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-descriptor-is-removed.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-descriptor-is-removed.https.html
index d180785..a05a2cb 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-descriptor-is-removed.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-descriptor-is-removed.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'Descriptor gets removed. Reject with InvalidStateError.';
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-before.https.html
similarity index 78%
rename from third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-before.https.html
index ab1bd94..e6fa2f27 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func) {
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-error.https.html
similarity index 78%
rename from third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-error.https.html
index f5ff668..92373e12 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-success.https.html
similarity index 78%
rename from third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-success.https.html
index 5a68451..6af39b0c 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-device-disconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-error.https.html
similarity index 78%
rename from third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-error.https.html
index 0ea2759..5b01140 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(
     () => {
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-success.https.html
similarity index 78%
rename from third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-success.https.html
index a5fa4e9..1b70a65e2 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-device-reconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(
     () => {
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-before.https.html
similarity index 65%
rename from third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-before.https.html
index fd13a71d..9feec49 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'disconnect() called before writeValue. Reject with ' +
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-error.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-error.https.html
index c129a7f..39fe1eeb 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'disconnect() called during a writeValue call that ' +
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-success.https.html
similarity index 71%
rename from third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-success.https.html
index 9921f61..048fd9d 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-disconnect-called-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'disconnect() called during a writeValue call that ' +
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-fails.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-fails.https.html
similarity index 78%
rename from third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-fails.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-fails.https.html
index cebe79f..773b6b3 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-fails.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-fails.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-error.https.html
similarity index 77%
rename from third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-error.https.html
index 44114834..1fa6af4b 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-success.https.html
similarity index 77%
rename from third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-success.https.html
index 4d77783..b3acc96 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-garbage-collection-ran-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-error.https.html
similarity index 76%
rename from third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-error.https.html
index a7c3cc8..bc451c0 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(
     () => {
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-success.https.html
similarity index 76%
rename from third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-success.https.html
index e90e736..508676d 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/gen-io-op-reconnect-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 bluetooth_test(
     () => {
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/value-too-long.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/value-too-long.https.html
new file mode 100644
index 0000000..b2a63e7
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/value-too-long.https.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+const test_desc = 'Trying to write more than 512 bytes should return an error.';
+const expected = new DOMException(
+    'Failed to execute \'writeValue\' on \'BluetoothRemoteGATTDescriptor\': ' +
+    'Value can\'t exceed 512 bytes.', 'InvalidModificationError');
+
+bluetooth_test(() => getUserDescriptionDescriptor()
+    .then(({descriptor}) => assert_promise_rejects_with_message(
+        descriptor.writeValue(new Uint8Array(513 /* length */)),
+        expected,
+        'Value passed was too long.')),
+    test_desc);
+</script>
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/write-succeeds.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/write-succeeds.https.html
similarity index 76%
rename from third_party/blink/web_tests/bluetooth/descriptor/writeValue/write-succeeds.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/write-succeeds.https.html
index 6373442..9be19cb 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/write-succeeds.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/write-succeeds.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'A regular write request to a writable descriptor ' +
diff --git a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/write-updates-value.html b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/write-updates-value.https.html
similarity index 62%
rename from third_party/blink/web_tests/bluetooth/descriptor/writeValue/write-updates-value.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/write-updates-value.https.html
index e4c0a6a..a96ff6f4 100644
--- a/third_party/blink/web_tests/bluetooth/descriptor/writeValue/write-updates-value.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/descriptor/writeValue/write-updates-value.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'Successful write should update descriptor\'s value.';
diff --git a/third_party/blink/web_tests/bluetooth/generate.py b/third_party/blink/web_tests/wpt_internal/bluetooth/generate.py
similarity index 78%
rename from third_party/blink/web_tests/bluetooth/generate.py
rename to third_party/blink/web_tests/wpt_internal/bluetooth/generate.py
index 222521a..aacf8a8f 100644
--- a/third_party/blink/web_tests/bluetooth/generate.py
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/generate.py
@@ -52,7 +52,7 @@
 }, 'example test for getPrimaryServices');
 
 Run
-$ python //third_party/blink/web_tests/bluetooth/generate.py
+$ python //third_party/blink/web_tests/wpt_internal/bluetooth/generate.py
 and commit the generated files.
 """
 
@@ -65,7 +65,6 @@
 
 
 class GeneratedTest:
-
     def __init__(self, data, path, template):
         self.data = data
         self.path = path
@@ -78,7 +77,8 @@
 
     # Read Base Test Template.
     base_template_file_handle = open(
-        os.path.join(bluetooth_tests_dir, TEMPLATES_DIR, 'base_test_template.html'))
+        os.path.join(bluetooth_tests_dir, TEMPLATES_DIR,
+                     'base_test.html.template'))
     base_template_file_data = base_template_file_handle.read().decode('utf-8')
     base_template_file_handle.close()
 
@@ -103,43 +103,55 @@
 
         # Find function names in multiline pattern: CALLS( [ function_name,function_name2[UUID] ])
         result = re.search(
-            r'CALLS\(' + # CALLS(
+            r'CALLS\(' +  # CALLS(
             r'[^\[]*' +  # Any characters not [, allowing for new lines.
-            r'\[' +      # [
-            r'(.*?)' +   # group matching: function_name(), function_name2[UUID]
-            r'\]\)',     # adjacent closing characters: ])
-            template_file_data, re.MULTILINE | re.DOTALL)
+            r'\[' +  # [
+            r'(.*?)' +  # group matching: function_name(), function_name2[UUID]
+            r'\]\)',  # adjacent closing characters: ])
+            template_file_data,
+            re.MULTILINE | re.DOTALL)
 
         if result is None:
             raise Exception('Template must contain \'CALLS\' tokens')
 
-        new_test_file_data = base_template_file_data.replace('TEST',
-            template_file_data)
+        new_test_file_data = base_template_file_data.replace(
+            'TEST', template_file_data)
         # Replace CALLS([...]) with CALLS so that we don't have to replace the
         # CALLS([...]) for every new test file.
-        new_test_file_data = new_test_file_data.replace(result.group(), 'CALLS')
+        new_test_file_data = new_test_file_data.replace(
+            result.group(), 'CALLS')
 
         # Replace 'PREVIOUS_CALL' with 'CALLS' so that we can replace it while
         # replacing CALLS.
-        new_test_file_data = new_test_file_data.replace('PREVIOUS_CALL', 'CALLS')
+        new_test_file_data = new_test_file_data.replace(
+            'PREVIOUS_CALL', 'CALLS')
 
         for call in result.group(1).split('|'):
             # Parse call
             call = call.strip()
-            function_name, args, uuid_suffix = re.search(r'(.*?)\((.*)\)(\[UUID\])?', call).groups()
+            function_name, args, uuid_suffix = re.search(
+                r'(.*?)\((.*)\)(\[UUID\])?', call).groups()
 
             # Replace template tokens
             call_test_file_data = new_test_file_data
-            call_test_file_data = call_test_file_data.replace('CALLS', '{}({})'.format(function_name, args))
-            call_test_file_data = call_test_file_data.replace('FUNCTION_NAME', function_name)
+            call_test_file_data = call_test_file_data.replace(
+                'CALLS', '{}({})'.format(function_name, args))
+            call_test_file_data = call_test_file_data.replace(
+                'FUNCTION_NAME', function_name)
 
             # Get test file name
-            group_dir = os.path.basename(os.path.abspath(os.path.join(template, os.pardir)))
+            group_dir = os.path.basename(
+                os.path.abspath(os.path.join(template, os.pardir)))
 
-            call_test_file_name = 'gen-{}{}.html'.format(template_name, '-with-uuid' if uuid_suffix else '')
-            call_test_file_path = os.path.join(bluetooth_tests_dir, group_dir, function_name, call_test_file_name)
+            call_test_file_name = 'gen-{}{}.https.html'.format(
+                template_name, '-with-uuid' if uuid_suffix else '')
+            call_test_file_path = os.path.join(bluetooth_tests_dir, group_dir,
+                                               function_name,
+                                               call_test_file_name)
 
-            yield GeneratedTest(call_test_file_data, call_test_file_path, template)
+            yield GeneratedTest(call_test_file_data, call_test_file_path,
+                                template)
+
 
 def main():
     previous_generated_files = set()
@@ -176,6 +188,5 @@
             print generated_file
 
 
-
 if __name__ == '__main__':
     sys.exit(main())
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/generate_test.py b/third_party/blink/web_tests/wpt_internal/bluetooth/generate_test.py
new file mode 100755
index 0000000..d74e3b2
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/generate_test.py
@@ -0,0 +1,56 @@
+#!/usr/bin/python
+
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# TODO(509038): Delete this file after generate.py has been deleted, as it will
+# no longer be needed. There is a copy of this file in wpt/ that tests the
+# generate.py file in that directory.
+"""Test that the set of gen-* files is the same as the generated files."""
+
+import fnmatch
+import os
+import sys
+import generate
+
+UPDATE_TIP = (
+    'To update the generated tests, run:\n'
+    '$ python third_party/blink/web_tests/wpt_internal/bluetooth/generate.py')
+
+
+def main():
+    generated_files = set()
+    # Tests data in gen-* files is the same as the data generated.
+    for generated_test in generate.GetGeneratedTests():
+        generated_files.add(generated_test.path)
+        try:
+            with open(generated_test.path) as f:
+                data = f.read().decode('utf-8')
+                if data != generated_test.data:
+                    print generated_test.path + ' does not match template.'
+                    print UPDATE_TIP
+                    return -1
+        except IOError, e:
+            if e.errno == 2:
+                print 'Missing generated test:\n{}\nFor template:\n{}'.format(
+                    generated_test.path, generated_test.template)
+                print UPDATE_TIP
+                return -1
+
+    # Tests that there are no obsolete generated files.
+    previous_generated_files = set()
+    current_path = os.path.dirname(os.path.realpath(__file__))
+    for root, _, filenames in os.walk(current_path):
+        for filename in fnmatch.filter(filenames, 'gen-*.html'):
+            previous_generated_files.add(os.path.join(root, filename))
+
+    if previous_generated_files != generated_files:
+        print 'There are extra generated tests. Please remove them.'
+        for test_path in previous_generated_files - generated_files:
+            print test_path
+        return -1
+
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/third_party/blink/web_tests/bluetooth/idl/idl-BluetoothGATTRemoteServer.html b/third_party/blink/web_tests/wpt_internal/bluetooth/idl/idl-BluetoothGATTRemoteServer.https.html
similarity index 75%
rename from third_party/blink/web_tests/bluetooth/idl/idl-BluetoothGATTRemoteServer.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/idl/idl-BluetoothGATTRemoteServer.https.html
index a86199f..52becd4 100644
--- a/third_party/blink/web_tests/bluetooth/idl/idl-BluetoothGATTRemoteServer.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/idl/idl-BluetoothGATTRemoteServer.https.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
 <script>
 test(() => {
   assert_throws_js(ReferenceError, () => new BluetoothGATTRemoteServer(),
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/acceptAllDevices/device-with-no-name.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/acceptAllDevices/device-with-no-name.https.html
new file mode 100644
index 0000000..8cd010d
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/acceptAllDevices/device-with-no-name.https.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(() => {
+  return setBluetoothFakeAdapter('NoNameDeviceAdapter')
+    .then(() => requestDeviceWithTrustedClick({acceptAllDevices: true}))
+    .then(device => {
+      assert_true(device.name === null);
+    });
+}, 'Device with no name or UUIDs nearby. Should be found if ' +
+   'acceptAllDevices is true.');
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/acceptAllDevices/device-with-uuids.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/acceptAllDevices/device-with-uuids.https.html
new file mode 100644
index 0000000..fabe2cb
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/acceptAllDevices/device-with-uuids.https.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(() => {
+  return setBluetoothFakeAdapter('NoNameHeartRateAdapter')
+    .then(() => requestDeviceWithTrustedClick({acceptAllDevices: true}))
+    .then(device => {
+      assert_true(device.name === null);
+    });
+}, 'Device with only UUIDs nearby. Should be found if ' +
+   'acceptAllDevices is true.');
+</script>
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/consecutive-calls.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/consecutive-calls.https.html
similarity index 79%
rename from third_party/blink/web_tests/bluetooth/requestDevice/chooser/consecutive-calls.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/consecutive-calls.https.html
index 3a5da5b..f906721 100644
--- a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/consecutive-calls.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/consecutive-calls.https.html
@@ -1,17 +1,17 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
     () => {
       function assert_expected_events(events) {
         assert_equals(events.length, 4);
-        assert_equals(events[0], 'chooser-opened(file://)');
+        assert_equals(events[0], 'chooser-opened(https://web-platform.test:8444)');
         assert_equals(events[1], 'discovering');
         let idsByName = new AddDeviceEventSet();
         idsByName.assert_add_device_event(events[2]);
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/device-removed.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/device-removed.https.html
similarity index 76%
rename from third_party/blink/web_tests/bluetooth/requestDevice/chooser/device-removed.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/device-removed.https.html
index baa9bbf..a8af133 100644
--- a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/device-removed.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/device-removed.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(
@@ -19,7 +19,7 @@
                     }));
       return assert_promise_rejects_with_message(
           getBluetoothManualChooserEvents(5).then(events => {
-            assert_equals(events[0], 'chooser-opened(file://)');
+            assert_equals(events[0], 'chooser-opened(https://web-platform.test:8444)');
             let idsByName = new AddDeviceEventSet();
             idsByName.assert_add_device_event(events[1]);
             assert_true(
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/multiple-matching-devices.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/multiple-matching-devices.https.html
similarity index 69%
rename from third_party/blink/web_tests/bluetooth/requestDevice/chooser/multiple-matching-devices.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/multiple-matching-devices.https.html
index 2aa4dc31..c8eb541 100644
--- a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/multiple-matching-devices.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/multiple-matching-devices.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
@@ -17,7 +17,7 @@
   return getBluetoothManualChooserEvents(5)
       .then(events => {
         assert_equals(events.length, 5, events);
-        assert_equals(events[0], 'chooser-opened(file://)');
+        assert_equals(events[0], 'chooser-opened(https://web-platform.test:8444)');
         assert_equals(events[1], 'discovering');
         let idsByName = new AddDeviceEventSet();
         for (let addedDevice of [events[2], events[3]]) {
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/new-scan-all-types.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/new-scan-all-types.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/requestDevice/chooser/new-scan-all-types.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/new-scan-all-types.https.html
index 6cf5b0a2..6888bd4f 100644
--- a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/new-scan-all-types.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/new-scan-all-types.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
@@ -20,7 +20,7 @@
                   ]
                 }));
   return getBluetoothManualChooserEvents(7).then(events => {
-    assert_equals(events[0], 'chooser-opened(file://)');
+    assert_equals(events[0], 'chooser-opened(https://web-platform.test:8444)');
     let idsByName = new AddDeviceEventSet();
     idsByName.assert_add_device_event(events[1]);
     assert_true(idsByName.has('Connected Heart Rate Device'));
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/new-scan-connected-devices.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/new-scan-connected-devices.https.html
similarity index 63%
rename from third_party/blink/web_tests/bluetooth/requestDevice/chooser/new-scan-connected-devices.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/new-scan-connected-devices.https.html
index 837d12d..85d733ef 100644
--- a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/new-scan-connected-devices.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/new-scan-connected-devices.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
@@ -15,7 +15,7 @@
                                          filters: [{services: ['heart_rate']}]
                                        }));
   return getBluetoothManualChooserEvents(4).then(events => {
-    assert_equals(events[0], 'chooser-opened(file://)');
+    assert_equals(events[0], 'chooser-opened(https://web-platform.test:8444)');
     let idsByName = new AddDeviceEventSet();
     idsByName.assert_add_device_event(events[1]);
     assert_true(idsByName.has('Connected Heart Rate Device'), events[1]);
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/new-scan-device-added.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/new-scan-device-added.https.html
similarity index 75%
rename from third_party/blink/web_tests/bluetooth/requestDevice/chooser/new-scan-device-added.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/new-scan-device-added.https.html
index 8b246924..0bcdda0 100644
--- a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/new-scan-device-added.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/new-scan-device-added.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'The chooser should display newly detected devices.';
@@ -22,7 +22,7 @@
   let events = await fake_chooser.waitForEvents(2);
   assert_equals(events.length, 2);
   assert_equals(events[0].type, 'chooser-opened');
-  assert_equals(events[0].origin.scheme, 'file');
+  assert_equals(events[0].origin.scheme, 'https');
   assert_equals(events[1].type, 'discovering');
 
   // 2. Send the advertisement packet to central.
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/new-scan-device-changed.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/new-scan-device-changed.https.html
similarity index 61%
rename from third_party/blink/web_tests/bluetooth/requestDevice/chooser/new-scan-device-changed.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/new-scan-device-changed.https.html
index e58a22a..f3a07a24 100644
--- a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/new-scan-device-changed.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/new-scan-device-changed.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
@@ -16,7 +16,7 @@
               () => requestDeviceWithTrustedClick(
                   {filters: [{services: ['battery_service']}]}));
   return getBluetoothManualChooserEvents(4).then(events => {
-    assert_equals(events[0], 'chooser-opened(file://)');
+    assert_equals(events[0], 'chooser-opened(https://web-platform.test:8444)');
     assert_equals(events[1], 'discovering');
     let idsByName = new AddDeviceEventSet();
     idsByName.assert_add_device_event(events[2]);
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/new-scan-services-discovered.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/new-scan-services-discovered.https.html
similarity index 62%
rename from third_party/blink/web_tests/bluetooth/requestDevice/chooser/new-scan-services-discovered.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/new-scan-services-discovered.https.html
index 023a5b65..5cc04c4 100644
--- a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/new-scan-services-discovered.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/new-scan-services-discovered.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
@@ -16,7 +16,7 @@
               () => requestDeviceWithTrustedClick(
                   {filters: [{services: ['generic_access']}]}));
   return getBluetoothManualChooserEvents(4).then(events => {
-    assert_equals(events[0], 'chooser-opened(file://)');
+    assert_equals(events[0], 'chooser-opened(https://web-platform.test:8444)');
     assert_equals(events[1], 'discovering');
     let idsByName = new AddDeviceEventSet();
     idsByName.assert_add_device_event(events[2]);
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/restart-scan-finds-new-device.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/restart-scan-finds-new-device.https.html
similarity index 76%
rename from third_party/blink/web_tests/bluetooth/requestDevice/chooser/restart-scan-finds-new-device.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/restart-scan-finds-new-device.https.html
index cbfee8f..502fba0 100644
--- a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/restart-scan-finds-new-device.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/restart-scan-finds-new-device.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
@@ -21,7 +21,7 @@
   return getBluetoothManualChooserEvents(3)
       .then(events => {
         assert_array_equals(events, [
-          'chooser-opened(file://)',
+          'chooser-opened(https://web-platform.test:8444)',
           'discovering',
           'discovery-idle',
         ]);
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/restart-scan-includes-previous-device.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/restart-scan-includes-previous-device.https.html
similarity index 78%
rename from third_party/blink/web_tests/bluetooth/requestDevice/chooser/restart-scan-includes-previous-device.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/restart-scan-includes-previous-device.https.html
index 6d83f6f..508ee2b 100644
--- a/third_party/blink/web_tests/bluetooth/requestDevice/chooser/restart-scan-includes-previous-device.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/chooser/restart-scan-includes-previous-device.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
@@ -20,7 +20,7 @@
   return getBluetoothManualChooserEvents(4)
       .then(events => {
         assert_equals(events.length, 4, events);
-        assert_equals(events[0], 'chooser-opened(file://)');
+        assert_equals(events[0], 'chooser-opened(https://web-platform.test:8444)');
         let idsByName = new AddDeviceEventSet();
         idsByName.assert_add_device_event(events[1]);
         assert_true(idsByName.has('Connected Heart Rate Device'));
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/correct-filters.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/correct-filters.https.html
similarity index 64%
rename from third_party/blink/web_tests/bluetooth/requestDevice/correct-filters.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/correct-filters.https.html
index 5cdadd4..c59f3dd4 100644
--- a/third_party/blink/web_tests/bluetooth/requestDevice/correct-filters.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/correct-filters.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/device-iframe.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/device-iframe.https.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/requestDevice/device-iframe.https.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/device-iframe.https.https.html
index 9d4c2ed..6a652b9 100644
--- a/third_party/blink/web_tests/bluetooth/requestDevice/device-iframe.https.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/device-iframe.https.https.html
@@ -1,8 +1,8 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <body></body>
 <script>
 'use strict';
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/discovery-fails-to-start.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/discovery-fails-to-start.https.html
similarity index 61%
rename from third_party/blink/web_tests/bluetooth/requestDevice/discovery-fails-to-start.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/discovery-fails-to-start.https.html
index bfd9344..78821170 100644
--- a/third_party/blink/web_tests/bluetooth/requestDevice/discovery-fails-to-start.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/discovery-fails-to-start.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
@@ -17,7 +17,7 @@
   return getBluetoothManualChooserEvents(3).then(events => {
     assert_array_equals(
         events,
-        ['chooser-opened(file://)', 'discovering', 'discovery-failed-to-start'],
+        ['chooser-opened(https://web-platform.test:8444)', 'discovering', 'discovery-failed-to-start'],
         events);
     sendBluetoothManualChooserEvent('cancelled', '');
     return assert_promise_rejects_with_message(
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/filter-does-not-match.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/filter-does-not-match.https.html
similarity index 83%
rename from third_party/blink/web_tests/bluetooth/requestDevice/filter-does-not-match.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/filter-does-not-match.https.html
index 2fab7cc..fc3ae3e 100644
--- a/third_party/blink/web_tests/bluetooth/requestDevice/filter-does-not-match.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/filter-does-not-match.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 let matching_services = [heart_rate.uuid];
 let matching_name = 'Heart Rate Device';
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-empty-device-from-name-prefix-filter.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-empty-device-from-name-prefix-filter.https.html
new file mode 100644
index 0000000..59bde2d
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-empty-device-from-name-prefix-filter.https.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(t => {
+  return setBluetoothFakeAdapter('EmptyNameHeartRateAdapter')
+      .then(
+          () => promise_rejects_dom(
+              t, 'NotFoundError',
+              requestDeviceWithTrustedClick(
+                  {filters: [{namePrefix: 'a', services: ['heart_rate']}]})));
+}, 'An empty name device is not matched by a filter with a namePrefix.');
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-empty-device-from-name-wrong-filter.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-empty-device-from-name-wrong-filter.https.html
new file mode 100644
index 0000000..3859a17
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-empty-device-from-name-wrong-filter.https.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(t => {
+  return setBluetoothFakeAdapter('EmptyNameHeartRateAdapter')
+      .then(
+          () => promise_rejects_dom(
+              t, 'NotFoundError',
+              requestDeviceWithTrustedClick(
+                  {filters: [{name: 'a', services: ['heart_rate']}]})));
+}, 'An empty name device is not matched by a filter with a name.');
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-empty-device-from-service-filter.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-empty-device-from-service-filter.https.html
new file mode 100644
index 0000000..c8a9328
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-empty-device-from-service-filter.https.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(
+    () => {return setBluetoothFakeAdapter('EmptyNameHeartRateAdapter')
+               .then(
+                   () => requestDeviceWithTrustedClick(
+                       {filters: [{services: ['heart_rate']}]}))
+               .then(device => {
+                 assert_equals(device.name, '');
+               })},
+    'An empty name device can be obtained by advertised service UUID.');
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-empty-filter.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-empty-filter.https.html
new file mode 100644
index 0000000..53041fb
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-empty-filter.https.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(t => {
+  return setBluetoothFakeAdapter('HeartRateAdapter')
+      .then(
+          () => promise_rejects_dom(
+              t, 'NotFoundError',
+              requestDeviceWithTrustedClick(
+                  {filters: [{name: '', services: ['heart_rate']}]})));
+}, 'A named device is not matched by a filter with an empty name.');
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-missing-device-from-name-empty-filter.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-missing-device-from-name-empty-filter.https.html
new file mode 100644
index 0000000..671736a
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-missing-device-from-name-empty-filter.https.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(t => {
+  return setBluetoothFakeAdapter('NoNameHeartRateAdapter')
+      .then(
+          () => promise_rejects_dom(
+              t, 'NotFoundError',
+              requestDeviceWithTrustedClick(
+                  {filters: [{name: '', services: ['heart_rate']}]})));
+}, 'An unnamed device can not be obtained by empty name filter.');
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-missing-device-from-name-prefix-filter.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-missing-device-from-name-prefix-filter.https.html
new file mode 100644
index 0000000..a54c5bad
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-missing-device-from-name-prefix-filter.https.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(t => {
+  return setBluetoothFakeAdapter('NoNameHeartRateAdapter')
+      .then(
+          () => promise_rejects_dom(
+              t, 'NotFoundError',
+              requestDeviceWithTrustedClick(
+                  {filters: [{namePrefix: 'a', services: ['heart_rate']}]})));
+}, 'An unnamed device can not be obtained by namePrefix filter.');
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-missing-device-from-name-wrong-filter.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-missing-device-from-name-wrong-filter.https.html
new file mode 100644
index 0000000..ea5ef51
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-missing-device-from-name-wrong-filter.https.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(t => {
+  return setBluetoothFakeAdapter('NoNameHeartRateAdapter')
+      .then(
+          () => promise_rejects_dom(
+              t, 'NotFoundError',
+              requestDeviceWithTrustedClick(
+                  {filters: [{name: 'a', services: ['heart_rate']}]})));
+}, 'An unnamed device can not be obtained by name filter.');
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-missing-device-from-service-filter.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-missing-device-from-service-filter.https.html
new file mode 100644
index 0000000..8498f38
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/name-missing-device-from-service-filter.https.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(
+    () => {return setBluetoothFakeAdapter('NoNameHeartRateAdapter')
+               .then(
+                   () => requestDeviceWithTrustedClick(
+                       {filters: [{services: ['heart_rate']}]}))
+               .then(device => {
+                 assert_equals(device.name, null);
+               })},
+    'An unnamed device can be obtained by advertised service UUID.');
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/no-devices.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/no-devices.https.html
new file mode 100644
index 0000000..9e8043a
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/no-devices.https.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(() => {
+  return setBluetoothFakeAdapter('EmptyAdapter')
+      .then(
+          () => assert_promise_rejects_with_message(
+              requestDeviceWithTrustedClick(
+                  {filters: [{services: ['generic_access']}]}),
+              new DOMException(
+                  'User cancelled the requestDevice() chooser.',
+                  'NotFoundError'),
+              'No Bluetooth devices in range.'));
+}, 'Reject with NotFoundError if there are no devices around.');
+</script>
diff --git a/third_party/blink/web_tests/bluetooth/requestDevice/radio-off.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/radio-off.https.html
similarity index 61%
rename from third_party/blink/web_tests/bluetooth/requestDevice/radio-off.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/radio-off.https.html
index 4fa6ce0..6a049db 100644
--- a/third_party/blink/web_tests/bluetooth/requestDevice/radio-off.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/radio-off.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
@@ -16,7 +16,7 @@
                   {filters: [{services: ['generic_access']}]}));
   return getBluetoothManualChooserEvents(2).then(events => {
     assert_array_equals(
-        events, ['chooser-opened(file://)', 'adapter-disabled'], events);
+        events, ['chooser-opened(https://web-platform.test:8444)', 'adapter-disabled'], events);
     sendBluetoothManualChooserEvent('cancelled', '');
     return assert_promise_rejects_with_message(
         requestDevicePromise,
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/single-filter-two-services-fails.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/single-filter-two-services-fails.https.html
new file mode 100644
index 0000000..68186931
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/single-filter-two-services-fails.https.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(t => {
+  // Both devices support the Heart Rate service, but things need to
+  // support both services to pass the filter, and neither has a Battery
+  // service.
+  return setBluetoothFakeAdapter('GlucoseHeartRateAdapter')
+      .then(
+          () => promise_rejects_dom(
+              t, 'NotFoundError',
+              requestDeviceWithTrustedClick(
+                  {filters: [{services: ['heart_rate', 'battery_service']}]})));
+}, 'Too-strict filters do prevent matching.');
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/single-filter-two-services-succeeds.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/single-filter-two-services-succeeds.https.html
new file mode 100644
index 0000000..0620918f
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/single-filter-two-services-succeeds.https.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(() => {
+  return setBluetoothFakeAdapter('GlucoseHeartRateAdapter')
+      .then(
+          () => requestDeviceWithTrustedClick(
+              {filters: [{services: ['glucose', 'tx_power']}]}))
+      .then(device => assert_equals(device.name, 'Glucose Device'));
+}, 'Filter with 2 services returns a matching device.');
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/two-filters.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/two-filters.https.html
new file mode 100644
index 0000000..2193e5b
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestDevice/two-filters.https.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(() => {
+  return setBluetoothFakeAdapter('GlucoseHeartRateAdapter')
+      .then(() => requestDeviceWithTrustedClick({
+              filters:
+                  [{services: ['battery_service']}, {services: ['heart_rate']}]
+            }))
+      .then(device => assert_equals(device.name, 'Heart Rate Device'));
+}, 'An extra filter doesn\'t prevent matching.');
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/accept-all-with-filter-throws.https.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/accept-all-with-filter-throws.https.https.html
new file mode 100644
index 0000000..9293717
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/accept-all-with-filter-throws.https.https.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
+<script>
+'use strict';
+const test_desc = 'requestLEScan scan options should have exactly one of ' +
+    '\'filters\' or \'acceptAllAdvertisements:true\'. Reject with TypeError if not.';
+const expected = new DOMException(
+    'Failed to execute \'requestLEScan\' on \'Bluetooth\': ' +
+        'Either \'filters\' should be present or ' +
+        '\'acceptAllAdvertisements\' should be true, but not both.',
+    new TypeError());
+
+bluetooth_test(() => {
+  return assert_promise_rejects_with_message(
+      requestLEScanWithTrustedClick(
+          {filters: [], acceptAllAdvertisements: true}),
+      expected);
+}, test_desc);
+</script>
diff --git a/third_party/blink/web_tests/bluetooth/requestLEScan/attempt-to-connect-after-scan.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/attempt-to-connect-after-scan.https.https.html
similarity index 69%
rename from third_party/blink/web_tests/bluetooth/requestLEScan/attempt-to-connect-after-scan.https.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/attempt-to-connect-after-scan.https.https.html
index 69a3acf..e3d1eeb 100644
--- a/third_party/blink/web_tests/bluetooth/requestLEScan/attempt-to-connect-after-scan.https.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/attempt-to-connect-after-scan.https.https.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
 <script>
 'use strict';
 const test_desc = 'Attempt to connect to scan result.';
diff --git a/third_party/blink/web_tests/bluetooth/requestLEScan/basic-scan.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/basic-scan.https.https.html
similarity index 61%
rename from third_party/blink/web_tests/bluetooth/requestLEScan/basic-scan.https.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/basic-scan.https.https.html
index 137d864..7f57985 100644
--- a/third_party/blink/web_tests/bluetooth/requestLEScan/basic-scan.https.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/basic-scan.https.https.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
 <script>
 'use strict';
 const test_desc = 'requestLEScan receive a scan result.';
diff --git a/third_party/blink/web_tests/bluetooth/requestLEScan/device-ids-match.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/device-ids-match.https.https.html
similarity index 70%
rename from third_party/blink/web_tests/bluetooth/requestLEScan/device-ids-match.https.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/device-ids-match.https.https.html
index 209c6cf..9752172 100644
--- a/third_party/blink/web_tests/bluetooth/requestLEScan/device-ids-match.https.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/device-ids-match.https.https.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
 <script>
 'use strict';
 const test_desc = 'Device address have the same device id.';
diff --git a/third_party/blink/web_tests/bluetooth/requestLEScan/doesnt-consume-user-gesture.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/doesnt-consume-user-gesture.https.https.html
similarity index 70%
rename from third_party/blink/web_tests/bluetooth/requestLEScan/doesnt-consume-user-gesture.https.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/doesnt-consume-user-gesture.https.https.html
index 8b10df3..4c9c351 100644
--- a/third_party/blink/web_tests/bluetooth/requestLEScan/doesnt-consume-user-gesture.https.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/doesnt-consume-user-gesture.https.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc = 'requestLEScan calls do not consume user gestures.';
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/le-not-supported.https.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/le-not-supported.https.https.html
new file mode 100644
index 0000000..3b08458
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/le-not-supported.https.https.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+const test_desc =
+    'requestLEScan reject with NotFoundError if Bluetooth is not supported.';
+const expected =
+    new DOMException('Bluetooth Low Energy not available.', 'NotFoundError');
+
+bluetooth_test(
+    () => navigator.bluetooth.test.setLESupported(false).then(
+        () => assert_promise_rejects_with_message(
+            requestLEScanWithTrustedClick({acceptAllAdvertisements: true}),
+            expected, 'Bluetooth Low Energy is not supported.')),
+    test_desc);
+</script>
diff --git a/third_party/blink/web_tests/bluetooth/requestLEScan/multiple-scan.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/multiple-scan.https.https.html
similarity index 67%
rename from third_party/blink/web_tests/bluetooth/requestLEScan/multiple-scan.https.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/multiple-scan.https.https.html
index f812c4a..ac18b75 100644
--- a/third_party/blink/web_tests/bluetooth/requestLEScan/multiple-scan.https.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/multiple-scan.https.https.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
 <script>
 'use strict';
 const test_desc = 'Multiple requestLEScan receive a scan result.';
diff --git a/third_party/blink/web_tests/bluetooth/requestLEScan/page-visibility.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/page-visibility.https.html
similarity index 65%
rename from third_party/blink/web_tests/bluetooth/requestLEScan/page-visibility.https.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/page-visibility.https.html
index f8a1f8f..265d838 100644
--- a/third_party/blink/web_tests/bluetooth/requestLEScan/page-visibility.https.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/page-visibility.https.html
@@ -1,16 +1,30 @@
 <!doctype html>
 <title>RequestLEScan Visiblility Test</title>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../resources/visibility.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
 <script>
 'use strict';
 
+function setMainWindowHidden(hidden) {
+  return new Promise((resolve, reject) => {
+    if (!window.testRunner) {
+      reject("no window.testRunner present");
+      return;
+    }
+    if (document.visibilityState == (hidden ? "hidden" : "visible")) {
+      reject("setMainWindowHidden(" + hidden + ") called but already " + hidden);
+      return;
+    }
+    document.addEventListener("visibilitychange", resolve, {once:true});
+    testRunner.setMainWindowHidden(hidden);
+  });
+}
+
 let ble_scan;
 bluetooth_test(async (t) => {
   navigator.bluetooth.addEventListener('advertisementreceived', () => {
diff --git a/third_party/blink/web_tests/bluetooth/requestLEScan/radio-not-present.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/radio-not-present.https.https.html
similarity index 60%
rename from third_party/blink/web_tests/bluetooth/requestLEScan/radio-not-present.https.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/radio-not-present.https.https.html
index bad1de56..9795362 100644
--- a/third_party/blink/web_tests/bluetooth/requestLEScan/radio-not-present.https.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/radio-not-present.https.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 const test_desc =
diff --git a/third_party/blink/web_tests/bluetooth/requestLEScan/scan-iframe.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-iframe.https.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/requestLEScan/scan-iframe.https.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-iframe.https.https.html
index 001ced7..13e3866 100644
--- a/third_party/blink/web_tests/bluetooth/requestLEScan/scan-iframe.https.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-iframe.https.https.html
@@ -1,8 +1,8 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <body></body>
 <script>
 'use strict';
diff --git a/third_party/blink/web_tests/bluetooth/requestLEScan/scan-options.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-options.https.https.html
similarity index 84%
rename from third_party/blink/web_tests/bluetooth/requestLEScan/scan-options.https.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-options.https.https.html
index 78a9e77..b35ad5e 100644
--- a/third_party/blink/web_tests/bluetooth/requestLEScan/scan-options.https.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-options.https.https.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
 <script>
 'use strict';
 const test_desc = 'requestLEScan options in scan result.';
diff --git a/third_party/blink/web_tests/bluetooth/requestLEScan/scan-with-multiple-filters.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-with-multiple-filters.https.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/requestLEScan/scan-with-multiple-filters.https.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-with-multiple-filters.https.https.html
index 62dbeca..fe76ead 100644
--- a/third_party/blink/web_tests/bluetooth/requestLEScan/scan-with-multiple-filters.https.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-with-multiple-filters.https.https.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
 <script>
 'use strict';
 const test_desc = 'requestLEScan with multiple filters.';
diff --git a/third_party/blink/web_tests/bluetooth/requestLEScan/scan-with-name-and-uuid-filter.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-with-name-and-uuid-filter.https.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/requestLEScan/scan-with-name-and-uuid-filter.https.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-with-name-and-uuid-filter.https.https.html
index 382f90e..3967079f 100644
--- a/third_party/blink/web_tests/bluetooth/requestLEScan/scan-with-name-and-uuid-filter.https.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-with-name-and-uuid-filter.https.https.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
 <script>
 'use strict';
 const test_desc =
diff --git a/third_party/blink/web_tests/bluetooth/requestLEScan/scan-with-name-filter.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-with-name-filter.https.https.html
similarity index 70%
rename from third_party/blink/web_tests/bluetooth/requestLEScan/scan-with-name-filter.https.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-with-name-filter.https.https.html
index afbbdac..6ce6d7e 100644
--- a/third_party/blink/web_tests/bluetooth/requestLEScan/scan-with-name-filter.https.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-with-name-filter.https.https.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
 <script>
 'use strict';
 const test_desc = 'requestLEScan with name filter.';
diff --git a/third_party/blink/web_tests/bluetooth/requestLEScan/scan-with-name-prefix-filter.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-with-name-prefix-filter.https.https.html
similarity index 70%
rename from third_party/blink/web_tests/bluetooth/requestLEScan/scan-with-name-prefix-filter.https.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-with-name-prefix-filter.https.https.html
index 0171db5..590ed23 100644
--- a/third_party/blink/web_tests/bluetooth/requestLEScan/scan-with-name-prefix-filter.https.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-with-name-prefix-filter.https.https.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
 <script>
 'use strict';
 const test_desc = 'requestLEScan with name prefix filter.';
diff --git a/third_party/blink/web_tests/bluetooth/requestLEScan/scan-with-service-uuid-filter.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-with-service-uuid-filter.https.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/requestLEScan/scan-with-service-uuid-filter.https.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-with-service-uuid-filter.https.https.html
index e3e5130..3e2f5b7 100644
--- a/third_party/blink/web_tests/bluetooth/requestLEScan/scan-with-service-uuid-filter.https.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/requestLEScan/scan-with-service-uuid-filter.https.https.html
@@ -1,11 +1,11 @@
 <!DOCTYPE html>
-<script src="../../resources/testharness.js"></script>
-<script src="../../resources/testharnessreport.js"></script>
-<script src="../../resources/testdriver.js"></script>
-<script src="../../resources/testdriver-vendor.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
-<script src="../../external/wpt/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/bluetooth/resources/bluetooth-scanning-helpers.js"></script>
 <script>
 'use strict';
 const test_desc = 'requestLEScan with uuid filter.';
diff --git a/third_party/blink/web_tests/resources/bluetooth/bluetooth-fake-adapter.js b/third_party/blink/web_tests/wpt_internal/bluetooth/resources/bluetooth-fake-adapter.js
similarity index 100%
rename from third_party/blink/web_tests/resources/bluetooth/bluetooth-fake-adapter.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/resources/bluetooth-fake-adapter.js
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/base_test.html.template b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/base_test.html.template
new file mode 100644
index 0000000..82c9323
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/base_test.html.template
@@ -0,0 +1,11 @@
+<!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+TEST
+</script>
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-blocklisted.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-blocklisted.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-blocklisted.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-blocklisted.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-device-disconnects-before.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-device-disconnects-before.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-device-disconnects-before.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-device-disconnects-before.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-device-disconnects-during-error.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-device-disconnects-during-error.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-device-disconnects-during-error.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-device-disconnects-during-error.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-device-disconnects-during-success.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-device-disconnects-during-success.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-device-disconnects-during-success.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-device-disconnects-during-success.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-disconnect-called-before.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-disconnect-called-before.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-disconnect-called-before.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-disconnect-called-before.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-disconnect-called-during-error.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-disconnect-called-during-error.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-disconnect-called-during-error.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-disconnect-called-during-error.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-disconnect-called-during-success.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-disconnect-called-during-success.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-disconnect-called-during-success.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-disconnect-called-during-success.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-garbage-collection-ran-during-error.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-garbage-collection-ran-during-error.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-garbage-collection-ran-during-error.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-garbage-collection-ran-during-error.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-garbage-collection-ran-during-success.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-garbage-collection-ran-during-success.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-garbage-collection-ran-during-success.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-garbage-collection-ran-during-success.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-invalid-name.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-invalid-name.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/descriptor-invalid-name.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/descriptor-invalid-name.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/device-out-of-range.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/device-out-of-range.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/device-out-of-range.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/device-out-of-range.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-device-disconnects-before.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-device-disconnects-before.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-device-disconnects-before.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-device-disconnects-before.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-device-disconnects-during-error.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-device-disconnects-during-error.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-device-disconnects-during-error.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-device-disconnects-during-error.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-device-disconnects-during-success.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-device-disconnects-during-success.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-device-disconnects-during-success.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-device-disconnects-during-success.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-device-reconnects-during-error.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-device-reconnects-during-error.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-device-reconnects-during-error.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-device-reconnects-during-error.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-device-reconnects-during-success.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-device-reconnects-during-success.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-device-reconnects-during-success.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-device-reconnects-during-success.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-disconnect-called-before.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-disconnect-called-before.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-disconnect-called-before.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-disconnect-called-before.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-disconnect-called-during-error.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-disconnect-called-during-error.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-disconnect-called-during-error.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-disconnect-called-during-error.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-disconnect-called-during-success.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-disconnect-called-during-success.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-disconnect-called-during-success.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-disconnect-called-during-success.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-garbage-collection-ran-during-error.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-garbage-collection-ran-during-error.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-garbage-collection-ran-during-error.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-garbage-collection-ran-during-error.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-garbage-collection-ran-during-success.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-garbage-collection-ran-during-success.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-garbage-collection-ran-during-success.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-garbage-collection-ran-during-success.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-reconnect-during-error.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-reconnect-during-error.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-reconnect-during-error.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-reconnect-during-error.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-reconnect-during-success.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-reconnect-during-success.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/characteristic/gatt-op-reconnect-during-success.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/characteristic/gatt-op-reconnect-during-success.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/descriptor/descriptor-is-removed.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/descriptor-is-removed.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/descriptor/descriptor-is-removed.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/descriptor-is-removed.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/descriptor/device-goes-out-of-range.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/device-goes-out-of-range.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/descriptor/device-goes-out-of-range.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/device-goes-out-of-range.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-device-disconnects-before.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-device-disconnects-before.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-device-disconnects-before.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-device-disconnects-before.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-error.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-error.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-error.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-error.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-success.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-success.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-success.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-device-disconnects-during-success.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-error.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-error.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-error.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-error.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-success.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-success.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-success.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-device-reconnects-during-success.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-disconnect-called-before.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-disconnect-called-before.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-disconnect-called-before.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-disconnect-called-before.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-error.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-error.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-error.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-error.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-success.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-success.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-success.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-disconnect-called-during-success.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-fails.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-fails.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-fails.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-fails.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-error.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-error.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-error.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-error.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-success.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-success.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-success.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-garbage-collection-ran-during-success.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-reconnect-during-error.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-reconnect-during-error.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-reconnect-during-error.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-reconnect-during-error.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-reconnect-during-success.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-reconnect-during-success.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/descriptor/io-op-reconnect-during-success.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/descriptor/io-op-reconnect-during-success.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/server/delayed-discovery-no-permission-present-service.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/delayed-discovery-no-permission-present-service.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/server/delayed-discovery-no-permission-present-service.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/delayed-discovery-no-permission-present-service.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/server/delayed-discovery-service-found.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/delayed-discovery-service-found.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/server/delayed-discovery-service-found.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/delayed-discovery-service-found.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/server/device-disconnects-before.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/device-disconnects-before.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/server/device-disconnects-before.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/device-disconnects-before.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/server/device-disconnects-during-error.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/device-disconnects-during-error.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/server/device-disconnects-during-error.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/device-disconnects-during-error.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/server/device-disconnects-during-success.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/device-disconnects-during-success.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/server/device-disconnects-during-success.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/device-disconnects-during-success.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/server/device-disconnects-during.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/device-disconnects-during.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/server/device-disconnects-during.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/device-disconnects-during.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/server/device-disconnects-invalidates-objects.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/device-disconnects-invalidates-objects.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/server/device-disconnects-invalidates-objects.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/device-disconnects-invalidates-objects.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/server/device-goes-out-of-range.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/device-goes-out-of-range.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/server/device-goes-out-of-range.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/device-goes-out-of-range.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/server/device-reconnects-during-error.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/device-reconnects-during-error.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/server/device-reconnects-during-error.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/device-reconnects-during-error.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/server/device-reconnects-during-success.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/device-reconnects-during-success.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/server/device-reconnects-during-success.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/device-reconnects-during-success.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/server/reconnect-during-error.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/reconnect-during-error.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/server/reconnect-during-error.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/reconnect-during-error.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/server/reconnect-during-success.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/reconnect-during-success.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/server/reconnect-during-success.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/server/reconnect-during-success.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/service/device-disconnects-before.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/service/device-disconnects-before.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/service/device-disconnects-before.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/service/device-disconnects-before.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/service/device-disconnects-during.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/service/device-disconnects-during.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/service/device-disconnects-during.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/service/device-disconnects-during.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/service/device-disconnects-invalidates-objects.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/service/device-disconnects-invalidates-objects.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/service/device-disconnects-invalidates-objects.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/service/device-disconnects-invalidates-objects.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/service/device-goes-out-of-range.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/service/device-goes-out-of-range.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/service/device-goes-out-of-range.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/service/device-goes-out-of-range.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/service/disconnect-called-before.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/service/disconnect-called-before.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/service/disconnect-called-before.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/service/disconnect-called-before.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/service/disconnect-called-during.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/service/disconnect-called-during.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/service/disconnect-called-during.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/service/disconnect-called-during.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/service/disconnect-invalidates-objects.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/service/disconnect-invalidates-objects.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/service/disconnect-invalidates-objects.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/service/disconnect-invalidates-objects.js
diff --git a/third_party/blink/web_tests/bluetooth/script-tests/service/garbage-collection-ran-during-success.js b/third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/service/garbage-collection-ran-during-success.js
similarity index 100%
rename from third_party/blink/web_tests/bluetooth/script-tests/service/garbage-collection-ran-during-success.js
rename to third_party/blink/web_tests/wpt_internal/bluetooth/script-tests/service/garbage-collection-ran-during-success.js
diff --git a/third_party/blink/web_tests/bluetooth/server/connect/connect-disconnected-connect.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/connect/connect-disconnected-connect.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/server/connect/connect-disconnected-connect.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/connect/connect-disconnected-connect.https.html
index b25bb7d..6d75743f 100644
--- a/third_party/blink/web_tests/bluetooth/server/connect/connect-disconnected-connect.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/connect/connect-disconnected-connect.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
  'use strict';
  bluetooth_test(t => {
diff --git a/third_party/blink/web_tests/bluetooth/server/connect/connect-twice.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/connect/connect-twice.https.html
similarity index 69%
rename from third_party/blink/web_tests/bluetooth/server/connect/connect-twice.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/connect/connect-twice.https.html
index 82db5485..42a163e 100644
--- a/third_party/blink/web_tests/bluetooth/server/connect/connect-twice.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/connect/connect-twice.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
  'use strict';
  bluetooth_test(t => {
diff --git a/third_party/blink/web_tests/bluetooth/server/connect/connection-fails.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/connect/connection-fails.https.html
similarity index 85%
rename from third_party/blink/web_tests/bluetooth/server/connect/connection-fails.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/connect/connection-fails.https.html
index aa16642..1ca007f 100644
--- a/third_party/blink/web_tests/bluetooth/server/connect/connection-fails.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/connect/connection-fails.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/server/connect/device-goes-out-of-range.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/connect/device-goes-out-of-range.https.html
new file mode 100644
index 0000000..b69cde6
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/connect/device-goes-out-of-range.https.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(() => {
+  return setBluetoothFakeAdapter('HeartRateAdapter')
+    .then(() => requestDeviceWithTrustedClick({
+      filters: [{services: ['heart_rate']}]}))
+    .then(device => {
+      return setBluetoothFakeAdapter('EmptyAdapter')
+        .then(() => assert_promise_rejects_with_message(
+          device.gatt.connect(),
+          new DOMException('Bluetooth Device is no longer in range.',
+                           'NetworkError'),
+          'Device went out of range.'));
+    });
+}, 'Device goes out of range. Reject with NetworkError.');
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/server/connect/garbage-collection-ran-during-error.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/connect/garbage-collection-ran-during-error.https.html
new file mode 100644
index 0000000..e3092b0
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/connect/garbage-collection-ran-during-error.https.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(t => {
+  return setBluetoothFakeAdapter('FailingConnectionsAdapter')
+    .then(() => requestDeviceWithTrustedClick({
+      filters: [{services: [errorUUID(0x1) /* in progress error */]}]}))
+    .then(device => {
+      promise_rejects_dom(t, 'NetworkError', device.gatt.connect());
+    })
+    .then(runGarbageCollection);
+}, 'Garbage collection ran during a connect call that fails. ' +
+   'Should not crash.');
+</script>
diff --git a/third_party/blink/web_tests/bluetooth/server/connect/same-gatt-server-both-receive-disconnect-event.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/connect/same-gatt-server-both-receive-disconnect-event.https.html
similarity index 67%
rename from third_party/blink/web_tests/bluetooth/server/connect/same-gatt-server-both-receive-disconnect-event.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/connect/same-gatt-server-both-receive-disconnect-event.https.html
index 83528099..3af4f5f 100644
--- a/third_party/blink/web_tests/bluetooth/server/connect/same-gatt-server-both-receive-disconnect-event.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/connect/same-gatt-server-both-receive-disconnect-event.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 var device;
diff --git a/third_party/blink/web_tests/bluetooth/server/disconnect/disconnect-after-request-disconnection.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/disconnect/disconnect-after-request-disconnection.https.html
similarity index 69%
rename from third_party/blink/web_tests/bluetooth/server/disconnect/disconnect-after-request-disconnection.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/disconnect/disconnect-after-request-disconnection.https.html
index 46a9329..dd8f5b7 100644
--- a/third_party/blink/web_tests/bluetooth/server/disconnect/disconnect-after-request-disconnection.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/disconnect/disconnect-after-request-disconnection.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 var device;
diff --git a/third_party/blink/web_tests/bluetooth/server/disconnect/disconnect-fires-event.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/disconnect/disconnect-fires-event.https.html
similarity index 61%
rename from third_party/blink/web_tests/bluetooth/server/disconnect/disconnect-fires-event.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/disconnect/disconnect-fires-event.https.html
index 6b78f36..f8957e3 100644
--- a/third_party/blink/web_tests/bluetooth/server/disconnect/disconnect-fires-event.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/disconnect/disconnect-fires-event.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
  'use strict';
  // TODO(ortuno): Write tests to check that "Disconnect" was actually
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/server/disconnect/disconnect-once.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/disconnect/disconnect-once.https.html
new file mode 100644
index 0000000..0f3001c
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/disconnect/disconnect-once.https.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+// TODO(ortuno): Write tests to check that "Disconnect" was actually
+// called on the device.
+// http://crbug.com/569716
+bluetooth_test(() => {
+  return setBluetoothFakeAdapter('HeartRateAdapter')
+    .then(() => requestDeviceWithTrustedClick({
+      filters: [{services: ['heart_rate']}]}))
+    .then(device => device.gatt.connect())
+    .then(gattServer => {
+      gattServer.disconnect();
+      assert_false(gattServer.connected);
+    });
+}, '\'connected\' is set to false after disconnect is called.');
+</script>
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-delayed-discovery-no-permission-present-service.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-delayed-discovery-no-permission-present-service.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-delayed-discovery-no-permission-present-service.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-delayed-discovery-no-permission-present-service.https.html
index 623eb737..a1b72e3 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-delayed-discovery-no-permission-present-service.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-delayed-discovery-no-permission-present-service.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 let expected = new DOMException('Origin is not allowed to access the ' +
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-delayed-discovery-service-found.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-delayed-discovery-service-found.https.html
similarity index 61%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-delayed-discovery-service-found.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-delayed-discovery-service-found.https.html
index 0d5f936..3445c8f 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-delayed-discovery-service-found.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-delayed-discovery-service-found.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-disconnects-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-disconnects-before.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-disconnects-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-disconnects-before.https.html
index 6f07204..7858958 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-disconnects-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-disconnects-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func) {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-disconnects-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-disconnects-during-error.https.html
similarity index 76%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-disconnects-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-disconnects-during-error.https.html
index 06d6c61..c17fca09 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-disconnects-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-disconnects-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(t => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-disconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-disconnects-during-success.https.html
similarity index 70%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-disconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-disconnects-during-success.https.html
index b7e7e6f..387094e 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-disconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-disconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(t => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-disconnects-during.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-disconnects-during.https.html
similarity index 63%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-disconnects-during.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-disconnects-during.https.html
index d5f8818..fc511511 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-disconnects-during.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-disconnects-during.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-disconnects-invalidates-objects.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-disconnects-invalidates-objects.https.html
similarity index 83%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-disconnects-invalidates-objects.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-disconnects-invalidates-objects.https.html
index 66048589..60ac52d6 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-disconnects-invalidates-objects.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-disconnects-invalidates-objects.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func, uuid) {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-goes-out-of-range.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-goes-out-of-range.https.html
similarity index 63%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-goes-out-of-range.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-goes-out-of-range.https.html
index d9735219..e9cac09 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-goes-out-of-range.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-goes-out-of-range.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-reconnects-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-reconnects-during-error.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-reconnects-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-reconnects-during-error.https.html
index 78b24f9..52bd3b4 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-reconnects-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-reconnects-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-reconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-reconnects-during-success.https.html
similarity index 70%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-reconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-reconnects-during-success.https.html
index 40415c59..cfc07f87 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-device-reconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-device-reconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-reconnect-during-error.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-reconnect-during-error.https.html
similarity index 71%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-reconnect-during-error.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-reconnect-during-error.https.html
index 48240ee6..025722f 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-reconnect-during-error.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-reconnect-during-error.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-reconnect-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-reconnect-during-success.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-reconnect-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-reconnect-during-success.https.html
index bd9059d..8d01caa 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryService/gen-reconnect-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryService/gen-reconnect-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/delayed-discovery-no-permission-present-service.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/delayed-discovery-no-permission-present-service.https.html
new file mode 100644
index 0000000..4750dec
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/delayed-discovery-no-permission-present-service.https.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(() => {
+  return setBluetoothFakeAdapter('DelayedServicesDiscoveryAdapter')
+    .then(() => requestDeviceWithTrustedClick({
+      filters: [{name: 'Heart Rate Device'}],
+      optionalServices: ['battery_service']}))
+    .then(device => device.gatt.connect())
+    .then(gattServer => assert_promise_rejects_with_message(
+      gattServer.getPrimaryServices(),
+      new DOMException('No Services found in device.', 'NotFoundError')));
+}, 'Delayed service discovery, request for present service without permission for that service. Reject with NotFoundError.');
+</script>
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/delayed-discovery-service-not-found.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/delayed-discovery-service-not-found.https.html
new file mode 100644
index 0000000..6153a747
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/delayed-discovery-service-not-found.https.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(() => {
+  return setBluetoothFakeAdapter('DelayedServicesDiscoveryAdapter')
+    .then(() => requestDeviceWithTrustedClick({
+      filters: [{name: 'Heart Rate Device'}],
+      optionalServices: ['battery_service']}))
+    .then(device => device.gatt.connect())
+    .then(gattServer => assert_promise_rejects_with_message(
+      gattServer.getPrimaryServices(),
+      new DOMException('No Services found in device.', 'NotFoundError')));
+}, 'Request for absent service. Must reject with NotFoundError even when the ' +
+   'services are not immediately discovered');
+</script>
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-delayed-discovery-no-permission-present-service-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-delayed-discovery-no-permission-present-service-with-uuid.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-delayed-discovery-no-permission-present-service-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-delayed-discovery-no-permission-present-service-with-uuid.https.html
index 84bf943..71c1a62 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-delayed-discovery-no-permission-present-service-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-delayed-discovery-no-permission-present-service-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 let expected = new DOMException('Origin is not allowed to access the ' +
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-delayed-discovery-service-found-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-delayed-discovery-service-found-with-uuid.https.html
similarity index 61%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-delayed-discovery-service-found-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-delayed-discovery-service-found-with-uuid.https.html
index d666434..06aa7fe 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-delayed-discovery-service-found-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-delayed-discovery-service-found-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-delayed-discovery-service-found.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-delayed-discovery-service-found.https.html
similarity index 60%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-delayed-discovery-service-found.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-delayed-discovery-service-found.https.html
index 4cb7b742..654bf15 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-delayed-discovery-service-found.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-delayed-discovery-service-found.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-before-with-uuid.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-before-with-uuid.https.html
index 1446a82e..9ac8b526 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-before-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func) {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-before.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-before.https.html
index d4688da..3b3b52a 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func) {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-error-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-error-with-uuid.https.html
similarity index 76%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-error-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-error-with-uuid.https.html
index 0dc00795..8f4203a 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-error-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-error-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(t => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-success-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-success-with-uuid.https.html
similarity index 70%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-success-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-success-with-uuid.https.html
index 312d04c5..9d13be0 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-success-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-success-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(t => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-success.https.html
similarity index 70%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-success.https.html
index fbc82475..8a14959c 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(t => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-with-uuid.https.html
similarity index 63%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-with-uuid.https.html
index 6972806..c916bf91 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-during-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-during.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-during.https.html
similarity index 62%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-during.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-during.https.html
index 49daf66..9ad50237d 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-during.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-during.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects-with-uuid.https.html
similarity index 83%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects-with-uuid.https.html
index f009e26..9a580206 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func, uuid) {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects.https.html
similarity index 82%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects.https.html
index cc15473..67ecb54 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-disconnects-invalidates-objects.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func, uuid) {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-goes-out-of-range-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-goes-out-of-range-with-uuid.https.html
similarity index 63%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-goes-out-of-range-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-goes-out-of-range-with-uuid.https.html
index 86c1173..ecee845 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-goes-out-of-range-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-goes-out-of-range-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-goes-out-of-range.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-goes-out-of-range.https.html
similarity index 63%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-goes-out-of-range.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-goes-out-of-range.https.html
index c7711c1..a694d7d 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-goes-out-of-range.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-goes-out-of-range.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-reconnects-during-error-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-reconnects-during-error-with-uuid.https.html
similarity index 73%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-reconnects-during-error-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-reconnects-during-error-with-uuid.https.html
index 2bb134c..79255d0 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-reconnects-during-error-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-reconnects-during-error-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-reconnects-during-success-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-reconnects-during-success-with-uuid.https.html
similarity index 70%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-reconnects-during-success-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-reconnects-during-success-with-uuid.https.html
index b298265..8295e46 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-reconnects-during-success-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-reconnects-during-success-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-reconnects-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-reconnects-during-success.https.html
similarity index 69%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-reconnects-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-reconnects-during-success.https.html
index af590a3a..62f8901 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-device-reconnects-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-device-reconnects-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-reconnect-during-error-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-reconnect-during-error-with-uuid.https.html
similarity index 71%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-reconnect-during-error-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-reconnect-during-error-with-uuid.https.html
index 3ce154f2..db309cd 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-reconnect-during-error-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-reconnect-during-error-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-reconnect-during-success-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-reconnect-during-success-with-uuid.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-reconnect-during-success-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-reconnect-during-success-with-uuid.https.html
index ff76759..1f26ffa 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-reconnect-during-success-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-reconnect-during-success-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-reconnect-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-reconnect-during-success.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-reconnect-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-reconnect-during-success.https.html
index e23ade2..0a6deec 100644
--- a/third_party/blink/web_tests/bluetooth/server/getPrimaryServices/gen-reconnect-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/gen-reconnect-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/no-permission-present-service.https.html b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/no-permission-present-service.https.html
new file mode 100644
index 0000000..387bfeb4
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/server/getPrimaryServices/no-permission-present-service.https.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script>
+'use strict';
+bluetooth_test(() => {
+  return setBluetoothFakeAdapter('HeartRateAdapter')
+    .then(() => requestDeviceWithTrustedClick({
+      filters: [{name: 'Heart Rate Device'}],
+      optionalServices: ['battery_service']}))
+    .then(device => device.gatt.connect())
+    .then(gattServer => assert_promise_rejects_with_message(
+        gattServer.getPrimaryServices(),
+      new DOMException('No Services found in device.', 'NotFoundError')));
+}, 'Request for present service without permission for that service. Reject with NotFoundError.');
+</script>
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-device-disconnects-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-device-disconnects-before.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-device-disconnects-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-device-disconnects-before.https.html
index 98d21e4..018e086 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-device-disconnects-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-device-disconnects-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func) {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-device-disconnects-during.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-device-disconnects-during.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-device-disconnects-during.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-device-disconnects-during.https.html
index eef5d46..9892ba8 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-device-disconnects-during.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-device-disconnects-during.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-device-disconnects-invalidates-objects.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-device-disconnects-invalidates-objects.https.html
similarity index 84%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-device-disconnects-invalidates-objects.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-device-disconnects-invalidates-objects.https.html
index 5e4815a6..cb91f8c 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-device-disconnects-invalidates-objects.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-device-disconnects-invalidates-objects.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func, uuid) {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-device-goes-out-of-range.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-device-goes-out-of-range.https.html
similarity index 67%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-device-goes-out-of-range.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-device-goes-out-of-range.https.html
index cbc8a2cd..9faca03 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-device-goes-out-of-range.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-device-goes-out-of-range.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-disconnect-called-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-disconnect-called-before.https.html
similarity index 71%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-disconnect-called-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-disconnect-called-before.https.html
index c308a577..9f5acc4 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-disconnect-called-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-disconnect-called-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func) {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-disconnect-called-during.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-disconnect-called-during.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-disconnect-called-during.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-disconnect-called-during.https.html
index d50e427..7fbc9f5 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-disconnect-called-during.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-disconnect-called-during.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-disconnect-invalidates-objects.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-disconnect-invalidates-objects.https.html
similarity index 83%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-disconnect-invalidates-objects.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-disconnect-invalidates-objects.https.html
index 7c2e0e1c..e7b1f93d 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-disconnect-invalidates-objects.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-disconnect-invalidates-objects.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func, uuid) {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-garbage-collection-ran-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-garbage-collection-ran-during-success.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-garbage-collection-ran-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-garbage-collection-ran-during-success.https.html
index 49112be..b0d15a8 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristic/gen-garbage-collection-ran-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristic/gen-garbage-collection-ran-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/correct-characteristics.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/correct-characteristics.https.html
similarity index 70%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristics/correct-characteristics.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/correct-characteristics.https.html
index c8f3f9d6..57a2d46c 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/correct-characteristics.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/correct-characteristics.https.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-disconnects-before-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-disconnects-before-with-uuid.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-disconnects-before-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-disconnects-before-with-uuid.https.html
index 7270f03b..49eaade 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-disconnects-before-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-disconnects-before-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func) {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-disconnects-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-disconnects-before.https.html
similarity index 74%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-disconnects-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-disconnects-before.https.html
index 90c284d..27ae34a 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-disconnects-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-disconnects-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func) {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-disconnects-during-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-disconnects-during-with-uuid.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-disconnects-during-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-disconnects-during-with-uuid.https.html
index 042e4f1..872324da 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-disconnects-during-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-disconnects-during-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-disconnects-during.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-disconnects-during.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-disconnects-during.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-disconnects-during.https.html
index 5a32faa..92b0c04 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-disconnects-during.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-disconnects-during.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects-with-uuid.https.html
similarity index 84%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects-with-uuid.https.html
index a9fbf6d..7b372a2 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func, uuid) {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects.https.html
similarity index 84%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects.https.html
index 0ea157d..80a370f 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-disconnects-invalidates-objects.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func, uuid) {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-goes-out-of-range-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-goes-out-of-range-with-uuid.https.html
similarity index 67%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-goes-out-of-range-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-goes-out-of-range-with-uuid.https.html
index d060493..711e726 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-goes-out-of-range-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-goes-out-of-range-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-goes-out-of-range.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-goes-out-of-range.https.html
similarity index 67%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-goes-out-of-range.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-goes-out-of-range.https.html
index edd4b1c9..70553a74 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-device-goes-out-of-range.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-device-goes-out-of-range.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-disconnect-called-before-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-disconnect-called-before-with-uuid.https.html
similarity index 71%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-disconnect-called-before-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-disconnect-called-before-with-uuid.https.html
index 5f5af4c0..ed3b8399 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-disconnect-called-before-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-disconnect-called-before-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func) {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-disconnect-called-before.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-disconnect-called-before.https.html
similarity index 70%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-disconnect-called-before.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-disconnect-called-before.https.html
index 4c109bf8..2d3a9801 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-disconnect-called-before.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-disconnect-called-before.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func) {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-disconnect-called-during-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-disconnect-called-during-with-uuid.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-disconnect-called-during-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-disconnect-called-during-with-uuid.https.html
index 680d54c3..213334230 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-disconnect-called-during-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-disconnect-called-during-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-disconnect-called-during.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-disconnect-called-during.https.html
similarity index 68%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-disconnect-called-during.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-disconnect-called-during.https.html
index cb9f1ca..8aaee48 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-disconnect-called-during.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-disconnect-called-during.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects-with-uuid.https.html
similarity index 83%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects-with-uuid.https.html
index 5ee0cf6..d47e508 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func, uuid) {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects.https.html
similarity index 83%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects.https.html
index 354dde5..46a84ea 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-disconnect-invalidates-objects.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 function createDOMException(func, uuid) {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success-with-uuid.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success-with-uuid.https.html
similarity index 72%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success-with-uuid.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success-with-uuid.https.html
index 2512989..fcf32d47 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success-with-uuid.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success-with-uuid.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success.html b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success.https.html
similarity index 71%
rename from third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success.html
rename to third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success.https.html
index ff45434..f2083e4 100644
--- a/third_party/blink/web_tests/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success.html
+++ b/third_party/blink/web_tests/wpt_internal/bluetooth/service/getCharacteristics/gen-garbage-collection-ran-during-success.https.html
@@ -1,11 +1,11 @@
 <!-- Generated by //third_party/blink/web_tests/bluetooth/generate.py -->
 <!DOCTYPE html>
-<script src="../../../resources/testharness.js"></script>
-<script src="../../../resources/testharnessreport.js"></script>
-<script src="../../../resources/testdriver.js"></script>
-<script src="../../../resources/testdriver-vendor.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-test.js"></script>
-<script src="../../../external/wpt/bluetooth/resources/bluetooth-fake-devices.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/bluetooth/resources/bluetooth-test.js"></script>
+<script src="/bluetooth/resources/bluetooth-fake-devices.js"></script>
 <script>
 'use strict';
 bluetooth_test(() => {
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 22434c3..2781943 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -990,7 +990,6 @@
       'linux-rts': 'release_trybot_rts',
       'linux-trusty-rel': 'gpu_tests_release_trybot_no_symbols_use_dummy_lastchange',
       'linux-viz-rel': 'release_trybot',
-      'linux-warmed': 'release_trybot_no_symbols_use_dummy_lastchange_code_coverage',
       'linux-wpt-fyi-rel': 'release_trybot',
       'linux-wpt-identity-fyi-rel': 'release_trybot',
       'linux-wpt-input-fyi-rel': 'release_trybot',
@@ -2564,11 +2563,6 @@
       'release_trybot', 'disable_nacl',
     ],
 
-    'release_trybot_no_symbols_use_dummy_lastchange_code_coverage': [
-      'release_trybot', 'no_symbols', 'use_dummy_lastchange',
-      'use_clang_coverage', 'partial_code_coverage_instrumentation',
-    ],
-
     'release_trybot_paeverywhere_x86': [
       'release_trybot', 'paeverywhere', 'x86',
     ],
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.linux.json b/tools/mb/mb_config_expectations/tryserver.chromium.linux.json
index b786fde6..26871fdb 100644
--- a/tools/mb/mb_config_expectations/tryserver.chromium.linux.json
+++ b/tools/mb/mb_config_expectations/tryserver.chromium.linux.json
@@ -583,18 +583,6 @@
       "use_goma": true
     }
   },
-  "linux-warmed": {
-    "gn_args": {
-      "coverage_instrumentation_input_file": "//.code-coverage/files_to_instrument.txt",
-      "dcheck_always_on": true,
-      "is_component_build": false,
-      "is_debug": false,
-      "symbol_level": 0,
-      "use_clang_coverage": true,
-      "use_dummy_lastchange": true,
-      "use_goma": true
-    }
-  },
   "linux-webkit-msan-rel": {
     "gn_args": {
       "is_component_build": false,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index d6e2196..59269df 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -11117,192 +11117,6 @@
   <int value="613" label="X_Takri"/>
 </enum>
 
-<enum name="CLD3LanguageCode">
-  <summary>
-    Hash values for the languages supported by CLD3. Each of these values is
-    computed by casting the output of base::HashMetricName(language_string_id)
-    to base::HistogramBase::Sample.
-  </summary>
-  <int value="-2132740958" label="gl"/>
-  <int value="-2112894028" label="haw"/>
-  <int value="-2092490813" label="fa"/>
-  <int value="-2084324285" label="iw"/>
-  <int value="-2070680532" label="hi"/>
-  <int value="-2070250592" label="zu"/>
-  <int value="-2042178987" label="si"/>
-  <int value="-2041104386" label="mi"/>
-  <int value="-2014954614" label="so"/>
-  <int value="-2005166181" label="ja-Latn"/>
-  <int value="-1999171202" label="lv"/>
-  <int value="-1998337622" label="es-CL"/>
-  <int value="-1994870905" label="lt"/>
-  <int value="-1986814580" label="om"/>
-  <int value="-1920649864" label="an"/>
-  <int value="-1898669966" label="zh-CN"/>
-  <int value="-1872667487" label="rm"/>
-  <int value="-1855113037" label="vi"/>
-  <int value="-1828586117" label="de"/>
-  <int value="-1823968882" label="zh"/>
-  <int value="-1797669833" label="it-IT"/>
-  <int value="-1791051166" label="ha"/>
-  <int value="-1787999070" label="wa"/>
-  <int value="-1776903256" label="es-ES"/>
-  <int value="-1767491741" label="es-HN"/>
-  <int value="-1760672594" label="mr"/>
-  <int value="-1741747229" label="es-419"/>
-  <int value="-1735828230" label="zh-TW"/>
-  <int value="-1734070684" label="en-NZ"/>
-  <int value="-1731398502" label="wo"/>
-  <int value="-1696927720" label="la"/>
-  <int value="-1690250140" label="ja"/>
-  <int value="-1683177340" label="qu"/>
-  <int value="-1662603770" label="es-VE"/>
-  <int value="-1625830957" label="ln"/>
-  <int value="-1612285087" label="en-ZA"/>
-  <int value="-1566592213" label="hi-Latn"/>
-  <int value="-1558307126" label="es-CO"/>
-  <int value="-1532548885" label="pa"/>
-  <int value="-1515310228" label="ps"/>
-  <int value="-1453785110" label="rw"/>
-  <int value="-1452189651" label="es-CR"/>
-  <int value="-1346992143" label="nn"/>
-  <int value="-1284862637" label="ru"/>
-  <int value="-1273588087" label="kn"/>
-  <int value="-1242903543" label="es-UY"/>
-  <int value="-1230368678" label="kok"/>
-  <int value="-1211529228" label="gd"/>
-  <int value="-1159958698" label="tl"/>
-  <int value="-1136256351" label="zh-HK"/>
-  <int value="-1117024738" label="zh-Latn"/>
-  <int value="-1100371650" label="sn"/>
-  <int value="-1086322569" label="es-AR"/>
-  <int value="-1052948093" label="jw"/>
-  <int value="-1048980531" label="ur"/>
-  <int value="-1042449480" label="cy"/>
-  <int value="-1033645590" label="fil"/>
-  <int value="-1025520269" label="az"/>
-  <int value="-1010619188" label="ru-Latn"/>
-  <int value="-1000295094" label="no"/>
-  <int value="-950444864" label="tk"/>
-  <int value="-926982267" label="de-AT"/>
-  <int value="-887258309" label="hu"/>
-  <int value="-873154203" label="en-CA"/>
-  <int value="-862298602" label="st"/>
-  <int value="-851607677" label="sm"/>
-  <int value="-846401046" label="chr"/>
-  <int value="-838275151" label="xh"/>
-  <int value="-812926878" label="ug"/>
-  <int value="-780984386" label="fr-CA"/>
-  <int value="-750267977" label="bg"/>
-  <int value="-742603342" label="ca"/>
-  <int value="-740941224" label="ku"/>
-  <int value="-739605699" label="de-LI"/>
-  <int value="-734032818" label="km"/>
-  <int value="-717751759" label="lb"/>
-  <int value="-659007214" label="el"/>
-  <int value="-647197922" label="ceb"/>
-  <int value="-645438410" label="my"/>
-  <int value="-644560085" label="su"/>
-  <int value="-598481752" label="et"/>
-  <int value="-548175087" label="tt"/>
-  <int value="-450972170" label="oc"/>
-  <int value="-442590807" label="sd"/>
-  <int value="-441493751" label="el-Latn"/>
-  <int value="-439564761" label="he"/>
-  <int value="-433923634" label="en-US"/>
-  <int value="-429718906" label="sh"/>
-  <int value="-426630965" label="ga"/>
-  <int value="-415677801" label="it"/>
-  <int value="-403118581" label="sw"/>
-  <int value="-371077109" label="fr-FR"/>
-  <int value="-349113427" label="am"/>
-  <int value="-342591258" label="sq"/>
-  <int value="-302282167" label="ti"/>
-  <int value="-226066958" label="bg-Latn"/>
-  <int value="-219674420" label="ta"/>
-  <int value="-183664425" label="pt-PT"/>
-  <int value="-181870943" label="bn"/>
-  <int value="-110306666" label="sr"/>
-  <int value="-91748674" label="tn"/>
-  <int value="-78164291" label="kk"/>
-  <int value="-74147910" label="en"/>
-  <int value="-35182995" label="fi"/>
-  <int value="-5034744" label="ny"/>
-  <int value="42532257" label="id"/>
-  <int value="64053359" label="eu"/>
-  <int value="114573335" label="es"/>
-  <int value="121688617" label="eo"/>
-  <int value="124739394" label="lo"/>
-  <int value="132594104" label="be"/>
-  <int value="134866094" label="ka"/>
-  <int value="142304335" label="gn"/>
-  <int value="142313505" label="ro"/>
-  <int value="145030010" label="gu"/>
-  <int value="162326141" label="sl"/>
-  <int value="183952636" label="mg"/>
-  <int value="191168946" label="mk"/>
-  <int value="350748440" label="und"/>
-  <int value="357286655" label="af"/>
-  <int value="461111861" label="mt"/>
-  <int value="462869158" label="hy"/>
-  <int value="470982931" label="sv"/>
-  <int value="522435458" label="hr"/>
-  <int value="526531379" label="ml"/>
-  <int value="538270200" label="uk"/>
-  <int value="549800655" label="de-CH"/>
-  <int value="584710092" label="nb"/>
-  <int value="596295208" label="bs"/>
-  <int value="632444664" label="yue-HK"/>
-  <int value="673577439" label="cs"/>
-  <int value="720107264" label="es-PE"/>
-  <int value="729519028" label="or"/>
-  <int value="796588925" label="yo"/>
-  <int value="804120371" label="jv"/>
-  <int value="873647701" label="th"/>
-  <int value="910795716" label="ne"/>
-  <int value="911100675" label="de-DE"/>
-  <int value="925733725" label="ms"/>
-  <int value="1062172280" label="en-IN"/>
-  <int value="1092864716" label="ht"/>
-  <int value="1110169461" label="hmn"/>
-  <int value="1119752109" label="te"/>
-  <int value="1140816756" label="ar"/>
-  <int value="1152813109" label="to"/>
-  <int value="1166708194" label="is"/>
-  <int value="1196096274" label="es-US"/>
-  <int value="1199169847" label="en-AU"/>
-  <int value="1214473765" label="unknown"/>
-  <int value="1228519432" label="fo"/>
-  <int value="1282439493" label="es-MX"/>
-  <int value="1311313702" label="pt"/>
-  <int value="1312638242" label="pl"/>
-  <int value="1437205305" label="uz"/>
-  <int value="1482920614" label="yi"/>
-  <int value="1483760478" label="tg"/>
-  <int value="1552733612" label="da"/>
-  <int value="1628170778" label="pt-BR"/>
-  <int value="1638257274" label="sk"/>
-  <int value="1670494558" label="ko"/>
-  <int value="1704087523" label="ky"/>
-  <int value="1704315002" label="fr"/>
-  <int value="1708437566" label="it-CH"/>
-  <int value="1717583602" label="co"/>
-  <int value="1724977738" label="ia"/>
-  <int value="1754979806" label="fy"/>
-  <int value="1853848431" label="tr"/>
-  <int value="1884922344" label="ckb"/>
-  <int value="1921155040" label="br"/>
-  <int value="1988450082" label="tw"/>
-  <int value="2039992295" label="ig"/>
-  <int value="2077417554" label="fr-CH"/>
-  <int value="2078974161" label="ast"/>
-  <int value="2087142539" label="mn"/>
-  <int value="2094171128" label="mo"/>
-  <int value="2098003573" label="as"/>
-  <int value="2119087611" label="nl"/>
-  <int value="2147270293" label="en-GB"/>
-</enum>
-
 <enum name="ClearBrowsingDataTab">
   <int value="0" label="Basic"/>
   <int value="1" label="Advanced"/>
@@ -30444,7 +30258,7 @@
   <int value="3353"
       label="CrossBrowsingContextGroupMainFrameNulledNonEmptyNameAccessed"/>
   <int value="3354" label="PositionSticky"/>
-  <int value="3355" label="CommaSeparatorInAllowAttribute"/>
+  <int value="3355" label="OBSOLETE_CommaSeparatorInAllowAttribute"/>
   <int value="3359" label="MainFrameCSPViaHTTP"/>
   <int value="3360" label="MainFrameCSPViaMeta"/>
   <int value="3361" label="MainFrameCSPViaOriginPolicy"/>
@@ -40504,8 +40318,12 @@
   <int value="2" label="ARC not available"/>
 </enum>
 
-<enum name="LanguageCode">
-  <summary>ISO 639 Language Codes.</summary>
+<enum name="LanguageName">
+  <summary>
+    Hash values for the first two letters of a locale code. This is mapped to
+    the English name for each language. Only the first two letters are used so
+    country and script codes are ignored /.
+  </summary>
   <int value="24929" label="Afar"/>
   <int value="24930" label="Abkhazian"/>
   <int value="24933" label="Avestan"/>
@@ -41093,6 +40911,8 @@
 
 <enum name="LaunchCause">
   <int value="0" label="Other"/>
+  <int value="1" label="Chrome Custom Tab"/>
+  <int value="2" label="Trusted Web Activity"/>
 </enum>
 
 <enum name="LauncherRankingItemType">
@@ -42006,6 +41826,192 @@
   <int value="3" label="Main dialog accepted"/>
 </enum>
 
+<enum name="LocaleCodeISO639">
+  <summary>
+    Hash values for ISO 639 locale codes (including country and script tags).
+    Each of these values is computed by casting the output of
+    base::HashMetricName(locale_string_id) to base::HistogramBase::Sample.
+  </summary>
+  <int value="-2132740958" label="gl"/>
+  <int value="-2112894028" label="haw"/>
+  <int value="-2092490813" label="fa"/>
+  <int value="-2084324285" label="iw"/>
+  <int value="-2070680532" label="hi"/>
+  <int value="-2070250592" label="zu"/>
+  <int value="-2042178987" label="si"/>
+  <int value="-2041104386" label="mi"/>
+  <int value="-2014954614" label="so"/>
+  <int value="-2005166181" label="ja-Latn"/>
+  <int value="-1999171202" label="lv"/>
+  <int value="-1998337622" label="es-CL"/>
+  <int value="-1994870905" label="lt"/>
+  <int value="-1986814580" label="om"/>
+  <int value="-1920649864" label="an"/>
+  <int value="-1898669966" label="zh-CN"/>
+  <int value="-1872667487" label="rm"/>
+  <int value="-1855113037" label="vi"/>
+  <int value="-1828586117" label="de"/>
+  <int value="-1823968882" label="zh"/>
+  <int value="-1797669833" label="it-IT"/>
+  <int value="-1791051166" label="ha"/>
+  <int value="-1787999070" label="wa"/>
+  <int value="-1776903256" label="es-ES"/>
+  <int value="-1767491741" label="es-HN"/>
+  <int value="-1760672594" label="mr"/>
+  <int value="-1741747229" label="es-419"/>
+  <int value="-1735828230" label="zh-TW"/>
+  <int value="-1734070684" label="en-NZ"/>
+  <int value="-1731398502" label="wo"/>
+  <int value="-1696927720" label="la"/>
+  <int value="-1690250140" label="ja"/>
+  <int value="-1683177340" label="qu"/>
+  <int value="-1662603770" label="es-VE"/>
+  <int value="-1625830957" label="ln"/>
+  <int value="-1612285087" label="en-ZA"/>
+  <int value="-1566592213" label="hi-Latn"/>
+  <int value="-1558307126" label="es-CO"/>
+  <int value="-1532548885" label="pa"/>
+  <int value="-1515310228" label="ps"/>
+  <int value="-1453785110" label="rw"/>
+  <int value="-1452189651" label="es-CR"/>
+  <int value="-1346992143" label="nn"/>
+  <int value="-1284862637" label="ru"/>
+  <int value="-1273588087" label="kn"/>
+  <int value="-1242903543" label="es-UY"/>
+  <int value="-1230368678" label="kok"/>
+  <int value="-1211529228" label="gd"/>
+  <int value="-1159958698" label="tl"/>
+  <int value="-1136256351" label="zh-HK"/>
+  <int value="-1117024738" label="zh-Latn"/>
+  <int value="-1100371650" label="sn"/>
+  <int value="-1086322569" label="es-AR"/>
+  <int value="-1052948093" label="jw"/>
+  <int value="-1048980531" label="ur"/>
+  <int value="-1042449480" label="cy"/>
+  <int value="-1033645590" label="fil"/>
+  <int value="-1025520269" label="az"/>
+  <int value="-1010619188" label="ru-Latn"/>
+  <int value="-1000295094" label="no"/>
+  <int value="-950444864" label="tk"/>
+  <int value="-926982267" label="de-AT"/>
+  <int value="-887258309" label="hu"/>
+  <int value="-873154203" label="en-CA"/>
+  <int value="-862298602" label="st"/>
+  <int value="-851607677" label="sm"/>
+  <int value="-846401046" label="chr"/>
+  <int value="-838275151" label="xh"/>
+  <int value="-812926878" label="ug"/>
+  <int value="-780984386" label="fr-CA"/>
+  <int value="-750267977" label="bg"/>
+  <int value="-742603342" label="ca"/>
+  <int value="-740941224" label="ku"/>
+  <int value="-739605699" label="de-LI"/>
+  <int value="-734032818" label="km"/>
+  <int value="-717751759" label="lb"/>
+  <int value="-659007214" label="el"/>
+  <int value="-647197922" label="ceb"/>
+  <int value="-645438410" label="my"/>
+  <int value="-644560085" label="su"/>
+  <int value="-598481752" label="et"/>
+  <int value="-548175087" label="tt"/>
+  <int value="-450972170" label="oc"/>
+  <int value="-442590807" label="sd"/>
+  <int value="-441493751" label="el-Latn"/>
+  <int value="-439564761" label="he"/>
+  <int value="-433923634" label="en-US"/>
+  <int value="-429718906" label="sh"/>
+  <int value="-426630965" label="ga"/>
+  <int value="-415677801" label="it"/>
+  <int value="-403118581" label="sw"/>
+  <int value="-371077109" label="fr-FR"/>
+  <int value="-349113427" label="am"/>
+  <int value="-342591258" label="sq"/>
+  <int value="-302282167" label="ti"/>
+  <int value="-226066958" label="bg-Latn"/>
+  <int value="-219674420" label="ta"/>
+  <int value="-183664425" label="pt-PT"/>
+  <int value="-181870943" label="bn"/>
+  <int value="-110306666" label="sr"/>
+  <int value="-91748674" label="tn"/>
+  <int value="-78164291" label="kk"/>
+  <int value="-74147910" label="en"/>
+  <int value="-35182995" label="fi"/>
+  <int value="-5034744" label="ny"/>
+  <int value="42532257" label="id"/>
+  <int value="64053359" label="eu"/>
+  <int value="114573335" label="es"/>
+  <int value="121688617" label="eo"/>
+  <int value="124739394" label="lo"/>
+  <int value="132594104" label="be"/>
+  <int value="134866094" label="ka"/>
+  <int value="142304335" label="gn"/>
+  <int value="142313505" label="ro"/>
+  <int value="145030010" label="gu"/>
+  <int value="162326141" label="sl"/>
+  <int value="183952636" label="mg"/>
+  <int value="191168946" label="mk"/>
+  <int value="350748440" label="und"/>
+  <int value="357286655" label="af"/>
+  <int value="461111861" label="mt"/>
+  <int value="462869158" label="hy"/>
+  <int value="470982931" label="sv"/>
+  <int value="522435458" label="hr"/>
+  <int value="526531379" label="ml"/>
+  <int value="538270200" label="uk"/>
+  <int value="549800655" label="de-CH"/>
+  <int value="584710092" label="nb"/>
+  <int value="596295208" label="bs"/>
+  <int value="632444664" label="yue-HK"/>
+  <int value="673577439" label="cs"/>
+  <int value="720107264" label="es-PE"/>
+  <int value="729519028" label="or"/>
+  <int value="796588925" label="yo"/>
+  <int value="804120371" label="jv"/>
+  <int value="873647701" label="th"/>
+  <int value="910795716" label="ne"/>
+  <int value="911100675" label="de-DE"/>
+  <int value="925733725" label="ms"/>
+  <int value="1062172280" label="en-IN"/>
+  <int value="1092864716" label="ht"/>
+  <int value="1110169461" label="hmn"/>
+  <int value="1119752109" label="te"/>
+  <int value="1140816756" label="ar"/>
+  <int value="1152813109" label="to"/>
+  <int value="1166708194" label="is"/>
+  <int value="1196096274" label="es-US"/>
+  <int value="1199169847" label="en-AU"/>
+  <int value="1214473765" label="unknown"/>
+  <int value="1228519432" label="fo"/>
+  <int value="1282439493" label="es-MX"/>
+  <int value="1311313702" label="pt"/>
+  <int value="1312638242" label="pl"/>
+  <int value="1437205305" label="uz"/>
+  <int value="1482920614" label="yi"/>
+  <int value="1483760478" label="tg"/>
+  <int value="1552733612" label="da"/>
+  <int value="1628170778" label="pt-BR"/>
+  <int value="1638257274" label="sk"/>
+  <int value="1670494558" label="ko"/>
+  <int value="1704087523" label="ky"/>
+  <int value="1704315002" label="fr"/>
+  <int value="1708437566" label="it-CH"/>
+  <int value="1717583602" label="co"/>
+  <int value="1724977738" label="ia"/>
+  <int value="1754979806" label="fy"/>
+  <int value="1853848431" label="tr"/>
+  <int value="1884922344" label="ckb"/>
+  <int value="1921155040" label="br"/>
+  <int value="1988450082" label="tw"/>
+  <int value="2039992295" label="ig"/>
+  <int value="2077417554" label="fr-CH"/>
+  <int value="2078974161" label="ast"/>
+  <int value="2087142539" label="mn"/>
+  <int value="2094171128" label="mo"/>
+  <int value="2098003573" label="as"/>
+  <int value="2119087611" label="nl"/>
+  <int value="2147270293" label="en-GB"/>
+</enum>
+
 <enum name="LocalFrameRootPurgeSignal">
   <int value="0" label="Initial"/>
   <int value="1" label="Multiple"/>
@@ -42733,6 +42739,7 @@
   <int value="-1669486359" label="ImportantSitesInCBD:enabled"/>
   <int value="-1668306615" label="CrostiniUseDlc:enabled"/>
   <int value="-1667822423" label="ContextMenuGoogleLensChip:disabled"/>
+  <int value="-1666652919" label="MagnifierPanningImprovements:disabled"/>
   <int value="-1665720309"
       label="ArcNativeBridge64BitSupportExperiment:disabled"/>
   <int value="-1664795930" label="StorageAccessAPI:disabled"/>
@@ -45421,6 +45428,7 @@
   <int value="855746780" label="disable-physical-keyboard-autocorrect"/>
   <int value="857391671" label="BluetoothNextHandsfreeProfile:disabled"/>
   <int value="857445869" label="enable-captive-portal-bypass-proxy"/>
+  <int value="859449217" label="MagnifierPanningImprovements:enabled"/>
   <int value="860336036" label="ChromeModernDesign:enabled"/>
   <int value="862453793" label="TranslateUI2016Q2:enabled"/>
   <int value="864024033" label="IsolatePrerendersMustProbeOrigin:enabled"/>
diff --git a/tools/metrics/histograms/histograms_xml/accessibility/histograms.xml b/tools/metrics/histograms/histograms_xml/accessibility/histograms.xml
index 7e0f4d0..6ffc298 100644
--- a/tools/metrics/histograms/histograms_xml/accessibility/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/accessibility/histograms.xml
@@ -215,7 +215,7 @@
 </histogram>
 
 <histogram name="Accessibility.CrosCursorHighlight" enum="BooleanEnabled"
-    expires_after="2021-04-04">
+    expires_after="2021-07-11">
   <owner>dmazzoni@chromium.org</owner>
   <owner>chrome-a11y-core@google.com</owner>
   <summary>
@@ -470,7 +470,7 @@
   </summary>
 </histogram>
 
-<histogram name="Accessibility.ImageLabels.PageLanguage" enum="LanguageCode"
+<histogram name="Accessibility.ImageLabels.PageLanguage" enum="LanguageName"
     expires_after="2021-05-16">
   <owner>katie@chromium.org</owner>
   <owner>dmazzoni@chromium.org</owner>
@@ -481,7 +481,7 @@
   </summary>
 </histogram>
 
-<histogram name="Accessibility.ImageLabels.RequestLanguage" enum="LanguageCode"
+<histogram name="Accessibility.ImageLabels.RequestLanguage" enum="LanguageName"
     expires_after="2021-03-28">
   <owner>katie@chromium.org</owner>
   <owner>dmazzoni@chromium.org</owner>
@@ -602,7 +602,7 @@
 </histogram>
 
 <histogram name="Accessibility.LiveCaption.Duration.CaptionBubbleHidden"
-    units="ms" expires_after="2021-04-30">
+    units="ms" expires_after="2021-07-11">
   <owner>abigailbklein@google.com</owner>
   <owner>evliu@google.com</owner>
   <owner>chrome-a11y-core@google.com</owner>
diff --git a/tools/metrics/histograms/histograms_xml/android/histograms.xml b/tools/metrics/histograms/histograms_xml/android/histograms.xml
index 89fc3e4..31fae64 100644
--- a/tools/metrics/histograms/histograms_xml/android/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/android/histograms.xml
@@ -241,7 +241,7 @@
 </histogram>
 
 <histogram name="Android.BackgroundTaskScheduler.TaskStarted"
-    enum="BackgroundTaskId" expires_after="2021-04-04">
+    enum="BackgroundTaskId" expires_after="2021-07-11">
   <owner>fgorski@chromium.org</owner>
   <owner>nyquist@chromium.org</owner>
   <summary>Records that a specific background task has been started.</summary>
@@ -364,6 +364,9 @@
 
 <histogram name="Android.CompressedResources.ExtractionBlockingTime" units="ms"
     expires_after="M82">
+  <obsolete>
+    Removed in M82.
+  </obsolete>
   <owner>estevenson@chromium.org</owner>
   <owner>agrieve@chromium.org</owner>
   <summary>
@@ -375,6 +378,9 @@
 
 <histogram name="Android.CompressedResources.ExtractionStatus"
     enum="AndroidResourceExtractionStatus" expires_after="2021-01-24">
+  <obsolete>
+    Removed in M82.
+  </obsolete>
   <owner>estevenson@chromium.org</owner>
   <owner>agrieve@chromium.org</owner>
   <summary>
@@ -385,6 +391,9 @@
 
 <histogram name="Android.CompressedResources.ExtractionTime" units="ms"
     expires_after="2021-01-24">
+  <obsolete>
+    Removed in M82.
+  </obsolete>
   <owner>estevenson@chromium.org</owner>
   <owner>agrieve@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/arc/histograms.xml b/tools/metrics/histograms/histograms_xml/arc/histograms.xml
index a2ec9c1..b33d452f 100644
--- a/tools/metrics/histograms/histograms_xml/arc/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/arc/histograms.xml
@@ -730,7 +730,7 @@
 </histogram>
 
 <histogram name="Arc.PlayAutoInstallRequest.TimeDelta" units="ms"
-    expires_after="2021-03-11">
+    expires_after="2021-07-11">
 <!-- Name completed by histogram_suffixes name="ArcUserTypes" -->
 
   <owner>jhorwich@google.com</owner>
@@ -1085,7 +1085,7 @@
   </summary>
 </histogram>
 
-<histogram name="Arc.State" enum="BooleanEnabled" expires_after="2021-05-09">
+<histogram name="Arc.State" enum="BooleanEnabled" expires_after="2021-07-11">
   <owner>elijahtaylor@google.com</owner>
   <owner>ttylenda@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/ash/histograms.xml b/tools/metrics/histograms/histograms_xml/ash/histograms.xml
index 21178092..a36e572 100644
--- a/tools/metrics/histograms/histograms_xml/ash/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/ash/histograms.xml
@@ -1213,7 +1213,7 @@
 </histogram>
 
 <histogram name="Ash.NightLight.ScheduleType" enum="AshNightLightScheduleType"
-    expires_after="2021-04-11">
+    expires_after="2021-07-11">
   <owner>afakhry@chromium.org</owner>
   <summary>
     The selected Night Light schedule type. Emitted when the user changes the
diff --git a/tools/metrics/histograms/histograms_xml/assistant/histograms.xml b/tools/metrics/histograms/histograms_xml/assistant/histograms.xml
index 38cab12..50e68e2 100644
--- a/tools/metrics/histograms/histograms_xml/assistant/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/assistant/histograms.xml
@@ -233,7 +233,7 @@
 </histogram>
 
 <histogram name="QuickAnswers.ActiveImpression.Duration" units="ms"
-    expires_after="2021-04-25">
+    expires_after="2021-07-11">
   <owner>llin@google.com</owner>
   <owner>croissant-eng@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/autofill/histograms.xml b/tools/metrics/histograms/histograms_xml/autofill/histograms.xml
index 3fe54b4..b158f780 100644
--- a/tools/metrics/histograms/histograms_xml/autofill/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/autofill/histograms.xml
@@ -1751,15 +1751,15 @@
   </summary>
 </histogram>
 
-<histogram name="Autofill.TranslatedPageLanguage" enum="LanguageCode"
+<histogram name="Autofill.TranslatedPageLanguage" enum="LanguageName"
     expires_after="2021-10-25">
   <owner>marsin@google.com</owner>
   <owner>koerber@google.com</owner>
   <summary>
     The visible page language (best guess of the original or the translated
     language, if translation was used) upon form submission. This is a sparse
-    histogram where the integer value represents the language code as described
-    by the ISO 639 standard.
+    histogram where the integer value represents the first two letters of the
+    language code and mapped to English language names.
   </summary>
 </histogram>
 
diff --git a/tools/metrics/histograms/histograms_xml/background/histograms.xml b/tools/metrics/histograms/histograms_xml/background/histograms.xml
index 83c2f67d..b1e080c 100644
--- a/tools/metrics/histograms/histograms_xml/background/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/background/histograms.xml
@@ -160,7 +160,7 @@
 </histogram>
 
 <histogram name="BackgroundMode.BackgroundApplicationsCount" units="units"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>atwilson@chromium.org</owner>
   <owner>mvanouwerkerk@chromium.org</owner>
   <summary>
@@ -360,7 +360,7 @@
 
 <histogram
     name="BackgroundSync.Registration.OneShot.EventSucceededAtCompletion"
-    enum="BooleanSuccess" expires_after="2021-05-09">
+    enum="BooleanSuccess" expires_after="2021-07-11">
   <owner>nator@chromium.org</owner>
   <owner>rayankans@chromium.org</owner>
   <owner>peter@chromium.org</owner>
@@ -382,7 +382,7 @@
 
 <histogram
     name="BackgroundSync.Registration.OneShot.NumAttemptsForSuccessfulEvent"
-    units="attempts" expires_after="2021-05-09">
+    units="attempts" expires_after="2021-07-11">
   <owner>nator@chromium.org</owner>
   <owner>rayankans@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/blink/histograms.xml b/tools/metrics/histograms/histograms_xml/blink/histograms.xml
index cb2e1243..8b5d95e 100644
--- a/tools/metrics/histograms/histograms_xml/blink/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/blink/histograms.xml
@@ -172,12 +172,16 @@
 </histogram>
 
 <histogram name="Blink.Canvas.IsComposited" enum="Boolean"
-    expires_after="2022-04-04">
+    expires_after="2021-01-31">
   <owner>aaronhk@chromium.org</owner>
   <owner>fserb@chromium.org</owner>
   <summary>
     Records if the canvas context is composited or not. Recorded in
     HTMLCanvasElement::GetCanvasRenderingContext.
+
+    Note: This has been recording bad data since at least 2020-01-01. It was
+    emitted in the wrong place and always recording false. Since it records the
+    same information as IsAccelerated, I am just going to let it expire.
   </summary>
 </histogram>
 
@@ -1035,7 +1039,7 @@
 </histogram>
 
 <histogram base="true" name="Blink.ImageDecoders.IncrementallyDecodedByteSize"
-    units="bytes" expires_after="2021-05-09">
+    units="bytes" expires_after="2021-07-11">
   <owner>mbarowsky@chromium.org</owner>
   <owner>andrescj@chromium.org</owner>
   <summary>
@@ -1645,7 +1649,7 @@
 </histogram>
 
 <histogram name="Blink.OffscreenCanvas.NewOffscreenCanvas" enum="Boolean"
-    expires_after="2021-01-31">
+    expires_after="2022-04-04">
   <owner>aaronhk@chromium.org</owner>
   <owner>fserb@chromium.org</owner>
   <summary>
@@ -1671,7 +1675,7 @@
 </histogram>
 
 <histogram name="Blink.OffscreenCanvas.Transferred" enum="Boolean"
-    expires_after="2021-01-31">
+    expires_after="2022-04-04">
   <owner>aaronhk@chromium.org</owner>
   <owner>fserb@chromium.org</owner>
   <summary>
@@ -1837,7 +1841,7 @@
 </histogram>
 
 <histogram name="Blink.Script.SchedulingType" enum="ScriptSchedulingType"
-    expires_after="2021-05-02">
+    expires_after="2021-07-11">
   <owner>kouhei@chromium.org</owner>
   <owner>hiroshige@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/bluetooth/histograms.xml b/tools/metrics/histograms/histograms_xml/bluetooth/histograms.xml
index c3611e7..247a320 100644
--- a/tools/metrics/histograms/histograms_xml/bluetooth/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/bluetooth/histograms.xml
@@ -104,7 +104,7 @@
 </histogram>
 
 <histogram name="Bluetooth.ChromeOS.Pairing.Result" enum="BooleanSuccess"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
 <!-- Name completed by histogram_suffixes name="BluetoothTransportTypes" -->
 
   <owner>hansberry@chromium.org</owner>
@@ -121,7 +121,7 @@
 </histogram>
 
 <histogram name="Bluetooth.ChromeOS.Pairing.Result.FailureReason"
-    enum="BluetoothConnectionFailureReason" expires_after="2021-03-05">
+    enum="BluetoothConnectionFailureReason" expires_after="2021-07-11">
 <!-- Name completed by histogram_suffixes name="BluetoothTransportTypes" -->
 
   <owner>hansberry@chromium.org</owner>
@@ -148,7 +148,7 @@
 </histogram>
 
 <histogram name="Bluetooth.ChromeOS.UserInitiatedReconnectionAttempt.Result"
-    enum="BooleanSuccess" expires_after="2021-05-09">
+    enum="BooleanSuccess" expires_after="2021-07-11">
 <!-- Name completed by histogram_suffixes name="BluetoothUISurfaces" -->
 
   <owner>hansberry@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/browser/histograms.xml b/tools/metrics/histograms/histograms_xml/browser/histograms.xml
index 901e137..565ddc0 100644
--- a/tools/metrics/histograms/histograms_xml/browser/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/browser/histograms.xml
@@ -398,7 +398,7 @@
 </histogram>
 
 <histogram base="true" name="Browser.Tabs.TabSwitchResult"
-    enum="TabSwitchResult" expires_after="2021-05-09">
+    enum="TabSwitchResult" expires_after="2021-07-11">
 <!-- Name completed by histogram_suffixes name="TabSwitchingType" -->
 
   <owner>fdoray@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/chromeos/histograms.xml b/tools/metrics/histograms/histograms_xml/chromeos/histograms.xml
index c46e9d6..bb22df5 100644
--- a/tools/metrics/histograms/histograms_xml/chromeos/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/chromeos/histograms.xml
@@ -607,7 +607,7 @@
 </histogram>
 
 <histogram name="ChromeOS.SAML.InSessionPasswordChangeEvent"
-    enum="SamlInSessionPasswordChangeEvent" expires_after="2021-04-30">
+    enum="SamlInSessionPasswordChangeEvent" expires_after="2021-07-11">
   <owner>mslus@chromium.org</owner>
   <owner>rsorokin@chromium.org</owner>
   <summary>
@@ -1079,7 +1079,7 @@
 </histogram>
 
 <histogram name="ChromeOS.SystemTray.FeaturePodCountOnOpen" units="count"
-    expires_after="2021-04-11">
+    expires_after="2021-07-11">
   <owner>tengs@chromium.org</owner>
   <owner>amehfooz@chromium.org</owner>
   <summary>
@@ -1125,7 +1125,7 @@
 </histogram>
 
 <histogram name="ChromeOS.SystemTray.NotificationsRemovedByClearAll"
-    units="notifications" expires_after="2021-05-10">
+    units="notifications" expires_after="2021-07-11">
   <owner>tengs@chromium.org</owner>
   <owner>gzadina@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/content/histograms.xml b/tools/metrics/histograms/histograms_xml/content/histograms.xml
index 75db8c7e..4a9a67a 100644
--- a/tools/metrics/histograms/histograms_xml/content/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/content/histograms.xml
@@ -835,7 +835,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.LoadStreamStatus.InitialFromStore"
-    enum="FeedLoadStreamStatus" expires_after="2021-05-01">
+    enum="FeedLoadStreamStatus" expires_after="2021-07-11">
   <owner>harringtond@chromium.org</owner>
   <owner>carlosk@chromium.org</owner>
   <owner>feed@chromium.org</owner>
@@ -961,7 +961,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.NoticeCardFulfilled" enum="Boolean"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>vincb@google.com</owner>
   <owner>feed@chromium.org</owner>
   <summary>
@@ -1259,7 +1259,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.UserJourney.GetMore.FailureDuration"
-    units="ms" expires_after="2021-05-01">
+    units="ms" expires_after="2021-07-11">
   <owner>harringtond@chromium.org</owner>
   <owner>carlosk@chromium.org</owner>
   <owner>feed@chromium.org</owner>
@@ -1270,7 +1270,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.UserJourney.GetMore.SuccessDuration"
-    units="ms" expires_after="2021-05-01">
+    units="ms" expires_after="2021-07-11">
   <owner>harringtond@chromium.org</owner>
   <owner>carlosk@chromium.org</owner>
   <owner>feed@chromium.org</owner>
@@ -1303,7 +1303,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.UserJourney.OpenFeed.FailureDuration"
-    units="ms" expires_after="2021-05-01">
+    units="ms" expires_after="2021-07-11">
   <owner>harringtond@chromium.org</owner>
   <owner>carlosk@chromium.org</owner>
   <owner>feed@chromium.org</owner>
@@ -1315,7 +1315,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.UserJourney.OpenFeed.SuccessDuration"
-    units="ms" expires_after="2021-05-01">
+    units="ms" expires_after="2021-07-11">
   <owner>harringtond@chromium.org</owner>
   <owner>carlosk@chromium.org</owner>
   <owner>feed@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/cros/histograms.xml b/tools/metrics/histograms/histograms_xml/cros/histograms.xml
index 69b0c04..4fd7ba825 100644
--- a/tools/metrics/histograms/histograms_xml/cros/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/cros/histograms.xml
@@ -84,7 +84,7 @@
 </histogram>
 
 <histogram name="CrosDisksClient.FormatCompletedError"
-    enum="CrosDisksClientFormatError" expires_after="2021-05-09">
+    enum="CrosDisksClientFormatError" expires_after="2021-07-11">
   <owner>austinct@chromium.org</owner>
   <summary>
     The error code of disk format signals received from the Chrome OS cros-disks
diff --git a/tools/metrics/histograms/histograms_xml/download/histograms.xml b/tools/metrics/histograms/histograms_xml/download/histograms.xml
index b29705e..4fee8d6 100644
--- a/tools/metrics/histograms/histograms_xml/download/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/download/histograms.xml
@@ -69,7 +69,7 @@
 </histogram>
 
 <histogram name="Download.ContentType.Text" enum="DownloadTextType"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>xingliu@chromium.org</owner>
   <summary>Types of text files that are downloaded.</summary>
 </histogram>
@@ -83,7 +83,7 @@
 </histogram>
 
 <histogram base="true" name="Download.Counts" enum="DownloadCountType"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
 <!-- Name completed by histogram_suffixes name="DownloadSource" -->
 
   <owner>xingliu@chromium.org</owner>
@@ -279,7 +279,7 @@
 </histogram>
 
 <histogram name="Download.IOSDownloadedFileAction" enum="DownloadedFileAction"
-    expires_after="2021-05-08">
+    expires_after="2021-07-11">
   <owner>eugenebut@chromium.org</owner>
   <owner>ewannpv@chromium.com</owner>
   <summary>
@@ -368,7 +368,7 @@
 </histogram>
 
 <histogram name="Download.IOSDownloadReplaced" enum="BooleanReplaced"
-    expires_after="2021-01-15">
+    expires_after="2021-07-15">
   <owner>eugenebut@chromium.org</owner>
   <owner>sdefresne@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/event/histograms.xml b/tools/metrics/histograms/histograms_xml/event/histograms.xml
index 51fec7b..03f4b86a 100644
--- a/tools/metrics/histograms/histograms_xml/event/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/event/histograms.xml
@@ -281,7 +281,7 @@
 </histogram>
 
 <histogram name="Event.Latency.EndToEnd.KeyPress" units="microseconds"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>flackr@chromium.org</owner>
   <owner>input-dev@chromium.org</owner>
   <summary>
@@ -573,7 +573,7 @@
 </histogram>
 
 <histogram name="Event.Latency.ScrollBegin.TimeToScrollUpdateSwapBegin2"
-    units="microseconds" expires_after="2021-05-09">
+    units="microseconds" expires_after="2021-07-11">
   <owner>nzolghadr@chromium.org</owner>
   <summary>
     Time between initial creation of a wheel/touch event and start of the frame
@@ -1650,7 +1650,7 @@
 </histogram>
 
 <histogram base="true" name="EventLatency" units="microseconds"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>mohsen@chromium.org</owner>
   <owner>graphics-dev@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/extensions/histograms.xml b/tools/metrics/histograms/histograms_xml/extensions/histograms.xml
index bc87cea..3d58ec7 100644
--- a/tools/metrics/histograms/histograms_xml/extensions/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/extensions/histograms.xml
@@ -582,7 +582,7 @@
 </histogram>
 
 <histogram name="Extensions.DeclarativeNetRequest.CreateVerifiedMatcherTime"
-    units="ms" expires_after="2021-05-02">
+    units="ms" expires_after="2021-07-11">
   <owner>karandeepb@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>
@@ -643,7 +643,7 @@
 </histogram>
 
 <histogram name="Extensions.DeclarativeNetRequest.LoadRulesetResult"
-    enum="LoadRulesetResult" expires_after="2021-05-02">
+    enum="LoadRulesetResult" expires_after="2021-07-11">
   <owner>karandeepb@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>
@@ -1235,7 +1235,7 @@
 </histogram>
 
 <histogram name="Extensions.ExtensionUninstalled" units="units"
-    expires_after="2021-04-04">
+    expires_after="2021-07-11">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>An extension has been uninstalled.</summary>
@@ -3365,7 +3365,7 @@
 </histogram>
 
 <histogram name="Extensions.UsedMimeTypeHandler" enum="UsedMimeTypeHandler"
-    expires_after="2021-03-01">
+    expires_after="2021-07-11">
   <owner>apotapchuk@chromium.org</owner>
   <owner>anqing@chromium.org</owner>
   <summary>
@@ -3561,7 +3561,7 @@
 </histogram>
 
 <histogram name="Extensions.WebRequestBlockingCount" units="extensions"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>karandeepb@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/gpu/histograms.xml b/tools/metrics/histograms/histograms_xml/gpu/histograms.xml
index 5f2bf10..02bbcd4 100644
--- a/tools/metrics/histograms/histograms_xml/gpu/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/gpu/histograms.xml
@@ -262,7 +262,7 @@
 </histogram>
 
 <histogram name="GPU.BlocklistFeatureTestResults"
-    enum="GPUBlocklistFeatureTestResults" expires_after="2021-03-21">
+    enum="GPUBlocklistFeatureTestResults" expires_after="2021-07-11">
   <owner>vmiura@chromium.org</owner>
   <owner>graphics-dev@chromium.org</owner>
   <summary>
@@ -640,7 +640,7 @@
 </histogram>
 
 <histogram name="GPU.EGLDisplayType" enum="EGLDisplayType"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>jbauman@chromium.org</owner>
   <summary>The display type used to ask for an EGLDisplay.</summary>
 </histogram>
@@ -762,7 +762,7 @@
 </histogram>
 
 <histogram name="GPU.GPUProcessLaunchTime" units="ms"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>vmiura@chromium.org</owner>
   <summary>
     Startup time of the GPU process as measured by the GPU process host.
diff --git a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
index f5ccc08..10f294c 100644
--- a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
+++ b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
@@ -19276,10 +19276,6 @@
   <suffix name="Success" label="The operation or partial operation succeeded."/>
   <affected-histogram name="Net.TrustTokens.NetErrorForTrustTokenOperation"/>
   <affected-histogram name="Net.TrustTokens.NetErrorForTrustTokenOperation"/>
-  <affected-histogram name="Net.TrustTokens.OperationBeginTime"/>
-  <affected-histogram name="Net.TrustTokens.OperationFinalizeTime"/>
-  <affected-histogram name="Net.TrustTokens.OperationServerTime"/>
-  <affected-histogram name="Net.TrustTokens.OperationTotalTime"/>
 </histogram_suffixes>
 
 <histogram_suffixes name="TrustTokenOperationType" separator=".">
@@ -19292,14 +19288,6 @@
       name="Net.TrustTokens.NetErrorForTrustTokenOperation.Failure"/>
   <affected-histogram
       name="Net.TrustTokens.NetErrorForTrustTokenOperation.Success"/>
-  <affected-histogram name="Net.TrustTokens.OperationBeginTime.Failure"/>
-  <affected-histogram name="Net.TrustTokens.OperationBeginTime.Success"/>
-  <affected-histogram name="Net.TrustTokens.OperationFinalizeTime.Failure"/>
-  <affected-histogram name="Net.TrustTokens.OperationFinalizeTime.Success"/>
-  <affected-histogram name="Net.TrustTokens.OperationServerTime.Failure"/>
-  <affected-histogram name="Net.TrustTokens.OperationServerTime.Success"/>
-  <affected-histogram name="Net.TrustTokens.OperationTotalTime.Failure"/>
-  <affected-histogram name="Net.TrustTokens.OperationTotalTime.Success"/>
   <affected-histogram name="Net.TrustTokens.RequestHelperFactoryOutcome"/>
 </histogram_suffixes>
 
diff --git a/tools/metrics/histograms/histograms_xml/input/histograms.xml b/tools/metrics/histograms/histograms_xml/input/histograms.xml
index 466ab52..6e85f70 100644
--- a/tools/metrics/histograms/histograms_xml/input/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/input/histograms.xml
@@ -168,7 +168,7 @@
 </histogram>
 
 <histogram name="InputMethod.Assistive.TimeToAccept.Emoji" units="ms"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>myy@google.com</owner>
   <owner>essential-inputs-team@google.com</owner>
   <summary>
@@ -198,7 +198,7 @@
 </histogram>
 
 <histogram name="InputMethod.Assistive.TimeToDismiss.PersonalInfo" units="ms"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>jiwan@google.com</owner>
   <owner>essential-inputs-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/instant/histograms.xml b/tools/metrics/histograms/histograms_xml/instant/histograms.xml
index 9160f47..d775318 100644
--- a/tools/metrics/histograms/histograms_xml/instant/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/instant/histograms.xml
@@ -211,7 +211,7 @@
 </histogram>
 
 <histogram name="InstantTethering.HostScanResult"
-    enum="InstantTethering_HostScanResult" expires_after="2021-05-09">
+    enum="InstantTethering_HostScanResult" expires_after="2021-07-11">
   <owner>hansberry@chromium.org</owner>
   <owner>better-together-dev@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/ios/histograms.xml b/tools/metrics/histograms/histograms_xml/ios/histograms.xml
index 79de568a..cac6f99 100644
--- a/tools/metrics/histograms/histograms_xml/ios/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/ios/histograms.xml
@@ -51,7 +51,7 @@
 </histogram>
 
 <histogram name="IOS.ContentExtension.DisplayCount" units="count"
-    expires_after="2021-05-02">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
@@ -61,7 +61,7 @@
 </histogram>
 
 <histogram name="IOS.ContentExtension.Index" units="index"
-    expires_after="2021-11-01">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
@@ -108,7 +108,7 @@
 </histogram>
 
 <histogram name="IOS.CredentialExtension.CopyPasswordCount" units="count"
-    expires_after="2021-06-06">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>djean@chromium.org</owner>
   <summary>
@@ -118,7 +118,7 @@
 </histogram>
 
 <histogram name="IOS.CredentialExtension.CopyURLCount" units="count"
-    expires_after="2021-05-09">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>djean@chromium.org</owner>
   <summary>
@@ -128,7 +128,7 @@
 </histogram>
 
 <histogram name="IOS.CredentialExtension.CopyUsernameCount" units="count"
-    expires_after="2021-05-09">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>djean@chromium.org</owner>
   <summary>
@@ -138,7 +138,7 @@
 </histogram>
 
 <histogram name="IOS.CredentialExtension.DisplayCount" units="count"
-    expires_after="2021-06-06">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>djean@chromium.org</owner>
   <summary>
@@ -148,7 +148,7 @@
 </histogram>
 
 <histogram name="IOS.CredentialExtension.FetchPasswordFailure" units="count"
-    expires_after="2021-05-09">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>djean@chromium.org</owner>
   <summary>
@@ -159,7 +159,7 @@
 </histogram>
 
 <histogram name="IOS.CredentialExtension.FetchPasswordNilArgument"
-    units="count" expires_after="2021-06-06">
+    units="count" expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>djean@chromium.org</owner>
   <summary>
@@ -170,7 +170,7 @@
 </histogram>
 
 <histogram name="IOS.CredentialExtension.PasswordUseCount" units="count"
-    expires_after="2021-06-06">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>djean@chromium.org</owner>
   <summary>
@@ -180,7 +180,7 @@
 </histogram>
 
 <histogram name="IOS.CredentialExtension.QuickPasswordUseCount" units="count"
-    expires_after="2021-06-06">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>djean@chromium.org</owner>
   <summary>
@@ -191,7 +191,7 @@
 </histogram>
 
 <histogram name="IOS.CredentialExtension.ReauthCount" units="count"
-    expires_after="2021-06-06">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>djean@chromium.org</owner>
   <summary>
@@ -201,7 +201,7 @@
 </histogram>
 
 <histogram name="IOS.CredentialExtension.SearchCount" units="count"
-    expires_after="2021-05-09">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>djean@chromium.org</owner>
   <summary>
@@ -213,7 +213,7 @@
 <histogram
     name="IOS.CredentialExtension.Service.Error.ReplaceCredentialIdentitiesWithIdentities"
     enum="iOSCredentialIdentityStoreErrorForReporting"
-    expires_after="2021-06-22">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>djean@chromium.org</owner>
   <summary>
@@ -223,7 +223,7 @@
 </histogram>
 
 <histogram name="IOS.CredentialExtension.ShowPasswordCount" units="count"
-    expires_after="2021-01-31">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>djean@chromium.org</owner>
   <summary>
@@ -362,7 +362,7 @@
 </histogram>
 
 <histogram name="IOS.FormInputAccessory.ExecuteFormAssistActionException"
-    enum="FormInputAccessoryAction" expires_after="2021-06-01">
+    enum="FormInputAccessoryAction" expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>eugenebut@chromium.org</owner>
   <summary>
@@ -380,7 +380,7 @@
   </summary>
 </histogram>
 
-<histogram name="IOS.Incognito.TimeSpent" units="ms" expires_after="2021-05-09">
+<histogram name="IOS.Incognito.TimeSpent" units="ms" expires_after="2021-07-11">
   <owner>olivierrobin@chromium.org</owner>
   <owner>thegreenfrog@chromium.org</owner>
   <summary>
@@ -493,7 +493,7 @@
 </histogram>
 
 <histogram name="IOS.MetricKit.ApplicationResumeTime" units="ms"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>eugenebut@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
@@ -513,7 +513,7 @@
 </histogram>
 
 <histogram name="IOS.MetricKit.BackgroundExitData" enum="MetricKitExitData"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>eugenebut@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
@@ -592,7 +592,7 @@
 </histogram>
 
 <histogram name="IOS.NSString.stringByReplacingCharactersInRange.NilArgument"
-    enum="Boolean" expires_after="2021-07-31">
+    enum="Boolean" expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>eugenebut@chromium.org</owner>
   <summary>
@@ -602,7 +602,7 @@
 </histogram>
 
 <histogram name="IOS.NTP.Impression" enum="IOSNTPImpression"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>gambard@chromium.org</owner>
   <summary>
     The type of NTP impressions on iOS, split by type of suggestions shown
@@ -668,9 +668,9 @@
 </histogram>
 
 <histogram name="IOS.Reauth.Password.Autofill" enum="ReauthenticationEvent"
-    expires_after="2021-06-20">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
-  <owner>bling-team@google.com</owner>
+  <owner>sarraf@google.com</owner>
   <summary>
     Tracks the results and attempts of reauthentication when using password
     Autofill suggestions.
@@ -678,9 +678,9 @@
 </histogram>
 
 <histogram name="IOS.Reauth.Password.ManualFallback"
-    enum="ReauthenticationEvent" expires_after="2021-06-20">
+    enum="ReauthenticationEvent" expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
-  <owner>bling-team@google.com</owner>
+  <owner>sarraf@google.com</owner>
   <summary>
     Tracks the results and attempts of reauthentication when using a password in
     Manual Fallback.
@@ -741,14 +741,14 @@
 </histogram>
 
 <histogram name="IOS.SearchExtension.Action" enum="IOSSearchExtensionAction"
-    expires_after="2021-05-23">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>The action selected by the user in the Search Extension.</summary>
 </histogram>
 
 <histogram name="IOS.SearchExtension.DisplayCount" units="count"
-    expires_after="2021-07-04">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
@@ -758,7 +758,7 @@
 </histogram>
 
 <histogram name="IOS.ShareExtension.ReceivedEntriesCount" units="files"
-    expires_after="2021-11-01">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
@@ -768,14 +768,14 @@
 </histogram>
 
 <histogram name="IOS.ShareExtension.ReceivedEntry"
-    enum="IOSShareExtensionReceivedEntryType" expires_after="2021-11-01">
+    enum="IOSShareExtensionReceivedEntryType" expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>Type of the item received from the iOS share extension.</summary>
 </histogram>
 
 <histogram name="IOS.ShareExtension.ReceivedEntryDelay" units="ms"
-    expires_after="2021-11-01">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
@@ -785,7 +785,7 @@
 </histogram>
 
 <histogram name="IOS.ShareExtension.Source"
-    enum="IOSShareExtensionReceivedEntrySource" expires_after="2021-11-01">
+    enum="IOSShareExtensionReceivedEntrySource" expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
@@ -820,7 +820,7 @@
   </summary>
 </histogram>
 
-<histogram name="IOS.Snapshots.CacheSize" units="KB" expires_after="2021-05-08">
+<histogram name="IOS.Snapshots.CacheSize" units="KB" expires_after="2021-07-11">
   <owner>edchin@chromium.org</owner>
   <owner>eugenebut@chromium.org</owner>
   <summary>
@@ -828,7 +828,7 @@
   </summary>
 </histogram>
 
-<histogram name="IOS.Snapshots.ImageSize" units="KB" expires_after="2021-05-08">
+<histogram name="IOS.Snapshots.ImageSize" units="KB" expires_after="2021-07-11">
   <owner>edchin@chromium.org</owner>
   <owner>eugenebut@chromium.org</owner>
   <summary>
@@ -837,7 +837,7 @@
   </summary>
 </histogram>
 
-<histogram name="IOS.Snapshots.PDFSize" units="KB" expires_after="2021-05-08">
+<histogram name="IOS.Snapshots.PDFSize" units="KB" expires_after="2021-07-11">
   <owner>edchin@chromium.org</owner>
   <owner>eugenebut@chromium.org</owner>
   <summary>
@@ -854,7 +854,7 @@
 </histogram>
 
 <histogram name="IOS.Spotlight.Availability" enum="IOSSpotlightAvailability"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>eugenebut@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
@@ -865,14 +865,14 @@
 </histogram>
 
 <histogram name="IOS.Spotlight.BookmarksIndexingDuration" units="ms"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>eugenebut@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>Time spent in Spotlight initial indexation of bookmarks.</summary>
 </histogram>
 
 <histogram name="IOS.Spotlight.BookmarksInitialIndexSize" units="units"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>eugenebut@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>Number of bookmarks indexed during initial indexation.</summary>
@@ -931,7 +931,7 @@
 </histogram>
 
 <histogram name="IOS.WidgetKit.Action" enum="IOSWidgetKitAction"
-    expires_after="2021-09-24">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>muradyan@google.com</owner>
   <summary>
@@ -941,7 +941,7 @@
 </histogram>
 
 <histogram name="IOS.WidgetKit.{Status}" enum="IOSWidgetKitExtensionKind"
-    expires_after="2021-10-30">
+    expires_after="2021-12-11">
   <owner>javierrobles@chromium.org</owner>
   <owner>muradyan@chromium.org</owner>
   <summary>
@@ -996,6 +996,90 @@
   </summary>
 </histogram>
 
+<histogram name="ManualFallback.PresentedOptions.AllPasswords"
+    units="Credentials" expires_after="2021-12-11">
+  <owner>javierrobles@chromium.org</owner>
+  <owner>gambard@chromium.org</owner>
+  <summary>
+    [iOS Only] Tracks the number of credentials presented to the user in the
+    &quot;Use other password...&quot; view in Manual Fallback. This is logged
+    everytime the user opens this view.
+  </summary>
+</histogram>
+
+<histogram name="ManualFallback.PresentedOptions.CreditCards" units="Cards"
+    expires_after="2021-12-11">
+  <owner>javierrobles@chromium.org</owner>
+  <owner>gambard@chromium.org</owner>
+  <summary>
+    [iOS Only] Tracks the number of cards presented to the user in Manual
+    Fallback. This is logged everytime the user opens this view.
+  </summary>
+</histogram>
+
+<histogram name="ManualFallback.PresentedOptions.Passwords" units="Credentials"
+    expires_after="2021-12-11">
+  <owner>javierrobles@chromium.org</owner>
+  <owner>gambard@chromium.org</owner>
+  <summary>
+    [iOS Only] Tracks the number of credentials presented to the user in the
+    Passwords Manual Fallback view. This is logged everytime the user opens this
+    view.
+  </summary>
+</histogram>
+
+<histogram name="ManualFallback.PresentedOptions.Profiles" units="Profiles"
+    expires_after="2021-12-11">
+  <owner>javierrobles@chromium.org</owner>
+  <owner>gambard@chromium.org</owner>
+  <summary>
+    [iOS Only] Tracks the number of profiles presented to the user in Manual
+    Fallback. This is logged everytime the user opens this view.
+  </summary>
+</histogram>
+
+<histogram name="ManualFallback.VisibleSuggestions.OpenCreditCards"
+    units="Suggestions" expires_after="2021-12-11">
+  <owner>javierrobles@chromium.org</owner>
+  <owner>gambard@chromium.org</owner>
+  <summary>
+    [iOS Only] Tracks the number of autofill suggestions present when the user
+    taps on the credit card button in manual fallback.
+  </summary>
+</histogram>
+
+<histogram name="ManualFallback.VisibleSuggestions.OpenPasswords"
+    units="Suggestions" expires_after="2021-12-11">
+  <owner>javierrobles@chromium.org</owner>
+  <owner>gambard@chromium.org</owner>
+  <summary>
+    [iOS Only] Tracks the number of password suggestions present when the user
+    taps on the password button in manual fallback.
+  </summary>
+</histogram>
+
+<histogram name="ManualFallback.VisibleSuggestions.OpenProfiles"
+    units="Suggestions" expires_after="2021-12-11">
+  <owner>javierrobles@chromium.org</owner>
+  <owner>gambard@chromium.org</owner>
+  <summary>
+    [iOS Only] Tracks the number of autofill suggestions present when the user
+    taps on the profiles (address) button in manual fallback.
+  </summary>
+</histogram>
+
+<histogram name="UserInterfaceStyle.CurrentlyUsed" enum="IOSUserInterfaceStyle"
+    expires_after="2021-12-11">
+  <owner>javierrobles@chromium.org</owner>
+  <owner>rkgibson@google.com</owner>
+  <owner>bling-team@google.com</owner>
+  <summary>
+    [iOS Only] Used on iOS 13+ to report the usage of Light and Dark mode. This
+    is logged at startup and on each user interface style change. Can be caused
+    by the system automatic switch or by the user manually changing the style.
+  </summary>
+</histogram>
+
 </histograms>
 
 </histogram-configuration>
diff --git a/tools/metrics/histograms/histograms_xml/media/histograms.xml b/tools/metrics/histograms/histograms_xml/media/histograms.xml
index 016be64..4b5c3dd88 100644
--- a/tools/metrics/histograms/histograms_xml/media/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/media/histograms.xml
@@ -3254,7 +3254,7 @@
 </histogram>
 
 <histogram name="Media.RTCVideoDecoderInitializationLatencyMs" units="ms"
-    expires_after="2021-05-02">
+    expires_after="2021-07-11">
   <owner>kron@chromium.org</owner>
   <owner>webrtc-video@google.com</owner>
   <summary>
@@ -3754,7 +3754,7 @@
   </summary>
 </histogram>
 
-<histogram name="Media.Video.Roughness" units="ms" expires_after="2021-05-09">
+<histogram name="Media.Video.Roughness" units="ms" expires_after="2021-07-11">
   <owner>eugene@chromium.org</owner>
   <owner>videostack-eng@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/memory/histograms.xml b/tools/metrics/histograms/histograms_xml/memory/histograms.xml
index 4ab40643..bf54f5d7 100644
--- a/tools/metrics/histograms/histograms_xml/memory/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/memory/histograms.xml
@@ -283,7 +283,7 @@
 </histogram>
 
 <histogram name="Memory.Browser.MemoryFootprint.NumLiveOverscroll" units="tabs"
-    expires_after="M91">
+    expires_after="2021-07-11">
   <owner>rkgibson@google.com</owner>
   <owner>eugenebut@chromium.org</owner>
   <summary>
@@ -298,7 +298,7 @@
 </histogram>
 
 <histogram name="Memory.Browser.MemoryFootprint.NumOpenTabs" units="tabs"
-    expires_after="M91">
+    expires_after="2021-07-11">
   <owner>rkgibson@google.com</owner>
   <owner>eugenebut@chromium.org</owner>
   <summary>
@@ -409,7 +409,7 @@
 </histogram>
 
 <histogram name="Memory.Discardable.LargeAllocationFromFreelist"
-    enum="BooleanLargeAllocationFromFreelist" expires_after="2021-05-09">
+    enum="BooleanLargeAllocationFromFreelist" expires_after="2021-07-11">
   <owner>thiabaud@google.com</owner>
   <owner>lizeb@chromium.org</owner>
   <summary>
@@ -419,7 +419,7 @@
 </histogram>
 
 <histogram name="Memory.Discardable.LockingSuccess"
-    enum="BooleanLockingSuccess" expires_after="2021-05-09">
+    enum="BooleanLockingSuccess" expires_after="2021-07-11">
   <owner>thiabaud@google.com</owner>
   <owner>lizeb@chromium.org</owner>
   <summary>
@@ -1016,7 +1016,7 @@
 </histogram>
 
 <histogram name="Memory.Experimental.Renderer.HighestPrivateMemoryFootprint"
-    units="MB" expires_after="2021-05-09">
+    units="MB" expires_after="2021-07-11">
   <owner>tasak@google.com</owner>
   <owner>bartekn@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/mobile/histograms.xml b/tools/metrics/histograms/histograms_xml/mobile/histograms.xml
index 2beb33a8..2bb652c 100644
--- a/tools/metrics/histograms/histograms_xml/mobile/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/mobile/histograms.xml
@@ -200,7 +200,7 @@
 </histogram>
 
 <histogram name="Mobile.Messages.Banner.OnScreenTime" units="ms"
-    expires_after="2021-03-20">
+    expires_after="2021-07-11">
   <owner>sczs@chromium.org</owner>
   <owner>thegreenfrog@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/navigation/histograms.xml b/tools/metrics/histograms/histograms_xml/navigation/histograms.xml
index 72ec02b..975ca72 100644
--- a/tools/metrics/histograms/histograms_xml/navigation/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/navigation/histograms.xml
@@ -721,7 +721,7 @@
 </histogram>
 
 <histogram name="Navigation.IsSameSiteInstance"
-    enum="NavigationIsSameSiteInstance" expires_after="2021-05-09">
+    enum="NavigationIsSameSiteInstance" expires_after="2021-07-11">
   <owner>arthursonzogni@chromium.org</owner>
   <owner>clamy@chromium.org</owner>
   <owner>nasko@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/net/histograms.xml b/tools/metrics/histograms/histograms_xml/net/histograms.xml
index c2dfd7f9..34ccf9d 100644
--- a/tools/metrics/histograms/histograms_xml/net/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/net/histograms.xml
@@ -41,7 +41,7 @@
 </histogram>
 
 <histogram name="Net.AlternateProtocolUsageGoogle"
-    enum="AlternateProtocolUsage" expires_after="2021-05-11">
+    enum="AlternateProtocolUsage" expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/OWNERS</owner>
   <summary>
@@ -363,7 +363,7 @@
 </histogram>
 
 <histogram name="Net.ConnectionInfo.MainFrame" enum="ConnectionInfo"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/OWNERS</owner>
   <summary>
@@ -1257,7 +1257,7 @@
 </histogram>
 
 <histogram base="true" name="Net.DNS.UI.DropdownSelectionEvent"
-    enum="DohProviderId" expires_after="2021-05-02">
+    enum="DohProviderId" expires_after="2021-07-11">
 <!-- Name completed by histogram_suffixes
    name="DnsDropdownSelectionEvent" -->
 
@@ -2042,7 +2042,7 @@
 </histogram>
 
 <histogram name="Net.QuicActiveSessions" units="units"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -2070,7 +2070,7 @@
 </histogram>
 
 <histogram name="Net.QuicConnection.WritePacketStatus" enum="QuicWriteStatus"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>wub@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -2080,7 +2080,7 @@
 </histogram>
 
 <histogram name="Net.QuicConnectivityMonitor.NumActiveDegradingSessions"
-    units="sessions" expires_after="2021-05-11">
+    units="sessions" expires_after="2021-07-11">
   <owner>zhongyi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -2185,7 +2185,7 @@
 </histogram>
 
 <histogram name="Net.QuicConnectivityMonitor.PercentageActiveDegradingSessions"
-    units="%" expires_after="2021-05-11">
+    units="%" expires_after="2021-07-11">
   <owner>zhongyi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -2221,7 +2221,7 @@
 </histogram>
 
 <histogram name="Net.QuicConnectivityMonitor.SessionDegradedBeforeWriteError"
-    enum="BooleanDetected" expires_after="2021-05-11">
+    enum="BooleanDetected" expires_after="2021-07-11">
   <owner>zhongyi@chromium.org</owner>
   <owner>rockot@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
@@ -2628,7 +2628,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.ConnectionCloseErrorCodeClientGoogle"
-    enum="QuicErrorCodes" expires_after="2021-05-11">
+    enum="QuicErrorCodes" expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -2648,7 +2648,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.ConnectionCloseErrorCodeServerGoogle"
-    enum="QuicErrorCodes" expires_after="2021-05-11">
+    enum="QuicErrorCodes" expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -2792,7 +2792,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.ConnectionMigrationProbeSuccess"
-    enum="BooleanSuccess" expires_after="2021-05-11">
+    enum="BooleanSuccess" expires_after="2021-07-11">
   <owner>fayang@chromium.org</owner>
   <owner>zhongyi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
@@ -2816,7 +2816,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.ConnectionTypeFromPeer" enum="AddressFamily"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -2854,7 +2854,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.CryptoRetransmitCount.HandshakeConfirmed"
-    units="count" expires_after="2021-05-11">
+    units="count" expires_after="2021-07-11">
   <owner>fayang@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -2863,7 +2863,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.CryptoRetransmitCount.HandshakeNotConfirmed"
-    units="count" expires_after="2021-05-11">
+    units="count" expires_after="2021-07-11">
   <owner>fayang@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -2912,7 +2912,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.FinchConfigIsValid" enum="Boolean"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -2965,7 +2965,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.HandshakeConfirmedTime" units="Milliseconds"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3062,7 +3062,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.InitialRttEsitmateSource"
-    enum="InitialRttEstimateSource" expires_after="2021-05-11">
+    enum="InitialRttEstimateSource" expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3086,7 +3086,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.KeyUpdate.PerConnection2" units="count"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>mattm@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3097,7 +3097,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.KeyUpdate.PotentialPeerKeyUpdateAttemptCount"
-    units="count" expires_after="2021-05-11">
+    units="count" expires_after="2021-07-11">
   <owner>mattm@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3133,7 +3133,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.KeyUpdate.Supported"
-    enum="QuicKeyUpdateSupported" expires_after="2021-05-11">
+    enum="QuicKeyUpdateSupported" expires_after="2021-07-11">
   <owner>mattm@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3203,7 +3203,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.MaxReorderingTimeLongRtt" units="%"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3222,7 +3222,7 @@
   </summary>
 </histogram>
 
-<histogram name="Net.QuicSession.MinRTT" units="ms" expires_after="2021-05-11">
+<histogram name="Net.QuicSession.MinRTT" units="ms" expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3241,7 +3241,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.NumActiveStreamsOnIdleTimeout" units="streams"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>renjietang@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3277,7 +3277,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.NumPendingStreamRequests"
-    units="stream requests" expires_after="2021-05-11">
+    units="stream requests" expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3297,7 +3297,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.NumStreamsWaitingToWriteOnIdleTimeout"
-    units="streams" expires_after="2021-05-11">
+    units="streams" expires_after="2021-07-11">
   <owner>renjietang@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3360,7 +3360,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.PacketGapReceivedNearPing" units="count"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>zhongyi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3381,7 +3381,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.PacketLossRate" units="1/10th Percent"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3432,7 +3432,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.PortMigration"
-    enum="QuicConnectionMigrationStatus" expires_after="2021-05-11">
+    enum="QuicConnectionMigrationStatus" expires_after="2021-07-11">
   <owner>zhongyi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>The result of a QUIC port migration attempt.</summary>
@@ -3480,7 +3480,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.Pushed" units="count"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3489,7 +3489,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.PushedAndClaimed" units="count"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3498,7 +3498,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.PushedAndUnclaimedBytes" units="count"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>zhongyi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3507,7 +3507,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.PushedBytes" units="count"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>zhongyi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3559,14 +3559,14 @@
 </histogram>
 
 <histogram name="Net.QuicSession.QuicVersion" units="units"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>Version of the QUIC protocol used for this connection.</summary>
 </histogram>
 
 <histogram name="Net.QuicSession.ReadError" enum="NetErrorCodes"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3576,7 +3576,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.ReadError.CurrentNetwork.HandshakeConfirmed"
-    enum="NetErrorCodes" expires_after="2021-05-11">
+    enum="NetErrorCodes" expires_after="2021-07-11">
   <owner>zhongyi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3731,7 +3731,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.SmoothedRTT" units="ms"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3796,7 +3796,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.StreamCloseErrorCodeServer.HandshakeConfirmed"
-    enum="QuicErrorCodes" expires_after="2021-05-11">
+    enum="QuicErrorCodes" expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3878,7 +3878,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.TimedOutWithOpenStreams.HasUnackedPackets"
-    units="units" expires_after="2021-05-11">
+    units="units" expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3938,7 +3938,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.UndecryptablePacketsReceivedWithDecrypter"
-    units="units" expires_after="2021-05-11">
+    units="units" expires_after="2021-07-11">
   <owner>mattm@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3991,7 +3991,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.VerifyProofTime" units="ms"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -4002,7 +4002,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.WriteError" enum="NetErrorCodes"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -4012,7 +4012,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.WriteError.HandshakeConfirmed"
-    enum="NetErrorCodes" expires_after="2021-05-11">
+    enum="NetErrorCodes" expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -4042,7 +4042,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.ZeroRttReason"
-    enum="SSLHandshakeEarlyDataReason" expires_after="2021-05-11">
+    enum="SSLHandshakeEarlyDataReason" expires_after="2021-07-11">
   <owner>nharper@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -4052,7 +4052,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.ZeroRttReasonGoogle"
-    enum="SSLHandshakeEarlyDataReason" expires_after="2021-05-11">
+    enum="SSLHandshakeEarlyDataReason" expires_after="2021-07-11">
   <owner>renjietang@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -4063,7 +4063,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.ZeroRttReasonNonGoogle"
-    enum="SSLHandshakeEarlyDataReason" expires_after="2021-05-11">
+    enum="SSLHandshakeEarlyDataReason" expires_after="2021-07-11">
   <owner>renjietang@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -4074,7 +4074,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.ZeroRttState" enum="ZeroRttState"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>renjietang@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>Whether 0-RTT was successfully used in the connection.</summary>
@@ -4421,7 +4421,7 @@
 </histogram>
 
 <histogram name="Net.SpdyPushedStreamFate" enum="SpdyPushedStreamFate"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/OWNERS</owner>
   <summary>
@@ -4539,7 +4539,7 @@
 </histogram>
 
 <histogram name="Net.SpdyStreamsPushedAndClaimedPerSession" units="units"
-    expires_after="2021-05-11">
+    expires_after="2021-07-11">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/OWNERS</owner>
   <summary>
@@ -4719,7 +4719,7 @@
 </histogram>
 
 <histogram name="Net.SSLVersionGoogle" enum="SSLOrQUICVersion"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>davidben@chromium.org</owner>
   <owner>rsleevi@chromium.org</owner>
   <summary>
@@ -4896,54 +4896,43 @@
   </summary>
 </histogram>
 
-<histogram base="true" name="Net.TrustTokens.OperationBeginTime" units="ms"
-    expires_after="2021-05-30">
-<!-- Name completed by histogram_suffixes name="TrustTokenOperationType" -->
-
+<histogram base="true"
+    name="Net.TrustTokens.Operation{TimeSpan}Time.{Outcome}.{Type}{OptionalPlatformProvided}"
+    units="ms" expires_after="2021-07-30">
   <owner>davidvc@chromium.org</owner>
   <owner>privacy-sandbox-dev@chromium.org</owner>
   <summary>
-    Time taken to execute a Trust Tokens operation's outbound Begin half (see
-    network::TrustTokenRequestHelper).
+    Time taken to execute various parts of a Trust Tokens operation: 1. Begin =
+    time taken to execute the operation's outbound Begin half 2. Server = time
+    from the end of the outbound Begin half to the beginning of the inbound
+    Finalize half 3. Finalize = time taken to execute the inbound Finalize half
+    4. Total = Begin + Server + Finalize (only recorded for operations that see
+    server responses)
+
+    The other variants (see histogram_suffixes_list's TrustTokenOperationType
+    entry): 1. Outcome (Success or Failure) 2. The type of Trust Tokens
+    operation 3. Whether the operation was platform-provided (i.e. executed by a
+    method other than a direct HTTP request to the issuer's server)
   </summary>
-</histogram>
-
-<histogram base="true" name="Net.TrustTokens.OperationFinalizeTime" units="ms"
-    expires_after="2021-03-30">
-<!-- Name completed by histogram_suffixes name="TrustTokenOperationType" -->
-
-  <owner>davidvc@chromium.org</owner>
-  <owner>privacy-sandbox-dev@chromium.org</owner>
-  <summary>
-    Time time to taken a Trust Tokens operation's inbound Finalize half (see
-    network::TrustTokenRequestHelper).
-  </summary>
-</histogram>
-
-<histogram base="true" name="Net.TrustTokens.OperationServerTime" units="ms"
-    expires_after="2021-07-04">
-<!-- Name completed by histogram_suffixes name="TrustTokenOperationType" -->
-
-  <owner>davidvc@chromium.org</owner>
-  <owner>privacy-sandbox-dev@chromium.org</owner>
-  <summary>
-    Time between finishing a Trust Tokens Tokens operation's outbound Begin half
-    and beginning its inbound Finalize half (see
-    network::TrustTokenRequestHelper).
-  </summary>
-</histogram>
-
-<histogram base="true" name="Net.TrustTokens.OperationTotalTime" units="ms"
-    expires_after="2021-06-06">
-<!-- Name completed by histogram_suffixes name="TrustTokenOperationType" -->
-
-  <owner>davidvc@chromium.org</owner>
-  <owner>privacy-sandbox-dev@chromium.org</owner>
-  <summary>
-    Time elapsed from the beginning of a Trust Tokens operation's outbound Begin
-    half to the end of its inbound Finalize half (see
-    network::TrustTokenRequestHelper), when the operation succeeded overall.
-  </summary>
+  <token key="TimeSpan">
+    <variant name="Begin"/>
+    <variant name="Finalize"/>
+    <variant name="Server"/>
+    <variant name="Total"/>
+  </token>
+  <token key="Outcome">
+    <variant name="Failure"/>
+    <variant name="Success"/>
+  </token>
+  <token key="Type">
+    <variant name="Issuance"/>
+    <variant name="Redemption"/>
+    <variant name="Signing"/>
+  </token>
+  <token key="OptionalPlatformProvided">
+    <variant name=""/>
+    <variant name=".PlatformProvided"/>
+  </token>
 </histogram>
 
 <histogram base="true" name="Net.TrustTokens.RequestHelperFactoryOutcome"
diff --git a/tools/metrics/histograms/histograms_xml/new_tab_page/histograms.xml b/tools/metrics/histograms/histograms_xml/new_tab_page/histograms.xml
index 51848a3..144a4f9 100644
--- a/tools/metrics/histograms/histograms_xml/new_tab_page/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/new_tab_page/histograms.xml
@@ -599,7 +599,7 @@
 </histogram>
 
 <histogram name="NewTabPage.Customized" enum="NTPCustomizedFeatures"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>tiborg@chromium.org</owner>
   <owner>yyushkina@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
@@ -718,7 +718,7 @@
 </histogram>
 
 <histogram name="NewTabPage.LogoShown" enum="NewTabPageLogoShown"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>tiborg@chromium.org</owner>
   <owner>yyushkina@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
@@ -886,7 +886,7 @@
 </histogram>
 
 <histogram name="NewTabPage.NumberOfTiles" units="units"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>tiborg@chromium.org</owner>
   <owner>yyushkina@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
@@ -914,7 +914,7 @@
 </histogram>
 
 <histogram name="NewTabPage.OneGoogleBar.ShownTime" units="ms"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>tiborg@chromium.org</owner>
   <owner>yyushkina@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
@@ -1037,7 +1037,7 @@
 </histogram>
 
 <histogram name="NewTabPage.Promos.ShownTime" units="ms"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>tiborg@chromium.org</owner>
   <owner>yyushkina@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
@@ -1613,7 +1613,7 @@
 </histogram>
 
 <histogram name="NewTabPage.VoiceActions" enum="NewTabPageVoiceAction"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>tiborg@chromium.org</owner>
   <owner>yyushkina@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
diff --git a/tools/metrics/histograms/histograms_xml/obsolete_histograms.xml b/tools/metrics/histograms/histograms_xml/obsolete_histograms.xml
index 850d262..c1f85b8 100644
--- a/tools/metrics/histograms/histograms_xml/obsolete_histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/obsolete_histograms.xml
@@ -27272,7 +27272,7 @@
   </summary>
 </histogram>
 
-<histogram name="Hotword.SharedModuleReinstallLanguage" enum="LanguageCode"
+<histogram name="Hotword.SharedModuleReinstallLanguage" enum="LanguageName"
     expires_after="2017-11-28">
   <obsolete>
     Removed as of 10/2017. Feature removed with crbug/761426.
diff --git a/tools/metrics/histograms/histograms_xml/offline/histograms.xml b/tools/metrics/histograms/histograms_xml/offline/histograms.xml
index ee2b5f4e5..fa72686 100644
--- a/tools/metrics/histograms/histograms_xml/offline/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/offline/histograms.xml
@@ -22,7 +22,7 @@
 <histograms>
 
 <histogram name="OfflineIndicator.ConnectivityChanged.DeviceState.Offline"
-    enum="OfflineIndicatorSurfaceState" expires_after="2021-05-09">
+    enum="OfflineIndicatorSurfaceState" expires_after="2021-07-11">
   <owner>curranmax@chromium.org</owner>
   <owner>tbansal@chromium.org</owner>
   <owner>sinansahin@google.com</owner>
@@ -58,7 +58,7 @@
 </histogram>
 
 <histogram name="OfflineIndicator.ShownDuration" units="ms"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>curranmax@chromium.org</owner>
   <owner>tbansal@chromium.org</owner>
   <owner>sinansahin@google.com</owner>
diff --git a/tools/metrics/histograms/histograms_xml/omnibox/histograms.xml b/tools/metrics/histograms/histograms_xml/omnibox/histograms.xml
index 21f5a8d5..d767436 100644
--- a/tools/metrics/histograms/histograms_xml/omnibox/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/omnibox/histograms.xml
@@ -726,7 +726,7 @@
 </histogram>
 
 <histogram name="Omnibox.SelectedPosition" units="position"
-    expires_after="2021-07-04">
+    expires_after="2021-07-11">
   <owner>jdonnelly@chromium.org</owner>
   <owner>mpearson@chromium.org</owner>
   <owner>chrome-omnibox-team@google.com</owner>
@@ -905,7 +905,7 @@
 </histogram>
 
 <histogram name="Omnibox.SuggestRequest.Failure.GoogleResponseTime" units="ms"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>mpearson@chromium.org</owner>
   <owner>jdonnelly@chromium.org</owner>
   <owner>cch@chromium.org</owner>
@@ -940,7 +940,7 @@
 </histogram>
 
 <histogram name="Omnibox.SuggestRequests" enum="OmniboxSuggestRequests"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>mpearson@chromium.org</owner>
   <owner>jdonnelly@chromium.org</owner>
   <owner>cch@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/others/histograms.xml b/tools/metrics/histograms/histograms_xml/others/histograms.xml
index 549a8c2..2caed7d 100644
--- a/tools/metrics/histograms/histograms_xml/others/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/others/histograms.xml
@@ -582,7 +582,7 @@
 </histogram>
 
 <histogram name="AppBanners.InstallEvent" enum="AppBannersInstallEvent"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>pjmclachlan@google.com</owner>
   <owner>pcovell@google.com</owner>
   <summary>
@@ -606,7 +606,7 @@
 </histogram>
 
 <histogram name="AppBanners.UserResponse" enum="AppBannersUserResponse"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>dominickn@chromium.org</owner>
   <owner>pjmclachlan@google.com</owner>
   <summary>
@@ -987,7 +987,7 @@
 </histogram>
 
 <histogram name="Aura.WebContentsWindowUnOccludedTime" units="ms"
-    expires_after="2021-02-28">
+    expires_after="2021-07-11">
   <owner>alemate@chromium.org</owner>
   <owner>oshima@chromium.org</owner>
   <summary>
@@ -1763,7 +1763,7 @@
 </histogram>
 
 <histogram name="Bookmarks.ReadingList.NumberOfReadItems" units="items"
-    expires_after="M91">
+    expires_after="2021-07-11">
   <owner>shaktisahu@chromium.org</owner>
   <owner>xingliu@chromium.org</owner>
   <summary>
@@ -2527,7 +2527,7 @@
 </histogram>
 
 <histogram name="Clipboard.Read" enum="ClipboardFormatRead"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>huangdarwin@chromium.org</owner>
   <owner>src/ui/base/clipboard/OWNERS</owner>
   <summary>
@@ -2552,7 +2552,7 @@
 </histogram>
 
 <histogram name="Clipboard.Write" enum="ClipboardFormatWrite"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>huangdarwin@chromium.org</owner>
   <owner>src/ui/base/clipboard/OWNERS</owner>
   <summary>
@@ -2618,7 +2618,7 @@
 </histogram>
 
 <histogram base="true" name="CompositorLatency" units="microseconds"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>sadrul@chromium.org</owner>
   <owner>graphics-dev@chromium.org</owner>
   <summary>
@@ -4059,7 +4059,7 @@
 </histogram>
 
 <histogram name="Display.ParseEdidFailure" enum="ParseEdidFailure"
-    expires_after="2021-05-01">
+    expires_after="2021-07-11">
   <owner>sashamcintosh@chromium.org</owner>
   <owner>chromeos-gfx@google.com</owner>
   <summary>
@@ -5999,7 +5999,7 @@
 </histogram>
 
 <histogram name="Graphics.Smoothness.Checkerboarding" units="%"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>sadrul@chromium.org</owner>
   <owner>graphics-dev@chromium.org</owner>
   <summary>
@@ -6777,13 +6777,13 @@
   </summary>
 </histogram>
 
-<histogram name="Hyphenation.Open" units="ms" expires_after="2021-05-09">
+<histogram name="Hyphenation.Open" units="ms" expires_after="2021-07-11">
   <owner>kojii@chromium.org</owner>
   <owner>layout-dev@chromium.org</owner>
   <summary>The time it takes to open a hyphenation dictionary.</summary>
 </histogram>
 
-<histogram name="Hyphenation.Open.File" units="ms" expires_after="2021-05-09">
+<histogram name="Hyphenation.Open.File" units="ms" expires_after="2021-07-11">
   <owner>kojii@chromium.org</owner>
   <owner>layout-dev@chromium.org</owner>
   <summary>The time it takes to open a hyphenation dictionary file.</summary>
@@ -6857,7 +6857,7 @@
 </histogram>
 
 <histogram name="ImportantFile.FileCreateError" enum="PlatformFileError"
-    expires_after="2021-03-21">
+    expires_after="2021-07-11">
   <owner>grt@chromium.org</owner>
   <owner>xaerox@yandex-team.ru</owner>
   <summary>
@@ -7919,13 +7919,13 @@
 </histogram>
 
 <histogram name="LanguageSettings.PageImpression"
-    enum="LanguageSettingsPageType" expires_after="2021-05-09">
+    enum="LanguageSettingsPageType" expires_after="2021-07-11">
   <owner>googleo@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>The type of panes which language settings loads.</summary>
 </histogram>
 
-<histogram name="LanguageUsage.AcceptLanguage" enum="LanguageCode"
+<histogram name="LanguageUsage.AcceptLanguage" enum="LanguageName"
     expires_after="2021-06-06">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
@@ -7945,7 +7945,7 @@
   </summary>
 </histogram>
 
-<histogram name="LanguageUsage.ApplicationLanguage" enum="LanguageCode"
+<histogram name="LanguageUsage.ApplicationLanguage" enum="LanguageName"
     expires_after="2021-06-06">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
@@ -7955,7 +7955,7 @@
   </summary>
 </histogram>
 
-<histogram name="LanguageUsage.MostFrequentPageLanguages" enum="LanguageCode"
+<histogram name="LanguageUsage.MostFrequentPageLanguages" enum="LanguageName"
     expires_after="2021-06-20">
   <owner>perrier@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
@@ -8914,77 +8914,6 @@
   </summary>
 </histogram>
 
-<histogram name="ManualFallback.PresentedOptions.AllPasswords"
-    units="Credentials" expires_after="2021-05-23">
-  <owner>javierrobles@chromium.org</owner>
-  <owner>gambard@chromium.org</owner>
-  <summary>
-    Tracks the number of credentials presented to the user in the &quot;Use
-    other password...&quot; view in Manual Fallback. This is logged everytime
-    the user opens this view.
-  </summary>
-</histogram>
-
-<histogram name="ManualFallback.PresentedOptions.CreditCards" units="Cards"
-    expires_after="2021-05-23">
-  <owner>javierrobles@chromium.org</owner>
-  <owner>gambard@chromium.org</owner>
-  <summary>
-    Tracks the number of cards presented to the user in Manual Fallback. This is
-    logged everytime the user opens this view.
-  </summary>
-</histogram>
-
-<histogram name="ManualFallback.PresentedOptions.Passwords" units="Credentials"
-    expires_after="2021-05-23">
-  <owner>javierrobles@chromium.org</owner>
-  <owner>gambard@chromium.org</owner>
-  <summary>
-    Tracks the number of credentials presented to the user in the Passwords
-    Manual Fallback view. This is logged everytime the user opens this view.
-  </summary>
-</histogram>
-
-<histogram name="ManualFallback.PresentedOptions.Profiles" units="Profiles"
-    expires_after="2021-05-23">
-  <owner>javierrobles@chromium.org</owner>
-  <owner>gambard@chromium.org</owner>
-  <summary>
-    Tracks the number of profiles presented to the user in Manual Fallback. This
-    is logged everytime the user opens this view.
-  </summary>
-</histogram>
-
-<histogram name="ManualFallback.VisibleSuggestions.OpenCreditCards"
-    units="Suggestions" expires_after="2021-05-30">
-  <owner>javierrobles@chromium.org</owner>
-  <owner>gambard@chromium.org</owner>
-  <summary>
-    Tracks the number of autofill suggestions present when the user taps on the
-    credit card button in manual fallback.
-  </summary>
-</histogram>
-
-<histogram name="ManualFallback.VisibleSuggestions.OpenPasswords"
-    units="Suggestions" expires_after="2021-05-30">
-  <owner>javierrobles@chromium.org</owner>
-  <owner>gambard@chromium.org</owner>
-  <summary>
-    Tracks the number of password suggestions present when the user taps on the
-    password button in manual fallback.
-  </summary>
-</histogram>
-
-<histogram name="ManualFallback.VisibleSuggestions.OpenProfiles"
-    units="Suggestions" expires_after="2021-01-15">
-  <owner>javierrobles@chromium.org</owner>
-  <owner>gambard@chromium.org</owner>
-  <summary>
-    Tracks the number of autofill suggestions present when the user taps on the
-    profiles (address) button in manual fallback.
-  </summary>
-</histogram>
-
 <histogram name="Mist.SwitchResult" enum="MistSwitchResult" expires_after="M77">
   <owner>akhouderchah@chromium.org</owner>
   <owner>benchan@chromium.org</owner>
@@ -10284,20 +10213,13 @@
   </token>
 </histogram>
 
-<histogram name="Nearby.Share.Transfer.FinalStatus"
-    enum="NearbyShareTransferFinalStatus" expires_after="2021-08-19">
-  <owner>nohle@chromium.org</owner>
-  <owner>nearby-share-chromeos-eng@google.com</owner>
-  <summary>
-    Records the final status of a Nearby Share transfer. Emitted when a transfer
-    completes successfully, fails, or was aborted by the user, for example, by
-    cancelling the transfer.
-  </summary>
-</histogram>
-
 <histogram
     name="Nearby.Share.Transfer.FinalStatus.{Direction}.{ShareTargetType}.{ContactStatus}"
     enum="NearbyShareTransferFinalStatus" expires_after="2021-08-19">
+  <obsolete>
+    Replaced 01/2021 with Nearby.Share.Transfer.FinalStatus{Variation}, which
+    slices by only one dimension.
+  </obsolete>
   <owner>nohle@chromium.org</owner>
   <owner>nearby-share-chromeos-eng@google.com</owner>
   <summary>
@@ -10322,6 +10244,31 @@
   </token>
 </histogram>
 
+<histogram name="Nearby.Share.Transfer.FinalStatus{Variation}"
+    enum="NearbyShareTransferFinalStatus" expires_after="2021-08-19">
+  <owner>nohle@chromium.org</owner>
+  <owner>nearby-share-chromeos-eng@google.com</owner>
+  <summary>
+    Records the final status of a Nearby Share transfer {Variation}. Emitted
+    when a transfer completes successfully, fails, or was aborted by the user,
+    for example, by cancelling the transfer.
+  </summary>
+  <token key="Variation">
+    <variant name=""
+        summary="for all sharing scenarios, agnostic of send/receive, device
+                 type, or contact/non-contact"/>
+    <variant name=".Contact" summary="when sharing with a contact"/>
+    <variant name=".Laptop" summary="when sharing with a laptop"/>
+    <variant name=".NonContact" summary="when sharing with a non-contact"/>
+    <variant name=".Phone" summary="when sharing with a phone"/>
+    <variant name=".Receive" summary="when receiving"/>
+    <variant name=".Send" summary="when sending"/>
+    <variant name=".Tablet" summary="when sharing with a tablet"/>
+    <variant name=".UnknownDeviceType"
+        summary="when sharing with an unknown device type"/>
+  </token>
+</histogram>
+
 <histogram name="Nearby.Share.Transfer.NumAttachments{Type}"
     units="attachments" expires_after="2021-08-19">
   <obsolete>
@@ -10614,7 +10561,7 @@
 </histogram>
 
 <histogram name="NQE.RTT.OnECTComputation" units="ms"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>bengr@chromium.org</owner>
   <owner>tbansal@chromium.org</owner>
   <summary>
@@ -11131,7 +11078,7 @@
 </histogram>
 
 <histogram name="PaintHolding.CommitTrigger2" enum="PaintHoldingCommitTrigger2"
-    expires_after="2021-01-15">
+    expires_after="2021-07-15">
   <owner>schenney@chromium.org</owner>
   <owner>paint-dev@chromium.org</owner>
   <summary>
@@ -11141,7 +11088,7 @@
 </histogram>
 
 <histogram name="PaintHolding.InputTiming2" enum="PaintHoldingInputTiming"
-    expires_after="2021-01-15">
+    expires_after="2021-07-15">
   <owner>schenney@chromium.org</owner>
   <owner>paint-dev@chromium.org</owner>
   <summary>
@@ -11235,7 +11182,7 @@
 </histogram>
 
 <histogram name="PDF.LoadStatus" enum="ChromePDFViewerLoadStatus"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>kmoon@chromium.org</owner>
   <owner>thestig@chromium.org</owner>
   <summary>
@@ -11245,7 +11192,7 @@
   </summary>
 </histogram>
 
-<histogram name="PDF.PageCount" units="pages" expires_after="2021-05-09">
+<histogram name="PDF.PageCount" units="pages" expires_after="2021-07-11">
   <owner>hnakashima@chromium.org</owner>
   <owner>thestig@chromium.org</owner>
   <summary>
@@ -13421,7 +13368,7 @@
 </histogram>
 
 <histogram name="SB2.ResourceTypes2" enum="ContentResourceType2"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>vakh@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -13920,7 +13867,7 @@
 </histogram>
 
 <histogram name="SharedHighlights.LinkGenerated" units="BooleanSuccess"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>gayane@chromium.org</owner>
   <owner>chrome-shared-highlighting@google.com</owner>
   <summary>
@@ -13929,7 +13876,7 @@
 </histogram>
 
 <histogram name="SharedHighlights.LinkGenerated.Error"
-    enum="LinkGenerationError" expires_after="2021-05-09">
+    enum="LinkGenerationError" expires_after="2021-07-11">
   <owner>gayane@chromium.org</owner>
   <owner>chrome-shared-highlighting@google.com</owner>
   <summary>
@@ -13938,7 +13885,7 @@
 </histogram>
 
 <histogram name="SharedHighlights.LinkGenerated.Error.Iterations"
-    units="iterations" expires_after="2021-05-09">
+    units="iterations" expires_after="2021-07-11">
   <owner>gayane@chromium.org</owner>
   <owner>chrome-shared-highlighting@google.com</owner>
   <summary>
@@ -13948,7 +13895,7 @@
 </histogram>
 
 <histogram name="SharedHighlights.LinkGenerated.Error.TimeToGenerate"
-    units="ms" expires_after="2021-05-09">
+    units="ms" expires_after="2021-07-11">
   <owner>gayane@chromium.org</owner>
   <owner>chrome-shared-highlighting@google.com</owner>
   <summary>
@@ -13958,7 +13905,7 @@
 </histogram>
 
 <histogram name="SharedHighlights.LinkGenerated.Iterations" units="iterations"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>gayane@chromium.org</owner>
   <owner>chrome-shared-highlighting@google.com</owner>
   <summary>
@@ -13968,7 +13915,7 @@
 </histogram>
 
 <histogram name="SharedHighlights.LinkGenerated.ParamLength" units="characters"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>gayane@chromium.org</owner>
   <owner>chrome-shared-highlighting@google.com</owner>
   <summary>
@@ -13980,7 +13927,7 @@
 </histogram>
 
 <histogram name="SharedHighlights.LinkGenerated.SelectionLength"
-    units="characters" expires_after="2021-05-09">
+    units="characters" expires_after="2021-07-11">
   <owner>gayane@chromium.org</owner>
   <owner>chrome-shared-highlighting@google.com</owner>
   <summary>
@@ -13990,7 +13937,7 @@
 </histogram>
 
 <histogram name="SharedHighlights.LinkGenerated.SelectorParameters"
-    enum="TextFragmentAnchorParameters" expires_after="2021-05-09">
+    enum="TextFragmentAnchorParameters" expires_after="2021-07-11">
   <owner>gayane@chromium.org</owner>
   <owner>chrome-shared-highlighting@google.com</owner>
   <summary>
@@ -14000,7 +13947,7 @@
 </histogram>
 
 <histogram name="SharedHighlights.LinkGenerated.TimeToGenerate" units="ms"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>gayane@chromium.org</owner>
   <owner>chrome-shared-highlighting@google.com</owner>
   <summary>
@@ -14332,7 +14279,7 @@
 </histogram>
 
 <histogram name="SiteEngagementService.EngagementScore" units="units"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>calamity@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
@@ -14375,7 +14322,7 @@
 </histogram>
 
 <histogram name="SiteEngagementService.MedianEngagement" units="units"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>calamity@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
@@ -14423,7 +14370,7 @@
 </histogram>
 
 <histogram name="SiteEngagementService.TotalEngagement" units="units"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>calamity@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <summary>
@@ -14829,7 +14776,7 @@
 </histogram>
 
 <histogram name="SpellCheck.SpellingService.RequestDuration" units="ms"
-    expires_after="2021-04-04">
+    expires_after="2021-07-11">
   <owner>yyushkina@google.com</owner>
   <owner>gujen@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -15414,7 +15361,7 @@
 </histogram>
 
 <histogram name="SupervisedUsers.PerAppTimeLimits.BlockedAppsCount"
-    units="Apps" expires_after="2021-03-15">
+    units="Apps" expires_after="2021-07-11">
   <owner>agawronska@chromium.org</owner>
   <owner>yilkal@chromium.org</owner>
   <owner>cros-families@google.com</owner>
@@ -15671,7 +15618,7 @@
 </histogram>
 
 <histogram name="TextFragmentAnchor.LinkOpenSource"
-    enum="TextFragmentLinkOpenSource" expires_after="2021-05-09">
+    enum="TextFragmentLinkOpenSource" expires_after="2021-07-11">
   <owner>gayane@chromium.org</owner>
   <owner>chrome-shared-highlighting@google.com</owner>
   <summary>
@@ -16626,7 +16573,7 @@
 
 <histogram name="TrustedWebActivity.QualityEnforcementViolation"
     enum="TrustedWebActivityQualityEnforcementViolationType"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>eirage@chromium.org</owner>
   <owner>peconn@chromium.org</owner>
   <summary>
@@ -16864,7 +16811,7 @@
 </histogram>
 
 <histogram name="UsageStats.Events" enum="UsageStatsEvents"
-    expires_after="2021-05-02">
+    expires_after="2021-07-11">
   <owner>pnoland@chromium.org</owner>
   <owner>fgorski@chromium.org</owner>
   <summary>
@@ -16887,18 +16834,6 @@
   <summary>The time it took to download user's profile picture.</summary>
 </histogram>
 
-<histogram name="UserInterfaceStyle.CurrentlyUsed" enum="IOSUserInterfaceStyle"
-    expires_after="2021-01-15">
-  <owner>javierrobles@chromium.org</owner>
-  <owner>rkgibson@google.com</owner>
-  <owner>bling-team@google.com</owner>
-  <summary>
-    [iOS] Used on iOS 13+ to report the usage of Light and Dark mode. This is
-    logged at startup and on each user interface style change. Can be caused by
-    the system automatic switch or by the user manually changing the style.
-  </summary>
-</histogram>
-
 <histogram name="UserManager.LoginUserType" enum="UserType"
     expires_after="2021-06-06">
   <owner>achuith@chromium.org</owner>
@@ -17350,7 +17285,7 @@
   </summary>
 </histogram>
 
-<histogram name="VRSessionVideoCount" units="units" expires_after="2021-05-10">
+<histogram name="VRSessionVideoCount" units="units" expires_after="2021-07-11">
   <owner>alcooper@chromium.org</owner>
   <owner>xr-dev@chromium.org</owner>
   <summary>
@@ -17359,7 +17294,7 @@
   </summary>
 </histogram>
 
-<histogram name="VRSessionVideoTime" units="ms" expires_after="2021-05-10">
+<histogram name="VRSessionVideoTime" units="ms" expires_after="2021-07-11">
   <owner>alcooper@chromium.org</owner>
   <owner>xr-dev@chromium.org</owner>
   <summary>
@@ -17438,7 +17373,7 @@
 </histogram>
 
 <histogram base="true" name="WebApp.Engagement"
-    enum="SiteEngagementServiceEngagementType" expires_after="2021-05-09">
+    enum="SiteEngagementServiceEngagementType" expires_after="2021-07-11">
   <owner>calamity@chromium.org</owner>
   <owner>mgiuca@chromium.org</owner>
   <owner>loyso@chromium.org</owner>
@@ -17513,7 +17448,7 @@
 </histogram>
 
 <histogram name="Webapp.Install.InstallEvent" enum="WebappInstallSource"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>dominickn@chromium.org</owner>
   <owner>loyso@chromium.org</owner>
   <owner>calamity@chromium.org</owner>
@@ -17706,7 +17641,7 @@
 </histogram>
 
 <histogram name="Webapp.SystemApps.FreshInstallDuration" units="ms"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>calamity@chromium.org</owner>
   <owner>ortuno@chromium.org</owner>
   <summary>
@@ -17740,7 +17675,7 @@
 </histogram>
 
 <histogram name="Webapp.UninstallDialogAction"
-    enum="WebappUninstallDialogAction" expires_after="2021-05-09">
+    enum="WebappUninstallDialogAction" expires_after="2021-07-11">
   <owner>benwells@chromium.org</owner>
   <owner>dominickn@chromium.org</owner>
   <owner>loyso@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/page/histograms.xml b/tools/metrics/histograms/histograms_xml/page/histograms.xml
index c2b19fd..0e16524 100644
--- a/tools/metrics/histograms/histograms_xml/page/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/page/histograms.xml
@@ -658,7 +658,7 @@
 </histogram>
 
 <histogram name="PageLoad.Clients.ThirdParty.Origins.SessionStorageAccess2"
-    units="Count" expires_after="2021-05-09">
+    units="Count" expires_after="2021-07-11">
   <owner>yaoxia@chromium.org</owner>
   <owner>jkarlin@chromium.org</owner>
   <summary>
@@ -1093,7 +1093,7 @@
 
 <histogram
     name="PageLoad.Experimental.NavigationTiming.NavigationStartToFirstRequestStart"
-    units="ms" expires_after="2021-05-08">
+    units="ms" expires_after="2021-07-11">
   <owner>nhiroki@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
@@ -1115,7 +1115,7 @@
 
 <histogram
     name="PageLoad.Experimental.NavigationTiming.NavigationStartToNavigationCommitSent"
-    units="ms" expires_after="2021-05-08">
+    units="ms" expires_after="2021-07-11">
   <owner>nhiroki@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/password/histograms.xml b/tools/metrics/histograms/histograms_xml/password/histograms.xml
index cdf7cd4..5119331 100644
--- a/tools/metrics/histograms/histograms_xml/password/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/password/histograms.xml
@@ -22,7 +22,7 @@
 <histograms>
 
 <histogram name="PasswordBubble.CompromisedBubble.CheckClicked"
-    enum="BooleanClicked" expires_after="2021-05-09">
+    enum="BooleanClicked" expires_after="2021-07-11">
   <owner>vasilii@chromium.org</owner>
   <owner>jdoerrie@chromium.org</owner>
   <summary>
@@ -32,7 +32,7 @@
 </histogram>
 
 <histogram name="PasswordBubble.CompromisedBubble.Type"
-    enum="PasswordBubbleFollowupType" expires_after="2021-05-09">
+    enum="PasswordBubbleFollowupType" expires_after="2021-07-11">
   <owner>vasilii@chromium.org</owner>
   <owner>jdoerrie@chromium.org</owner>
   <summary>
@@ -67,7 +67,7 @@
 </histogram>
 
 <histogram name="PasswordGeneration.GeneratedPasswordWasEdited"
-    enum="BooleanGeneratedPasswordWasEdited" expires_after="2021-05-09">
+    enum="BooleanGeneratedPasswordWasEdited" expires_after="2021-07-11">
   <owner>kolos@chromium.org</owner>
   <summary>
     Measures the frequency of user editing of generated passwords. Uploaded once
@@ -102,7 +102,7 @@
 </histogram>
 
 <histogram name="PasswordGeneration.SubmissionEvent"
-    enum="PasswordSubmissionEvent" expires_after="2021-05-09">
+    enum="PasswordSubmissionEvent" expires_after="2021-07-11">
   <owner>jdoerrie@chromium.org</owner>
   <owner>kolos@chromium.org</owner>
   <summary>
@@ -654,7 +654,7 @@
 </histogram>
 
 <histogram name="PasswordManager.ApplySyncChanges.AddLoginSyncError"
-    enum="PasswordAddLoginSyncError" expires_after="2021-01-31">
+    enum="PasswordAddLoginSyncError" expires_after="2021-07-31">
   <owner>mamir@chromium.org</owner>
   <owner>mastiz@chromium.org</owner>
   <summary>
@@ -665,7 +665,7 @@
 </histogram>
 
 <histogram name="PasswordManager.ApplySyncChanges.UpdateLoginSyncError"
-    enum="PasswordUpdateLoginSyncError" expires_after="2021-01-31">
+    enum="PasswordUpdateLoginSyncError" expires_after="2021-07-31">
   <owner>mamir@chromium.org</owner>
   <owner>mastiz@chromium.org</owner>
   <summary>
@@ -676,7 +676,7 @@
 </histogram>
 
 <histogram name="PasswordManager.ApplySyncChangesState"
-    enum="PasswordApplySyncChangesState" expires_after="2021-01-31">
+    enum="PasswordApplySyncChangesState" expires_after="2021-07-31">
   <owner>mamir@chromium.org</owner>
   <owner>mastiz@chromium.org</owner>
   <summary>
@@ -943,7 +943,7 @@
 </histogram>
 
 <histogram name="PasswordManager.CredentialsCountFromAccountStoreAfterUnlock"
-    units="credentials" expires_after="2021-05-09">
+    units="credentials" expires_after="2021-07-11">
   <owner>fhorschig@chromium.org</owner>
   <owner>mamir@chromium.org</owner>
   <summary>
@@ -1569,7 +1569,7 @@
 </histogram>
 
 <histogram name="PasswordManager.MergeSyncData.AddLoginSyncError"
-    enum="PasswordAddLoginSyncError" expires_after="2021-04-25">
+    enum="PasswordAddLoginSyncError" expires_after="2021-07-31">
   <owner>mamir@chromium.org</owner>
   <owner>mastiz@chromium.org</owner>
   <summary>
@@ -1580,7 +1580,7 @@
 </histogram>
 
 <histogram name="PasswordManager.MergeSyncData.UpdateLoginSyncError"
-    enum="PasswordUpdateLoginSyncError" expires_after="2021-01-31">
+    enum="PasswordUpdateLoginSyncError" expires_after="2021-07-31">
   <owner>mamir@chromium.org</owner>
   <owner>mastiz@chromium.org</owner>
   <summary>
@@ -1952,7 +1952,7 @@
 </histogram>
 
 <histogram name="PasswordManager.SavedGaiaPasswordHashCount" units="count"
-    expires_after="2021-04-04">
+    expires_after="2021-07-11">
   <owner>vakh@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/plugin/histograms.xml b/tools/metrics/histograms/histograms_xml/plugin/histograms.xml
index 18dc982..795552f 100644
--- a/tools/metrics/histograms/histograms_xml/plugin/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/plugin/histograms.xml
@@ -125,7 +125,7 @@
 </histogram>
 
 <histogram name="PluginVm.DlcUseResult" units="PluginVmDlcUseResult"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>kimjae@google.com</owner>
   <owner>timloh@google.com</owner>
   <summary>Recorded at each time PluginVM DLC is installed.</summary>
diff --git a/tools/metrics/histograms/histograms_xml/print/histograms.xml b/tools/metrics/histograms/histograms_xml/print/histograms.xml
index 4e0afd88..304fb55 100644
--- a/tools/metrics/histograms/histograms_xml/print/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/print/histograms.xml
@@ -128,7 +128,7 @@
 </histogram>
 
 <histogram name="PrintPreview.PrintSettings" enum="PrintSettings"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>thestig@chromium.org</owner>
   <summary>
     Track the popularity of print settings. (Settings when printing to PDF are
diff --git a/tools/metrics/histograms/histograms_xml/profile/histograms.xml b/tools/metrics/histograms/histograms_xml/profile/histograms.xml
index a26f13ec..9a5ac3e 100644
--- a/tools/metrics/histograms/histograms_xml/profile/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/profile/histograms.xml
@@ -85,7 +85,7 @@
 </histogram>
 
 <histogram name="Profile.BrowserActive.PerProfile" enum="Profile"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>msarda@chromium.org</owner>
   <owner>tangltom@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/safe_browsing/histograms.xml b/tools/metrics/histograms/histograms_xml/safe_browsing/histograms.xml
index cb4e7ac..899f31e 100644
--- a/tools/metrics/histograms/histograms_xml/safe_browsing/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/safe_browsing/histograms.xml
@@ -884,7 +884,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.RT.CanCheckDatabase" enum="BooleanEnabled"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -930,7 +930,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.RT.GetToken.Time" units="ms"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -941,7 +941,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.RT.HasTokenFromFetcher" enum="BooleanHasToken"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -952,7 +952,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.RT.HasTokenInRequest" enum="BooleanHasToken"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
@@ -1039,7 +1039,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.RT.Request.UserPopulation"
-    enum="SafeBrowsingUserPopulation" expires_after="2021-05-11">
+    enum="SafeBrowsingUserPopulation" expires_after="2021-07-11">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-safebrowsing-alerts@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/session/histograms.xml b/tools/metrics/histograms/histograms_xml/session/histograms.xml
index e28fff5..95a417f 100644
--- a/tools/metrics/histograms/histograms_xml/session/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/session/histograms.xml
@@ -313,7 +313,7 @@
 </histogram>
 
 <histogram name="Session.TotalDuration.TouchMode" units="times"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>collinbaker@chromium.org</owner>
   <owner>chrome-desktop-ui-sea@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/settings/histograms.xml b/tools/metrics/histograms/histograms_xml/settings/histograms.xml
index e5028be..b6458cfe 100644
--- a/tools/metrics/histograms/histograms_xml/settings/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/settings/histograms.xml
@@ -343,7 +343,7 @@
 </histogram>
 
 <histogram name="Settings.StartupPageLoadSettings" enum="SessionStartupPref"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>mpearson@chromium.org</owner>
   <owner>ramyan@chromium.org</owner>
   <owner>tiborg@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/signin/histograms.xml b/tools/metrics/histograms/histograms_xml/signin/histograms.xml
index 10bda5a..4e05162 100644
--- a/tools/metrics/histograms/histograms_xml/signin/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/signin/histograms.xml
@@ -1053,7 +1053,7 @@
 
 <histogram
     name="Signin.SSOIdentityListRequest.FetchIdentitiesWithCallback.Duration"
-    units="ms" expires_after="2021-04-19">
+    units="ms" expires_after="2021-07-11">
   <owner>jlebel@chromium.org</owner>
   <owner>fernandex@chromium.org</owner>
   <owner>chrome-signin-team@google.com</owner>
@@ -1116,7 +1116,7 @@
 </histogram>
 
 <histogram name="Signin.SSOWKWebView.GetAllCookies.CookieCount" units="cookies"
-    expires_after="2021-04-19">
+    expires_after="2021-07-11">
   <owner>jlebel@chromium.org</owner>
   <owner>chrome-signin-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/stability/histograms.xml b/tools/metrics/histograms/histograms_xml/stability/histograms.xml
index ee1cd40..4ce9bbd 100644
--- a/tools/metrics/histograms/histograms_xml/stability/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/stability/histograms.xml
@@ -437,7 +437,7 @@
 </histogram>
 
 <histogram name="Stability.iOS.UTE.MobileSessionAppWillTerminateWasReceived"
-    enum="AppWillTerminateReceived" expires_after="2021-04-29">
+    enum="AppWillTerminateReceived" expires_after="2021-07-11">
   <owner>eugenebut@chromium.org</owner>
   <owner>olivierrobin@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/sync/histograms.xml b/tools/metrics/histograms/histograms_xml/sync/histograms.xml
index 99cc772..750b95e 100644
--- a/tools/metrics/histograms/histograms_xml/sync/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/sync/histograms.xml
@@ -140,7 +140,7 @@
 </histogram>
 
 <histogram name="Sync.ConfigureDataTypeManagerOption"
-    enum="SyncFeatureOrTransport" expires_after="2021-05-09">
+    enum="SyncFeatureOrTransport" expires_after="2021-07-11">
   <owner>treib@chromium.org</owner>
   <summary>
     Whether the full Sync feature or only the Sync transport layer is being
@@ -963,7 +963,7 @@
 </histogram>
 
 <histogram name="Sync.StopSource" enum="SyncStopSource"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>treib@chromium.org</owner>
   <owner>mastiz@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/tab/histograms.xml b/tools/metrics/histograms/histograms_xml/tab/histograms.xml
index 5702aef..c2302cc6 100644
--- a/tools/metrics/histograms/histograms_xml/tab/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/tab/histograms.xml
@@ -151,7 +151,7 @@
   </summary>
 </histogram>
 
-<histogram name="Tab.NewTab" enum="NewTabType" expires_after="2021-07-04">
+<histogram name="Tab.NewTab" enum="NewTabType" expires_after="2021-07-11">
   <owner>tbergquist@chromium.org</owner>
   <owner>bsep@chromium.org</owner>
   <summary>
@@ -592,7 +592,7 @@
 </histogram>
 
 <histogram name="TabGroups.CollapsedGroupCountPerLoad" units="groups"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>cyan@chromium.org</owner>
   <owner>chrome-desktop-ui-sea@google.com</owner>
   <summary>
@@ -614,7 +614,7 @@
 </histogram>
 
 <histogram name="TabGroups.TimeSpentCollapsed" units="ms"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>cyan@chromium.org</owner>
   <owner>chrome-desktop-ui-sea@google.com</owner>
   <summary>
@@ -624,7 +624,7 @@
 </histogram>
 
 <histogram name="TabGroups.TimeSpentExpanded" units="ms"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>cyan@chromium.org</owner>
   <owner>chrome-desktop-ui-sea@google.com</owner>
   <summary>
@@ -634,7 +634,7 @@
 </histogram>
 
 <histogram name="TabGroups.UserCustomizedGroupCountPerLoad" units="groups"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>connily@chromium.org</owner>
   <owner>cyan@chromium.org</owner>
   <owner>chrome-desktop-ui-sea@google.com</owner>
@@ -655,7 +655,7 @@
 </histogram>
 
 <histogram name="TabGroups.UserGroupCountPerLoad" units="groups"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>connily@chromium.org</owner>
   <owner>cyan@chromium.org</owner>
   <owner>chrome-desktop-ui-sea@google.com</owner>
@@ -2553,7 +2553,7 @@
   </summary>
 </histogram>
 
-<histogram name="TabStrip.TimeToSwitch" units="ms" expires_after="2021-05-09">
+<histogram name="TabStrip.TimeToSwitch" units="ms" expires_after="2021-07-11">
   <owner>connily@chromium.org</owner>
   <owner>cyan@chromium.org</owner>
   <owner>chrome-desktop-ui-sea@google.com</owner>
diff --git a/tools/metrics/histograms/histograms_xml/translate/histograms.xml b/tools/metrics/histograms/histograms_xml/translate/histograms.xml
index 07ae711..edd31c5 100644
--- a/tools/metrics/histograms/histograms_xml/translate/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/translate/histograms.xml
@@ -60,7 +60,7 @@
   </summary>
 </histogram>
 
-<histogram name="Translate.CLD3.LanguageDetected" enum="CLD3LanguageCode"
+<histogram name="Translate.CLD3.LanguageDetected" enum="LocaleCodeISO639"
     expires_after="2021-06-06">
   <owner>frechette@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
@@ -99,7 +99,7 @@
 </histogram>
 
 <histogram name="Translate.CompactInfobar.Language.AlwaysTranslate"
-    enum="CLD3LanguageCode" expires_after="2021-06-06">
+    enum="LocaleCodeISO639" expires_after="2021-06-06">
   <owner>anthonyvd@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -109,7 +109,7 @@
 </histogram>
 
 <histogram name="Translate.CompactInfobar.Language.MoreLanguages"
-    enum="CLD3LanguageCode" expires_after="2021-04-04">
+    enum="LocaleCodeISO639" expires_after="2021-06-06">
   <owner>anthonyvd@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -118,7 +118,7 @@
 </histogram>
 
 <histogram name="Translate.CompactInfobar.Language.NeverTranslate"
-    enum="CLD3LanguageCode" expires_after="2021-06-06">
+    enum="LocaleCodeISO639" expires_after="2021-06-06">
   <owner>anthonyvd@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -128,7 +128,7 @@
 </histogram>
 
 <histogram name="Translate.CompactInfobar.Language.PageNotIn"
-    enum="CLD3LanguageCode" expires_after="2021-06-06">
+    enum="LocaleCodeISO639" expires_after="2021-06-06">
   <owner>anthonyvd@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -138,11 +138,12 @@
 </histogram>
 
 <histogram name="Translate.CompactInfobar.Language.Translate"
-    enum="CLD3LanguageCode" expires_after="M85">
+    enum="LocaleCodeISO639" expires_after="2021-06-06">
   <owner>anthonyvd@chromium.org</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
-    Records the hashcode of the language clicked on the infobar.
+    Records the hashcode of the language clicked on the infobar. Expired from
+    M86 - M89.
   </summary>
 </histogram>
 
@@ -223,7 +224,7 @@
 </histogram>
 
 <histogram name="Translate.ExplicitLanguageAsk.LanguageAdded"
-    enum="CLD3LanguageCode" expires_after="2021-06-06">
+    enum="LocaleCodeISO639" expires_after="2021-06-06">
   <owner>yyushkina@google.com</owner>
   <owner>anthonyvd@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -234,7 +235,7 @@
 </histogram>
 
 <histogram name="Translate.ExplicitLanguageAsk.LanguageRemoved"
-    enum="CLD3LanguageCode" expires_after="2021-06-06">
+    enum="LocaleCodeISO639" expires_after="2021-06-06">
   <owner>yyushkina@google.com</owner>
   <owner>anthonyvd@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -369,7 +370,7 @@
   </summary>
 </histogram>
 
-<histogram name="Translate.LocalesOnDisabledByPrefs" enum="LanguageCode"
+<histogram name="Translate.LocalesOnDisabledByPrefs" enum="LanguageName"
     expires_after="2021-01-31">
   <owner>kenjibaheux@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -472,7 +473,7 @@
 </histogram>
 
 <histogram name="Translate.PageLoad.FinalSourceLanguage"
-    enum="CLD3LanguageCode" expires_after="2021-06-06">
+    enum="LocaleCodeISO639" expires_after="2021-06-06">
   <owner>curranmax@google.com</owner>
   <owner>megjablon@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -500,7 +501,7 @@
 </histogram>
 
 <histogram name="Translate.PageLoad.FinalTargetLanguage"
-    enum="CLD3LanguageCode" expires_after="2021-06-06">
+    enum="LocaleCodeISO639" expires_after="2021-06-06">
   <owner>curranmax@google.com</owner>
   <owner>megjablon@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -514,7 +515,7 @@
 </histogram>
 
 <histogram name="Translate.PageLoad.InitialSourceLanguage"
-    enum="CLD3LanguageCode" expires_after="2021-04-04">
+    enum="LocaleCodeISO639" expires_after="2021-04-04">
   <owner>curranmax@google.com</owner>
   <owner>megjablon@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -542,7 +543,7 @@
 </histogram>
 
 <histogram name="Translate.PageLoad.InitialTargetLanguage"
-    enum="CLD3LanguageCode" expires_after="2021-06-13">
+    enum="LocaleCodeISO639" expires_after="2021-06-13">
   <owner>curranmax@google.com</owner>
   <owner>megjablon@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -788,7 +789,7 @@
   </summary>
 </histogram>
 
-<histogram name="Translate.SourceLanguage" enum="CLD3LanguageCode"
+<histogram name="Translate.SourceLanguage" enum="LocaleCodeISO639"
     expires_after="2021-06-06">
   <owner>yyushkina@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -798,7 +799,7 @@
   </summary>
 </histogram>
 
-<histogram name="Translate.TargetLanguage" enum="CLD3LanguageCode"
+<histogram name="Translate.TargetLanguage" enum="LocaleCodeISO639"
     expires_after="2021-06-06">
   <owner>yyushkina@google.com</owner>
   <owner>chrome-language@google.com</owner>
@@ -922,8 +923,11 @@
   </summary>
 </histogram>
 
-<histogram name="Translate.UndisplayableLanguage" enum="LanguageCode"
+<histogram name="Translate.UndisplayableLanguage" enum="LanguageName"
     expires_after="M81">
+  <obsolete>
+    Removed 01/09/2021. Not used anymore.
+  </obsolete>
   <owner>kenjibaheux@google.com</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -934,8 +938,8 @@
   </summary>
 </histogram>
 
-<histogram name="Translate.UnsupportedLanguageAtInitiation" enum="LanguageCode"
-    expires_after="M81">
+<histogram name="Translate.UnsupportedLanguageAtInitiation" enum="LanguageName"
+    expires_after="2021-06-06">
   <owner>kenjibaheux@google.com</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
@@ -944,6 +948,7 @@
     detects the language of the webpage, but the language is not supported by
     the translation server because it is too minor. This metric allows us to
     assess how important the unsupported language is for Google translate.
+    Expired from M86 - M89.
   </summary>
 </histogram>
 
diff --git a/tools/metrics/histograms/histograms_xml/ukm/histograms.xml b/tools/metrics/histograms/histograms_xml/ukm/histograms.xml
index 24efc88..bbfb2f1 100644
--- a/tools/metrics/histograms/histograms_xml/ukm/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/ukm/histograms.xml
@@ -135,7 +135,7 @@
 </histogram>
 
 <histogram name="UKM.IOSLog.OnSuccess" units="records"
-    expires_after="2021-04-11">
+    expires_after="2021-07-11">
   <owner>eugenebut@chromium.org</owner>
   <owner>rkaplow@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/uma/histograms.xml b/tools/metrics/histograms/histograms_xml/uma/histograms.xml
index 46b4f97..00c1efe 100644
--- a/tools/metrics/histograms/histograms_xml/uma/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/uma/histograms.xml
@@ -132,7 +132,7 @@
 </histogram>
 
 <histogram name="UMA.IsClonedInstall" enum="BooleanCloned"
-    expires_after="2021-04-15">
+    expires_after="2021-07-11">
   <owner>asvitkine@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
   <summary>
@@ -571,7 +571,7 @@
 </histogram>
 
 <histogram name="UMA.TruncatedEvents.UserAction" units="events"
-    expires_after="2021-07-04">
+    expires_after="2021-07-11">
   <owner>rkaplow@chromium.org</owner>
   <owner>src/base/metrics/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/update_engine/histograms.xml b/tools/metrics/histograms/histograms_xml/update_engine/histograms.xml
index 18f878f..33c3f44 100644
--- a/tools/metrics/histograms/histograms_xml/update_engine/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/update_engine/histograms.xml
@@ -597,8 +597,8 @@
 
 <histogram
     name="UpdateEngine.SuccessfulUpdate.DurationFromSeenDays.NoTimeRestriction"
-    units="days" expires_after="2021-05-09">
-  <owner>mpolzer@google.com</owner>
+    units="days" expires_after="2021-07-11">
+  <owner>snijhara@google.com</owner>
   <owner>managed-platforms@google.com</owner>
   <summary>
     The total number of days from when an update is first seen to when an update
@@ -612,8 +612,8 @@
 
 <histogram
     name="UpdateEngine.SuccessfulUpdate.DurationFromSeenDays.TimeRestricted"
-    units="days" expires_after="2021-01-01">
-  <owner>mpolzer@google.com</owner>
+    units="days" expires_after="2021-05-09">
+  <owner>snijhara@google.com</owner>
   <owner>managed-platforms@google.com</owner>
   <summary>
     The total number of days from when an update is first seen to when an update
diff --git a/tools/metrics/histograms/histograms_xml/v8/histograms.xml b/tools/metrics/histograms/histograms_xml/v8/histograms.xml
index 8c4b94b..8a619511 100644
--- a/tools/metrics/histograms/histograms_xml/v8/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/v8/histograms.xml
@@ -644,7 +644,7 @@
 </histogram>
 
 <histogram name="V8.GCScavenger.ScavengeRoots" units="ms"
-    expires_after="2021-04-01">
+    expires_after="2021-07-11">
   <owner>mlippautz@chromium.org</owner>
   <owner>v8-memory-sheriffs@google.com</owner>
   <summary>Time spent in scavenging the roots during a V8 scavenge.</summary>
@@ -774,7 +774,7 @@
 </histogram>
 
 <histogram name="V8.MemoryHeapSampleTotalUsed" units="KB"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>hpayer@chromium.org</owner>
   <summary>
     The total size of live memory used by V8 after each GC in KB.
diff --git a/tools/metrics/histograms/histograms_xml/web_apk/histograms.xml b/tools/metrics/histograms/histograms_xml/web_apk/histograms.xml
index 1f60dae..0e4e422 100644
--- a/tools/metrics/histograms/histograms_xml/web_apk/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/web_apk/histograms.xml
@@ -70,7 +70,7 @@
 </histogram>
 
 <histogram name="WebApk.Install.GooglePlayInstallResult"
-    enum="WebApkGooglePlayInstallResult" expires_after="2021-05-09">
+    enum="WebApkGooglePlayInstallResult" expires_after="2021-07-11">
   <owner>hartmanng@chromium.org</owner>
   <owner>
     src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS
diff --git a/tools/metrics/histograms/histograms_xml/web_rtc/histograms.xml b/tools/metrics/histograms/histograms_xml/web_rtc/histograms.xml
index 50da81e..1d650a3b 100644
--- a/tools/metrics/histograms/histograms_xml/web_rtc/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/web_rtc/histograms.xml
@@ -931,7 +931,7 @@
 </histogram>
 
 <histogram name="WebRTC.BWE.Probing.TimePerProbeCluster" units="ms"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>jonasolsson@chromium.org</owner>
   <owner>crodbro@chromium.org</owner>
   <summary>
@@ -951,7 +951,7 @@
 </histogram>
 
 <histogram name="WebRTC.BWE.Probing.TotalProbeClustersRequested" units="units"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>jonasolsson@chromium.org</owner>
   <owner>crodbro@chromium.org</owner>
   <summary>
@@ -3544,7 +3544,7 @@
 </histogram>
 
 <histogram name="WebRTC.webkitApiCount" enum="RTCAPIName"
-    expires_after="2021-05-09">
+    expires_after="2021-07-11">
   <owner>guidou@chromium.org</owner>
   <owner>hbos@chromium.org</owner>
   <owner>mcasas@chromium.org</owner>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 0d357a4..79760a7 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,12 +5,12 @@
             "remote_path": "perfetto_binaries/trace_processor_shell/win/e3e59aac750e507e91be98ff4944a7bdd601a08e/trace_processor_shell.exe"
         },
         "mac": {
-            "hash": "fd0d9f70fe09c168bbb999ade77e6f9e4c991c3c",
-            "remote_path": "perfetto_binaries/trace_processor_shell/mac/bd6bd346f6773bdded75a794f6af704018722de4/trace_processor_shell"
+            "hash": "d9a52ed5c07fbc0eb8c051b372fb462788267b3c",
+            "remote_path": "perfetto_binaries/trace_processor_shell/mac/c60dda78e4abc2a16052ac325dcc0e2fab39d54c/trace_processor_shell"
         },
         "linux": {
-            "hash": "9de25afa2969d17640815fe3b83e4427b0526564",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/e3e59aac750e507e91be98ff4944a7bdd601a08e/trace_processor_shell"
+            "hash": "dc8c4a04caf836aca794cd8e8f19207ca3116bc7",
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/002c03c4b6ed27434ff35dbb31bd8c3288b0ccbd/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/run-swarmed.py b/tools/run-swarmed.py
index b8908196..b298daf 100755
--- a/tools/run-swarmed.py
+++ b/tools/run-swarmed.py
@@ -41,26 +41,24 @@
   """Triggers a swarming job. The arguments passed are:
   - The index of the job;
   - The command line arguments object;
-  - The hash of the isolate job used to trigger.
+  - The digest of test files.
 
   The return value is passed to a collect-style map() and consists of:
   - The index of the job;
   - The json file created by triggering and used to collect results;
   - The command line arguments object.
   """
-  index, args, isolated_hash, swarming_command = args
+  index, args, cas_digest, swarming_command = args
   json_file = os.path.join(args.results, '%d.json' % index)
   trigger_args = [
       'tools/luci-go/swarming',
       'trigger',
       '-S',
       'https://chromium-swarm.appspot.com',
-      '-I',
-      'https://isolateserver.appspot.com',
       '-d',
       'pool=' + args.pool,
-      '-s',
-      isolated_hash,
+      '-digest',
+      cas_digest,
       '-dump-json',
       json_file,
       '-d',
@@ -244,14 +242,14 @@
   )
 
   print('Uploading to isolate server, this can take a while...')
-  isolated = os.path.join(args.out_dir, args.target_name + '.isolated')
+  isolate = os.path.join(args.out_dir, args.target_name + '.isolate')
+  digest_json = os.path.join(args.out_dir, args.target_name + '.digest.json')
   subprocess.check_output([
-      'tools/luci-go/isolate', 'archive', '-I',
-      'https://isolateserver.appspot.com', '-i',
-      os.path.join(args.out_dir, args.target_name + '.isolate'), '-s', isolated
+      'tools/luci-go/isolate', 'archive', '-cas-instance', 'chromium-swarm',
+      '-isolate', isolate, '-dump-json', digest_json
   ])
-  with open(isolated) as f:
-    isolated_hash = hashlib.sha1(f.read()).hexdigest()
+  with open(digest_json) as f:
+    cas_digest = json.load(f).get(args.target_name)
 
   mb_cmd = [
       sys.executable, 'tools/mb/mb.py', 'get-swarming-command', '--as-list'
@@ -272,7 +270,7 @@
     # Use dummy since threadpools give better exception messages
     # than process pools do, and threads work fine for what we're doing.
     pool = multiprocessing.dummy.Pool()
-    spawn_args = map(lambda i: (i, args, isolated_hash, swarming_cmd),
+    spawn_args = map(lambda i: (i, args, cas_digest, swarming_cmd),
                      range(args.copies))
     spawn_results = pool.imap_unordered(_Spawn, spawn_args)
 
diff --git a/ui/accessibility/accessibility_features.cc b/ui/accessibility/accessibility_features.cc
index 7ff8967..2a80d11 100644
--- a/ui/accessibility/accessibility_features.cc
+++ b/ui/accessibility/accessibility_features.cc
@@ -91,6 +91,14 @@
 bool IsMagnifierNewFocusFollowingEnabled() {
   return base::FeatureList::IsEnabled(::features::kMagnifierNewFocusFollowing);
 }
+
+const base::Feature kMagnifierPanningImprovements{
+    "MagnifierPanningImprovements", base::FEATURE_DISABLED_BY_DEFAULT};
+
+bool IsMagnifierPanningImprovementsEnabled() {
+  return base::FeatureList::IsEnabled(
+      ::features::kMagnifierPanningImprovements);
+}
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 const base::Feature kAugmentExistingImageLabels{
diff --git a/ui/accessibility/accessibility_features.h b/ui/accessibility/accessibility_features.h
index a954257..8ce561b 100644
--- a/ui/accessibility/accessibility_features.h
+++ b/ui/accessibility/accessibility_features.h
@@ -76,6 +76,13 @@
 
 // Returns true if the new magnifier focus following feature is enabled.
 AX_BASE_EXPORT bool IsMagnifierNewFocusFollowingEnabled();
+
+// Enables new magnifier panning improvements feature, which adds
+// additional keyboard and mouse panning functionality in Magnifier.
+AX_BASE_EXPORT extern const base::Feature kMagnifierPanningImprovements;
+
+// Returns true if the new magnifier panning improvements feature is enabled.
+AX_BASE_EXPORT bool IsMagnifierPanningImprovementsEnabled();
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
 // Enables Get Image Descriptions to augment existing images labels,
diff --git a/ui/accessibility/ax_node.cc b/ui/accessibility/ax_node.cc
index 977a8e8..a114dd8b 100644
--- a/ui/accessibility/ax_node.cc
+++ b/ui/accessibility/ax_node.cc
@@ -89,6 +89,7 @@
 }
 
 AXNode* AXNode::GetDeepestFirstUnignoredChild() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   if (!GetUnignoredChildCount())
     return nullptr;
 
@@ -101,6 +102,7 @@
 }
 
 AXNode* AXNode::GetDeepestLastUnignoredChild() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   if (!GetUnignoredChildCount())
     return nullptr;
 
@@ -287,6 +289,7 @@
 }
 
 AXNode* AXNode::GetNextUnignoredInTreeOrder() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   if (GetUnignoredChildCount())
     return GetFirstUnignoredChild();
 
@@ -303,6 +306,7 @@
 }
 
 AXNode* AXNode::GetPreviousUnignoredInTreeOrder() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   AXNode* sibling = GetPreviousUnignoredSibling();
   if (!sibling)
     return GetUnignoredParent();
@@ -419,6 +423,7 @@
 }
 
 std::vector<int> AXNode::GetOrComputeLineStartOffsets() {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   std::vector<int> line_offsets;
   if (data().GetIntListAttribute(ax::mojom::IntListAttribute::kCachedLineStarts,
                                  &line_offsets)) {
@@ -434,6 +439,7 @@
 
 void AXNode::ComputeLineStartOffsets(std::vector<int>* line_offsets,
                                      int* start_offset) const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   DCHECK(line_offsets);
   DCHECK(start_offset);
   for (const AXNode* child : children()) {
@@ -487,6 +493,7 @@
 }
 
 std::string AXNode::GetHypertext() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   if (IsLeaf())
     return GetInnerText();
 
@@ -509,6 +516,7 @@
 }
 
 std::string AXNode::GetInnerText() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   // If a text field has no descendants, then we compute its inner text from its
   // value or its placeholder. Otherwise we prefer to look at its descendant
   // text nodes because Blink doesn't always add all trailing white space to the
@@ -569,6 +577,7 @@
 }
 
 std::string AXNode::GetLanguage() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   // Walk up tree considering both detected and author declared languages.
   for (const AXNode* cur = this; cur; cur = cur->parent()) {
     // If language detection has assigned a language then we prefer that.
@@ -588,6 +597,7 @@
 }
 
 std::string AXNode::GetValueForControl() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   if (data().IsTextField())
     return GetValueForTextField();
   if (data().IsRangeValueSupported())
@@ -608,6 +618,7 @@
 }
 
 base::Optional<int> AXNode::GetTableColCount() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   const AXTableInfo* table_info = GetAncestorTableInfo();
   if (!table_info)
     return base::nullopt;
@@ -615,6 +626,7 @@
 }
 
 base::Optional<int> AXNode::GetTableRowCount() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   const AXTableInfo* table_info = GetAncestorTableInfo();
   if (!table_info)
     return base::nullopt;
@@ -622,6 +634,7 @@
 }
 
 base::Optional<int> AXNode::GetTableAriaColCount() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   const AXTableInfo* table_info = GetAncestorTableInfo();
   if (!table_info)
     return base::nullopt;
@@ -629,6 +642,7 @@
 }
 
 base::Optional<int> AXNode::GetTableAriaRowCount() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   const AXTableInfo* table_info = GetAncestorTableInfo();
   if (!table_info)
     return base::nullopt;
@@ -636,6 +650,7 @@
 }
 
 base::Optional<int> AXNode::GetTableCellCount() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   const AXTableInfo* table_info = GetAncestorTableInfo();
   if (!table_info)
     return base::nullopt;
@@ -644,6 +659,7 @@
 }
 
 base::Optional<bool> AXNode::GetTableHasColumnOrRowHeaderNode() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   const AXTableInfo* table_info = GetAncestorTableInfo();
   if (!table_info)
     return base::nullopt;
@@ -652,6 +668,7 @@
 }
 
 AXNode* AXNode::GetTableCellFromIndex(int index) const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   const AXTableInfo* table_info = GetAncestorTableInfo();
   if (!table_info)
     return nullptr;
@@ -665,6 +682,7 @@
 }
 
 AXNode* AXNode::GetTableCaption() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   const AXTableInfo* table_info = GetAncestorTableInfo();
   if (!table_info)
     return nullptr;
@@ -673,6 +691,7 @@
 }
 
 AXNode* AXNode::GetTableCellFromCoords(int row_index, int col_index) const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   const AXTableInfo* table_info = GetAncestorTableInfo();
   if (!table_info)
     return nullptr;
@@ -688,6 +707,7 @@
 }
 
 std::vector<AXNode::AXID> AXNode::GetTableColHeaderNodeIds() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   const AXTableInfo* table_info = GetAncestorTableInfo();
   if (!table_info)
     return std::vector<AXNode::AXID>();
@@ -705,6 +725,7 @@
 
 std::vector<AXNode::AXID> AXNode::GetTableColHeaderNodeIds(
     int col_index) const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   const AXTableInfo* table_info = GetAncestorTableInfo();
   if (!table_info)
     return std::vector<AXNode::AXID>();
@@ -717,6 +738,7 @@
 
 std::vector<AXNode::AXID> AXNode::GetTableRowHeaderNodeIds(
     int row_index) const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   const AXTableInfo* table_info = GetAncestorTableInfo();
   if (!table_info)
     return std::vector<AXNode::AXID>();
@@ -728,6 +750,7 @@
 }
 
 std::vector<AXNode::AXID> AXNode::GetTableUniqueCellIds() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   const AXTableInfo* table_info = GetAncestorTableInfo();
   if (!table_info)
     return std::vector<AXNode::AXID>();
@@ -736,6 +759,7 @@
 }
 
 const std::vector<AXNode*>* AXNode::GetExtraMacNodes() const {
+  DCHECK(!tree_->GetTreeUpdateInProgressState());
   // Should only be available on the table node itself, not any of its children.
   const AXTableInfo* table_info = tree_->GetTableInfo(this);
   if (!table_info)
diff --git a/ui/accessibility/platform/ax_unique_id.cc b/ui/accessibility/platform/ax_unique_id.cc
index ea5d9ce1..cfb433a 100644
--- a/ui/accessibility/platform/ax_unique_id.cc
+++ b/ui/accessibility/platform/ax_unique_id.cc
@@ -46,7 +46,7 @@
 
   const int32_t prev_id = current_id;
   do {
-    if (current_id == max_id) {
+    if (current_id >= max_id) {
       current_id = 1;
       has_wrapped = true;
     } else {
diff --git a/ui/accessibility/platform/ax_unique_id_unittest.cc b/ui/accessibility/platform/ax_unique_id_unittest.cc
index d6fdb58..42a722b 100644
--- a/ui/accessibility/platform/ax_unique_id_unittest.cc
+++ b/ui/accessibility/platform/ax_unique_id_unittest.cc
@@ -53,4 +53,22 @@
   EXPECT_EQ(ids[kIdToReplace]->Get(), expected_id);
 }
 
+TEST(AXPlatformUniqueIdTest, DoesCreateCorrectId) {
+  int kLargerThanMaxId = kMaxId * 2;
+  std::unique_ptr<AXUniqueId> ids[kLargerThanMaxId];
+  // Creates and releases to fill up the internal static counter.
+  for (int i = 0; i < kLargerThanMaxId; i++) {
+    ids[i] = std::make_unique<AXUniqueId>();
+  }
+  for (int i = 0; i < kLargerThanMaxId; i++) {
+    ids[i].reset(nullptr);
+  }
+  // Creates an unique id whose max value is less than the internal
+  // static counter.
+  std::unique_ptr<AXTestSmallBankUniqueId> unique_id =
+      std::make_unique<AXTestSmallBankUniqueId>();
+
+  EXPECT_LE(unique_id->Get(), kMaxId);
+}
+
 }  // namespace ui
diff --git a/ui/views/animation/ink_drop_painted_layer_delegates.h b/ui/views/animation/ink_drop_painted_layer_delegates.h
index c2090df..82b6763 100644
--- a/ui/views/animation/ink_drop_painted_layer_delegates.h
+++ b/ui/views/animation/ink_drop_painted_layer_delegates.h
@@ -35,11 +35,12 @@
   void OnDeviceScaleFactorChanged(float old_device_scale_factor,
                                   float new_device_scale_factor) override;
 
+  SkColor color() const { return color_; }
+  void set_color(SkColor color) { color_ = color; }
+
  protected:
   explicit BasePaintedLayerDelegate(SkColor color);
 
-  SkColor color() const { return color_; }
-
  private:
   // The color to paint.
   SkColor color_;
diff --git a/ui/webui/resources/cr_elements/cr_menu_selector/cr_menu_selector.js b/ui/webui/resources/cr_elements/cr_menu_selector/cr_menu_selector.js
index 7b1254a8..3f2225bc 100644
--- a/ui/webui/resources/cr_elements/cr_menu_selector/cr_menu_selector.js
+++ b/ui/webui/resources/cr_elements/cr_menu_selector/cr_menu_selector.js
@@ -46,9 +46,10 @@
     // If the focus was moved by keyboard and is coming in from a relatedTarget
     // that is not within this menu, move the focus to the first menu item. This
     // ensures that the first menu item is always the first focused item when
-    // focusing into the menu.
+    // focusing into the menu. A null relatedTarget means the focus was moved
+    // from outside the WebContents.
     const focusMovedWithKeyboard = this.focusOutlineManager_.visible;
-    const focusMovedFromOutside = e.relatedTarget &&
+    const focusMovedFromOutside = e.relatedTarget === null ||
         !this.contains(/** @type {!HTMLElement} */ (e.relatedTarget));
     if (focusMovedWithKeyboard && focusMovedFromOutside) {
       this.getItems_()[0].focus();