diff --git a/.vpython3 b/.vpython3
index cc05918..1ef981d 100644
--- a/.vpython3
+++ b/.vpython3
@@ -28,5 +28,5 @@
 # become available.
 wheel: <
   name: "infra/python/wheels/six-py2_py3"
-  version: "version:1.10.0"
+  version: "version:1.15.0"
 >
diff --git a/AUTHORS b/AUTHORS
index 638c949..c2bd015 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -89,6 +89,7 @@
 Andrew Hung <andrhung@amazon.com>
 Andrew Jorgensen <ajorgens@amazon.com>
 Andrew MacPherson <andrew.macpherson@soundtrap.com>
+Andrew Nicols <andrewrn@gmail.com>
 Andrew Tulloch <andrew@tullo.ch>
 Andriy Rysin <arysin@gmail.com>
 Anish Patankar <anish.p@samsung.com>
diff --git a/DEPS b/DEPS
index 2dbc76b..c7c9bf1 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': '415642b766face3623257248e2c0f1d99d1406b2',
+  'skia_revision': '80dc74b30b5a50f133de6e8985d1c10a0c0f380e',
   # 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': '68e7e8e44e2565c394ee558210d6d9fa5a4d80ff',
+  'v8_revision': 'c4b600873d9668aeeb4f28e20f86d82b5c75379c',
   # 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.
@@ -211,7 +211,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': 'c47b951ecbcbbba653db801bc7eb5f4fa5d72042',
+  'angle_revision': 'ed9213bca0643edb65b7d39a938210419398a1b3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -219,7 +219,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling PDFium
   # and whatever else without interference from each other.
-  'pdfium_revision': '0a1e0410572e3c9f378c426e9301f878798b3ab0',
+  'pdfium_revision': '4f67a285e22100c9dc9d175e8269c8fed1734f34',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
@@ -274,7 +274,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '50f3473f0f8aae9c656db4922a33607de0d7530e',
+  'devtools_frontend_revision': '2d25220a33955364a5d806c265cd1d161b03f0d9',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -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': 'ee977a0df8e3f3a12a6f2983db98838bf65566da',
+  'dawn_revision': '5d4fd88a7403aa255d49919d011af54c691b344a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -353,7 +353,7 @@
   'ukey2_revision': '0275885d8e6038c39b8a8ca55e75d1d4d1727f47',
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'tint_revision': 'd1469c60c1ab5c96278d570aa93ef38b722b67e4',
+  'tint_revision': '9a644c7903caa792fc5f78ffe945289d802687df',
 
   # TODO(crbug.com/941824): The values below need to be kept in sync
   # between //DEPS and //buildtools/DEPS, so if you're updating one,
@@ -1514,7 +1514,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '3c2fe3888658d82b47ca831d59a2e07579619c2d',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '8592111e458d253e53806db65d23d21bfe9d9db4',
+    Var('webrtc_git') + '/src.git' + '@' + 'd7f750f7be4b2f61018d3cb55a995d09daa226e6',
 
   'src/third_party/libgifcodec':
      Var('skia_git') + '/libgifcodec' + '@'+  Var('libgifcodec_revision'),
@@ -1586,7 +1586,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@36bcb86f66a4d861de00d0b4dff06111fd1cab21',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@fedff31db07933f52e860a4fa75744c90c71a383',
     'condition': 'checkout_src_internal',
   },
 
@@ -1605,7 +1605,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'Lqnbzl4-hoc2WrAL80TsiADU6Of1I2wk_-c35v-9vSkC',
+        'version': 'cLMbR5hrZxbw11Uo04_qMEm4sHJn3Ur2ZPVxIm1LhUQC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/browser/BUILD.gn b/android_webview/browser/BUILD.gn
index f80d91f..c1354b19 100644
--- a/android_webview/browser/BUILD.gn
+++ b/android_webview/browser/BUILD.gn
@@ -246,6 +246,7 @@
     "//content/public/browser",
     "//media/mojo:buildflags",
     "//printing",
+    "//services/network/public/mojom",
     "//services/preferences/tracked",
     "//services/proxy_resolver:lib",
     "//third_party/blink/public/common",
diff --git a/android_webview/browser/aw_content_browser_client.cc b/android_webview/browser/aw_content_browser_client.cc
index 806880c..855c301 100644
--- a/android_webview/browser/aw_content_browser_client.cc
+++ b/android_webview/browser/aw_content_browser_client.cc
@@ -96,11 +96,11 @@
 #include "services/network/network_service.h"
 #include "services/network/public/cpp/resource_request.h"
 #include "services/network/public/mojom/cookie_manager.mojom-forward.h"
+#include "services/network/public/mojom/fetch_api.mojom.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "services/service_manager/public/cpp/interface_provider.h"
 #include "third_party/blink/public/common/loader/url_loader_throttle.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
-#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/resource/resource_bundle_android.h"
 #include "ui/display/display.h"
@@ -136,16 +136,8 @@
   explicit AwContentsMessageFilter(int process_id);
 
   // BrowserMessageFilter methods.
-  void OverrideThreadForMessage(const IPC::Message& message,
-                                BrowserThread::ID* thread) override;
   bool OnMessageReceived(const IPC::Message& message) override;
 
-  void OnShouldOverrideUrlLoading(int routing_id,
-                                  const base::string16& url,
-                                  bool has_user_gesture,
-                                  bool is_redirect,
-                                  bool is_main_frame,
-                                  bool* ignore_navigation);
   void OnSubFrameCreated(int parent_render_frame_id, int child_render_frame_id);
 
  private:
@@ -161,49 +153,15 @@
 
 AwContentsMessageFilter::~AwContentsMessageFilter() = default;
 
-void AwContentsMessageFilter::OverrideThreadForMessage(
-    const IPC::Message& message,
-    BrowserThread::ID* thread) {
-  if (message.type() == AwViewHostMsg_ShouldOverrideUrlLoading::ID) {
-    *thread = BrowserThread::UI;
-  }
-}
-
 bool AwContentsMessageFilter::OnMessageReceived(const IPC::Message& message) {
   bool handled = true;
   IPC_BEGIN_MESSAGE_MAP(AwContentsMessageFilter, message)
-    IPC_MESSAGE_HANDLER(AwViewHostMsg_ShouldOverrideUrlLoading,
-                        OnShouldOverrideUrlLoading)
     IPC_MESSAGE_HANDLER(AwViewHostMsg_SubFrameCreated, OnSubFrameCreated)
     IPC_MESSAGE_UNHANDLED(handled = false)
   IPC_END_MESSAGE_MAP()
   return handled;
 }
 
-void AwContentsMessageFilter::OnShouldOverrideUrlLoading(
-    int render_frame_id,
-    const base::string16& url,
-    bool has_user_gesture,
-    bool is_redirect,
-    bool is_main_frame,
-    bool* ignore_navigation) {
-  DCHECK_CURRENTLY_ON(BrowserThread::UI);
-  *ignore_navigation = false;
-  AwContentsClientBridge* client =
-      AwContentsClientBridge::FromID(process_id_, render_frame_id);
-  if (client) {
-    if (!client->ShouldOverrideUrlLoading(url, has_user_gesture, is_redirect,
-                                          is_main_frame, ignore_navigation)) {
-      // If the shouldOverrideUrlLoading call caused a java exception we should
-      // always return immediately here!
-      return;
-    }
-  } else {
-    LOG(WARNING) << "Failed to find the associated render view host for url: "
-                 << url;
-  }
-}
-
 void AwContentsMessageFilter::OnSubFrameCreated(int parent_render_frame_id,
                                                 int child_render_frame_id) {
   AwContentsIoThreadClient::SubFrameCreated(process_id_, parent_render_frame_id,
@@ -717,8 +675,7 @@
       // Since AW currently doesn't support UKM, this feature is not enabled.
       /* rt_lookup_service */ nullptr));
 
-  if (request.resource_type ==
-      static_cast<int>(blink::mojom::ResourceType::kMainFrame)) {
+  if (request.destination == network::mojom::RequestDestination::kDocument) {
     const bool is_load_url =
         request.transition_type & ui::PAGE_TRANSITION_FROM_API;
     const bool is_go_back_forward =
diff --git a/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc b/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc
index e2b6ddbb..794d955 100644
--- a/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc
+++ b/android_webview/browser/network_service/aw_proxying_url_loader_factory.cc
@@ -37,7 +37,7 @@
 #include "net/base/load_flags.h"
 #include "net/http/http_util.h"
 #include "services/network/public/cpp/resource_request.h"
-#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
+#include "services/network/public/mojom/fetch_api.mojom.h"
 #include "url/gurl.h"
 
 namespace android_webview {
@@ -511,8 +511,7 @@
                        std::move(error_info)));
   }
 
-  if (request_.resource_type ==
-      static_cast<int>(blink::mojom::ResourceType::kMainFrame)) {
+  if (request_.destination == network::mojom::RequestDestination::kDocument) {
     // Check for x-auto-login-header
     HeaderData header_data;
     std::string header_string;
diff --git a/android_webview/browser/network_service/aw_web_resource_request.cc b/android_webview/browser/network_service/aw_web_resource_request.cc
index c64093a..faaee21 100644
--- a/android_webview/browser/network_service/aw_web_resource_request.cc
+++ b/android_webview/browser/network_service/aw_web_resource_request.cc
@@ -9,7 +9,7 @@
 #include "net/http/http_request_headers.h"
 #include "net/http/http_response_headers.h"
 #include "services/network/public/cpp/resource_request.h"
-#include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h"
+#include "services/network/public/mojom/fetch_api.mojom.h"
 #include "ui/base/page_transition_types.h"
 
 using base::android::ConvertJavaStringToUTF16;
@@ -38,8 +38,8 @@
     const network::ResourceRequest& request)
     : url(request.url.spec()),
       method(request.method),
-      is_main_frame(request.resource_type ==
-                    static_cast<int>(blink::mojom::ResourceType::kMainFrame)),
+      is_main_frame(request.destination ==
+                    network::mojom::RequestDestination::kDocument),
       has_user_gesture(request.has_user_gesture),
       is_renderer_initiated(ui::PageTransitionIsWebTriggerable(
           static_cast<ui::PageTransition>(request.transition_type))) {
diff --git a/android_webview/browser/renderer_host/aw_render_view_host_ext.cc b/android_webview/browser/renderer_host/aw_render_view_host_ext.cc
index 2ddcd22..efa5e86 100644
--- a/android_webview/browser/renderer_host/aw_render_view_host_ext.cc
+++ b/android_webview/browser/renderer_host/aw_render_view_host_ext.cc
@@ -5,12 +5,15 @@
 #include "android_webview/browser/renderer_host/aw_render_view_host_ext.h"
 
 #include "android_webview/browser/aw_browser_context.h"
+#include "android_webview/browser/aw_contents_client_bridge.h"
 #include "android_webview/common/render_view_messages.h"
 #include "base/android/scoped_java_ref.h"
 #include "base/bind.h"
 #include "base/callback.h"
 #include "base/command_line.h"
 #include "base/logging.h"
+#include "content/public/browser/browser_task_traits.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/render_process_host.h"
@@ -20,6 +23,36 @@
 
 namespace android_webview {
 
+namespace {
+
+void ShouldOverrideUrlLoadingOnUI(
+    content::WebContents* web_contents,
+    const base::string16& url,
+    bool has_user_gesture,
+    bool is_redirect,
+    bool is_main_frame,
+    mojom::FrameHost::ShouldOverrideUrlLoadingCallback callback) {
+  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  bool ignore_navigation = false;
+  AwContentsClientBridge* client =
+      AwContentsClientBridge::FromWebContents(web_contents);
+  if (client) {
+    if (!client->ShouldOverrideUrlLoading(url, has_user_gesture, is_redirect,
+                                          is_main_frame, &ignore_navigation)) {
+      // If the shouldOverrideUrlLoading call caused a java exception we should
+      // always return immediately here!
+      return;
+    }
+  } else {
+    LOG(WARNING) << "Failed to find the associated render view host for url: "
+                 << url;
+  }
+
+  std::move(callback).Run(ignore_navigation);
+}
+
+}  // namespace
+
 AwRenderViewHostExt::AwRenderViewHostExt(AwRenderViewHostExtClient* client,
                                          content::WebContents* contents)
     : content::WebContentsObserver(contents),
@@ -173,4 +206,17 @@
   client_->OnWebLayoutContentsSizeChanged(contents_size);
 }
 
+void AwRenderViewHostExt::ShouldOverrideUrlLoading(
+    const base::string16& url,
+    bool has_user_gesture,
+    bool is_redirect,
+    bool is_main_frame,
+    ShouldOverrideUrlLoadingCallback callback) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  content::GetUIThreadTaskRunner({})->PostTask(
+      FROM_HERE, base::BindOnce(&ShouldOverrideUrlLoadingOnUI, web_contents(),
+                                url, has_user_gesture, is_redirect,
+                                is_main_frame, std::move(callback)));
+}
+
 }  // namespace android_webview
diff --git a/android_webview/browser/renderer_host/aw_render_view_host_ext.h b/android_webview/browser/renderer_host/aw_render_view_host_ext.h
index c9e366e..ce90800 100644
--- a/android_webview/browser/renderer_host/aw_render_view_host_ext.h
+++ b/android_webview/browser/renderer_host/aw_render_view_host_ext.h
@@ -89,6 +89,12 @@
   void UpdateHitTestData(
       android_webview::mojom::HitTestDataPtr hit_test_data) override;
   void ContentsSizeChanged(const gfx::Size& contents_size) override;
+  void ShouldOverrideUrlLoading(
+      const base::string16& url,
+      bool has_user_gesture,
+      bool is_redirect,
+      bool is_main_frame,
+      ShouldOverrideUrlLoadingCallback callback) override;
 
   bool IsRenderViewReady() const;
 
diff --git a/android_webview/common/mojom/frame.mojom b/android_webview/common/mojom/frame.mojom
index 6ccdb17..4e60e1f 100644
--- a/android_webview/common/mojom/frame.mojom
+++ b/android_webview/common/mojom/frame.mojom
@@ -122,4 +122,16 @@
 
   // Calls whenever the contents size (as seen by RenderView) is changed.
   ContentsSizeChanged(gfx.mojom.Size contents_size);
+
+  // Calls immediately before a top level navigation is initiated within Blink.
+  // There are some exlusions, the most important ones are it is not sent
+  // when creating a popup window, and not sent for application initiated
+  // navigations. See AwContentRendererClient::HandleNavigation for all
+  // cornercases. This is sent before updating the NavigationController state
+  // or creating a URLRequest for the main frame resource.
+  [Sync]
+  ShouldOverrideUrlLoading(mojo_base.mojom.String16 url,
+                           bool has_user_gesture, bool is_redirect,
+                           bool is_main_frame)
+      => (bool result);
 };
diff --git a/android_webview/common/render_view_messages.h b/android_webview/common/render_view_messages.h
index f52b6817..6ee0c3cc 100644
--- a/android_webview/common/render_view_messages.h
+++ b/android_webview/common/render_view_messages.h
@@ -24,20 +24,6 @@
 // RenderView messages
 // These are messages sent from the renderer to the browser process.
 
-// Sent immediately before a top level navigation is initiated within Blink.
-// There are some exlusions, the most important ones are it is not sent
-// when creating a popup window, and not sent for application initiated
-// navigations. See AwContentRendererClient::HandleNavigation for all
-// cornercases. This is sent before updating the NavigationController state
-// or creating a URLRequest for the main frame resource.
-IPC_SYNC_MESSAGE_CONTROL5_1(AwViewHostMsg_ShouldOverrideUrlLoading,
-                            int /* render_frame_id id */,
-                            base::string16 /* in - url */,
-                            bool /* in - has_user_gesture */,
-                            bool /* in - is_redirect */,
-                            bool /* in - is_main_frame */,
-                            bool /* out - result */)
-
 // Sent when a subframe is created.
 IPC_MESSAGE_CONTROL2(AwViewHostMsg_SubFrameCreated,
                      int /* parent_render_frame_id */,
diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc
index 35bbd895..8b232ac 100644
--- a/android_webview/renderer/aw_content_renderer_client.cc
+++ b/android_webview/renderer/aw_content_renderer_client.cc
@@ -35,6 +35,7 @@
 #include "content/public/renderer/render_thread.h"
 #include "content/public/renderer/render_view.h"
 #include "mojo/public/cpp/bindings/binder_map.h"
+#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
 #include "third_party/blink/public/platform/platform.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/platform/web_url.h"
@@ -137,10 +138,12 @@
   base::string16 url = request.Url().GetString().Utf16();
   bool has_user_gesture = request.HasUserGesture();
 
-  int render_frame_id = render_frame->GetRoutingID();
-  RenderThread::Get()->Send(new AwViewHostMsg_ShouldOverrideUrlLoading(
-      render_frame_id, url, has_user_gesture, is_redirect, is_main_frame,
-      &ignore_navigation));
+  mojo::AssociatedRemote<mojom::FrameHost> frame_host_remote;
+  render_frame->GetRemoteAssociatedInterfaces()->GetInterface(
+      &frame_host_remote);
+  frame_host_remote->ShouldOverrideUrlLoading(
+      url, has_user_gesture, is_redirect, is_main_frame, &ignore_navigation);
+
   return ignore_navigation;
 }
 
diff --git a/android_webview/renderer/aw_content_renderer_client.h b/android_webview/renderer/aw_content_renderer_client.h
index aaf3800..490483e 100644
--- a/android_webview/renderer/aw_content_renderer_client.h
+++ b/android_webview/renderer/aw_content_renderer_client.h
@@ -8,11 +8,13 @@
 #include <memory>
 #include <string>
 
+#include "android_webview/common/mojom/frame.mojom.h"
 #include "android_webview/renderer/aw_render_thread_observer.h"
 #include "base/compiler_specific.h"
 #include "base/memory/weak_ptr.h"
 #include "components/spellcheck/spellcheck_buildflags.h"
 #include "content/public/renderer/content_renderer_client.h"
+#include "mojo/public/cpp/bindings/associated_remote.h"
 #include "services/service_manager/public/cpp/local_interface_provider.h"
 #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
 
diff --git a/ash/capture_mode/capture_mode_controller.cc b/ash/capture_mode/capture_mode_controller.cc
index 3dd7580..e0ba962 100644
--- a/ash/capture_mode/capture_mode_controller.cc
+++ b/ash/capture_mode/capture_mode_controller.cc
@@ -74,6 +74,10 @@
 constexpr char k24HourTimeFmtStr[] = "%02d.%02d.%02d";
 constexpr char kAmPmTimeFmtStr[] = "%d.%02d.%02d";
 
+// Duration to clear the capture region selection from the previous session.
+constexpr base::TimeDelta kResetCaptureRegionDuration =
+    base::TimeDelta::FromMinutes(8);
+
 // The screenshot notification button index.
 enum ScreenshotNotificationButtonIndex {
   BUTTON_EDIT = 0,
@@ -320,6 +324,14 @@
   }
 
   RecordCaptureModeEntryType(entry_type);
+  // Reset the user capture region if enough time has passed as it can be
+  // annoying to still have the old capture region from the previous session
+  // long time ago.
+  if (!user_capture_region_.IsEmpty() &&
+      base::TimeTicks::Now() - last_capture_region_update_time_ >
+          kResetCaptureRegionDuration) {
+    SetUserCaptureRegion(gfx::Rect(), /*by_user=*/false);
+  }
   capture_mode_session_ = std::make_unique<CaptureModeSession>(this);
 }
 
@@ -328,6 +340,13 @@
   capture_mode_session_.reset();
 }
 
+void CaptureModeController::SetUserCaptureRegion(const gfx::Rect& region,
+                                                 bool by_user) {
+  user_capture_region_ = region;
+  if (!user_capture_region_.IsEmpty() && by_user)
+    last_capture_region_update_time_ = base::TimeTicks::Now();
+}
+
 void CaptureModeController::PerformCapture() {
   DCHECK(IsActive());
   const base::Optional<CaptureParams> capture_params = GetCaptureParams();
diff --git a/ash/capture_mode/capture_mode_controller.h b/ash/capture_mode/capture_mode_controller.h
index 4c5d505..84cccffe 100644
--- a/ash/capture_mode/capture_mode_controller.h
+++ b/ash/capture_mode/capture_mode_controller.h
@@ -63,9 +63,6 @@
     return capture_mode_session_.get();
   }
   gfx::Rect user_capture_region() const { return user_capture_region_; }
-  void set_user_capture_region(const gfx::Rect& region) {
-    user_capture_region_ = region;
-  }
   bool is_recording_in_progress() const { return is_recording_in_progress_; }
 
   // Returns true if a capture mode session is currently active.
@@ -83,6 +80,10 @@
   // Stops an existing capture session.
   void Stop();
 
+  // Sets the user capture region. If it's non-empty and changed by the user,
+  // update |last_capture_region_update_time_|.
+  void SetUserCaptureRegion(const gfx::Rect& region, bool by_user);
+
   // Called only while a capture session is in progress to perform the actual
   // capture depending on the current selected |source_| and |type_|, and ends
   // the capture session.
@@ -297,6 +298,12 @@
   // collection.
   base::TimeTicks recording_start_time_;
 
+  // The last time the user sets a non-empty capture region. It will be used to
+  // clear the user capture region from previous capture sessions if 8+ minutes
+  // has passed since the last time the user changes the capture region when the
+  // new capture session starts .
+  base::TimeTicks last_capture_region_update_time_;
+
   base::WeakPtrFactory<CaptureModeController> weak_ptr_factory_{this};
 };
 
diff --git a/ash/capture_mode/capture_mode_session.cc b/ash/capture_mode/capture_mode_session.cc
index e3e598d..d8804f8 100644
--- a/ash/capture_mode/capture_mode_session.cc
+++ b/ash/capture_mode/capture_mode_session.cc
@@ -993,7 +993,7 @@
     // If the point is outside the capture region and not on the capture bar,
     // restart to the select phase.
     is_selecting_region_ = true;
-    UpdateCaptureRegion(gfx::Rect(), /*is_resizing=*/true);
+    UpdateCaptureRegion(gfx::Rect(), /*is_resizing=*/true, /*by_user=*/true);
     num_capture_region_adjusted_ = 0;
     return;
   }
@@ -1026,7 +1026,7 @@
   if (is_selecting_region_) {
     UpdateCaptureRegion(
         GetRectEnclosingPoints({initial_location_in_root_, location_in_root}),
-        /*is_resizing=*/true);
+        /*is_resizing=*/true, /*by_user=*/true);
     return;
   }
 
@@ -1040,7 +1040,8 @@
     gfx::Rect new_capture_region = controller_->user_capture_region();
     new_capture_region.Offset(location_in_root - previous_location_in_root);
     new_capture_region.AdjustToFit(current_root_->bounds());
-    UpdateCaptureRegion(new_capture_region, /*is_resizing=*/false);
+    UpdateCaptureRegion(new_capture_region, /*is_resizing=*/false,
+                        /*by_user=*/true);
     return;
   }
 
@@ -1064,7 +1065,8 @@
     resizing_point.set_x(points.front().x());
   }
   points.push_back(resizing_point);
-  UpdateCaptureRegion(GetRectEnclosingPoints(points), /*is_resizing=*/true);
+  UpdateCaptureRegion(GetRectEnclosingPoints(points), /*is_resizing=*/true,
+                      /*by_user=*/true);
   MaybeShowMagnifierGlassAtPoint(location_in_root);
 }
 
@@ -1086,7 +1088,8 @@
 
 void CaptureModeSession::UpdateCaptureRegion(
     const gfx::Rect& new_capture_region,
-    bool is_resizing) {
+    bool is_resizing,
+    bool by_user) {
   const gfx::Rect old_capture_region = controller_->user_capture_region();
   if (old_capture_region == new_capture_region)
     return;
@@ -1099,7 +1102,7 @@
   damage_region.Inset(gfx::Insets(-kDamageInsetDp));
   layer()->SchedulePaint(damage_region);
 
-  controller_->set_user_capture_region(new_capture_region);
+  controller_->SetUserCaptureRegion(new_capture_region, by_user);
   UpdateDimensionsLabelWidget(is_resizing);
   UpdateCaptureLabelWidget();
 }
@@ -1406,7 +1409,7 @@
 
   // Start with a new region when we switch displays.
   is_selecting_region_ = true;
-  UpdateCaptureRegion(gfx::Rect(), /*is_resizing=*/false);
+  UpdateCaptureRegion(gfx::Rect(), /*is_resizing=*/false, /*by_user=*/false);
 
   UpdateRootWindowDimmers();
 }
@@ -1522,7 +1525,7 @@
 void CaptureModeSession::ClampCaptureRegionToRootWindowSize() {
   gfx::Rect new_capture_region = controller_->user_capture_region();
   new_capture_region.AdjustToFit(current_root_->bounds());
-  controller_->set_user_capture_region(new_capture_region);
+  controller_->SetUserCaptureRegion(new_capture_region, /*by_user=*/false);
 }
 
 void CaptureModeSession::EndSelection(bool is_event_on_capture_bar,
@@ -1558,7 +1561,8 @@
   gfx::Rect default_capture_region = current_root_->bounds();
   default_capture_region.ClampToCenteredSize(gfx::ScaleToCeiledSize(
       default_capture_region.size(), kRegionDefaultRatio));
-  UpdateCaptureRegion(default_capture_region, /*is_resizing=*/false);
+  UpdateCaptureRegion(default_capture_region, /*is_resizing=*/false,
+                      /*by_user=*/true);
 }
 
 void CaptureModeSession::UpdateRegionHorizontally(bool left,
@@ -1596,7 +1600,8 @@
     ClipRectToFit(&new_capture_region, current_root_->bounds());
   }
 
-  UpdateCaptureRegion(new_capture_region, /*is_resizing=*/false);
+  UpdateCaptureRegion(new_capture_region, /*is_resizing=*/false,
+                      /*by_user=*/true);
 }
 
 void CaptureModeSession::UpdateRegionVertically(bool up, bool is_shift_down) {
@@ -1636,7 +1641,8 @@
     ClipRectToFit(&new_capture_region, current_root_->bounds());
   }
 
-  UpdateCaptureRegion(new_capture_region, /*is_resizing=*/false);
+  UpdateCaptureRegion(new_capture_region, /*is_resizing=*/false,
+                      /*by_user=*/true);
 }
 
 }  // namespace ash
diff --git a/ash/capture_mode/capture_mode_session.h b/ash/capture_mode/capture_mode_session.h
index 3097f23..7c8f42b 100644
--- a/ash/capture_mode/capture_mode_session.h
+++ b/ash/capture_mode/capture_mode_session.h
@@ -137,9 +137,11 @@
                               bool region_intersects_capture_bar);
 
   // Updates the capture region and the capture region widgets depending on the
-  // value of |is_resizing|.
+  // value of |is_resizing|. |by_user| is true if the capture region is changed
+  // by user.
   void UpdateCaptureRegion(const gfx::Rect& new_capture_region,
-                           bool is_resizing);
+                           bool is_resizing,
+                           bool by_user);
 
   // Updates the dimensions label widget shown during a region capture session.
   // If not |is_resizing|, not a region capture session or the capture region is
diff --git a/ash/capture_mode/capture_mode_test_api.cc b/ash/capture_mode/capture_mode_test_api.cc
index 82bed56..6f93d11 100644
--- a/ash/capture_mode/capture_mode_test_api.cc
+++ b/ash/capture_mode/capture_mode_test_api.cc
@@ -43,7 +43,7 @@
 }
 
 void CaptureModeTestApi::SetUserSelectedRegion(const gfx::Rect& region) {
-  controller_->set_user_capture_region(region);
+  controller_->SetUserCaptureRegion(region, /*by_user=*/true);
 }
 
 void CaptureModeTestApi::PerformCapture() {
diff --git a/ash/capture_mode/capture_mode_unittests.cc b/ash/capture_mode/capture_mode_unittests.cc
index 92ba5aa..427fda1 100644
--- a/ash/capture_mode/capture_mode_unittests.cc
+++ b/ash/capture_mode/capture_mode_unittests.cc
@@ -2059,6 +2059,35 @@
   histogram_tester.ExpectBucketCount(kConsecutiveScreenshotsHistogram, 2, 1);
 }
 
+// Tests that the user capture region will be cleared up after a period of time.
+TEST_F(CaptureModeMockTimeTest, ClearUserCaptureRegionBetweenSessions) {
+  UpdateDisplay("800x800");
+  auto* controller = StartImageRegionCapture();
+  EXPECT_EQ(gfx::Rect(), controller->user_capture_region());
+
+  const gfx::Rect capture_region(100, 100, 600, 600);
+  SelectRegion(capture_region);
+  EXPECT_EQ(capture_region, controller->user_capture_region());
+  controller->PerformCapture();
+  EXPECT_EQ(capture_region, controller->user_capture_region());
+
+  // Start region image capture again shortly after the previous capture
+  // session, we should still be able to reuse the previous capture region.
+  task_environment()->FastForwardBy(base::TimeDelta::FromMinutes(1));
+  StartImageRegionCapture();
+  EXPECT_EQ(capture_region, controller->user_capture_region());
+  auto* event_generator = GetEventGenerator();
+  // Even if the capture is cancelled, we still remember the capture region.
+  SendKey(ui::VKEY_ESCAPE, event_generator);
+  EXPECT_EQ(capture_region, controller->user_capture_region());
+
+  // Wait for 8 second and then start region image capture again. We should have
+  // forgot the previous capture region.
+  task_environment()->FastForwardBy(base::TimeDelta::FromMinutes(8));
+  StartImageRegionCapture();
+  EXPECT_EQ(gfx::Rect(), controller->user_capture_region());
+}
+
 // Tests that in Region mode, the capture bar hides and shows itself correctly.
 TEST_F(CaptureModeTest, CaptureBarOpacity) {
   UpdateDisplay("800x800");
diff --git a/base/i18n/file_util_icu.cc b/base/i18n/file_util_icu.cc
index c744468..85962b5 100644
--- a/base/i18n/file_util_icu.cc
+++ b/base/i18n/file_util_icu.cc
@@ -8,8 +8,6 @@
 
 #include <stdint.h>
 
-#include <memory>
-
 #include "base/check.h"
 #include "base/files/file_path.h"
 #include "base/i18n/icu_string_conversions.h"
@@ -37,33 +35,32 @@
     return Singleton<IllegalCharacters>::get();
   }
 
-  bool DisallowedEverywhere(UChar32 ucs4) const {
-    return !!illegal_anywhere_->contains(ucs4);
+  bool IsDisallowedEverywhere(UChar32 ucs4) const {
+    return !!illegal_anywhere_.contains(ucs4);
   }
 
-  bool DisallowedLeadingOrTrailing(UChar32 ucs4) const {
-    return !!illegal_at_ends_->contains(ucs4);
+  bool IsDisallowedLeadingOrTrailing(UChar32 ucs4) const {
+    return !!illegal_at_ends_.contains(ucs4);
   }
 
   bool IsAllowedName(const string16& s) const {
-    return s.empty() || (!!illegal_anywhere_->containsNone(
+    return s.empty() || (!!illegal_anywhere_.containsNone(
                              icu::UnicodeString(s.c_str(), s.size())) &&
-                         !illegal_at_ends_->contains(*s.begin()) &&
-                         !illegal_at_ends_->contains(*s.rbegin()));
+                         !illegal_at_ends_.contains(*s.begin()) &&
+                         !illegal_at_ends_.contains(*s.rbegin()));
   }
 
  private:
-  friend class Singleton<IllegalCharacters>;
   friend struct DefaultSingletonTraits<IllegalCharacters>;
 
   IllegalCharacters();
   ~IllegalCharacters() = default;
 
-  // set of characters considered invalid anywhere inside a filename.
-  std::unique_ptr<icu::UnicodeSet> illegal_anywhere_;
+  // Set of characters considered invalid anywhere inside a filename.
+  icu::UnicodeSet illegal_anywhere_;
 
-  // set of characters considered invalid at either end of a filename.
-  std::unique_ptr<icu::UnicodeSet> illegal_at_ends_;
+  // Set of characters considered invalid at either end of a filename.
+  icu::UnicodeSet illegal_at_ends_;
 };
 
 IllegalCharacters::IllegalCharacters() {
@@ -71,32 +68,32 @@
   UErrorCode ends_status = U_ZERO_ERROR;
   // Control characters, formatting characters, non-characters, path separators,
   // and some printable ASCII characters regarded as dangerous ('"*/:<>?\\').
-  // See  http://blogs.msdn.com/michkap/archive/2006/11/03/941420.aspx
+  // See http://blogs.msdn.com/michkap/archive/2006/11/03/941420.aspx
   // and http://msdn2.microsoft.com/en-us/library/Aa365247.aspx
   // Note that code points in the "Other, Format" (Cf) category are ignored on
   // HFS+ despite the ZERO_WIDTH_JOINER and ZERO_WIDTH_NON-JOINER being
   // legitimate in Arabic and some S/SE Asian scripts. In addition tilde (~) is
   // also excluded due to the possibility of interacting poorly with short
   // filenames on VFAT. (Related to CVE-2014-9390)
-  illegal_anywhere_.reset(new icu::UnicodeSet(
-      UNICODE_STRING_SIMPLE("[[\"~*/:<>?\\\\|][:Cc:][:Cf:]]"),
-      everywhere_status));
-  illegal_at_ends_.reset(new icu::UnicodeSet(
-      UNICODE_STRING_SIMPLE("[[:WSpace:][.]]"), ends_status));
+  illegal_anywhere_ =
+      icu::UnicodeSet(UNICODE_STRING_SIMPLE("[[\"~*/:<>?\\\\|][:Cc:][:Cf:]]"),
+                      everywhere_status);
+  illegal_at_ends_ =
+      icu::UnicodeSet(UNICODE_STRING_SIMPLE("[[:WSpace:][.]]"), ends_status);
   DCHECK(U_SUCCESS(everywhere_status));
   DCHECK(U_SUCCESS(ends_status));
 
   // Add non-characters. If this becomes a performance bottleneck by
   // any chance, do not add these to |set| and change IsFilenameLegal()
-  // to check |ucs4 & 0xFFFEu == 0xFFFEu|, in addiition to calling
+  // to check |ucs4 & 0xFFFEu == 0xFFFEu|, in addition to calling
   // IsAllowedName().
-  illegal_anywhere_->add(0xFDD0, 0xFDEF);
+  illegal_anywhere_.add(0xFDD0, 0xFDEF);
   for (int i = 0; i <= 0x10; ++i) {
     int plane_base = 0x10000 * i;
-    illegal_anywhere_->add(plane_base + 0xFFFE, plane_base + 0xFFFF);
+    illegal_anywhere_.add(plane_base + 0xFFFE, plane_base + 0xFFFF);
   }
-  illegal_anywhere_->freeze();
-  illegal_at_ends_->freeze();
+  illegal_anywhere_.freeze();
+  illegal_at_ends_.freeze();
 }
 
 }  // namespace
@@ -109,13 +106,13 @@
                                     char replace_char) {
   IllegalCharacters* illegal = IllegalCharacters::GetInstance();
 
-  DCHECK(!(illegal->DisallowedEverywhere(replace_char)));
-  DCHECK(!(illegal->DisallowedLeadingOrTrailing(replace_char)));
+  DCHECK(!(illegal->IsDisallowedEverywhere(replace_char)));
+  DCHECK(!(illegal->IsDisallowedLeadingOrTrailing(replace_char)));
 
   int cursor = 0;  // The ICU macros expect an int.
   while (cursor < static_cast<int>(file_name->size())) {
     int char_begin = cursor;
-    uint32_t code_point;
+    UChar32 code_point;
 #if defined(OS_WIN)
     // Windows uses UTF-16 encoding for filenames.
     U16_NEXT(file_name->data(), cursor, static_cast<int>(file_name->length()),
@@ -130,9 +127,9 @@
 #error Unsupported platform
 #endif
 
-    if (illegal->DisallowedEverywhere(code_point) ||
+    if (illegal->IsDisallowedEverywhere(code_point) ||
         ((char_begin == 0 || cursor == static_cast<int>(file_name->length())) &&
-         illegal->DisallowedLeadingOrTrailing(code_point))) {
+         illegal->IsDisallowedLeadingOrTrailing(code_point))) {
       file_name->replace(char_begin, cursor - char_begin, 1, replace_char);
       // We just made the potentially multi-byte/word char into one that only
       // takes one byte/word, so need to adjust the cursor to point to the next
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1
index d1b8ddc..81b433cf 100644
--- a/build/fuchsia/linux.sdk.sha1
+++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@
-0.20201217.2.1
+0.20201219.1.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1
index d1b8ddc..81b433cf 100644
--- a/build/fuchsia/mac.sdk.sha1
+++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@
-0.20201217.2.1
+0.20201219.1.1
diff --git a/cc/paint/paint_image.h b/cc/paint/paint_image.h
index 256e0fd..ab1a18c 100644
--- a/cc/paint/paint_image.h
+++ b/cc/paint/paint_image.h
@@ -21,6 +21,10 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 
+namespace blink {
+class VideoFrame;
+}
+
 namespace cc {
 
 class PaintImageGenerator;
@@ -239,7 +243,6 @@
   gpu::Mailbox GetMailbox() const;
 
   Id stable_id() const { return id_; }
-  const sk_sp<SkImage>& GetSkImage() const;
   SkImageInfo GetSkImageInfo() const;
   AnimationType animation_type() const { return animation_type_; }
   CompletionState completion_state() const { return completion_state_; }
@@ -324,6 +327,12 @@
   friend class DrawImageRectOp;
   friend class DrawImageOp;
 
+  // TODO(crbug.com/1031051): Remove these once GetSkImage()
+  // is fully removed.
+  friend class ImagePaintFilter;
+  friend class PaintShader;
+  friend class blink::VideoFrame;
+
   bool DecodeFromGenerator(void* memory,
                            SkImageInfo* info,
                            sk_sp<SkColorSpace> color_space,
@@ -339,6 +348,10 @@
   // Only supported in non-OOPR contexts by friend callers.
   sk_sp<SkImage> GetAcceleratedSkImage() const;
 
+  // GetSkImage() is being deprecated, see crbug.com/1031051.
+  // Prefer using GetSwSkImage() or GetSkImageInfo().
+  const sk_sp<SkImage>& GetSkImage() const;
+
   sk_sp<SkImage> sk_image_;
   sk_sp<PaintRecord> paint_record_;
   gfx::Rect paint_record_rect_;
diff --git a/chrome/VERSION b/chrome/VERSION
index 776c3c7..45e4f4a5 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=89
 MINOR=0
-BUILD=4360
+BUILD=4361
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index e940751..66c3513 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -2196,6 +2196,7 @@
     "//chrome/browser/flags:java",
     "//chrome/browser/preferences:java",
     "//chrome/browser/util:java",
+    "//chrome/browser/version:java",
     "//components/crash/android:java",
     "//components/embedder_support/android:application_java",
     "//components/media_router/browser/android:cast_options_provider_java",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitChromeApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitChromeApplication.java
index a08a9a8..1cfa929 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitChromeApplication.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitChromeApplication.java
@@ -25,8 +25,12 @@
 import org.chromium.base.TraceEvent;
 import org.chromium.base.compat.ApiHelperForO;
 import org.chromium.base.metrics.RecordHistogram;
+import org.chromium.base.task.PostTask;
+import org.chromium.base.task.TaskTraits;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
+import org.chromium.chrome.browser.version.ChromeVersionInfo;
+import org.chromium.content_public.browser.BrowserStartupController;
 
 import java.lang.reflect.Field;
 
@@ -182,38 +186,59 @@
      * compile if necessary.
      */
     private void applyDexCompileWorkaround() {
-        // This bug only happens in OMR1.
-        if (Build.VERSION.SDK_INT != Build.VERSION_CODES.O_MR1) {
+        // This bug only happens in OMR1. Skip the workaround on local builds to avoid affecting
+        // perf bots.
+        if (Build.VERSION.SDK_INT != Build.VERSION_CODES.O_MR1
+                || ChromeVersionInfo.isLocalBuild()) {
             return;
         }
 
-        new Thread(() -> {
-            try {
-                // If the app has just been updated, it will be compiled with quicken. The next time
-                // bg-dexopt-job runs it will break the optimized dex for splits. If we force
-                // compile now, then bg-dexopt-job won't mess up the splits, and we save the user a
-                // slow startup.
-                if (needsDexCompileAfterUpdate()) {
-                    performDexCompile();
-                    return;
-                }
+        // Wait until startup completes so this doesn't slow down early startup or mess with
+        // compiled dex files before they get loaded initially.
+        // TODO(crbug.com/1159608): Determine if this works good enough, or if more needs to be done
+        // to avoid slowing startup.
+        BrowserStartupController.getInstance().addStartupCompletedObserver(
+                new BrowserStartupController.StartupCallback() {
+                    @Override
+                    public void onSuccess() {
+                        // BEST_EFFORT will only affect when the task runs, the dexopt will run with
+                        // normal priority (but in a separate process, due to using Runtime.exec()).
+                        PostTask.postTask(TaskTraits.BEST_EFFORT_MAY_BLOCK, () -> {
+                            try {
+                                // If the app has just been updated, it will be compiled with
+                                // quicken. The next time bg-dexopt-job runs it will break the
+                                // optimized dex for splits. If we force compile now, then
+                                // bg-dexopt-job won't mess up the splits, and we save the user a
+                                // slow startup.
+                                if (needsDexCompileAfterUpdate()) {
+                                    performDexCompile();
+                                    return;
+                                }
 
-                // Make sure all splits are compiled correclty, and if not force a compile.
-                String[] splitNames = ApiHelperForO.getSplitNames(getApplicationInfo());
-                for (int i = 0; i < splitNames.length; i++) {
-                    // Ignore config splits like "config.en".
-                    if (splitNames[i].contains(".")) {
-                        continue;
+                                // Make sure all splits are compiled correclty, and if not force a
+                                // compile.
+                                String[] splitNames =
+                                        ApiHelperForO.getSplitNames(getApplicationInfo());
+                                for (int i = 0; i < splitNames.length; i++) {
+                                    // Ignore config splits like "config.en".
+                                    if (splitNames[i].contains(".")) {
+                                        continue;
+                                    }
+                                    if (DexFile.isDexOptNeeded(
+                                                getApplicationInfo().splitSourceDirs[i])) {
+                                        performDexCompile();
+                                        return;
+                                    }
+                                }
+                            } catch (Exception e) {
+                                Log.e(TAG, "Error compiling dex.", e);
+                            }
+                        });
                     }
-                    if (DexFile.isDexOptNeeded(getApplicationInfo().splitSourceDirs[i])) {
-                        performDexCompile();
-                        return;
-                    }
-                }
-            } catch (Exception e) {
-                Log.e(TAG, "Error compiling dex.", e);
-            }
-        }).start();
+
+                    @Override
+                    public void onFailure() {}
+                });
     }
 
     /** Returns whether the dex has been compiled since the last app update. */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java
index 4d6c56b..8b8eea82 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java
@@ -49,6 +49,7 @@
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
 import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.components.browser_ui.site_settings.SiteSettingsFeatureList;
 import org.chromium.components.browser_ui.site_settings.WebsitePreferenceBridge;
 import org.chromium.components.browser_ui.site_settings.WebsitePreferenceBridgeJni;
 import org.chromium.components.content_settings.ContentSettingValues;
@@ -381,6 +382,25 @@
     }
 
     /**
+     * Tests the permissions page of the new PageInfo UI with permissions and actionable flag
+     * enabled.
+     */
+    @Test
+    @MediumTest
+    @Feature({"RenderTest"})
+    @Features.EnableFeatures(
+            {PageInfoFeatureList.PAGE_INFO_V2, SiteSettingsFeatureList.ACTIONABLE_CONTENT_SETTINGS})
+    public void
+    testShowPermissionsActionableSubpage() throws IOException {
+        mActivityTestRule.startMainActivityOnBlankPage();
+        addSomePermissions(mTestServerRule.getServer().getURL("/"));
+        loadUrlAndOpenPageInfo(mTestServerRule.getServer().getURL(sSimpleHtml));
+        onView(withId(R.id.page_info_permissions_row)).perform(click());
+        onViewWaiting(allOf(withText("Control this site's access to your device"), isDisplayed()));
+        mRenderTestRule.render(getPageInfoView(), "PageInfo_PermissionsSubpage_Actionable");
+    }
+
+    /**
      * Tests the cookies page of the new PageInfo UI.
      */
     @Test
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArAnchorsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArAnchorsTest.java
index 8cb33e3..f69887bf 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArAnchorsTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArAnchorsTest.java
@@ -23,6 +23,7 @@
 import org.chromium.base.test.params.ParameterSet;
 import org.chromium.base.test.params.ParameterizedRunner;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.vr.rules.ArPlaybackFile;
@@ -82,6 +83,7 @@
      */
     @Test
     @MediumTest
+    @DisabledTest(message = "https://crbug.com/1158528")
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
     @ArPlaybackFile("chrome/test/data/xr/ar_playback_datasets/floor_session_12s_30fps.mp4")
     public void testFreeFloatingAnchorSucceeds() {
@@ -98,6 +100,7 @@
      */
     @Test
     @LargeTest
+    @DisabledTest(message = "https://crbug.com/1158528")
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
     @ArPlaybackFile(
             "chrome/test/data/xr/ar_playback_datasets/floor_session_with_tracking_loss_37s_30fps.mp4")
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArCameraAccessTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArCameraAccessTest.java
index d1fcf67..7f7a7cf 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArCameraAccessTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArCameraAccessTest.java
@@ -69,6 +69,7 @@
      */
     @Test
     @MediumTest
+    @DisabledTest(message = "https://crbug.com/1158528")
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
     @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
             "enable-features=WebXRIncubations,LogJsConsoleMessages"})
@@ -110,6 +111,7 @@
      */
     @Test
     @MediumTest
+    @DisabledTest(message = "https://crbug.com/1158528")
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
     @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
             "enable-features=WebXRIncubations,LogJsConsoleMessages"})
@@ -181,6 +183,7 @@
      */
     @Test
     @MediumTest
+    @DisabledTest(message = "https://crbug.com/1158528")
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
     @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
             "enable-features=WebXRIncubations,LogJsConsoleMessages"})
@@ -216,4 +219,4 @@
         mWebXrArTestFramework.waitOnJavaScriptStep();
         mWebXrArTestFramework.endTest();
     }
-}
\ No newline at end of file
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArHitTestTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArHitTestTest.java
index 622f54a..0e5e97cf 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArHitTestTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/WebXrArHitTestTest.java
@@ -21,6 +21,7 @@
 import org.chromium.base.test.params.ParameterSet;
 import org.chromium.base.test.params.ParameterizedRunner;
 import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.MinAndroidSdkLevel;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.vr.rules.ArPlaybackFile;
@@ -65,6 +66,7 @@
      */
     @Test
     @MediumTest
+    @DisabledTest(message = "https://crbug.com/1158528")
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
     @ArPlaybackFile("chrome/test/data/xr/ar_playback_datasets/floor_session_12s_30fps.mp4")
     public void testHitTestSucceedsWithPlane() {
@@ -81,6 +83,7 @@
      */
     @Test
     @MediumTest
+    @DisabledTest(message = "https://crbug.com/1158528")
     @XrActivityRestriction({XrActivityRestriction.SupportedActivity.ALL})
     @ArPlaybackFile("chrome/test/data/xr/ar_playback_datasets/floor_session_12s_30fps.mp4")
     public void testHitTestResultsAvailableInSubsequentFrame() {
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 2d71a60..5a0b7f66 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -10251,6 +10251,9 @@
       <message name="IDS_FONT_ACCESS_CHOOSER_CANCEL_BUTTON_TEXT" desc="Label on the button that closes the chooser popup without selecting an option.">
         Cancel
       </message>
+      <message name="IDS_FONT_ACCESS_CHOOSER_SELECT_ALL_CHECKBOX_TEXT" desc="Label for the checkbox that allows the selection of all fonts.">
+        Select all fonts
+      </message>
     </if>
 
     <!-- Chrome IME API activated bubble. -->
diff --git a/chrome/app/generated_resources_grd/IDS_FONT_ACCESS_CHOOSER_SELECT_ALL_CHECKBOX_TEXT.png.sha1 b/chrome/app/generated_resources_grd/IDS_FONT_ACCESS_CHOOSER_SELECT_ALL_CHECKBOX_TEXT.png.sha1
new file mode 100644
index 0000000..e69ba210
--- /dev/null
+++ b/chrome/app/generated_resources_grd/IDS_FONT_ACCESS_CHOOSER_SELECT_ALL_CHECKBOX_TEXT.png.sha1
@@ -0,0 +1 @@
+310ac15fc23be1a1d0496c2cf1d71dfcaa17797e
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp
index a13a5fd..13eca4a 100644
--- a/chrome/app/os_settings_strings.grdp
+++ b/chrome/app/os_settings_strings.grdp
@@ -2461,6 +2461,9 @@
   <message name="IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_SECTION_TITLE" desc="The title of the Phone Hub section on the settings page.">
     Phone Hub
   </message>
+  <message name="IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_LEARN_MORE_LABEL" desc="Accessibility label (used by screen readers, not shown in UI) for a link that leads to a page with more information about the 'Phone Hub' feature.">
+    Phone Hub, Learn More
+  </message>
   <message name="IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_NOTIFICATIONS_SECTION_TITLE" desc="The title of the Phone Hub Notifications section on the settings page.">
     Notifications
   </message>
@@ -2476,6 +2479,12 @@
   <message name="IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_TASK_CONTINUATION_SUMMARY" desc="Description of for the 'Phone Hub Task Continuation' setting. This feature lets users resume in-app actions and chrome tabs that are open on a connected Android phone from Chrome OS devices.">
     View recent Chrome tabs from your phone
   </message>
+  <message name="IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_TASK_CONTINUATION_DISABLED_SUMMARY" desc="Description of for the 'Phone Hub Task Continuation' setting when Chrome sync is not enabled. This feature lets users resume in-app actions and chrome tabs that are open on a connected Android phone from Chrome OS devices.">
+    Turn on<ph name="LINK1_BEGIN">&lt;a id="chromeSyncLink"&gt;</ph>Chrome Sync<ph name="LINK1_END">&lt;/a&gt;</ph> to view recent Chrome tabs.<ph name="LINK2_BEGIN">&lt;a target="_blank" id="learnMoreLink" href="$1<ex>https://google.com/</ex>"&gt;</ph>Learn More<ph name="LINK2_END">&lt;/a&gt;</ph>
+  </message>
+  <message name="IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_TASK_CONTINUATION_SYNC_LABEL" desc="Accessibility label (used by screen readers, not shown in UI) for a link that leads to the Chrome Sync toggle that needs to be enabled as a prerequisite for the 'Phone Hub Task Continuation' feature to be enabled. This feature lets users resume chrome tabs that are open on a connected Android phone from Chrome OS devices.">
+    Turn on Chrome Sync to view recent Chrome tabs from your phone
+  </message>
   <message name="IDS_SETTINGS_MULTIDEVICE_NOTIFICATION_ACCESS_SETUP_DIALOG_ACK_TITLE" desc="The title of the dialog containing the Phone Hub notification opt-in flow shown when the Phone Hub 'Notifications' toggle is switched on.">
     Turn on notifications on your phone
   </message>
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_LEARN_MORE_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_LEARN_MORE_LABEL.png.sha1
new file mode 100644
index 0000000..e87d1d2d
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_LEARN_MORE_LABEL.png.sha1
@@ -0,0 +1 @@
+fc72fe3b2a3da97c50e316807509a7724ea69896
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_TASK_CONTINUATION_DISABLED_SUMMARY.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_TASK_CONTINUATION_DISABLED_SUMMARY.png.sha1
new file mode 100644
index 0000000..4d36365
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_TASK_CONTINUATION_DISABLED_SUMMARY.png.sha1
@@ -0,0 +1 @@
+2720eadd205fbd423bcf77978c03da7c5e99bb14
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_TASK_CONTINUATION_SYNC_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_TASK_CONTINUATION_SYNC_LABEL.png.sha1
new file mode 100644
index 0000000..56fd531
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_TASK_CONTINUATION_SYNC_LABEL.png.sha1
@@ -0,0 +1 @@
+b92b8a4fdaf732eb2a00eb2e1cfe44809cc03a37
\ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 25f250c..6c85d11 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -2389,7 +2389,7 @@
 constexpr char kAssistantTimersV2InternalName[] = "enable-assistant-timers-v2";
 #endif  // BUILDFLAG(IS_CHROMEOS_ASH)
 
-#if !defined(OS_WIN) && !defined(OS_FUCHSIA)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
 const FeatureEntry::FeatureParam
     kSendWebUIJavaScriptErrorReportsVariationSendToStaging[] = {
         {features::kSendWebUIJavaScriptErrorReportsSendToProductionVariation,
@@ -2558,11 +2558,11 @@
      flag_descriptions::kWebrtcPipeWireCapturerDescription, kOsLinux,
      FEATURE_VALUE_TYPE(features::kWebRtcPipeWireCapturer)},
 #endif  // defined(WEBRTC_USE_PIPEWIRE)
-#if !defined(OS_WIN) && !defined(OS_FUCHSIA)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
     {"send-webui-javascript-error-reports",
      flag_descriptions::kSendWebUIJavaScriptErrorReportsName,
      flag_descriptions::kSendWebUIJavaScriptErrorReportsDescription,
-     kOsLinux | kOsCrOS | kOsAndroid,
+     kOsLinux | kOsCrOS,
      FEATURE_WITH_PARAMS_VALUE_TYPE(
          features::kSendWebUIJavaScriptErrorReports,
          kSendWebUIJavaScriptErrorReportsVariations,
@@ -6995,6 +6995,12 @@
      FEATURE_VALUE_TYPE(chrome_pdf::features::kPdfXfaSupport)},
 #endif  // BUILDFLAG(ENABLE_PDF)
 
+#if defined(OS_ANDROID)
+    {"actionable-content-settings",
+     flag_descriptions::kActionableContentSettingsName,
+     flag_descriptions::kActionableContentSettingsDescription, kOsAndroid,
+     FEATURE_VALUE_TYPE(browser_ui::kActionableContentSettings)},
+#endif
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
     // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag
     // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/bad_message.cc b/chrome/browser/bad_message.cc
index f87d5adf..1d57bad 100644
--- a/chrome/browser/bad_message.cc
+++ b/chrome/browser/bad_message.cc
@@ -14,6 +14,8 @@
 namespace {
 
 void LogBadMessage(BadMessageReason reason) {
+  TRACE_EVENT_INSTANT1("ipc,security", "chrome::ReceivedBadMessage",
+                       TRACE_EVENT_SCOPE_THREAD, "reason", reason);
   LOG(ERROR) << "Terminating renderer for bad IPC message, reason " << reason;
   base::UmaHistogramSparse("Stability.BadMessageTerminated.Chrome", reason);
 }
diff --git a/chrome/browser/chooser_controller/chooser_controller.cc b/chrome/browser/chooser_controller/chooser_controller.cc
index d277831..df95777 100644
--- a/chrome/browser/chooser_controller/chooser_controller.cc
+++ b/chrome/browser/chooser_controller/chooser_controller.cc
@@ -84,10 +84,18 @@
   return false;
 }
 
+bool ChooserController::ShouldShowSelectAllCheckbox() const {
+  return false;
+}
+
 base::string16 ChooserController::GetCancelButtonLabel() const {
   return l10n_util::GetStringUTF16(IDS_DEVICE_CHOOSER_CANCEL_BUTTON_TEXT);
 }
 
+base::string16 ChooserController::GetSelectAllCheckboxLabel() const {
+  return base::string16();
+}
+
 bool ChooserController::BothButtonsAlwaysEnabled() const {
   return false;
 }
diff --git a/chrome/browser/chooser_controller/chooser_controller.h b/chrome/browser/chooser_controller/chooser_controller.h
index 304514df..119ee81 100644
--- a/chrome/browser/chooser_controller/chooser_controller.h
+++ b/chrome/browser/chooser_controller/chooser_controller.h
@@ -79,6 +79,9 @@
   // Returns whether the chooser allows multiple items to be selected.
   virtual bool AllowMultipleSelection() const;
 
+  // Returns whether the chooser needs to show a select-all checkbox.
+  virtual bool ShouldShowSelectAllCheckbox() const;
+
   // Returns the text to be displayed in the chooser when there are no options.
   virtual base::string16 GetNoOptionsText() const = 0;
 
@@ -88,6 +91,9 @@
   // Returns the label for Cancel button.
   virtual base::string16 GetCancelButtonLabel() const;
 
+  // Returns the label for SelectAll checkbox.
+  virtual base::string16 GetSelectAllCheckboxLabel() const;
+
   // Returns whether both OK and Cancel buttons are enabled.
   //
   // For chooser used in Web APIs such as WebBluetooth, WebUSB,
diff --git a/chrome/browser/external_protocol/external_protocol_handler.cc b/chrome/browser/external_protocol/external_protocol_handler.cc
index 98ca27c..94f799b 100644
--- a/chrome/browser/external_protocol/external_protocol_handler.cc
+++ b/chrome/browser/external_protocol/external_protocol_handler.cc
@@ -41,9 +41,11 @@
 
 namespace {
 
-// Whether we accept requests for launching external protocols. This is set to
-// false every time an external protocol is requested, and set back to true on
-// each user gesture. This variable should only be accessed from the UI thread.
+// Anti-flood protection controls whether we accept requests for launching
+// external protocols. Set to false each time an external protocol is requested,
+// and set back to true on each user gesture, extension API call, and navigation
+// to an external handler via bookmarks or the omnibox. This variable should
+// only be accessed from the UI thread.
 bool g_accept_requests = true;
 
 ExternalProtocolHandler::Delegate* g_external_protocol_handler_delegate =
@@ -394,6 +396,15 @@
     const base::Optional<url::Origin>& initiating_origin) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 
+  // Disable anti-flood protection if the user is invoking a bookmark or
+  // navigating directly using the omnibox.
+  if (!g_accept_requests &&
+      (PageTransitionCoreTypeIs(page_transition,
+                                ui::PAGE_TRANSITION_AUTO_BOOKMARK) ||
+       PageTransitionCoreTypeIs(page_transition, ui::PAGE_TRANSITION_TYPED))) {
+    g_accept_requests = true;
+  }
+
   // Escape the input scheme to be sure that the command does not
   // have parameters unexpected by the external program.
   // TODO(mgiuca): This essentially amounts to "remove illegal characters from
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index c38a765..dd46c834d9 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -49,6 +49,11 @@
     "expiry_milestone": 91
   },
   {
+    "name": "actionable-content-settings",
+    "owners": ["oroshiba", "dullweber"],
+    "expiry_milestone": 93
+  },
+  {
     "name": "aggregated-ml-app-ranking",
     "owners": [ "pdyson", "jiameng" ],
     "expiry_milestone": 81
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 149f46d..40e1f3b 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3070,6 +3070,11 @@
     "separated like strict site isolation, but process selection puts multiple "
     "site instances in a single process.";
 
+const char kActionableContentSettingsName[] = "Improvements to site settings";
+const char kActionableContentSettingsDescription[] =
+    "Changes the site settings to use a switch instead of a dialog. "
+    " Additionally improves icons to show current blocked status.";
+
 const char kQueryTilesName[] = "Show query tiles";
 const char kQueryTilesDescription[] = "Shows query tiles in Chrome";
 const char kQueryTilesNTPName[] = "Show query tiles in NTP";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 42b3261..6847b214 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -1854,6 +1854,9 @@
 extern const char kStrictSiteIsolationName[];
 extern const char kStrictSiteIsolationDescription[];
 
+extern const char kActionableContentSettingsName[];
+extern const char kActionableContentSettingsDescription[];
+
 extern const char kToolbarIphAndroidName[];
 extern const char kToolbarIphAndroidDescription[];
 
diff --git a/chrome/browser/resources/interventions_internals/index.js b/chrome/browser/resources/interventions_internals/index.js
index 1ff7876f..503c3dbe 100644
--- a/chrome/browser/resources/interventions_internals/index.js
+++ b/chrome/browser/resources/interventions_internals/index.js
@@ -13,9 +13,7 @@
 const ENABLE_BLOCKLIST_BUTTON = 'Enable Blocklist';
 const IGNORE_BLOCKLIST_BUTTON = 'Ignore Blocklist';
 const IGNORE_BLOCKLIST_MESSAGE = 'Blocklist decisions are ignored.';
-const URL_THRESHOLD = 40;  // Maximum URL length
-// Export on |window| for tests.
-window.URL_THRESHOLD = URL_THRESHOLD;
+export const URL_THRESHOLD = 40;  // Maximum URL length
 
 window.logTableMap = {};
 
@@ -38,7 +36,7 @@
  * @param {number} time Time in millisecond since Unix Epoch.
  * @return The converted string format.
  */
-function getTimeFormat(time) {
+export function getTimeFormat(time) {
   const date = new Date(time);
   const options = {
     year: 'numeric',
@@ -53,8 +51,6 @@
   const millisec = getPaddedValue(date.getMilliseconds(), 3);
   return dateString + ' ' + hour + ':' + min + ':' + sec + '.' + millisec;
 }
-// Export on |window| for tests.
-window.getTimeFormat = getTimeFormat;
 
 /**
  * Append a button to |element|, so that when the button is clicked, the
@@ -462,11 +458,9 @@
  * @constructor
  * @implements {mojom.InterventionsInternalsPageInterface}
  */
-const InterventionsInternalPageImpl = function() {
+export const InterventionsInternalPageImpl = function() {
   this.receiver_ = new mojom.InterventionsInternalsPageReceiver(this);
 };
-// Export on |window| for tests.
-window.InterventionsInternalPageImpl = InterventionsInternalPageImpl;
 
 InterventionsInternalPageImpl.prototype = {
   /**
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn
index 7513988..a097d99 100644
--- a/chrome/browser/resources/settings/chromeos/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -344,6 +344,8 @@
     "chromeos/multidevice_page/multidevice_smartlock_subpage.m.js",
     "chromeos/multidevice_page/multidevice_subpage.m.js",
     "chromeos/multidevice_page/multidevice_tether_item.m.js",
+    "chromeos/multidevice_page/multidevice_task_continuation_disabled_link.m.js",
+    "chromeos/multidevice_page/multidevice_task_continuation_item.m.js",
     "chromeos/multidevice_page/multidevice_wifi_sync_disabled_link.m.js",
     "chromeos/multidevice_page/multidevice_wifi_sync_item.m.js",
     "chromeos/nearby_share_page/nearby_account_manager_browser_proxy.m.js",
@@ -659,6 +661,10 @@
     "chromeos/multidevice_page/multidevice_subpage.js",
     "chromeos/multidevice_page/multidevice_tether_item.html",
     "chromeos/multidevice_page/multidevice_tether_item.js",
+    "chromeos/multidevice_page/multidevice_task_continuation_disabled_link.html",
+    "chromeos/multidevice_page/multidevice_task_continuation_disabled_link.js",
+    "chromeos/multidevice_page/multidevice_task_continuation_item.html",
+    "chromeos/multidevice_page/multidevice_task_continuation_item.js",
     "chromeos/multidevice_page/multidevice_wifi_sync_disabled_link.html",
     "chromeos/multidevice_page/multidevice_wifi_sync_disabled_link.js",
     "chromeos/multidevice_page/multidevice_wifi_sync_item.html",
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn
index 2a80838..d92899e 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/BUILD.gn
@@ -16,6 +16,8 @@
     ":multidevice_page",
     ":multidevice_smartlock_subpage",
     ":multidevice_subpage",
+    ":multidevice_task_continuation_disabled_link",
+    ":multidevice_task_continuation_item",
     ":multidevice_tether_item",
     ":multidevice_wifi_sync_disabled_link",
     ":multidevice_wifi_sync_item",
@@ -117,6 +119,7 @@
     ":multidevice_browser_proxy",
     ":multidevice_constants",
     ":multidevice_feature_behavior",
+    ":multidevice_task_continuation_item",
     ":multidevice_wifi_sync_item",
     "..:deep_linking_behavior",
     "..:os_route",
@@ -128,6 +131,15 @@
   extra_sources = [ "$interfaces_path/networking_private_interface.js" ]
 }
 
+js_library("multidevice_task_continuation_disabled_link") {
+  deps = [
+    "..:os_route",
+    "../..:router",
+    "//ui/webui/resources/js:i18n_behavior",
+    "//ui/webui/resources/js:load_time_data",
+  ]
+}
+
 js_library("multidevice_tether_item") {
   deps = [
     ":multidevice_feature_behavior",
@@ -141,6 +153,16 @@
   extra_sources = [ "$interfaces_path/networking_private_interface.js" ]
 }
 
+js_library("multidevice_task_continuation_item") {
+  deps = [
+    ":multidevice_feature_behavior",
+    ":multidevice_feature_item",
+    ":multidevice_task_continuation_disabled_link",
+    "../../people_page:sync_browser_proxy",
+    "//ui/webui/resources/js:web_ui_listener_behavior",
+  ]
+}
+
 js_library("multidevice_wifi_sync_item") {
   deps = [
     ":multidevice_feature_behavior",
@@ -180,6 +202,8 @@
     ":multidevice_radio_button.m",
     ":multidevice_smartlock_subpage.m",
     ":multidevice_subpage.m",
+    ":multidevice_task_continuation_disabled_link.m",
+    ":multidevice_task_continuation_item.m",
     ":multidevice_tether_item.m",
     ":multidevice_wifi_sync_disabled_link.m",
     ":multidevice_wifi_sync_item.m",
@@ -300,6 +324,7 @@
   deps = [
     ":multidevice_browser_proxy.m",
     ":multidevice_constants.m",
+    ":multidevice_task_continuation_item.m",
     ":multidevice_wifi_sync_item.m",
     "..:deep_linking_behavior.m",
     "..:os_route.m",
@@ -325,6 +350,20 @@
   extra_deps = [ ":multidevice_tether_item_module" ]
 }
 
+js_library("multidevice_task_continuation_item.m") {
+  sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_item.m.js" ]
+  deps = [
+    ":multidevice_constants.m",
+    ":multidevice_feature_behavior.m",
+    ":multidevice_feature_item.m",
+    ":multidevice_task_continuation_disabled_link.m",
+    "../../people_page:sync_browser_proxy.m",
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/js:web_ui_listener_behavior.m",
+  ]
+  extra_deps = [ ":multidevice_task_continuation_item_module" ]
+}
+
 js_library("multidevice_wifi_sync_item.m") {
   sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_item.m.js" ]
   deps = [
@@ -344,6 +383,18 @@
   extra_deps = [ ":multidevice_wifi_sync_item_module" ]
 }
 
+js_library("multidevice_task_continuation_disabled_link.m") {
+  sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_disabled_link.m.js" ]
+  deps = [
+    "..:os_route.m",
+    "../..:router.m",
+    "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
+    "//ui/webui/resources/js:i18n_behavior.m",
+    "//ui/webui/resources/js:load_time_data.m",
+  ]
+  extra_deps = [ ":multidevice_task_continuation_disabled_link_module" ]
+}
+
 js_library("multidevice_wifi_sync_disabled_link.m") {
   sources = [ "$root_gen_dir/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_wifi_sync_disabled_link.m.js" ]
   deps = [
@@ -368,6 +419,8 @@
     ":multidevice_radio_button_module",
     ":multidevice_smartlock_subpage_module",
     ":multidevice_subpage_module",
+    ":multidevice_task_continuation_disabled_link_module",
+    ":multidevice_task_continuation_item_module",
     ":multidevice_tether_item_module",
     ":multidevice_wifi_sync_disabled_link_module",
     ":multidevice_wifi_sync_item_module",
@@ -449,6 +502,15 @@
   auto_imports = os_settings_auto_imports
 }
 
+polymer_modulizer("multidevice_task_continuation_item") {
+  js_file = "multidevice_task_continuation_item.js"
+  html_file = "multidevice_task_continuation_item.html"
+  html_type = "dom-module"
+  migrated_imports = os_settings_migrated_imports
+  namespace_rewrites = os_settings_namespace_rewrites
+  auto_imports = os_settings_auto_imports
+}
+
 polymer_modulizer("multidevice_wifi_sync_item") {
   js_file = "multidevice_wifi_sync_item.js"
   html_file = "multidevice_wifi_sync_item.html"
@@ -458,6 +520,15 @@
   auto_imports = os_settings_auto_imports
 }
 
+polymer_modulizer("multidevice_task_continuation_disabled_link") {
+  js_file = "multidevice_task_continuation_disabled_link.js"
+  html_file = "multidevice_task_continuation_disabled_link.html"
+  html_type = "dom-module"
+  migrated_imports = os_settings_migrated_imports
+  namespace_rewrites = os_settings_namespace_rewrites
+  auto_imports = os_settings_auto_imports
+}
+
 polymer_modulizer("multidevice_wifi_sync_disabled_link") {
   js_file = "multidevice_wifi_sync_disabled_link.js"
   html_file = "multidevice_wifi_sync_disabled_link.html"
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.html b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.html
index 0d61af8..5ab03a8 100644
--- a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.html
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_subpage.html
@@ -18,6 +18,7 @@
 <link rel="import" href="multidevice_feature_behavior.html">
 <link rel="import" href="multidevice_feature_item.html">
 <link rel="import" href="multidevice_feature_toggle.html">
+<link rel="import" href="multidevice_task_continuation_item.html">
 <link rel="import" href="multidevice_tether_item.html">
 <link rel="import" href="multidevice_wifi_sync_item.html">
 
@@ -134,11 +135,11 @@
             if="[[isFeatureSupported(
                 MultiDeviceFeature.PHONE_HUB_TASK_CONTINUATION, pageContentData)]]"
             restamp>
-          <settings-multidevice-feature-item id="phoneHubTaskContinuationItem"
-              feature="[[MultiDeviceFeature.PHONE_HUB_TASK_CONTINUATION]]"
-              page-content-data="[[pageContentData]]" is-sub-feature
+          <settings-multidevice-task-continuation-item
+              id="phoneHubTaskContinuationItem"
+              page-content-data="[[pageContentData]]"
               deep-link-focus-id$="[[Setting.kPhoneHubTaskContinuationOnOff]]">
-          </settings-multidevice-feature-item>
+          </settings-multidevice-task-continuation-item>
         </template>
         <template is="dom-if"
             if="[[isFeatureSupported(
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_disabled_link.html b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_disabled_link.html
new file mode 100644
index 0000000..6f25e82
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_disabled_link.html
@@ -0,0 +1,18 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/html/load_time_data.html">
+<link rel="import" href="../os_route.html">
+<link rel="import" href="../os_settings_routes.html">
+<link rel="import" href="../../router.html">
+<link rel="import" href="../../settings_shared_css.html">
+
+<dom-module id="settings-multidevice-task-continuation-disabled-link">
+  <template>
+    <style include="settings-shared"></style>
+    <div id="container"
+        inner-h-t-m-l="[[getAriaLabelledContent_()]]">
+    </div>
+  </template>
+  <script src="multidevice_task_continuation_disabled_link.js"></script>
+</dom-module>
\ No newline at end of file
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_disabled_link.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_disabled_link.js
new file mode 100644
index 0000000..6559a55
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_disabled_link.js
@@ -0,0 +1,77 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview 'settings-multidevice-task-continuation-disabled-link'
+ * creates a localized string with accessibility labels for the Phone Hub Task
+ * continuation feature when the prerequisite Chrome Sync setting is not
+ * enabled.
+ *
+ * The localized string is treated as a special case for accessibility
+ * labelling since it contains two links, one to the Chrome Sync dependency
+ * and the other to a Learn More page for Phone Hub.
+ */
+Polymer({
+  is: 'settings-multidevice-task-continuation-disabled-link',
+
+  behaviors: [I18nBehavior],
+
+  /** @override */
+  attached() {
+    const chromeSyncLink = this.$$('#chromeSyncLink');
+    if (chromeSyncLink) {
+      chromeSyncLink.addEventListener(
+          'click', this.onChromeSyncLinkClick_.bind(this));
+    }
+  },
+
+  /**
+   * @return {string} Localized summary of Task Continuation when Chrome Sync is
+   *     turned off, formatted with correct aria-labels and click events.
+   * @private
+   */
+  getAriaLabelledContent_() {
+    const tempEl = document.createElement('div');
+    tempEl.innerHTML = this.i18nAdvanced(
+        'multidevicePhoneHubTaskContinuationDisabledSummary', {attrs: ['id']});
+
+    tempEl.childNodes.forEach((node, index) => {
+      // Text nodes should be aria-hidden
+      if (node.nodeType === Node.TEXT_NODE) {
+        const spanNode = document.createElement('span');
+        spanNode.textContent = node.textContent;
+        spanNode.id = `id${index}`;
+        spanNode.setAttribute('aria-hidden', true);
+        node.replaceWith(spanNode);
+        return;
+      }
+    });
+
+    const chromeSyncLink = tempEl.querySelector('#chromeSyncLink');
+    const learnMoreLink = tempEl.querySelector('#learnMoreLink');
+
+    chromeSyncLink.setAttribute(
+        'aria-label',
+        this.i18n('multidevicePhoneHubTaskContinuationSyncLabel'));
+    learnMoreLink.setAttribute(
+        'aria-label', this.i18n('multidevicePhoneHubLearnMoreLabel'));
+    chromeSyncLink.href = '#';
+
+    return tempEl.innerHTML;
+  },
+
+  /**
+   * @param {!Event} event
+   * @private
+   */
+  onChromeSyncLinkClick_(event) {
+    event.preventDefault();
+    if (loadTimeData.getBoolean('splitSettingsSyncEnabled')) {
+      window.open('chrome://settings/syncSetup/advanced');
+      this.fire('opened-browser-advanced-sync-settings');
+    } else {
+      settings.Router.getInstance().navigateTo(settings.routes.SYNC_ADVANCED);
+    }
+  },
+});
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_item.html b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_item.html
new file mode 100644
index 0000000..b3b1d251
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_item.html
@@ -0,0 +1,35 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="multidevice_feature_behavior.html">
+<link rel="import" href="multidevice_feature_item.html">
+<link rel="import" href="multidevice_task_continuation_disabled_link.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_toggle/cr_toggle.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/html/load_time_data.html">
+<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
+<link rel="import" href="multidevice_constants.html">
+<link rel="import" href="../../settings_shared_css.html">
+<link rel="import" href="../../people_page/sync_browser_proxy.html">
+
+<dom-module id="settings-multidevice-task-continuation-item">
+  <template>
+    <style include="settings-shared"></style>
+    <settings-multidevice-feature-item id="phoneHubTaskContinuationItem"
+        feature="[[MultiDeviceFeature.PHONE_HUB_TASK_CONTINUATION]]"
+        page-content-data="[[pageContentData]]" is-sub-feature>
+      <template is="dom-if" if="[[!isChromeTabsSyncEnabled_]]" restamp>
+        <settings-multidevice-task-continuation-disabled-link
+            class="secondary"
+            id="featureSecondary"
+            slot="feature-summary">
+        </settings-multidevice-task-continuation-disabled-link>
+        <!-- Replace the standard feature-controller with an always disabled and
+          off cr-toggle when Chrome Sync Open Tabs is disabled. When Chrome Sync
+          is enabled the standard feature-controller is used. -->
+        <cr-toggle disabled slot="feature-controller">
+        </cr-toggle>
+      </template>
+    </settings-multidevice-feature-item>
+  </template>
+  <script src="multidevice_task_continuation_item.js"></script>
+</dom-module>
diff --git a/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_item.js b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_item.js
new file mode 100644
index 0000000..6785c80a
--- /dev/null
+++ b/chrome/browser/resources/settings/chromeos/multidevice_page/multidevice_task_continuation_item.js
@@ -0,0 +1,70 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview 'settings-multidevice-task-continuation-item' encapsulates
+ * special logic for the phonehub task continuation item used in the multidevice
+ * subpage.
+ *
+ * Task continuation depends on the 'Open Tabs' Chrome sync type being
+ * activated. This component uses sync proxies from the people page to check
+ * whether chrome sync is enabled.
+ *
+ * If it is enabled the multidevice feature item is used in the standard way,
+ * otherwise the feature-controller and localized-link slots are overridden with
+ * a disabled toggle and the task continuation localized string component that
+ * is a special case containing two links.
+ */
+Polymer({
+  is: 'settings-multidevice-task-continuation-item',
+
+  behaviors: [
+    MultiDeviceFeatureBehavior,
+    WebUIListenerBehavior,
+  ],
+
+  properties: {
+    /** @private */
+    isChromeTabsSyncEnabled_: {
+      type: Boolean,
+      value: false,
+    },
+  },
+
+  /** @private {?settings.SyncBrowserProxy} */
+  syncBrowserProxy_: null,
+
+  /** @override */
+  created() {
+    this.syncBrowserProxy_ = settings.SyncBrowserProxyImpl.getInstance();
+  },
+
+  /** @override */
+  attached() {
+    this.addWebUIListener(
+        'sync-prefs-changed', this.handleSyncPrefsChanged_.bind(this));
+
+    // Cause handleSyncPrefsChanged_() to be called when the element is first
+    // attached so that the state of |syncPrefs.tabsSynced| is known.
+    this.syncBrowserProxy_.sendSyncPrefsChanged();
+  },
+
+  /** @override */
+  focus() {
+    if (!this.isChromeTabsSyncEnabled_) {
+      this.$$('cr-toggle').focus();
+    } else {
+      this.$.phoneHubTaskContinuationItem.focus();
+    }
+  },
+
+  /**
+   * Handler for when the sync preferences are updated.
+   * @param {!settings.SyncPrefs} syncPrefs
+   * @private
+   */
+  handleSyncPrefsChanged_(syncPrefs) {
+    this.isChromeTabsSyncEnabled_ = !!syncPrefs && syncPrefs.tabsSynced;
+  },
+});
diff --git a/chrome/browser/resources/settings/icons.html b/chrome/browser/resources/settings/icons.html
index 6e5af49..ad5d253 100644
--- a/chrome/browser/resources/settings/icons.html
+++ b/chrome/browser/resources/settings/icons.html
@@ -11,6 +11,7 @@
     <defs>
       <g id="credit-card"><path d="M16.4,4 L3.6,4 C2.716,4 2.008,4.7271875 2.008,5.625 L2,15.375 C2,16.2728125 2.716,17 3.6,17 L16.4,17 C17.284,17 18,16.2728125 18,15.375 L18,5.625 C18,4.7271875 17.284,4 16.4,4 Z M16.5,15 L3.5,15 L3.5,10 L16.5,10 L16.5,15 Z M16.5,7 L3.5,7 L3.5,5.5 L16.5,5.5 L16.5,7 Z"></path></g>
       <g id="data"><path d="M0 0h20v20H0z" fill="none" fill-rule="evenodd"></path><path d="M6.5 7v9H4V7h2.5zm5-3v12H9V4h2.5zm5 7v5H14v-5h2.5z"></path></g>
+      <g id="experiment"><path d="M17.2667 14.7583L12.5 8.18332V4.23332H14.1667V2.56665H5.83332V4.23332H7.49998V8.17498L2.61665 14.9166C2.24998 15.425 2.19998 16.0917 2.48332 16.65C2.76665 17.2083 3.34165 17.5583 3.96665 17.5583H16.05C16.9667 17.5583 17.7167 16.8083 17.7167 15.8917C17.7167 15.4583 17.5416 15.0583 17.2667 14.7583Z" fill="#5F6368"></path></g>
       <g id="googleg"><path d="M16.58 8H9v2.75h4.47c-.24 1.2-1.42 3.27-4.47 3.27-2.72 0-4.93-2.25-4.93-5.02S6.28 3.98 9 3.98c1.54 0 2.57.66 3.17 1.22l2.19-2.12C12.97 1.79 11.16 1 9 1 4.58 1 1 4.58 1 9s3.58 8 8 8c4.62 0 7.68-3.25 7.68-7.82 0-.46-.04-.83-.1-1.18z"></path></g>
       <g id="incognito" fill="#5F6368"><circle cx="6.8" cy="12.964" r="1.764"/><path d="M10 0C4.473 0 0 4.473 0 10s4.473 10 10 10 10-4.473 10-10S15.527 0 10 0zM7.619 4.1a.696.696 0 0 1 .881-.419l1.473.492 1.463-.492a.716.716 0 0 1 .883.419l1.608 4.291H6.02l1.6-4.291zm5.517 11.328a2.463 2.463 0 0 1-2.445-2.256c-.682-.436-1.237-.162-1.455-.017a2.45 2.45 0 0 1-2.445 2.263 2.471 2.471 0 0 1-2.464-2.463 2.47 2.47 0 0 1 2.463-2.464c1.165 0 2.138.809 2.391 1.9a1.934 1.934 0 0 1 1.546.009 2.462 2.462 0 0 1 2.392-1.909 2.47 2.47 0 0 1 2.462 2.463 2.435 2.435 0 0 1-2.445 2.474zM16.31 9.8H3.637v-.709H16.31V9.8h-.001z"/><circle cx="13.136" cy="12.964" r="1.764"/></g>
       <g id="location-on"><path d="M10,2 C6.95928571,2 4.5,4.504 4.5,7.6 C4.5,11.8 10,18 10,18 C10,18 15.5,11.8 15.5,7.6 C15.5,4.504 13.0407143,2 10,2 Z M10,9.5 C8.896,9.5 8,8.604 8,7.5 C8,6.396 8.896,5.5 10,5.5 C11.104,5.5 12,6.396 12,7.5 C12,8.604 11.104,9.5 10,9.5 Z"></path></g>
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.html b/chrome/browser/resources/settings/privacy_page/privacy_page.html
index 5db3d9b..8a013e01 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_page.html
+++ b/chrome/browser/resources/settings/privacy_page/privacy_page.html
@@ -49,6 +49,15 @@
             sub-label="$i18n{permissionsPageDescription}"
             on-click="onPermissionsPageClick_"
             role-description="$i18n{subpageArrowRoleDescription}"></cr-link-row>
+        <cr-link-row id="privacySandboxLinkRow"
+            start-icon="settings20:experiment"
+            class="hr"
+            label="$i18n{privacySandboxTitle}"
+            sub-label="$i18n{privacySandboxTitle}"
+            on-click="onPrivacySandboxClick_"
+            hidden="[[!enablePrivacySandboxSettings_]]"
+            external
+            role-description="$i18n{subpageArrowRoleDescription}"></cr-link-row>
       </div>
 
 <if expr="use_nss_certs">
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.js b/chrome/browser/resources/settings/privacy_page/privacy_page.js
index 86446bb..1a31634 100644
--- a/chrome/browser/resources/settings/privacy_page/privacy_page.js
+++ b/chrome/browser/resources/settings/privacy_page/privacy_page.js
@@ -165,6 +165,12 @@
           loadTimeData.getBoolean('enableWebBluetoothNewPermissionsBackend'),
     },
 
+    /** @private */
+    enablePrivacySandboxSettings_: {
+      type: Boolean,
+      value: () => loadTimeData.getBoolean('privacySandboxSettingsEnabled'),
+    },
+
     /** @private {!Map<string, string>} */
     focusConfig_: {
       type: Object,
@@ -329,6 +335,13 @@
   },
 
   /** @private */
+  onPrivacySandboxClick_() {
+    // TODO(crbug/1159942): Replace this with an ordinary OpenWindowProxy call
+    // once crbug/1159942 is fixed.
+    window.location = 'chrome://settings/privacySandbox';
+  },
+
+  /** @private */
   getProtectedContentLabel_(value) {
     return value ? this.i18n('siteSettingsProtectedContentEnable') :
                    this.i18n('siteSettingsBlocked');
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
index 081402d..b1421a8 100644
--- a/chrome/browser/ui/browser.cc
+++ b/chrome/browser/ui/browser.cc
@@ -1614,8 +1614,9 @@
   if (is_popup && navigated_or_inserted_contents) {
     auto* tracker = blocked_content::PopupTracker::CreateForWebContents(
         navigated_or_inserted_contents, source, params.disposition);
-    tracker->set_is_trusted(params.triggering_event_info !=
-                            blink::TriggeringEventInfo::kFromUntrustedEvent);
+    tracker->set_is_trusted(
+        params.triggering_event_info !=
+        blink::mojom::TriggeringEventInfo::kFromUntrustedEvent);
   }
 
   return navigated_or_inserted_contents;
diff --git a/chrome/browser/ui/font_access/font_access_chooser_controller.cc b/chrome/browser/ui/font_access/font_access_chooser_controller.cc
index 0a4bedd..46cf49ad 100644
--- a/chrome/browser/ui/font_access/font_access_chooser_controller.cc
+++ b/chrome/browser/ui/font_access/font_access_chooser_controller.cc
@@ -71,6 +71,11 @@
   return base::UTF8ToUTF16(items_[index]);
 }
 
+base::string16 FontAccessChooserController::GetSelectAllCheckboxLabel() const {
+  return l10n_util::GetStringUTF16(
+      IDS_FONT_ACCESS_CHOOSER_SELECT_ALL_CHECKBOX_TEXT);
+}
+
 bool FontAccessChooserController::ShouldShowHelpButton() const {
   return false;
 }
@@ -88,6 +93,10 @@
   return true;
 }
 
+bool FontAccessChooserController::ShouldShowSelectAllCheckbox() const {
+  return true;
+}
+
 bool FontAccessChooserController::TableViewAlwaysDisabled() const {
   return false;
 }
diff --git a/chrome/browser/ui/font_access/font_access_chooser_controller.h b/chrome/browser/ui/font_access/font_access_chooser_controller.h
index e6e737a..cf1464d 100644
--- a/chrome/browser/ui/font_access/font_access_chooser_controller.h
+++ b/chrome/browser/ui/font_access/font_access_chooser_controller.h
@@ -32,12 +32,14 @@
   base::string16 GetOkButtonLabel() const override;
   size_t NumOptions() const override;
   base::string16 GetOption(size_t index) const override;
+  base::string16 GetSelectAllCheckboxLabel() const override;
 
   bool ShouldShowHelpButton() const override;
   bool ShouldShowReScanButton() const override;
   bool BothButtonsAlwaysEnabled() const override;
   bool TableViewAlwaysDisabled() const override;
   bool AllowMultipleSelection() const override;
+  bool ShouldShowSelectAllCheckbox() const override;
 
   void Select(const std::vector<size_t>& indices) override;
   void Cancel() override;
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc
index a459360..701bb9d 100644
--- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc
+++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc
@@ -9,6 +9,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "build/build_config.h"
 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
+#include "chrome/browser/external_protocol/external_protocol_handler.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/tab_ui_helper.h"
@@ -200,3 +201,126 @@
     EXPECT_EQ("?1", GetContent());
   }
 }
+
+// Class intercepts invocations of external protocol handlers.
+class FakeProtocolHandlerDelegate : public ExternalProtocolHandler::Delegate {
+ public:
+  FakeProtocolHandlerDelegate() = default;
+
+  // Wait until an external handler url is received by the class method
+  // |RunExternalProtocolDialog|.
+  const GURL& WaitForUrl() {
+    run_loop_.Run();
+    return url_invoked_;
+  }
+
+  FakeProtocolHandlerDelegate(const FakeProtocolHandlerDelegate& other) =
+      delete;
+  FakeProtocolHandlerDelegate& operator=(
+      const FakeProtocolHandlerDelegate& other) = delete;
+  class FakeDefaultProtocolClientWorker
+      : public shell_integration::DefaultProtocolClientWorker {
+   public:
+    explicit FakeDefaultProtocolClientWorker(const std::string& protocol)
+        : DefaultProtocolClientWorker(protocol) {}
+    FakeDefaultProtocolClientWorker(
+        const FakeDefaultProtocolClientWorker& other) = delete;
+    FakeDefaultProtocolClientWorker& operator=(
+        const FakeDefaultProtocolClientWorker& other) = delete;
+
+   private:
+    ~FakeDefaultProtocolClientWorker() override = default;
+    shell_integration::DefaultWebClientState CheckIsDefaultImpl() override {
+      return shell_integration::DefaultWebClientState::NOT_DEFAULT;
+    }
+
+    void SetAsDefaultImpl(base::OnceClosure on_finished_callback) override {
+      base::SequencedTaskRunnerHandle::Get()->PostTask(
+          FROM_HERE, std::move(on_finished_callback));
+    }
+  };
+
+ private:
+  scoped_refptr<shell_integration::DefaultProtocolClientWorker>
+  CreateShellWorker(const std::string& protocol) override {
+    return base::MakeRefCounted<FakeDefaultProtocolClientWorker>(protocol);
+  }
+
+  void BlockRequest() override { FAIL(); }
+
+  ExternalProtocolHandler::BlockState GetBlockState(const std::string& scheme,
+                                                    Profile* profile) override {
+    return ExternalProtocolHandler::GetBlockState(scheme, nullptr, profile);
+  }
+
+  void RunExternalProtocolDialog(
+      const GURL& url,
+      content::WebContents* web_contents,
+      ui::PageTransition page_transition,
+      bool has_user_gesture,
+      const base::Optional<url::Origin>& initiating_origin) override {
+    DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+    EXPECT_TRUE(url_invoked_.is_empty());
+    url_invoked_ = url;
+    run_loop_.Quit();
+  }
+
+  void LaunchUrlWithoutSecurityCheck(
+      const GURL& url,
+      content::WebContents* web_contents) override {
+    FAIL();
+  }
+
+  void FinishedProcessingCheck() override {}
+
+  GURL url_invoked_;
+  base::RunLoop run_loop_;
+  SEQUENCE_CHECKER(sequence_checker_);
+};
+
+// Checks that opening a bookmark to a URL handled by an external handler is not
+// blocked by anti-flood protection. Regression test for
+// https://crbug.com/1156651
+IN_PROC_BROWSER_TEST_F(BookmarkBarNavigationTest, ExternalHandlerAllowed) {
+  const char external_protocol[] = "fake";
+  const GURL external_url = GURL("fake://path");
+
+  bookmarks::BookmarkModel* model =
+      BookmarkModelFactory::GetForBrowserContext(browser()->profile());
+  bookmarks::test::WaitForBookmarkModelToLoad(model);
+  model->ClearStore();
+  model->AddURL(model->bookmark_bar_node(), 0, base::ASCIIToUTF16("Example"),
+                external_url);
+
+  // First, get into a known (unblocked) state.
+  ExternalProtocolHandler::PermitLaunchUrl();
+  EXPECT_NE(ExternalProtocolHandler::BLOCK,
+            ExternalProtocolHandler::GetBlockState(external_protocol, nullptr,
+                                                   browser()->profile()));
+
+  // Next, try to launch a bookmark pointed at the url of an external handler.
+  {
+    FakeProtocolHandlerDelegate external_handler_delegate;
+    ExternalProtocolHandler::SetDelegateForTesting(&external_handler_delegate);
+    NavigateToBookmark();
+    auto launched_url = external_handler_delegate.WaitForUrl();
+    EXPECT_EQ(external_url, launched_url);
+    // Verify that the state has returned to block.
+    EXPECT_EQ(ExternalProtocolHandler::BLOCK,
+              ExternalProtocolHandler::GetBlockState(external_protocol, nullptr,
+                                                     browser()->profile()));
+  }
+  // Finally, without first calling PermitLaunchUrl, try to launch the bookmark.
+  {
+    FakeProtocolHandlerDelegate external_handler_delegate;
+    ExternalProtocolHandler::SetDelegateForTesting(&external_handler_delegate);
+    NavigateToBookmark();
+    auto launched_url = external_handler_delegate.WaitForUrl();
+    EXPECT_EQ(external_url, launched_url);
+    // Verify the launch state has changed back.
+    EXPECT_EQ(ExternalProtocolHandler::BLOCK,
+              ExternalProtocolHandler::GetBlockState(external_protocol, nullptr,
+                                                     browser()->profile()));
+  }
+}
diff --git a/chrome/browser/ui/views/device_chooser_content_view.cc b/chrome/browser/ui/views/device_chooser_content_view.cc
index f65cce23..b5698b9 100644
--- a/chrome/browser/ui/views/device_chooser_content_view.cc
+++ b/chrome/browser/ui/views/device_chooser_content_view.cc
@@ -20,6 +20,7 @@
 #include "ui/gfx/paint_vector_icon.h"
 #include "ui/resources/grit/ui_resources.h"
 #include "ui/views/accessibility/view_accessibility.h"
+#include "ui/views/controls/button/checkbox.h"
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/button/image_button_factory.h"
 #include "ui/views/controls/button/label_button.h"
@@ -118,7 +119,22 @@
   chooser_controller_->set_view(this);
 
   SetPreferredSize({402, 320});
-  SetLayoutManager(std::make_unique<views::FillLayout>());
+
+  if (chooser_controller_->ShouldShowSelectAllCheckbox()) {
+    SetLayoutManager(std::make_unique<views::BoxLayout>(
+        views::BoxLayout::Orientation::kVertical));
+    auto select_all_view = std::make_unique<views::Checkbox>(
+        chooser_controller_->GetSelectAllCheckboxLabel());
+    select_all_view->SetVisible(false);
+    select_all_subscription_ = select_all_view->AddCheckedChangedCallback(
+        base::BindRepeating(&DeviceChooserContentView::SelectAllCheckboxChanged,
+                            base::Unretained(this)));
+    select_all_view_ = AddChildView(std::move(select_all_view));
+  } else {
+    // FillLayout is the default. There will only be the ScrollView,
+    // therefore there's no point to have a BoxLayout.
+    SetLayoutManager(std::make_unique<views::FillLayout>());
+  }
 
   std::vector<ui::TableColumn> table_columns = {ui::TableColumn()};
   auto table_view = std::make_unique<views::TableView>(
@@ -134,6 +150,12 @@
 
   table_parent_ = AddChildView(
       views::TableView::CreateScrollViewWithTable(std::move(table_view)));
+  if (chooser_controller_->ShouldShowSelectAllCheckbox()) {
+    // This will be using the BoxLayout manager.
+    // Set min and max height, otherwise CalculatePreferredSize() will be
+    // called, returning 0, 0 always.
+    table_parent_->ClipHeightTo(320, 320);
+  }
 
   const auto add_centering_view = [this](auto view) {
     auto* container = AddChildView(std::make_unique<views::View>());
@@ -342,6 +364,12 @@
       GetWidget()->GetFocusManager()->GetFocusedView()) {
     is_initialized_ = true;  // Can show no_options_view_ after initial focus.
   }
+
+  if (select_all_view_) {
+    select_all_view_->SetVisible(
+        has_options && chooser_controller_->ShouldShowSelectAllCheckbox());
+  }
+
   table_parent_->SetVisible(has_options);
   table_view_->SetEnabled(has_options &&
                           !chooser_controller_->TableViewAlwaysDisabled());
@@ -352,6 +380,11 @@
   adapter_off_view_->SetVisible(!adapter_enabled_);
 }
 
+void DeviceChooserContentView::SelectAllCheckboxChanged() {
+  DCHECK(select_all_view_ && table_view_);
+  table_view_->SetSelectionAll(/*select=*/select_all_view_->GetChecked());
+}
+
 views::LabelButton* DeviceChooserContentView::ReScanButtonForTesting() {
   return bluetooth_status_container_->re_scan_button_;
 }
diff --git a/chrome/browser/ui/views/device_chooser_content_view.h b/chrome/browser/ui/views/device_chooser_content_view.h
index adf3260..9308d67 100644
--- a/chrome/browser/ui/views/device_chooser_content_view.h
+++ b/chrome/browser/ui/views/device_chooser_content_view.h
@@ -16,6 +16,7 @@
 
 class BluetoothStatusContainer;
 namespace views {
+class Checkbox;
 class Label;
 class LabelButton;
 class TableView;
@@ -61,6 +62,7 @@
   void Cancel();
   void Close();
   void UpdateTableView();
+  void SelectAllCheckboxChanged();
 
   // Test-only accessors to children.
   views::TableView* table_view_for_testing() { return table_view_; }
@@ -75,13 +77,15 @@
 
   bool adapter_enabled_ = true;
 
-  views::View* table_parent_ = nullptr;
+  views::ScrollView* table_parent_ = nullptr;
+  views::Checkbox* select_all_view_ = nullptr;
   views::TableView* table_view_ = nullptr;
   views::View* no_options_view_ = nullptr;
   views::View* adapter_off_view_ = nullptr;
   BluetoothStatusContainer* bluetooth_status_container_ = nullptr;
 
   bool is_initialized_ = false;
+  base::CallbackListSubscription select_all_subscription_;
 
   DISALLOW_COPY_AND_ASSIGN(DeviceChooserContentView);
 };
diff --git a/chrome/browser/ui/views/device_chooser_content_view_unittest.cc b/chrome/browser/ui/views/device_chooser_content_view_unittest.cc
index 853fc35..c763304 100644
--- a/chrome/browser/ui/views/device_chooser_content_view_unittest.cc
+++ b/chrome/browser/ui/views/device_chooser_content_view_unittest.cc
@@ -17,6 +17,7 @@
 #include "ui/events/base_event_utils.h"
 #include "ui/views/controls/button/image_button.h"
 #include "ui/views/controls/button/label_button.h"
+#include "ui/views/controls/scroll_view.h"
 #include "ui/views/controls/styled_label.h"
 #include "ui/views/controls/table/table_view.h"
 #include "ui/views/controls/table/table_view_observer.h"
@@ -76,7 +77,7 @@
   views::TableView* table_view() {
     return content_view_->table_view_for_testing();
   }
-  views::View* table_parent() { return content_view_->table_parent_; }
+  views::ScrollView* table_parent() { return content_view_->table_parent_; }
   ui::TableModel* table_model() { return table_view()->model(); }
   views::View* no_options_view() { return content_view_->no_options_view_; }
   views::View* adapter_off_view() { return content_view_->adapter_off_view_; }
diff --git a/chrome/browser/ui/views/screen_capture_notification_ui_views.cc b/chrome/browser/ui/views/screen_capture_notification_ui_views.cc
index 81da737..ba4ff2c 100644
--- a/chrome/browser/ui/views/screen_capture_notification_ui_views.cc
+++ b/chrome/browser/ui/views/screen_capture_notification_ui_views.cc
@@ -87,7 +87,6 @@
   views::ClientView* CreateClientView(views::Widget* widget) override;
   std::unique_ptr<views::NonClientFrameView> CreateNonClientFrameView(
       views::Widget* widget) override;
-  bool CanActivate() const override;
 
   // views::ViewObserver:
   void OnViewBoundsChanged(View* observed_view) override;
@@ -249,13 +248,6 @@
   return frame;
 }
 
-bool ScreenCaptureNotificationUIViews::CanActivate() const {
-  // When the window is visible, it can be activated so the mouse clicks
-  // can be sent to the window; when the window is minimized, we don't want it
-  // to activate, otherwise it sometimes does not show properly on Windows.
-  return GetWidget() && GetWidget()->IsVisible();
-}
-
 void ScreenCaptureNotificationUIViews::OnViewBoundsChanged(
     View* observed_view) {
   gfx::Rect client_rect = source_button_->bounds();
diff --git a/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.cc b/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.cc
index b8bdba5..bc0703c 100644
--- a/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.cc
+++ b/chrome/browser/ui/webui/interventions_internals/interventions_internals_ui.cc
@@ -31,6 +31,13 @@
       "interventions_internals.mojom-lite.js",
       IDR_INTERVENTIONS_INTERNALS_MOJOM_LITE_JS);
   source->SetDefaultResource(IDR_INTERVENTIONS_INTERNALS_INDEX_HTML);
+
+  source->OverrideContentSecurityPolicy(
+      network::mojom::CSPDirectiveName::TrustedTypes,
+      "trusted-types interventions-internals-test-script;");
+  source->OverrideContentSecurityPolicy(
+      network::mojom::CSPDirectiveName::ScriptSrc,
+      "script-src chrome://resources chrome://test 'self';");
   return source;
 }
 
diff --git a/chrome/browser/ui/webui/settings/chromeos/multidevice_section.cc b/chrome/browser/ui/webui/settings/chromeos/multidevice_section.cc
index c2ee3a1..4bff3c0 100644
--- a/chrome/browser/ui/webui/settings/chromeos/multidevice_section.cc
+++ b/chrome/browser/ui/webui/settings/chromeos/multidevice_section.cc
@@ -295,12 +295,16 @@
       {"multideviceSmartLockItemTitle", IDS_SETTINGS_EASY_UNLOCK_SECTION_TITLE},
       {"multidevicePhoneHubItemTitle",
        IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_SECTION_TITLE},
+      {"multidevicePhoneHubLearnMoreLabel",
+       IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_LEARN_MORE_LABEL},
       {"multidevicePhoneHubNotificationsItemTitle",
        IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_NOTIFICATIONS_SECTION_TITLE},
       {"multidevicePhoneHubTaskContinuationItemTitle",
        IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_TASK_CONTINUATION_SECTION_TITLE},
       {"multidevicePhoneHubTaskContinuationItemSummary",
        IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_TASK_CONTINUATION_SUMMARY},
+      {"multidevicePhoneHubTaskContinuationSyncLabel",
+       IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_TASK_CONTINUATION_SYNC_LABEL},
       {"multideviceWifiSyncItemTitle",
        IDS_SETTINGS_MULTIDEVICE_WIFI_SYNC_SECTION_TITLE},
       {"multideviceWifiSyncChromeSyncLabel",
@@ -435,6 +439,11 @@
       l10n_util::GetStringFUTF16(
           IDS_SETTINGS_MULTIDEVICE_ENABLE_WIFI_SYNC_V1_SUMMARY,
           GetHelpUrlWithBoard(chrome::kWifiSyncLearnMoreURL)));
+  html_source->AddString(
+      "multidevicePhoneHubTaskContinuationDisabledSummary",
+      l10n_util::GetStringFUTF16(
+          IDS_SETTINGS_MULTIDEVICE_PHONE_HUB_TASK_CONTINUATION_DISABLED_SUMMARY,
+          GetHelpUrlWithBoard(chrome::kPhoneHubLearnMoreLink)));
 
   AddEasyUnlockStrings(html_source);
   ::settings::AddNearbyShareData(html_source);
diff --git a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
index eae2c75d..a88c988 100644
--- a/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
+++ b/chrome/browser/ui/webui/settings/settings_localized_strings_provider.cc
@@ -1444,13 +1444,22 @@
 }
 
 void AddPrivacySandboxStrings(content::WebUIDataSource* html_source) {
+  // Strings that need to be available in any case.
   static constexpr webui::LocalizedString kLocalizedStrings[] = {
       {"privacySandboxTitle", IDS_SETTINGS_PRIVACY_SANDBOX_TITLE},
-      {"privacySandboxPageHeading", IDS_SETTINGS_PRIVACY_SANDBOX_PAGE_HEADING},
   };
   AddLocalizedStringsBulk(html_source, kLocalizedStrings);
 
-  html_source->AddString("privacySandboxURL", chrome::kPrivacySandboxURL);
+  // Strings that only need to be available when the flag is enabled.
+  if (base::FeatureList::IsEnabled(features::kPrivacySandboxSettings)) {
+    static constexpr webui::LocalizedString kLocalizedStringsBehindFlag[] = {
+        {"privacySandboxPageHeading",
+         IDS_SETTINGS_PRIVACY_SANDBOX_PAGE_HEADING},
+    };
+    AddLocalizedStringsBulk(html_source, kLocalizedStringsBehindFlag);
+
+    html_source->AddString("privacySandboxURL", chrome::kPrivacySandboxURL);
+  }
 }
 
 void AddSafetyCheckStrings(content::WebUIDataSource* html_source) {
@@ -2434,6 +2443,7 @@
   AddLanguagesStrings(html_source, profile);
   AddOnStartupStrings(html_source);
   AddPeopleStrings(html_source, profile);
+  AddPrivacySandboxStrings(html_source);
   AddPrivacyStrings(html_source, profile);
   AddSafetyCheckStrings(html_source);
   AddResetStrings(html_source, profile);
@@ -2442,9 +2452,6 @@
   AddSearchStrings(html_source);
   AddSiteSettingsStrings(html_source, profile);
 
-  if (base::FeatureList::IsEnabled(features::kPrivacySandboxSettings))
-    AddPrivacySandboxStrings(html_source);
-
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   AddChromeOSUserStrings(html_source, profile);
 #else
diff --git a/chrome/browser/ui/webui/settings/settings_ui.cc b/chrome/browser/ui/webui/settings/settings_ui.cc
index 69e549a2..97fd8a5 100644
--- a/chrome/browser/ui/webui/settings/settings_ui.cc
+++ b/chrome/browser/ui/webui/settings/settings_ui.cc
@@ -318,6 +318,10 @@
       "safetyCheckWeakPasswordsEnabled",
       base::FeatureList::IsEnabled(features::kSafetyCheckWeakPasswords));
 
+  html_source->AddBoolean(
+      "privacySandboxSettingsEnabled",
+      base::FeatureList::IsEnabled(features::kPrivacySandboxSettings));
+
   AddSettingsPageUIHandler(std::make_unique<AboutHandler>(profile));
   AddSettingsPageUIHandler(std::make_unique<ResetSettingsHandler>(profile));
 
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 22bd1b9..19f2c9b 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-master-1608249589-9c170b057d7f5d331838398008b8ec38a41e02e3.profdata
+chrome-linux-master-1608332413-e74bf19c468b4f240b918ee99bd718a9ec1e581b.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index fcef0766..013f45c 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-master-1608249589-e11ce53a2384150a68c372a42aa0334667012fbb.profdata
+chrome-mac-master-1608374575-799ca6e7dd99bf829770e0fae450259047134228.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 719b2d2..f6f58a1 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-master-1608228003-e74739fcdefa7518b67623025a08d95b63f00b00.profdata
+chrome-win64-master-1608366709-04c75f5dea3220c85227eec575768650c19be6b2.profdata
diff --git a/chrome/common/url_constants.cc b/chrome/common/url_constants.cc
index e5d4c11..5b5c9a83 100644
--- a/chrome/common/url_constants.cc
+++ b/chrome/common/url_constants.cc
@@ -398,6 +398,9 @@
 const char kOnlineEulaURLPath[] =
     "https://policies.google.com/terms/embedded?hl=%s";
 
+const char kPhoneHubLearnMoreLink[] =
+    "https://support.google.com/chromebook?p=phone_hub";
+
 const char kAdditionalToSOnlineURLPath[] =
     "https://www.google.com/intl/%s/chrome/terms/";
 
diff --git a/chrome/common/url_constants.h b/chrome/common/url_constants.h
index 6ad80524..9bc91bf 100644
--- a/chrome/common/url_constants.h
+++ b/chrome/common/url_constants.h
@@ -364,6 +364,9 @@
 
 extern const char kOnlineEulaURLPath[];
 
+// The URL for the help center article about PhoneHub.
+extern const char kPhoneHubLearnMoreLink[];
+
 extern const char kAdditionalToSOnlineURLPath[];
 
 // The URL for the "learn more" link for TPM firmware update.
diff --git a/chrome/test/chromedriver/js/get_element_region.js b/chrome/test/chromedriver/js/get_element_region.js
index 6014b59..472db87 100644
--- a/chrome/test/chromedriver/js/get_element_region.js
+++ b/chrome/test/chromedriver/js/get_element_region.js
@@ -18,10 +18,10 @@
     // Given two regions, determines if any intersection occurs.
     // Overlapping edges are not considered intersections.
     function getIntersectingSubregion(region1, region2) {
-      if (!(region2.right  <= region1.left   ||
-            region2.left   >= region1.right  ||
-            region2.top    >= region1.bottom ||
-            region2.bottom <= region1.top)) {
+      if (!(Math.round(region2.right)  <= Math.round(region1.left)   ||
+            Math.round(region2.left)   >= Math.round(region1.right)  ||
+            Math.round(region2.top)    >= Math.round(region1.bottom) ||
+            Math.round(region2.bottom) <= Math.round(region1.top))) {
         // Determines region of intersection.
         // If region2 contains region1, returns region1.
         // If region1 contains region2, returns region2.
diff --git a/chrome/test/chromedriver/js/get_element_region_test.html b/chrome/test/chromedriver/js/get_element_region_test.html
index 7c070f45..13c94f2 100644
--- a/chrome/test/chromedriver/js/get_element_region_test.html
+++ b/chrome/test/chromedriver/js/get_element_region_test.html
@@ -73,6 +73,25 @@
   window.scrollTo(0, 0);
 }
 
+function testScrolledPartiallyOutOfView() {
+  // Scroll to an offset to make element with id=a partially visible.
+  document.body.style.paddingTop = '0.25px';
+  document.body.style.paddingLeft = '0.25px';
+  var elem = document.getElementById("check");
+  window.scrollTo(
+    elem.offsetLeft + elem.offsetWidth,
+    elem.offsetTop + elem.offsetHeight,
+  );
+  var region = getElementRegion(elem);
+  assertEquals(0, region.left);
+  assertEquals(0, region.top);
+  assertEquals(elem.offsetWidth, region.width);
+  assertEquals(elem.offsetHeight, region.height);
+  window.scrollTo(0, 0);
+  document.body.style.paddingTop = '';
+  document.body.style.paddingLeft = '';
+}
+
 function testFullOutOfView() {
   var region = getElementRegion(document.getElementById('out-of-view'));
   assertEquals(0, region.left);
@@ -186,6 +205,8 @@
   <!-- This element adds scroll to see how script handles viewport with scroll -->
   <div style="background-color:red;width:50px;height:50px;position:absolute;top:200vh;left:200vw;">
   </div>
+  <input type="checkbox" id="check">
+  <div style="height:4000px"></div>
 
 </div>
 </body>
diff --git a/chrome/test/data/pdf/BUILD.gn b/chrome/test/data/pdf/BUILD.gn
index dd3c010..37d8fb79 100644
--- a/chrome/test/data/pdf/BUILD.gn
+++ b/chrome/test/data/pdf/BUILD.gn
@@ -133,6 +133,7 @@
     ":test_util",
     "../webui:test_util.m",
     "//chrome/browser/resources/pdf:constants",
+    "//chrome/browser/resources/pdf:pdf_scripting_api",
     "//chrome/browser/resources/pdf:pdf_viewer",
     "//third_party/polymer/v3_0/components-chromium/iron-test-helpers:mock-interactions",
     "//ui/webui/resources/js:cr.m",
diff --git a/chrome/test/data/pdf/fullscreen_test.js b/chrome/test/data/pdf/fullscreen_test.js
index 4eca3c8..6fdca035a 100644
--- a/chrome/test/data/pdf/fullscreen_test.js
+++ b/chrome/test/data/pdf/fullscreen_test.js
@@ -4,6 +4,7 @@
 
 import {eventToPromise} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/_test_resources/webui/test_util.m.js';
 import {FittingType} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/constants.js';
+import {PDFScriptingAPI} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/pdf_scripting_api.js';
 import {PDFViewerElement} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/pdf_viewer.js';
 import {isMac} from 'chrome://resources/js/cr.m.js';
 import {keyDownOn} from 'chrome://resources/polymer/v3_0/iron-test-helpers/mock-interactions.js';
@@ -128,6 +129,17 @@
 
     chrome.test.succeed();
   },
+  async function testTextSelectionDisabled() {
+    await ensureFullscreen();
+
+    const client = new PDFScriptingAPI(window, window);
+    client.selectAll();
+    client.getSelectedText(selectedText => {
+      // No text should be selected.
+      chrome.test.assertEq(0, selectedText.length);
+      chrome.test.succeed();
+    });
+  },
 ];
 
 chrome.test.runTests(tests);
diff --git a/chrome/test/data/webui/interventions_internals_browsertest.js b/chrome/test/data/webui/interventions_internals_browsertest.js
index 280404a..19abf07 100644
--- a/chrome/test/data/webui/interventions_internals_browsertest.js
+++ b/chrome/test/data/webui/interventions_internals_browsertest.js
@@ -14,7 +14,7 @@
  * @extends testing.Test
  */
 function InterventionsInternalsUITest() {
-  this.setupFnResolver = new PromiseResolver();
+  window.setupFnResolver = new PromiseResolver();
 }
 
 InterventionsInternalsUITest.prototype = {
@@ -34,595 +34,52 @@
     '//chrome/test/data/webui/mocha_adapter.js',
     '//ui/webui/resources/js/assert.js',
     '//ui/webui/resources/js/promise_resolver.js',
-    '//ui/webui/resources/js/util.js',
-    '//chrome/test/data/webui/test_browser_proxy.js',
   ],
 
   preLoad: function() {
-    /**
-     * A stub class for the Mojo PageHandler.
-     */
-    class TestPageHandler extends TestBrowserProxy {
-      constructor() {
-        super(['getPreviewsEnabled', 'getPreviewsFlagsDetails']);
-
-        /** @private {!Map} */
-        this.previewsModeStatuses_ = new Map();
-        this.previewsFlagsStatuses_ = new Map();
-      }
-
-      /**
-       * Setup testing map for getPreviewsEnabled.
-       * @param {!Map} map The testing status map.
-       */
-      setTestingPreviewsModeMap(map) {
-        this.previewsModeStatuses_ = map;
-      }
-
-      setTestingPreviewsFlagsMap(map) {
-        this.previewsFlagsStatuses_ = map;
-      }
-
-      /** @override **/
-      getPreviewsEnabled() {
-        this.methodCalled('getPreviewsEnabled');
-        return Promise.resolve({
-          statuses: this.previewsModeStatuses_,
-        });
-      }
-
-      /** @override **/
-      getPreviewsFlagsDetails() {
-        this.methodCalled('getPreviewsFlagsDetails');
-        return Promise.resolve({
-          flags: this.previewsFlagsStatuses_,
-        });
-      }
-    }
-
     window.setupFn = function() {
-      return this.setupFnResolver.promise;
-    }.bind(this);
-
-    window.testPageHandler = new TestPageHandler();
-
-    getBlocklistedStatus = function(blocklisted) {
-      return (blocklisted ? 'Blocklisted' : 'Not blocklisted');
+      return window.setupFnResolver.promise;
     };
   },
 };
 
-TEST_F('InterventionsInternalsUITest', 'GetPreviewsEnabled', function() {
-  let setupFnResolver = this.setupFnResolver;
-
-  test('DisplayCorrectStatuses', () => {
-    // Setup testPageHandler behavior.
-    let testArray = [
-      {
-        htmlId: 'params1',
-        description: 'Params 1',
-        enabled: true,
-      },
-      {
-        htmlId: 'params2',
-        description: 'Params 2',
-        enabled: false,
-      },
-      {
-        htmlId: 'params3',
-        description: 'Param 3',
-        enabled: false,
-      },
-    ];
-
-    window.testPageHandler.setTestingPreviewsModeMap(testArray);
-    this.setupFnResolver.resolve();
-
-    return setupFnResolver.promise
-        .then(() => {
-          return window.testPageHandler.whenCalled('getPreviewsEnabled');
-        })
-        .then(() => {
-          testArray.forEach((value) => {
-            let expected = value.description + ': ' +
-                (value.enabled ? 'Enabled' : 'Disabled');
-            let actual = document.querySelector('#' + value.htmlId).textContent;
-            expectEquals(expected, actual);
-          });
-        });
-  });
-
-  mocha.run();
-});
-
-TEST_F('InterventionsInternalsUITest', 'GetPreviewsFlagsDetails', function() {
-  let setupFnResolver = this.setupFnResolver;
-
-  test('DisplayCorrectStatuses', () => {
-    // Setup testPageHandler behavior.
-    let testArray = [
-      {
-        htmlId: 'params2',
-        description: 'Params 2',
-        link: 'Link 2',
-        value: 'Value 2',
-      },
-      {
-        htmlId: 'params3',
-        description: 'Param 3',
-        link: 'Link 3',
-        value: 'Value 3',
-      },
-      {
-        htmlId: 'params1',
-        description: 'Params 1',
-        link: 'Link 1',
-        value: 'Value 1',
-      },
-    ];
-
-    window.testPageHandler.setTestingPreviewsFlagsMap(testArray);
-    this.setupFnResolver.resolve();
-
-    return setupFnResolver.promise
-        .then(() => {
-          return window.testPageHandler.whenCalled('getPreviewsFlagsDetails');
-        })
-        .then(() => {
-          testArray.forEach((value) => {
-            let key = value.htmlId;
-            let actualDescription =
-                document.querySelector('#' + key + 'Description');
-            let actualValue = document.querySelector('#' + key + 'Value');
-            expectEquals(value.description, actualDescription.textContent);
-            expectEquals(value.link, actualDescription.getAttribute('href'));
-            expectEquals(value.value, actualValue.textContent);
-          });
-        });
-  });
-
-  mocha.run();
-});
-
-TEST_F('InterventionsInternalsUITest', 'LogNewMessage', function() {
-  test('LogMessageIsPostedCorrectly', () => {
-    let pageImpl = new window.InterventionsInternalPageImpl(null);
-    let logs = [
-      {
-        type: 'Type_a',
-        description: 'Some description_a',
-        url: {url: 'Some gurl.spec()_a'},
-        time: 1507221689240,  // Oct 05 2017 16:41:29 UTC
-        pageId: 0,
-      },
-      {
-        type: 'Type_b',
-        description: 'Some description_b',
-        url: {url: 'Some gurl.spec()_b'},
-        time: 758675653000,  // Jan 15 1994 23:14:13 UTC
-        pageId: 0,
-      },
-      {
-        type: 'Type_c',
-        description: 'Some description_c',
-        url: {url: 'Some gurl.spec()_c'},
-        time: -314307870000,  // Jan 16 1960 04:15:30 UTC
-        pageId: 0,
-      },
-    ];
-
-    logs.forEach((log) => {
-      pageImpl.logNewMessage(log);
-    });
-
-    let rows = $('message-logs-table').querySelectorAll('.log-message');
-    expectEquals(logs.length, rows.length);
-
-    logs.forEach((log, index) => {
-      let row = rows[logs.length - index - 1];  // Expecting reversed order.
-                                                // (i.e. a new log message is
-                                                // appended to the top of the
-                                                // log table).
-
-      expectEquals(
-          window.getTimeFormat(log.time), row.querySelector('.log-time').textContent);
-      expectEquals(log.type, row.querySelector('.log-type').textContent);
-      expectEquals(
-          log.description, row.querySelector('.log-description').textContent);
-      expectEquals(
-          log.url.url, row.querySelector('.log-url-value').textContent);
-    });
-  });
-
-  mocha.run();
-});
-
-TEST_F('InterventionsInternalsUITest', 'LogNewMessageWithLongUrl', function() {
-  test('LogMessageIsPostedCorrectly', () => {
-    let pageImpl = new window.InterventionsInternalPageImpl(null);
-    let log = {
-      type: 'Some type',
-      url: {url: ''},
-      description: 'Some description',
-      time: 758675653000,  // Jan 15 1994 23:14:13 UTC
-      pageId: 0,
-    };
-    // Creating long url.
-    for (let i = 0; i <= 2 * URL_THRESHOLD; i++) {
-      log.url.url += 'a';
-    }
-    let expectedUrl = log.url.url.substring(0, URL_THRESHOLD - 3) + '...';
-
-    pageImpl.logNewMessage(log);
-    expectEquals(
-        expectedUrl, document.querySelector('div.log-url-value').textContent);
-  });
-
-  mocha.run();
-});
-
-TEST_F('InterventionsInternalsUITest', 'LogNewMessageWithNoUrl', function() {
-  test('LogMessageIsPostedCorrectly', () => {
-    let pageImpl = new window.InterventionsInternalPageImpl(null);
-    let log = {
-      type: 'Some type',
-      url: {url: ''},
-      description: 'Some description',
-      time: 758675653000,  // Jan 15 1994 23:14:13 UTC
-      pageId: 0,
-    };
-    pageImpl.logNewMessage(log);
-    let actual = $('message-logs-table').rows[1];
-    let expectedNoColumns = 3;
-    expectEquals(expectedNoColumns, actual.querySelectorAll('td').length);
-    assert(
-        !actual.querySelector('.log-url'),
-        'There should not be a log-url column for empty URL');
-  });
-
-  mocha.run();
-});
-
-TEST_F('InterventionsInternalsUITest', 'LogNewMessagePageIdZero', function() {
-  test('LogMessageWithPageIdZero', () => {
-    let pageImpl = new window.InterventionsInternalPageImpl(null);
-    let logs = [
-      {
-        type: 'Type_a',
-        description: 'Some description_a',
-        url: {url: 'Some gurl.spec()_a'},
-        time: 1507221689240,  // Oct 05 2017 16:41:29 UTC
-        pageId: 0,
-      },
-      {
-        type: 'Type_b',
-        description: 'Some description_b',
-        url: {url: 'Some gurl.spec()_b'},
-        time: 758675653000,  // Jan 15 1994 23:14:13 UTC
-        pageId: 0,
-      },
-    ];
-
-    logs.forEach((log) => {
-      pageImpl.logNewMessage(log);
-    });
-
-    // Expect 2 different rows in logs table.
-    let rows = $('message-logs-table').querySelectorAll('.log-message');
-    let expectedNumberOfRows = 2;
-    expectEquals(expectedNumberOfRows, rows.length);
-
-    logs.forEach((log, index) => {
-      let expectedTime = getTimeFormat(log.time);
-      let row = rows[logs.length - index - 1];
-
-      expectEquals(expectedTime, row.querySelector('.log-time').textContent);
-      expectEquals(log.type, row.querySelector('.log-type').textContent);
-      expectEquals(
-          log.description, row.querySelector('.log-description').textContent);
-      expectEquals(
-          log.url.url, row.querySelector('.log-url-value').textContent);
-    });
-  });
-
-  mocha.run();
-});
-
-TEST_F('InterventionsInternalsUITest', 'LogNewMessageNewPageId', function() {
-  test('LogMessageWithNewPageId', () => {
-    let pageImpl = new window.InterventionsInternalPageImpl(null);
-    let logs = [
-      {
-        type: 'Type_a',
-        description: 'Some description_a',
-        url: {url: 'Some gurl.spec()_a'},
-        time: 1507221689240,  // Oct 05 2017 16:41:29 UTC
-        pageId: 123,
-      },
-      {
-        type: 'Type_b',
-        description: 'Some description_b',
-        url: {url: 'Some gurl.spec()_b'},
-        time: 758675653000,  // Jan 15 1994 23:14:13 UTC
-        pageId: 321,
-      },
-    ];
-
-    logs.forEach((log) => {
-      pageImpl.logNewMessage(log);
-    });
-
-    // Expect 2 different rows in logs table.
-    let rows = $('message-logs-table').querySelectorAll('.log-message');
-    expectEquals(2, rows.length);
-
-    logs.forEach((log, index) => {
-      let expectedTime = getTimeFormat(log.time);
-      let row = rows[logs.length - index - 1];
-
-      expectEquals(expectedTime, row.querySelector('.log-time').textContent);
-      expectEquals(log.type, row.querySelector('.log-type').textContent);
-      expectEquals(
-          log.description, row.querySelector('.log-description').textContent);
-      expectEquals(
-          log.url.url, row.querySelector('.log-url-value').textContent);
-    });
-  });
-
-  mocha.run();
-});
-
-TEST_F(
-    'InterventionsInternalsUITest', 'LogNewMessageExistedPageId', function() {
-      test('LogMessageWithExistedPageId', () => {
-        let pageImpl = new window.InterventionsInternalPageImpl(null);
-        let logs = [
-          {
-            type: 'Type_a',
-            description: 'Some description_a',
-            url: {url: 'Some gurl.spec()_a'},
-            time: 1507221689240,  // Oct 05 2017 16:41:29 UTC
-            pageId: 3,
-          },
-          {
-            type: 'Type_b',
-            description: 'Some description_b',
-            url: {url: 'Some gurl.spec()_b'},
-            time: 758675653000,  // Jan 15 1994 23:14:13 UTC
-            pageId: 3,
-          },
-        ];
-
-        logs.forEach((log) => {
-          pageImpl.logNewMessage(log);
-        });
-
-        let logTableRows =
-            $('message-logs-table').querySelectorAll('.log-message');
-        expectEquals(1, logTableRows.length);
-        expectEquals(
-            1, document.querySelector('.expansion-logs-table').rows.length);
-
-        // Log table row.
-        let row = $('message-logs-table').querySelector('.log-message');
-        let expectedRowTime = getTimeFormat(logs[1].time);
-        expectEquals(
-            expectedRowTime, row.querySelector('.log-time').textContent);
-        expectEquals(logs[1].type, row.querySelector('.log-type').textContent);
-        expectEquals(
-            logs[1].description,
-            row.querySelector('.log-description').textContent);
-        expectEquals(
-            logs[1].url.url, row.querySelector('.log-url-value').textContent);
-
-        // Sub log table row.
-        let subRow = document.querySelector('.expansion-logs-table').rows[0];
-        let expectedSubTime = getTimeFormat(logs[0].time);
-        expectEquals(
-            expectedSubTime, subRow.querySelector('.log-time').textContent);
-        expectEquals(
-            logs[0].type, subRow.querySelector('.log-type').textContent);
-        expectEquals(
-            logs[0].description,
-            subRow.querySelector('.log-description').textContent);
-        expectEquals(
-            logs[0].url.url,
-            subRow.querySelector('.log-url-value').textContent);
+// Helper for loading the Mocha test file as a JS module. Not using
+// test_loader.html, as the test code needs to be loaded in the context of the
+// entire UI.
+function loadTestModule() {
+  const scriptPolicy =
+      window.trustedTypes.createPolicy('interventions-internals-test-script', {
+        createScriptURL: () => 'chrome://test/interventions_internals_test.js',
       });
-
-      mocha.run();
-    });
-
-TEST_F(
-    'InterventionsInternalsUITest',
-    'LogNewMessageExistedPageIdGroupToTopOfTable', function() {
-      test('NewMessagePushedToTopOfTable', () => {
-        let pageImpl = new window.InterventionsInternalPageImpl(null);
-        let logs = [
-          {
-            type: 'Type_a',
-            description: 'Some description_a',
-            url: {url: 'Some gurl.spec()_a'},
-            time: 0,
-            pageId: 3,
-          },
-          {
-            type: 'Type_b',
-            description: 'Some description_b',
-            url: {url: 'Some gurl.spec()_b'},
-            time: 1,
-            pageId: 123,
-          },
-          {
-            type: 'Type_c',
-            description: 'Some description_c',
-            url: {url: 'Some gurl.spec()_c'},
-            time: 2,
-            pageId: 3,
-          },
-        ];
-
-        pageImpl.logNewMessage(logs[0]);
-        pageImpl.logNewMessage(logs[1]);
-        let rows = $('message-logs-table').querySelectorAll('.log-message');
-        expectEquals(2, rows.length);
-        expectEquals(
-            logs[1].type, rows[0].querySelector('.log-type').textContent);
-        expectEquals(
-            logs[0].type, rows[1].querySelector('.log-type').textContent);
-
-        // Existing group pushed to the top of the log table.
-        pageImpl.logNewMessage(logs[2]);
-        rows = $('message-logs-table').querySelectorAll('.log-message');
-        expectEquals(2, rows.length);
-        expectEquals(
-            logs[2].type, rows[0].querySelector('.log-type').textContent);
-        expectEquals(
-            logs[1].type, rows[1].querySelector('.log-type').textContent);
-      });
-
-      mocha.run();
-    });
-
-TEST_F('InterventionsInternalsUITest', 'AddNewBlocklistedHost', function() {
-  test('AddNewBlocklistedHost', () => {
-    let pageImpl = new window.InterventionsInternalPageImpl(null);
-    let time = 758675653000;  // Jan 15 1994 23:14:13 UTC
-    let expectedHost = 'example.com';
-    pageImpl.onBlocklistedHost(expectedHost, time);
-
-    let blocklistedTable = $('blocklisted-hosts-table');
-    let row = blocklistedTable.querySelector('.blocklisted-host-row');
-
-    let expectedTime = getTimeFormat(time);
-
-    expectEquals(
-        expectedHost, row.querySelector('.host-blocklisted').textContent);
-    expectEquals(
-        expectedTime, row.querySelector('.host-blocklisted-time').textContent);
+  const s = document.createElement('script');
+  s.type = 'module';
+  s.src = scriptPolicy.createScriptURL('');
+  document.body.appendChild(s);
+  return new Promise(function(resolve, reject) {
+    s.addEventListener('load', () => resolve());
   });
+}
 
-  mocha.run();
-});
-
-TEST_F('InterventionsInternalsUITest', 'HostAlreadyBlocklisted', function() {
-  test('HostAlreadyBlocklisted', () => {
-    let pageImpl = new window.InterventionsInternalPageImpl(null);
-    let time0 = 758675653000;   // Jan 15 1994 23:14:13 UTC
-    let time1 = 1507221689240;  // Oct 05 2017 16:41:29 UTC
-    let expectedHost = 'example.com';
-
-    pageImpl.onBlocklistedHost(expectedHost, time0);
-
-    let blocklistedTable = $('blocklisted-hosts-table');
-    let row = blocklistedTable.querySelector('.blocklisted-host-row');
-    let expectedTime = getTimeFormat(time0);
-    expectEquals(
-        expectedHost, row.querySelector('.host-blocklisted').textContent);
-    expectEquals(
-        expectedTime, row.querySelector('.host-blocklisted-time').textContent);
-
-    pageImpl.onBlocklistedHost(expectedHost, time1);
-
-    // The row remains the same.
-    expectEquals(
-        expectedHost, row.querySelector('.host-blocklisted').textContent);
-    expectEquals(
-        expectedTime, row.querySelector('.host-blocklisted-time').textContent);
-  });
-
-  mocha.run();
-});
-
-TEST_F('InterventionsInternalsUITest', 'UpdateUserBlocklisted', function() {
-  test('UpdateUserBlocklistedDisplayCorrectly', () => {
-    let pageImpl = new window.InterventionsInternalPageImpl(null);
-    let state = $('user-blocklisted-status-value');
-
-    pageImpl.onUserBlocklistedStatusChange(true /* blocklisted */);
-    expectEquals(
-        getBlocklistedStatus(true /* blocklisted */), state.textContent);
-
-    pageImpl.onUserBlocklistedStatusChange(false /* blocklisted */);
-    expectEquals(
-        getBlocklistedStatus(false /* blocklisted */), state.textContent);
-  });
-
-  mocha.run();
-});
-
-TEST_F('InterventionsInternalsUITest', 'OnBlocklistCleared', function() {
-  test('OnBlocklistClearedRemovesAllBlocklistedHostInTable', () => {
-    let pageImpl = new window.InterventionsInternalPageImpl(null);
-    let state = $('user-blocklisted-status-value');
-    let time = 758675653000;  // Jan 15 1994 23:14:13 UTC
-
-    pageImpl.onBlocklistCleared(time);
-    let actualClearedTime = $('blocklist-last-cleared-time').textContent;
-    expectEquals(getTimeFormat(time), actualClearedTime);
-    let blocklistedTable = $('blocklisted-hosts-table');
-    let rows = blocklistedTable.querySelectorAll('.blocklisted-host-row');
-    expectEquals(0, rows.length);
-  });
-
-  mocha.run();
-});
-
-TEST_F(
-    'InterventionsInternalsUITest', 'ClearLogMessageOnBlocklistCleared',
-    function() {
-      test('ClearLogsTableOnBlocklistCleared', () => {
-        let pageImpl = new window.InterventionsInternalPageImpl(null);
-        let time = 758675653000;  // Jan 15 1994 23:14:13 UTC
-        let log = {
-          type: 'Some type',
-          url: {url: ''},
-          description: 'Some description',
-          time: 758675653000,  // Jan 15 1994 23:14:13 UTC
-          pageId: 0,
-        };
-
-        pageImpl.logNewMessage(log);
-        expectGT($('message-logs-table').rows.length, 1 /* header row */);
-        pageImpl.onBlocklistCleared(time);
-        let expectedNumberOfRows = 2;  // header row and clear blocklist log.
-        let rows = $('message-logs-table').rows;
-        expectEquals(expectedNumberOfRows, rows.length);
-        expectEquals(
-            'Blocklist Cleared',
-            rows[1].querySelector('.log-description').textContent);
-      });
-
-      mocha.run();
-    });
-
-TEST_F('InterventionsInternalsUITest', 'OnECTChanged', function() {
-  test('UpdateETCOnChange', () => {
-    let pageImpl = new window.InterventionsInternalPageImpl(null);
-    let ectTypes = ['type1', 'type2', 'type3'];
-    ectTypes.forEach((type) => {
-      pageImpl.updateEffectiveConnectionType(type, 'max');
-      let actual = $('nqe-type').textContent;
-      expectEquals(type, actual);
+['GetPreviewsEnabled',
+ 'GetPreviewsFlagsDetails',
+ 'LogNewMessage',
+ 'LogNewMessageWithLongUrl',
+ 'LogNewMessageWithNoUrl',
+ 'LogNewMessagePageIdZero',
+ 'LogNewMessageNewPageId',
+ 'LogNewMessageExistedPageId',
+ 'LogNewMessageExistedPageIdGroupToTopOfTable',
+ 'AddNewBlocklistedHost',
+ 'HostAlreadyBlocklisted',
+ 'UpdateUserBlocklisted',
+ 'OnBlocklistCleared',
+ 'ClearLogMessageOnBlocklistCleared',
+ 'OnECTChanged',
+ 'OnBlocklistIgnoreChange',
+].forEach(name => {
+  TEST_F('InterventionsInternalsUITest', name, function() {
+    loadTestModule().then(() => {
+      runMochaTest('InterventionsInternalsUITest', name);
     });
   });
-
-  mocha.run();
-});
-
-TEST_F('InterventionsInternalsUITest', 'OnBlocklistIgnoreChange', function() {
-  test('OnBlocklistIgnoreChangeDisable', () => {
-    let pageImpl = new window.InterventionsInternalPageImpl(null);
-    pageImpl.onIgnoreBlocklistDecisionStatusChanged(true /* ignored */);
-    expectEquals('Enable Blocklist', $('ignore-blocklist-button').textContent);
-    expectEquals(
-        'Blocklist decisions are ignored.',
-        $('blocklist-ignored-status').textContent);
-
-    pageImpl.onIgnoreBlocklistDecisionStatusChanged(false /* ignored */);
-    expectEquals('Ignore Blocklist', $('ignore-blocklist-button').textContent);
-    expectEquals('', $('blocklist-ignored-status').textContent);
-  });
-
-  mocha.run();
 });
diff --git a/chrome/test/data/webui/interventions_internals_test.js b/chrome/test/data/webui/interventions_internals_test.js
new file mode 100644
index 0000000..2537a2f
--- /dev/null
+++ b/chrome/test/data/webui/interventions_internals_test.js
@@ -0,0 +1,518 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {getTimeFormat, InterventionsInternalPageImpl, URL_THRESHOLD} from 'chrome://interventions-internals/index.js';
+import {$} from 'chrome://resources/js/util.m.js';
+
+import {TestBrowserProxy} from './test_browser_proxy.m.js';
+
+suite('InterventionsInternalsUITest', function() {
+  /**
+   * A stub class for the Mojo PageHandler.
+   */
+  class TestPageHandler extends TestBrowserProxy {
+    constructor() {
+      super(['getPreviewsEnabled', 'getPreviewsFlagsDetails']);
+
+      /** @private {!Map} */
+      this.previewsModeStatuses_ = new Map();
+      this.previewsFlagsStatuses_ = new Map();
+    }
+
+    /**
+     * Setup testing map for getPreviewsEnabled.
+     * @param {!Map} map The testing status map.
+     */
+    setTestingPreviewsModeMap(map) {
+      this.previewsModeStatuses_ = map;
+    }
+
+    setTestingPreviewsFlagsMap(map) {
+      this.previewsFlagsStatuses_ = map;
+    }
+
+    /** @override **/
+    getPreviewsEnabled() {
+      this.methodCalled('getPreviewsEnabled');
+      return Promise.resolve({
+        statuses: this.previewsModeStatuses_,
+      });
+    }
+
+    /** @override **/
+    getPreviewsFlagsDetails() {
+      this.methodCalled('getPreviewsFlagsDetails');
+      return Promise.resolve({
+        flags: this.previewsFlagsStatuses_,
+      });
+    }
+  }
+
+  function getBlocklistedStatus(blocklisted) {
+    return (blocklisted ? 'Blocklisted' : 'Not blocklisted');
+  }
+
+  let testPageHandler = null;
+
+  setup(function() {
+    testPageHandler = new TestPageHandler();
+    window.testPageHandler = testPageHandler;
+  });
+
+  test('GetPreviewsEnabled', () => {
+    // Setup testPageHandler behavior.
+    let testArray = [
+      {
+        htmlId: 'params1',
+        description: 'Params 1',
+        enabled: true,
+      },
+      {
+        htmlId: 'params2',
+        description: 'Params 2',
+        enabled: false,
+      },
+      {
+        htmlId: 'params3',
+        description: 'Param 3',
+        enabled: false,
+      },
+    ];
+
+    testPageHandler.setTestingPreviewsModeMap(testArray);
+    window.setupFnResolver.resolve();
+
+    return window.setupFnResolver.promise
+        .then(() => {
+          return testPageHandler.whenCalled('getPreviewsEnabled');
+        })
+        .then(() => {
+          testArray.forEach((value) => {
+            let expected = value.description + ': ' +
+                (value.enabled ? 'Enabled' : 'Disabled');
+            let actual = document.querySelector('#' + value.htmlId).textContent;
+            expectEquals(expected, actual);
+          });
+        });
+  });
+
+  test('GetPreviewsFlagsDetails', () => {
+    // Setup testPageHandler behavior.
+    let testArray = [
+      {
+        htmlId: 'params2',
+        description: 'Params 2',
+        link: 'Link 2',
+        value: 'Value 2',
+      },
+      {
+        htmlId: 'params3',
+        description: 'Param 3',
+        link: 'Link 3',
+        value: 'Value 3',
+      },
+      {
+        htmlId: 'params1',
+        description: 'Params 1',
+        link: 'Link 1',
+        value: 'Value 1',
+      },
+    ];
+
+    testPageHandler.setTestingPreviewsFlagsMap(testArray);
+    window.setupFnResolver.resolve();
+
+    return window.setupFnResolver.promise
+        .then(() => {
+          return testPageHandler.whenCalled('getPreviewsFlagsDetails');
+        })
+        .then(() => {
+          testArray.forEach((value) => {
+            let key = value.htmlId;
+            let actualDescription =
+                document.querySelector('#' + key + 'Description');
+            let actualValue = document.querySelector('#' + key + 'Value');
+            expectEquals(value.description, actualDescription.textContent);
+            expectEquals(value.link, actualDescription.getAttribute('href'));
+            expectEquals(value.value, actualValue.textContent);
+          });
+        });
+  });
+
+  test('LogNewMessage', () => {
+    let pageImpl = new InterventionsInternalPageImpl(null);
+    let logs = [
+      {
+        type: 'Type_a',
+        description: 'Some description_a',
+        url: {url: 'Some gurl.spec()_a'},
+        time: 1507221689240,  // Oct 05 2017 16:41:29 UTC
+        pageId: 0,
+      },
+      {
+        type: 'Type_b',
+        description: 'Some description_b',
+        url: {url: 'Some gurl.spec()_b'},
+        time: 758675653000,  // Jan 15 1994 23:14:13 UTC
+        pageId: 0,
+      },
+      {
+        type: 'Type_c',
+        description: 'Some description_c',
+        url: {url: 'Some gurl.spec()_c'},
+        time: -314307870000,  // Jan 16 1960 04:15:30 UTC
+        pageId: 0,
+      },
+    ];
+
+    logs.forEach((log) => {
+      pageImpl.logNewMessage(log);
+    });
+
+    let rows = $('message-logs-table').querySelectorAll('.log-message');
+    expectEquals(logs.length, rows.length);
+
+    logs.forEach((log, index) => {
+      let row = rows[logs.length - index - 1];  // Expecting reversed order.
+                                                // (i.e. a new log message is
+                                                // appended to the top of the
+                                                // log table).
+
+      expectEquals(
+          getTimeFormat(log.time), row.querySelector('.log-time').textContent);
+      expectEquals(log.type, row.querySelector('.log-type').textContent);
+      expectEquals(
+          log.description, row.querySelector('.log-description').textContent);
+      expectEquals(
+          log.url.url, row.querySelector('.log-url-value').textContent);
+    });
+  });
+
+  test('LogNewMessageWithLongUrl', () => {
+    let pageImpl = new InterventionsInternalPageImpl(null);
+    let log = {
+      type: 'Some type',
+      url: {url: ''},
+      description: 'Some description',
+      time: 758675653000,  // Jan 15 1994 23:14:13 UTC
+      pageId: 0,
+    };
+    // Creating long url.
+    for (let i = 0; i <= 2 * URL_THRESHOLD; i++) {
+      log.url.url += 'a';
+    }
+    let expectedUrl = log.url.url.substring(0, URL_THRESHOLD - 3) + '...';
+
+    pageImpl.logNewMessage(log);
+    expectEquals(
+        expectedUrl, document.querySelector('div.log-url-value').textContent);
+  });
+
+
+  test('LogNewMessageWithNoUrl', () => {
+    let pageImpl = new InterventionsInternalPageImpl(null);
+    let log = {
+      type: 'Some type',
+      url: {url: ''},
+      description: 'Some description',
+      time: 758675653000,  // Jan 15 1994 23:14:13 UTC
+      pageId: 0,
+    };
+    pageImpl.logNewMessage(log);
+    let actual = $('message-logs-table').rows[1];
+    let expectedNoColumns = 3;
+    expectEquals(expectedNoColumns, actual.querySelectorAll('td').length);
+    assert(
+        !actual.querySelector('.log-url'),
+        'There should not be a log-url column for empty URL');
+  });
+
+  test('LogNewMessagePageIdZero', () => {
+    let pageImpl = new InterventionsInternalPageImpl(null);
+    let logs = [
+      {
+        type: 'Type_a',
+        description: 'Some description_a',
+        url: {url: 'Some gurl.spec()_a'},
+        time: 1507221689240,  // Oct 05 2017 16:41:29 UTC
+        pageId: 0,
+      },
+      {
+        type: 'Type_b',
+        description: 'Some description_b',
+        url: {url: 'Some gurl.spec()_b'},
+        time: 758675653000,  // Jan 15 1994 23:14:13 UTC
+        pageId: 0,
+      },
+    ];
+
+    logs.forEach((log) => {
+      pageImpl.logNewMessage(log);
+    });
+
+    // Expect 2 different rows in logs table.
+    let rows = $('message-logs-table').querySelectorAll('.log-message');
+    let expectedNumberOfRows = 2;
+    expectEquals(expectedNumberOfRows, rows.length);
+
+    logs.forEach((log, index) => {
+      let expectedTime = getTimeFormat(log.time);
+      let row = rows[logs.length - index - 1];
+
+      expectEquals(expectedTime, row.querySelector('.log-time').textContent);
+      expectEquals(log.type, row.querySelector('.log-type').textContent);
+      expectEquals(
+          log.description, row.querySelector('.log-description').textContent);
+      expectEquals(
+          log.url.url, row.querySelector('.log-url-value').textContent);
+    });
+  });
+
+  test('LogNewMessageNewPageId', () => {
+    let pageImpl = new InterventionsInternalPageImpl(null);
+    let logs = [
+      {
+        type: 'Type_a',
+        description: 'Some description_a',
+        url: {url: 'Some gurl.spec()_a'},
+        time: 1507221689240,  // Oct 05 2017 16:41:29 UTC
+        pageId: 123,
+      },
+      {
+        type: 'Type_b',
+        description: 'Some description_b',
+        url: {url: 'Some gurl.spec()_b'},
+        time: 758675653000,  // Jan 15 1994 23:14:13 UTC
+        pageId: 321,
+      },
+    ];
+
+    logs.forEach((log) => {
+      pageImpl.logNewMessage(log);
+    });
+
+    // Expect 2 different rows in logs table.
+    let rows = $('message-logs-table').querySelectorAll('.log-message');
+    expectEquals(2, rows.length);
+
+    logs.forEach((log, index) => {
+      let expectedTime = getTimeFormat(log.time);
+      let row = rows[logs.length - index - 1];
+
+      expectEquals(expectedTime, row.querySelector('.log-time').textContent);
+      expectEquals(log.type, row.querySelector('.log-type').textContent);
+      expectEquals(
+          log.description, row.querySelector('.log-description').textContent);
+      expectEquals(
+          log.url.url, row.querySelector('.log-url-value').textContent);
+    });
+  });
+
+  test('LogNewMessageExistedPageId', () => {
+    let pageImpl = new InterventionsInternalPageImpl(null);
+    let logs = [
+      {
+        type: 'Type_a',
+        description: 'Some description_a',
+        url: {url: 'Some gurl.spec()_a'},
+        time: 1507221689240,  // Oct 05 2017 16:41:29 UTC
+        pageId: 3,
+      },
+      {
+        type: 'Type_b',
+        description: 'Some description_b',
+        url: {url: 'Some gurl.spec()_b'},
+        time: 758675653000,  // Jan 15 1994 23:14:13 UTC
+        pageId: 3,
+      },
+    ];
+
+    logs.forEach((log) => {
+      pageImpl.logNewMessage(log);
+    });
+
+    let logTableRows = $('message-logs-table').querySelectorAll('.log-message');
+    expectEquals(1, logTableRows.length);
+    expectEquals(
+        1, document.querySelector('.expansion-logs-table').rows.length);
+
+    // Log table row.
+    let row = $('message-logs-table').querySelector('.log-message');
+    let expectedRowTime = getTimeFormat(logs[1].time);
+    expectEquals(expectedRowTime, row.querySelector('.log-time').textContent);
+    expectEquals(logs[1].type, row.querySelector('.log-type').textContent);
+    expectEquals(
+        logs[1].description, row.querySelector('.log-description').textContent);
+    expectEquals(
+        logs[1].url.url, row.querySelector('.log-url-value').textContent);
+
+    // Sub log table row.
+    let subRow = document.querySelector('.expansion-logs-table').rows[0];
+    let expectedSubTime = getTimeFormat(logs[0].time);
+    expectEquals(
+        expectedSubTime, subRow.querySelector('.log-time').textContent);
+    expectEquals(logs[0].type, subRow.querySelector('.log-type').textContent);
+    expectEquals(
+        logs[0].description,
+        subRow.querySelector('.log-description').textContent);
+    expectEquals(
+        logs[0].url.url, subRow.querySelector('.log-url-value').textContent);
+  });
+
+  test('LogNewMessageExistedPageIdGroupToTopOfTable', () => {
+    let pageImpl = new InterventionsInternalPageImpl(null);
+    let logs = [
+      {
+        type: 'Type_a',
+        description: 'Some description_a',
+        url: {url: 'Some gurl.spec()_a'},
+        time: 0,
+        pageId: 3,
+      },
+      {
+        type: 'Type_b',
+        description: 'Some description_b',
+        url: {url: 'Some gurl.spec()_b'},
+        time: 1,
+        pageId: 123,
+      },
+      {
+        type: 'Type_c',
+        description: 'Some description_c',
+        url: {url: 'Some gurl.spec()_c'},
+        time: 2,
+        pageId: 3,
+      },
+    ];
+
+    pageImpl.logNewMessage(logs[0]);
+    pageImpl.logNewMessage(logs[1]);
+    let rows = $('message-logs-table').querySelectorAll('.log-message');
+    expectEquals(2, rows.length);
+    expectEquals(logs[1].type, rows[0].querySelector('.log-type').textContent);
+    expectEquals(logs[0].type, rows[1].querySelector('.log-type').textContent);
+
+    // Existing group pushed to the top of the log table.
+    pageImpl.logNewMessage(logs[2]);
+    rows = $('message-logs-table').querySelectorAll('.log-message');
+    expectEquals(2, rows.length);
+    expectEquals(logs[2].type, rows[0].querySelector('.log-type').textContent);
+    expectEquals(logs[1].type, rows[1].querySelector('.log-type').textContent);
+  });
+
+  test('AddNewBlocklistedHost', () => {
+    let pageImpl = new InterventionsInternalPageImpl(null);
+    let time = 758675653000;  // Jan 15 1994 23:14:13 UTC
+    let expectedHost = 'example.com';
+    pageImpl.onBlocklistedHost(expectedHost, time);
+
+    let blocklistedTable = $('blocklisted-hosts-table');
+    let row = blocklistedTable.querySelector('.blocklisted-host-row');
+
+    let expectedTime = getTimeFormat(time);
+
+    expectEquals(
+        expectedHost, row.querySelector('.host-blocklisted').textContent);
+    expectEquals(
+        expectedTime, row.querySelector('.host-blocklisted-time').textContent);
+  });
+
+
+  test('HostAlreadyBlocklisted', () => {
+    let pageImpl = new InterventionsInternalPageImpl(null);
+    let time0 = 758675653000;   // Jan 15 1994 23:14:13 UTC
+    let time1 = 1507221689240;  // Oct 05 2017 16:41:29 UTC
+    let expectedHost = 'example.com';
+
+    pageImpl.onBlocklistedHost(expectedHost, time0);
+
+    let blocklistedTable = $('blocklisted-hosts-table');
+    let row = blocklistedTable.querySelector('.blocklisted-host-row');
+    let expectedTime = getTimeFormat(time0);
+    expectEquals(
+        expectedHost, row.querySelector('.host-blocklisted').textContent);
+    expectEquals(
+        expectedTime, row.querySelector('.host-blocklisted-time').textContent);
+
+    pageImpl.onBlocklistedHost(expectedHost, time1);
+
+    // The row remains the same.
+    expectEquals(
+        expectedHost, row.querySelector('.host-blocklisted').textContent);
+    expectEquals(
+        expectedTime, row.querySelector('.host-blocklisted-time').textContent);
+  });
+
+  test('UpdateUserBlocklisted', () => {
+    let pageImpl = new InterventionsInternalPageImpl(null);
+    let state = $('user-blocklisted-status-value');
+
+    pageImpl.onUserBlocklistedStatusChange(true /* blocklisted */);
+    expectEquals(
+        getBlocklistedStatus(true /* blocklisted */), state.textContent);
+
+    pageImpl.onUserBlocklistedStatusChange(false /* blocklisted */);
+    expectEquals(
+        getBlocklistedStatus(false /* blocklisted */), state.textContent);
+  });
+
+  test('OnBlocklistCleared', () => {
+    let pageImpl = new InterventionsInternalPageImpl(null);
+    let state = $('user-blocklisted-status-value');
+    let time = 758675653000;  // Jan 15 1994 23:14:13 UTC
+
+    pageImpl.onBlocklistCleared(time);
+    let actualClearedTime = $('blocklist-last-cleared-time').textContent;
+    expectEquals(getTimeFormat(time), actualClearedTime);
+    let blocklistedTable = $('blocklisted-hosts-table');
+    let rows = blocklistedTable.querySelectorAll('.blocklisted-host-row');
+    expectEquals(0, rows.length);
+  });
+
+  test('ClearLogMessageOnBlocklistCleared', () => {
+    let pageImpl = new InterventionsInternalPageImpl(null);
+    let time = 758675653000;  // Jan 15 1994 23:14:13 UTC
+    let log = {
+      type: 'Some type',
+      url: {url: ''},
+      description: 'Some description',
+      time: 758675653000,  // Jan 15 1994 23:14:13 UTC
+      pageId: 0,
+    };
+
+    pageImpl.logNewMessage(log);
+    expectGT($('message-logs-table').rows.length, 1 /* header row */);
+    pageImpl.onBlocklistCleared(time);
+    let expectedNumberOfRows = 2;  // header row and clear blocklist log.
+    let rows = $('message-logs-table').rows;
+    expectEquals(expectedNumberOfRows, rows.length);
+    expectEquals(
+        'Blocklist Cleared',
+        rows[1].querySelector('.log-description').textContent);
+  });
+
+
+  test('OnECTChanged', () => {
+    let pageImpl = new InterventionsInternalPageImpl(null);
+    let ectTypes = ['type1', 'type2', 'type3'];
+    ectTypes.forEach((type) => {
+      pageImpl.updateEffectiveConnectionType(type, 'max');
+      let actual = $('nqe-type').textContent;
+      expectEquals(type, actual);
+    });
+  });
+
+  test('OnBlocklistIgnoreChange', () => {
+    let pageImpl = new InterventionsInternalPageImpl(null);
+    pageImpl.onIgnoreBlocklistDecisionStatusChanged(true /* ignored */);
+    expectEquals('Enable Blocklist', $('ignore-blocklist-button').textContent);
+    expectEquals(
+        'Blocklist decisions are ignored.',
+        $('blocklist-ignored-status').textContent);
+
+    pageImpl.onIgnoreBlocklistDecisionStatusChanged(false /* ignored */);
+    expectEquals('Ignore Blocklist', $('ignore-blocklist-button').textContent);
+    expectEquals('', $('blocklist-ignored-status').textContent);
+  });
+});
diff --git a/chrome/test/data/webui/settings/chromeos/BUILD.gn b/chrome/test/data/webui/settings/chromeos/BUILD.gn
index b2cef129..34223f6 100644
--- a/chrome/test/data/webui/settings/chromeos/BUILD.gn
+++ b/chrome/test/data/webui/settings/chromeos/BUILD.gn
@@ -65,6 +65,8 @@
     "multidevice_page_tests.js",
     "multidevice_smartlock_subpage_test.js",
     "multidevice_subpage_tests.js",
+    "multidevice_task_continuation_item_tests.js",
+    "multidevice_task_continuation_disabled_link_tests.js",
     "multidevice_wifi_sync_disabled_link_tests.js",
     "multidevice_wifi_sync_item_tests.js",
     "nearby_share_receive_dialog_tests.js",
diff --git a/chrome/test/data/webui/settings/chromeos/multidevice_task_continuation_disabled_link_tests.js b/chrome/test/data/webui/settings/chromeos/multidevice_task_continuation_disabled_link_tests.js
new file mode 100644
index 0000000..b0b64dec
--- /dev/null
+++ b/chrome/test/data/webui/settings/chromeos/multidevice_task_continuation_disabled_link_tests.js
@@ -0,0 +1,66 @@
+// 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.
+
+// clang-format off
+// #import 'chrome://os-settings/chromeos/os_settings.js';
+
+// #import {Router, routes} from 'chrome://os-settings/chromeos/os_settings.js';
+// #import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
+// #import {assert} from 'chrome://resources/js/assert.m.js';
+// #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+// clang-format on
+
+suite('Multidevice', function() {
+  let localizedLink = null;
+
+  setup(function() {
+    PolymerTest.clearBody();
+    localizedLink = document.createElement(
+        'settings-multidevice-task-continuation-disabled-link');
+    document.body.appendChild(localizedLink);
+    Polymer.dom.flush();
+  });
+
+  teardown(function() {
+    localizedLink.remove();
+    settings.Router.getInstance().resetRouteForTesting();
+  });
+
+  test('Contains 2 links with aria-labels', async () => {
+    const chromeSyncLink = localizedLink.$$('#chromeSyncLink');
+    assertTrue(!!chromeSyncLink);
+    assertTrue(chromeSyncLink.hasAttribute('aria-label'));
+    const learnMoreLink = localizedLink.$$('#learnMoreLink');
+    assertTrue(!!learnMoreLink);
+    assertTrue(learnMoreLink.hasAttribute('aria-label'));
+  });
+
+  test('Spans are aria-hidden', async () => {
+    const spans = localizedLink.shadowRoot.querySelectorAll('span');
+    spans.forEach((span) => {
+      assertTrue(span.hasAttribute('aria-hidden'));
+    });
+  });
+
+  test('ChromeSyncLink navigates to appropriate route', async () => {
+    const chromeSyncLink = localizedLink.$$('#chromeSyncLink');
+    chromeSyncLink.click();
+
+    if (loadTimeData.getBoolean('splitSettingsSyncEnabled')) {
+      await test_util.eventToPromise(
+          'opened-browser-advanced-sync-setting', localizedLink);
+      assertNotEquals(
+          settings.Router.getInstance().getCurrentRoute(),
+          settings.routes.OS_SYNC);
+      assertNotEquals(
+          settings.Router.getInstance().getCurrentRoute(),
+          settings.routes.SYNC_ADVANCED);
+    } else {
+      Polymer.dom.flush();
+      assertEquals(
+          settings.Router.getInstance().getCurrentRoute(),
+          settings.routes.SYNC_ADVANCED);
+    }
+  });
+});
\ No newline at end of file
diff --git a/chrome/test/data/webui/settings/chromeos/multidevice_task_continuation_item_tests.js b/chrome/test/data/webui/settings/chromeos/multidevice_task_continuation_item_tests.js
new file mode 100644
index 0000000..655dc92
--- /dev/null
+++ b/chrome/test/data/webui/settings/chromeos/multidevice_task_continuation_item_tests.js
@@ -0,0 +1,67 @@
+// 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.
+
+// clang-format off
+// #import 'chrome://os-settings/chromeos/os_settings.js';
+
+// #import {assertFalse, assertTrue} from '../../chai_assert.js';
+// #import {assert} from 'chrome://resources/js/assert.m.js';
+// #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
+// #import {SyncBrowserProxyImpl} from 'chrome://os-settings/chromeos/os_settings.js';
+// #import {TestBrowserProxy} from 'chrome://test/test_browser_proxy.m.js';
+// #import {TestSyncBrowserProxy} from './test_os_sync_browser_proxy.m.js';
+// clang-format on
+
+function getPrefs() {
+  return {
+    tabsSynced: true,
+  };
+}
+
+suite('Multidevice', function() {
+  let taskContinuationItem;
+
+  setup(function() {
+    const browserProxy = new TestSyncBrowserProxy();
+    settings.SyncBrowserProxyImpl.instance_ = browserProxy;
+
+    PolymerTest.clearBody();
+
+    taskContinuationItem =
+        document.createElement('settings-multidevice-task-continuation-item');
+    document.body.appendChild(taskContinuationItem);
+
+    Polymer.dom.flush();
+  });
+
+  teardown(function() {
+    taskContinuationItem.remove();
+  });
+
+  test('Chrome Sync off', async () => {
+    const prefs = getPrefs();
+    prefs.tabsSynced = false;
+    Polymer.dom.flush();
+
+    cr.webUIListenerCallback('sync-prefs-changed', prefs);
+    Polymer.dom.flush();
+
+    assertTrue(!!taskContinuationItem.$$(
+        'settings-multidevice-task-continuation-disabled-link'));
+
+    const toggle = taskContinuationItem.$$('cr-toggle');
+    assertTrue(!!toggle);
+    assertTrue(toggle.disabled);
+  });
+
+  test('Chrome Sync on', async () => {
+    const prefs = getPrefs();
+    prefs.tabsSynced = true;
+    cr.webUIListenerCallback('sync-prefs-changed', prefs);
+    Polymer.dom.flush();
+
+    assertFalse(!!taskContinuationItem.$$(
+        'settings-multidevice-task-continuation-disabled-link'));
+  });
+});
\ No newline at end of file
diff --git a/chrome/test/data/webui/settings/chromeos/multidevice_wifi_sync_disabled_link_tests.js b/chrome/test/data/webui/settings/chromeos/multidevice_wifi_sync_disabled_link_tests.js
index 49a204a..5257f42 100644
--- a/chrome/test/data/webui/settings/chromeos/multidevice_wifi_sync_disabled_link_tests.js
+++ b/chrome/test/data/webui/settings/chromeos/multidevice_wifi_sync_disabled_link_tests.js
@@ -6,8 +6,7 @@
 // #import 'chrome://os-settings/chromeos/os_settings.js';
 
 // #import {Router, routes} from 'chrome://os-settings/chromeos/os_settings.js';
-// #import {assertEquals, assertFalse, assertTrue} from '../../chai_assert.js';
-// #import {assert} from 'chrome://resources/js/assert.m.js';
+// #import {assertEquals, assertTrue} from '../../chai_assert.js';
 // #import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
 // clang-format on
 
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
index 5f1fdf4c..d7cfe5d 100644
--- a/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
+++ b/chrome/test/data/webui/settings/chromeos/os_settings_browsertest.js
@@ -1395,6 +1395,7 @@
   /** @override */
   get extraLibraries() {
     return super.extraLibraries.concat([
+      '//ui/webui/resources/js/util.js',
       BROWSER_SETTINGS_PATH + '../test_browser_proxy.js',
       BROWSER_SETTINGS_PATH + '../test_util.js',
       'test_multidevice_browser_proxy.js',
@@ -1407,6 +1408,56 @@
   mocha.run();
 });
 
+// Test fixture for the multidevice task continuation sync disabled link.
+// eslint-disable-next-line no-var
+var OSSettingsMultideviceTaskContinuationItemTest =
+    class extends OSSettingsBrowserTest {
+  /** @override */
+  get browsePreload() {
+    return super.browsePreload +
+        'chromeos/multidevice_page/multidevice_task_continuation_item.html';
+  }
+
+  /** @override */
+  get extraLibraries() {
+    return super.extraLibraries.concat([
+      BROWSER_SETTINGS_PATH + '../test_util.js',
+      BROWSER_SETTINGS_PATH + '../test_browser_proxy.js',
+      BROWSER_SETTINGS_PATH + 'test_sync_browser_proxy.js',
+      'multidevice_task_continuation_item_tests.js',
+    ]);
+  }
+};
+
+TEST_F('OSSettingsMultideviceTaskContinuationItemTest', 'AllJsTests', () => {
+  mocha.run();
+});
+
+// Test fixture for the multidevice task continuation sync disabled link.
+// eslint-disable-next-line no-var
+var OSSettingsMultideviceTaskContinuationDisabledLinkTest =
+    class extends OSSettingsBrowserTest {
+  /** @override */
+  get browsePreload() {
+    return super.browsePreload + 'chromeos/multidevice_page/' +
+        'multidevice_task_continuation_disabled_link.html';
+  }
+
+  /** @override */
+  get extraLibraries() {
+    return super.extraLibraries.concat([
+      BROWSER_SETTINGS_PATH + '../test_util.js',
+      'multidevice_task_continuation_disabled_link_tests.js',
+    ]);
+  }
+};
+
+TEST_F(
+    'OSSettingsMultideviceTaskContinuationDisabledLinkTest', 'AllJsTests',
+    () => {
+      mocha.run();
+    });
+
 // Test fixture for the multidevice wifi sync disabled link.
 // eslint-disable-next-line no-var
 var OSSettingsMultideviceWifiSyncDisabledLinkTest =
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
index 457415e..882cfcf 100644
--- a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
+++ b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
@@ -224,6 +224,14 @@
  ['MultideviceSmartLockSubPage', 'multidevice_smartlock_subpage_test.m.js'],
  ['MultideviceSubPage', 'multidevice_subpage_tests.m.js'],
  [
+   'MultideviceTaskContinuationItem',
+   'multidevice_task_continuation_item_tests.m.js'
+ ],
+ [
+   'MultideviceTaskContinuationDisabledLink',
+   'multidevice_task_continuation_disabled_link_tests.m.js'
+ ],
+ [
    'MultideviceWifiSyncDisabledLink',
    'multidevice_wifi_sync_disabled_link_tests.m.js'
  ],
@@ -244,7 +252,10 @@
  ['ResetPage', 'os_reset_page_test.m.js'],
  ['SmartInputsPage', 'smart_inputs_page_test.m.js'],
  ['SmbPage', 'smb_shares_page_tests.m.js'],
- ['SwitchAccessActionAssignmentDialog', 'switch_access_action_assignment_dialog_test.m.js'],
+ [
+   'SwitchAccessActionAssignmentDialog',
+   'switch_access_action_assignment_dialog_test.m.js'
+ ],
  ['TetherConnectionDialog', 'tether_connection_dialog_test.m.js'],
  ['TimezoneSelector', 'timezone_selector_test.m.js'],
  ['TimezoneSubpage', 'timezone_subpage_test.m.js'],
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 ed5686b..f29d4b7 100644
--- a/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js
+++ b/chrome/test/data/webui/settings/cr_settings_v3_browsertest.js
@@ -377,6 +377,11 @@
   get browsePreload() {
     return 'chrome://settings/test_loader.html?module=settings/privacy_page_test.js';
   }
+
+  /** @override */
+  get featureList() {
+    return {enabled: ['features::kPrivacySandboxSettings']};
+  }
 };
 
 TEST_F('CrSettingsPrivacyPageV3Test', 'PrivacyPageTests', function() {
diff --git a/chrome/test/data/webui/settings/privacy_page_test.js b/chrome/test/data/webui/settings/privacy_page_test.js
index c8905100..9a222ea 100644
--- a/chrome/test/data/webui/settings/privacy_page_test.js
+++ b/chrome/test/data/webui/settings/privacy_page_test.js
@@ -78,6 +78,7 @@
   suiteSetup(function() {
     loadTimeData.overrideValues({
       enableContentSettingsRedesign: false,
+      privacySandboxSettingsEnabled: false,
     });
   });
 
@@ -153,8 +154,27 @@
         0);
     assertFalse(isChildVisible(page, '#notficationRadioGroup'));
   });
+
+  test('privacySandboxRowNotVisible', function() {
+    assertFalse(isChildVisible(page, '#privacySandboxLinkRow'));
+  });
 });
 
+suite('PrivacySandboxSettingsEnabled', function() {
+  /** @type {!SettingsPrivacyPageElement} */
+  let page;
+
+  setup(function() {
+    document.body.innerHTML = '';
+    page = /** @type {!SettingsPrivacyPageElement} */
+        (document.createElement('settings-privacy-page'));
+    document.body.appendChild(page);
+  });
+
+  test('privacySandboxRowVisible', function() {
+    assertTrue(isChildVisible(page, '#privacySandboxLinkRow'));
+  });
+});
 
 suite('ContentSettingsRedesign', function() {
   /** @type {!SettingsPrivacyPageElement} */
diff --git a/components/blocked_content/popup_blocker.cc b/components/blocked_content/popup_blocker.cc
index 8f8438c..fd67c3ed 100644
--- a/components/blocked_content/popup_blocker.cc
+++ b/components/blocked_content/popup_blocker.cc
@@ -58,8 +58,9 @@
 
   // This is trusted user action (e.g. shift-click), so make sure it is not
   // blocked.
-  if (open_url_params && open_url_params->triggering_event_info !=
-                             blink::TriggeringEventInfo::kFromUntrustedEvent) {
+  if (open_url_params &&
+      open_url_params->triggering_event_info !=
+          blink::mojom::TriggeringEventInfo::kFromUntrustedEvent) {
     return PopupBlockType::kNotBlocked;
   }
 
diff --git a/components/blocked_content/safe_browsing_triggered_popup_blocker.cc b/components/blocked_content/safe_browsing_triggered_popup_blocker.cc
index ac5e7fd72..1a6f586a5 100644
--- a/components/blocked_content/safe_browsing_triggered_popup_blocker.cc
+++ b/components/blocked_content/safe_browsing_triggered_popup_blocker.cc
@@ -20,8 +20,8 @@
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/render_frame_host.h"
 #include "content/public/browser/web_contents.h"
-#include "third_party/blink/public/common/navigation/triggering_event_info.h"
 #include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom.h"
 
 namespace blocked_content {
 namespace {
diff --git a/components/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc b/components/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc
index d17c0b3..6fc8c69 100644
--- a/components/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc
+++ b/components/blocked_content/safe_browsing_triggered_popup_blocker_unittest.cc
@@ -37,7 +37,7 @@
 #include "content/public/test/test_navigation_throttle_inserter.h"
 #include "content/public/test/test_renderer_host.h"
 #include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/navigation/triggering_event_info.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom.h"
 #include "third_party/blink/public/mojom/window_features/window_features.mojom.h"
 #include "ui/base/page_transition_types.h"
 #include "ui/base/window_open_disposition.h"
@@ -234,7 +234,7 @@
       ui::PAGE_TRANSITION_LINK, true /* is_renderer_initiated */);
   params.user_gesture = true;
   params.triggering_event_info =
-      blink::TriggeringEventInfo::kFromUntrustedEvent;
+      blink::mojom::TriggeringEventInfo::kFromUntrustedEvent;
 
   MaybeBlockPopup(web_contents(), nullptr,
                   std::make_unique<TestPopupNavigationDelegate>(
@@ -259,7 +259,8 @@
       popup_url, content::Referrer(), WindowOpenDisposition::NEW_FOREGROUND_TAB,
       ui::PAGE_TRANSITION_LINK, true /* is_renderer_initiated */);
   params.user_gesture = true;
-  params.triggering_event_info = blink::TriggeringEventInfo::kFromTrustedEvent;
+  params.triggering_event_info =
+      blink::mojom::TriggeringEventInfo::kFromTrustedEvent;
 
   MaybeBlockPopup(web_contents(), nullptr,
                   std::make_unique<TestPopupNavigationDelegate>(
diff --git a/components/browser_ui/settings/android/widget/java/src/org/chromium/components/browser_ui/settings/ChromeSwitchPreference.java b/components/browser_ui/settings/android/widget/java/src/org/chromium/components/browser_ui/settings/ChromeSwitchPreference.java
index 0038b0b..82b2914 100644
--- a/components/browser_ui/settings/android/widget/java/src/org/chromium/components/browser_ui/settings/ChromeSwitchPreference.java
+++ b/components/browser_ui/settings/android/widget/java/src/org/chromium/components/browser_ui/settings/ChromeSwitchPreference.java
@@ -19,6 +19,10 @@
 public class ChromeSwitchPreference extends SwitchPreferenceCompat {
     private ManagedPreferenceDelegate mManagedPrefDelegate;
 
+    public ChromeSwitchPreference(Context context) {
+        super(context);
+    }
+
     public ChromeSwitchPreference(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
diff --git a/components/browser_ui/site_settings/android/features.cc b/components/browser_ui/site_settings/android/features.cc
index 358edad..763945b 100644
--- a/components/browser_ui/site_settings/android/features.cc
+++ b/components/browser_ui/site_settings/android/features.cc
@@ -12,4 +12,7 @@
 const base::Feature kAppNotificationStatusMessaging{
     "AppNotificationStatusMessaging", base::FEATURE_DISABLED_BY_DEFAULT};
 
+const base::Feature kActionableContentSettings{
+    "ActionableContentSettings", base::FEATURE_DISABLED_BY_DEFAULT};
+
 }  // namespace browser_ui
diff --git a/components/browser_ui/site_settings/android/features.h b/components/browser_ui/site_settings/android/features.h
index 523b7ff3..cf329bce 100644
--- a/components/browser_ui/site_settings/android/features.h
+++ b/components/browser_ui/site_settings/android/features.h
@@ -14,6 +14,8 @@
 // Enables messaging in the site settings UI to tell users notifications are
 // disabled for the entire app
 extern const base::Feature kAppNotificationStatusMessaging;
+// Enables toggles and slash through diabled icons for content settings.
+extern const base::Feature kActionableContentSettings;
 
 }  // namespace browser_ui
 
diff --git a/components/browser_ui/site_settings/android/java/res/xml/single_website_preferences.xml b/components/browser_ui/site_settings/android/java/res/xml/single_website_preferences.xml
index 00d43e5..e146a00 100644
--- a/components/browser_ui/site_settings/android/java/res/xml/single_website_preferences.xml
+++ b/components/browser_ui/site_settings/android/java/res/xml/single_website_preferences.xml
@@ -46,46 +46,6 @@
         android:key="site_permissions"
         android:title="@string/website_settings_permissions_category" />
 
-    <!-- The order of the following items is from: http://crbug.com/610358. -->
-    <ListPreference
-        android:key="cookies_permission_list" />
-    <ListPreference
-        android:key="location_access_list" />
-    <ListPreference
-        android:key="camera_permission_list" />
-    <ListPreference
-        android:key="microphone_permission_list" />
-    <ListPreference
-        android:key="push_notifications_list" />
-    <ListPreference
-        android:key="javascript_permission_list" />
-    <ListPreference
-        android:key="popup_permission_list" />
-    <ListPreference
-        android:key="ads_permission_list" />
-    <ListPreference
-        android:key="background_sync_permission_list" />
-    <ListPreference
-        android:key="automatic_downloads_permission_list" />
-    <ListPreference
-        android:key="protected_media_identifier_permission_list" />
-    <ListPreference
-        android:key="sound_permission_list" />
-    <ListPreference
-        android:key="midi_sysex_permission_list" />
-    <ListPreference
-        android:key="clipboard_permission_list" />
-    <ListPreference
-        android:key="nfc_permission_list" />
-    <ListPreference
-        android:key="bluetooth_scanning_permission_list" />
-    <ListPreference
-        android:key="vr_permission_list" />
-    <ListPreference
-        android:key="ar_permission_list" />
-    <ListPreference
-        android:key="idle_detection_permission_list" />
-
     <org.chromium.components.browser_ui.settings.ButtonPreference
         android:key="reset_site_button" />
 </PreferenceScreen>
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
index d824112..6df1e0d5 100644
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleWebsiteSettings.java
@@ -29,6 +29,7 @@
 import org.chromium.base.Callback;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.components.browser_ui.settings.ChromeImageViewPreference;
+import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
 import org.chromium.components.browser_ui.settings.ManagedPreferencesUtils;
 import org.chromium.components.browser_ui.settings.SettingsUtils;
 import org.chromium.components.content_settings.ContentSettingValues;
@@ -86,6 +87,30 @@
     // Buttons:
     public static final String PREF_RESET_SITE = "reset_site_button";
 
+    // Defining the order for content settings based on http://crbug.com/610358
+    private static final int[] SETTINGS_ORDER = {
+            ContentSettingsType.COOKIES,
+            ContentSettingsType.GEOLOCATION,
+            ContentSettingsType.MEDIASTREAM_CAMERA,
+            ContentSettingsType.MEDIASTREAM_MIC,
+            ContentSettingsType.NOTIFICATIONS,
+            ContentSettingsType.JAVASCRIPT,
+            ContentSettingsType.POPUPS,
+            ContentSettingsType.ADS,
+            ContentSettingsType.BACKGROUND_SYNC,
+            ContentSettingsType.AUTOMATIC_DOWNLOADS,
+            ContentSettingsType.PROTECTED_MEDIA_IDENTIFIER,
+            ContentSettingsType.SOUND,
+            ContentSettingsType.MIDI_SYSEX,
+            ContentSettingsType.CLIPBOARD_READ_WRITE,
+            ContentSettingsType.NFC,
+            ContentSettingsType.BLUETOOTH_SCANNING,
+            ContentSettingsType.VR,
+            ContentSettingsType.AR,
+            ContentSettingsType.IDLE_DETECTION,
+            ContentSettingsType.SENSORS,
+    };
+
     /**
      * @param type ContentSettingsType
      * @return The preference key of this type
@@ -137,6 +162,14 @@
         }
     }
 
+    /**
+     * @return The status of the actionable content settings flag
+     */
+    private static boolean isActionableContentSettingsEnabled() {
+        return SiteSettingsFeatureList.isEnabled(
+                SiteSettingsFeatureList.ACTIONABLE_CONTENT_SETTINGS);
+    }
+
     // A list of preferences keys that will be hidden on this page if this boolean below is true
     private boolean mHideNonPermissionPreferences;
     private static final String[] NON_PERMISSION_PREFERENCES = {
@@ -173,6 +206,9 @@
 
     private Dialog mConfirmationDialog;
 
+    // Maximum value used for the order of the permissions
+    private int mMaxPermissionOrder;
+
     private class SingleWebsitePermissionsPopulator
             implements WebsitePermissionsFetcher.WebsitePermissionsCallback {
         private final WebsiteAddress mSiteAddress;
@@ -378,7 +414,7 @@
                 ? SettingsUtils.getTintedIcon(
                         getContext(), ContentSettingsResources.getIcon(contentSettingsType))
                 : ContentSettingsResources.getDisabledIcon(contentSettingsType, getResources());
-        if (getSiteSettingsClient().isPageInfoV2Enabled() && value != null
+        if (isActionableContentSettingsEnabled() && value != null
                 && value == ContentSettingValues.BLOCK) {
             return ContentSettingsResources.getBlockedSquareIcon(getResources(), icon);
         }
@@ -395,19 +431,11 @@
         }
         SettingsUtils.addPreferencesFromResource(this, R.xml.single_website_preferences);
 
-        int maxPermissionOrder = 0;
-        PreferenceScreen preferenceScreen = getPreferenceScreen();
-        // Iterate over preferences in reverse order because some preferences will be removed during
-        // this setup, causing indices of later preferences to change.
-        for (int i = preferenceScreen.getPreferenceCount() - 1; i >= 0; i--) {
-            Preference preference = preferenceScreen.getPreference(i);
-            setUpPreference(preference);
-            if (getContentSettingsTypeFromPreferenceKey(preference.getKey())
-                    != ContentSettingsType.DEFAULT) {
-                maxPermissionOrder = Math.max(maxPermissionOrder, preference.getOrder());
-            }
-        }
-        setUpChosenObjectPreferences(maxPermissionOrder);
+        findPreference(PREF_SITE_TITLE).setTitle(mSite.getTitle());
+        setupContentSettingsPreferences();
+        setupResetSitePreference();
+        setUpClearDataPreference();
+        setUpChosenObjectPreferences();
         setUpOsWarningPreferences();
 
         setUpAdsInformationalBanner();
@@ -430,34 +458,29 @@
         }
     }
 
-    private void setUpPreference(Preference preference) {
-        if (PREF_SITE_TITLE.equals(preference.getKey())) {
-            preference.setTitle(mSite.getTitle());
-        } else if (PREF_CLEAR_DATA.equals(preference.getKey())) {
-            setUpClearDataPreference((ClearWebsiteStorage) preference);
-        } else if (PREF_RESET_SITE.equals(preference.getKey())) {
-            setupResetSitePreference(preference);
-        } else {
-            @ContentSettingsType
-            int type = getContentSettingsTypeFromPreferenceKey(preference.getKey());
-            if (type != ContentSettingsType.DEFAULT) {
-                if (type == ContentSettingsType.ADS) {
-                    setUpAdsPreference(preference);
-                } else if (type == ContentSettingsType.SOUND) {
-                    setUpSoundPreference(preference);
-                } else if (type == ContentSettingsType.JAVASCRIPT) {
-                    setUpJavascriptPreference(preference);
-                } else if (type == ContentSettingsType.GEOLOCATION) {
-                    setUpLocationPreference(preference);
-                } else if (type == ContentSettingsType.NOTIFICATIONS) {
-                    setUpNotificationsPreference(preference, isPermissionEmbargoed(type));
-                } else {
-                    setUpListPreference(preference,
-                            mSite.getContentSetting(
-                                    getSiteSettingsClient().getBrowserContextHandle(), type),
-                            isPermissionEmbargoed(type));
-                }
-                return;
+    private void setupContentSettingsPreferences() {
+        mMaxPermissionOrder = findPreference(PREF_PERMISSIONS_HEADER).getOrder();
+        for (@ContentSettingsType int type : SETTINGS_ORDER) {
+            Preference preference = isActionableContentSettingsEnabled()
+                    ? new ChromeSwitchPreference(getStyledContext())
+                    : new ListPreference(getStyledContext());
+            preference.setKey(getPreferenceKey(type));
+
+            if (type == ContentSettingsType.ADS) {
+                setUpAdsPreference(preference);
+            } else if (type == ContentSettingsType.SOUND) {
+                setUpSoundPreference(preference);
+            } else if (type == ContentSettingsType.JAVASCRIPT) {
+                setUpJavascriptPreference(preference);
+            } else if (type == ContentSettingsType.GEOLOCATION) {
+                setUpLocationPreference(preference);
+            } else if (type == ContentSettingsType.NOTIFICATIONS) {
+                setUpNotificationsPreference(preference, isPermissionEmbargoed(type));
+            } else {
+                setupContentSettingsPreference(preference,
+                        mSite.getContentSetting(
+                                getSiteSettingsClient().getBrowserContextHandle(), type),
+                        isPermissionEmbargoed(type));
             }
         }
     }
@@ -466,7 +489,8 @@
         return mSite.getPermissionInfo(type) != null && mSite.getPermissionInfo(type).isEmbargoed();
     }
 
-    private void setUpClearDataPreference(ClearWebsiteStorage preference) {
+    private void setUpClearDataPreference() {
+        ClearWebsiteStorage preference = findPreference(PREF_CLEAR_DATA);
         long usage = mSite.getTotalUsage();
         if (usage > 0) {
             boolean appFound = getSiteSettingsClient()
@@ -488,10 +512,12 @@
         }
     }
 
-    private void setupResetSitePreference(Preference preference) {
+    private void setupResetSitePreference() {
+        Preference preference = findPreference(PREF_RESET_SITE);
         int titleResId = mHideNonPermissionPreferences ? R.string.page_info_permissions_reset
                                                        : R.string.website_reset;
         preference.setTitle(titleResId);
+        preference.setOrder(mMaxPermissionOrder + 1);
         preference.setOnPreferenceClickListener(this);
         if (WebsitePreferenceBridge.isCookieDeletionDisabled(
                     getSiteSettingsClient().getBrowserContextHandle(),
@@ -519,7 +545,7 @@
      * summary and (intentionally) loses its click handler.
      * @return A read-only copy of the preference passed in as |oldPreference|.
      */
-    private ChromeImageViewPreference replaceWithReadOnlyCopyOf(Preference oldPreference,
+    private ChromeImageViewPreference createReadOnlyCopyOf(Preference oldPreference,
             String newSummary, @ContentSettingValues @Nullable Integer value) {
         ChromeImageViewPreference newPreference =
                 new ChromeImageViewPreference(oldPreference.getContext());
@@ -527,12 +553,6 @@
         setUpPreferenceCommon(newPreference, value);
         newPreference.setSummary(newSummary);
 
-        // This preference is read-only so should not attempt to persist to shared prefs.
-        newPreference.setPersistent(false);
-
-        newPreference.setOrder(oldPreference.getOrder());
-        getPreferenceScreen().removePreference(oldPreference);
-        getPreferenceScreen().addPreference(newPreference);
         return newPreference;
     }
 
@@ -558,7 +578,7 @@
                 getSiteSettingsClient().getDelegatePackageNameForOrigin(origin, type), type);
         String summaryText = getString(R.string.website_setting_managed_by_app, managedByAppName);
         ChromeImageViewPreference newPreference =
-                replaceWithReadOnlyCopyOf(preference, summaryText, value);
+                createReadOnlyCopyOf(preference, summaryText, value);
 
         newPreference.setImageView(R.drawable.permission_popups, contentDescriptionRes, null);
         // By disabling the ImageView, clicks will go through to the preference.
@@ -585,9 +605,9 @@
                     || (value != ContentSettingValues.ALLOW
                             && value != ContentSettingValues.BLOCK)) {
                 // TODO(crbug.com/735110): Figure out if this is the correct thing to do, for values
-                // that are non-null, but not ALLOW or BLOCK either. (In setupListPreference we
-                // treat non-ALLOW settings as BLOCK, but here we are simply removing them.)
-                getPreferenceScreen().removePreference(preference);
+                // that are non-null, but not ALLOW or BLOCK either. (In
+                // setupContentSettingsPreference we treat non-ALLOW settings as BLOCK, but here we
+                // are simply not adding it.)
                 return;
             }
             String overrideSummary;
@@ -602,7 +622,7 @@
             // On Android O this preference is read-only, so we replace the existing pref with a
             // regular Preference that takes users to OS settings on click.
             ChromeImageViewPreference newPreference =
-                    replaceWithReadOnlyCopyOf(preference, overrideSummary, value);
+                    createReadOnlyCopyOf(preference, overrideSummary, value);
             newPreference.setDefaultValue(value);
 
             newPreference.setOnPreferenceClickListener(unused -> {
@@ -610,7 +630,7 @@
                 return true;
             });
         } else {
-            setUpListPreference(preference, value, isEmbargoed);
+            setupContentSettingsPreference(preference, value, isEmbargoed);
             if (isPermissionControlledByDSE(ContentSettingsType.NOTIFICATIONS) && value != null) {
                 updatePreferenceForDSESetting(preference, value);
             }
@@ -698,10 +718,8 @@
      * when permissions are modified to determine if this preference list should be displayed or
      * not. The preferences are added to the preference screen using |maxPermissionOrder| to order
      * the preferences in the list.
-     * @param maxPermissionOrder The listing order of the ChromeImageViewPreference(s) with respect
-     *                           to the other preferences.
      */
-    private void setUpChosenObjectPreferences(int maxPermissionOrder) {
+    private void setUpChosenObjectPreferences() {
         PreferenceScreen preferenceScreen = getPreferenceScreen();
 
         for (ChosenObjectInfo info : mSite.getChosenObjectInfo()) {
@@ -711,7 +729,6 @@
             preference.setKey(CHOOSER_PERMISSION_PREFERENCE_KEY);
             preference.setIcon(SettingsUtils.getTintedIcon(
                     getContext(), ContentSettingsResources.getIcon(info.getContentSettingsType())));
-            preference.setOrder(maxPermissionOrder);
             preference.setTitle(info.getName());
             preference.setImageView(R.drawable.ic_delete_white_24dp,
                     R.string.website_settings_revoke_device_permission, (View view) -> {
@@ -738,6 +755,7 @@
                 mObjectUserPermissionCount++;
             }
 
+            preference.setOrder(++mMaxPermissionOrder);
             preferenceScreen.addPreference(preference);
         }
     }
@@ -844,6 +862,26 @@
         return false;
     }
 
+    private void setupContentSettingsPreference(Preference preference,
+            @ContentSettingValues @Nullable Integer value, boolean isEmbargoed) {
+        if (value == null) return;
+
+        setUpPreferenceCommon(preference, value);
+
+        if (!isActionableContentSettingsEnabled()) {
+            setUpListPreference(preference, value, isEmbargoed);
+            return;
+        }
+
+        ChromeSwitchPreference switchPreference = (ChromeSwitchPreference) preference;
+
+        switchPreference.setChecked(value == ContentSettingValues.ALLOW);
+        switchPreference.setSummary(isEmbargoed
+                        ? getString(R.string.automatically_blocked)
+                        : getString(ContentSettingsResources.getCategorySummary(value)));
+        switchPreference.setOnPreferenceChangeListener(this);
+    }
+
     /**
      * Initialize a ListPreference with a certain value.
      * @param preference The ListPreference to initialize.
@@ -851,11 +889,6 @@
      */
     private void setUpListPreference(Preference preference,
             @ContentSettingValues @Nullable Integer value, boolean isEmbargoed) {
-        if (value == null) {
-            getPreferenceScreen().removePreference(preference);
-            return;
-        }
-        setUpPreferenceCommon(preference, value);
         ListPreference listPreference = (ListPreference) preference;
 
         CharSequence[] keys = new String[2];
@@ -886,6 +919,7 @@
             Preference preference, @ContentSettingValues @Nullable Integer value) {
         int contentType = getContentSettingsTypeFromPreferenceKey(preference.getKey());
         int titleResourceId = ContentSettingsResources.getTitle(contentType);
+
         if (titleResourceId != 0) {
             preference.setTitle(titleResourceId);
         }
@@ -902,6 +936,12 @@
         } else {
             preference.setIcon(getContentSettingsIcon(contentType, value, true));
         }
+
+        preference.setOrder(++mMaxPermissionOrder);
+        // These preferences are persisted elsewhere, using SharedPreferences
+        //  can cause issues with keys matching up with value.
+        preference.setPersistent(false);
+        getPreferenceScreen().addPreference(preference);
     }
 
     private void setUpLocationPreference(Preference preference) {
@@ -914,7 +954,7 @@
             return;
         }
 
-        setUpListPreference(
+        setupContentSettingsPreference(
                 preference, permission, isPermissionEmbargoed(ContentSettingsType.GEOLOCATION));
         if (isPermissionControlledByDSE(ContentSettingsType.GEOLOCATION) && permission != null) {
             updatePreferenceForDSESetting(preference, permission);
@@ -937,7 +977,7 @@
                     : ContentSettingValues.BLOCK;
         }
         // Not possible to embargo SOUND.
-        setUpListPreference(preference, currentValue, false /* isEmbargoed */);
+        setupContentSettingsPreference(preference, currentValue, false /* isEmbargoed */);
     }
 
     private void setUpJavascriptPreference(Preference preference) {
@@ -955,7 +995,7 @@
             currentValue = ContentSettingValues.BLOCK;
         }
         // Not possible to embargo JAVASCRIPT.
-        setUpListPreference(preference, currentValue, false /* isEmbargoed */);
+        setupContentSettingsPreference(preference, currentValue, false /* isEmbargoed */);
     }
 
     /**
@@ -970,7 +1010,7 @@
                 getSiteSettingsClient().getBrowserContextHandle();
         // Do not show the setting if the category is not enabled.
         if (!SiteSettingsCategory.adsCategoryEnabled()) {
-            setUpListPreference(preference, null, false);
+            setupContentSettingsPreference(preference, null, false);
             return;
         }
         // If the ad blocker is activated, then this site will have ads blocked unless there is an
@@ -985,7 +1025,7 @@
         // If the site is not considered a candidate for blocking, do the standard thing and remove
         // the preference.
         if (permission == null && !activated) {
-            setUpListPreference(preference, null, false);
+            setupContentSettingsPreference(preference, null, false);
             return;
         }
 
@@ -998,14 +1038,16 @@
                     : ContentSettingValues.BLOCK;
         }
         // Not possible to embargo ADS.
-        setUpListPreference(preference, permission, false /* isEmbargoed */);
+        setupContentSettingsPreference(preference, permission, false /* isEmbargoed */);
 
         // The subresource filter permission has a custom BLOCK string.
-        ListPreference listPreference = (ListPreference) preference;
-        listPreference.setEntries(
-                new String[] {getString(R.string.website_settings_permissions_allow),
-                        getString(R.string.website_settings_permissions_ads_block)});
-        listPreference.setValueIndex(permission == ContentSettingValues.ALLOW ? 0 : 1);
+        if (preference instanceof ListPreference) {
+            ListPreference listPreference = (ListPreference) preference;
+            listPreference.setEntries(
+                    new String[] {getString(R.string.website_settings_permissions_allow),
+                            getString(R.string.website_settings_permissions_ads_block)});
+            listPreference.setValueIndex(permission == ContentSettingValues.ALLOW ? 0 : 1);
+        }
     }
 
     private String getDSECategorySummary(@ContentSettingValues int value) {
@@ -1031,12 +1073,15 @@
      */
     private void updatePreferenceForDSESetting(
             Preference preference, @ContentSettingValues int value) {
-        ListPreference listPreference = (ListPreference) preference;
-        listPreference.setEntries(new String[] {
-                getString(R.string.website_settings_permissions_allow_dse),
-                getString(R.string.website_settings_permissions_block_dse),
-        });
-        listPreference.setSummary(getDSECategorySummary(value));
+        preference.setSummary(getDSECategorySummary(value));
+
+        if (preference instanceof ListPreference) {
+            ListPreference listPreference = (ListPreference) preference;
+            listPreference.setEntries(new String[] {
+                    getString(R.string.website_settings_permissions_allow_dse),
+                    getString(R.string.website_settings_permissions_block_dse),
+            });
+        }
     }
 
     public @ContentSettingsType int getContentSettingsTypeFromPreferenceKey(String preferenceKey) {
@@ -1065,25 +1110,31 @@
         // It is possible that this UI is destroyed while a ListPreference dialog is open because
         // incognito mode is closed through the system notification.
         if (getView() == null) return true;
-
-        @ContentSettingValues
-        int permission = ContentSetting.fromString((String) newValue);
         BrowserContextHandle browserContextHandle =
                 getSiteSettingsClient().getBrowserContextHandle();
         int type = getContentSettingsTypeFromPreferenceKey(preference.getKey());
-        if (type != ContentSettingsType.DEFAULT) {
-            mSite.setContentSetting(browserContextHandle, type, permission);
-            if (isPermissionControlledByDSE(type)) {
-                preference.setSummary(getDSECategorySummary(permission));
-            } else {
-                preference.setSummary(
-                        getString(ContentSettingsResources.getCategorySummary(permission)));
-            }
-            preference.setIcon(getContentSettingsIcon(type, permission, true));
+        if (type == ContentSettingsType.DEFAULT) return false;
 
-            if (mWebsiteSettingsObserver != null) {
-                mWebsiteSettingsObserver.onPermissionChanged();
-            }
+        @ContentSettingValues
+        int permission;
+        if (preference instanceof ListPreference) {
+            permission = ContentSetting.fromString((String) newValue);
+        } else {
+            permission =
+                    (Boolean) newValue ? ContentSettingValues.ALLOW : ContentSettingValues.BLOCK;
+        }
+
+        mSite.setContentSetting(browserContextHandle, type, permission);
+        if (isPermissionControlledByDSE(type)) {
+            preference.setSummary(getDSECategorySummary(permission));
+        } else {
+            preference.setSummary(
+                    getString(ContentSettingsResources.getCategorySummary(permission)));
+        }
+        preference.setIcon(getContentSettingsIcon(type, permission, true));
+
+        if (mWebsiteSettingsObserver != null) {
+            mWebsiteSettingsObserver.onPermissionChanged();
         }
 
         return true;
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsFeatureList.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsFeatureList.java
index 7cf8cd26b..b84040d 100644
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsFeatureList.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsFeatureList.java
@@ -17,6 +17,7 @@
 @MainDex
 public class SiteSettingsFeatureList {
     public static final String APP_NOTIFICATION_STATUS_MESSAGING = "AppNotificationStatusMessaging";
+    public static final String ACTIONABLE_CONTENT_SETTINGS = "ActionableContentSettings";
 
     private SiteSettingsFeatureList() {}
 
diff --git a/components/browser_ui/site_settings/android/site_settings_feature_list.cc b/components/browser_ui/site_settings/android/site_settings_feature_list.cc
index 70c94e7c..71f5492 100644
--- a/components/browser_ui/site_settings/android/site_settings_feature_list.cc
+++ b/components/browser_ui/site_settings/android/site_settings_feature_list.cc
@@ -22,6 +22,7 @@
 // in other locations in the code base (e.g. content_features.h).
 const base::Feature* kFeaturesExposedToJava[] = {
     &kAppNotificationStatusMessaging,
+    &kActionableContentSettings,
 };
 
 // TODO(crbug.com/1060097): Remove this once a generalized FeatureList exists.
diff --git a/components/safe_browsing/core/common/utils.cc b/components/safe_browsing/core/common/utils.cc
index 36fe89c..744a85c 100644
--- a/components/safe_browsing/core/common/utils.cc
+++ b/components/safe_browsing/core/common/utils.cc
@@ -89,7 +89,7 @@
   }
 
   if (net::IsLocalhost(url)) {
-    // Includes: "//localhost/", "//localhost.localdomain/", "//127.0.0.1/"
+    // Includes: "//localhost/", "//127.0.0.1/"
     return false;
   }
 
diff --git a/components/safe_browsing/core/realtime/url_lookup_service_unittest.cc b/components/safe_browsing/core/realtime/url_lookup_service_unittest.cc
index 55018600..6bf6722 100644
--- a/components/safe_browsing/core/realtime/url_lookup_service_unittest.cc
+++ b/components/safe_browsing/core/realtime/url_lookup_service_unittest.cc
@@ -487,7 +487,6 @@
     bool can_check;
   } can_check_url_cases[] = {{"ftp://example.test/path", false},
                              {"http://localhost/path", false},
-                             {"http://localhost.localdomain/path", false},
                              {"http://127.0.0.1/path", false},
                              {"http://127.0.0.1:2222/path", false},
                              {"http://192.168.1.1/path", false},
diff --git a/content/browser/bad_message.cc b/content/browser/bad_message.cc
index 0fe3592..588b8da 100644
--- a/content/browser/bad_message.cc
+++ b/content/browser/bad_message.cc
@@ -23,6 +23,8 @@
   static auto* bad_message_reason = base::debug::AllocateCrashKeyString(
       "bad_message_reason", base::debug::CrashKeySize::Size32);
 
+  TRACE_EVENT_INSTANT1("ipc,security", "content::ReceivedBadMessage",
+                       TRACE_EVENT_SCOPE_THREAD, "reason", reason);
   LOG(ERROR) << "Terminating renderer for bad IPC message, reason " << reason;
   base::UmaHistogramSparse("Stability.BadMessageTerminated.Content", reason);
   base::debug::SetCrashKeyString(bad_message_reason,
diff --git a/content/browser/navigation_browsertest.cc b/content/browser/navigation_browsertest.cc
index 71d657e..f6add29f 100644
--- a/content/browser/navigation_browsertest.cc
+++ b/content/browser/navigation_browsertest.cc
@@ -1067,50 +1067,6 @@
   }
 }
 
-// Ensure that renderer initiated navigations which have the opener suppressed
-// work.
-IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
-                       RendererInitiatedNewWindowNoOpenerNavigation) {
-  GURL url(embedded_test_server()->GetURL("/simple_links.html"));
-  EXPECT_TRUE(NavigateToURL(shell(), url));
-
-  RenderFrameHost* initial_rfh = current_frame_host();
-  url::Origin initial_origin = initial_rfh->GetLastCommittedOrigin();
-  base::UnguessableToken initiator_frame_token = initial_rfh->GetFrameToken();
-
-  // Simulate clicking on a cross-site link which has rel="noopener".
-  {
-    const char kReplacePortNumber[] =
-        "window.domAutomationController.send(setPortNumber(%d));";
-    uint16_t port_number = embedded_test_server()->port();
-    GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html");
-    bool success = false;
-    EXPECT_TRUE(ExecuteScriptAndExtractBool(
-        shell(), base::StringPrintf(kReplacePortNumber, port_number),
-        &success));
-    success = false;
-
-    ShellAddedObserver new_shell_observer;
-    EXPECT_TRUE(
-        ExecuteScriptAndExtractBool(shell(),
-                                    "window.domAutomationController.send("
-                                    "clickCrossSiteNewWindowNoOpenerLink());",
-                                    &success));
-    EXPECT_TRUE(success);
-
-    TestNavigationObserver observer(
-        new_shell_observer.GetShell()->web_contents());
-    observer.Wait();
-
-    EXPECT_EQ(url, observer.last_navigation_url());
-    EXPECT_TRUE(observer.last_navigation_succeeded());
-    EXPECT_EQ(initial_origin, observer.last_initiator_origin().value());
-    EXPECT_TRUE(observer.last_initiator_frame_token().has_value());
-    EXPECT_EQ(initiator_frame_token,
-              observer.last_initiator_frame_token().value());
-  }
-}
-
 IN_PROC_BROWSER_TEST_F(NavigationBrowserTest,
                        RendererInitiatedWithSubframeInitator) {
   GURL url(embedded_test_server()->GetURL(
diff --git a/content/browser/renderer_host/navigation_controller_impl.cc b/content/browser/renderer_host/navigation_controller_impl.cc
index a96a0103..f7f15e53 100644
--- a/content/browser/renderer_host/navigation_controller_impl.cc
+++ b/content/browser/renderer_host/navigation_controller_impl.cc
@@ -3492,7 +3492,7 @@
 
   auto navigation_request = NavigationRequest::CreateBrowserInitiated(
       node, std::move(common_params), std::move(commit_params),
-      !params.is_renderer_initiated, params.was_opener_suppressed,
+      !params.is_renderer_initiated,
       params.initiator_frame_token.has_value()
           ? &(params.initiator_frame_token.value())
           : nullptr,
@@ -3613,8 +3613,7 @@
 
   return NavigationRequest::CreateBrowserInitiated(
       frame_tree_node, std::move(common_params), std::move(commit_params),
-      !entry->is_renderer_initiated(), false /* was_opener_suppressed */,
-      nullptr /* initiator_frame_token */,
+      !entry->is_renderer_initiated(), nullptr /* initiator_frame_token */,
       ChildProcessHost::kInvalidUniqueID /* initiator_process_id */,
       entry->extra_headers(), frame_entry, entry, request_body,
       nullptr /* navigation_ui_data */, base::nullopt /* impression */);
@@ -3715,8 +3714,7 @@
   std::unique_ptr<NavigationRequest> navigation_request =
       NavigationRequest::CreateBrowserInitiated(
           node, std::move(common_params), std::move(commit_params),
-          true /* browser_initiated */, false /* was_opener_suppressed */,
-          nullptr /* initiator_frame_token */,
+          true /* browser_initiated */, nullptr /* initiator_frame_token */,
           ChildProcessHost::kInvalidUniqueID /* initiator_process_id */,
           "" /* extra_headers */, nullptr /* frame_entry */,
           nullptr /* entry */, nullptr /* post_body */,
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index 5ccaece..ce1cb30 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -708,7 +708,6 @@
     mojom::CommonNavigationParamsPtr common_params,
     mojom::CommitNavigationParamsPtr commit_params,
     bool browser_initiated,
-    bool was_opener_suppressed,
     const base::UnguessableToken* initiator_frame_token,
     int initiator_process_id,
     const std::string& extra_headers,
@@ -764,7 +763,7 @@
       false /* from_begin_navigation */, false /* is_for_commit */, frame_entry,
       entry, std::move(navigation_ui_data), mojo::NullAssociatedRemote(),
       mojo::NullRemote(), rfh_restored_from_back_forward_cache,
-      initiator_process_id, was_opener_suppressed));
+      initiator_process_id));
 
   if (frame_entry) {
     navigation_request->blob_url_loader_factory_ =
@@ -871,8 +870,6 @@
   int initiator_process_id =
       frame_tree_node->current_frame_host()->GetProcess()->GetID();
 
-  // `was_opener_suppressed` can be true for renderer initiated navigations, but
-  // only in cases which get routed through `CreateBrowserInitiated()` instead.
   std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest(
       frame_tree_node, std::move(common_params), std::move(begin_params),
       std::move(commit_params),
@@ -883,8 +880,7 @@
       nullptr,  // navigation_ui_data
       std::move(navigation_client), std::move(navigation_initiator),
       nullptr,  // rfh_restored_from_back_forward_cache
-      initiator_process_id,
-      /*was_opener_suppressed=*/false));
+      initiator_process_id));
   navigation_request->blob_url_loader_factory_ =
       std::move(blob_url_loader_factory);
   navigation_request->prefetched_signed_exchange_cache_ =
@@ -981,8 +977,7 @@
       nullptr /* frame_navigation_entry */, nullptr /* navigation_entry */,
       nullptr /* navigation_ui_data */, mojo::NullAssociatedRemote(),
       mojo::NullRemote(), nullptr /* rfh_restored_from_back_forward_cache */,
-      ChildProcessHost::kInvalidUniqueID /* initiator_process_id */,
-      false /* was_opener_suppressed */));
+      ChildProcessHost::kInvalidUniqueID /* initiator_process_id */));
 
   navigation_request->web_bundle_navigation_info_ =
       std::move(web_bundle_navigation_info);
@@ -1014,8 +1009,7 @@
     mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client,
     mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator,
     RenderFrameHostImpl* rfh_restored_from_back_forward_cache,
-    int initiator_process_id,
-    bool was_opener_suppressed)
+    int initiator_process_id)
     : frame_tree_node_(frame_tree_node),
       is_for_commit_(is_for_commit),
       common_params_(std::move(common_params)),
@@ -1045,7 +1039,6 @@
           frame_tree_node->current_frame_host()->GetRoutingID())),
       initiator_frame_token_(begin_params_->initiator_frame_token),
       initiator_process_id_(initiator_process_id),
-      was_opener_suppressed_(was_opener_suppressed),
       coop_status_(frame_tree_node, common_params_->initiator_origin),
       previous_page_ukm_source_id_(
           frame_tree_node_->current_frame_host()->GetPageUkmSourceId()) {
@@ -1477,9 +1470,8 @@
                                  frame_host_choice_reason);
       SCOPED_CRASH_KEY_BOOL("nav_request", "has_source_instance",
                             !!GetSourceSiteInstance());
-      // Crash keys capturing values for/related to |was_opener_suppressed_|.
-      SCOPED_CRASH_KEY_BOOL("nav_request", "was_opener_suppressed",
-                            was_opener_suppressed_);
+      // Crash keys capturing values affecting |was_opener_suppressed| in
+      // RequiresInitiatorBasedSourceSiteInstance:
       SCOPED_CRASH_KEY_BOOL("nav_request", "is_main_frame", IsInMainFrame());
       SCOPED_CRASH_KEY_BOOL("nav_request", "got_initiator_routing_id",
                             GetInitiatorFrameToken() != base::nullopt);
@@ -5165,7 +5157,17 @@
       common_params_->initiator_origin->GetTupleOrPrecursorTupleIfOpaque()
           .IsValid();
 
-  return is_data_or_about && has_valid_initiator && !was_opener_suppressed_ &&
+  // If renderer-initiated navigation of a main frame |has_valid_initiator| but
+  // has no |initiator_frame_token_|, then it means that the opener was
+  // suppressed (and therefore that a source SiteInstance is not needed). Note
+  // that |initiator_frame_token_| is always base::nullopt during
+  // browser-initiated navigations (including session restore or history
+  // navigations).
+  const bool was_opener_suppressed =
+      has_valid_initiator && frame_tree_node()->IsMainFrame() &&
+      !initiator_frame_token_.has_value() && !browser_initiated_;
+
+  return is_data_or_about && has_valid_initiator && !was_opener_suppressed &&
          !dest_site_instance_;
 }
 
diff --git a/content/browser/renderer_host/navigation_request.h b/content/browser/renderer_host/navigation_request.h
index a1647b73..eaa4909 100644
--- a/content/browser/renderer_host/navigation_request.h
+++ b/content/browser/renderer_host/navigation_request.h
@@ -170,7 +170,6 @@
       mojom::CommonNavigationParamsPtr common_params,
       mojom::CommitNavigationParamsPtr commit_params,
       bool browser_initiated,
-      bool was_opener_suppressed,
       const base::UnguessableToken* initiator_frame_token,
       int initiator_process_id,
       const std::string& extra_headers,
@@ -801,8 +800,7 @@
       mojo::PendingRemote<blink::mojom::NavigationInitiator>
           navigation_initiator,
       RenderFrameHostImpl* rfh_restored_from_back_forward_cache,
-      int initiator_process_id,
-      bool was_opener_suppressed);
+      int initiator_process_id);
 
   // Checks if the response requests an isolated origin (using either origin
   // policy or the Origin-Isolation header), and if so opts in the origin to be
@@ -1463,11 +1461,6 @@
   // only valid in conjunction with it.
   int initiator_process_id_ = ChildProcessHost::kInvalidUniqueID;
 
-  // Whether a navigation in a new window had the opener suppressed. False if
-  // the navigation is not in a new window. Can only be true for renderer
-  // initiated navigations which use `CreateBrowserInitiated()`.
-  bool was_opener_suppressed_;
-
   // This tracks a connection between the current pending entry and this
   // request, such that the pending entry can be discarded if no requests are
   // left referencing it.
diff --git a/content/browser/renderer_host/navigation_request_unittest.cc b/content/browser/renderer_host/navigation_request_unittest.cc
index 07616a2..ae69926 100644
--- a/content/browser/renderer_host/navigation_request_unittest.cc
+++ b/content/browser/renderer_host/navigation_request_unittest.cc
@@ -200,7 +200,7 @@
     request_ = NavigationRequest::CreateBrowserInitiated(
         main_test_rfh()->frame_tree_node(), std::move(common_params),
         std::move(commit_params), false /* browser-initiated */,
-        false /* was_opener_suppressed */, nullptr /* initiator_frame_token */,
+        nullptr /* initiator_frame_token */,
         ChildProcessHost::kInvalidUniqueID /* initiator_process_id */,
         std::string() /* extra_headers */, nullptr /* frame_entry */,
         nullptr /* entry */, nullptr /* post_body */,
diff --git a/content/browser/renderer_host/navigator.cc b/content/browser/renderer_host/navigator.cc
index bc820f3..8f9fd24 100644
--- a/content/browser/renderer_host/navigator.cc
+++ b/content/browser/renderer_host/navigator.cc
@@ -509,7 +509,7 @@
     WindowOpenDisposition disposition,
     bool should_replace_current_entry,
     bool user_gesture,
-    blink::TriggeringEventInfo triggering_event_info,
+    blink::mojom::TriggeringEventInfo triggering_event_info,
     const std::string& href_translate,
     scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
     const base::Optional<Impression>& impression) {
diff --git a/content/browser/renderer_host/navigator.h b/content/browser/renderer_host/navigator.h
index 2876307..2431c90 100644
--- a/content/browser/renderer_host/navigator.h
+++ b/content/browser/renderer_host/navigator.h
@@ -18,7 +18,7 @@
 #include "mojo/public/cpp/bindings/pending_associated_remote.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "third_party/blink/public/common/loader/previews_state.h"
-#include "third_party/blink/public/common/navigation/triggering_event_info.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom.h"
 #include "third_party/blink/public/mojom/frame/navigation_initiator.mojom.h"
 #include "ui/base/window_open_disposition.h"
 
@@ -131,7 +131,7 @@
       WindowOpenDisposition disposition,
       bool should_replace_current_entry,
       bool user_gesture,
-      blink::TriggeringEventInfo triggering_event_info,
+      blink::mojom::TriggeringEventInfo triggering_event_info,
       const std::string& href_translate,
       scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
       const base::Optional<Impression>& impression);
diff --git a/content/browser/renderer_host/render_frame_host_manager_unittest.cc b/content/browser/renderer_host/render_frame_host_manager_unittest.cc
index df5bc69..bbbae29 100644
--- a/content/browser/renderer_host/render_frame_host_manager_unittest.cc
+++ b/content/browser/renderer_host/render_frame_host_manager_unittest.cc
@@ -414,7 +414,7 @@
     std::unique_ptr<NavigationRequest> navigation_request =
         NavigationRequest::CreateBrowserInitiated(
             frame_tree_node, std::move(common_params), std::move(commit_params),
-            !entry->is_renderer_initiated(), false /* was_opener_suppressed */,
+            !entry->is_renderer_initiated(),
             nullptr /* initiator_frame_token */,
             ChildProcessHost::kInvalidUniqueID /* initiator_process_id */,
             entry->extra_headers(), frame_entry, entry, request_body,
@@ -2854,8 +2854,7 @@
   std::unique_ptr<NavigationRequest> navigation_request =
       NavigationRequest::CreateBrowserInitiated(
           frame_tree_node, std::move(common_params), std::move(commit_params),
-          !entry.is_renderer_initiated(), false /* was_opener_suppressed */,
-          nullptr /* initiator_frame_token */,
+          !entry.is_renderer_initiated(), nullptr /* initiator_frame_token */,
           ChildProcessHost::kInvalidUniqueID /* initiator_process_id */,
           entry.extra_headers(), frame_entry, &entry,
           nullptr /* request_body */, nullptr /* navigation_ui_data */,
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index 046084c5..e1e48dd8 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -84,11 +84,11 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/blob/blob_utils.h"
-#include "third_party/blink/public/common/navigation/triggering_event_info.h"
 #include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
 #include "third_party/blink/public/mojom/blob/blob_url_store.mojom-test-utils.h"
 #include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
 #include "third_party/blink/public/mojom/frame/frame.mojom-test-utils.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom.h"
 
 using IPC::IpcSecurityTestUtil;
 using ::testing::HasSubstr;
@@ -144,7 +144,7 @@
       ChildProcessHost::kInvalidUniqueID /* initiator_process_id */,
       url::Origin::Create(foo), nullptr, std::string(), Referrer(),
       WindowOpenDisposition::CURRENT_TAB, false, true,
-      blink::TriggeringEventInfo::kFromTrustedEvent, std::string(),
+      blink::mojom::TriggeringEventInfo::kFromTrustedEvent, std::string(),
       nullptr /* blob_url_loader_factory */, base::nullopt /* impression */);
 
   // Since the navigation above requires a cross-process swap, there will be a
diff --git a/content/browser/service_worker/service_worker_client_utils.cc b/content/browser/service_worker/service_worker_client_utils.cc
index 7128171..4434163 100644
--- a/content/browser/service_worker/service_worker_client_utils.cc
+++ b/content/browser/service_worker/service_worker_client_utils.cc
@@ -308,8 +308,9 @@
           url, Referrer(script_url, network::mojom::ReferrerPolicy::kDefault)),
       WindowOpenDisposition::CURRENT_TAB,
       false /* should_replace_current_entry */, false /* user_gesture */,
-      blink::TriggeringEventInfo::kUnknown, std::string() /* href_translate */,
-      nullptr /* blob_url_loader_factory */, base::nullopt);
+      blink::mojom::TriggeringEventInfo::kUnknown,
+      std::string() /* href_translate */, nullptr /* blob_url_loader_factory */,
+      base::nullopt);
   new OpenURLObserver(web_contents, frame_tree_node_id, std::move(callback));
 }
 
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 0488afe..8056f3b 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -3660,7 +3660,6 @@
           std::make_unique<NavigationController::LoadURLParams>(
               params.target_url);
       load_params->initiator_origin = opener->GetLastCommittedOrigin();
-      load_params->initiator_frame_token = opener->GetFrameToken();
       // Avoiding setting |load_params->source_site_instance| when
       // |opener_suppressed| is true, because in that case we do not want to use
       // the old SiteInstance and/or BrowsingInstance.  See also the test here:
@@ -3668,9 +3667,7 @@
       load_params->referrer = params.referrer.To<Referrer>();
       load_params->transition_type = ui::PAGE_TRANSITION_LINK;
       load_params->is_renderer_initiated = true;
-      load_params->was_opener_suppressed = true;
       load_params->has_user_gesture = has_user_gesture;
-      load_params->impression = params.impression;
 
       if (delegate_ && !is_guest &&
           !delegate_->ShouldResumeRequestsForCreatedWindow()) {
diff --git a/content/common/BUILD.gn b/content/common/BUILD.gn
index c370af73..ef8ea1e 100644
--- a/content/common/BUILD.gn
+++ b/content/common/BUILD.gn
@@ -530,10 +530,6 @@
           cpp = "::ui::NativeTheme::SystemThemeColor"
         },
         {
-          mojom = "content.mojom.TriggeringEventInfo"
-          cpp = "::blink::TriggeringEventInfo"
-        },
-        {
           mojom = "content.mojom.VisualProperties"
           cpp = "::blink::VisualProperties"
         },
@@ -564,7 +560,6 @@
         "//third_party/blink/public/common/input/web_mouse_wheel_event.h",
         "//third_party/blink/public/common/input/web_pointer_properties.h",
         "//third_party/blink/public/common/input/web_touch_point.h",
-        "//third_party/blink/public/common/navigation/triggering_event_info.h",
         "//ui/events/blink/did_overscroll_params.h",
         "//ui/events/blink/web_input_event_traits.h",
         "//ui/latency/ipc/latency_info_param_traits.h",
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
index 559d2ee..e6788b4 100644
--- a/content/common/frame.mojom
+++ b/content/common/frame.mojom
@@ -27,6 +27,7 @@
 import "third_party/blink/public/mojom/commit_result/commit_result.mojom";
 import "third_party/blink/public/mojom/devtools/console_message.mojom";
 import "third_party/blink/public/mojom/devtools/devtools_agent.mojom";
+import "third_party/blink/public/mojom/frame/frame.mojom";
 import "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom";
 import "third_party/blink/public/mojom/frame/frame_owner_properties.mojom";
 import "third_party/blink/public/mojom/frame/frame_policy.mojom";
@@ -280,10 +281,6 @@
 
   // The window features to use for the new window.
   blink.mojom.WindowFeatures features;
-
-  // The impression associated with the navigation in the new window, if
-  // one is specified.
-  Impression? impression;
 };
 
 // Operation result when the renderer asks the browser to create a new window.
@@ -347,9 +344,6 @@
   blink.mojom.PolicyContainer policy_container;
 };
 
-[Native]
-enum TriggeringEventInfo;
-
 // This struct holds parameters included in the OpenURL method sent by the
 // renderer to the browser, |is_history_navigation_in_new_child_frame| is true
 // in the case that the browser process should look for an existing history item
@@ -374,7 +368,7 @@
   bool user_gesture;
 
   // Extra information about the triggering of the OpenURL.
-  TriggeringEventInfo triggering_event_info;
+  blink.mojom.TriggeringEventInfo triggering_event_info;
   pending_remote<blink.mojom.BlobURLToken>? blob_url_token;
   string href_translate;
   Impression? impression;
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index b7562c8f..f0690df 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -47,7 +47,6 @@
 #include "third_party/blink/public/common/frame/frame_visual_properties.h"
 #include "third_party/blink/public/common/loader/previews_state.h"
 #include "third_party/blink/public/common/messaging/message_port_channel.h"
-#include "third_party/blink/public/common/navigation/triggering_event_info.h"
 #include "third_party/blink/public/common/page_state/page_state.h"
 #include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
 #include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
@@ -56,6 +55,7 @@
 #include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-shared.h"
 #include "third_party/blink/public/mojom/feature_policy/policy_disposition.mojom.h"
 #include "third_party/blink/public/mojom/frame/blocked_navigation_types.mojom.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom.h"
 #include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom.h"
 #include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom.h"
 #include "third_party/blink/public/mojom/frame/lifecycle.mojom.h"
@@ -106,8 +106,6 @@
                           blink::mojom::FeaturePolicyFeature::kMaxValue)
 IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::DocumentPolicyFeature,
                           blink::mojom::DocumentPolicyFeature::kMaxValue)
-IPC_ENUM_TRAITS_MAX_VALUE(blink::TriggeringEventInfo,
-                          blink::TriggeringEventInfo::kMaxValue)
 IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::UserActivationUpdateType,
                           blink::mojom::UserActivationUpdateType::kMaxValue)
 IPC_ENUM_TRAITS_MAX_VALUE(blink::mojom::PolicyDisposition,
diff --git a/content/public/browser/navigation_controller.h b/content/public/browser/navigation_controller.h
index e744c444..6017ae6 100644
--- a/content/public/browser/navigation_controller.h
+++ b/content/public/browser/navigation_controller.h
@@ -183,11 +183,6 @@
     // important for tracking whether to display pending URLs.
     bool is_renderer_initiated;
 
-    // Whether a navigation in a new window has the opener suppressed. False if
-    // the navigation is not in a new window. Can only be true when
-    // |is_renderer_initiated| is true.
-    bool was_opener_suppressed;
-
     // User agent override for this load. See comments in
     // UserAgentOverrideOption definition.
     UserAgentOverrideOption override_user_agent = UA_OVERRIDE_INHERIT;
diff --git a/content/public/browser/page_navigator.h b/content/public/browser/page_navigator.h
index c7b9618f..1c10e21 100644
--- a/content/public/browser/page_navigator.h
+++ b/content/public/browser/page_navigator.h
@@ -24,7 +24,7 @@
 #include "ipc/ipc_message.h"
 #include "services/network/public/cpp/resource_request_body.h"
 #include "services/network/public/cpp/shared_url_loader_factory.h"
-#include "third_party/blink/public/common/navigation/triggering_event_info.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom.h"
 #include "ui/base/page_transition_types.h"
 #include "ui/base/window_open_disposition.h"
 #include "url/gurl.h"
@@ -130,8 +130,8 @@
 
   // Whether the call to OpenURL was triggered by an Event, and what the
   // isTrusted flag of the event was.
-  blink::TriggeringEventInfo triggering_event_info =
-      blink::TriggeringEventInfo::kUnknown;
+  blink::mojom::TriggeringEventInfo triggering_event_info =
+      blink::mojom::TriggeringEventInfo::kUnknown;
 
   // Indicates whether this navigation was started via context menu.
   bool started_from_context_menu;
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 47572dce..8c10cc7 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -936,7 +936,7 @@
     "RetryGetVideoCaptureDeviceInfos", base::FEATURE_DISABLED_BY_DEFAULT};
 #endif  // defined(OS_MAC)
 
-#if !defined(OS_WIN) && !defined(OS_FUCHSIA) && !defined(OS_IOS)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
 // If the JavaScript on a WebUI page has an error (such as an unhandled
 // exception), report that error back the crash reporting infrastructure, same
 // as we do for program crashes.
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 629c425..3e9bfcf 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -220,7 +220,7 @@
 CONTENT_EXPORT extern const base::Feature kRetryGetVideoCaptureDeviceInfos;
 #endif  // defined(OS_MAC)
 
-#if !defined(OS_WIN) && !defined(OS_FUCHSIA) && !defined(OS_IOS)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
 CONTENT_EXPORT extern const base::Feature kSendWebUIJavaScriptErrorReports;
 CONTENT_EXPORT extern const char
     kSendWebUIJavaScriptErrorReportsSendToProductionVariation[];
diff --git a/content/public/renderer/render_frame.h b/content/public/renderer/render_frame.h
index d49cdad..84df29a0 100644
--- a/content/public/renderer/render_frame.h
+++ b/content/public/renderer/render_frame.h
@@ -21,8 +21,8 @@
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "services/service_manager/public/cpp/binder_registry.h"
 #include "third_party/blink/public/common/loader/previews_state.h"
-#include "third_party/blink/public/common/navigation/triggering_event_info.h"
 #include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom.h"
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/public/web/web_navigation_policy.h"
 #include "ui/accessibility/ax_mode.h"
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index 82e8465d5..afe16314 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -74,7 +74,6 @@
 #include "third_party/blink/public/common/feature_policy/feature_policy.h"
 #include "third_party/blink/public/common/loader/loading_behavior_flag.h"
 #include "third_party/blink/public/common/loader/previews_state.h"
-#include "third_party/blink/public/common/navigation/triggering_event_info.h"
 #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/common/unique_name/unique_name_helper.h"
 #include "third_party/blink/public/mojom/autoplay/autoplay.mojom.h"
@@ -82,6 +81,7 @@
 #include "third_party/blink/public/mojom/commit_result/commit_result.mojom.h"
 #include "third_party/blink/public/mojom/devtools/console_message.mojom.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom.h"
 #include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom.h"
 #include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom-forward.h"
 #include "third_party/blink/public/mojom/frame/policy_container.mojom-shared.h"
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc
index e9afefe..b810421f 100644
--- a/content/renderer/render_frame_proxy.cc
+++ b/content/renderer/render_frame_proxy.cc
@@ -34,7 +34,7 @@
 #include "mojo/public/cpp/bindings/pending_associated_remote.h"
 #include "third_party/blink/public/common/feature_policy/feature_policy.h"
 #include "third_party/blink/public/common/frame/frame_policy.h"
-#include "third_party/blink/public/common/navigation/triggering_event_info.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom.h"
 #include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom.h"
 #include "third_party/blink/public/platform/url_conversion.h"
 #include "third_party/blink/public/platform/web_rect.h"
@@ -618,7 +618,7 @@
   params->disposition = WindowOpenDisposition::CURRENT_TAB;
   params->should_replace_current_entry = should_replace_current_entry;
   params->user_gesture = request.HasUserGesture();
-  params->triggering_event_info = blink::TriggeringEventInfo::kUnknown;
+  params->triggering_event_info = blink::mojom::TriggeringEventInfo::kUnknown;
   params->blob_url_token = std::move(blob_url_token);
 
   params->initiator_frame_token =
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc
index 35de7c7..c53f732 100644
--- a/content/renderer/render_view_browsertest.cc
+++ b/content/renderer/render_view_browsertest.cc
@@ -13,7 +13,6 @@
 #include "base/json/json_reader.h"
 #include "base/json/json_writer.h"
 #include "base/location.h"
-#include "base/optional.h"
 #include "base/run_loop.h"
 #include "base/single_thread_task_runner.h"
 #include "base/stl_util.h"
@@ -1078,8 +1077,7 @@
       GetMainFrame(), popup_request, blink::WebWindowFeatures(), "foo",
       blink::kWebNavigationPolicyNewForegroundTab,
       network::mojom::WebSandboxFlags::kNone,
-      blink::AllocateSessionStorageNamespaceId(), consumed_user_gesture,
-      base::nullopt);
+      blink::AllocateSessionStorageNamespaceId(), consumed_user_gesture);
   auto popup_navigation_info = std::make_unique<blink::WebNavigationInfo>();
   popup_navigation_info->url_request = std::move(popup_request);
   popup_navigation_info->frame_type =
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index 3128b21..95450cc 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -22,7 +22,6 @@
 #include "content/public/renderer/render_view_visitor.h"
 #include "content/public/renderer/window_features_converter.h"
 #include "content/renderer/agent_scheduling_group.h"
-#include "content/renderer/impression_conversions.h"
 #include "content/renderer/render_frame_proxy.h"
 #include "content/renderer/render_thread_impl.h"
 #include "third_party/blink/public/common/features.h"
@@ -346,8 +345,7 @@
     WebNavigationPolicy policy,
     network::mojom::WebSandboxFlags sandbox_flags,
     const blink::SessionStorageNamespaceId& session_storage_namespace_id,
-    bool& consumed_user_gesture,
-    const base::Optional<blink::WebImpression>& impression) {
+    bool& consumed_user_gesture) {
   consumed_user_gesture = false;
   RenderFrameImpl* creator_frame = RenderFrameImpl::FromWebFrame(creator);
   mojom::CreateNewWindowParamsPtr params = mojom::CreateNewWindowParams::New();
@@ -382,10 +380,6 @@
   }
   params->features = ConvertWebWindowFeaturesToMojoWindowFeatures(features);
 
-  if (impression) {
-    params->impression = ConvertWebImpressionToImpression(*impression);
-  }
-
   // We preserve this information before sending the message since |params| is
   // moved on send.
   bool is_background_tab =
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index c860de18..5ec763b 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -170,8 +170,7 @@
       blink::WebNavigationPolicy policy,
       network::mojom::WebSandboxFlags sandbox_flags,
       const blink::SessionStorageNamespaceId& session_storage_namespace_id,
-      bool& consumed_user_gesture,
-      const base::Optional<blink::WebImpression>& impression) override;
+      bool& consumed_user_gesture) override;
   blink::WebPagePopup* CreatePopup(blink::WebLocalFrame* creator) override;
   base::StringPiece GetSessionStorageNamespaceId() override;
   void PrintPage(blink::WebLocalFrame* frame) override;
diff --git a/content/test/data/conversions/register_impression.js b/content/test/data/conversions/register_impression.js
index c7d7d212..70eba0f 100644
--- a/content/test/data/conversions/register_impression.js
+++ b/content/test/data/conversions/register_impression.js
@@ -46,6 +46,9 @@
 function createImpressionTagWithTarget(id, url, data, destination, target) {
   let anchor = document.createElement("a");
   anchor.href = url;
+  if (target === "_blank") {
+    anchor.rel = "opener";
+  }
   anchor.setAttribute("impressiondata", data);
   anchor.setAttribute("conversiondestination", destination);
   anchor.setAttribute("target", target);
diff --git a/content/test/data/simple_links.html b/content/test/data/simple_links.html
index 381ed5e..4cbfd6f9 100644
--- a/content/test/data/simple_links.html
+++ b/content/test/data/simple_links.html
@@ -17,9 +17,6 @@
 
     link = document.getElementById("cross_site_new_window_link");
     link.setAttribute("href", "http://foo.com:" + portNumber + "/title2.html");
-
-    link = document.getElementById("cross_site_new_window_no_opener_link");
-    link.setAttribute("href", "http://foo.com:" + portNumber + "/title2.html");
     return true;
   }
 
@@ -39,10 +36,6 @@
     return simulateClick(document.getElementById("cross_site_new_window_link"));
   }
 
-  function clickCrossSiteNewWindowNoOpenerLink() {
-    return simulateClick(document.getElementById("cross_site_new_window_no_opener_link"));
-  }
-
   function clickViewSourceLink() {
     return simulateClick(document.getElementById("view_source_link"));
   }
@@ -62,7 +55,6 @@
 <a href="view-source:about:blank" id="view_source_link">view-source:</a><br>
 <a href="title2.html" id="same_site_new_window_link" rel="opener" target="_blank">same-site new window</a>
 <a href="http://foo.com/title2.html" id="cross_site_new_window_link" rel="opener" target="_blank">cross-site new window</a>
-<a href="http://foo.com/title2.html" id="cross_site_new_window_no_opener_link" rel="noopener" target="_blank">cross-site new window no opener</a>
 <a href="" id="linkToSelf" rel="opener" target="_blank">self new window</a>
 <script>
   document.getElementById("linkToSelf").href = window.location.toString();
diff --git a/content/web_test/renderer/web_view_test_proxy.cc b/content/web_test/renderer/web_view_test_proxy.cc
index ace2e77..26e244ec 100644
--- a/content/web_test/renderer/web_view_test_proxy.cc
+++ b/content/web_test/renderer/web_view_test_proxy.cc
@@ -43,8 +43,7 @@
     blink::WebNavigationPolicy policy,
     network::mojom::WebSandboxFlags sandbox_flags,
     const blink::SessionStorageNamespaceId& session_storage_namespace_id,
-    bool& consumed_user_gesture,
-    const base::Optional<blink::WebImpression>& impression) {
+    bool& consumed_user_gesture) {
   if (test_runner_->ShouldDumpNavigationPolicy()) {
     test_runner_->PrintMessage(
         "Default policy for createView for '" +
@@ -62,7 +61,7 @@
   }
   return RenderViewImpl::CreateView(
       creator, request, features, frame_name, policy, sandbox_flags,
-      session_storage_namespace_id, consumed_user_gesture, impression);
+      session_storage_namespace_id, consumed_user_gesture);
 }
 
 void WebViewTestProxy::PrintPage(blink::WebLocalFrame* frame) {
diff --git a/content/web_test/renderer/web_view_test_proxy.h b/content/web_test/renderer/web_view_test_proxy.h
index 96f0faa6c..2c694e04 100644
--- a/content/web_test/renderer/web_view_test_proxy.h
+++ b/content/web_test/renderer/web_view_test_proxy.h
@@ -71,8 +71,7 @@
       blink::WebNavigationPolicy policy,
       network::mojom::WebSandboxFlags sandbox_flags,
       const blink::SessionStorageNamespaceId& session_storage_namespace_id,
-      bool& consumed_user_gesture,
-      const base::Optional<blink::WebImpression>& impression) override;
+      bool& consumed_user_gesture) override;
   void PrintPage(blink::WebLocalFrame* frame) override;
   blink::WebString AcceptLanguages() override;
 
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
index 6de753f..12208ff 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-de654378bbf0a74d626daa79dc838fb2876444e4
\ No newline at end of file
+8493e8d04083a4921d0d46b556443bf8f978d42c
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
index 5e6a2cb..1905e8e 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-61ad6e54b577c0bde9cb9eef59ff41d53e455370
\ No newline at end of file
+78fdced5554ddd871ff39e4b943c57a9840ac6e0
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
index 3686341..482be11 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-a89ae00e87759465366eac23e4330f804bfe2a31
\ No newline at end of file
+11e8055d0ca7ed3c174263771a9f5099831a285c
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
index 52aa4bd..e4fe888 100644
--- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-41732b01adb26c0d55b3cb6e99d118d291647031
\ No newline at end of file
+ba13d4d17a95485196a6ec2b0a3e990f677448d9
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
index 96f528a..abfb929 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-9b564cc539ed938da626b5149af2b897384fa39c
\ No newline at end of file
+d2bdd8ef794346dd9609aebc7f2c0c3626831510
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
index 4f73a0d..23d84fc 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-4cea067acbfea54b8bcd66e461fe075d2482e0c6
\ No newline at end of file
+33afa940b3f0967f8549d3e0bef245b033af237f
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
index b6191d8..85d82dc 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.arm64.zip.sha1
@@ -1 +1 @@
-017771985e2200e689cf266b05ec0f758369075f
\ No newline at end of file
+ccedac2b85d68b3dc14a5ecb67c2b7484c566ed8
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
index 51ce7de..b9cfb6ed 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.x64.zip.sha1
@@ -1 +1 @@
-1899a2b075e85b7a9f8b4740931fa47397006708
\ No newline at end of file
+256a34114e3c2c394a21d27377b2a04978d71550
\ No newline at end of file
diff --git a/net/base/url_util.cc b/net/base/url_util.cc
index 7b276c7..83dc9f8a 100644
--- a/net/base/url_util.cc
+++ b/net/base/url_util.cc
@@ -451,7 +451,6 @@
     normalized_host.resize(normalized_host.size() - 1);
 
   return normalized_host == "localhost" ||
-         normalized_host == "localhost.localdomain" ||
          IsNormalizedLocalhostTLD(normalized_host);
 }
 
diff --git a/net/base/url_util_unittest.cc b/net/base/url_util_unittest.cc
index 9d6bd70cf..d556d83 100644
--- a/net/base/url_util_unittest.cc
+++ b/net/base/url_util_unittest.cc
@@ -449,9 +449,6 @@
   EXPECT_TRUE(HostStringIsLocalhost("localHosT"));
   EXPECT_TRUE(HostStringIsLocalhost("localhost."));
   EXPECT_TRUE(HostStringIsLocalhost("localHost."));
-  EXPECT_TRUE(HostStringIsLocalhost("localhost.localdomain"));
-  EXPECT_TRUE(HostStringIsLocalhost("localhost.localDOMain"));
-  EXPECT_TRUE(HostStringIsLocalhost("localhost.localdomain."));
   EXPECT_TRUE(HostStringIsLocalhost("127.0.0.1"));
   EXPECT_TRUE(HostStringIsLocalhost("127.0.1.0"));
   EXPECT_TRUE(HostStringIsLocalhost("127.1.0.0"));
@@ -465,6 +462,9 @@
   EXPECT_TRUE(HostStringIsLocalhost("foo.localhoST"));
   EXPECT_TRUE(HostStringIsLocalhost("foo.localhoST."));
 
+  EXPECT_FALSE(HostStringIsLocalhost("localhost.localdomain"));
+  EXPECT_FALSE(HostStringIsLocalhost("localhost.localDOMain"));
+  EXPECT_FALSE(HostStringIsLocalhost("localhost.localdomain."));
   EXPECT_FALSE(HostStringIsLocalhost("localhost6"));
   EXPECT_FALSE(HostStringIsLocalhost("localhost6."));
   EXPECT_FALSE(HostStringIsLocalhost("localhost6.localdomain6"));
diff --git a/net/dns/dns_hosts_unittest.cc b/net/dns/dns_hosts_unittest.cc
index 5035336..65b0df2 100644
--- a/net/dns/dns_hosts_unittest.cc
+++ b/net/dns/dns_hosts_unittest.cc
@@ -33,7 +33,7 @@
 
 TEST(DnsHostsTest, ParseHosts) {
   const std::string kContents =
-      "127.0.0.1       localhost\tlocalhost.localdomain # standard\n"
+      "127.0.0.1       localhost # standard\n"
       "\n"
       "1.0.0.1 localhost # ignored, first hit above\n"
       "fe00::x example company # ignored, malformed IPv6\n"
@@ -56,7 +56,6 @@
 
   const ExpectedHostsEntry kEntries[] = {
       {"localhost", ADDRESS_FAMILY_IPV4, "127.0.0.1"},
-      {"localhost.localdomain", ADDRESS_FAMILY_IPV4, "127.0.0.1"},
       {"company", ADDRESS_FAMILY_IPV4, "1.0.0.1"},
       {"localhost", ADDRESS_FAMILY_IPV6, "::1"},
       {"ip6-localhost", ADDRESS_FAMILY_IPV6, "::1"},
diff --git a/net/dns/host_resolver_manager_unittest.cc b/net/dns/host_resolver_manager_unittest.cc
index 8dc9641..6d0aa18f 100644
--- a/net/dns/host_resolver_manager_unittest.cc
+++ b/net/dns/host_resolver_manager_unittest.cc
@@ -7072,16 +7072,16 @@
   TestBothLoopbackIPs("localhoST");
   TestBothLoopbackIPs("localhost.");
   TestBothLoopbackIPs("localhoST.");
-  TestBothLoopbackIPs("localhost.localdomain");
-  TestBothLoopbackIPs("localhost.localdomAIn");
-  TestBothLoopbackIPs("localhost.localdomain.");
-  TestBothLoopbackIPs("localhost.localdomAIn.");
   TestBothLoopbackIPs("foo.localhost");
   TestBothLoopbackIPs("foo.localhOSt");
   TestBothLoopbackIPs("foo.localhost.");
   TestBothLoopbackIPs("foo.localhOSt.");
 
   // Legacy localhost names.
+  EXPECT_FALSE(ResolveLocalHostname("localhost.localdomain", &addresses));
+  EXPECT_FALSE(ResolveLocalHostname("localhost.localdomAIn", &addresses));
+  EXPECT_FALSE(ResolveLocalHostname("localhost.localdomain.", &addresses));
+  EXPECT_FALSE(ResolveLocalHostname("localhost.localdomAIn.", &addresses));
   EXPECT_FALSE(ResolveLocalHostname("localhost6", &addresses));
   EXPECT_FALSE(ResolveLocalHostname("localhoST6", &addresses));
   EXPECT_FALSE(ResolveLocalHostname("localhost6.", &addresses));
diff --git a/pdf/out_of_process_instance.cc b/pdf/out_of_process_instance.cc
index e101717b..59c5a81 100644
--- a/pdf/out_of_process_instance.cc
+++ b/pdf/out_of_process_instance.cc
@@ -689,6 +689,12 @@
 }
 
 bool OutOfProcessInstance::HandleInputEvent(const pp::InputEvent& event) {
+  // Ignore user input in read-only mode.
+  // TODO(dhoss): Add a test for ignored input events. It is currently difficult
+  // to unit test certain `OutOfProcessInstance` methods.
+  if (engine()->IsReadOnly())
+    return false;
+
   // To simplify things, convert the event into device coordinates.
   pp::InputEvent event_device_res(event);
   {
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc
index 640024dc2..28e3ae9 100644
--- a/pdf/pdfium/pdfium_engine.cc
+++ b/pdf/pdfium/pdfium_engine.cc
@@ -976,7 +976,7 @@
 
 void PDFiumEngine::UpdateFocus(bool has_focus) {
   base::AutoReset<bool> updating_focus_guard(&updating_focus_, true);
-  if (has_focus) {
+  if (has_focus && !IsReadOnly()) {
     UpdateFocusItemType(last_focused_item_type_);
     if (focus_item_type_ == FocusElementType::kPage &&
         PageIndexInBounds(last_focused_page_) &&
@@ -2064,6 +2064,20 @@
 
 void PDFiumEngine::SetReadOnly(bool enable) {
   read_only_ = enable;
+
+  // Restore form highlights.
+  if (!read_only_) {
+    FPDF_SetFormFieldHighlightAlpha(form(), kFormHighlightAlpha);
+    return;
+  }
+
+  // Hide form highlights.
+  FPDF_SetFormFieldHighlightAlpha(form(), /*alpha=*/0);
+  KillFormFocus();
+
+  // Unselect text.
+  SelectionChangeInvalidator selection_invalidator(this);
+  selection_.clear();
 }
 
 void PDFiumEngine::SetTwoUpView(bool enable) {
@@ -2222,7 +2236,7 @@
 }
 
 void PDFiumEngine::SelectAll() {
-  if (in_form_text_area_)
+  if (in_form_text_area_ || IsReadOnly())
     return;
 
   SelectionChangeInvalidator selection_invalidator(this);
diff --git a/pdf/pdfium/pdfium_engine_unittest.cc b/pdf/pdfium/pdfium_engine_unittest.cc
index edf008f..f6c27b1 100644
--- a/pdf/pdfium/pdfium_engine_unittest.cc
+++ b/pdf/pdfium/pdfium_engine_unittest.cc
@@ -36,6 +36,7 @@
 using ::testing::Invoke;
 using ::testing::IsEmpty;
 using ::testing::NiceMock;
+using ::testing::Not;
 using ::testing::Return;
 using ::testing::StrictMock;
 
@@ -1125,4 +1126,56 @@
   ScrollFocusedAnnotationIntoView(engine.get());
 }
 
+class ReadOnlyTestClient : public TestClient {
+ public:
+  ReadOnlyTestClient() = default;
+  ~ReadOnlyTestClient() override = default;
+  ReadOnlyTestClient(const ReadOnlyTestClient&) = delete;
+  ReadOnlyTestClient& operator=(const ReadOnlyTestClient&) = delete;
+
+  // Mock PDFEngine::Client methods.
+  MOCK_METHOD(void, FormTextFieldFocusChange, (bool), (override));
+  MOCK_METHOD(void, SetSelectedText, (const std::string&), (override));
+};
+
+using PDFiumEngineReadOnlyTest = PDFiumTestBase;
+
+TEST_F(PDFiumEngineReadOnlyTest, KillFormFocus) {
+  NiceMock<ReadOnlyTestClient> client;
+  std::unique_ptr<PDFiumEngine> engine = InitializeEngine(
+      &client, FILE_PATH_LITERAL("annotation_form_fields.pdf"));
+  ASSERT_TRUE(engine);
+
+  // Setting read-only mode should kill form focus.
+  EXPECT_FALSE(engine->IsReadOnly());
+  EXPECT_CALL(client, FormTextFieldFocusChange(false));
+  engine->SetReadOnly(true);
+
+  // Attempting to focus during read-only mode should once more trigger a
+  // killing of form focus.
+  EXPECT_TRUE(engine->IsReadOnly());
+  EXPECT_CALL(client, FormTextFieldFocusChange(false));
+  engine->UpdateFocus(true);
+}
+
+TEST_F(PDFiumEngineReadOnlyTest, UnselectText) {
+  NiceMock<ReadOnlyTestClient> client;
+  std::unique_ptr<PDFiumEngine> engine =
+      InitializeEngine(&client, FILE_PATH_LITERAL("hello_world2.pdf"));
+  ASSERT_TRUE(engine);
+
+  // Update the plugin size so that all the text is visible by
+  // `SelectionChangeInvalidator`.
+  engine->PluginSizeUpdated({500, 500});
+
+  // Select text before going into read-only mode.
+  EXPECT_FALSE(engine->IsReadOnly());
+  EXPECT_CALL(client, SetSelectedText(Not(IsEmpty())));
+  engine->SelectAll();
+
+  // Setting read-only mode should unselect the text.
+  EXPECT_CALL(client, SetSelectedText(IsEmpty()));
+  engine->SetReadOnly(true);
+}
+
 }  // namespace chrome_pdf
diff --git a/services/network/public/cpp/is_potentially_trustworthy.cc b/services/network/public/cpp/is_potentially_trustworthy.cc
index dd7632e..87a5005 100644
--- a/services/network/public/cpp/is_potentially_trustworthy.cc
+++ b/services/network/public/cpp/is_potentially_trustworthy.cc
@@ -223,8 +223,6 @@
   // 5. If origin’s host component is "localhost" or falls within ".localhost",
   //    and the user agent conforms to the name resolution rules in
   //    [let-localhost-be-localhost], return "Potentially Trustworthy".
-  // TODO(https://crbug.com/1153337): This returns true for
-  // "localhost.localdomain". Should this host be excluded?
   if (net::IsLocalhost(origin.GetURL()))
     return true;
 
diff --git a/services/network/public/cpp/is_potentially_trustworthy_unittest.cc b/services/network/public/cpp/is_potentially_trustworthy_unittest.cc
index 7e3d1e3..ee4c69d 100644
--- a/services/network/public/cpp/is_potentially_trustworthy_unittest.cc
+++ b/services/network/public/cpp/is_potentially_trustworthy_unittest.cc
@@ -115,10 +115,8 @@
 
   EXPECT_FALSE(IsUrlPotentiallyTrustworthy("http://loopback"));
 
-  // TODO(https://crbug.com/1153337): Return false?
-  EXPECT_TRUE(IsUrlPotentiallyTrustworthy("http://localhost.localdomain"));
-
   // Legacy localhost names.
+  EXPECT_FALSE(IsUrlPotentiallyTrustworthy("http://localhost.localdomain"));
   EXPECT_FALSE(IsUrlPotentiallyTrustworthy("http://localhost6"));
   EXPECT_FALSE(IsUrlPotentiallyTrustworthy("ftp://localhost6.localdomain6"));
 
diff --git a/third_party/blink/public/common/BUILD.gn b/third_party/blink/public/common/BUILD.gn
index 95d0be7..bb3d652 100644
--- a/third_party/blink/public/common/BUILD.gn
+++ b/third_party/blink/public/common/BUILD.gn
@@ -157,7 +157,6 @@
     "mime_util/mime_util.h",
     "mobile_metrics/mobile_friendliness.h",
     "native_io/native_io_utils.h",
-    "navigation/triggering_event_info.h",
     "notifications/notification_constants.h",
     "notifications/notification_mojom_traits.h",
     "notifications/notification_resources.h",
diff --git a/third_party/blink/public/common/navigation/triggering_event_info.h b/third_party/blink/public/common/navigation/triggering_event_info.h
deleted file mode 100644
index 9232d7f..0000000
--- a/third_party/blink/public/common/navigation/triggering_event_info.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_NAVIGATION_TRIGGERING_EVENT_INFO_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_NAVIGATION_TRIGGERING_EVENT_INFO_H_
-
-namespace blink {
-
-// Extra info sometimes associated with a navigation.
-enum class TriggeringEventInfo {
-  kUnknown,
-
-  // The navigation was not triggered via a JS Event.
-  kNotFromEvent,
-
-  // The navigation was triggered via a JS event with isTrusted() == true.
-  kFromTrustedEvent,
-
-  // The navigation was triggered via a JS event with isTrusted() == false.
-  kFromUntrustedEvent,
-
-  kMaxValue = kFromUntrustedEvent,
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_NAVIGATION_TRIGGERING_EVENT_INFO_H_
diff --git a/third_party/blink/public/mojom/frame/frame.mojom b/third_party/blink/public/mojom/frame/frame.mojom
index af720508..f8cfa660 100644
--- a/third_party/blink/public/mojom/frame/frame.mojom
+++ b/third_party/blink/public/mojom/frame/frame.mojom
@@ -121,6 +121,19 @@
   kRotate90Counterclockwise,
 };
 
+enum TriggeringEventInfo {
+  kUnknown,
+
+  // The navigation was not triggered via a JS Event.
+  kNotFromEvent,
+
+  // The navigation was triggered via a JS event with isTrusted() == true.
+  kFromTrustedEvent,
+
+  // The navigation was triggered via a JS event with isTrusted() == false.
+  kFromUntrustedEvent,
+};
+
 // The maximum number of characters of the document's title that we're willing
 // to accept in the browser process.
 const uint16 kMaxTitleChars = 4096; // 4 * 1024;
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h
index 85a51e35..03bbdf9d 100644
--- a/third_party/blink/public/web/web_local_frame_client.h
+++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -43,11 +43,11 @@
 #include "third_party/blink/public/common/feature_policy/feature_policy.h"
 #include "third_party/blink/public/common/loader/loading_behavior_flag.h"
 #include "third_party/blink/public/common/loader/url_loader_factory_bundle.h"
-#include "third_party/blink/public/common/navigation/triggering_event_info.h"
 #include "third_party/blink/public/common/tokens/tokens.h"
 #include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
 #include "third_party/blink/public/mojom/devtools/console_message.mojom-forward.h"
 #include "third_party/blink/public/mojom/frame/blocked_navigation_types.mojom-shared.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom-shared.h"
 #include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom-shared.h"
 #include "third_party/blink/public/mojom/frame/lifecycle.mojom-shared.h"
 #include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom-shared.h"
diff --git a/third_party/blink/public/web/web_navigation_params.h b/third_party/blink/public/web/web_navigation_params.h
index ad5e87e2f..9000734 100644
--- a/third_party/blink/public/web/web_navigation_params.h
+++ b/third_party/blink/public/web/web_navigation_params.h
@@ -17,9 +17,9 @@
 #include "services/network/public/mojom/url_loader_factory.mojom-shared.h"
 #include "services/network/public/mojom/web_client_hints_types.mojom-shared.h"
 #include "third_party/blink/public/common/frame/frame_policy.h"
-#include "third_party/blink/public/common/navigation/triggering_event_info.h"
 #include "third_party/blink/public/mojom/blob/blob_url_store.mojom-shared.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-shared.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom-shared.h"
 #include "third_party/blink/public/mojom/frame/navigation_initiator.mojom-shared.h"
 #include "third_party/blink/public/mojom/frame/policy_container.mojom-forward.h"
 #include "third_party/blink/public/platform/cross_variant_mojo_util.h"
@@ -115,7 +115,8 @@
   bool blocking_downloads_in_sandbox_enabled = false;
 
   // Event information. See TriggeringEventInfo.
-  TriggeringEventInfo triggering_event_info = TriggeringEventInfo::kUnknown;
+  blink::mojom::TriggeringEventInfo triggering_event_info =
+      blink::mojom::TriggeringEventInfo::kUnknown;
 
   // If the navigation is a result of form submit, the form element is provided.
   WebFormElement form;
diff --git a/third_party/blink/public/web/web_view_client.h b/third_party/blink/public/web/web_view_client.h
index 50c14b8..8c8220f 100644
--- a/third_party/blink/public/web/web_view_client.h
+++ b/third_party/blink/public/web/web_view_client.h
@@ -31,14 +31,12 @@
 #ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_VIEW_CLIENT_H_
 #define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_VIEW_CLIENT_H_
 
-#include "base/optional.h"
 #include "base/strings/string_piece.h"
 #include "services/network/public/mojom/web_sandbox_flags.mojom-shared.h"
 #include "third_party/blink/public/common/dom_storage/session_storage_namespace_id.h"
 #include "third_party/blink/public/common/feature_policy/feature_policy_features.h"
 #include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
 #include "third_party/blink/public/mojom/page/page_visibility_state.mojom-forward.h"
-#include "third_party/blink/public/platform/web_impression.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/public/web/web_ax_enums.h"
 #include "third_party/blink/public/web/web_frame.h"
@@ -72,8 +70,7 @@
       WebNavigationPolicy policy,
       network::mojom::WebSandboxFlags,
       const SessionStorageNamespaceId& session_storage_namespace_id,
-      bool& consumed_user_gesture,
-      const base::Optional<WebImpression>&) {
+      bool& consumed_user_gesture) {
     return nullptr;
   }
 
diff --git a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc
index 577bfc0..947bc28 100644
--- a/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc
+++ b/third_party/blink/renderer/bindings/core/v8/serialization/v8_script_value_serializer_test.cc
@@ -777,11 +777,11 @@
   // ImageData objects with color space information should serialize and
   // deserialize correctly.
   V8TestingScope scope;
-  ImageDataSettings* color_settings = ImageDataSettings::Create();
-  color_settings->setColorSpace("display-p3");
-  color_settings->setStorageFormat("float32");
-  ImageData* image_data =
-      ImageData::CreateImageData(2, 1, color_settings, ASSERT_NO_EXCEPTION);
+  ImageDataSettings* image_data_settings = ImageDataSettings::Create();
+  image_data_settings->setColorSpace("display-p3");
+  image_data_settings->setStorageFormat("float32");
+  ImageData* image_data = ImageData::CreateImageData(2, 1, image_data_settings,
+                                                     ASSERT_NO_EXCEPTION);
   static_cast<unsigned char*>(image_data->BufferBase()->Data())[0] = 200;
   v8::Local<v8::Value> wrapper =
       ToV8(image_data, scope.GetContext()->Global(), scope.GetIsolate());
@@ -790,9 +790,9 @@
   ImageData* new_image_data = V8ImageData::ToImpl(result.As<v8::Object>());
   EXPECT_NE(image_data, new_image_data);
   EXPECT_EQ(image_data->Size(), new_image_data->Size());
-  ImageDataSettings* new_color_settings = new_image_data->getSettings();
-  EXPECT_EQ("display-p3", new_color_settings->colorSpace());
-  EXPECT_EQ("float32", new_color_settings->storageFormat());
+  ImageDataSettings* new_image_data_settings = new_image_data->getSettings();
+  EXPECT_EQ("display-p3", new_image_data_settings->colorSpace());
+  EXPECT_EQ("float32", new_image_data_settings->storageFormat());
   EXPECT_EQ(image_data->BufferBase()->ByteLength(),
             new_image_data->BufferBase()->ByteLength());
   EXPECT_EQ(200, static_cast<unsigned char*>(
@@ -845,9 +845,9 @@
   ASSERT_TRUE(V8ImageData::HasInstance(result, scope.GetIsolate()));
   ImageData* new_image_data = V8ImageData::ToImpl(result.As<v8::Object>());
   EXPECT_EQ(IntSize(2, 1), new_image_data->Size());
-  ImageDataSettings* new_color_settings = new_image_data->getSettings();
-  EXPECT_EQ("display-p3", new_color_settings->colorSpace());
-  EXPECT_EQ("float32", new_color_settings->storageFormat());
+  ImageDataSettings* new_image_data_settings = new_image_data->getSettings();
+  EXPECT_EQ("display-p3", new_image_data_settings->colorSpace());
+  EXPECT_EQ("float32", new_image_data_settings->storageFormat());
   EXPECT_EQ(32u, new_image_data->BufferBase()->ByteLength());
   EXPECT_EQ(200, static_cast<unsigned char*>(
                      new_image_data->BufferBase()->Data())[0]);
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc
index cc8a42a..4693c0d 100644
--- a/third_party/blink/renderer/core/exported/web_view_test.cc
+++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -3745,8 +3745,7 @@
                       WebNavigationPolicy,
                       network::mojom::blink::WebSandboxFlags,
                       const SessionStorageNamespaceId&,
-                      bool& consumed_user_gesture,
-                      const base::Optional<WebImpression>&) override {
+                      bool& consumed_user_gesture) override {
     return web_view_helper_.InitializeWithOpener(opener);
   }
   void DidFocus() override { did_focus_called_ = true; }
@@ -3828,8 +3827,7 @@
                       WebNavigationPolicy,
                       network::mojom::blink::WebSandboxFlags,
                       const SessionStorageNamespaceId&,
-                      bool& consumed_user_gesture,
-                      const base::Optional<WebImpression>&) override {
+                      bool& consumed_user_gesture) override {
     return web_view_;
   }
 
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.cc b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
index 171d487..a7f8eeb7 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.cc
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.cc
@@ -872,8 +872,7 @@
                                        WebNavigationPolicy,
                                        network::mojom::blink::WebSandboxFlags,
                                        const SessionStorageNamespaceId&,
-                                       bool& consumed_user_gesture,
-                                       const base::Optional<WebImpression>&) {
+                                       bool& consumed_user_gesture) {
   auto webview_helper = std::make_unique<WebViewHelper>();
   WebView* result = webview_helper->InitializeWithOpener(opener);
   child_web_views_.push_back(std::move(webview_helper));
diff --git a/third_party/blink/renderer/core/frame/frame_test_helpers.h b/third_party/blink/renderer/core/frame/frame_test_helpers.h
index 5f28a822b..f38dcc8e 100644
--- a/third_party/blink/renderer/core/frame/frame_test_helpers.h
+++ b/third_party/blink/renderer/core/frame/frame_test_helpers.h
@@ -307,8 +307,7 @@
                       WebNavigationPolicy,
                       network::mojom::blink::WebSandboxFlags,
                       const SessionStorageNamespaceId&,
-                      bool& consumed_user_gesture,
-                      const base::Optional<WebImpression>&) override;
+                      bool& consumed_user_gesture) override;
 
  private:
   WTF::Vector<std::unique_ptr<WebViewHelper>> child_web_views_;
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h
index ef7391a..5c171f8 100644
--- a/third_party/blink/renderer/core/frame/local_frame_client.h
+++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -43,9 +43,9 @@
 #include "third_party/blink/public/common/feature_policy/document_policy_features.h"
 #include "third_party/blink/public/common/feature_policy/feature_policy.h"
 #include "third_party/blink/public/common/loader/loading_behavior_flag.h"
-#include "third_party/blink/public/common/navigation/triggering_event_info.h"
 #include "third_party/blink/public/common/tokens/tokens.h"
 #include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/frame/navigation_initiator.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/portal/portal.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/use_counter/css_property_id.mojom-blink-forward.h"
@@ -157,7 +157,7 @@
       NavigationPolicy,
       WebFrameLoadType,
       bool is_client_redirect,
-      TriggeringEventInfo,
+      mojom::blink::TriggeringEventInfo,
       HTMLFormElement*,
       network::mojom::CSPDisposition
           should_check_main_world_content_security_policy,
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
index 3cd9f679..df004b1f 100644
--- a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
+++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
@@ -616,7 +616,7 @@
     NavigationPolicy policy,
     WebFrameLoadType frame_load_type,
     bool is_client_redirect,
-    TriggeringEventInfo triggering_event_info,
+    mojom::blink::TriggeringEventInfo triggering_event_info,
     HTMLFormElement* form,
     network::mojom::CSPDisposition
         should_check_main_world_content_security_policy,
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.h b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
index e720a49..00780a6 100644
--- a/third_party/blink/renderer/core/frame/local_frame_client_impl.h
+++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
@@ -116,7 +116,7 @@
       NavigationPolicy,
       WebFrameLoadType,
       bool is_client_redirect,
-      TriggeringEventInfo,
+      mojom::blink::TriggeringEventInfo,
       HTMLFormElement*,
       network::mojom::CSPDisposition should_bypass_main_world_csp,
       mojo::PendingRemote<mojom::blink::BlobURLToken>,
diff --git a/third_party/blink/renderer/core/frame/web_frame_test.cc b/third_party/blink/renderer/core/frame/web_frame_test.cc
index 5570a0d..ae96337 100644
--- a/third_party/blink/renderer/core/frame/web_frame_test.cc
+++ b/third_party/blink/renderer/core/frame/web_frame_test.cc
@@ -7003,8 +7003,7 @@
                       WebNavigationPolicy,
                       network::mojom::blink::WebSandboxFlags,
                       const SessionStorageNamespaceId&,
-                      bool& consumed_user_gesture,
-                      const base::Optional<WebImpression>&) override {
+                      bool& consumed_user_gesture) override {
     EXPECT_TRUE(false);
     return nullptr;
   }
@@ -7059,7 +7058,8 @@
       MouseEvent::Create(nullptr, event_type_names::kClick, mouse_initializer);
   FrameLoadRequest frame_request(window, ResourceRequest(destination));
   frame_request.SetNavigationPolicy(NavigationPolicyFromEvent(event));
-  frame_request.SetTriggeringEventInfo(TriggeringEventInfo::kFromTrustedEvent);
+  frame_request.SetTriggeringEventInfo(
+      mojom::blink::TriggeringEventInfo::kFromTrustedEvent);
   LocalFrame::NotifyUserActivation(
       frame, mojom::UserActivationNotificationType::kTest);
   web_frame_client.IgnoreNavigations();
diff --git a/third_party/blink/renderer/core/html/canvas/image_data.cc b/third_party/blink/renderer/core/html/canvas/image_data.cc
index 2df387a..eb4eb12 100644
--- a/third_party/blink/renderer/core/html/canvas/image_data.cc
+++ b/third_party/blink/renderer/core/html/canvas/image_data.cc
@@ -58,7 +58,7 @@
     const unsigned& width,
     const unsigned& height,
     const NotShared<DOMArrayBufferView> data,
-    const ImageDataSettings* color_settings,
+    const ImageDataSettings* settings,
     ExceptionState* exception_state) {
   // We accept all the combinations of colorSpace and storageFormat in an
   // ImageDataSettings to be stored in an ImageData. Therefore, we don't
@@ -78,11 +78,9 @@
 
   if (param_flags & (kParamWidth | kParamHeight)) {
     base::CheckedNumeric<unsigned> data_size =
-        ImageData::StorageFormatBytesPerPixel(
-            kUint8ClampedArrayStorageFormatName);
-    if (color_settings) {
-      data_size = ImageData::StorageFormatBytesPerPixel(
-          color_settings->storageFormat());
+        StorageFormatBytesPerPixel(kUint8ClampedArrayStorageFormatName);
+    if (settings) {
+      data_size = StorageFormatBytesPerPixel(settings->storageFormat());
     }
     data_size *= width;
     data_size *= height;
@@ -203,107 +201,75 @@
   return data_array;
 }
 
-NotShared<DOMUint8ClampedArray> ImageData::AllocateAndValidateUint8ClampedArray(
-    const unsigned& length,
-    ExceptionState* exception_state) {
-  NotShared<DOMUint8ClampedArray> buffer_view;
-  buffer_view = AllocateAndValidateDataArray(
-      length, kUint8ClampedArrayStorageFormat, exception_state);
-  return buffer_view;
-}
-
-NotShared<DOMUint16Array> ImageData::AllocateAndValidateUint16Array(
-    const unsigned& length,
-    ExceptionState* exception_state) {
-  NotShared<DOMUint16Array> buffer_view;
-  buffer_view = AllocateAndValidateDataArray(length, kUint16ArrayStorageFormat,
-                                             exception_state);
-  return buffer_view;
-}
-
-NotShared<DOMFloat32Array> ImageData::AllocateAndValidateFloat32Array(
-    const unsigned& length,
-    ExceptionState* exception_state) {
-  NotShared<DOMFloat32Array> buffer_view;
-  buffer_view = AllocateAndValidateDataArray(length, kFloat32ArrayStorageFormat,
-                                             exception_state);
-  return buffer_view;
-}
-
 ImageData* ImageData::Create(const IntSize& size,
-                             const ImageDataSettings* color_settings) {
+                             const ImageDataSettings* settings) {
   if (!ValidateConstructorArguments(kParamSize, &size, 0, 0,
-                                    NotShared<DOMArrayBufferView>(),
-                                    color_settings))
+                                    NotShared<DOMArrayBufferView>(), settings))
     return nullptr;
   ImageDataStorageFormat storage_format = kUint8ClampedArrayStorageFormat;
-  if (color_settings) {
+  if (settings) {
     storage_format =
-        ImageData::GetImageDataStorageFormat(color_settings->storageFormat());
+        ImageData::GetImageDataStorageFormat(settings->storageFormat());
   }
   NotShared<DOMArrayBufferView> data_array =
       AllocateAndValidateDataArray(4 * static_cast<unsigned>(size.Width()) *
                                        static_cast<unsigned>(size.Height()),
                                    storage_format);
   return data_array
-             ? MakeGarbageCollected<ImageData>(size, data_array, color_settings)
+             ? MakeGarbageCollected<ImageData>(size, data_array, settings)
              : nullptr;
 }
 
 ImageData* ImageData::Create(const IntSize& size,
                              CanvasColorSpace color_space,
                              ImageDataStorageFormat storage_format) {
-  ImageDataSettings* color_settings = ImageDataSettings::Create();
+  ImageDataSettings* settings = ImageDataSettings::Create();
   switch (color_space) {
     case CanvasColorSpace::kSRGB:
-      color_settings->setColorSpace(kSRGBCanvasColorSpaceName);
+      settings->setColorSpace(kSRGBCanvasColorSpaceName);
       break;
     case CanvasColorSpace::kRec2020:
-      color_settings->setColorSpace(kRec2020CanvasColorSpaceName);
+      settings->setColorSpace(kRec2020CanvasColorSpaceName);
       break;
     case CanvasColorSpace::kP3:
-      color_settings->setColorSpace(kP3CanvasColorSpaceName);
+      settings->setColorSpace(kP3CanvasColorSpaceName);
       break;
   }
 
   switch (storage_format) {
     case kUint8ClampedArrayStorageFormat:
-      color_settings->setStorageFormat(kUint8ClampedArrayStorageFormatName);
+      settings->setStorageFormat(kUint8ClampedArrayStorageFormatName);
       break;
     case kUint16ArrayStorageFormat:
-      color_settings->setStorageFormat(kUint16ArrayStorageFormatName);
+      settings->setStorageFormat(kUint16ArrayStorageFormatName);
       break;
     case kFloat32ArrayStorageFormat:
-      color_settings->setStorageFormat(kFloat32ArrayStorageFormatName);
+      settings->setStorageFormat(kFloat32ArrayStorageFormatName);
       break;
   }
 
-  return ImageData::Create(size, color_settings);
+  return ImageData::Create(size, settings);
 }
 
 ImageData* ImageData::Create(const IntSize& size,
                              NotShared<DOMArrayBufferView> data_array,
-                             const ImageDataSettings* color_settings) {
-  if (!ImageData::ValidateConstructorArguments(
-          kParamSize | kParamData, &size, 0, 0, data_array, color_settings))
+                             const ImageDataSettings* settings) {
+  if (!ValidateConstructorArguments(kParamSize | kParamData, &size, 0, 0,
+                                    data_array, settings))
     return nullptr;
-  return MakeGarbageCollected<ImageData>(size, data_array, color_settings);
+  return MakeGarbageCollected<ImageData>(size, data_array, settings);
 }
 
 ImageData* ImageData::Create(unsigned width,
                              unsigned height,
                              ExceptionState& exception_state) {
-  if (!ImageData::ValidateConstructorArguments(
-          kParamWidth | kParamHeight, nullptr, width, height,
-          NotShared<DOMArrayBufferView>(), nullptr, &exception_state))
+  if (!ValidateConstructorArguments(kParamWidth | kParamHeight, nullptr, width,
+                                    height, NotShared<DOMArrayBufferView>(),
+                                    nullptr, &exception_state))
     return nullptr;
 
-  NotShared<DOMUint8ClampedArray> byte_array =
-      AllocateAndValidateUint8ClampedArray(
-          ImageData::StorageFormatBytesPerPixel(
-              kUint8ClampedArrayStorageFormat) *
-              width * height,
-          &exception_state);
+  NotShared<DOMArrayBufferView> byte_array = AllocateAndValidateDataArray(
+      4 * width * height, kUint8ClampedArrayStorageFormat, &exception_state);
   return byte_array ? MakeGarbageCollected<ImageData>(IntSize(width, height),
                                                       byte_array)
                     : nullptr;
@@ -312,9 +278,8 @@
 ImageData* ImageData::Create(NotShared<DOMUint8ClampedArray> data,
                              unsigned width,
                              ExceptionState& exception_state) {
-  if (!ImageData::ValidateConstructorArguments(kParamData | kParamWidth,
-                                               nullptr, width, 0, data, nullptr,
-                                               &exception_state))
+  if (!ValidateConstructorArguments(kParamData | kParamWidth, nullptr, width, 0,
+                                    data, nullptr, &exception_state))
     return nullptr;
 
   unsigned height = base::checked_cast<unsigned>(data->length()) / (width * 4);
@@ -325,88 +290,25 @@
                              unsigned width,
                              unsigned height,
                              ExceptionState& exception_state) {
-  if (!ImageData::ValidateConstructorArguments(
-          kParamData | kParamWidth | kParamHeight, nullptr, width, height, data,
-          nullptr, &exception_state))
+  if (!ValidateConstructorArguments(kParamData | kParamWidth | kParamHeight,
+                                    nullptr, width, height, data, nullptr,
+                                    &exception_state))
     return nullptr;
 
   return MakeGarbageCollected<ImageData>(IntSize(width, height), data);
 }
 
-ImageData* ImageData::Create(NotShared<DOMUint16Array> data,
-                             unsigned width,
-                             ExceptionState& exception_state) {
-  if (!ImageData::ValidateConstructorArguments(kParamData | kParamWidth,
-                                               nullptr, width, 0, data, nullptr,
-                                               &exception_state))
-    return nullptr;
-  unsigned height = base::checked_cast<unsigned>(data->length()) /
-                    (width * ImageData::StorageFormatBytesPerPixel(
-                                 kUint16ArrayStorageFormatName));
-  ImageDataSettings* image_setting = ImageDataSettings::Create();
-  image_setting->setStorageFormat(kUint16ArrayStorageFormatName);
-  return MakeGarbageCollected<ImageData>(IntSize(width, height), data,
-                                         image_setting);
-}
-
-ImageData* ImageData::Create(NotShared<DOMUint16Array> data,
-                             unsigned width,
-                             unsigned height,
-                             ExceptionState& exception_state) {
-  if (!ImageData::ValidateConstructorArguments(
-          kParamData | kParamWidth | kParamHeight, nullptr, width, height, data,
-          nullptr, &exception_state))
-    return nullptr;
-
-  ImageDataSettings* image_setting = ImageDataSettings::Create();
-  image_setting->setStorageFormat(kUint16ArrayStorageFormatName);
-  return MakeGarbageCollected<ImageData>(IntSize(width, height), data,
-                                         image_setting);
-}
-
-ImageData* ImageData::Create(NotShared<DOMFloat32Array> data,
-                             unsigned width,
-                             ExceptionState& exception_state) {
-  if (!ImageData::ValidateConstructorArguments(kParamData | kParamWidth,
-                                               nullptr, width, 0, data, nullptr,
-                                               &exception_state))
-    return nullptr;
-
-  unsigned height = base::checked_cast<unsigned>(data->length()) /
-                    (width * ImageData::StorageFormatBytesPerPixel(
-                                 kFloat32ArrayStorageFormatName));
-  ImageDataSettings* image_setting = ImageDataSettings::Create();
-  image_setting->setStorageFormat(kFloat32ArrayStorageFormatName);
-  return MakeGarbageCollected<ImageData>(IntSize(width, height), data,
-                                         image_setting);
-}
-
-ImageData* ImageData::Create(NotShared<DOMFloat32Array> data,
-                             unsigned width,
-                             unsigned height,
-                             ExceptionState& exception_state) {
-  if (!ImageData::ValidateConstructorArguments(
-          kParamData | kParamWidth | kParamHeight, nullptr, width, height, data,
-          nullptr, &exception_state))
-    return nullptr;
-
-  ImageDataSettings* image_setting = ImageDataSettings::Create();
-  image_setting->setStorageFormat(kFloat32ArrayStorageFormatName);
-  return MakeGarbageCollected<ImageData>(IntSize(width, height), data,
-                                         image_setting);
-}
-
 ImageData* ImageData::CreateImageData(unsigned width,
                                       unsigned height,
-                                      const ImageDataSettings* color_settings,
+                                      const ImageDataSettings* settings,
                                       ExceptionState& exception_state) {
-  if (!ImageData::ValidateConstructorArguments(
-          kParamWidth | kParamHeight, nullptr, width, height,
-          NotShared<DOMArrayBufferView>(), color_settings, &exception_state))
+  if (!ValidateConstructorArguments(kParamWidth | kParamHeight, nullptr, width,
+                                    height, NotShared<DOMArrayBufferView>(),
+                                    settings, &exception_state))
     return nullptr;
 
   ImageDataStorageFormat storage_format =
-      ImageData::GetImageDataStorageFormat(color_settings->storageFormat());
+      GetImageDataStorageFormat(settings->storageFormat());
   NotShared<DOMArrayBufferView> buffer_view = AllocateAndValidateDataArray(
       4 * width * height, storage_format, &exception_state);
 
@@ -414,13 +316,13 @@
     return nullptr;
 
   return MakeGarbageCollected<ImageData>(IntSize(width, height), buffer_view,
-                                         color_settings);
+                                         settings);
 }
 
 ImageData* ImageData::CreateImageData(ImageDataArray& data,
                                       unsigned width,
                                       unsigned height,
-                                      ImageDataSettings* color_settings,
+                                      ImageDataSettings* settings,
                                       ExceptionState& exception_state) {
   NotShared<DOMArrayBufferView> buffer_view;
 
@@ -442,23 +344,23 @@
     NOTREACHED();
   }
 
-  if (color_settings->storageFormat() != storage_format_name)
-    color_settings->setStorageFormat(storage_format_name);
+  if (settings->storageFormat() != storage_format_name)
+    settings->setStorageFormat(storage_format_name);
 
-  if (!ImageData::ValidateConstructorArguments(
-          kParamData | kParamWidth | kParamHeight, nullptr, width, height,
-          buffer_view, color_settings, &exception_state))
+  if (!ValidateConstructorArguments(kParamData | kParamWidth | kParamHeight,
+                                    nullptr, width, height, buffer_view,
+                                    settings, &exception_state))
     return nullptr;
 
   return MakeGarbageCollected<ImageData>(IntSize(width, height), buffer_view,
-                                         color_settings);
+                                         settings);
 }
 
 // This function accepts size (0, 0) and always returns the ImageData in
 // "srgb" color space and "uint8" storage format.
 ImageData* ImageData::CreateForTest(const IntSize& size) {
   base::CheckedNumeric<unsigned> data_size =
-      ImageData::StorageFormatBytesPerPixel(kUint8ClampedArrayStorageFormat);
+      StorageFormatBytesPerPixel(kUint8ClampedArrayStorageFormat);
   data_size *= size.Width();
   data_size *= size.Height();
   if (!data_size.IsValid() ||
@@ -477,8 +379,8 @@
 // to be validated on the call site.
 ImageData* ImageData::CreateForTest(const IntSize& size,
                                     NotShared<DOMArrayBufferView> buffer_view,
-                                    const ImageDataSettings* color_settings) {
-  return MakeGarbageCollected<ImageData>(size, buffer_view, color_settings);
+                                    const ImageDataSettings* settings) {
+  return MakeGarbageCollected<ImageData>(size, buffer_view, settings);
 }
 
 // Crops ImageData to the intersect of its size and the given rectangle. If the
@@ -497,8 +399,7 @@
 
   unsigned data_size = 4 * dst_rect.Width() * dst_rect.Height();
   NotShared<DOMArrayBufferView> buffer_view = AllocateAndValidateDataArray(
-      data_size,
-      ImageData::GetImageDataStorageFormat(color_settings_->storageFormat()));
+      data_size, GetImageDataStorageFormat(settings_->storageFormat()));
   if (!buffer_view)
     return nullptr;
 
@@ -507,7 +408,7 @@
                 data_size * buffer_view->TypeSize());
   } else {
     unsigned data_type_size =
-        ImageData::StorageFormatBytesPerPixel(color_settings_->storageFormat());
+        StorageFormatBytesPerPixel(settings_->storageFormat());
     int src_index = (dst_rect.X() + dst_rect.Y() * src_rect.Width()) * 4;
     int dst_index = 0;
     if (flip_y)
@@ -525,7 +426,7 @@
     }
   }
   return MakeGarbageCollected<ImageData>(dst_rect.Size(), buffer_view,
-                                         color_settings_);
+                                         settings_);
 }
 
 ScriptPromise ImageData::CreateImageBitmap(ScriptState* script_state,
@@ -597,7 +498,7 @@
 CanvasColorSpace ImageData::GetCanvasColorSpace() const {
   if (!RuntimeEnabledFeatures::CanvasColorManagementEnabled())
     return CanvasColorSpace::kSRGB;
-  return CanvasColorSpaceFromName(color_settings_->colorSpace());
+  return CanvasColorSpaceFromName(settings_->colorSpace());
 }
 
 ImageDataStorageFormat ImageData::GetImageDataStorageFormat() const {
@@ -658,7 +559,7 @@
 }
 
 void ImageData::Trace(Visitor* visitor) const {
-  visitor->Trace(color_settings_);
+  visitor->Trace(settings_);
   visitor->Trace(data_);
   visitor->Trace(data_u8_);
   visitor->Trace(data_u16_);
@@ -668,8 +569,8 @@
 
 ImageData::ImageData(const IntSize& size,
                      NotShared<DOMArrayBufferView> data,
-                     const ImageDataSettings* color_settings)
-    : size_(size), color_settings_(ImageDataSettings::Create()) {
+                     const ImageDataSettings* settings)
+    : size_(size), settings_(ImageDataSettings::Create()) {
   DCHECK_GE(size.Width(), 0);
   DCHECK_GE(size.Height(), 0);
   DCHECK(data);
@@ -678,19 +579,13 @@
   data_u16_.Clear();
   data_f32_.Clear();
 
-  if (color_settings) {
-    color_settings_->setColorSpace(color_settings->colorSpace());
-    color_settings_->setStorageFormat(color_settings->storageFormat());
+  if (settings) {
+    settings_->setColorSpace(settings->colorSpace());
+    settings_->setStorageFormat(settings->storageFormat());
   }
 
   ImageDataStorageFormat storage_format =
-      GetImageDataStorageFormat(color_settings_->storageFormat());
-
-  // TODO (zakerinasab): crbug.com/779570
-  // The default color space for ImageData with U16/F32 data should be
-  // extended-srgb color space. It is temporarily set to linear-rgb, which is
-  // not correct, but fixes crbug.com/779419.
-
+      GetImageDataStorageFormat(settings_->storageFormat());
   switch (storage_format) {
     case kUint8ClampedArrayStorageFormat:
       DCHECK(data->GetType() ==
diff --git a/third_party/blink/renderer/core/html/canvas/image_data.h b/third_party/blink/renderer/core/html/canvas/image_data.h
index 19a58cd..2148cc41 100644
--- a/third_party/blink/renderer/core/html/canvas/image_data.h
+++ b/third_party/blink/renderer/core/html/canvas/image_data.h
@@ -85,20 +85,6 @@
                            unsigned width,
                            unsigned height,
                            ExceptionState&);
-  static ImageData* Create(NotShared<DOMUint16Array>,
-                           unsigned width,
-                           ExceptionState&);
-  static ImageData* Create(NotShared<DOMUint16Array>,
-                           unsigned width,
-                           unsigned height,
-                           ExceptionState&);
-  static ImageData* Create(NotShared<DOMFloat32Array>,
-                           unsigned width,
-                           ExceptionState&);
-  static ImageData* Create(NotShared<DOMFloat32Array>,
-                           unsigned width,
-                           unsigned height,
-                           ExceptionState&);
 
   static ImageData* CreateImageData(unsigned width,
                                     unsigned height,
@@ -110,7 +96,7 @@
                                     ImageDataSettings*,
                                     ExceptionState&);
 
-  ImageDataSettings* getSettings() { return color_settings_; }
+  ImageDataSettings* getSettings() { return settings_; }
 
   static ImageData* CreateForTest(const IntSize&);
   static ImageData* CreateForTest(const IntSize&,
@@ -168,7 +154,7 @@
 
  private:
   IntSize size_;
-  Member<ImageDataSettings> color_settings_;
+  Member<ImageDataSettings> settings_;
   ImageDataArray data_;
   NotShared<DOMUint8ClampedArray> data_u8_;
   NotShared<DOMUint16Array> data_u16_;
@@ -178,18 +164,6 @@
       const unsigned&,
       ImageDataStorageFormat,
       ExceptionState* = nullptr);
-
-  static NotShared<DOMUint8ClampedArray> AllocateAndValidateUint8ClampedArray(
-      const unsigned&,
-      ExceptionState* = nullptr);
-
-  static NotShared<DOMUint16Array> AllocateAndValidateUint16Array(
-      const unsigned&,
-      ExceptionState* = nullptr);
-
-  static NotShared<DOMFloat32Array> AllocateAndValidateFloat32Array(
-      const unsigned&,
-      ExceptionState* = nullptr);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/html/canvas/image_data_test.cc b/third_party/blink/renderer/core/html/canvas/image_data_test.cc
index aa04c9abe..0b90941 100644
--- a/third_party/blink/renderer/core/html/canvas/image_data_test.cc
+++ b/third_party/blink/renderer/core/html/canvas/image_data_test.cc
@@ -101,10 +101,10 @@
     else
       data_array = data_f32;
 
-    ImageDataSettings* color_settings = ImageDataSettings::Create();
-    color_settings->setStorageFormat(image_data_storage_format_names[i]);
+    ImageDataSettings* image_data_settings = ImageDataSettings::Create();
+    image_data_settings->setStorageFormat(image_data_storage_format_names[i]);
     image_data = ImageData::CreateForTest(IntSize(width, height), data_array,
-                                          color_settings);
+                                          image_data_settings);
     for (int j = 0; j < num_test_cases; j++) {
       // Test the size of the cropped image data
       IntRect src_rect(IntPoint(), image_data->Size());
diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third_party/blink/renderer/core/html/html_anchor_element.cc
index 44ab2ac..15265fa5 100644
--- a/third_party/blink/renderer/core/html/html_anchor_element.cc
+++ b/third_party/blink/renderer/core/html/html_anchor_element.cc
@@ -554,25 +554,13 @@
   }
 
   frame_request.SetTriggeringEventInfo(
-      event.isTrusted() ? TriggeringEventInfo::kFromTrustedEvent
-                        : TriggeringEventInfo::kFromUntrustedEvent);
+      event.isTrusted()
+          ? mojom::blink::TriggeringEventInfo::kFromTrustedEvent
+          : mojom::blink::TriggeringEventInfo::kFromUntrustedEvent);
   frame_request.SetInputStartTime(event.PlatformTimeStamp());
 
   frame->MaybeLogAdClickNavigation();
 
-  if (request.HasUserGesture() && HasImpression()) {
-    // An impression must be attached prior to the
-    // FindOrCreateFrameForNavigation() call, as that call may result in
-    // performing a navigation if the call results in creating a new window with
-    // noopener set.
-    base::Optional<WebImpression> impression = GetImpressionForNavigation();
-    if (impression)
-      frame_request.SetImpression(*impression);
-  }
-
-  // Note that we do not need to worry about impressions being attached to
-  // subframe navigations in the following call, a frame is only
-  // created/navigated if we are intending to navigate a new window/main frame.
   Frame* target_frame =
       frame->Tree().FindOrCreateFrameForNavigation(frame_request, target).frame;
 
@@ -587,15 +575,16 @@
                       WebFeature::kHTMLAnchorElementHrefTranslateAttribute);
   }
 
-  if (target_frame) {
-    // We do not need to attach impressions for navigations to subframes, as the
-    // Conversion Measurement API only applies to main frame navigations. Clear
-    // out the impression in that case.
-    if (!target_frame->IsMainFrame()) {
-      frame_request.SetImpression(base::nullopt);
-    }
-    target_frame->Navigate(frame_request, WebFrameLoadType::kStandard);
+  // Only attach impressions for main frame navigations.
+  if (target_frame && target_frame->IsMainFrame() && request.HasUserGesture() &&
+      HasImpression()) {
+    base::Optional<WebImpression> impression = GetImpressionForNavigation();
+    if (impression)
+      frame_request.SetImpression(*impression);
   }
+
+  if (target_frame)
+    target_frame->Navigate(frame_request, WebFrameLoadType::kStandard);
 }
 
 bool IsEnterKeyKeydownEvent(Event& event) {
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index d17fb25..c68d6bb 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -3447,10 +3447,11 @@
 
 LayoutObject* LayoutObject::Container(AncestorSkipInfo* skip_info) const {
   NOT_DESTROYED();
-  // TODO(mstensho): Get rid of this. Nobody should call this method with those
-  // flags already set.
+
+#if DCHECK_IS_ON()
   if (skip_info)
-    skip_info->ResetOutput();
+    skip_info->AssertClean();
+#endif
 
   if (IsTextOrSVGChild())
     return Parent();
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index f8dac76..7903e2d 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -1810,12 +1810,12 @@
         filter_skipped_ = true;
     }
 
-    // TODO(mstensho): Get rid of this. It's just a temporary thing to retain
-    // old behavior in LayoutObject::container().
-    void ResetOutput() {
-      ancestor_skipped_ = false;
-      filter_skipped_ = false;
+#if DCHECK_IS_ON()
+    void AssertClean() {
+      DCHECK(!ancestor_skipped_);
+      DCHECK(!filter_skipped_);
     }
+#endif
 
     bool AncestorSkipped() const { return ancestor_skipped_; }
     bool FilterSkipped() const {
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 399cd82..3f295bb 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
@@ -41,11 +41,23 @@
   CacheItemSetIndices(algorithm_column_track_collection, &grid_items);
   CacheItemSetIndices(algorithm_row_track_collection, &grid_items);
 
-  // Resolve inline size.
-  ComputeUsedTrackSizes(&algorithm_column_track_collection, &grid_items);
+  // Create a vector of grid item indices using |NGGridChildIterator| order.
+  Vector<wtf_size_t> reordered_item_indices(grid_items.size());
+  for (wtf_size_t i = 0; i < grid_items.size(); ++i)
+    reordered_item_indices[i] = i;
 
+  // Cache track span properties for grid items.
+  CacheGridItemsTrackSpanProperties(algorithm_column_track_collection,
+                                    &grid_items, &reordered_item_indices);
+  CacheGridItemsTrackSpanProperties(algorithm_row_track_collection, &grid_items,
+                                    &reordered_item_indices);
+
+  // Resolve inline size.
+  ComputeUsedTrackSizes(&algorithm_column_track_collection, &grid_items,
+                        &reordered_item_indices);
   // Resolve block size.
-  ComputeUsedTrackSizes(&algorithm_row_track_collection, &grid_items);
+  ComputeUsedTrackSizes(&algorithm_row_track_collection, &grid_items,
+                        &reordered_item_indices);
 
   // Place items.
   LayoutUnit intrinsic_block_size;
@@ -85,8 +97,18 @@
   // Cache set indices.
   CacheItemSetIndices(algorithm_column_track_collection, &grid_items);
 
+  // Create a vector of grid item indices using |NGGridChildIterator| order.
+  Vector<wtf_size_t> reordered_item_indices(grid_items.size());
+  for (wtf_size_t i = 0; i < grid_items.size(); ++i)
+    reordered_item_indices[i] = i;
+
+  // Cache track span properties for grid items.
+  CacheGridItemsTrackSpanProperties(algorithm_column_track_collection,
+                                    &grid_items, &reordered_item_indices);
+
   // Resolve inline size.
-  ComputeUsedTrackSizes(&algorithm_column_track_collection, &grid_items);
+  ComputeUsedTrackSizes(&algorithm_column_track_collection, &grid_items,
+                        &reordered_item_indices);
 
   const LayoutUnit grid_gap = GridGap(kForColumns);
 
@@ -124,9 +146,6 @@
   return {grid_min_max_sizes, /* depends_on_percentage_block_size */ true};
 }
 
-NGGridLayoutAlgorithm::GridItemData::GridItemData(const NGBlockNode node)
-    : node(node) {}
-
 NGGridLayoutAlgorithm::AutoPlacementType
 NGGridLayoutAlgorithm::GridItemData::AutoPlacement(
     GridTrackSizingDirection flow_direction) const {
@@ -145,6 +164,21 @@
   return AutoPlacementType::kNotNeeded;
 }
 
+const GridSpan& NGGridLayoutAlgorithm::GridItemData::Span(
+    GridTrackSizingDirection track_direction) const {
+  return (track_direction == kForColumns) ? resolved_position.columns
+                                          : resolved_position.rows;
+}
+
+void NGGridLayoutAlgorithm::GridItemData::SetSpan(
+    const GridSpan& span,
+    GridTrackSizingDirection track_direction) {
+  if (track_direction == kForColumns)
+    resolved_position.columns = span;
+  else
+    resolved_position.rows = span;
+}
+
 wtf_size_t NGGridLayoutAlgorithm::GridItemData::StartLine(
     GridTrackSizingDirection track_direction) const {
   const GridSpan& span = (track_direction == kForColumns)
@@ -172,19 +206,32 @@
   return span.IntegerSpan();
 }
 
-const GridSpan& NGGridLayoutAlgorithm::GridItemData::Span(
+const TrackSpanProperties&
+NGGridLayoutAlgorithm::GridItemData::GetTrackSpanProperties(
     GridTrackSizingDirection track_direction) const {
-  return (track_direction == kForColumns) ? resolved_position.columns
-                                          : resolved_position.rows;
+  return track_direction == kForColumns ? column_span_properties
+                                        : row_span_properties;
 }
 
-void NGGridLayoutAlgorithm::GridItemData::SetSpan(
-    const GridSpan& span,
+void NGGridLayoutAlgorithm::GridItemData::SetTrackSpanProperty(
+    TrackSpanProperties::PropertyId property,
     GridTrackSizingDirection track_direction) {
   if (track_direction == kForColumns)
-    resolved_position.columns = span;
+    column_span_properties.SetProperty(property);
   else
-    resolved_position.rows = span;
+    row_span_properties.SetProperty(property);
+}
+
+bool NGGridLayoutAlgorithm::GridItemData::IsSpanningFlexibleTrack(
+    GridTrackSizingDirection track_direction) const {
+  return GetTrackSpanProperties(track_direction)
+      .HasProperty(TrackSpanProperties::kHasFlexibleTrack);
+}
+
+bool NGGridLayoutAlgorithm::GridItemData::IsSpanningIntrinsicTrack(
+    GridTrackSizingDirection track_direction) const {
+  return GetTrackSpanProperties(track_direction)
+      .HasProperty(TrackSpanProperties::kHasIntrinsicTrack);
 }
 
 NGGridLayoutAlgorithm::ReorderedGridItems::Iterator::Iterator(
@@ -390,7 +437,7 @@
   GridItemData grid_item(node);
   const ComputedStyle& child_style = node.Style();
   bool is_orthogonal_flow_root = !IsParallelWritingMode(
-      ConstraintSpace().GetWritingMode(), child_style.GetWritingMode());
+      container_style.GetWritingMode(), child_style.GetWritingMode());
   NGConstraintSpace constraint_space = BuildSpaceForGridItem(node);
 
   // Children with orthogonal writing modes require a full layout pass to
@@ -429,7 +476,7 @@
       ComputeMarginsFor(constraint_space, child_style, ConstraintSpace());
   grid_item.min_max_sizes =
       node.ComputeMinMaxSizes(
-              ConstraintSpace().GetWritingMode(),
+              container_style.GetWritingMode(),
               MinMaxSizesInput(child_percentage_size_.block_size,
                                MinMaxSizesType::kContent),
               &constraint_space)
@@ -610,7 +657,7 @@
   }
 }
 
-void NGGridLayoutAlgorithm::DetermineGridItemsSpanningIntrinsicOrFlexTracks(
+void NGGridLayoutAlgorithm::CacheGridItemsTrackSpanProperties(
     const NGGridLayoutAlgorithmTrackCollection& track_collection,
     Vector<GridItemData>* grid_items,
     Vector<wtf_size_t>* reordered_item_indices) const {
@@ -626,61 +673,63 @@
   std::sort(reordered_item_indices->begin(), reordered_item_indices->end(),
             CompareGridItemsByStartLine);
 
-  // At this point we have the grid items sorted by their start line in the
-  // respective direction; this is important since we'll process both, the
-  // ranges in the track collection and the grid items, incrementally.
-  auto range_spanning_flex_track_iterator = track_collection.RangeIterator();
-  auto range_spanning_intrinsic_track_iterator =
-      track_collection.RangeIterator();
+  auto CacheTrackSpanPropertyForAllGridItems =
+      [&](TrackSpanProperties::PropertyId property) {
+        // At this point we have the grid items sorted by their start line in
+        // the respective direction; this is important since we'll process both,
+        // the ranges in the track collection and the grid items, incrementally.
+        auto range_iterator = track_collection.RangeIterator();
 
-  for (GridItemData& grid_item :
-       ReorderedGridItems(*reordered_item_indices, *grid_items)) {
-    // We want to find the first range in the collection that:
-    //   - Spans tracks located AFTER the start line of the current grid item;
-    //   this can be done by checking that the last track number of the current
-    //   range is NOT less than the current grid item's start line. Furthermore,
-    //   since grid items are sorted by start line, if at any point a range is
-    //   located BEFORE the current grid item's start line, the same range will
-    //   also be located BEFORE any subsequent item's start line.
-    //   - Contains a track with an intrinsic/flexible sizing function.
-    while (!range_spanning_intrinsic_track_iterator.IsAtEnd() &&
-           (range_spanning_intrinsic_track_iterator.RangeTrackEnd() <
-                grid_item.StartLine(track_direction) ||
-            !track_collection.IsRangeSpanningIntrinsicTrack(
-                range_spanning_intrinsic_track_iterator.RangeIndex()))) {
-      range_spanning_intrinsic_track_iterator.MoveToNextRange();
-    }
-    while (!range_spanning_flex_track_iterator.IsAtEnd() &&
-           (range_spanning_flex_track_iterator.RangeTrackEnd() <
-                grid_item.StartLine(track_direction) ||
-            !track_collection.IsRangeSpanningFlexTrack(
-                range_spanning_flex_track_iterator.RangeIndex()))) {
-      range_spanning_flex_track_iterator.MoveToNextRange();
-    }
+        for (GridItemData& grid_item :
+             ReorderedGridItems(*reordered_item_indices, *grid_items)) {
+          // We want to find the first range in the collection that:
+          //   - Spans tracks located AFTER the start line of the current grid
+          //   item; this can be done by checking that the last track number of
+          //   the current range is NOT less than the current grid item's start
+          //   line. Furthermore, since grid items are sorted by start line, if
+          //   at any point a range is located BEFORE the current grid item's
+          //   start line, the same range will also be located BEFORE any
+          //   subsequent item's start line.
+          //   - Contains a track that fulfills the specified property.
+          while (!range_iterator.IsAtEnd() &&
+                 (range_iterator.RangeTrackEnd() <
+                      grid_item.StartLine(track_direction) ||
+                  !track_collection.RangeHasTrackSpanProperty(
+                      range_iterator.RangeIndex(), property))) {
+            range_iterator.MoveToNextRange();
+          }
 
-    // Notice that, from the way we build the ranges of a track collection (see
-    // |NGGridBlockTrackCollection::EnsureTrackCoverage|), any given range must
-    // either be completely contained or excluded from a grid item's span. Thus,
-    // if the current range's last track is also located BEFORE the item's end
-    // line, then this range, including the intrinsic/flexible track it spans,
-    // is completely contained within this grid item's boundaries.
-    // Otherwise, this and any subsequent range are excluded from this item's
-    // span, meaning that it does not span an intrinsic/flexible track.
-    grid_item.is_spanning_intrinsic_track =
-        !range_spanning_intrinsic_track_iterator.IsAtEnd() &&
-        range_spanning_intrinsic_track_iterator.RangeTrackEnd() <
-            grid_item.EndLine(track_direction);
-    grid_item.is_spanning_flex_track =
-        !range_spanning_flex_track_iterator.IsAtEnd() &&
-        range_spanning_flex_track_iterator.RangeTrackEnd() <
-            grid_item.EndLine(track_direction);
-  }
+          // Since we discarded every range in the track collection, any
+          // following grid item cannot fulfill the property.
+          if (range_iterator.IsAtEnd())
+            break;
+
+          // Notice that, from the way we build the ranges of a track collection
+          // (see |NGGridBlockTrackCollection::EnsureTrackCoverage|), any given
+          // range must either be completely contained or excluded from a grid
+          // item's span. Thus, if the current range's last track is also
+          // located BEFORE the item's end line, then this range, including a
+          // track that fulfills the specified property, is completely contained
+          // within this item's boundaries. Otherwise, this and every subsequent
+          // range are excluded from the grid item's span, meaning that such
+          // item cannot satisfy the property we are looking for.
+          if (range_iterator.RangeTrackEnd() <
+              grid_item.EndLine(track_direction)) {
+            grid_item.SetTrackSpanProperty(property, track_direction);
+          }
+        }
+      };
+
+  CacheTrackSpanPropertyForAllGridItems(TrackSpanProperties::kHasFlexibleTrack);
+  CacheTrackSpanPropertyForAllGridItems(
+      TrackSpanProperties::kHasIntrinsicTrack);
 }
 
 // https://drafts.csswg.org/css-grid-1/#algo-track-sizing
 void NGGridLayoutAlgorithm::ComputeUsedTrackSizes(
     NGGridLayoutAlgorithmTrackCollection* track_collection,
-    Vector<GridItemData>* grid_items) const {
+    Vector<GridItemData>* grid_items,
+    Vector<wtf_size_t>* reordered_item_indices) const {
   DCHECK(track_collection && grid_items);
   LayoutUnit content_box_size = track_collection->IsForColumns()
                                     ? child_percentage_size_.inline_size
@@ -726,15 +775,8 @@
   }
 
   // 2. Resolve intrinsic track sizing functions to absolute lengths.
-  // Fill grid item indices vector in document order.
-  Vector<wtf_size_t> reordered_item_indices;
-  reordered_item_indices.ReserveInitialCapacity(grid_items->size());
-  for (wtf_size_t i = 0; i < grid_items->size(); ++i)
-    reordered_item_indices.push_back(i);
-  DetermineGridItemsSpanningIntrinsicOrFlexTracks(*track_collection, grid_items,
-                                                  &reordered_item_indices);
   ResolveIntrinsicTrackSizes(track_collection, grid_items,
-                             &reordered_item_indices);
+                             reordered_item_indices);
 }
 
 // Helpers for the track sizing algorithm.
@@ -1055,14 +1097,9 @@
   NGGridSetVector sets_to_grow;
   NGGridSetVector sets_to_grow_beyond_limit;
   for (auto grid_item = group_begin; grid_item != group_end; ++grid_item) {
-    // TODO(ethavar): Remove the |IsOutOfFlowPositioned| condition once the
-    // out-of-flow items are stored separately.
-    if (!grid_item->is_spanning_intrinsic_track ||
-        grid_item->node.IsOutOfFlowPositioned()) {
-      // Don't consider items not spanning intrinsic tracks in this step;
-      // absolute positioned items don't affect track sizing.
+    // We can skip this item if it doesn't span intrinsic tracks.
+    if (!grid_item->IsSpanningIntrinsicTrack(track_direction))
       continue;
-    }
 
     sets_to_grow.Shrink(0);
     sets_to_grow_beyond_limit.Shrink(0);
@@ -1128,11 +1165,11 @@
   auto CompareGridItemsForIntrinsicTrackResolution =
       [grid_items, track_direction](wtf_size_t index_a,
                                     wtf_size_t index_b) -> bool {
-    if (grid_items->at(index_a).is_spanning_flex_track ||
-        grid_items->at(index_b).is_spanning_flex_track) {
+    if (grid_items->at(index_a).IsSpanningFlexibleTrack(track_direction) ||
+        grid_items->at(index_b).IsSpanningFlexibleTrack(track_direction)) {
       // Ignore span sizes if one of the items spans a track with a flexible
       // sizing function; items not spanning such tracks should come first.
-      return !grid_items->at(index_a).is_spanning_flex_track;
+      return !grid_items->at(index_a).IsSpanningFlexibleTrack(track_direction);
     }
     return grid_items->at(index_a).SpanSize(track_direction) <
            grid_items->at(index_b).SpanSize(track_direction);
@@ -1146,16 +1183,16 @@
   ReorderedGridItems::Iterator current_group_begin = reordered_items.begin();
 
   while (current_group_begin != reordered_items.end() &&
-         !current_group_begin->is_spanning_flex_track) {
+         !current_group_begin->IsSpanningFlexibleTrack(track_direction)) {
     // Each iteration considers all items with the same span size.
     wtf_size_t current_group_span_size =
         current_group_begin->SpanSize(track_direction);
     ReorderedGridItems::Iterator current_group_end = current_group_begin;
     do {
-      DCHECK(!current_group_end->is_spanning_flex_track);
+      DCHECK(!current_group_end->IsSpanningFlexibleTrack(track_direction));
       ++current_group_end;
     } while (current_group_end != reordered_items.end() &&
-             !current_group_end->is_spanning_flex_track &&
+             !current_group_end->IsSpanningFlexibleTrack(track_direction) &&
              current_group_end->SpanSize(track_direction) ==
                  current_group_span_size);
 
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 95473be..299d30f 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
@@ -34,7 +34,7 @@
   };
 
   struct GridItemData {
-    explicit GridItemData(const NGBlockNode node);
+    explicit GridItemData(const NGBlockNode node) : node(node) {}
 
     AutoPlacementType AutoPlacement(
         GridTrackSizingDirection flow_direction) const;
@@ -46,6 +46,16 @@
     wtf_size_t EndLine(GridTrackSizingDirection track_direction) const;
     wtf_size_t SpanSize(GridTrackSizingDirection track_direction) const;
 
+    const TrackSpanProperties& GetTrackSpanProperties(
+        GridTrackSizingDirection track_direction) const;
+    void SetTrackSpanProperty(TrackSpanProperties::PropertyId property,
+                              GridTrackSizingDirection track_direction);
+
+    bool IsSpanningFlexibleTrack(
+        GridTrackSizingDirection track_direction) const;
+    bool IsSpanningIntrinsicTrack(
+        GridTrackSizingDirection track_direction) const;
+
     const NGBlockNode node;
     GridArea resolved_position;
 
@@ -66,8 +76,8 @@
     bool is_inline_axis_stretched;
     bool is_block_axis_stretched;
 
-    bool is_spanning_flex_track : 1;
-    bool is_spanning_intrinsic_track : 1;
+    TrackSpanProperties column_span_properties;
+    TrackSpanProperties row_span_properties;
   };
 
   explicit NGGridLayoutAlgorithm(const NGLayoutAlgorithmParams& params);
@@ -164,9 +174,9 @@
   void CacheItemSetIndices(
       const NGGridLayoutAlgorithmTrackCollection& track_collection,
       Vector<GridItemData>* grid_items) const;
-  // For every grid item, determines if it spans a track with an intrinsic or
-  // flexible sizing function and caches the answer in its |GridItemData|.
-  void DetermineGridItemsSpanningIntrinsicOrFlexTracks(
+  // For every grid item, caches properties of the track sizing functions it
+  // spans (i.e. whether an item spans intrinsic or flexible tracks).
+  void CacheGridItemsTrackSpanProperties(
       const NGGridLayoutAlgorithmTrackCollection& track_collection,
       Vector<GridItemData>* grid_items,
       Vector<wtf_size_t>* reordered_item_indices) const;
@@ -174,7 +184,8 @@
   // Calculates from the min and max track sizing functions the used track size.
   void ComputeUsedTrackSizes(
       NGGridLayoutAlgorithmTrackCollection* track_collection,
-      Vector<GridItemData>* grid_items) const;
+      Vector<GridItemData>* grid_items,
+      Vector<wtf_size_t>* reordered_item_indices) const;
 
   // These methods implement the steps of the algorithm for intrinsic track size
   // resolution defined in https://drafts.csswg.org/css-grid-1/#algo-content.
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc
index f91ddf4..f5a401f 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc
@@ -55,13 +55,24 @@
     algorithm.CacheItemSetIndices(algorithm_row_track_collection_,
                                   &grid_items_);
 
+    // Create a vector of grid item indices using |NGGridChildIterator| order.
+    Vector<wtf_size_t> reordered_item_indices(grid_items_.size());
+    for (wtf_size_t i = 0; i < grid_items_.size(); ++i)
+      reordered_item_indices[i] = i;
+
+    // Cache track span properties for grid items.
+    algorithm.CacheGridItemsTrackSpanProperties(
+        algorithm_column_track_collection_, &grid_items_,
+        &reordered_item_indices);
+    algorithm.CacheGridItemsTrackSpanProperties(
+        algorithm_row_track_collection_, &grid_items_, &reordered_item_indices);
+
     // Resolve inline size.
     algorithm.ComputeUsedTrackSizes(&algorithm_column_track_collection_,
-                                    &grid_items_);
-
+                                    &grid_items_, &reordered_item_indices);
     // Resolve block size.
     algorithm.ComputeUsedTrackSizes(&algorithm_row_track_collection_,
-                                    &grid_items_);
+                                    &grid_items_, &reordered_item_indices);
   }
 
   NGGridLayoutAlgorithmTrackCollection& TrackCollection(
@@ -111,32 +122,23 @@
     return results;
   }
 
-  void DetermineGridItemsSpanningIntrinsicOrFlexTracks(
+  Vector<wtf_size_t> GridItemsWithColumnSpanProperty(
       const NGGridLayoutAlgorithm& algorithm,
-      const NGGridLayoutAlgorithmTrackCollection& track_collection) {
-    Vector<wtf_size_t> reordered_item_indices;
-    reordered_item_indices.ReserveInitialCapacity(grid_items_.size());
-    for (wtf_size_t i = 0; i < grid_items_.size(); ++i)
-      reordered_item_indices.push_back(i);
-    algorithm.DetermineGridItemsSpanningIntrinsicOrFlexTracks(
-        track_collection, &grid_items_, &reordered_item_indices);
-  }
-
-  Vector<wtf_size_t> GridItemsSpanningIntrinsicTrack(
-      const NGGridLayoutAlgorithm& algorithm) {
+      TrackSpanProperties::PropertyId property) {
     Vector<wtf_size_t> results;
     for (wtf_size_t i = 0; i < grid_items_.size(); ++i) {
-      if (grid_items_[i].is_spanning_intrinsic_track)
+      if (grid_items_[i].column_span_properties.HasProperty(property))
         results.push_back(i);
     }
     return results;
   }
 
-  Vector<wtf_size_t> GridItemsSpanningFlexTrack(
-      const NGGridLayoutAlgorithm& algorithm) {
+  Vector<wtf_size_t> GridItemsWithRowSpanProperty(
+      const NGGridLayoutAlgorithm& algorithm,
+      TrackSpanProperties::PropertyId property) {
     Vector<wtf_size_t> results;
     for (wtf_size_t i = 0; i < grid_items_.size(); ++i) {
-      if (grid_items_[i].is_spanning_flex_track)
+      if (grid_items_[i].row_span_properties.HasProperty(property))
         results.push_back(i);
     }
     return results;
@@ -1191,35 +1193,37 @@
   NGGridLayoutAlgorithm algorithm({node, fragment_geometry, space});
   BuildGridItemsAndTrackCollections(algorithm);
 
-  DetermineGridItemsSpanningIntrinsicOrFlexTracks(algorithm,
-                                                  TrackCollection(kForColumns));
+  // Test grid items spanning intrinsic/flexible columns.
   Vector<wtf_size_t> expected_grid_items_spanning_intrinsic_track = {0, 1, 3};
   Vector<wtf_size_t> expected_grid_items_spanning_flex_track = {1};
 
-  Vector<wtf_size_t> actual_items = GridItemsSpanningIntrinsicTrack(algorithm);
+  Vector<wtf_size_t> actual_items = GridItemsWithColumnSpanProperty(
+      algorithm, TrackSpanProperties::kHasIntrinsicTrack);
   EXPECT_EQ(expected_grid_items_spanning_intrinsic_track.size(),
             actual_items.size());
   for (wtf_size_t i = 0; i < actual_items.size(); ++i)
     EXPECT_EQ(expected_grid_items_spanning_intrinsic_track[i], actual_items[i]);
 
-  actual_items = GridItemsSpanningFlexTrack(algorithm);
+  actual_items = GridItemsWithColumnSpanProperty(
+      algorithm, TrackSpanProperties::kHasFlexibleTrack);
   EXPECT_EQ(expected_grid_items_spanning_flex_track.size(),
             actual_items.size());
   for (wtf_size_t i = 0; i < actual_items.size(); ++i)
     EXPECT_EQ(expected_grid_items_spanning_flex_track[i], actual_items[i]);
 
-  DetermineGridItemsSpanningIntrinsicOrFlexTracks(algorithm,
-                                                  TrackCollection(kForRows));
+  // Test grid items spanning intrinsic/flexible rows.
   expected_grid_items_spanning_intrinsic_track = {1, 2, 3};
   expected_grid_items_spanning_flex_track = {2};
 
-  actual_items = GridItemsSpanningIntrinsicTrack(algorithm);
+  actual_items = GridItemsWithRowSpanProperty(
+      algorithm, TrackSpanProperties::kHasIntrinsicTrack);
   EXPECT_EQ(expected_grid_items_spanning_intrinsic_track.size(),
             actual_items.size());
   for (wtf_size_t i = 0; i < actual_items.size(); ++i)
     EXPECT_EQ(expected_grid_items_spanning_intrinsic_track[i], actual_items[i]);
 
-  actual_items = GridItemsSpanningFlexTrack(algorithm);
+  actual_items = GridItemsWithRowSpanProperty(
+      algorithm, TrackSpanProperties::kHasFlexibleTrack);
   EXPECT_EQ(expected_grid_items_spanning_flex_track.size(),
             actual_items.size());
   for (wtf_size_t i = 0; i < actual_items.size(); ++i)
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc
index fbe4536..92c56e4 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.cc
@@ -136,6 +136,22 @@
   return true;
 }
 
+bool NGGridBlockTrackCollection::Range::IsImplicit() const {
+  return properties.HasProperty(TrackSpanProperties::kIsImplicit);
+}
+
+bool NGGridBlockTrackCollection::Range::IsCollapsed() const {
+  return properties.HasProperty(TrackSpanProperties::kIsCollapsed);
+}
+
+void NGGridBlockTrackCollection::Range::SetIsImplicit() {
+  properties.SetProperty(TrackSpanProperties::kIsImplicit);
+}
+
+void NGGridBlockTrackCollection::Range::SetIsCollapsed() {
+  properties.SetProperty(TrackSpanProperties::kIsCollapsed);
+}
+
 NGGridBlockTrackCollection::NGGridBlockTrackCollection(
     GridTrackSizingDirection direction)
     : direction_(direction) {}
@@ -259,7 +275,7 @@
 
     // Compute repeater index and offset.
     if (repeater_index == kInvalidRangeIndex) {
-      range.is_implicit_range = true;
+      range.SetIsImplicit();
       if (implicit_tracks_->RepeaterCount() == 0) {
         // No specified implicit tracks, use auto tracks.
         range.repeater_index = kInvalidRangeIndex;
@@ -271,11 +287,12 @@
             current_range_track_start - repeater_track_start;
       }
     } else {
-      range.is_implicit_range = false;
       range.repeater_index = repeater_index;
       range.repeater_offset = current_range_track_start - repeater_track_start;
     }
-    range.is_collapsed = is_in_auto_fit_range && open_items_or_repeaters == 1u;
+
+    if (is_in_auto_fit_range && open_items_or_repeaters == 1u)
+      range.SetIsCollapsed();
 
     current_range_track_start += range.track_count;
     ranges_.push_back(range);
@@ -296,15 +313,13 @@
   ending_tracks_.clear();
 }
 
-const NGGridBlockTrackCollection::Range&
-NGGridBlockTrackCollection::RangeAtRangeIndex(wtf_size_t range_index) const {
+bool NGGridBlockTrackCollection::IsRangeImplicit(wtf_size_t range_index) const {
   DCHECK_LT(range_index, ranges_.size());
-  return ranges_[range_index];
+  return ranges_[range_index].IsImplicit();
 }
 
 const NGGridBlockTrackCollection::Range&
-NGGridBlockTrackCollection::RangeAtTrackNumber(wtf_size_t track_number) const {
-  wtf_size_t range_index = RangeIndexFromTrackNumber(track_number);
+NGGridBlockTrackCollection::RangeAtRangeIndex(wtf_size_t range_index) const {
   DCHECK_LT(range_index, ranges_.size());
   return ranges_[range_index];
 }
@@ -372,7 +387,7 @@
 bool NGGridBlockTrackCollection::IsRangeCollapsed(
     wtf_size_t range_index) const {
   DCHECK_LT(range_index, RangeCount());
-  return ranges_[range_index].is_collapsed;
+  return ranges_[range_index].IsCollapsed();
 }
 
 wtf_size_t NGGridBlockTrackCollection::RangeCount() const {
@@ -483,7 +498,11 @@
     : starting_track_number(block_track_range.starting_track_number),
       track_count(block_track_range.track_count),
       starting_set_index(starting_set_index),
-      is_collapsed(block_track_range.is_collapsed) {}
+      properties(block_track_range.properties) {}
+
+bool NGGridLayoutAlgorithmTrackCollection::Range::IsCollapsed() const {
+  return properties.HasProperty(TrackSpanProperties::kIsCollapsed);
+}
 
 NGGridLayoutAlgorithmTrackCollection::NGGridLayoutAlgorithmTrackCollection(
     const NGGridBlockTrackCollection& block_track_collection,
@@ -494,7 +513,7 @@
     const NGGridBlockTrackCollection::Range& block_track_range =
         block_track_collection.RangeAtRangeIndex(range_iterator.RangeIndex());
     AppendTrackRange(block_track_range,
-                     block_track_range.is_implicit_range
+                     block_track_range.IsImplicit()
                          ? block_track_collection.ImplicitTracks()
                          : block_track_collection.ExplicitTracks(),
                      is_content_box_size_indefinite);
@@ -507,18 +526,18 @@
     bool is_content_box_size_indefinite) {
   Range new_range(block_track_range, /* starting_set_index */ sets_.size());
 
-  if (block_track_range.is_collapsed ||
+  if (block_track_range.IsCollapsed() ||
       block_track_range.repeater_index == kInvalidRangeIndex) {
 #if DCHECK_IS_ON()
     // If there are no specified repeaters for this range, it must be implicit.
     if (block_track_range.repeater_index == kInvalidRangeIndex)
-      DCHECK(block_track_range.is_implicit_range);
+      DCHECK(block_track_range.IsImplicit());
 #endif
 
     // Append a single element for the entire range's set.
     new_range.set_count = 1;
     sets_.emplace_back(block_track_range.track_count,
-                       block_track_range.is_collapsed);
+                       block_track_range.IsCollapsed());
   } else {
     wtf_size_t repeater_size =
         specified_track_list.RepeatSize(block_track_range.repeater_index);
@@ -557,21 +576,27 @@
     }
   }
 
-  // Cache if this range contains an intrinsic or flexible track.
-  new_range.is_spanning_flex_track = false;
-  new_range.is_spanning_intrinsic_track = false;
+  // Cache this range's track span properties.
+  bool is_range_spanning_flexible_track = false;
+  bool is_range_spanning_intrinsic_track = false;
+
   for (wtf_size_t i = 0; i < new_range.set_count; ++i) {
     const NGGridSet& set = sets_[new_range.starting_set_index + i];
 
     // From https://drafts.csswg.org/css-grid-1/#algo-terms, a <flex> minimum
     // sizing function shouldn't happen as it would be normalized to 'auto'.
     DCHECK(!set.TrackSize().HasFlexMinTrackBreadth());
-    new_range.is_spanning_flex_track |=
+    is_range_spanning_flexible_track |=
         set.TrackSize().HasFlexMaxTrackBreadth();
-    new_range.is_spanning_intrinsic_track |=
+    is_range_spanning_intrinsic_track |=
         set.TrackSize().HasIntrinsicMinTrackBreadth() ||
         set.TrackSize().HasIntrinsicMaxTrackBreadth();
   }
+
+  if (is_range_spanning_flexible_track)
+    new_range.properties.SetProperty(TrackSpanProperties::kHasFlexibleTrack);
+  if (is_range_spanning_intrinsic_track)
+    new_range.properties.SetProperty(TrackSpanProperties::kHasIntrinsicTrack);
   ranges_.push_back(new_range);
 }
 
@@ -621,16 +646,11 @@
   return ranges_[range_index].starting_set_index;
 }
 
-bool NGGridLayoutAlgorithmTrackCollection::IsRangeSpanningIntrinsicTrack(
-    wtf_size_t range_index) const {
+bool NGGridLayoutAlgorithmTrackCollection::RangeHasTrackSpanProperty(
+    wtf_size_t range_index,
+    TrackSpanProperties::PropertyId property_id) const {
   DCHECK_LT(range_index, RangeCount());
-  return ranges_[range_index].is_spanning_intrinsic_track;
-}
-
-bool NGGridLayoutAlgorithmTrackCollection::IsRangeSpanningFlexTrack(
-    wtf_size_t range_index) const {
-  DCHECK_LT(range_index, RangeCount());
-  return ranges_[range_index].is_spanning_flex_track;
+  return ranges_[range_index].properties.HasProperty(property_id);
 }
 
 wtf_size_t NGGridLayoutAlgorithmTrackCollection::RangeTrackNumber(
@@ -648,7 +668,7 @@
 bool NGGridLayoutAlgorithmTrackCollection::IsRangeCollapsed(
     wtf_size_t range_index) const {
   DCHECK_LT(range_index, RangeCount());
-  return ranges_[range_index].is_collapsed;
+  return ranges_[range_index].IsCollapsed();
 }
 
 wtf_size_t NGGridLayoutAlgorithmTrackCollection::RangeCount() const {
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.h b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.h
index a70bc18..8d52bf4 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.h
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.h
@@ -66,17 +66,39 @@
   virtual wtf_size_t RangeCount() const = 0;
 };
 
+struct CORE_EXPORT TrackSpanProperties {
+ public:
+  enum PropertyId : unsigned {
+    kNone = 0,
+    kHasIntrinsicTrack = 1 << 0,
+    kHasFlexibleTrack = 1 << 1,
+    kHasAutoMinimumTrack = 1 << 2,
+    kIsCollapsed = 1 << 3,
+    kIsImplicit = 1 << 4
+  };
+
+  inline bool HasProperty(PropertyId id) const { return bitmask_ & id; }
+  inline void SetProperty(PropertyId id) { bitmask_ |= id; }
+
+ private:
+  uint8_t bitmask_{kNone};
+};
+
 class CORE_EXPORT NGGridBlockTrackCollection
     : public NGGridTrackCollectionBase {
  public:
   struct Range {
+    bool IsImplicit() const;
+    bool IsCollapsed() const;
+
+    void SetIsImplicit();
+    void SetIsCollapsed();
+
     wtf_size_t starting_track_number;
     wtf_size_t track_count;
     wtf_size_t repeater_index;
     wtf_size_t repeater_offset;
-
-    bool is_implicit_range : 1;
-    bool is_collapsed : 1;
+    TrackSpanProperties properties;
   };
 
   explicit NGGridBlockTrackCollection(
@@ -89,14 +111,12 @@
   // Ensures that after FinalizeRanges is called, a range will start at the
   // |track_number|, and a range will end at |track_number| + |span_length|
   void EnsureTrackCoverage(wtf_size_t track_number, wtf_size_t span_length);
-
   // Build the collection of ranges based on information provided by
   // SetSpecifiedTracks and EnsureTrackCoverage.
   void FinalizeRanges();
-  // Returns the range at the given range index.
+
+  bool IsRangeImplicit(wtf_size_t range_index) const;
   const Range& RangeAtRangeIndex(wtf_size_t range_index) const;
-  // Returns the range at the given track.
-  const Range& RangeAtTrackNumber(wtf_size_t track_number) const;
 
   GridTrackSizingDirection Direction() const { return direction_; }
   bool IsForColumns() const { return direction_ == kForColumns; }
@@ -226,14 +246,13 @@
     Range(const NGGridBlockTrackCollection::Range& block_track_range,
           wtf_size_t starting_set_index);
 
+    bool IsCollapsed() const;
+
     wtf_size_t starting_track_number;
     wtf_size_t track_count;
     wtf_size_t starting_set_index;
     wtf_size_t set_count;
-
-    bool is_spanning_intrinsic_track : 1;
-    bool is_spanning_flex_track : 1;
-    bool is_collapsed : 1;
+    TrackSpanProperties properties;
   };
 
   template <bool is_const>
@@ -306,10 +325,11 @@
   wtf_size_t RangeSetCount(wtf_size_t range_index) const;
   wtf_size_t RangeStartingSetIndex(wtf_size_t range_index) const;
 
-  // Returns true if the range contains a set with an intrinsic sizing function.
-  bool IsRangeSpanningIntrinsicTrack(wtf_size_t range_index) const;
-  // Returns true if the range contains a set with a flexible sizing function.
-  bool IsRangeSpanningFlexTrack(wtf_size_t range_index) const;
+  // Returns true if the specified property has been set in the track span
+  // properties bitmask of the range at position |range_index|.
+  bool RangeHasTrackSpanProperty(
+      wtf_size_t range_index,
+      TrackSpanProperties::PropertyId property_id) const;
 
   GridTrackSizingDirection Direction() const { return direction_; }
   bool IsForColumns() const { return direction_ == kForColumns; }
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection_test.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection_test.cc
index 8819b003..5064b1f 100644
--- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection_test.cc
+++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection_test.cc
@@ -247,22 +247,22 @@
   NGGridTrackCollectionBase::RangeRepeatIterator iterator(&block_collection,
                                                           0u);
   EXPECT_RANGE(0u, 3u, iterator);
-  EXPECT_FALSE(block_collection.RangeAtTrackNumber(0u).is_implicit_range);
+  EXPECT_FALSE(block_collection.IsRangeImplicit(iterator.RangeIndex()));
 
   EXPECT_TRUE(iterator.MoveToNextRange());
   EXPECT_RANGE(3u, 5u, iterator);
-  EXPECT_FALSE(block_collection.RangeAtTrackNumber(3).is_implicit_range);
+  EXPECT_FALSE(block_collection.IsRangeImplicit(iterator.RangeIndex()));
 
   EXPECT_TRUE(iterator.MoveToNextRange());
   EXPECT_RANGE(8u, 9u, iterator);
-  EXPECT_FALSE(block_collection.RangeAtTrackNumber(11).is_implicit_range);
+  EXPECT_FALSE(block_collection.IsRangeImplicit(iterator.RangeIndex()));
 
   EXPECT_TRUE(iterator.MoveToNextRange());
-  EXPECT_FALSE(block_collection.RangeAtTrackNumber(20).is_implicit_range);
+  EXPECT_FALSE(block_collection.IsRangeImplicit(iterator.RangeIndex()));
   EXPECT_RANGE(17u, 21u, iterator);
 
   EXPECT_TRUE(iterator.MoveToNextRange());
-  EXPECT_TRUE(block_collection.RangeAtTrackNumber(40).is_implicit_range);
+  EXPECT_TRUE(block_collection.IsRangeImplicit(iterator.RangeIndex()));
   EXPECT_RANGE(38u, 5u, iterator);
 
   EXPECT_FALSE(iterator.MoveToNextRange());
@@ -599,10 +599,10 @@
   EXPECT_SET(GridTrackSize(Length::MinContent()), 1u, set_iterator);
   EXPECT_FALSE(set_iterator.MoveToNextSet());
   wtf_size_t current_range_index = range_iterator.RangeIndex();
-  EXPECT_TRUE(
-      algorithm_collection.IsRangeSpanningIntrinsicTrack(current_range_index));
-  EXPECT_FALSE(
-      algorithm_collection.IsRangeSpanningFlexTrack(current_range_index));
+  EXPECT_FALSE(algorithm_collection.RangeHasTrackSpanProperty(
+      current_range_index, TrackSpanProperties::kHasFlexibleTrack));
+  EXPECT_TRUE(algorithm_collection.RangeHasTrackSpanProperty(
+      current_range_index, TrackSpanProperties::kHasIntrinsicTrack));
   EXPECT_TRUE(range_iterator.MoveToNextRange());
 
   EXPECT_RANGE(1u, 2u, range_iterator);
@@ -613,10 +613,10 @@
   EXPECT_SET(GridTrackSize(Length::Fixed(2)), 1u, set_iterator);
   EXPECT_FALSE(set_iterator.MoveToNextSet());
   current_range_index = range_iterator.RangeIndex();
-  EXPECT_TRUE(
-      algorithm_collection.IsRangeSpanningIntrinsicTrack(current_range_index));
-  EXPECT_TRUE(
-      algorithm_collection.IsRangeSpanningFlexTrack(current_range_index));
+  EXPECT_TRUE(algorithm_collection.RangeHasTrackSpanProperty(
+      current_range_index, TrackSpanProperties::kHasFlexibleTrack));
+  EXPECT_TRUE(algorithm_collection.RangeHasTrackSpanProperty(
+      current_range_index, TrackSpanProperties::kHasIntrinsicTrack));
   EXPECT_TRUE(range_iterator.MoveToNextRange());
 
   EXPECT_RANGE(3u, 4u, range_iterator);
@@ -631,10 +631,10 @@
   EXPECT_SET(GridTrackSize(Length::Fixed(2)), 1u, set_iterator);
   EXPECT_FALSE(set_iterator.MoveToNextSet());
   current_range_index = range_iterator.RangeIndex();
-  EXPECT_TRUE(
-      algorithm_collection.IsRangeSpanningIntrinsicTrack(current_range_index));
-  EXPECT_TRUE(
-      algorithm_collection.IsRangeSpanningFlexTrack(current_range_index));
+  EXPECT_TRUE(algorithm_collection.RangeHasTrackSpanProperty(
+      current_range_index, TrackSpanProperties::kHasFlexibleTrack));
+  EXPECT_TRUE(algorithm_collection.RangeHasTrackSpanProperty(
+      current_range_index, TrackSpanProperties::kHasIntrinsicTrack));
   EXPECT_TRUE(range_iterator.MoveToNextRange());
 
   EXPECT_RANGE(7u, 1u, range_iterator);
@@ -643,10 +643,10 @@
   EXPECT_SET(GridTrackSize(Length::Fixed(3)), 1u, set_iterator);
   EXPECT_FALSE(set_iterator.MoveToNextSet());
   current_range_index = range_iterator.RangeIndex();
-  EXPECT_FALSE(
-      algorithm_collection.IsRangeSpanningIntrinsicTrack(current_range_index));
-  EXPECT_FALSE(
-      algorithm_collection.IsRangeSpanningFlexTrack(current_range_index));
+  EXPECT_FALSE(algorithm_collection.RangeHasTrackSpanProperty(
+      current_range_index, TrackSpanProperties::kHasFlexibleTrack));
+  EXPECT_FALSE(algorithm_collection.RangeHasTrackSpanProperty(
+      current_range_index, TrackSpanProperties::kHasIntrinsicTrack));
   EXPECT_TRUE(range_iterator.MoveToNextRange());
 
   EXPECT_RANGE(8u, 3u, range_iterator);
@@ -655,10 +655,10 @@
   EXPECT_SET(GridTrackSize(Length::Auto()), 3u, set_iterator);
   EXPECT_FALSE(set_iterator.MoveToNextSet());
   current_range_index = range_iterator.RangeIndex();
-  EXPECT_TRUE(
-      algorithm_collection.IsRangeSpanningIntrinsicTrack(current_range_index));
-  EXPECT_FALSE(
-      algorithm_collection.IsRangeSpanningFlexTrack(current_range_index));
+  EXPECT_FALSE(algorithm_collection.RangeHasTrackSpanProperty(
+      current_range_index, TrackSpanProperties::kHasFlexibleTrack));
+  EXPECT_TRUE(algorithm_collection.RangeHasTrackSpanProperty(
+      current_range_index, TrackSpanProperties::kHasIntrinsicTrack));
   EXPECT_FALSE(range_iterator.MoveToNextRange());
 }
 
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
index 66b5b78..d3c7107b 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -1227,7 +1227,14 @@
     const auto& child_fragment = To<NGPhysicalBoxFragment>(*child);
     const auto* child_box = To<LayoutBox>(child_fragment.GetLayoutObject());
     if (child_box && child_box != box_) {
-      DCHECK(child_box->IsColumnSpanAll());
+      if (!child_box->IsColumnSpanAll()) {
+        // TODO(almaher): In order for legacy tree operations to work properly,
+        // we need to CopyChildFragmentPosition(). We should probably also
+        // update the LayoutBox size at the last fragment of an OOF node.
+        // (See comments in CL:2597769).
+        DCHECK(child_box->IsOutOfFlowPositioned());
+        continue;
+      }
       CopyChildFragmentPosition(child_fragment, child.offset,
                                 physical_fragment);
       LayoutBox* placeholder = child_box->SpannerPlaceholder();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
index 117f65d..dc0a9b3 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.cc
@@ -168,7 +168,8 @@
     const LogicalOffset& child_offset,
     NGLogicalStaticPosition::InlineEdge inline_edge,
     NGLogicalStaticPosition::BlockEdge block_edge,
-    bool needs_block_offset_adjustment) {
+    bool needs_block_offset_adjustment,
+    const base::Optional<LogicalRect> containing_block_rect) {
   DCHECK(child);
 
   // If an OOF-positioned candidate has a static-position which uses a
@@ -181,7 +182,9 @@
 
   oof_positioned_candidates_.emplace_back(
       child, NGLogicalStaticPosition{child_offset, inline_edge, block_edge},
-      /* inline_container */ nullptr, needs_block_offset_adjustment);
+      /* inline_container */ nullptr, needs_block_offset_adjustment,
+      /*containing_block_offset */ LogicalOffset(),
+      /* containing_block_fragment */ nullptr, containing_block_rect);
 }
 
 void NGContainerFragmentBuilder::AddOutOfFlowInlineChildCandidate(
diff --git a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h
index a8225df5..545da74 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_container_fragment_builder.h
@@ -111,7 +111,8 @@
       NGLogicalStaticPosition::InlineEdge =
           NGLogicalStaticPosition::kInlineStart,
       NGLogicalStaticPosition::BlockEdge = NGLogicalStaticPosition::kBlockStart,
-      bool needs_block_offset_adjustment = true);
+      bool needs_block_offset_adjustment = true,
+      const base::Optional<LogicalRect> containing_block_rect = base::nullopt);
 
   // This should only be used for inline-level OOF-positioned nodes.
   // |inline_container_direction| is the current text direction for determining
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
index 185cfe1..388682f8b 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
+++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.cc
@@ -105,6 +105,7 @@
     base::Optional<LogicalSize> initial_containing_block_fixed_size)
     : container_builder_(container_builder),
       writing_mode_(container_style.GetWritingMode()),
+      default_writing_direction_(container_style.GetWritingDirection()),
       is_absolute_container_(is_absolute_container),
       is_fixed_container_(is_fixed_container),
       has_block_fragmentation_(container_space.HasBlockFragmentation()) {
@@ -113,20 +114,23 @@
            ->HasPositionedObjects())
     return;
 
-  default_containing_block_.writing_direction =
-      container_style.GetWritingDirection();
+  default_containing_block_info_for_absolute_.writing_direction =
+      default_writing_direction_;
+  default_containing_block_info_for_fixed_.writing_direction =
+      default_writing_direction_;
   const NGBoxStrut border_scrollbar =
       container_builder->Borders() + container_builder->Scrollbar();
   allow_first_tier_oof_cache_ = border_scrollbar.IsEmpty();
-  default_containing_block_.content_size_for_absolute =
+  default_containing_block_info_for_absolute_.rect.size =
       ShrinkLogicalSize(container_builder_->Size(), border_scrollbar);
-  default_containing_block_.content_size_for_fixed =
+  default_containing_block_info_for_fixed_.rect.size =
       initial_containing_block_fixed_size
           ? *initial_containing_block_fixed_size
-          : default_containing_block_.content_size_for_absolute;
-
-  default_containing_block_.container_offset = LogicalOffset(
-      border_scrollbar.inline_start, border_scrollbar.block_start);
+          : default_containing_block_info_for_absolute_.rect.size;
+  LogicalOffset container_offset = {border_scrollbar.inline_start,
+                                    border_scrollbar.block_start};
+  default_containing_block_info_for_absolute_.rect.offset = container_offset;
+  default_containing_block_info_for_fixed_.rect.offset = container_offset;
 }
 
 void NGOutOfFlowLayoutPart::Run(const LayoutBox* only_layout) {
@@ -287,14 +291,16 @@
 // When fragmenting, the ContainingBlockInfo is not stored ahead of time and
 // must be generated on demand. The reason being that during fragmentation, we
 // wait to place positioned nodes until they've reached the fragmentation
-// context root. In such cases, we cannot use |default_containing_block_| since
-// the fragmentation root is not the containing block of the positioned nodes.
-// Rather, we must generate their ContainingBlockInfo based on the provided
-// |containing_block_fragment|.
-const NGOutOfFlowLayoutPart::ContainingBlockInfo&
+// context root. In such cases, we cannot use default |ContainingBlockInfo|
+// since the fragmentation root is not the containing block of the positioned
+// nodes. Rather, we must generate their ContainingBlockInfo based on the
+// provided |containing_block_fragment|.
+const NGOutOfFlowLayoutPart::ContainingBlockInfo
 NGOutOfFlowLayoutPart::GetContainingBlockInfo(
     const NGLogicalOutOfFlowPositionedNode& candidate,
     const NGPhysicalContainerFragment* containing_block_fragment) {
+  if (candidate.containing_block_rect)
+    return {default_writing_direction_, *candidate.containing_block_rect};
   if (candidate.inline_container) {
     const auto it = containing_blocks_map_.find(candidate.inline_container);
     DCHECK(it != containing_blocks_map_.end());
@@ -327,14 +333,17 @@
         LogicalOffset(border.inline_start, border.block_start);
     container_offset += candidate.containing_block_offset;
 
-    ContainingBlockInfo containing_block_info{writing_direction, content_size,
-                                              content_size, container_offset};
+    ContainingBlockInfo containing_block_info{
+        writing_direction, LogicalRect(container_offset, content_size)};
 
     return containing_blocks_map_
         .insert(containing_block, containing_block_info)
         .stored_value->value;
   }
-  return default_containing_block_;
+
+  return candidate.node.Style().GetPosition() == EPosition::kAbsolute
+             ? default_containing_block_info_for_absolute_
+             : default_containing_block_info_for_fixed_;
 }
 
 void NGOutOfFlowLayoutPart::ComputeInlineContainingBlocks(
@@ -417,7 +426,7 @@
     DCHECK(inline_cb_style);
 
     const auto container_writing_direction =
-        default_containing_block_.writing_direction;
+        default_containing_block_info_for_absolute_.writing_direction;
     const auto inline_writing_direction =
         inline_cb_style->GetWritingDirection();
     NGBoxStrut inline_cb_borders = ComputeBordersForInline(*inline_cb_style);
@@ -475,8 +484,8 @@
 
     containing_blocks_map_.insert(
         block_info.key,
-        ContainingBlockInfo{inline_writing_direction, inline_cb_size,
-                            inline_cb_size, container_offset});
+        ContainingBlockInfo{inline_writing_direction,
+                            LogicalRect(container_offset, inline_cb_size)});
   }
 }
 
@@ -542,15 +551,13 @@
           node.GetLayoutBox()->ContainingBlock()) ||
          node.GetLayoutBox()->ContainingBlock()->IsTable());
 
-  const auto default_writing_direction =
-      default_containing_block_.writing_direction;
-  const ContainingBlockInfo& container_info = GetContainingBlockInfo(candidate);
+  const ContainingBlockInfo container_info = GetContainingBlockInfo(candidate);
   const ComputedStyle& candidate_style = node.Style();
   const auto candidate_writing_direction =
       candidate_style.GetWritingDirection();
 
-  LogicalSize container_content_size =
-      container_info.ContentSize(candidate_style.GetPosition());
+  LogicalSize container_content_size = container_info.rect.size;
+
   PhysicalSize container_physical_content_size =
       ToPhysicalSize(container_content_size, writing_mode_);
 
@@ -577,12 +584,12 @@
   // container's border-box). ng_absolute_utils expects the static position to
   // be relative to the container's padding-box.
   NGLogicalStaticPosition static_position = candidate.static_position;
-  static_position.offset -= container_info.container_offset;
+  static_position.offset -= container_info.rect.offset;
 
   NGLogicalStaticPosition candidate_static_position =
       static_position
           .ConvertToPhysical(
-              {default_writing_direction, container_physical_content_size})
+              {default_writing_direction_, container_physical_content_size})
           .ConvertToLogical(
               {candidate_writing_direction, container_physical_content_size});
 
@@ -599,7 +606,7 @@
     scoped_refptr<const NGLayoutResult> layout_result =
         Layout(node, candidate_constraint_space, candidate_static_position,
                container_physical_content_size, container_info,
-               default_writing_direction, only_layout);
+               default_writing_direction_, only_layout);
 
     if (!freeze_scrollbars.has_value()) {
       // Since out-of-flow positioning sets up a constraint space with fixed
@@ -670,7 +677,7 @@
          containing_block_fragment->GetLayoutObject() ==
              node.GetLayoutBox()->ContainingBlock());
 
-  const ContainingBlockInfo& container_info =
+  const ContainingBlockInfo container_info =
       GetContainingBlockInfo(descendant, containing_block_fragment);
   const auto default_writing_direction =
       containing_block_fragment->Style().GetWritingDirection();
@@ -678,19 +685,18 @@
   const auto descendant_writing_direction =
       descendant_style.GetWritingDirection();
 
-  LogicalSize container_content_size =
-      container_info.ContentSize(descendant_style.GetPosition());
+  LogicalSize container_content_size = container_info.rect.size;
   PhysicalSize container_physical_content_size = ToPhysicalSize(
       container_content_size, default_writing_direction.GetWritingMode());
 
   // Adjust the |static_position| (which is currently relative to the default
   // container's border-box). ng_absolute_utils expects the static position to
   // be relative to the container's padding-box. Since
-  // |container_info.container_offset| is relative to its fragmentainer in this
+  // |container_info.rect.offset| is relative to its fragmentainer in this
   // case, we also need to adjust the offset to account for this.
   NGLogicalStaticPosition static_position = descendant.static_position;
   static_position.offset -=
-      container_info.container_offset - descendant.containing_block_offset;
+      container_info.rect.offset - descendant.containing_block_offset;
 
   NGLogicalStaticPosition descendant_static_position =
       static_position
@@ -878,7 +884,7 @@
 
   // |inset| is relative to the container's padding-box. Convert this to being
   // relative to the default container's border-box.
-  LogicalOffset offset = container_info.container_offset;
+  LogicalOffset offset = container_info.rect.offset;
   offset.inline_offset += inset.inline_start;
   offset.block_offset += inset.block_start;
 
@@ -1008,6 +1014,10 @@
 
 bool NGOutOfFlowLayoutPart::IsContainingBlockForCandidate(
     const NGLogicalOutOfFlowPositionedNode& candidate) {
+  // Column boxes are not allowed to be containing blocks.
+  if (container_builder_->IsFragmentainerBoxType())
+    return false;
+
   EPosition position = candidate.node.Style().GetPosition();
 
   // Candidates whose containing block is inline are always positioned inside
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h
index 6184c6d..4762a16 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_layout_part.h
@@ -8,6 +8,7 @@
 #include "third_party/blink/renderer/core/core_export.h"
 
 #include "base/optional.h"
+#include "third_party/blink/renderer/core/layout/geometry/logical_rect.h"
 #include "third_party/blink/renderer/core/layout/geometry/physical_offset.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_absolute_utils.h"
 #include "third_party/blink/renderer/core/layout/ng/ng_constraint_space.h"
@@ -80,23 +81,13 @@
     // The writing direction of the container.
     WritingDirectionMode writing_direction = {WritingMode::kHorizontalTb,
                                               TextDirection::kLtr};
-    // Logical in containing block coordinates.
-    LogicalSize content_size_for_absolute;
-    // Content size for fixed is different for the ICB.
-    LogicalSize content_size_for_fixed;
-
-    // Offset of the container's padding-box.
-    LogicalOffset container_offset;
-
-    LogicalSize ContentSize(EPosition position) const {
-      return position == EPosition::kAbsolute ? content_size_for_absolute
-                                              : content_size_for_fixed;
-    }
+    // Size and offset of the container.
+    LogicalRect rect;
   };
 
   bool SweepLegacyCandidates(HashSet<const LayoutObject*>* placed_objects);
 
-  const ContainingBlockInfo& GetContainingBlockInfo(
+  const ContainingBlockInfo GetContainingBlockInfo(
       const NGLogicalOutOfFlowPositionedNode&,
       const NGPhysicalContainerFragment* = nullptr);
 
@@ -151,7 +142,8 @@
       LogicalOffset* offset) const;
 
   NGBoxFragmentBuilder* container_builder_;
-  ContainingBlockInfo default_containing_block_;
+  ContainingBlockInfo default_containing_block_info_for_absolute_;
+  ContainingBlockInfo default_containing_block_info_for_fixed_;
   HashMap<const LayoutObject*, ContainingBlockInfo> containing_blocks_map_;
   HashMap<wtf_size_t, NGConstraintSpace> fragmentainer_constraint_space_map_;
   // Map of fragmentainer indexes to a list of descendant layout results to
@@ -159,6 +151,7 @@
   HashMap<wtf_size_t, Vector<scoped_refptr<const NGLayoutResult>>>
       fragmentainer_descendant_results_;
   const WritingMode writing_mode_;
+  const WritingDirectionMode default_writing_direction_;
   LayoutUnit column_inline_progression_ = kIndefiniteSize;
   // The block size of the multi-column (before adjustment for spanners, etc.)
   // This is used to calculate the column size of any newly added proxy
diff --git a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h
index c1ff1621..bfba553 100644
--- a/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h
+++ b/third_party/blink/renderer/core/layout/ng/ng_out_of_flow_positioned_node.h
@@ -73,6 +73,7 @@
   bool needs_block_offset_adjustment;
   LogicalOffset containing_block_offset;
   scoped_refptr<const NGPhysicalContainerFragment> containing_block_fragment;
+  base::Optional<LogicalRect> containing_block_rect;
 
   NGLogicalOutOfFlowPositionedNode(
       NGBlockNode node,
@@ -81,13 +82,15 @@
       bool needs_block_offset_adjustment = false,
       LogicalOffset containing_block_offset = LogicalOffset(),
       scoped_refptr<const NGPhysicalContainerFragment>
-          containing_block_fragment = nullptr)
+          containing_block_fragment = nullptr,
+      const base::Optional<LogicalRect> containing_block_rect = base::nullopt)
       : node(node),
         static_position(static_position),
         inline_container(inline_container),
         needs_block_offset_adjustment(needs_block_offset_adjustment),
         containing_block_offset(containing_block_offset),
-        containing_block_fragment(std::move(containing_block_fragment)) {
+        containing_block_fragment(std::move(containing_block_fragment)),
+        containing_block_rect(containing_block_rect) {
     DCHECK(!inline_container ||
            inline_container == inline_container->ContinuationRoot());
   }
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.cc
index e76dd6f..828d497 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.cc
@@ -86,19 +86,4 @@
   return false;
 }
 
-LayoutSVGResourceFilter* GetFilterResourceForSVG(SVGResourceClient& client,
-                                                 const ComputedStyle& style) {
-  if (!style.HasFilter())
-    return nullptr;
-  const FilterOperations& operations = style.Filter();
-  if (operations.size() != 1)
-    return nullptr;
-  const auto* reference_filter =
-      DynamicTo<ReferenceFilterOperation>(*operations.at(0));
-  if (!reference_filter)
-    return nullptr;
-  return GetSVGResourceAsType<LayoutSVGResourceFilter>(
-      client, reference_filter->Resource());
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.h b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.h
index d7419ff..256b782a 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.h
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_filter.h
@@ -60,11 +60,6 @@
   bool FindCycleFromSelf(SVGResourcesCycleSolver&) const override;
 };
 
-// Get the LayoutSVGResourceFilter from the 'filter' property iff the 'filter'
-// is a single url(...) reference.
-LayoutSVGResourceFilter* GetFilterResourceForSVG(SVGResourceClient&,
-                                                 const ComputedStyle&);
-
 template <>
 struct DowncastTraits<LayoutSVGResourceFilter> {
   static bool AllowFrom(const LayoutSVGResourceContainer& container) {
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.cc b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.cc
index c795f3c..d20bb36 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.cc
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.cc
@@ -41,7 +41,6 @@
 void LayoutSVGResourceMasker::RemoveAllClientsFromCache() {
   NOT_DESTROYED();
   cached_paint_record_.reset();
-  mask_content_boundaries_ = FloatRect();
   MarkAllClientsForInvalidation(
       SVGResourceClient::kPaintPropertiesInvalidation |
       SVGResourceClient::kPaintInvalidation);
@@ -76,20 +75,6 @@
   return cached_paint_record_;
 }
 
-void LayoutSVGResourceMasker::CalculateMaskContentVisualRect() {
-  NOT_DESTROYED();
-  for (const SVGElement& child_element :
-       Traversal<SVGElement>::ChildrenOf(*GetElement())) {
-    const LayoutObject* layout_object = child_element.GetLayoutObject();
-    if (!layout_object ||
-        layout_object->StyleRef().Display() == EDisplay::kNone)
-      continue;
-    mask_content_boundaries_.Unite(
-        layout_object->LocalToSVGParentTransform().MapRect(
-            layout_object->VisualRectInLocalSVGCoordinates()));
-  }
-}
-
 SVGUnitTypes::SVGUnitType LayoutSVGResourceMasker::MaskUnits() const {
   NOT_DESTROYED();
   return To<SVGMaskElement>(GetElement())->maskUnits()->CurrentEnumValue();
@@ -119,22 +104,7 @@
   if (mask_units == SVGUnitTypes::kSvgUnitTypeUserspaceonuse)
     mask_boundaries.Scale(reference_box_zoom);
 
-  if (mask_content_boundaries_.IsEmpty())
-    CalculateMaskContentVisualRect();
-
-  FloatRect mask_rect = mask_content_boundaries_;
-  if (MaskContentUnits() == SVGUnitTypes::kSvgUnitTypeObjectboundingbox) {
-    AffineTransform transform;
-    transform.Translate(reference_box.X(), reference_box.Y());
-    transform.ScaleNonUniform(reference_box.Width(), reference_box.Height());
-    mask_rect = transform.MapRect(mask_rect);
-  } else {
-    // Scale the mask rect to the same space as the reference box.
-    mask_rect.Scale(reference_box_zoom);
-  }
-
-  mask_rect.Intersect(mask_boundaries);
-  return mask_rect;
+  return mask_boundaries;
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h
index 3088ac3..86ff367 100644
--- a/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h
+++ b/third_party/blink/renderer/core/layout/svg/layout_svg_resource_masker.h
@@ -59,10 +59,7 @@
                                              GraphicsContext&);
 
  private:
-  void CalculateMaskContentVisualRect();
-
   sk_sp<const PaintRecord> cached_paint_record_;
-  FloatRect mask_content_boundaries_;
 };
 
 template <>
diff --git a/third_party/blink/renderer/core/layout/svg/svg_layout_tree_as_text.cc b/third_party/blink/renderer/core/layout/svg/svg_layout_tree_as_text.cc
index 339ffe8..785956e 100644
--- a/third_party/blink/renderer/core/layout/svg/svg_layout_tree_as_text.cc
+++ b/third_party/blink/renderer/core/layout/svg/svg_layout_tree_as_text.cc
@@ -704,6 +704,24 @@
   WriteResources(ts, shape, indent);
 }
 
+// Get the LayoutSVGResourceFilter from the 'filter' property iff the 'filter'
+// is a single url(...) reference.
+static LayoutSVGResourceFilter* GetFilterResourceForSVG(
+    SVGResourceClient& client,
+    const ComputedStyle& style) {
+  if (!style.HasFilter())
+    return nullptr;
+  const FilterOperations& operations = style.Filter();
+  if (operations.size() != 1)
+    return nullptr;
+  const auto* reference_filter =
+      DynamicTo<ReferenceFilterOperation>(*operations.at(0));
+  if (!reference_filter)
+    return nullptr;
+  return GetSVGResourceAsType<LayoutSVGResourceFilter>(
+      client, reference_filter->Resource());
+}
+
 static void WriteSVGResourceReferencePrefix(
     WTF::TextStream& ts,
     const char* resource_name,
@@ -746,6 +764,7 @@
         ts, "clipPath", clipper, clip_path_reference.Url(), tree_scope, indent);
     ts << " " << clipper->ResourceBoundingBox(reference_box) << "\n";
   }
+  // TODO(fs): Only handles the single url(...) case. Do we care?
   if (LayoutSVGResourceFilter* filter =
           GetFilterResourceForSVG(*client, style)) {
     DCHECK(style.HasFilter());
diff --git a/third_party/blink/renderer/core/layout/svg/svg_resources.cc b/third_party/blink/renderer/core/layout/svg/svg_resources.cc
index 2afe8794..561db1a 100644
--- a/third_party/blink/renderer/core/layout/svg/svg_resources.cc
+++ b/third_party/blink/renderer/core/layout/svg/svg_resources.cc
@@ -293,19 +293,35 @@
   if (!operations.IsEmpty() && !filter_data_dirty_ &&
       reference_box == operations.ReferenceBox())
     return;
-  if (!filter_data_ && GetFilterResourceForSVG(*this, object.StyleRef())) {
-    FilterEffectBuilder builder(reference_box, 1);
-    filter_data_ = CreateFilterDataWithNodeMap(
-        builder,
-        To<ReferenceFilterOperation>(*object.StyleRef().Filter().at(0)));
-  }
-  operations.Clear();
-  if (filter_data_) {
-    operations.AppendReferenceFilter(filter_data_->BuildPaintFilter());
+  const ComputedStyle& style = object.StyleRef();
+  FilterEffectBuilder builder(reference_box, 1);
+  builder.SetShorthandScale(1 / style.EffectiveZoom());
+  const FilterOperations& filter = style.Filter();
+  // If the filter is a single 'url(...)' reference we can optimize some
+  // mutations to the referenced filter chain by tracking the filter
+  // dependencies and only perform partial invalidations of the filter chain.
+  const bool is_single_reference_filter =
+      filter.size() == 1 && IsA<ReferenceFilterOperation>(*filter.at(0));
+  if (is_single_reference_filter) {
+    if (!filter_data_) {
+      filter_data_ = CreateFilterDataWithNodeMap(
+          builder, To<ReferenceFilterOperation>(*filter.at(0)));
+    }
+    operations.Clear();
+    if (filter_data_) {
+      operations.AppendReferenceFilter(filter_data_->BuildPaintFilter());
+    } else {
+      // Filter construction failed. Create a filter chain that yields
+      // transparent black.
+      operations.AppendOpacityFilter(0);
+    }
   } else {
-    // Filter construction failed. Create a filter chain that yields
-    // transparent black.
-    operations.AppendOpacityFilter(0);
+    // Drop any existing filter data since the filter is no longer
+    // cacheable.
+    if (FilterData* filter_data = filter_data_.Release())
+      filter_data->Dispose();
+
+    operations = builder.BuildFilterOperations(filter);
   }
   operations.SetReferenceBox(reference_box);
   filter_data_dirty_ = false;
@@ -340,7 +356,7 @@
 
 void SVGResourceInvalidator::InvalidateEffects() {
   const ComputedStyle& style = object_.StyleRef();
-  if (style.HasFilter() && style.Filter().HasReferenceFilter()) {
+  if (style.HasFilter()) {
     if (SVGElementResourceClient* client = SVGResources::GetClient(object_))
       client->InvalidateFilterData();
   }
diff --git a/third_party/blink/renderer/core/loader/empty_clients.cc b/third_party/blink/renderer/core/loader/empty_clients.cc
index fd7bce3..1627238 100644
--- a/third_party/blink/renderer/core/loader/empty_clients.cc
+++ b/third_party/blink/renderer/core/loader/empty_clients.cc
@@ -97,7 +97,7 @@
     NavigationPolicy,
     WebFrameLoadType,
     bool,
-    TriggeringEventInfo,
+    mojom::blink::TriggeringEventInfo,
     HTMLFormElement*,
     network::mojom::CSPDisposition,
     mojo::PendingRemote<mojom::blink::BlobURLToken>,
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h
index 1bc22007..f380e39 100644
--- a/third_party/blink/renderer/core/loader/empty_clients.h
+++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -266,7 +266,7 @@
       NavigationPolicy,
       WebFrameLoadType,
       bool,
-      TriggeringEventInfo,
+      mojom::blink::TriggeringEventInfo,
       HTMLFormElement*,
       network::mojom::CSPDisposition,
       mojo::PendingRemote<mojom::blink::BlobURLToken>,
diff --git a/third_party/blink/renderer/core/loader/form_submission.cc b/third_party/blink/renderer/core/loader/form_submission.cc
index e99e160..af8c4ec 100644
--- a/third_party/blink/renderer/core/loader/form_submission.cc
+++ b/third_party/blink/renderer/core/loader/form_submission.cc
@@ -152,7 +152,7 @@
     scoped_refptr<EncodedFormData> data,
     const Event* event,
     NavigationPolicy navigation_policy,
-    TriggeringEventInfo triggering_event_info,
+    mojom::blink::TriggeringEventInfo triggering_event_info,
     ClientNavigationReason reason,
     std::unique_ptr<ResourceRequest> resource_request,
     Frame* target_frame,
@@ -293,15 +293,16 @@
   resource_request->SetHasUserGesture(
       LocalFrame::HasTransientUserActivation(form->GetDocument().GetFrame()));
 
-  TriggeringEventInfo triggering_event_info;
+  mojom::blink::TriggeringEventInfo triggering_event_info;
   if (event) {
-    triggering_event_info = event->isTrusted()
-                                ? TriggeringEventInfo::kFromTrustedEvent
-                                : TriggeringEventInfo::kFromUntrustedEvent;
+    triggering_event_info =
+        event->isTrusted()
+            ? mojom::blink::TriggeringEventInfo::kFromTrustedEvent
+            : mojom::blink::TriggeringEventInfo::kFromUntrustedEvent;
     if (event->UnderlyingEvent())
       event = event->UnderlyingEvent();
   } else {
-    triggering_event_info = TriggeringEventInfo::kNotFromEvent;
+    triggering_event_info = mojom::blink::TriggeringEventInfo::kNotFromEvent;
   }
 
   FrameLoadRequest frame_request(form->GetDocument().domWindow(),
diff --git a/third_party/blink/renderer/core/loader/form_submission.h b/third_party/blink/renderer/core/loader/form_submission.h
index 89f11989..d7e7e3ea 100644
--- a/third_party/blink/renderer/core/loader/form_submission.h
+++ b/third_party/blink/renderer/core/loader/form_submission.h
@@ -32,7 +32,7 @@
 #define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_FORM_SUBMISSION_H_
 
 #include "base/macros.h"
-#include "third_party/blink/public/common/navigation/triggering_event_info.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom-blink-forward.h"
 #include "third_party/blink/public/web/web_frame_load_type.h"
 #include "third_party/blink/renderer/core/loader/frame_load_request.h"
 #include "third_party/blink/renderer/core/loader/navigation_policy.h"
@@ -108,7 +108,7 @@
                  scoped_refptr<EncodedFormData>,
                  const Event*,
                  NavigationPolicy navigation_policy,
-                 TriggeringEventInfo triggering_event_info,
+                 mojom::blink::TriggeringEventInfo triggering_event_info,
                  ClientNavigationReason reason,
                  std::unique_ptr<ResourceRequest> resource_request,
                  Frame* target_frame,
@@ -142,7 +142,7 @@
   Member<HTMLFormElement> form_;
   scoped_refptr<EncodedFormData> form_data_;
   NavigationPolicy navigation_policy_;
-  TriggeringEventInfo triggering_event_info_;
+  mojom::blink::TriggeringEventInfo triggering_event_info_;
   String result_;
   ClientNavigationReason reason_;
   std::unique_ptr<ResourceRequest> resource_request_;
diff --git a/third_party/blink/renderer/core/loader/frame_load_request.h b/third_party/blink/renderer/core/loader/frame_load_request.h
index f58eff2a..9b6772e 100644
--- a/third_party/blink/renderer/core/loader/frame_load_request.h
+++ b/third_party/blink/renderer/core/loader/frame_load_request.h
@@ -29,8 +29,8 @@
 #include "base/memory/scoped_refptr.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/network/public/mojom/referrer_policy.mojom-blink.h"
-#include "third_party/blink/public/common/navigation/triggering_event_info.h"
 #include "third_party/blink/public/mojom/blob/blob_url_store.mojom-blink.h"
+#include "third_party/blink/public/mojom/frame/frame.mojom-blink.h"
 #include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom-blink.h"
 #include "third_party/blink/public/platform/web_impression.h"
 #include "third_party/blink/public/web/web_window_features.h"
@@ -86,11 +86,11 @@
     navigation_policy_ = navigation_policy;
   }
 
-  TriggeringEventInfo GetTriggeringEventInfo() const {
+  mojom::blink::TriggeringEventInfo GetTriggeringEventInfo() const {
     return triggering_event_info_;
   }
-  void SetTriggeringEventInfo(TriggeringEventInfo info) {
-    DCHECK(info != TriggeringEventInfo::kUnknown);
+  void SetTriggeringEventInfo(mojom::blink::TriggeringEventInfo info) {
+    DCHECK(info != mojom::blink::TriggeringEventInfo::kUnknown);
     triggering_event_info_ = info;
   }
 
@@ -147,13 +147,11 @@
 
   // Impressions are set when a FrameLoadRequest is created for a click on an
   // anchor tag that has conversion measurement attributes.
-  void SetImpression(const base::Optional<WebImpression>& impression) {
+  void SetImpression(const WebImpression& impression) {
     impression_ = impression;
   }
 
-  const base::Optional<WebImpression>& Impression() const {
-    return impression_;
-  }
+  const base::Optional<WebImpression>& Impression() { return impression_; }
 
   bool CanDisplay(const KURL&) const;
 
@@ -171,8 +169,8 @@
   ClientNavigationReason client_navigation_reason_ =
       ClientNavigationReason::kNone;
   NavigationPolicy navigation_policy_ = kNavigationPolicyCurrentTab;
-  TriggeringEventInfo triggering_event_info_ =
-      TriggeringEventInfo::kNotFromEvent;
+  mojom::blink::TriggeringEventInfo triggering_event_info_ =
+      mojom::blink::TriggeringEventInfo::kNotFromEvent;
   HTMLFormElement* form_ = nullptr;
   ShouldSendReferrer should_send_referrer_;
   scoped_refptr<const DOMWrapperWorld> world_;
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc
index b21834ea..b38b221 100644
--- a/third_party/blink/renderer/core/loader/frame_loader.cc
+++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -627,7 +627,8 @@
 void FrameLoader::StartNavigation(FrameLoadRequest& request,
                                   WebFrameLoadType frame_load_type) {
   CHECK(!IsBackForwardLoadType(frame_load_type));
-  DCHECK(request.GetTriggeringEventInfo() != TriggeringEventInfo::kUnknown);
+  DCHECK(request.GetTriggeringEventInfo() !=
+         mojom::blink::TriggeringEventInfo::kUnknown);
   DCHECK(frame_->GetDocument());
   if (HTMLFrameOwnerElement* element = frame_->DeprecatedLocalOwner())
     element->CancelPendingLazyLoad();
@@ -689,7 +690,8 @@
   if (same_document_navigation) {
     document_loader_->CommitSameDocumentNavigation(
         url, frame_load_type, nullptr, request.ClientRedirect(), origin_window,
-        request.GetTriggeringEventInfo() != TriggeringEventInfo::kNotFromEvent,
+        request.GetTriggeringEventInfo() !=
+            mojom::blink::TriggeringEventInfo::kNotFromEvent,
         nullptr /* extra_data */);
     return;
   }
@@ -704,7 +706,8 @@
 
   WebNavigationType navigation_type = DetermineNavigationType(
       frame_load_type, resource_request.HttpBody() || request.Form(),
-      request.GetTriggeringEventInfo() != TriggeringEventInfo::kNotFromEvent);
+      request.GetTriggeringEventInfo() !=
+          mojom::blink::TriggeringEventInfo::kNotFromEvent);
   mojom::blink::RequestContextType request_context_type =
       DetermineRequestContextFromNavigationType(navigation_type);
 
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.cc b/third_party/blink/renderer/core/page/chrome_client_impl.cc
index d31dd9eb..ef66eff 100644
--- a/third_party/blink/renderer/core/page/chrome_client_impl.cc
+++ b/third_party/blink/renderer/core/page/chrome_client_impl.cc
@@ -261,8 +261,7 @@
           WebLocalFrameImpl::FromFrame(frame),
           WrappedResourceRequest(r.GetResourceRequest()), features, frame_name,
           static_cast<WebNavigationPolicy>(r.GetNavigationPolicy()),
-          sandbox_flags, session_storage_namespace_id, consumed_user_gesture,
-          r.Impression()));
+          sandbox_flags, session_storage_namespace_id, consumed_user_gesture));
   if (!new_view)
     return nullptr;
   return new_view->GetPage();
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl_test.cc b/third_party/blink/renderer/core/page/chrome_client_impl_test.cc
index 28ea879..cfa73a8 100644
--- a/third_party/blink/renderer/core/page/chrome_client_impl_test.cc
+++ b/third_party/blink/renderer/core/page/chrome_client_impl_test.cc
@@ -66,8 +66,7 @@
                       WebNavigationPolicy,
                       network::mojom::blink::WebSandboxFlags,
                       const SessionStorageNamespaceId&,
-                      bool& consumed_user_gesture,
-                      const base::Optional<WebImpression>&) override {
+                      bool& consumed_user_gesture) override {
     return web_view_helper_.InitializeWithOpener(opener);
   }
 
diff --git a/third_party/blink/renderer/core/page/spatial_navigation_test.cc b/third_party/blink/renderer/core/page/spatial_navigation_test.cc
index 6ad77be..52663c0f 100644
--- a/third_party/blink/renderer/core/page/spatial_navigation_test.cc
+++ b/third_party/blink/renderer/core/page/spatial_navigation_test.cc
@@ -784,6 +784,9 @@
 }
 
 TEST_F(SpatialNavigationTest, InlineImageTextLinkWithLineHeight) {
+  // Fails when LayoutNG is disabled. See crbug.com/1160211
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+    return;
   LoadAhem();
   SetBodyInnerHTML(
       "<!DOCTYPE html>"
@@ -809,6 +812,9 @@
 }
 
 TEST_F(SpatialNavigationTest, InlineLinkWithInnerBlock) {
+  // Fails when LayoutNG is disabled. See crbug.com/1160211
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+    return;
   LoadAhem();
   SetBodyInnerHTML(
       "<!DOCTYPE html>"
@@ -954,6 +960,9 @@
 }
 
 TEST_F(SpatialNavigationTest, NormalizedLineBrokenLinkWithImg) {
+  // Fails when LayoutNG is disabled. See crbug.com/1160211
+  if (!RuntimeEnabledFeatures::LayoutNGEnabled())
+    return;
   LoadAhem();
   SetBodyInnerHTML(
       "<!DOCTYPE html>"
diff --git a/third_party/blink/renderer/core/paint/css_mask_painter_test.cc b/third_party/blink/renderer/core/paint/css_mask_painter_test.cc
index 5625d19..816482e1 100644
--- a/third_party/blink/renderer/core/paint/css_mask_painter_test.cc
+++ b/third_party/blink/renderer/core/paint/css_mask_painter_test.cc
@@ -28,7 +28,7 @@
   base::Optional<IntRect> mask_bounding_box =
       CSSMaskPainter::MaskBoundingBox(masked, PhysicalOffset());
   ASSERT_TRUE(mask_bounding_box.has_value());
-  EXPECT_EQ(IntRect(75, 75, 100, 100), *mask_bounding_box);
+  EXPECT_EQ(IntRect(35, 35, 180, 180), *mask_bounding_box);
 }
 
 TEST_F(CSSMaskPainterTest, MaskBoundingBoxCSSBlock) {
diff --git a/third_party/blink/renderer/core/paint/filter_effect_builder.cc b/third_party/blink/renderer/core/paint/filter_effect_builder.cc
index 38870c57..e5727f8b 100644
--- a/third_party/blink/renderer/core/paint/filter_effect_builder.cc
+++ b/third_party/blink/renderer/core/paint/filter_effect_builder.cc
@@ -130,6 +130,7 @@
     SkBlurImageFilter::TileMode blur_tile_mode)
     : reference_box_(reference_box),
       zoom_(zoom),
+      shorthand_scale_(1),
       fill_flags_(fill_flags),
       stroke_flags_(stroke_flags),
       blur_tile_mode_(blur_tile_mode) {}
@@ -262,6 +263,7 @@
       case FilterOperation::BLUR: {
         float std_deviation = FloatValueForLength(
             To<BlurFilterOperation>(filter_operation)->StdDeviation(), 0);
+        std_deviation *= shorthand_scale_;
         effect = MakeGarbageCollected<FEGaussianBlur>(
             parent_filter, std_deviation, std_deviation);
         break;
@@ -269,8 +271,10 @@
       case FilterOperation::DROP_SHADOW: {
         const ShadowData& shadow =
             To<DropShadowFilterOperation>(*filter_operation).Shadow();
+        FloatPoint offset = shadow.Location().ScaledBy(shorthand_scale_);
+        float radius = shadow.Blur() * shorthand_scale_;
         effect = MakeGarbageCollected<FEDropShadow>(
-            parent_filter, shadow.Blur(), shadow.Blur(), shadow.X(), shadow.Y(),
+            parent_filter, radius, radius, offset.X(), offset.Y(),
             shadow.GetColor().GetColor(), 1);
         break;
       }
@@ -378,13 +382,16 @@
       case FilterOperation::BLUR: {
         float pixel_radius =
             To<BlurFilterOperation>(*op).StdDeviation().GetFloatValue();
+        pixel_radius *= shorthand_scale_;
         filters.AppendBlurFilter(pixel_radius, blur_tile_mode_);
         break;
       }
       case FilterOperation::DROP_SHADOW: {
         const ShadowData& shadow = To<DropShadowFilterOperation>(*op).Shadow();
-        filters.AppendDropShadowFilter(FlooredIntPoint(shadow.Location()),
-                                       shadow.Blur(),
+        IntPoint floored_offset =
+            FlooredIntPoint(shadow.Location().ScaledBy(shorthand_scale_));
+        float radius = shadow.Blur() * shorthand_scale_;
+        filters.AppendDropShadowFilter(floored_offset, radius,
                                        shadow.GetColor().GetColor());
         break;
       }
diff --git a/third_party/blink/renderer/core/paint/filter_effect_builder.h b/third_party/blink/renderer/core/paint/filter_effect_builder.h
index 111b5d2a..e67d112 100644
--- a/third_party/blink/renderer/core/paint/filter_effect_builder.h
+++ b/third_party/blink/renderer/core/paint/filter_effect_builder.h
@@ -63,9 +63,14 @@
   CompositorFilterOperations BuildFilterOperations(
       const FilterOperations&) const;
 
+  void SetShorthandScale(float shorthand_scale) {
+    shorthand_scale_ = shorthand_scale;
+  }
+
  private:
-  FloatRect reference_box_;
-  float zoom_;
+  const FloatRect reference_box_;
+  const float zoom_;
+  float shorthand_scale_;  // Scale factor for shorthand filter functions.
   const PaintFlags* fill_flags_;
   const PaintFlags* stroke_flags_;
   const SkBlurImageFilter::TileMode blur_tile_mode_;
diff --git a/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc b/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc
index 62843e2..af13bf9f 100644
--- a/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc
+++ b/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc
@@ -848,7 +848,7 @@
                                  IntRect(155, 166, 7, 8),
                                  PaintInvalidationReason::kSVGResource},
           RasterInvalidationInfo{real_rect, real_rect->DebugName(),
-                                 IntRect(155, 166, 7, 8),
+                                 IntRect(154, 165, 9, 10),
                                  PaintInvalidationReason::kSVGResource}));
 
   GetDocument().View()->SetTracksRasterInvalidations(false);
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc
index d16c303..979f565 100644
--- a/third_party/blink/renderer/core/paint/paint_layer.cc
+++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -147,8 +147,11 @@
     skip_info.emplace(&ancestor->GetLayoutObject());
   while (auto* container = layout_object->Container(
              skipped_ancestor ? &*skip_info : nullptr)) {
-    if (skipped_ancestor && skip_info->AncestorSkipped())
-      *skipped_ancestor = true;
+    if (skipped_ancestor) {
+      if (skip_info->AncestorSkipped())
+        *skipped_ancestor = true;
+      skip_info.emplace(&ancestor->GetLayoutObject());
+    }
     if (container->HasLayer())
       return To<LayoutBoxModelObject>(container)->Layer();
     layout_object = container;
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
index 4ff31df..2227b7db 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -1332,15 +1332,6 @@
   return reasons;
 }
 
-static bool HasReferenceFilterOnly(const ComputedStyle& style) {
-  if (!style.HasFilter())
-    return false;
-  const FilterOperations& operations = style.Filter();
-  if (operations.size() != 1)
-    return false;
-  return operations.at(0)->GetType() == FilterOperation::REFERENCE;
-}
-
 static bool IsClipPathDescendant(const LayoutObject& object) {
   // If the object itself is a resource container (root of a resource subtree)
   // it is not considered a clipPath descendant since it is independent of its
@@ -1370,7 +1361,7 @@
       return true;
   } else if (object.IsSVGChild() && !object.IsText() &&
              SVGResources::GetClient(object)) {
-    if (HasReferenceFilterOnly(object.StyleRef())) {
+    if (object.StyleRef().HasFilter()) {
       // Filters don't apply to elements that are descendants of a <clipPath>.
       if (!full_context.has_svg_hidden_container_ancestor ||
           !IsClipPathDescendant(object))
@@ -1398,7 +1389,7 @@
     SVGElementResourceClient* client = SVGResources::GetClient(object);
     if (!client)
       return;
-    if (!HasReferenceFilterOnly(object.StyleRef()))
+    if (!object.StyleRef().HasFilter())
       return;
     // Try to use the cached filter.
     if (effect_node)
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc b/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc
index 582eb21..be2c5f63 100644
--- a/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc
+++ b/third_party/blink/renderer/core/paint/paint_property_tree_update_tests.cc
@@ -1077,7 +1077,8 @@
   EXPECT_NE(nullptr, properties->Mask());
   const auto* mask_clip = properties->MaskClip();
   ASSERT_NE(nullptr, mask_clip);
-  EXPECT_EQ(FloatRoundedRect(0, 100, 100, 100), mask_clip->UnsnappedClipRect());
+  EXPECT_EQ(FloatRoundedRect(0, 100, 10000, 20000),
+            mask_clip->UnsnappedClipRect());
 
   GetDocument().getElementById("rect")->removeAttribute("mask");
   UpdateAllLifecyclePhasesForTest();
@@ -1104,13 +1105,15 @@
   EXPECT_NE(nullptr, properties->Mask());
   const auto* mask_clip = properties->MaskClip();
   ASSERT_NE(nullptr, mask_clip);
-  EXPECT_EQ(FloatRoundedRect(0, 50, 100, 150), mask_clip->UnsnappedClipRect());
+  EXPECT_EQ(FloatRoundedRect(0, 50, 5000, 20000),
+            mask_clip->UnsnappedClipRect());
 
   GetDocument().getElementById("rect")->setAttribute("width", "200");
   UpdateAllLifecyclePhasesForTest();
   EXPECT_NE(nullptr, properties->Effect());
   EXPECT_NE(nullptr, properties->Mask());
-  EXPECT_EQ(FloatRoundedRect(0, 50, 100, 150), mask_clip->UnsnappedClipRect());
+  EXPECT_EQ(FloatRoundedRect(0, 50, 20000, 20000),
+            mask_clip->UnsnappedClipRect());
 }
 
 TEST_P(PaintPropertyTreeUpdateTest, WillTransformChangeAboveFixed) {
diff --git a/third_party/blink/renderer/core/paint/svg_mask_painter.cc b/third_party/blink/renderer/core/paint/svg_mask_painter.cc
index 2d0af7b..d049d3e 100644
--- a/third_party/blink/renderer/core/paint/svg_mask_painter.cc
+++ b/third_party/blink/renderer/core/paint/svg_mask_painter.cc
@@ -36,8 +36,8 @@
                                                   DisplayItem::kSVGMask))
     return;
 
+  // TODO(fs): Should clip this with the bounds of the mask's PaintRecord.
   FloatRect visual_rect = properties->MaskClip()->UnsnappedClipRect().Rect();
-  visual_rect.Intersect(layout_object.VisualRectInLocalSVGCoordinates());
   DrawingRecorder recorder(context, display_item_client, DisplayItem::kSVGMask,
                            EnclosingIntRect(visual_rect));
 
diff --git a/third_party/blink/renderer/core/svg/svg_a_element.cc b/third_party/blink/renderer/core/svg/svg_a_element.cc
index 10b3ec25c..494c2d4 100644
--- a/third_party/blink/renderer/core/svg/svg_a_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_a_element.cc
@@ -141,8 +141,9 @@
           ResourceRequest(GetDocument().CompleteURL(url)));
       frame_request.SetNavigationPolicy(NavigationPolicyFromEvent(&event));
       frame_request.SetTriggeringEventInfo(
-          event.isTrusted() ? TriggeringEventInfo::kFromTrustedEvent
-                            : TriggeringEventInfo::kFromUntrustedEvent);
+          event.isTrusted()
+              ? mojom::blink::TriggeringEventInfo::kFromTrustedEvent
+              : mojom::blink::TriggeringEventInfo::kFromUntrustedEvent);
       frame_request.GetResourceRequest().SetHasUserGesture(
           LocalFrame::HasTransientUserActivation(GetDocument().GetFrame()));
 
diff --git a/third_party/blink/renderer/core/svg/svg_external_document_cache.cc b/third_party/blink/renderer/core/svg/svg_external_document_cache.cc
index 8b1428a78..c1dffa7 100644
--- a/third_party/blink/renderer/core/svg/svg_external_document_cache.cc
+++ b/third_party/blink/renderer/core/svg/svg_external_document_cache.cc
@@ -29,6 +29,7 @@
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/core/loader/resource/text_resource.h"
 #include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
 
 namespace blink {
 
@@ -42,46 +43,44 @@
          mime_type == "application/xml" || mime_type == "application/xhtml+xml";
 }
 
+Document* CreateDocument(const TextResource* resource,
+                         ExecutionContext* execution_context) {
+  const ResourceResponse& response = resource->GetResponse();
+  if (!MimeTypeAllowed(response))
+    return nullptr;
+  auto* document =
+      XMLDocument::CreateSVG(DocumentInit::Create()
+                                 .WithURL(response.CurrentRequestUrl())
+                                 .WithExecutionContext(execution_context));
+  document->SetContent(resource->DecodedText());
+  return document;
+}
+
 }  // namespace
 
-void SVGExternalDocumentCache::Entry::AddClient(Client* client) {
-  if (!GetResource()->IsLoaded()) {
-    clients_.insert(client);
-    return;
-  }
-  context_->GetTaskRunner(TaskType::kInternalLoading)
-      ->PostTask(
-          FROM_HERE,
-          WTF::Bind(&SVGExternalDocumentCache::Client::NotifyFinished,
-                    WrapPersistent(client), WrapPersistent(document_.Get())));
-}
-
-void SVGExternalDocumentCache::Entry::NotifyFinished(Resource* resource) {
-  DCHECK_EQ(GetResource(), resource);
-  for (auto client : clients_) {
-    if (client)
-      client->NotifyFinished(GetDocument());
-  }
-}
-
 Document* SVGExternalDocumentCache::Entry::GetDocument() {
-  const TextResource* resource = To<TextResource>(GetResource());
-  if (!document_ && resource->IsLoaded() && resource->HasData() &&
-      MimeTypeAllowed(resource->GetResponse())) {
-    document_ = XMLDocument::CreateSVG(
-        DocumentInit::Create()
-            .WithURL(resource->GetResponse().CurrentRequestUrl())
-            .WithExecutionContext(context_.Get()));
-    document_->SetContent(resource->DecodedText());
+  if (resource_->IsLoaded()) {
+    // If this entry saw a revalidation, re-parse the document.
+    // TODO(fs): This will be inefficient for successful revalidations, so we
+    // want to detect those and not re-parse the document in those cases.
+    if (was_revalidating_) {
+      document_.Clear();
+      was_revalidating_ = false;
+    }
+    if (!document_ && resource_->HasData())
+      document_ = CreateDocument(resource_, context_);
   }
-  return document_.Get();
+  return document_;
+}
+
+const KURL& SVGExternalDocumentCache::Entry::Url() const {
+  return resource_->Url();
 }
 
 void SVGExternalDocumentCache::Entry::Trace(Visitor* visitor) const {
-  ResourceClient::Trace(visitor);
+  visitor->Trace(resource_);
   visitor->Trace(document_);
   visitor->Trace(context_);
-  visitor->Trace(clients_);
 }
 
 const char SVGExternalDocumentCache::kSupplementName[] =
@@ -101,13 +100,13 @@
     : Supplement<Document>(document) {}
 
 SVGExternalDocumentCache::Entry* SVGExternalDocumentCache::Get(
-    Client* client,
+    ResourceClient* client,
     const KURL& url,
     const AtomicString& initiator_name,
     network::mojom::blink::CSPDisposition csp_disposition) {
   Document* context_document = GetSupplementable();
-  ResourceLoaderOptions options(
-      context_document->GetExecutionContext()->GetCurrentWorld());
+  ExecutionContext* execution_context = context_document->GetExecutionContext();
+  ResourceLoaderOptions options(execution_context->GetCurrentWorld());
   options.initiator_info.name = initiator_name;
   FetchParameters params(ResourceRequest(url), options);
   params.SetContentSecurityCheck(csp_disposition);
@@ -116,16 +115,15 @@
   params.SetRequestContext(mojom::blink::RequestContextType::IMAGE);
   params.SetRequestDestination(network::mojom::RequestDestination::kImage);
 
-  Entry* entry =
-      MakeGarbageCollected<Entry>(context_document->GetExecutionContext());
-  Resource* resource = TextResource::FetchSVGDocument(
-      params, context_document->Fetcher(), entry);
-  // TODO(fs): Handle revalidations that return a new/different resource without
-  // needing to throw away the old Entry.
-  if (resource && resource->IsCacheValidator())
-    entries_.erase(resource);
-  entry = entries_.insert(resource, entry).stored_value->value;
-  entry->AddClient(client);
+  TextResource* resource = TextResource::FetchSVGDocument(
+      params, context_document->Fetcher(), client);
+  if (!resource)
+    return nullptr;
+  auto& entry = entries_.insert(resource, nullptr).stored_value->value;
+  if (!entry)
+    entry = MakeGarbageCollected<Entry>(resource, execution_context);
+  if (resource->IsCacheValidator())
+    entry->SetWasRevalidating();
   return entry;
 }
 
diff --git a/third_party/blink/renderer/core/svg/svg_external_document_cache.h b/third_party/blink/renderer/core/svg/svg_external_document_cache.h
index 379f5c99..d65938b5 100644
--- a/third_party/blink/renderer/core/svg/svg_external_document_cache.h
+++ b/third_party/blink/renderer/core/svg/svg_external_document_cache.h
@@ -27,14 +27,16 @@
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
 #include "third_party/blink/renderer/platform/loader/fetch/resource.h"
-#include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
 #include "third_party/blink/renderer/platform/supplementable.h"
 
 namespace blink {
+
 class Document;
 class ExecutionContext;
+class ResourceClient;
+class TextResource;
 
-class CORE_EXPORT SVGExternalDocumentCache
+class CORE_EXPORT SVGExternalDocumentCache final
     : public GarbageCollected<SVGExternalDocumentCache>,
       public Supplement<Document> {
  public:
@@ -43,41 +45,35 @@
   explicit SVGExternalDocumentCache(Document&);
   void Trace(Visitor*) const override;
 
-  class Client : public GarbageCollectedMixin {
+  class CORE_EXPORT Entry final : public GarbageCollected<Entry> {
    public:
-    virtual void NotifyFinished(Document*) = 0;
-  };
+    Entry(TextResource* resource, ExecutionContext* context)
+        : resource_(resource), context_(context) {
+      DCHECK(resource_);
+      DCHECK(context_);
+    }
+    void SetWasRevalidating() { was_revalidating_ = true; }
 
-  class CORE_EXPORT Entry final : public GarbageCollected<Entry>,
-                                  public ResourceClient {
-   public:
-    explicit Entry(ExecutionContext* context) : context_(context) {}
-    ~Entry() override = default;
-    void Trace(Visitor*) const override;
     Document* GetDocument();
-    const KURL& Url() const { return GetResource()->Url(); }
+    const KURL& Url() const;
+
+    void Trace(Visitor*) const;
 
    private:
-    friend class SVGExternalDocumentCache;
-    void AddClient(Client*);
-
-    // ResourceClient overrides;
-    void NotifyFinished(Resource*) override;
-    String DebugName() const override { return "SVGExternalDocumentCache"; }
-
+    Member<TextResource> resource_;
     Member<Document> document_;
     Member<ExecutionContext> context_;
-    HeapHashSet<WeakMember<Client>> clients_;
+    bool was_revalidating_ = false;
   };
 
-  Entry* Get(Client*,
+  Entry* Get(ResourceClient*,
              const KURL&,
              const AtomicString& initiator_name,
              network::mojom::blink::CSPDisposition =
                  network::mojom::blink::CSPDisposition::CHECK);
 
  private:
-  HeapHashMap<WeakMember<Resource>, WeakMember<Entry>> entries_;
+  HeapHashMap<WeakMember<Resource>, Member<Entry>> entries_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/svg/svg_external_document_cache_test.cc b/third_party/blink/renderer/core/svg/svg_external_document_cache_test.cc
index 1886837..5dfad10 100644
--- a/third_party/blink/renderer/core/svg/svg_external_document_cache_test.cc
+++ b/third_party/blink/renderer/core/svg/svg_external_document_cache_test.cc
@@ -11,13 +11,6 @@
 
 namespace blink {
 
-class DummyCacheClient : public GarbageCollected<DummyCacheClient>,
-                         public SVGExternalDocumentCache::Client {
- public:
-  DummyCacheClient() = default;
-  void NotifyFinished(Document*) override {}
-};
-
 class SVGExternalDocumentCacheTest : public SimTest {};
 
 TEST_F(SVGExternalDocumentCacheTest, GetDocumentBeforeLoadComplete) {
@@ -27,12 +20,11 @@
 
   const char kSVGUrl[] = "https://example.com/svg.svg";
   SimSubresourceRequest svg_resource(kSVGUrl, "application/xml");
-  DummyCacheClient* client = MakeGarbageCollected<DummyCacheClient>();
 
   // Request a resource from the cache.
   auto* entry =
       SVGExternalDocumentCache::From(GetDocument())
-          ->Get(client, KURL(kSVGUrl), fetch_initiator_type_names::kCSS);
+          ->Get(nullptr, KURL(kSVGUrl), fetch_initiator_type_names::kCSS);
 
   // Write part of the response. The document should not be initialized yet,
   // because the response is not complete. The document would be invalid at this
diff --git a/third_party/blink/renderer/core/svg/svg_resource.cc b/third_party/blink/renderer/core/svg/svg_resource.cc
index ad3f7900..2f69af2 100644
--- a/third_party/blink/renderer/core/svg/svg_resource.cc
+++ b/third_party/blink/renderer/core/svg/svg_resource.cc
@@ -193,7 +193,7 @@
   target_ = ResolveTarget();
 }
 
-void ExternalSVGResource::NotifyFinished(Document*) {
+void ExternalSVGResource::NotifyFinished(Resource*) {
   Element* new_target = ResolveTarget();
   if (new_target == target_)
     return;
@@ -201,6 +201,10 @@
   NotifyElementChanged();
 }
 
+String ExternalSVGResource::DebugName() const {
+  return "ExternalSVGResource";
+}
+
 Element* ExternalSVGResource::ResolveTarget() {
   if (!cache_entry_)
     return nullptr;
@@ -217,7 +221,7 @@
 void ExternalSVGResource::Trace(Visitor* visitor) const {
   visitor->Trace(cache_entry_);
   SVGResource::Trace(visitor);
-  SVGExternalDocumentCache::Client::Trace(visitor);
+  ResourceClient::Trace(visitor);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/svg/svg_resource.h b/third_party/blink/renderer/core/svg/svg_resource.h
index 9448de0..87544ad 100644
--- a/third_party/blink/renderer/core/svg/svg_resource.h
+++ b/third_party/blink/renderer/core/svg/svg_resource.h
@@ -9,6 +9,7 @@
 #include "third_party/blink/renderer/core/svg/svg_external_document_cache.h"
 #include "third_party/blink/renderer/core/svg/svg_resource_client.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
 #include "third_party/blink/renderer/platform/wtf/hash_map.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -128,8 +129,7 @@
 };
 
 // External resource reference (see SVGResource.)
-class ExternalSVGResource final : public SVGResource,
-                                  private SVGExternalDocumentCache::Client {
+class ExternalSVGResource final : public SVGResource, public ResourceClient {
  public:
   explicit ExternalSVGResource(const KURL&);
 
@@ -141,8 +141,9 @@
  private:
   Element* ResolveTarget();
 
-  // SVGExternalDocumentCache::Client implementation
-  void NotifyFinished(Document*) override;
+  // ResourceClient implementation
+  void NotifyFinished(Resource*) override;
+  String DebugName() const override;
 
   Member<SVGExternalDocumentCache::Entry> cache_entry_;
   KURL url_;
diff --git a/third_party/blink/renderer/core/svg/svg_use_element.cc b/third_party/blink/renderer/core/svg/svg_use_element.cc
index dd89332..9c6725e 100644
--- a/third_party/blink/renderer/core/svg/svg_use_element.cc
+++ b/third_party/blink/renderer/core/svg/svg_use_element.cc
@@ -101,7 +101,7 @@
   visitor->Trace(target_id_observer_);
   SVGGraphicsElement::Trace(visitor);
   SVGURIReference::Trace(visitor);
-  SVGExternalDocumentCache::Client::Trace(visitor);
+  ResourceClient::Trace(visitor);
 }
 
 #if DCHECK_IS_ON()
@@ -195,6 +195,7 @@
   element_url_ = GetDocument().CompleteURL(url_string);
   element_url_is_local_ = url_string.StartsWith('#');
   if (!IsStructurallyExternal() || !GetDocument().IsActive()) {
+    ClearResource();
     cache_entry_ = nullptr;
     return;
   }
@@ -587,12 +588,12 @@
   DispatchEvent(*Event::Create(event_type_names::kLoad));
 }
 
-void SVGUseElement::NotifyFinished(Document* external_document) {
+void SVGUseElement::NotifyFinished(Resource* resource) {
   if (!isConnected())
     return;
 
   InvalidateShadowTree();
-  if (!external_document) {
+  if (resource->ErrorOccurred() || !cache_entry_->GetDocument()) {
     DispatchEvent(*Event::Create(event_type_names::kError));
   } else {
     if (have_fired_load_event_)
@@ -608,4 +609,8 @@
   }
 }
 
+String SVGUseElement::DebugName() const {
+  return "SVGUseElement";
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/svg/svg_use_element.h b/third_party/blink/renderer/core/svg/svg_use_element.h
index 8ffbf59..2c710eb6 100644
--- a/third_party/blink/renderer/core/svg/svg_use_element.h
+++ b/third_party/blink/renderer/core/svg/svg_use_element.h
@@ -29,6 +29,7 @@
 #include "third_party/blink/renderer/core/svg/svg_graphics_element.h"
 #include "third_party/blink/renderer/core/svg/svg_uri_reference.h"
 #include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
 
 namespace blink {
 
@@ -36,7 +37,7 @@
 
 class SVGUseElement final : public SVGGraphicsElement,
                             public SVGURIReference,
-                            public SVGExternalDocumentCache::Client {
+                            public ResourceClient {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
@@ -104,7 +105,8 @@
   bool HasCycleUseReferencing(const ContainerNode& target_instance,
                               const SVGElement& new_target) const;
 
-  void NotifyFinished(Document*) override;
+  void NotifyFinished(Resource*) override;
+  String DebugName() const override;
   void UpdateTargetReference();
 
   Member<SVGExternalDocumentCache::Entry> cache_entry_;
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
index 1620d1d..4fb8cf24 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/base_rendering_context_2d.cc
@@ -1569,8 +1569,8 @@
     ImageData* image_data,
     ExceptionState& exception_state) const {
   ImageData* result = nullptr;
-  ImageDataSettings* color_settings = image_data->getSettings();
-  result = ImageData::Create(image_data->Size(), color_settings);
+  ImageDataSettings* image_data_settings = image_data->getSettings();
+  result = ImageData::Create(image_data->Size(), image_data_settings);
   if (!result)
     exception_state.ThrowRangeError("Out of memory at ImageData creation");
   return result;
@@ -1589,10 +1589,10 @@
 
   IntSize size(abs(sw), abs(sh));
   ImageData* result = nullptr;
-  ImageDataSettings* color_settings = ImageDataSettings::Create();
-  color_settings->setColorSpace(kSRGBCanvasColorSpaceName);
-  color_settings->setStorageFormat(kUint8ClampedArrayStorageFormatName);
-  result = ImageData::Create(size, color_settings);
+  ImageDataSettings* image_data_settings = ImageDataSettings::Create();
+  image_data_settings->setColorSpace(kSRGBCanvasColorSpaceName);
+  image_data_settings->setStorageFormat(kUint8ClampedArrayStorageFormatName);
+  result = ImageData::Create(size, image_data_settings);
 
   if (!result)
     exception_state.ThrowRangeError("Out of memory at ImageData creation");
@@ -1602,9 +1602,9 @@
 ImageData* BaseRenderingContext2D::createImageData(
     unsigned width,
     unsigned height,
-    ImageDataSettings* color_settings,
+    ImageDataSettings* image_data_settings,
     ExceptionState& exception_state) const {
-  return ImageData::CreateImageData(width, height, color_settings,
+  return ImageData::CreateImageData(width, height, image_data_settings,
                                     exception_state);
 }
 
@@ -1622,9 +1622,10 @@
     int sy,
     int sw,
     int sh,
-    ImageDataSettings* color_settings,
+    ImageDataSettings* image_data_settings,
     ExceptionState& exception_state) {
-  return getImageDataInternal(sx, sy, sw, sh, color_settings, exception_state);
+  return getImageDataInternal(sx, sy, sw, sh, image_data_settings,
+                              exception_state);
 }
 
 ImageData* BaseRenderingContext2D::getImageDataInternal(
@@ -1632,7 +1633,7 @@
     int sy,
     int sw,
     int sh,
-    ImageDataSettings* color_settings,
+    ImageDataSettings* image_data_settings,
     ExceptionState& exception_state) {
   if (!base::CheckMul(sw, sh).IsValid<int>()) {
     exception_state.ThrowRangeError("Out of memory at ImageData creation");
@@ -1678,17 +1679,18 @@
 
   const IntRect image_data_rect(sx, sy, sw, sh);
 
-  if (!color_settings) {
-    color_settings = ImageDataSettings::Create();
-    color_settings->setColorSpace(kSRGBCanvasColorSpaceName);
-    color_settings->setStorageFormat(kUint8ClampedArrayStorageFormatName);
+  if (!image_data_settings) {
+    image_data_settings = ImageDataSettings::Create();
+    image_data_settings->setColorSpace(kSRGBCanvasColorSpaceName);
+    image_data_settings->setStorageFormat(kUint8ClampedArrayStorageFormatName);
   }
 
   const ImageDataStorageFormat storage_format =
-      ImageData::GetImageDataStorageFormat(color_settings->storageFormat());
+      ImageData::GetImageDataStorageFormat(
+          image_data_settings->storageFormat());
   if (!CanCreateCanvas2dResourceProvider() || isContextLost()) {
     ImageData* result =
-        ImageData::Create(image_data_rect.Size(), color_settings);
+        ImageData::Create(image_data_rect.Size(), image_data_settings);
     if (!result)
       exception_state.ThrowRangeError("Out of memory at ImageData creation");
     return result;
@@ -1733,7 +1735,7 @@
         NOTREACHED();
     }
     sk_sp<SkColorSpace> color_space = CanvasColorSpaceToSkColorSpace(
-        CanvasColorSpaceFromName(color_settings->colorSpace()));
+        CanvasColorSpaceFromName(image_data_settings->colorSpace()));
     image_info = SkImageInfo::Make(sw, sh, color_type, kUnpremul_SkAlphaType,
                                    color_space);
   }
@@ -1812,7 +1814,7 @@
       NOTREACHED();
   }
   ImageData* image_data = ImageData::Create(
-      image_data_rect.Size(), std::move(data_array), color_settings);
+      image_data_rect.Size(), std::move(data_array), image_data_settings);
 
   if (!IsPaint2D()) {
     int scaled_time = getScaledElapsedTime(
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
index 3e38dee..463a072 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
@@ -695,7 +695,7 @@
     int sy,
     int sw,
     int sh,
-    ImageDataSettings* color_settings,
+    ImageDataSettings* image_data_settings,
     ExceptionState& exception_state) {
   const IdentifiableSurface surface = IdentifiableSurface::FromTypeAndToken(
       IdentifiableSurface::Type::kCanvasReadback, GetContextType());
@@ -705,7 +705,7 @@
         .Record(ukm_recorder_);
   }
   return BaseRenderingContext2D::getImageDataInternal(
-      sx, sy, sw, sh, color_settings, exception_state);
+      sx, sy, sw, sh, image_data_settings, exception_state);
 }
 
 void CanvasRenderingContext2D::FinalizeFrame() {
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
index dd70d199..989abc2 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
@@ -943,7 +943,7 @@
   EXPECT_EQ(data_length, data_f32->length());
 
   ImageData* image_data = nullptr;
-  ImageDataSettings* color_settings = ImageDataSettings::Create();
+  ImageDataSettings* image_data_settings = ImageDataSettings::Create();
   int num_pixels = data_length / 4;
 
   // At most four bytes are needed for Float32 output per color component.
@@ -953,7 +953,7 @@
   // Loop through different possible combinations of image data color space and
   // storage formats and create the respective test image data objects.
   for (unsigned i = 0; i < num_image_data_color_spaces; i++) {
-    color_settings->setColorSpace(
+    image_data_settings->setColorSpace(
         ImageData::CanvasColorSpaceName(image_data_color_spaces[i]));
 
     for (unsigned j = 0; j < num_image_data_storage_formats; j++) {
@@ -961,22 +961,23 @@
       switch (image_data_storage_formats[j]) {
         case kUint8ClampedArrayStorageFormat:
           data_array = data_u8;
-          color_settings->setStorageFormat(kUint8ClampedArrayStorageFormatName);
+          image_data_settings->setStorageFormat(
+              kUint8ClampedArrayStorageFormatName);
           break;
         case kUint16ArrayStorageFormat:
           data_array = data_u16;
-          color_settings->setStorageFormat(kUint16ArrayStorageFormatName);
+          image_data_settings->setStorageFormat(kUint16ArrayStorageFormatName);
           break;
         case kFloat32ArrayStorageFormat:
           data_array = data_f32;
-          color_settings->setStorageFormat(kFloat32ArrayStorageFormatName);
+          image_data_settings->setStorageFormat(kFloat32ArrayStorageFormatName);
           break;
         default:
           NOTREACHED();
       }
 
-      image_data =
-          ImageData::CreateForTest(IntSize(2, 2), data_array, color_settings);
+      image_data = ImageData::CreateForTest(IntSize(2, 2), data_array,
+                                            image_data_settings);
       unsigned k = static_cast<unsigned>(canvas_colorspace_setting);
       ImageDataSettings* canvas_color_setting = ImageDataSettings::Create();
       canvas_color_setting->setColorSpace(
diff --git a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc
index ecc741c..4ad64d3 100644
--- a/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc
+++ b/third_party/blink/renderer/modules/mediacapturefromelement/canvas_capture_handler.cc
@@ -31,8 +31,6 @@
 #include "third_party/skia/include/gpu/GrBackendSurface.h"
 #include "ui/gfx/color_space.h"
 
-using media::VideoFrame;
-
 namespace blink {
 
 namespace {
@@ -117,7 +115,7 @@
     DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
   }
 
-  void SendNewFrameOnIOThread(scoped_refptr<VideoFrame> video_frame,
+  void SendNewFrameOnIOThread(scoped_refptr<media::VideoFrame> video_frame,
                               base::TimeTicks current_time) {
     DCHECK_CALLED_ON_VALID_THREAD(io_thread_checker_);
     new_frame_callback_.Run(std::move(video_frame), current_time);
@@ -269,7 +267,7 @@
   PaintImage paint_image = image->PaintImageForCurrentFrame();
   const base::TimeTicks timestamp = base::TimeTicks::Now();
   const gfx::Size image_size(paint_image.width(), paint_image.height());
-  scoped_refptr<VideoFrame> temp_argb_frame = frame_pool_.CreateFrame(
+  scoped_refptr<media::VideoFrame> temp_argb_frame = frame_pool_.CreateFrame(
       media::PIXEL_FORMAT_ARGB, image_size, gfx::Rect(image_size), image_size,
       base::TimeDelta());
   if (!temp_argb_frame) {
@@ -281,8 +279,9 @@
       image_size.width(), image_size.height(),
       is_opaque ? kPremul_SkAlphaType : kUnpremul_SkAlphaType);
   if (!paint_image.readPixels(
-          image_info, temp_argb_frame->visible_data(VideoFrame::kARGBPlane),
-          temp_argb_frame->stride(VideoFrame::kARGBPlane), 0 /*srcX*/,
+          image_info,
+          temp_argb_frame->visible_data(media::VideoFrame::kARGBPlane),
+          temp_argb_frame->stride(media::VideoFrame::kARGBPlane), 0 /*srcX*/,
           0 /*srcY*/)) {
     DLOG(ERROR) << "Couldn't read pixels from PaintImage";
     return;
@@ -290,8 +289,9 @@
   SendFrame(
       ConvertToYUVFrame(
           is_opaque, false /* flip */,
-          temp_argb_frame->visible_data(VideoFrame::kARGBPlane), image_size,
-          temp_argb_frame->stride(VideoFrame::kARGBPlane), kN32_SkColorType),
+          temp_argb_frame->visible_data(media::VideoFrame::kARGBPlane),
+          image_size, temp_argb_frame->stride(media::VideoFrame::kARGBPlane),
+          kN32_SkColorType),
       timestamp, GetImageYUVColorSpace(image));
 }
 
@@ -303,7 +303,7 @@
 
   const base::TimeTicks timestamp = base::TimeTicks::Now();
   const gfx::Size image_size(image->width(), image->height());
-  scoped_refptr<VideoFrame> temp_argb_frame = frame_pool_.CreateFrame(
+  scoped_refptr<media::VideoFrame> temp_argb_frame = frame_pool_.CreateFrame(
       media::PIXEL_FORMAT_ARGB, image_size, gfx::Rect(image_size), image_size,
       base::TimeDelta());
   if (!temp_argb_frame) {
@@ -328,7 +328,7 @@
       mailbox_holder.sync_token.GetConstData());
   context_provider->RasterInterface()->ReadbackARGBPixelsAsync(
       mailbox_holder.mailbox, mailbox_holder.texture_target, image_size,
-      temp_argb_frame->visible_data(VideoFrame::kARGBPlane), format,
+      temp_argb_frame->visible_data(media::VideoFrame::kARGBPlane), format,
       WTF::Bind(&CanvasCaptureHandler::OnARGBPixelsReadAsync,
                 weak_ptr_factory_.GetWeakPtr(), image, temp_argb_frame,
                 timestamp, !image->IsOriginTopLeft()));
@@ -343,7 +343,7 @@
 
   const base::TimeTicks timestamp = base::TimeTicks::Now();
   const gfx::Size image_size(image->width(), image->height());
-  scoped_refptr<VideoFrame> output_frame = frame_pool_.CreateFrame(
+  scoped_refptr<media::VideoFrame> output_frame = frame_pool_.CreateFrame(
       media::PIXEL_FORMAT_I420, image_size, gfx::Rect(image_size), image_size,
       base::TimeDelta());
   if (!output_frame) {
@@ -391,13 +391,13 @@
   const bool is_opaque = image->CurrentFrameKnownToBeOpaque();
   const auto color_space = GetImageYUVColorSpace(image);
 
-  SendFrame(
-      ConvertToYUVFrame(is_opaque, flip,
-                        temp_argb_frame->visible_data(VideoFrame::kARGBPlane),
-                        temp_argb_frame->visible_rect().size(),
-                        temp_argb_frame->stride(VideoFrame::kARGBPlane),
-                        kN32_SkColorType),
-      this_frame_ticks, color_space);
+  SendFrame(ConvertToYUVFrame(
+                is_opaque, flip,
+                temp_argb_frame->visible_data(media::VideoFrame::kARGBPlane),
+                temp_argb_frame->visible_rect().size(),
+                temp_argb_frame->stride(media::VideoFrame::kARGBPlane),
+                kN32_SkColorType),
+            this_frame_ticks, color_space);
   if (num_ongoing_async_pixel_readouts_ == 0 && deferred_request_refresh_frame_)
     SendRefreshFrame();
 }
@@ -432,7 +432,7 @@
   DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
   TRACE_EVENT0("webrtc", "CanvasCaptureHandler::ConvertToYUVFrame");
 
-  scoped_refptr<VideoFrame> video_frame = frame_pool_.CreateFrame(
+  scoped_refptr<media::VideoFrame> video_frame = frame_pool_.CreateFrame(
       is_opaque ? media::PIXEL_FORMAT_I420 : media::PIXEL_FORMAT_I420A,
       image_size, gfx::Rect(image_size), image_size, base::TimeDelta());
   if (!video_frame) {
@@ -472,17 +472,19 @@
     // It is ok to use ARGB function because alpha has the same alignment for
     // both ABGR and ARGB.
     libyuv::ARGBExtractAlpha(
-        source_ptr, stride, video_frame->visible_data(VideoFrame::kAPlane),
-        video_frame->stride(VideoFrame::kAPlane), image_size.width(),
+        source_ptr, stride,
+        video_frame->visible_data(media::VideoFrame::kAPlane),
+        video_frame->stride(media::VideoFrame::kAPlane), image_size.width(),
         (flip ? -1 : 1) * image_size.height());
   }
 
   return video_frame;
 }
 
-void CanvasCaptureHandler::SendFrame(scoped_refptr<VideoFrame> video_frame,
-                                     base::TimeTicks this_frame_ticks,
-                                     const gfx::ColorSpace& color_space) {
+void CanvasCaptureHandler::SendFrame(
+    scoped_refptr<media::VideoFrame> video_frame,
+    base::TimeTicks this_frame_ticks,
+    const gfx::ColorSpace& color_space) {
   DCHECK_CALLED_ON_VALID_THREAD(main_render_thread_checker_);
 
   // If this function is called asynchronously, |delegate_| might have been
diff --git a/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc b/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc
index cccd87a..2010768 100644
--- a/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc
+++ b/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc
@@ -36,7 +36,6 @@
 #include "third_party/blink/renderer/modules/mediarecorder/h264_encoder.h"
 #endif  // #if BUILDFLAG(RTC_USE_H264)
 
-using media::VideoFrame;
 using video_track_recorder::kVEAEncoderMinResolutionHeight;
 using video_track_recorder::kVEAEncoderMinResolutionWidth;
 
@@ -275,7 +274,7 @@
 }
 
 void VideoTrackRecorderImpl::Encoder::StartFrameEncode(
-    scoped_refptr<VideoFrame> video_frame,
+    scoped_refptr<media::VideoFrame> video_frame,
     base::TimeTicks capture_timestamp) {
   // Cache the thread sending frames on first frame arrival.
   if (!origin_task_runner_.get())
@@ -335,7 +334,7 @@
 }
 
 void VideoTrackRecorderImpl::Encoder::RetrieveFrameOnEncodingTaskRunner(
-    scoped_refptr<VideoFrame> video_frame,
+    scoped_refptr<media::VideoFrame> video_frame,
     base::TimeTicks capture_timestamp) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(encoding_sequence_checker_);
 
diff --git a/third_party/blink/renderer/platform/weborigin/security_origin.cc b/third_party/blink/renderer/platform/weborigin/security_origin.cc
index b437ca1..4e016d6a 100644
--- a/third_party/blink/renderer/platform/weborigin/security_origin.cc
+++ b/third_party/blink/renderer/platform/weborigin/security_origin.cc
@@ -449,8 +449,6 @@
   // 5. If origin’s host component is "localhost" or falls within ".localhost",
   //    and the user agent conforms to the name resolution rules in
   //    [let-localhost-be-localhost], return "Potentially Trustworthy".
-  // TODO(https://crbug.com/1153337): This returns true for
-  // "localhost.localdomain". Should this host be excluded?
   if (IsLocalhost())
     return true;
 
diff --git a/third_party/blink/renderer/platform/weborigin/security_origin_test.cc b/third_party/blink/renderer/platform/weborigin/security_origin_test.cc
index 64d19c23..3ee29cf 100644
--- a/third_party/blink/renderer/platform/weborigin/security_origin_test.cc
+++ b/third_party/blink/renderer/platform/weborigin/security_origin_test.cc
@@ -144,10 +144,8 @@
       // IPv4 compatible IPv6 literal for 127.0.0.1.
       {false, false, "http://[::127.0.0.1]"},
 
-      // TODO(eroman): Not documented why these are recognized.
-      {true, true, "http://localhost.localdomain"},
-
       // Legacy localhost names.
+      {false, false, "http://localhost.localdomain"},
       {false, false, "http://localhost6"},
       {false, false, "ftp://localhost6.localdomain6"},
 
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 8b2ae57..abf55077 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -385,6 +385,9 @@
 # Fails, at a minimum, due to lack of support for CSS mask property in html elements
 crbug.com/432153 external/wpt/svg/painting/reftests/display-none-mask.html [ Skip ]
 
+# Bug accidentally masked by using square mask geometry.
+crbug.com/1155161 svg/masking/mask-of-root.html [ Failure ]
+
 # Failures due to pointerMove building synthetic events without button information (main thread only).
 crbug.com/1056778 fast/scrolling/scrollbars/scrollbar-thumb-snapping.html [ Failure ]
 
@@ -1035,9 +1038,7 @@
 crbug.com/1079031 virtual/layout_ng_block_frag/external/wpt/css/css-multicol/change-out-of-flow-type-and-remove-inner-multicol-crash.html [ Crash Failure ]
 crbug.com/1058792 virtual/layout_ng_block_frag/external/wpt/css/css-multicol/composited-under-clip-under-multicol.html [ Failure Crash ]
 crbug.com/996655 virtual/layout_ng_block_frag/external/wpt/css/css-multicol/going-out-of-flow-after-spanner.html [ Crash Failure Pass ]
-crbug.com/1079031 virtual/layout_ng_block_frag/external/wpt/css/css-multicol/multicol-containing-002.xht [ Crash Failure ]
 crbug.com/1079031 virtual/layout_ng_block_frag/external/wpt/css/css-multicol/multicol-fill-auto-002.xht [ Crash Failure ]
-crbug.com/1079031 virtual/layout_ng_block_frag/external/wpt/css/css-multicol/multicol-fill-balance-001.xht [ Crash Failure ]
 crbug.com/829028 virtual/layout_ng_block_frag/external/wpt/css/css-multicol/multicol-inherit-001.xht [ Failure ]
 crbug.com/829028 virtual/layout_ng_block_frag/external/wpt/css/css-multicol/multicol-inherit-002.xht [ Failure ]
 crbug.com/829028 virtual/layout_ng_block_frag/external/wpt/css/css-multicol/multicol-nested-002.xht [ Failure ]
@@ -1093,7 +1094,6 @@
 crbug.com/1079031 virtual/layout_ng_block_frag/fast/multicol/out-of-flow/abspos-auto-position-on-line-rtl.html [ Failure ]
 crbug.com/1079031 virtual/layout_ng_block_frag/fast/multicol/out-of-flow/nested-multicol.html [ Failure ]
 crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/overflowing-columns-large-gaps.html [ Failure ]
-crbug.com/1079031 virtual/layout_ng_block_frag/fast/multicol/positioned-outside-of-columns.html [ Crash Failure ]
 crbug.com/1079031 virtual/layout_ng_block_frag/fast/multicol/positioned-split.html [ Failure ]
 crbug.com/1058792 virtual/layout_ng_block_frag/fast/multicol/span/invalid-spanner-in-transform.html [ Failure Crash ]
 crbug.com/829028 virtual/layout_ng_block_frag/fast/multicol/span/outer-column-break-after-inner-spanner-2.html [ Failure ]
diff --git a/third_party/blink/web_tests/WebGPUExpectations b/third_party/blink/web_tests/WebGPUExpectations
index a6fb559..904879e 100644
--- a/third_party/blink/web_tests/WebGPUExpectations
+++ b/third_party/blink/web_tests/WebGPUExpectations
@@ -19,42 +19,17 @@
 # ****************************************************************************
 
 #
-# Test file splits (These expectations should all be Pass, but tell
+# Test file splits. These expectations should all be Pass, but they tell
 # regenerate_internal_cts_html.sh to run them (and siblings) as separate tests.
 #
 
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:* [ Pass ]
+wpt_internal/webgpu/cts.html?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="r8unorm";* [ Pass ]
+wpt_internal/webgpu/cts.html?q=webgpu:api,validation,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc1-rgba-unorm";* [ Pass ]
 
 #
 # Untriaged failures
 #
 
-wpt_internal/webgpu/cts.html?q=webgpu:api,operation,buffers,map_oom:mappedAtCreation,smaller_getMappedRange:* [ Failure ]
-wpt_internal/webgpu/cts.html?q=webgpu:api,operation,render_pass,storeOp:* [ Failure ]
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createBindGroup:buffer_binding_must_contain_exactly_one_buffer_of_its_type,* [ Failure ]
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createBindGroup:texture_binding_must_have_correct_usage,* [ Failure ]
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createBindGroupLayout:bindingTypeSpecific_optional_members,* [ Failure ]
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createBindGroupLayout:visibility,* [ Failure ]
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,copyBufferToBuffer:copy_with_invalid_buffer: [ Failure ]
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,encoding,cmds,compute_pass:* [ Failure ]
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,render_pass,storeOp:* [ Failure ]
-# Crash with validation layer
-wpt_internal/webgpu/cts.html?q=webgpu:api,operation,render_pipeline,primitive_topology:* [ Failure Crash ]
-
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,buffer,mapping:mapAsync,invalidBuffer:* [ Failure ]
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,buffer,mapping:mapAsync,offsetAndSizeAlignment,* [ Failure ]
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,buffer,mapping:mapAsync,offsetAndSizeOOB,* [ Failure ]
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,buffer,mapping:mapAsync,sizeUnspecifiedOOB,* [ Failure ]
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,buffer,mapping:mapAsync,state,* [ Failure ]
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,buffer,mapping:mapAsync,usage,* [ Failure ]
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,buffer,mapping:mapAsync_,* [ Failure ]
-
-# Precision. Need a better way to compare expected values
-wpt_internal/webgpu/cts.html?q=webgpu:util,texture,texelData:unorm_texel_data_in_shader:format="rgba8unorm-srgb";* [ Failure ]
-wpt_internal/webgpu/cts.html?q=webgpu:util,texture,texelData:unorm_texel_data_in_shader:format="bgra8unorm-srgb";* [ Failure ]
-wpt_internal/webgpu/cts.html?q=webgpu:util,texture,texelData:ufloat_texel_data_in_shader:format="rg11b10ufloat";* [ Failure ]
-wpt_internal/webgpu/cts.html?q=webgpu:util,texture,texelData:ufloat_texel_data_in_shader:format="rgb9e5ufloat";* [ Failure ]
-
 # Many formats failing on Windows
 [ Win ] wpt_internal/webgpu/cts.html?q=webgpu:api,operation,resource_init,texture_zero_init:uninitialized_texture_is_zero:readMethod="Sample";* [ Failure ]
 
@@ -71,7 +46,7 @@
 # Win missing resource state D3D12_RESOURCE_STATE_DEPTH_WRITE
 [ Linux ] wpt_internal/webgpu/cts.html?q=webgpu:api,operation,resource_init,texture_zero_init:uninitialized_texture_is_zero:readMethod="DepthTest";* [ Failure ]
 [ Mac ] wpt_internal/webgpu/cts.html?q=webgpu:api,operation,resource_init,texture_zero_init:uninitialized_texture_is_zero:readMethod="DepthTest";* [ Failure ]
-[ Win ] wpt_internal/webgpu/cts.html?q=webgpu:api,operation,resource_init,texture_zero_init:uninitialized_texture_is_zero:readMethod="DepthTest";* [ Slow Failure Crash ]
+[ Win ] wpt_internal/webgpu/cts.html?q=webgpu:api,operation,resource_init,texture_zero_init:uninitialized_texture_is_zero:readMethod="DepthTest";* [ Failure Crash Timeout ]
 
 # Crash with validation layer. May also be slow.
 # Missing D3D12_RESOURCE_STATE_DEPTH_WRITE
@@ -123,6 +98,43 @@
 crbug.com/1083478 [ Win ] wpt_internal/webgpu/webgpu/web_platform/reftests/canvas_clear.html [ Skip ]
 crbug.com/1083478 [ Win ] wpt_internal/webgpu/webgpu/web_platform/reftests/canvas_complex_bgra8unorm.html [ Skip ]
 
+# Spec was changed so BGLs should eagerly apply per-pipeline limits. Tests need fixing, then Dawn
+# needs to pass them. https://github.com/gpuweb/cts/issues/230
+wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createBindGroupLayout:max_resources_per_stage,in_bind_group_layout,* [ Failure ]
+
+# Precision. Need a better way to compare expected values
+wpt_internal/webgpu/cts.html?q=webgpu:util,texture,texelData:unorm_texel_data_in_shader:format="rgba8unorm-srgb";* [ Failure ]
+wpt_internal/webgpu/cts.html?q=webgpu:util,texture,texelData:unorm_texel_data_in_shader:format="bgra8unorm-srgb";* [ Failure ]
+wpt_internal/webgpu/cts.html?q=webgpu:util,texture,texelData:ufloat_texel_data_in_shader:format="rg11b10ufloat";* [ Failure ]
+wpt_internal/webgpu/cts.html?q=webgpu:util,texture,texelData:ufloat_texel_data_in_shader:format="rgb9e5ufloat";* [ Failure ]
+
+# Test is outdated relative to spec; need to fix the test first.
+wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createBindGroupLayout:bindingTypeSpecific_optional_members,* [ Skip ]
+
+#
+# Test bugs (fixed upstream)
+#
+
+# Tries to use depth32float as a color attachment.
+wpt_internal/webgpu/cts.html?q=webgpu:api,operation,render_pass,storeOp:* [ Failure ]
+
+# Missing an error scope wrapper around intentionally-error buffer.
+# Also breaks on the distinction between multisampled and non-multisampled texture bindings.
+wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createBindGroup:buffer_binding_must_contain_exactly_one_buffer_of_its_type,* [ Failure ]
+
+# Tries to create a multisampled storage texture.
+wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createBindGroup:texture_binding_must_have_correct_usage,* [ Failure ]
+
+# Neglects to set storageTextureFormat for storage texture bindings.
+wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createBindGroupLayout:visibility,* [ Failure ]
+
+# Outdated WGSL code.
+wpt_internal/webgpu/cts.html?q=webgpu:api,validation,encoding,cmds,compute_pass:* [ Failure ]
+
+# "Only CopyDst is allowed with MapRead", and uncaught promise rejections.
+wpt_internal/webgpu/cts.html?q=webgpu:api,validation,buffer,mapping:* [ Failure ]
+wpt_internal/webgpu/cts.html?q=webgpu:api,validation,copyBufferToBuffer:copy_with_invalid_buffer: [ Failure ]
+
 #
 # Platform-independent failures
 #
@@ -135,17 +147,20 @@
 crbug.com/dawn/375 wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createBindGroup:buffer_offset_and_size_for_bind_groups_match:offset=1024;size=0 [ Failure ]
 crbug.com/dawn/375 wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createBindGroup:buffer_offset_and_size_for_bind_groups_match:offset=1024;size="_undef_" [ Failure ]
 
-# Test doesn't check for an OOM error. gpuweb/cts#199 crbug.com/1014740 crbug.com/1014740
-# Actually passes on Windows NVIDIA which may be a Dawn bug.
-wpt_internal/webgpu/cts.html?q=webgpu:api,operation,buffers,map_oom:mapAsync:* [ Failure Crash ]
+crbug.com/dawn/608 wpt_internal/webgpu/cts.html?q=webgpu:api,operation,buffers,map_oom:mappedAtCreation,smaller_getMappedRange:* [ Failure ]
+
+crbug.com/dawn/609 wpt_internal/webgpu/cts.html?q=webgpu:api,operation,buffers,map_oom:mapAsync:* [ Failure Crash ]
+
+# Dawn is missing several validation rules about depthReadOnly/stencilReadOnly.
+wpt_internal/webgpu/cts.html?q=webgpu:api,validation,render_pass,storeOp:* [ Failure ]
+
+# Crash with validation layer.
+wpt_internal/webgpu/cts.html?q=webgpu:api,operation,render_pipeline,primitive_topology:* [ Failure Crash ]
 
 # Timeout on Windows/NVIDIA with backend validation
 # Dawn doesn't implement these limits yet
 wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createBindGroupLayout:max_resources_per_stage,in_pipeline_layout:* [ Failure Timeout ]
 
-# https://github.com/gpuweb/cts/issues/230 these tests need to be updated and Dawn will fail once we implement proper limits
-wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createBindGroupLayout:max_resources_per_stage,in_bind_group_layout,* [ Failure ]
-
 # Failure in both D3D12 and Vulkan validation layers
 wpt_internal/webgpu/cts.html?q=webgpu:api,validation,encoding,cmds,index_access:* [ Skip ]
 
@@ -159,7 +174,6 @@
 # Precision. Need a better way to compare expected values
 [ Mac ] wpt_internal/webgpu/cts.html?q=webgpu:util,texture,texelData:unorm_texel_data_in_shader:format="rgb10a2unorm";* [ Failure ]
 
-
 #
 # Linux (Vulkan) specific
 #
@@ -171,7 +185,8 @@
 [ Linux ] wpt_internal/webgpu/cts.html?worker=1&q=webgpu:api,operation,command_buffer,render,storeop:* [ Failure ]
 
 # Crash with backend validation.
-[ Linux ] wpt_internal/webgpu/cts.html?q=webgpu:api,operation,memory_sync,buffer,ww:* [ Failure Crash ]
+[ Linux ] wpt_internal/webgpu/cts.html?q=webgpu:api,operation,memory_sync,buffer,ww:* [ Failure Crash Timeout ]
+
 
 #
 # Windows (D3D12) specific
@@ -179,4 +194,3 @@
 
 # Very flaky on Windows/Linux, especially (but not exclusively!) with backend validation
 crbug.com/1087130 [ Win ] wpt_internal/webgpu/cts.html?q=webgpu:api,validation,createView:* [ RetryOnFailure ]
-
diff --git a/third_party/blink/web_tests/animations/svg/animated-filter-svg-element-expected.html b/third_party/blink/web_tests/animations/svg/animated-filter-svg-element-expected.html
index ac44e0d..4f588185 100644
--- a/third_party/blink/web_tests/animations/svg/animated-filter-svg-element-expected.html
+++ b/third_party/blink/web_tests/animations/svg/animated-filter-svg-element-expected.html
@@ -1,4 +1,4 @@
 <!doctype html>
 <div style="width: 100px; height: 100px; background-color: blue; filter: drop-shadow(10px 10px black)"></div>
 <br>
-<div style="width: 100px; height: 100px; background-color: blue"></div>
+<div style="width: 100px; height: 100px; background-color: blue; filter: drop-shadow(10px 10px black)"></div>
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 6092084..968f3e6 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
@@ -52668,7 +52668,7 @@
       ]
      ],
      "out-of-flow-in-multicolumn-001.html": [
-      "370561f3362bfec6d2ea9d6a0ba5b71ffbb00e70",
+      "33036d99d33bfc767eee8c3946b0299d9807515d",
       [
        null,
        [
@@ -52681,7 +52681,7 @@
       ]
      ],
      "out-of-flow-in-multicolumn-002.html": [
-      "bc91fe11c6975eb6ea9fbe274a0a93d596efff5f",
+      "b5fa72b33297990a89cfbc45229eaf0fabf746ba",
       [
        null,
        [
@@ -52694,7 +52694,7 @@
       ]
      ],
      "out-of-flow-in-multicolumn-003.html": [
-      "1eac0b9a67f385cb118f60174678ea0070621eb8",
+      "c8e1b6f3cbbcecf7053ed0dcbdb2ca04a677f078",
       [
        null,
        [
@@ -52720,7 +52720,7 @@
       ]
      ],
      "out-of-flow-in-multicolumn-005.html": [
-      "6f9a1641be65619e94cf06e29ca20db22becd592",
+      "3917db44daf06a906382349418dc3d2989c810af",
       [
        null,
        [
@@ -52733,7 +52733,7 @@
       ]
      ],
      "out-of-flow-in-multicolumn-006.html": [
-      "8138b429a40d2dda9ac3a30f0970e5c00be7af58",
+      "7d1803e4183751562f53c294c865a2750d8b8a5d",
       [
        null,
        [
@@ -52746,7 +52746,7 @@
       ]
      ],
      "out-of-flow-in-multicolumn-007.html": [
-      "934f12c0cbec3555fdb56d6121c343169af5808a",
+      "a6e68a08e102473b40cd91492baf3bf24088377e",
       [
        null,
        [
@@ -52759,7 +52759,7 @@
       ]
      ],
      "out-of-flow-in-multicolumn-008.html": [
-      "3e665b3564c4edf374d9fd6611fe6cd4f8e77678",
+      "0c1405dd30fb13ff698637a758e254a72057442e",
       [
        null,
        [
@@ -52772,7 +52772,7 @@
       ]
      ],
      "out-of-flow-in-multicolumn-009.html": [
-      "ac278953b0857934d65b52ff0d2b3d00d7854f3b",
+      "88b8d4886698a1cd3be8024020f39aedf5ac885d",
       [
        null,
        [
@@ -52785,7 +52785,7 @@
       ]
      ],
      "out-of-flow-in-multicolumn-010.html": [
-      "76f7f2d1e34f55a6c9fae74a4bbe9af7104024e6",
+      "708b13400b8da2d42e8a5457a4cb341cc3210f6c",
       [
        null,
        [
@@ -52798,7 +52798,7 @@
       ]
      ],
      "out-of-flow-in-multicolumn-011.html": [
-      "8432c1afde9164b2b6d277c616e037ca6c0bc402",
+      "93350899950a11631484564027cad7d458f8f39b",
       [
        null,
        [
@@ -86544,6 +86544,19 @@
       ]
      },
      "mask-svg-content": {
+      "mask-empty-container-with-filter.svg": [
+       "ebe7e7e4d1cecd5b8c8343cdac85be644724a24f",
+       [
+        null,
+        [
+         [
+          "/css/css-masking/mask-svg-content/reference/mask-green-square-001-ref.svg",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "mask-negative-scale.svg": [
        "36b7abb42eb157b9feff158c6dfb399249ee437c",
        [
@@ -87561,6 +87574,19 @@
        {}
       ]
      ],
+     "multicol-containing-003.html": [
+      "c190385751e56e157d0f349c0b732f322e6c3b44",
+      [
+       null,
+       [
+        [
+         "/css/reference/ref-filled-green-100px-square.xht",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "multicol-count-001.xht": [
       "eb3272f9a4e68500fd846ae62958aac397037433",
       [
@@ -147350,6 +147376,201 @@
        {}
       ]
      ],
+     "svg-filter-vs-clip-path.html": [
+      "0e17117e355c91c4b59230163999bf9edde6b4ae",
+      [
+       null,
+       [
+        [
+         "/css/filter-effects/reference/green-100x100.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "svg-filter-vs-mask.html": [
+      "279db20022df4252808d0ecd346c676efcc173b6",
+      [
+       null,
+       [
+        [
+         "/css/filter-effects/reference/green-100x100.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "svg-multiple-filter-functions.html": [
+      "d1b182a1c603b8f03c21bc16e9ec0c687a619e9b",
+      [
+       null,
+       [
+        [
+         "/css/filter-effects/reference/green-100x100.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "svg-mutation-drop-shadow-color.html": [
+      "fe8bf7ec5fe284608a4ba329681a12c17c82437d",
+      [
+       null,
+       [
+        [
+         "/css/filter-effects/reference/green-100x100.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "svg-mutation-drop-shadow-offset.html": [
+      "2d5a12906d89a8fcd09ffb19e310e32da42441a1",
+      [
+       null,
+       [
+        [
+         "/css/filter-effects/reference/green-100x100.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "svg-mutation-function-to-url.html": [
+      "61d657bfb2b3f80884a81d7b9dac5597d02dbff3",
+      [
+       null,
+       [
+        [
+         "/css/filter-effects/reference/green-100x100.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "svg-mutation-group-position-changed.html": [
+      "5a73f6eefc04343fbe73cfc5ccfdff5b86050f87",
+      [
+       null,
+       [
+        [
+         "/css/filter-effects/reference/green-100x100.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "svg-mutation-group-size-changed.html": [
+      "0486ec0806ba697da4ad3d7a62e6f0dcd7d1c2ff",
+      [
+       null,
+       [
+        [
+         "/css/filter-effects/reference/green-100x100.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "svg-mutation-group-transform-changed.html": [
+      "f0ff16e7c8932f68c5c53955cab4fd500d445401",
+      [
+       null,
+       [
+        [
+         "/css/filter-effects/reference/green-100x100.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "svg-mutation-object-position-changed.html": [
+      "76b75fc329868cb1597dd375052653e135c8c3eb",
+      [
+       null,
+       [
+        [
+         "/css/filter-effects/reference/green-100x100.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "svg-mutation-object-size-changed.html": [
+      "2d55387b73f91b347f5a48e12f256208e2a215b0",
+      [
+       null,
+       [
+        [
+         "/css/filter-effects/reference/green-100x100.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "svg-mutation-object-transform-changed.html": [
+      "75a82b1d964cc3131322c1e26b193b905cd1f4ef",
+      [
+       null,
+       [
+        [
+         "/css/filter-effects/reference/green-100x100.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "svg-mutation-single-to-multiple-001.html": [
+      "13da58c03ac26078fa0ad8be0ccfc690a4717dc3",
+      [
+       null,
+       [
+        [
+         "/css/filter-effects/reference/green-100x100.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "svg-mutation-single-to-multiple-002.html": [
+      "d7769a7cfd6a0986c15a40c0df8ca96a16069c7d",
+      [
+       null,
+       [
+        [
+         "/css/filter-effects/reference/green-100x100.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "svg-mutation-url-to-function.html": [
+      "fb08d8409ed382324c8752f9587c8d3244632a56",
+      [
+       null,
+       [
+        [
+         "/css/filter-effects/reference/green-100x100.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "svg-relative-urls-001.html": [
       "5dd382c6dfd2271449627e956f7723e810662cee",
       [
@@ -147376,6 +147597,32 @@
        {}
       ]
      ],
+     "svg-shorthand-drop-shadow-001.html": [
+      "0d05046807384ff0c2d14f29c9cffeb6f33e46e9",
+      [
+       null,
+       [
+        [
+         "/css/filter-effects/reference/green-100x100.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
+     "svg-shorthand-hue-rotate-001.html": [
+      "34f9b5c76d4f474fa3349946f40e097c4e7b3707",
+      [
+       null,
+       [
+        [
+         "/css/filter-effects/reference/green-100x100.html",
+         "=="
+        ]
+       ],
+       {}
+      ]
+     ],
      "svg-sourcegraphic-currentcolor-dynamic-001.html": [
       "e3be6544dc803ba7d9c69e9a1d906296c2c15301",
       [
@@ -255645,7 +255892,7 @@
       []
      ],
      "requirements.txt": [
-      "5cfa9f3faf9c0088348c78b4030df450989066b7",
+      "a0b9b2df9f7dc4654f25e510498da706cff9cda8",
       []
      ],
      "requirements_android_webview.txt": [
@@ -255677,7 +255924,7 @@
       []
      ],
      "requirements_firefox.txt": [
-      "622c34dcb038347db4f58fa3c69f00ffd0c3e280",
+      "43245f992d4a406ef158c0809fc4e742a738c7c4",
       []
      ],
      "requirements_ie.txt": [
@@ -255723,11 +255970,11 @@
         []
        ],
        "android_weblayer.py": [
-        "ca93004b6e75822a6dbae7d2d4beacacd94f86e7",
+        "f68312f231bba4f08aba7defbc272a86e98af244",
         []
        ],
        "android_webview.py": [
-        "27a09f5d2cdeb5557118a059e0dcb2a88f967c1b",
+        "3cde248b4465cd10a86a813de8551808c42dbf18",
         []
        ],
        "base.py": [
@@ -255739,7 +255986,7 @@
         []
        ],
        "chrome_android.py": [
-        "607b783566e1b751dc9d37936a6c64f4d843e3df",
+        "d7e3e21012169fdf12e47d3bc87552f46c779cf9",
         []
        ],
        "chrome_ios.py": [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-001.html b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-001.html
index 370561f..33036d99 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-001.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-001.html
@@ -3,7 +3,6 @@
 <link rel="help" href="href=https://www.w3.org/TR/css-break-3/#break-decoration">
 <link rel="match" href="out-of-flow-in-multicolumn-001-ref.html">
 
-<p>The abs element should be split equally into the two columns - no red!</p>
 <style>
   #multicol {
       column-count: 2;
@@ -28,6 +27,7 @@
     background: red;
   }
 </style>
+<p>The abs element should be split equally into the two columns - no red!</p>
 <div id="container">
   <div id="multicol">
       <div style="width:100px; height:30px;"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-002.html b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-002.html
index bc91fe1..b5fa72b3 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-002.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-002.html
@@ -2,7 +2,6 @@
 <link rel="help" href="href=https://www.w3.org/TR/css-break-3/#break-decoration">
 <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
 <!-- Tests fragmentation when a positioned node's child overflows. -->
-<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
 <style>
   #multicol {
     column-count: 2;
@@ -23,6 +22,7 @@
     background: green;
   }
 </style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
 <div id="multicol">
   <div class="rel">
     <div class="abs">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-003.html b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-003.html
index 1eac0b9..c8e1b6f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-003.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-003.html
@@ -4,7 +4,6 @@
 <!-- Tests that empty column fragments are added if an OOF element begins layout
      in a fragmentainer that is more than one index beyond the last existing
      column fragmentainer. -->
-<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
 <style>
   #multicol {
     column-count: 2;
@@ -27,6 +26,7 @@
     background: green;
   }
 </style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
 <div id="multicol">
   <div class="rel">
     <div class="abs"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-005.html b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-005.html
index 6f9a164..3917db4 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-005.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-005.html
@@ -2,7 +2,6 @@
 <link rel="help" href="href=https://www.w3.org/TR/css-break-3/#breaking-controls">
 <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
 <!-- break-after: column does not apply to absolute positioned elements. -->
-<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
 <style>
   #multicol {
     column-count: 2;
@@ -29,6 +28,7 @@
     background: green;
   }
 </style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
 <div id="multicol">
   <div class="content"></div>
   <div class="rel">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-006.html b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-006.html
index 8138b42..7d1803e 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-006.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-006.html
@@ -2,7 +2,6 @@
 <link rel="help" href="href=https://www.w3.org/TR/css-position-3/#abspos-breaking">
 <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
 <!-- Tests that the fragments of a positioned element are added to the right fragmentainer despite the presence of column spanners. -->
-<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
 <style>
   #multicol {
     column-count: 2;
@@ -25,12 +24,13 @@
     column-span: all;
     height: 5px;
   }
- </style>
- <div id="multicol">
-   <div class="rel">
-     <div class="spanner"></div>
-     <div style="height: 60px; "></div>
-     <div class="spanner"></div>
-     <div class="abs"></div>
-   </div>
- </div>
+</style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div id="multicol">
+  <div class="rel">
+    <div class="spanner"></div>
+    <div style="height: 60px; "></div>
+    <div class="spanner"></div>
+    <div class="abs"></div>
+  </div>
+</div>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-007.html b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-007.html
index 934f12c..a6e68a0 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-007.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-007.html
@@ -3,7 +3,6 @@
 <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
 <!-- Tests that a positioned element without a top or bottom property uses the static position -
      even though it's treated as an OOF element. -->
-<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
 <style>
   #multicol {
     column-count: 2;
@@ -25,9 +24,10 @@
     background: green;
   }
 </style>
- <div id="multicol">
-   <div class="rel">
-     <div style="height: 100px; width: 50px;"></div>
-     <div class="abs"></div>
-   </div>
- </div>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div id="multicol">
+  <div class="rel">
+    <div style="height: 100px; width: 50px;"></div>
+    <div class="abs"></div>
+  </div>
+</div>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-008.html b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-008.html
index 3e665b3..0c1405d 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-008.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-008.html
@@ -2,7 +2,6 @@
 <link rel="help" href="href=https://www.w3.org/TR/css-position-3/#abspos-breaking">
 <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
 <!-- Tests fragmented abspos elements with a spanner nested inside. -->
-<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
 <style>
   #multicol {
     column-count: 2;
@@ -25,6 +24,7 @@
     height: 10px;
   }
 </style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
 <div id="multicol">
   <div class="rel">
     <div class="abs">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-009.html b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-009.html
index ac278953..88b8d48 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-009.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-009.html
@@ -2,7 +2,6 @@
 <link rel="help" href="href=https://www.w3.org/TR/css-position-3/#abspos-breaking">
 <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
 <!-- Tests that empty column fragments are added if an OOF element begins layout in a fragmentainer that is more than one index beyond the last existing column fragmentainer in the presence of a spanner. -->
-<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
 <style>
   #multicol {
     column-count: 2;
@@ -23,6 +22,7 @@
     background: green;
   }
 </style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
 <div id="multicol">
   <div class="rel">
     <div class="abs"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-010.html b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-010.html
index 76f7f2d1..708b134 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-010.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-010.html
@@ -2,7 +2,6 @@
 <link rel="help" href="href=https://www.w3.org/TR/css-position-3/#abspos-breaking">
 <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
 <!-- Fragmented OOF element with block-size percentage resolution. -->
-<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
 <style>
   #multicol {
     column-count: 3;
@@ -30,6 +29,7 @@
     height: 33.33%;
   }
 </style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
 <div id="multicol">
   <div class="rel">
     <div class="abs"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-011.html b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-011.html
index 8432c1a..9335089 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-011.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-011.html
@@ -2,7 +2,6 @@
 <link rel="help" href="href=https://www.w3.org/TR/css-position-3/#abspos-breaking">
 <link rel="match" href="../reference/ref-filled-green-100px-square.xht">
 <!-- Fragmented OOF element with block-size percentage resolution and overflow. -->
-<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
 <style>
   #multicol {
     /* Set things up so that the absolutely positioned element takes up two
@@ -26,6 +25,7 @@
     background: green;
   }
 </style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
 <div id="multicol">
   <div style="height: 100px;"></div>
   <div class="rel">
diff --git a/third_party/blink/web_tests/external/wpt/css/css-masking/mask-svg-content/mask-empty-container-with-filter.svg b/third_party/blink/web_tests/external/wpt/css/css-masking/mask-svg-content/mask-empty-container-with-filter.svg
new file mode 100644
index 0000000..ebe7e7e4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-masking/mask-svg-content/mask-empty-container-with-filter.svg
@@ -0,0 +1,23 @@
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:h="http://www.w3.org/1999/xhtml">
+  <title>mask with only an empty container with a filter</title>
+  <h:link rel="help" href="https://drafts.fxtf.org/css-masking-1/#svg-masks"/>
+  <h:link rel="match" href="reference/mask-green-square-001-ref.svg"/>
+
+  <filter id="double" x="0" y="0" width="200" height="200" filterUnits="userSpaceOnUse">
+    <feOffset dy="100"/>
+    <feMerge>
+      <feMergeNode/>
+      <feMergeNode in="SourceGraphic"/>
+    </feMerge>
+  </filter>
+  <filter id="f" x="0" y="0" width="200" height="200" filterUnits="userSpaceOnUse">
+    <feFlood flood-color="#fff"/>
+  </filter>
+  <mask id="m" x="50" y="50" width="100" height="100" maskUnits="userSpaceOnUse">
+    <g filter="url(#f)"/>
+  </mask>
+
+  <rect width="100" height="200" fill="green" mask="url(#m)"/>
+  <rect width="100" height="100" x="100" fill="green" mask="url(#m)"
+	filter="url(#double)"/>
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-containing-003.html b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-containing-003.html
new file mode 100644
index 0000000..c190385
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-multicol/multicol-containing-003.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<link rel="help" href="https://drafts.csswg.org/css-multicol/#the-multi-column-model">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<style>
+  #multicol {
+    columns: 2;
+    width: 100px;
+    height: 100px;
+    column-fill: auto;
+    column-gap: 0px;
+  }
+  .rel {
+    position: relative;
+  }
+  .abs {
+    position: absolute;
+    width: 100px;
+    height: 100px;
+    background: green;
+    top: 0;
+    left: 0;
+  }
+</style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div class="rel" id="multicol">
+  <div style="height:200px; width: 50px; background: red;"></div>
+  <div class="abs"></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-filter-vs-clip-path.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-filter-vs-clip-path.html
new file mode 100644
index 0000000..0e17117
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-filter-vs-clip-path.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>Filter Effects: 'filter' and 'clip-path' on SVG element</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#placement">
+<link rel="match" href="reference/green-100x100.html">
+<svg>
+  <clipPath id="c">
+    <rect width="100" height="100"/>
+  </clipPath>
+  <rect width="100" height="100" fill="red"
+	filter="blur(20px)" clip-path="url(#c)"/>
+  <rect width="100" height="100" fill="green"/>
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-filter-vs-mask.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-filter-vs-mask.html
new file mode 100644
index 0000000..279db20
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-filter-vs-mask.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<title>Filter Effects: 'filter' and 'mask' on SVG element</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#placement">
+<link rel="match" href="reference/green-100x100.html">
+<svg>
+  <mask id="m">
+    <rect width="100" height="100" fill="white"/>
+  </mask>
+  <rect width="100" height="100" fill="red"
+	filter="blur(20px)" mask="url(#m)"/>
+  <rect width="100" height="100" fill="green"/>
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-multiple-filter-functions.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-multiple-filter-functions.html
new file mode 100644
index 0000000..d1b182a1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-multiple-filter-functions.html
@@ -0,0 +1,22 @@
+<!doctype html>
+<title>Filter Effects: filter with multiple filter functions on SVG element</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#filter-functions">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterElement">
+<link rel="match" href="reference/green-100x100.html">
+<svg>
+  <filter id="f_left" x="0" y="0" width="1" height="1"
+	  color-interpolation-filters="sRGB">
+    <feFlood flood-color="rgb(71.79%, 28.82%, 0%)" width="50"/>
+  </filter>
+  <filter id="f_right" x="0" y="0" width="1" height="1"
+	  color-interpolation-filters="sRGB">
+    <feFlood flood-color="rgb(71.79%, 28.82%, 0%)" x="50" width="50"/>
+    <feMerge>
+      <feMergeNode in="SourceGraphic"/>
+      <feMergeNode/>
+    </feMerge>
+  </filter>
+  <rect width="100" height="100" fill="red"
+	filter="url(#f_left) url(#f_right) hue-rotate(90deg)"/>
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-drop-shadow-color.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-drop-shadow-color.html
new file mode 100644
index 0000000..fe8bf7ec
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-drop-shadow-color.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>Filter Effects: changing color of drop-shadow() function on an SVG element</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter-drop-shadow">
+<link rel="match" href="reference/green-100x100.html">
+<script src="/common/rendering-utils.js"></script>
+<script src="/common/reftest-wait.js"></script>
+<svg>
+  <rect width="100" height="100" fill="red"/>
+  <rect id="target" width="50" height="100" fill="green" filter="drop-shadow(50px 0 red)"/>
+</svg>
+<script>
+  waitForAtLeastOneFrame().then(() => {
+    let rect = document.getElementById("target");
+    rect.setAttribute("filter", "drop-shadow(50px 0 green)");
+    takeScreenshot();
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-drop-shadow-offset.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-drop-shadow-offset.html
new file mode 100644
index 0000000..2d5a1290
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-drop-shadow-offset.html
@@ -0,0 +1,18 @@
+<!doctype html>
+<title>Filter Effects: changing offset of drop-shadow() function on an SVG element</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter-drop-shadow">
+<link rel="match" href="reference/green-100x100.html">
+<script src="/common/rendering-utils.js"></script>
+<script src="/common/reftest-wait.js"></script>
+<svg>
+  <rect width="100" height="100" fill="red"/>
+  <rect id="target" width="50" height="100" fill="green" filter="drop-shadow(5px 0 green)"/>
+</svg>
+<script>
+  waitForAtLeastOneFrame().then(() => {
+    let rect = document.getElementById("target");
+    rect.setAttribute("filter", "drop-shadow(50px 0 green)");
+    takeScreenshot();
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-function-to-url.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-function-to-url.html
new file mode 100644
index 0000000..61d657bf
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-function-to-url.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>Filter Effects: switching from hue-rotate() to url() on an SVG element</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#filter-functions">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterElement">
+<link rel="match" href="reference/green-100x100.html">
+<script src="/common/rendering-utils.js"></script>
+<script src="/common/reftest-wait.js"></script>
+<svg>
+  <filter id="hue" color-interpolation-filters="sRGB">
+    <feColorMatrix type="hueRotate" values="90"/>
+  </filter>
+  <rect width="100" height="100" fill="rgb(71.79%, 28.82%, 0%)" filter="hue-rotate(330deg)"/>
+</svg>
+<script>
+  waitForAtLeastOneFrame().then(() => {
+    let rect = document.querySelector("svg > rect");
+    rect.setAttribute("filter", "url(#hue)");
+    takeScreenshot();
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-group-position-changed.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-group-position-changed.html
new file mode 100644
index 0000000..5a73f6e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-group-position-changed.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>Filter Effects: changing the position of an SVG group with filter</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter-drop-shadow">
+<link rel="match" href="reference/green-100x100.html">
+<script src="/common/rendering-utils.js"></script>
+<script src="/common/reftest-wait.js"></script>
+<svg>
+  <rect width="100" height="100" fill="red"/>
+  <g filter="drop-shadow(-50px 0 green)">
+    <rect id="target" width="50" height="100" fill="green"/>
+  </g>
+</svg>
+<script>
+  waitForAtLeastOneFrame().then(() => {
+    let rect = document.getElementById("target");
+    rect.setAttribute("x", "50");
+    takeScreenshot();
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-group-size-changed.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-group-size-changed.html
new file mode 100644
index 0000000..0486ec0
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-group-size-changed.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>Filter Effects: changing the size of an SVG group with filter</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter-drop-shadow">
+<link rel="match" href="reference/green-100x100.html">
+<script src="/common/rendering-utils.js"></script>
+<script src="/common/reftest-wait.js"></script>
+<svg>
+  <rect width="100" height="100" fill="red"/>
+  <g filter="drop-shadow(50px 0 green)">
+    <rect id="target" width="50" height="50" fill="green"/>
+  </g>
+</svg>
+<script>
+  waitForAtLeastOneFrame().then(() => {
+    let rect = document.getElementById("target");
+    rect.setAttribute("height", "100");
+    takeScreenshot();
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-group-transform-changed.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-group-transform-changed.html
new file mode 100644
index 0000000..f0ff16e7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-group-transform-changed.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>Filter Effects: changing the transform of an SVG group with filter</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter-drop-shadow">
+<link rel="match" href="reference/green-100x100.html">
+<script src="/common/rendering-utils.js"></script>
+<script src="/common/reftest-wait.js"></script>
+<svg>
+  <rect width="100" height="100" fill="red"/>
+  <g id="target" filter="drop-shadow(-50px 0 green)">
+    <rect width="50" height="100" fill="green"/>
+  </g>
+</svg>
+<script>
+  waitForAtLeastOneFrame().then(() => {
+    let group = document.getElementById("target");
+    group.setAttribute("transform", "translate(50, 0)");
+    takeScreenshot();
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-object-position-changed.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-object-position-changed.html
new file mode 100644
index 0000000..76b75fc
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-object-position-changed.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>Filter Effects: changing the position of an SVG element with filter</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter-drop-shadow">
+<link rel="match" href="reference/green-100x100.html">
+<script src="/common/rendering-utils.js"></script>
+<script src="/common/reftest-wait.js"></script>
+<svg>
+  <rect width="100" height="100" fill="red"/>
+  <rect id="target" width="50" height="100" fill="green"
+	filter="drop-shadow(-50px 0 green)"/>
+</svg>
+<script>
+  waitForAtLeastOneFrame().then(() => {
+    let rect = document.getElementById("target");
+    rect.setAttribute("x", "50");
+    takeScreenshot();
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-object-size-changed.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-object-size-changed.html
new file mode 100644
index 0000000..2d55387b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-object-size-changed.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>Filter Effects: changing the size of an SVG element with filter</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter-drop-shadow">
+<link rel="match" href="reference/green-100x100.html">
+<script src="/common/rendering-utils.js"></script>
+<script src="/common/reftest-wait.js"></script>
+<svg>
+  <rect width="100" height="100" fill="red"/>
+  <rect id="target" width="50" height="50" fill="green"
+	filter="drop-shadow(50px 0 green)"/>
+</svg>
+<script>
+  waitForAtLeastOneFrame().then(() => {
+    let rect = document.getElementById("target");
+    rect.setAttribute("height", "100");
+    takeScreenshot();
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-object-transform-changed.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-object-transform-changed.html
new file mode 100644
index 0000000..75a82b1
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-object-transform-changed.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<title>Filter Effects: changing the transform of an SVG element with filter</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter-drop-shadow">
+<link rel="match" href="reference/green-100x100.html">
+<script src="/common/rendering-utils.js"></script>
+<script src="/common/reftest-wait.js"></script>
+<svg>
+  <rect width="100" height="100" fill="red"/>
+  <rect id="target" width="50" height="100" fill="green"
+	filter="drop-shadow(-50px 0 green)"/>
+</svg>
+<script>
+  waitForAtLeastOneFrame().then(() => {
+    let rect = document.getElementById("target");
+    rect.setAttribute("transform", "translate(50, 0)");
+    takeScreenshot();
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-single-to-multiple-001.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-single-to-multiple-001.html
new file mode 100644
index 0000000..13da58c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-single-to-multiple-001.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<title>Filter Effects: extending the filter chain with an additional function on SVG element</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter-drop-shadow">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter-hue-rotate">
+<link rel="match" href="reference/green-100x100.html">
+<script src="/common/rendering-utils.js"></script>
+<script src="/common/reftest-wait.js"></script>
+<svg>
+  <rect width="100" height="100" fill="red"/>
+  <rect id="target" width="50" height="100" fill="rgb(71.79%, 28.82%, 0%)"
+	filter="hue-rotate(90deg)"/>
+</svg>
+<script>
+  waitForAtLeastOneFrame().then(() => {
+    let rect = document.getElementById("target");
+    rect.setAttribute("filter", "hue-rotate(90deg) drop-shadow(50px 0 green)");
+    takeScreenshot();
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-single-to-multiple-002.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-single-to-multiple-002.html
new file mode 100644
index 0000000..d7769a7
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-single-to-multiple-002.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>Filter Effects: extending the filter chain with an additional function on SVG element</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter-drop-shadow">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#feColorMatrixElement">
+<link rel="match" href="reference/green-100x100.html">
+<script src="/common/rendering-utils.js"></script>
+<script src="/common/reftest-wait.js"></script>
+<svg>
+  <filter id="hue" color-interpolation-filters="sRGB">
+    <feColorMatrix type="hueRotate" values="90"/>
+  </filter>
+  <rect width="100" height="100" fill="red"/>
+  <rect id="target" width="50" height="100" fill="rgb(71.79%, 28.82%, 0%)"
+	filter="url(#hue)"/>
+</svg>
+<script>
+  waitForAtLeastOneFrame().then(() => {
+    let rect = document.getElementById("target");
+    rect.setAttribute("filter", "url(#hue) drop-shadow(50px 0 green)");
+    takeScreenshot();
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-url-to-function.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-url-to-function.html
new file mode 100644
index 0000000..fb08d840
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-mutation-url-to-function.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<title>Filter Effects: switching from url() to hue-rotate() on an SVG element</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#filter-functions">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterElement">
+<link rel="match" href="reference/green-100x100.html">
+<script src="/common/rendering-utils.js"></script>
+<script src="/common/reftest-wait.js"></script>
+<svg>
+  <filter id="hue" color-interpolation-filters="sRGB">
+    <feColorMatrix type="hueRotate" values="330"/>
+  </filter>
+  <rect width="100" height="100" fill="rgb(71.79%, 28.82%, 0%)" filter="url(#hue)"/>
+</svg>
+<script>
+  waitForAtLeastOneFrame().then(() => {
+    let rect = document.querySelector("svg > rect");
+    rect.setAttribute("filter", "hue-rotate(90deg)");
+    takeScreenshot();
+  });
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-shorthand-drop-shadow-001.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-shorthand-drop-shadow-001.html
new file mode 100644
index 0000000..0d050468
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-shorthand-drop-shadow-001.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>Filter Effects: drop-shadow() function on SVG element</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter-drop-shadow">
+<link rel="match" href="reference/green-100x100.html">
+<svg>
+  <rect width="100" height="100" fill="red"/>
+  <rect width="50" height="100" fill="green" filter="drop-shadow(50px 0 green)"/>
+</svg>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-shorthand-hue-rotate-001.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-shorthand-hue-rotate-001.html
new file mode 100644
index 0000000..34f9b5c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/svg-shorthand-hue-rotate-001.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>Filter Effects: hue-rotate() function on SVG element</title>
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#funcdef-filter-hue-rotate">
+<link rel="match" href="reference/green-100x100.html">
+<svg>
+  <rect width="100" height="100" fill="rgb(71.79%, 28.82%, 0%)" filter="hue-rotate(90deg)"/>
+</svg>
+
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt b/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt
index 5cfa9f3..a0b9b2d 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements.txt
@@ -1,6 +1,6 @@
 html5lib==1.1
 mozinfo==1.2.1  # https://bugzilla.mozilla.org/show_bug.cgi?id=1621226
-mozlog==7.0.1
+mozlog==7.1.0
 mozdebug==0.2
 # Pillow 7 requires Python 3
 pillow==6.2.2; python_version <= '2.7'  # pyup: <7.0
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements_firefox.txt b/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements_firefox.txt
index 622c34dc..43245f99 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements_firefox.txt
+++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/requirements_firefox.txt
@@ -5,6 +5,6 @@
 moznetwork==1.1.0
 mozprocess==1.2.1
 mozprofile==2.5.0
-mozrunner==8.0.3
+mozrunner==8.1.0
 mozversion==2.3.0
-psutil==5.7.3
+psutil==5.8.0
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/js-late-mask-and-object-creation-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/js-late-mask-and-object-creation-expected.txt
index 50911ea2..4c9e0dc 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/js-late-mask-and-object-creation-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/js-late-mask-and-object-creation-expected.txt
@@ -6,7 +6,7 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [0, 100, 800, 100]
+        [0, 0, 800, 300]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/js-late-mask-creation-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/js-late-mask-creation-expected.txt
index 50911ea2..4c9e0dc 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/js-late-mask-creation-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/js-late-mask-creation-expected.txt
@@ -6,7 +6,7 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [0, 100, 800, 100]
+        [0, 0, 800, 300]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/mask-child-changes-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/mask-child-changes-expected.txt
index 50911ea2..4c9e0dc 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/mask-child-changes-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/mask-child-changes-expected.txt
@@ -6,7 +6,7 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [0, 100, 800, 100]
+        [0, 0, 800, 300]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/mask-clip-target-transform-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/mask-clip-target-transform-expected.txt
index 3dbdf70..6f12a005 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/mask-clip-target-transform-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/mask-clip-target-transform-expected.txt
@@ -6,7 +6,8 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [150, 50, 100, 100],
+        [0, 0, 340, 120],
+        [80, 0, 240, 340],
         [50, 150, 100, 100]
       ]
     }
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/mask-invalidation-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/mask-invalidation-expected.txt
index ce440a6..51f97ecd 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/mask-invalidation-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/mask-invalidation-expected.txt
@@ -6,8 +6,7 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [50, 50, 453, 299],
-        [200, 100, 403, 249]
+        [0, 0, 800, 600]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/resource-invalidate-on-target-update-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/resource-invalidate-on-target-update-expected.txt
index 5badbc6b..2389907 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/resource-invalidate-on-target-update-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/resource-invalidate-on-target-update-expected.txt
@@ -6,9 +6,9 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
+        [0, 0, 230, 120],
         [0, 240, 222, 120],
-        [10, 130, 200, 100],
-        [10, 10, 200, 100]
+        [10, 130, 200, 100]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/text-mask-update-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/text-mask-update-expected.txt
index 5d86f2ac..c91dd5b 100644
--- a/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/text-mask-update-expected.txt
+++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/paint/invalidation/svg/text-mask-update-expected.txt
@@ -6,8 +6,7 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [10, 3, 45, 22],
-        [10, 33, 43, 17]
+        [0, 0, 110, 55]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/forms/select/select-multiple-rtl-expected.png b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/forms/select/select-multiple-rtl-expected.png
index 012f167e..12f6b4d 100644
--- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/forms/select/select-multiple-rtl-expected.png
+++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/fast/forms/select/select-multiple-rtl-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/images/color-profile-mask-image-svg-expected.png b/third_party/blink/web_tests/images/color-profile-mask-image-svg-expected.png
index c94f52c..e71c32a 100644
--- a/third_party/blink/web_tests/images/color-profile-mask-image-svg-expected.png
+++ b/third_party/blink/web_tests/images/color-profile-mask-image-svg-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/paint/invalidation/svg/js-late-mask-and-object-creation-expected.txt b/third_party/blink/web_tests/paint/invalidation/svg/js-late-mask-and-object-creation-expected.txt
index 769ae10..8e00193 100644
--- a/third_party/blink/web_tests/paint/invalidation/svg/js-late-mask-and-object-creation-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/svg/js-late-mask-and-object-creation-expected.txt
@@ -6,7 +6,7 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [0, 100, 800, 100]
+        [0, 0, 800, 300]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/paint/invalidation/svg/js-late-mask-creation-expected.txt b/third_party/blink/web_tests/paint/invalidation/svg/js-late-mask-creation-expected.txt
index 769ae10..8e00193 100644
--- a/third_party/blink/web_tests/paint/invalidation/svg/js-late-mask-creation-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/svg/js-late-mask-creation-expected.txt
@@ -6,7 +6,7 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [0, 100, 800, 100]
+        [0, 0, 800, 300]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/paint/invalidation/svg/mask-child-changes-expected.txt b/third_party/blink/web_tests/paint/invalidation/svg/mask-child-changes-expected.txt
index 769ae10..8e00193 100644
--- a/third_party/blink/web_tests/paint/invalidation/svg/mask-child-changes-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/svg/mask-child-changes-expected.txt
@@ -6,7 +6,7 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [0, 100, 800, 100]
+        [0, 0, 800, 300]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/paint/invalidation/svg/mask-clip-target-transform-expected.png b/third_party/blink/web_tests/paint/invalidation/svg/mask-clip-target-transform-expected.png
index 9a7856b..1d6bc00 100644
--- a/third_party/blink/web_tests/paint/invalidation/svg/mask-clip-target-transform-expected.png
+++ b/third_party/blink/web_tests/paint/invalidation/svg/mask-clip-target-transform-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/paint/invalidation/svg/mask-clip-target-transform-expected.txt b/third_party/blink/web_tests/paint/invalidation/svg/mask-clip-target-transform-expected.txt
index 7245147..eba80ac 100644
--- a/third_party/blink/web_tests/paint/invalidation/svg/mask-clip-target-transform-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/svg/mask-clip-target-transform-expected.txt
@@ -6,7 +6,8 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [150, 50, 100, 100],
+        [0, 0, 340, 120],
+        [80, 0, 240, 340],
         [50, 150, 100, 100]
       ]
     }
diff --git a/third_party/blink/web_tests/paint/invalidation/svg/mask-invalidation-expected.txt b/third_party/blink/web_tests/paint/invalidation/svg/mask-invalidation-expected.txt
index 89af166..196c637 100644
--- a/third_party/blink/web_tests/paint/invalidation/svg/mask-invalidation-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/svg/mask-invalidation-expected.txt
@@ -6,8 +6,7 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [50, 50, 453, 299],
-        [200, 100, 403, 249]
+        [0, 0, 800, 600]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/paint/invalidation/svg/resource-invalidate-on-target-update-expected.png b/third_party/blink/web_tests/paint/invalidation/svg/resource-invalidate-on-target-update-expected.png
index 0f2f5aa..8c82a4433 100644
--- a/third_party/blink/web_tests/paint/invalidation/svg/resource-invalidate-on-target-update-expected.png
+++ b/third_party/blink/web_tests/paint/invalidation/svg/resource-invalidate-on-target-update-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/paint/invalidation/svg/resource-invalidate-on-target-update-expected.txt b/third_party/blink/web_tests/paint/invalidation/svg/resource-invalidate-on-target-update-expected.txt
index 14b080f..0ff6509 100644
--- a/third_party/blink/web_tests/paint/invalidation/svg/resource-invalidate-on-target-update-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/svg/resource-invalidate-on-target-update-expected.txt
@@ -6,9 +6,9 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
+        [0, 0, 230, 120],
         [0, 240, 222, 120],
-        [10, 130, 200, 100],
-        [10, 10, 200, 100]
+        [10, 130, 200, 100]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt b/third_party/blink/web_tests/paint/invalidation/svg/text-mask-update-expected.txt
similarity index 80%
rename from third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt
rename to third_party/blink/web_tests/paint/invalidation/svg/text-mask-update-expected.txt
index 3fad3a7..5b304d1 100644
--- a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt
+++ b/third_party/blink/web_tests/paint/invalidation/svg/text-mask-update-expected.txt
@@ -6,8 +6,7 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [10, 3, 45, 22],
-        [10, 33, 43, 17]
+        [0, 0, 110, 55]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/masking-intro-01-f-expected.png b/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/masking-intro-01-f-expected.png
index 163dcc3..085f63e6 100644
--- a/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/masking-intro-01-f-expected.png
+++ b/third_party/blink/web_tests/platform/linux/svg/W3C-SVG-1.1/masking-intro-01-f-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/as-background-image/svg-as-background-6-expected.png b/third_party/blink/web_tests/platform/linux/svg/as-background-image/svg-as-background-6-expected.png
index d2f3d56..8ac8f0d2 100644
--- a/third_party/blink/web_tests/platform/linux/svg/as-background-image/svg-as-background-6-expected.png
+++ b/third_party/blink/web_tests/platform/linux/svg/as-background-image/svg-as-background-6-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/batik/masking/maskRegions-expected.png b/third_party/blink/web_tests/platform/linux/svg/batik/masking/maskRegions-expected.png
index 2e76c03..b5b7be4 100644
--- a/third_party/blink/web_tests/platform/linux/svg/batik/masking/maskRegions-expected.png
+++ b/third_party/blink/web_tests/platform/linux/svg/batik/masking/maskRegions-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/custom/clip-mask-negative-scale-expected.png b/third_party/blink/web_tests/platform/linux/svg/custom/clip-mask-negative-scale-expected.png
index b855650..d5cf659 100644
--- a/third_party/blink/web_tests/platform/linux/svg/custom/clip-mask-negative-scale-expected.png
+++ b/third_party/blink/web_tests/platform/linux/svg/custom/clip-mask-negative-scale-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/svg/zoom/page/zoom-mask-with-percentages-expected.png b/third_party/blink/web_tests/platform/linux/svg/zoom/page/zoom-mask-with-percentages-expected.png
index 9806a59..dd3b95a 100644
--- a/third_party/blink/web_tests/platform/linux/svg/zoom/page/zoom-mask-with-percentages-expected.png
+++ b/third_party/blink/web_tests/platform/linux/svg/zoom/page/zoom-mask-with-percentages-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png b/third_party/blink/web_tests/platform/linux/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
deleted file mode 100644
index 049267c..0000000
--- a/third_party/blink/web_tests/platform/linux/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac-arm11.0/images/color-profile-mask-image-svg-expected.png b/third_party/blink/web_tests/platform/mac-mac-arm11.0/images/color-profile-mask-image-svg-expected.png
new file mode 100644
index 0000000..c94f52c
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/images/color-profile-mask-image-svg-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt b/third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/js-late-mask-and-object-creation-expected.txt
similarity index 79%
copy from third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt
copy to third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/js-late-mask-and-object-creation-expected.txt
index 3fad3a7..769ae10 100644
--- a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt
+++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/js-late-mask-and-object-creation-expected.txt
@@ -6,8 +6,7 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [10, 3, 45, 22],
-        [10, 33, 43, 17]
+        [0, 100, 800, 100]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt b/third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/js-late-mask-creation-expected.txt
similarity index 79%
copy from third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt
copy to third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/js-late-mask-creation-expected.txt
index 3fad3a7..769ae10 100644
--- a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt
+++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/js-late-mask-creation-expected.txt
@@ -6,8 +6,7 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [10, 3, 45, 22],
-        [10, 33, 43, 17]
+        [0, 100, 800, 100]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt b/third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/mask-child-changes-expected.txt
similarity index 79%
copy from third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt
copy to third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/mask-child-changes-expected.txt
index 3fad3a7..769ae10 100644
--- a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt
+++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/mask-child-changes-expected.txt
@@ -6,8 +6,7 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [10, 3, 45, 22],
-        [10, 33, 43, 17]
+        [0, 100, 800, 100]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt b/third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/mask-clip-target-transform-expected.txt
similarity index 77%
copy from third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt
copy to third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/mask-clip-target-transform-expected.txt
index 3fad3a7..7245147 100644
--- a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt
+++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/mask-clip-target-transform-expected.txt
@@ -6,8 +6,8 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [10, 3, 45, 22],
-        [10, 33, 43, 17]
+        [150, 50, 100, 100],
+        [50, 150, 100, 100]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt b/third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/mask-invalidation-expected.txt
similarity index 77%
copy from third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt
copy to third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/mask-invalidation-expected.txt
index 3fad3a7..89af166 100644
--- a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt
+++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/mask-invalidation-expected.txt
@@ -6,8 +6,8 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [10, 3, 45, 22],
-        [10, 33, 43, 17]
+        [50, 50, 453, 299],
+        [200, 100, 403, 249]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/resource-invalidate-on-target-update-expected.png b/third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/resource-invalidate-on-target-update-expected.png
new file mode 100644
index 0000000..0f2f5aa
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/resource-invalidate-on-target-update-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt b/third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/resource-invalidate-on-target-update-expected.txt
similarity index 70%
copy from third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt
copy to third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/resource-invalidate-on-target-update-expected.txt
index 3fad3a7..14b080f 100644
--- a/third_party/blink/web_tests/platform/linux/paint/invalidation/svg/text-mask-update-expected.txt
+++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/resource-invalidate-on-target-update-expected.txt
@@ -6,8 +6,9 @@
       "contentsOpaque": true,
       "backgroundColor": "#FFFFFF",
       "invalidations": [
-        [10, 3, 45, 22],
-        [10, 33, 43, 17]
+        [0, 240, 222, 120],
+        [10, 130, 200, 100],
+        [10, 10, 200, 100]
       ]
     }
   ]
diff --git a/third_party/blink/web_tests/platform/mac/paint/invalidation/svg/text-mask-update-expected.txt b/third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/text-mask-update-expected.txt
similarity index 100%
rename from third_party/blink/web_tests/platform/mac/paint/invalidation/svg/text-mask-update-expected.txt
rename to third_party/blink/web_tests/platform/mac-mac-arm11.0/paint/invalidation/svg/text-mask-update-expected.txt
diff --git a/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/custom/clip-mask-negative-scale-expected.png b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/custom/clip-mask-negative-scale-expected.png
new file mode 100644
index 0000000..c7c81734
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/custom/clip-mask-negative-scale-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-dom-height-attr-expected.png b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-dom-height-attr-expected.png
new file mode 100644
index 0000000..b5de8e2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-dom-height-attr-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-dom-maskContentUnits-attr-expected.png b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-dom-maskContentUnits-attr-expected.png
new file mode 100644
index 0000000..b5de8e2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-dom-maskContentUnits-attr-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-dom-width-attr-expected.png b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-dom-width-attr-expected.png
new file mode 100644
index 0000000..b5de8e2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-dom-width-attr-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-dom-x-attr-expected.png b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-dom-x-attr-expected.png
new file mode 100644
index 0000000..b5de8e2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-dom-x-attr-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-dom-y-attr-expected.png b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-dom-y-attr-expected.png
new file mode 100644
index 0000000..b5de8e2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-dom-y-attr-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-svgdom-height-prop-expected.png b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-svgdom-height-prop-expected.png
new file mode 100644
index 0000000..b5de8e2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-svgdom-height-prop-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-svgdom-maskContentUnits-prop-expected.png b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-svgdom-maskContentUnits-prop-expected.png
new file mode 100644
index 0000000..b5de8e2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-svgdom-maskContentUnits-prop-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-svgdom-width-prop-expected.png b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-svgdom-width-prop-expected.png
new file mode 100644
index 0000000..b5de8e2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-svgdom-width-prop-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-svgdom-x-prop-expected.png b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-svgdom-x-prop-expected.png
new file mode 100644
index 0000000..b5de8e2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-svgdom-x-prop-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-svgdom-y-prop-expected.png b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-svgdom-y-prop-expected.png
new file mode 100644
index 0000000..b5de8e2
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac-mac-arm11.0/svg/dynamic-updates/SVGMaskElement-svgdom-y-prop-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/virtual/exotic-color-space/images/color-profile-mask-image-svg-expected.png b/third_party/blink/web_tests/platform/mac-mac-arm11.0/virtual/exotic-color-space/images/color-profile-mask-image-svg-expected.png
similarity index 100%
rename from third_party/blink/web_tests/virtual/exotic-color-space/images/color-profile-mask-image-svg-expected.png
rename to third_party/blink/web_tests/platform/mac-mac-arm11.0/virtual/exotic-color-space/images/color-profile-mask-image-svg-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png b/third_party/blink/web_tests/platform/mac-mac-arm11.0/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
similarity index 100%
rename from third_party/blink/web_tests/platform/mac/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
rename to third_party/blink/web_tests/platform/mac-mac-arm11.0/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/svg/as-background-image/svg-as-background-6-expected.png b/third_party/blink/web_tests/platform/mac-mac10.12/svg/as-background-image/svg-as-background-6-expected.png
index 7822c0b..0a7b49e 100644
--- a/third_party/blink/web_tests/platform/mac-mac10.12/svg/as-background-image/svg-as-background-6-expected.png
+++ b/third_party/blink/web_tests/platform/mac-mac10.12/svg/as-background-image/svg-as-background-6-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/W3C-SVG-1.1/masking-intro-01-f-expected.png b/third_party/blink/web_tests/platform/mac/svg/W3C-SVG-1.1/masking-intro-01-f-expected.png
index 9b192a9..0919878 100644
--- a/third_party/blink/web_tests/platform/mac/svg/W3C-SVG-1.1/masking-intro-01-f-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/W3C-SVG-1.1/masking-intro-01-f-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/as-background-image/svg-as-background-6-expected.png b/third_party/blink/web_tests/platform/mac/svg/as-background-image/svg-as-background-6-expected.png
index 28f15b9..82cc3ec6 100644
--- a/third_party/blink/web_tests/platform/mac/svg/as-background-image/svg-as-background-6-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/as-background-image/svg-as-background-6-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/batik/masking/maskRegions-expected.png b/third_party/blink/web_tests/platform/mac/svg/batik/masking/maskRegions-expected.png
index 7df7a17..5ef260e 100644
--- a/third_party/blink/web_tests/platform/mac/svg/batik/masking/maskRegions-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/batik/masking/maskRegions-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/custom/clip-mask-negative-scale-expected.png b/third_party/blink/web_tests/platform/mac/svg/custom/clip-mask-negative-scale-expected.png
index c7c81734..85faa95 100644
--- a/third_party/blink/web_tests/platform/mac/svg/custom/clip-mask-negative-scale-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/custom/clip-mask-negative-scale-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/svg/zoom/page/zoom-mask-with-percentages-expected.png b/third_party/blink/web_tests/platform/mac/svg/zoom/page/zoom-mask-with-percentages-expected.png
index f8b8982..8795c6c 100644
--- a/third_party/blink/web_tests/platform/mac/svg/zoom/page/zoom-mask-with-percentages-expected.png
+++ b/third_party/blink/web_tests/platform/mac/svg/zoom/page/zoom-mask-with-percentages-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-mask-image-svg-expected.png b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-mask-image-svg-expected.png
new file mode 100644
index 0000000..32ce8a8
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/virtual/exotic-color-space/images/color-profile-mask-image-svg-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/invalidation/svg/text-mask-update-expected.txt b/third_party/blink/web_tests/platform/win/paint/invalidation/svg/text-mask-update-expected.txt
deleted file mode 100644
index 62d55652..0000000
--- a/third_party/blink/web_tests/platform/win/paint/invalidation/svg/text-mask-update-expected.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-{
-  "layers": [
-    {
-      "name": "Scrolling Contents Layer",
-      "bounds": [800, 600],
-      "contentsOpaque": true,
-      "backgroundColor": "#FFFFFF",
-      "invalidations": [
-        [10, 3, 45, 22],
-        [10, 33, 41, 17]
-      ]
-    }
-  ]
-}
-
diff --git a/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/masking-intro-01-f-expected.png b/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/masking-intro-01-f-expected.png
index eae58a0..ebea164 100644
--- a/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/masking-intro-01-f-expected.png
+++ b/third_party/blink/web_tests/platform/win/svg/W3C-SVG-1.1/masking-intro-01-f-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/as-background-image/svg-as-background-6-expected.png b/third_party/blink/web_tests/platform/win/svg/as-background-image/svg-as-background-6-expected.png
index 4ae0f19..7dbf3c5 100644
--- a/third_party/blink/web_tests/platform/win/svg/as-background-image/svg-as-background-6-expected.png
+++ b/third_party/blink/web_tests/platform/win/svg/as-background-image/svg-as-background-6-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/batik/masking/maskRegions-expected.png b/third_party/blink/web_tests/platform/win/svg/batik/masking/maskRegions-expected.png
index e77c1056..822a0684 100644
--- a/third_party/blink/web_tests/platform/win/svg/batik/masking/maskRegions-expected.png
+++ b/third_party/blink/web_tests/platform/win/svg/batik/masking/maskRegions-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/custom/clip-mask-negative-scale-expected.png b/third_party/blink/web_tests/platform/win/svg/custom/clip-mask-negative-scale-expected.png
index afb77682..fa6993b8 100644
--- a/third_party/blink/web_tests/platform/win/svg/custom/clip-mask-negative-scale-expected.png
+++ b/third_party/blink/web_tests/platform/win/svg/custom/clip-mask-negative-scale-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-mask-with-percentages-expected.png b/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-mask-with-percentages-expected.png
index c5235051..165dd2a 100644
--- a/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-mask-with-percentages-expected.png
+++ b/third_party/blink/web_tests/platform/win/svg/zoom/page/zoom-mask-with-percentages-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/color-profile-mask-image-svg-expected.png b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/color-profile-mask-image-svg-expected.png
index 33d5e415..cc7f30b0 100644
--- a/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/color-profile-mask-image-svg-expected.png
+++ b/third_party/blink/web_tests/platform/win/virtual/exotic-color-space/images/color-profile-mask-image-svg-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png b/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
deleted file mode 100644
index 049267c..0000000
--- a/third_party/blink/web_tests/platform/win/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win7/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png b/third_party/blink/web_tests/platform/win7/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
deleted file mode 100644
index 049267c..0000000
--- a/third_party/blink/web_tests/platform/win7/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
+++ /dev/null
Binary files differ
diff --git a/third_party/blink/web_tests/svg/custom/grayscale-gradient-mask-expected.png b/third_party/blink/web_tests/svg/custom/grayscale-gradient-mask-expected.png
index f101697..2486aa0 100644
--- a/third_party/blink/web_tests/svg/custom/grayscale-gradient-mask-expected.png
+++ b/third_party/blink/web_tests/svg/custom/grayscale-gradient-mask-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-height-attr-expected.png b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-height-attr-expected.png
index b5de8e2..2b62614 100644
--- a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-height-attr-expected.png
+++ b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-height-attr-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-maskContentUnits-attr-expected.png b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-maskContentUnits-attr-expected.png
index b5de8e2..2b62614 100644
--- a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-maskContentUnits-attr-expected.png
+++ b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-maskContentUnits-attr-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-width-attr-expected.png b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-width-attr-expected.png
index b5de8e2..2b62614 100644
--- a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-width-attr-expected.png
+++ b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-width-attr-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-x-attr-expected.png b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-x-attr-expected.png
index b5de8e2..2b62614 100644
--- a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-x-attr-expected.png
+++ b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-x-attr-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-y-attr-expected.png b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-y-attr-expected.png
index b5de8e2..2b62614 100644
--- a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-y-attr-expected.png
+++ b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-dom-y-attr-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-height-prop-expected.png b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-height-prop-expected.png
index b5de8e2..2b62614 100644
--- a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-height-prop-expected.png
+++ b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-height-prop-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-maskContentUnits-prop-expected.png b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-maskContentUnits-prop-expected.png
index b5de8e2..2b62614 100644
--- a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-maskContentUnits-prop-expected.png
+++ b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-maskContentUnits-prop-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-width-prop-expected.png b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-width-prop-expected.png
index b5de8e2..2b62614 100644
--- a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-width-prop-expected.png
+++ b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-width-prop-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-x-prop-expected.png b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-x-prop-expected.png
index b5de8e2..2b62614 100644
--- a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-x-prop-expected.png
+++ b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-x-prop-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-y-prop-expected.png b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-y-prop-expected.png
index b5de8e2..2b62614 100644
--- a/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-y-prop-expected.png
+++ b/third_party/blink/web_tests/svg/dynamic-updates/SVGMaskElement-svgdom-y-prop-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/svg/filters/svg-element-invalid-filter.html b/third_party/blink/web_tests/svg/filters/svg-element-invalid-filter.html
index 1a59b0f..c00bb31 100644
--- a/third_party/blink/web_tests/svg/filters/svg-element-invalid-filter.html
+++ b/third_party/blink/web_tests/svg/filters/svg-element-invalid-filter.html
@@ -66,7 +66,7 @@
 </svg>
 
 <svg viewBox="0 0 50 50">
-  <rect fill="lime" x="0" y="0" height="50" width="50"
+  <rect fill="red" x="0" y="0" height="50" width="50"
        style="filter: url(#filter) blur(0px)"/>
 </svg>
 
diff --git a/third_party/blink/web_tests/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png b/third_party/blink/web_tests/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
new file mode 100644
index 0000000..acf2133
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/gpu-rasterization/images/color-profile-mask-image-svg-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/wpt_internal/webgpu/cts.html b/third_party/blink/web_tests/wpt_internal/webgpu/cts.html
index f99b8bb..6eff38b 100644
--- a/third_party/blink/web_tests/wpt_internal/webgpu/cts.html
+++ b/third_party/blink/web_tests/wpt_internal/webgpu/cts.html
@@ -165,15 +165,7 @@
 <meta name=variant content='?q=webgpu:api,operation,resource_init,texture_zero_init:uninitialized_texture_is_zero:readMethod="StencilTest";*'>
 <meta name=variant content='?q=webgpu:api,validation,buffer,create:*'>
 <meta name=variant content='?q=webgpu:api,validation,buffer,destroy:*'>
-<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,usage,*'>
-<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,invalidBuffer:*'>
-<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,state,*'>
-<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,sizeUnspecifiedOOB,*'>
-<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,offsetAndSizeAlignment,*'>
-<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync,offsetAndSizeOOB,*'>
-<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:mapAsync_,*'>
-<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:getMappedRange,*'>
-<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:unmap,*'>
+<meta name=variant content='?q=webgpu:api,validation,buffer,mapping:*'>
 <meta name=variant content='?q=webgpu:api,validation,copyBufferToBuffer:copy_with_invalid_buffer:'>
 <meta name=variant content='?q=webgpu:api,validation,copyBufferToBuffer:buffer_usage,*'>
 <meta name=variant content='?q=webgpu:api,validation,copyBufferToBuffer:copy_size_alignment,*'>
@@ -186,11 +178,76 @@
 <meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_usage,*'>
 <meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:sample_count,*'>
 <meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:multisampled_copy_restrictions,*'>
-<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="r8unorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="r8snorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="r8uint";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="r8sint";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="r16uint";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="r16sint";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="r16float";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rg8unorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rg8snorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rg8uint";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rg8sint";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="r32uint";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="r32sint";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="r32float";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rg16uint";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rg16sint";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rg16float";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rgba8unorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rgba8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rgba8snorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rgba8uint";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rgba8sint";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="bgra8unorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="bgra8unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rgb10a2unorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rg11b10ufloat";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rgb9e5ufloat";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rg32uint";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rg32sint";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rg32float";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rgba16uint";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rgba16sint";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rgba16float";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rgba32uint";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rgba32sint";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="rgba32float";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="depth32float";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="depth24plus";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="depth24plus-stencil8";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="bc1-rgba-unorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="bc1-rgba-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="bc2-rgba-unorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="bc2-rgba-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="bc3-rgba-unorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="bc3-rgba-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="bc4-r-unorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="bc4-r-snorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="bc5-rg-unorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="bc5-rg-snorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="bc6h-rgb-ufloat";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="bc6h-rgb-float";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="bc7-rgba-unorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:texture_format_equality:srcFormat="bc7-rgba-unorm-srgb";*'>
 <meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:depth_stencil_copy_restrictions,*'>
 <meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:copy_ranges,*'>
 <meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:copy_within_same_texture,*'>
-<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:copy_ranges_with_compressed_texture_formats,*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc1-rgba-unorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc1-rgba-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc2-rgba-unorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc2-rgba-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc3-rgba-unorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc3-rgba-unorm-srgb";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc4-r-unorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc4-r-snorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc5-rg-unorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc5-rg-snorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc6h-rgb-ufloat";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc6h-rgb-float";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc7-rgba-unorm";*'>
+<meta name=variant content='?q=webgpu:api,validation,copyTextureToTexture:copy_ranges_with_compressed_texture_formats:format="bc7-rgba-unorm-srgb";*'>
 <meta name=variant content='?q=webgpu:api,validation,copy_between_linear_data_and_texture,copyBetweenLinearDataAndTexture_dataRelated:*'>
 <meta name=variant content='?q=webgpu:api,validation,copy_between_linear_data_and_texture,copyBetweenLinearDataAndTexture_textureRelated:*'>
 <meta name=variant content='?q=webgpu:api,validation,createBindGroup:binding_count_mismatch,*'>
diff --git a/third_party/opus/README.chromium b/third_party/opus/README.chromium
index 8f4ed5e..730df97 100644
--- a/third_party/opus/README.chromium
+++ b/third_party/opus/README.chromium
@@ -17,6 +17,7 @@
 * remove assertion messages in release builds (see crbug/1053572)
 * apply patch to fix int-overflow in silk (https://gitlab.xiph.org/xiph/opus/-/commit/923bebde)
 * apply patch to fix another int-overflow in silk (https://gitlab.xiph.org/xiph/opus/-/commit/adcb7bc2)
+* add workaround to ignore some int-overflows when fuzzing (see crbug/1146174)
 
 Opus' own unit tests are located in ./src/tests
 Additional chromium tests are located in ./tests
diff --git a/third_party/opus/src/silk/NSQ_del_dec.c b/third_party/opus/src/silk/NSQ_del_dec.c
index 00e749c..fc6500c 100644
--- a/third_party/opus/src/silk/NSQ_del_dec.c
+++ b/third_party/opus/src/silk/NSQ_del_dec.c
@@ -423,18 +423,30 @@
             /* Output of lowpass section */
             tmp2 = silk_SMLAWB( psDD->Diff_Q14, psDD->sAR2_Q14[ 0 ], warping_Q16 );
             /* Output of allpass section */
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+            tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ 0 ], silk_SUB32_ovflw(psDD->sAR2_Q14[ 1 ], tmp2), warping_Q16 );
+#else
             tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 );
+#endif
             psDD->sAR2_Q14[ 0 ] = tmp2;
             n_AR_Q14 = silk_RSHIFT( shapingLPCOrder, 1 );
             n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp2, AR_shp_Q13[ 0 ] );
             /* Loop over allpass sections */
             for( j = 2; j < shapingLPCOrder; j += 2 ) {
                 /* Output of allpass section */
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+                tmp2 = silk_SMLAWB( psDD->sAR2_Q14[ j - 1 ], silk_SUB32_ovflw(psDD->sAR2_Q14[ j + 0 ], tmp1), warping_Q16 );
+#else
                 tmp2 = silk_SMLAWB( psDD->sAR2_Q14[ j - 1 ], psDD->sAR2_Q14[ j + 0 ] - tmp1, warping_Q16 );
+#endif
                 psDD->sAR2_Q14[ j - 1 ] = tmp1;
                 n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp1, AR_shp_Q13[ j - 1 ] );
                 /* Output of allpass section */
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+                tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ j + 0 ], silk_SUB32_ovflw(psDD->sAR2_Q14[ j + 1 ], tmp2), warping_Q16 );
+#else
                 tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ j + 0 ], psDD->sAR2_Q14[ j + 1 ] - tmp2, warping_Q16 );
+#endif
                 psDD->sAR2_Q14[ j + 0 ] = tmp2;
                 n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp2, AR_shp_Q13[ j ] );
             }
@@ -534,7 +546,11 @@
 
             /* Update states */
             psSS[ 0 ].Diff_Q14     = silk_SUB_LSHIFT32( xq_Q14, x_Q10[ i ], 4 );
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+            sLF_AR_shp_Q14         = silk_SUB32_ovflw( psSS[ 0 ].Diff_Q14, n_AR_Q14 );
+#else
             sLF_AR_shp_Q14         = silk_SUB32( psSS[ 0 ].Diff_Q14, n_AR_Q14 );
+#endif
             psSS[ 0 ].sLTP_shp_Q14 = silk_SUB_SAT32( sLF_AR_shp_Q14, n_LF_Q14 );
             psSS[ 0 ].LF_AR_Q14    = sLF_AR_shp_Q14;
             psSS[ 0 ].LPC_exc_Q14  = LPC_exc_Q14;
@@ -554,7 +570,11 @@
 
             /* Update states */
             psSS[ 1 ].Diff_Q14     = silk_SUB_LSHIFT32( xq_Q14, x_Q10[ i ], 4 );
+#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
+            sLF_AR_shp_Q14         = silk_SUB32_ovflw( psSS[ 1 ].Diff_Q14, n_AR_Q14 );
+#else
             sLF_AR_shp_Q14         = silk_SUB32( psSS[ 1 ].Diff_Q14, n_AR_Q14 );
+#endif
             psSS[ 1 ].sLTP_shp_Q14 = silk_SUB_SAT32( sLF_AR_shp_Q14, n_LF_Q14 );
             psSS[ 1 ].LF_AR_Q14    = sLF_AR_shp_Q14;
             psSS[ 1 ].LPC_exc_Q14  = LPC_exc_Q14;
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 87302c1..480cdd1 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -44941,6 +44941,7 @@
   <int value="610545308" label="enable-potentially-annoying-security-features"/>
   <int value="613629912" label="LookalikeUrlNavigationSuggestions:enabled"/>
   <int value="614174812" label="GlobalMediaControlsOverlayControls:disabled"/>
+  <int value="616609955" label="ActionableContentSettings:enabled"/>
   <int value="616660621" label="ImeInputLogicFst:disabled"/>
   <int value="617762656" label="FirstScrollLatencyMeasurement:enabled"/>
   <int value="618532343" label="DesktopPWAsLocalUpdating:disabled"/>
@@ -45896,6 +45897,7 @@
   <int value="1514158607" label="NearbySharingDeviceContacts:enabled"/>
   <int value="1515196403" label="fast-user-switching"/>
   <int value="1517863401" label="history-entry-requires-user-gesture"/>
+  <int value="1519067750" label="ActionableContentSettings:disabled"/>
   <int value="1520181151" label="PrintServerScaling:disabled"/>
   <int value="1524178643" label="AppServiceExternalProtocol:enabled"/>
   <int value="1526718531"
diff --git a/ui/accessibility/extensions/chromevoxclassic/BUILD.gn b/ui/accessibility/extensions/chromevoxclassic/BUILD.gn
index acc5ac8..21cded3 100644
--- a/ui/accessibility/extensions/chromevoxclassic/BUILD.gn
+++ b/ui/accessibility/extensions/chromevoxclassic/BUILD.gn
@@ -225,7 +225,6 @@
 
 group("chromevox") {
   deps = [
-    ":accessibility_strings",
     ":chromevox_background_script",
     ":chromevox_content_script",
     ":chromevox_copied_files",
diff --git a/ui/accessibility/extensions/chromevoxclassic/README b/ui/accessibility/extensions/chromevoxclassic/README
index 586478d..4210be7 100644
--- a/ui/accessibility/extensions/chromevoxclassic/README
+++ b/ui/accessibility/extensions/chromevoxclassic/README
@@ -21,6 +21,11 @@
 
 out/Release/chromevoxclassic.
 
+The one exception is ./_locales. You must copy this directory manually to
+out/Release/chromevoxclassic.
+
+These translations are no longer part of mainline ChromeVox.
+
 #Loading and Testing
 Go to chrome://extensions, and click "Load
 Unpacked". Select out/Release/chromevoxclassic.
@@ -46,3 +51,9 @@
 
 Once confirmed, the entire directory can be uploaded once zipped to the Chrome
 webstore.
+
+## A final note on branding
+
+In order to further differentiate ChromeVox from ChromeVox Classic, the Classic
+extension is now simply known as "Screen Reader" and scrubbed of the ChromeVox
+brand.
\ No newline at end of file
diff --git a/ui/accessibility/extensions/chromevoxclassic/chromevox/background/tabs_api_handler.js b/ui/accessibility/extensions/chromevoxclassic/chromevox/background/tabs_api_handler.js
index 000462f..350ce62 100644
--- a/ui/accessibility/extensions/chromevoxclassic/chromevox/background/tabs_api_handler.js
+++ b/ui/accessibility/extensions/chromevoxclassic/chromevox/background/tabs_api_handler.js
@@ -208,15 +208,6 @@
    * @private
    */
   refreshAutomationHandler_: function(tabId) {
-    if (!cvox.ChromeVox.isMac)
-      return;
-
-    chrome.automation.getTree(tabId, function(node) {
-      if (this.handler_)
-        this.handler_.removeAllListeners();
-
-      this.handler_ = new TabsAutomationHandler(node);
-    }.bind(this));
   },
 
   /**
diff --git a/ui/accessibility/extensions/chromevoxclassic/cvox2/background/desktop_automation_handler.js b/ui/accessibility/extensions/chromevoxclassic/cvox2/background/desktop_automation_handler.js
index 0b2ac9b..0c0cd11 100644
--- a/ui/accessibility/extensions/chromevoxclassic/cvox2/background/desktop_automation_handler.js
+++ b/ui/accessibility/extensions/chromevoxclassic/cvox2/background/desktop_automation_handler.js
@@ -42,7 +42,8 @@
   this.lastValueChanged_ = new Date(0);
 
   var e = EventType;
-  this.addListener_(e.ACTIVEDESCENDANTCHANGED, this.onActiveDescendantChanged);
+  this.addListener_(
+      e.ACTIVE_DESCENDANT_CHANGED, this.onActiveDescendantChanged);
   this.addListener_(e.ALERT, this.onAlert);
   this.addListener_(e.ARIA_ATTRIBUTE_CHANGED, this.onEventIfInRange);
   this.addListener_(e.CHECKED_STATE_CHANGED, this.onEventIfInRange);
diff --git a/ui/accessibility/extensions/chromevoxclassic/host/chrome/braille_background.js b/ui/accessibility/extensions/chromevoxclassic/host/chrome/braille_background.js
index 7ac49299..8dd3ab3a 100644
--- a/ui/accessibility/extensions/chromevoxclassic/host/chrome/braille_background.js
+++ b/ui/accessibility/extensions/chromevoxclassic/host/chrome/braille_background.js
@@ -63,7 +63,7 @@
 
 /** @override */
 cvox.BrailleBackground.prototype.write = function(params) {
-  this.setContent_(params, null);
+  // Stubbed out.
 };
 
 
diff --git a/ui/accessibility/extensions/chromevoxclassic/manifest.json.jinja2 b/ui/accessibility/extensions/chromevoxclassic/manifest.json.jinja2
index c0bb2af..ebf6d3b 100644
--- a/ui/accessibility/extensions/chromevoxclassic/manifest.json.jinja2
+++ b/ui/accessibility/extensions/chromevoxclassic/manifest.json.jinja2
@@ -5,46 +5,14 @@
    "background": {
       "page": "cvox2/background/background.html"
    },
-   "commands": {
-      "nextObject": {
-         "description": "__MSG_CHROMEVOX_NEXT_OBJECT__",
-         "suggested_key": {
-            "default": "Alt+Shift+Right"
-         }
-      },
-      "performDefaultAction": {
-         "description": "__MSG_CHROMEVOX_PERFORM_DEFAULT_ACTION__",
-         "suggested_key": {
-            "default": "Alt+Shift+Space"
-         }
-      },
-      "previousObject": {
-         "description": "__MSG_CHROMEVOX_PREVIOUS_OBJECT__",
-         "suggested_key": {
-            "default": "Alt+Shift+Left"
-         }
-      },
-      "readFromHere": {
-         "description": "__MSG_CHROMEVOX_READ_FROM_HERE__",
-         "suggested_key": {
-            "default": "Alt+Shift+R"
-         }
-      },
-      "toggleChromeVoxVersion": {
-         "description": "__MSG_CHROMEVOX_TOGGLE_CHROMEVOX__",
-         "suggested_key": {
-            "default": "Alt+Shift+Q"
-         }
-      }
-   },
    "content_scripts": [ {
       "all_frames": true,
       "exclude_globs": [  ],
       "js": [ "chromeVoxChromePageScript.js" ],
-      "matches": [ "\u003Call_urls>" ]
+      "matches": [ "<all_urls>" ]
    } ],
    "default_locale": "en",
-   "description": "__MSG_CHROMEVOX_DESCRIPTION__",
+   "description": "A web-powered screen reader",
    "icons": {
       "128": "images/chromevox-128.png",
       "16": "images/chromevox-16.png",
@@ -52,10 +20,10 @@
    },
    "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDEGBi/oD7Yl/Y16w3+gee/95/EUpRZ2U6c+8orV5ei+3CRsBsoXI/DPGBauZ3rWQ47aQnfoG00sXigFdJA2NhNK9OgmRA2evnsRRbjYm2BG1twpaLsgQPPus3PyczbDCvhFu8k24wzFyEtxLrfxAGBseBPb9QrCz7B4k2QgxD/CwIDAQAB",
    "manifest_version": 2,
-   "name": "__MSG_CHROMEVOX_NAME__",
+   "name": "Screen Reader",
    "options_page": "chromevox/background/options.html",
-   "permissions": [ "accessibilityPrivate", "bookmarks", "brailleDisplayPrivate", "commands.accessibility", "commandLinePrivate", "experimental", "history", "notifications", "storage", "tabs", "tts", "virtualKeyboardPrivate", "\u003Call_urls>" ],
+   "permissions": [ "accessibilityPrivate", "bookmarks", "history", "notifications", "storage", "tabs", "tts", "<all_urls>" ],
    "update_url": "https://clients2.google.com/service/update2/crx",
-   "version": "53.0.2784.6",
+   "version": "53.0.2784.8",
    "web_accessible_resources": [ "chromevox/background/keymaps/next_keymap.json", "chromevox/injected/api.js", "chromevox/injected/api_util.js", "chromevox/injected/mathjax.js", "chromevox/injected/mathjax_external_util.js" ]
 }