Project import generated by Copybara.

GitOrigin-RevId: 35f3aa90db9cd77f0f586257ef9a788fadb1e27f
diff --git a/third_party/blink/common/BUILD.gn b/third_party/blink/common/BUILD.gn
index 454b556..4769d98 100644
--- a/third_party/blink/common/BUILD.gn
+++ b/third_party/blink/common/BUILD.gn
@@ -142,6 +142,7 @@
     "messaging/message_port_descriptor.cc",
     "messaging/message_port_descriptor_mojom_traits.cc",
     "messaging/string_message_codec.cc",
+    "messaging/task_attribution_id_mojom_traits.cc",
     "messaging/transferable_message.cc",
     "messaging/transferable_message_mojom_traits.cc",
     "messaging/web_message_port.cc",
diff --git a/third_party/blink/common/messaging/cloneable_message.cc b/third_party/blink/common/messaging/cloneable_message.cc
index abbaeb3..10a1d16 100644
--- a/third_party/blink/common/messaging/cloneable_message.cc
+++ b/third_party/blink/common/messaging/cloneable_message.cc
@@ -67,6 +67,7 @@
     clone.file_system_access_tokens.push_back(std::move(cloned_token));
     token = source_token.Unbind();
   }
+  clone.sender_agent_cluster_id = sender_agent_cluster_id;
   return clone;
 }
 
diff --git a/third_party/blink/common/messaging/cloneable_message_mojom_traits.cc b/third_party/blink/common/messaging/cloneable_message_mojom_traits.cc
index 8b23444..dd1ebda 100644
--- a/third_party/blink/common/messaging/cloneable_message_mojom_traits.cc
+++ b/third_party/blink/common/messaging/cloneable_message_mojom_traits.cc
@@ -20,9 +20,9 @@
     Read(blink::mojom::CloneableMessage::DataView data,
          blink::CloneableMessage* out) {
   mojo_base::BigBufferView message_view;
-  absl::optional<base::UnguessableToken> locked_agent_cluster_id;
+  base::UnguessableToken sender_agent_cluster_id;
   if (!data.ReadEncodedMessage(&message_view) || !data.ReadBlobs(&out->blobs) ||
-      !data.ReadLockedAgentClusterId(&locked_agent_cluster_id) ||
+      !data.ReadSenderAgentClusterId(&sender_agent_cluster_id) ||
       !data.ReadSenderOrigin(&out->sender_origin) ||
       !data.ReadFileSystemAccessTokens(&out->file_system_access_tokens)) {
     return false;
@@ -35,7 +35,8 @@
   out->stack_trace_debugger_id_first = data.stack_trace_debugger_id_first();
   out->stack_trace_debugger_id_second = data.stack_trace_debugger_id_second();
   out->stack_trace_should_pause = data.stack_trace_should_pause();
-  out->locked_agent_cluster_id = locked_agent_cluster_id;
+  out->sender_agent_cluster_id = sender_agent_cluster_id;
+  out->locked_to_sender_agent_cluster = data.locked_to_sender_agent_cluster();
   return true;
 }
 
diff --git a/third_party/blink/common/messaging/task_attribution_id_mojom_traits.cc b/third_party/blink/common/messaging/task_attribution_id_mojom_traits.cc
new file mode 100644
index 0000000..61db59c
--- /dev/null
+++ b/third_party/blink/common/messaging/task_attribution_id_mojom_traits.cc
@@ -0,0 +1,19 @@
+// Copyright 2022 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/public/common/messaging/task_attribution_id_mojom_traits.h"
+
+#include "third_party/blink/public/common/scheduler/task_attribution_id.h"
+
+namespace mojo {
+
+bool StructTraits<blink::mojom::TaskAttributionId::DataView,
+                  blink::scheduler::TaskAttributionId>::
+    Read(blink::mojom::TaskAttributionId::DataView data,
+         blink::scheduler::TaskAttributionId* out) {
+  *out = blink::scheduler::TaskAttributionId(data.value());
+  return true;
+}
+
+}  // namespace mojo
diff --git a/third_party/blink/common/messaging/transferable_message_mojom_traits.cc b/third_party/blink/common/messaging/transferable_message_mojom_traits.cc
index 8df6ebc..cab44fe 100644
--- a/third_party/blink/common/messaging/transferable_message_mojom_traits.cc
+++ b/third_party/blink/common/messaging/transferable_message_mojom_traits.cc
@@ -20,7 +20,8 @@
       !data.ReadArrayBufferContentsArray(&out->array_buffer_contents_array) ||
       !data.ReadImageBitmapContentsArray(&out->image_bitmap_contents_array) ||
       !data.ReadPorts(&ports) || !data.ReadStreamChannels(&stream_channels) ||
-      !data.ReadUserActivation(&out->user_activation)) {
+      !data.ReadUserActivation(&out->user_activation) ||
+      !data.ReadParentTaskId(&out->parent_task_id)) {
     return false;
   }
 
diff --git a/third_party/blink/common/messaging/web_message_port.cc b/third_party/blink/common/messaging/web_message_port.cc
index 88adf1b..f15a4f3 100644
--- a/third_party/blink/common/messaging/web_message_port.cc
+++ b/third_party/blink/common/messaging/web_message_port.cc
@@ -124,6 +124,15 @@
   return port;
 }
 
+const base::UnguessableToken& WebMessagePort::GetEmbedderAgentClusterID() {
+  // This is creating a single agent cluster ID that would represent the
+  // embedder in MessagePort IPCs. While we could create a new ID on each call,
+  // providing a consistent one saves RNG work and could be useful in the future
+  // if we'd want to consistently identify messages from the embedder.
+  static const auto agent_cluster_id = base::UnguessableToken::Create();
+  return agent_cluster_id;
+}
+
 WebMessagePort::WebMessagePort(MessagePortDescriptor&& port)
     : port_(std::move(port)), is_closed_(false), is_transferable_(true) {
   DCHECK(port_.IsValid());
@@ -160,6 +169,10 @@
   transferable_message.ports =
       blink::MessagePortChannel::CreateFromHandles(std::move(ports));
 
+  // Get the embedder assigned cluster ID, as these messages originate from the
+  // embedder.
+  transferable_message.sender_agent_cluster_id = GetEmbedderAgentClusterID();
+
   // TODO(chrisha): Notify the instrumentation delegate of a message being sent!
 
   // Send via Mojo. The message should never be malformed so should always be
diff --git a/third_party/blink/public/common/messaging/cloneable_message.h b/third_party/blink/public/common/messaging/cloneable_message.h
index 5056743..b88afb6 100644
--- a/third_party/blink/public/common/messaging/cloneable_message.h
+++ b/third_party/blink/public/common/messaging/cloneable_message.h
@@ -65,10 +65,12 @@
   int64_t stack_trace_debugger_id_second = 0;
   bool stack_trace_should_pause = false;
 
-  // If not null, this message is locked to the given agent cluster ID.
+  // The sender's agent cluster ID.
   // See
   // https://html.spec.whatwg.org/multipage/webappapis.html#integration-with-the-javascript-agent-cluster-formalism
-  absl::optional<base::UnguessableToken> locked_agent_cluster_id;
+  base::UnguessableToken sender_agent_cluster_id;
+  // If true, this message is locked to the sender agent cluster ID.
+  bool locked_to_sender_agent_cluster = false;
 
   // Tokens required to clone FileSystemFileHandles and/or
   // FileSystemDirectoryHandles.
diff --git a/third_party/blink/public/common/messaging/cloneable_message_mojom_traits.h b/third_party/blink/public/common/messaging/cloneable_message_mojom_traits.h
index a622019..6c0be65 100644
--- a/third_party/blink/public/common/messaging/cloneable_message_mojom_traits.h
+++ b/third_party/blink/public/common/messaging/cloneable_message_mojom_traits.h
@@ -48,9 +48,14 @@
     return input.stack_trace_should_pause;
   }
 
-  static const absl::optional<base::UnguessableToken>& locked_agent_cluster_id(
+  static const base::UnguessableToken& sender_agent_cluster_id(
       const blink::CloneableMessage& input) {
-    return input.locked_agent_cluster_id;
+    return input.sender_agent_cluster_id;
+  }
+
+  static bool locked_to_sender_agent_cluster(
+      const blink::CloneableMessage& input) {
+    return input.locked_to_sender_agent_cluster;
   }
 
   static bool Read(blink::mojom::CloneableMessage::DataView data,
diff --git a/third_party/blink/public/common/messaging/task_attribution_id_mojom_traits.h b/third_party/blink/public/common/messaging/task_attribution_id_mojom_traits.h
new file mode 100644
index 0000000..fe1a84e
--- /dev/null
+++ b/third_party/blink/public/common/messaging/task_attribution_id_mojom_traits.h
@@ -0,0 +1,29 @@
+// Copyright 2022 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_MESSAGING_TASK_ATTRIBUTION_ID_MOJOM_TRAITS_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_MESSAGING_TASK_ATTRIBUTION_ID_MOJOM_TRAITS_H_
+
+#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/common/scheduler/task_attribution_id.h"
+#include "third_party/blink/public/mojom/messaging/task_attribution_id.mojom.h"
+
+namespace mojo {
+
+template <>
+struct BLINK_COMMON_EXPORT
+    StructTraits<blink::mojom::TaskAttributionId::DataView,
+                 blink::scheduler::TaskAttributionId> {
+  static uint32_t value(const blink::scheduler::TaskAttributionId& input) {
+    return input.value();
+  }
+
+  static bool Read(blink::mojom::TaskAttributionId::DataView data,
+                   blink::scheduler::TaskAttributionId* out);
+};
+
+}  // namespace mojo
+
+#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_MESSAGING_TASK_ATTRIBUTION_ID_MOJOM_TRAITS_H_
diff --git a/third_party/blink/public/common/messaging/transferable_message.h b/third_party/blink/public/common/messaging/transferable_message.h
index 37b2599..568d580 100644
--- a/third_party/blink/public/common/messaging/transferable_message.h
+++ b/third_party/blink/public/common/messaging/transferable_message.h
@@ -12,8 +12,10 @@
 #include "third_party/blink/public/common/common_export.h"
 #include "third_party/blink/public/common/messaging/cloneable_message.h"
 #include "third_party/blink/public/common/messaging/message_port_channel.h"
+#include "third_party/blink/public/common/scheduler/task_attribution_id.h"
 #include "third_party/blink/public/mojom/array_buffer/array_buffer_contents.mojom.h"
 #include "third_party/blink/public/mojom/blob/blob.mojom.h"
+#include "third_party/blink/public/mojom/messaging/task_attribution_id.mojom.h"
 #include "third_party/blink/public/mojom/messaging/user_activation_snapshot.mojom.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
@@ -43,6 +45,9 @@
   // Whether payment request capability is delegated to the destination frame.
   bool delegate_payment_request = false;
 
+  // The transferable message's parent task ID.
+  absl::optional<scheduler::TaskAttributionId> parent_task_id;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(TransferableMessage);
 };
diff --git a/third_party/blink/public/common/messaging/transferable_message_mojom_traits.h b/third_party/blink/public/common/messaging/transferable_message_mojom_traits.h
index 7972cdc..75dd5c5 100644
--- a/third_party/blink/public/common/messaging/transferable_message_mojom_traits.h
+++ b/third_party/blink/public/common/messaging/transferable_message_mojom_traits.h
@@ -8,7 +8,9 @@
 #include "skia/public/mojom/bitmap_skbitmap_mojom_traits.h"
 #include "third_party/blink/public/common/messaging/cloneable_message_mojom_traits.h"
 #include "third_party/blink/public/common/messaging/message_port_descriptor_mojom_traits.h"
+#include "third_party/blink/public/common/messaging/task_attribution_id_mojom_traits.h"
 #include "third_party/blink/public/common/messaging/transferable_message.h"
+#include "third_party/blink/public/common/scheduler/task_attribution_id.h"
 #include "third_party/blink/public/mojom/messaging/transferable_message.mojom.h"
 #include "third_party/skia/include/core/SkBitmap.h"
 
@@ -51,6 +53,14 @@
     return input.delegate_payment_request;
   }
 
+  static absl::optional<blink::scheduler::TaskAttributionId> parent_task_id(
+      blink::TransferableMessage& input) {
+    return input.parent_task_id
+               ? absl::make_optional(blink::scheduler::TaskAttributionId(
+                     input.parent_task_id.value()))
+               : absl::nullopt;
+  }
+
   static bool Read(blink::mojom::TransferableMessage::DataView data,
                    blink::TransferableMessage* out);
 };
diff --git a/third_party/blink/public/common/messaging/web_message_port.h b/third_party/blink/public/common/messaging/web_message_port.h
index 43b8469..6fb5361 100644
--- a/third_party/blink/public/common/messaging/web_message_port.h
+++ b/third_party/blink/public/common/messaging/web_message_port.h
@@ -156,6 +156,10 @@
   // false). This can only be called if "is_transferable()" returns true.
   MessagePortDescriptor PassPort();
 
+  // Maintains a static agent cluster ID that is used as the cluster ID in
+  // casees where the embedder is the one calling PostMessage.
+  static const base::UnguessableToken& GetEmbedderAgentClusterID();
+
  private:
   // Creates a message port that wraps the provided |port|. This provided |port|
   // must be valid. This is private as it should only be called by message
diff --git a/third_party/blink/public/common/scheduler/task_attribution_id.h b/third_party/blink/public/common/scheduler/task_attribution_id.h
new file mode 100644
index 0000000..9a5573c
--- /dev/null
+++ b/third_party/blink/public/common/scheduler/task_attribution_id.h
@@ -0,0 +1,43 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_SCHEDULER_TASK_ATTRIBUTION_ID_H_
+#define THIRD_PARTY_BLINK_PUBLIC_COMMON_SCHEDULER_TASK_ATTRIBUTION_ID_H_
+
+#include <cstdint>
+#include "base/types/strong_alias.h"
+
+namespace blink::scheduler {
+
+using TaskAttributionIdType = uint32_t;
+
+// TaskAttributionId represents the ID of a task scope, encompassing a task and
+// its continuations. It enables comparison and incrementation operations on it,
+// while abstracting the underlying value from callers.
+class TaskAttributionId {
+ public:
+  TaskAttributionId() = default;
+  explicit TaskAttributionId(TaskAttributionIdType value) : value_(value) {}
+  TaskAttributionId(const TaskAttributionId&) = default;
+  TaskAttributionId& operator=(const TaskAttributionId&) = default;
+  TaskAttributionIdType value() const { return value_; }
+
+  bool operator==(const TaskAttributionId& id) const {
+    return id.value_ == value_;
+  }
+  bool operator!=(const TaskAttributionId& id) const {
+    return id.value_ != value_;
+  }
+  bool operator<(const TaskAttributionId& id) const {
+    return value_ < id.value_;
+  }
+  TaskAttributionId NextId() const { return TaskAttributionId(value_ + 1); }
+
+ private:
+  TaskAttributionIdType value_ = {0};
+};
+
+}  // namespace blink::scheduler
+
+#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_SCHEDULER_TASK_ATTRIBUTION_ID_H_
diff --git a/third_party/blink/public/mojom/BUILD.gn b/third_party/blink/public/mojom/BUILD.gn
index 8104656..d6e1614 100644
--- a/third_party/blink/public/mojom/BUILD.gn
+++ b/third_party/blink/public/mojom/BUILD.gn
@@ -883,6 +883,7 @@
     # transferable_message.mojom depends the other three messaging/ mojom files.
     "messaging/cloneable_message.mojom",
     "messaging/message_port_descriptor.mojom",
+    "messaging/task_attribution_id.mojom",
     "messaging/transferable_message.mojom",
     "messaging/user_activation_snapshot.mojom",
 
@@ -993,6 +994,16 @@
       ]
       traits_private_headers = [ "//third_party/blink/public/common/messaging/transferable_message_mojom_traits.h" ]
     },
+    {
+      types = [
+        {
+          mojom = "blink.mojom.TaskAttributionId"
+          cpp = "::blink::scheduler::TaskAttributionId"
+          move_only = true
+        },
+      ]
+      traits_private_headers = [ "//third_party/blink/public/common/messaging/task_attribution_id_mojom_traits.h" ]
+    },
   ]
   cpp_typemaps += shared_cpp_typemaps
 
diff --git a/third_party/blink/public/mojom/messaging/cloneable_message.mojom b/third_party/blink/public/mojom/messaging/cloneable_message.mojom
index f96d40f..8efa3dc 100644
--- a/third_party/blink/public/mojom/messaging/cloneable_message.mojom
+++ b/third_party/blink/public/mojom/messaging/cloneable_message.mojom
@@ -36,9 +36,11 @@
   int64 stack_trace_debugger_id_first;
   int64 stack_trace_debugger_id_second;
   bool stack_trace_should_pause;
-  // If not null, this message is locked to the given agent cluster ID.
+  // The sender's agent cluster ID.
   // See https://html.spec.whatwg.org/multipage/webappapis.html#integration-with-the-javascript-agent-cluster-formalism
-  mojo_base.mojom.UnguessableToken? locked_agent_cluster_id;
+  mojo_base.mojom.UnguessableToken sender_agent_cluster_id;
+  // If true, this message is locked to the sender agent cluster ID.
+  bool locked_to_sender_agent_cluster;
   // Tokens required to clone FileSystemFileHandles and/or
   // FileSystemDirectoryHandles.
   array<pending_remote<FileSystemAccessTransferToken>> file_system_access_tokens;
diff --git a/third_party/blink/public/mojom/messaging/task_attribution_id.mojom b/third_party/blink/public/mojom/messaging/task_attribution_id.mojom
new file mode 100644
index 0000000..9049b55
--- /dev/null
+++ b/third_party/blink/public/mojom/messaging/task_attribution_id.mojom
@@ -0,0 +1,10 @@
+// Copyright 2022 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.
+
+module blink.mojom;
+
+// This struct represents a TaskAttributionTracker ID.
+struct TaskAttributionId {
+  uint32 value;
+};
diff --git a/third_party/blink/public/mojom/messaging/transferable_message.mojom b/third_party/blink/public/mojom/messaging/transferable_message.mojom
index 1e80ce0..4b3679e 100644
--- a/third_party/blink/public/mojom/messaging/transferable_message.mojom
+++ b/third_party/blink/public/mojom/messaging/transferable_message.mojom
@@ -10,6 +10,7 @@
 import "third_party/blink/public/mojom/messaging/cloneable_message.mojom";
 import "third_party/blink/public/mojom/messaging/message_port_descriptor.mojom";
 import "third_party/blink/public/mojom/messaging/user_activation_snapshot.mojom";
+import "third_party/blink/public/mojom/messaging/task_attribution_id.mojom";
 
 // A MessagePort is represented as a raw mojo message pipe, as such no interface
 // definition exists for it here. Messages on this pipe are serialized versions
@@ -37,4 +38,6 @@
   //
   // TODO(mustaq): Replace this with a structure for capability-specific bits.
   bool delegate_payment_request;
+  // The ID of the task initiating the message.
+  TaskAttributionId? parent_task_id;
 };
diff --git a/third_party/blink/public/web/web_dom_message_event.h b/third_party/blink/public/web/web_dom_message_event.h
index d8e846a..dcb856b 100644
--- a/third_party/blink/public/web/web_dom_message_event.h
+++ b/third_party/blink/public/web/web_dom_message_event.h
@@ -62,19 +62,9 @@
 
   BLINK_EXPORT WebString Origin() const;
 
-  absl::optional<base::UnguessableToken> locked_agent_cluster_id() const {
-    return locked_agent_cluster_id_;
-  }
-
 #if INSIDE_BLINK
-  explicit WebDOMMessageEvent(
-      MessageEvent* e,
-      absl::optional<base::UnguessableToken> locked_agent_cluster_id)
-      : WebDOMEvent(e), locked_agent_cluster_id_(locked_agent_cluster_id) {}
+  explicit WebDOMMessageEvent(MessageEvent* e) : WebDOMEvent(e) {}
 #endif
-
- private:
-  absl::optional<base::UnguessableToken> locked_agent_cluster_id_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/exported/web_dom_message_event.cc b/third_party/blink/renderer/core/exported/web_dom_message_event.cc
index 72caf09..f03ba28 100644
--- a/third_party/blink/renderer/core/exported/web_dom_message_event.cc
+++ b/third_party/blink/renderer/core/exported/web_dom_message_event.cc
@@ -50,7 +50,7 @@
     const WebFrame* source_frame,
     const WebDocument& target_document,
     WebVector<MessagePortChannel> channels)
-    : WebDOMMessageEvent(MessageEvent::Create(), absl::nullopt) {
+    : WebDOMMessageEvent(MessageEvent::Create()) {
   DOMWindow* window = nullptr;
   if (source_frame)
     window = WebFrame::ToCoreFrame(*source_frame)->DomWindow();
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index fab2d2c..81c9ae6 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -3039,7 +3039,7 @@
   DOMWindowPortalHost::portalHost(*DomWindow())->OnPortalActivated();
   GetPage()->SetInsidePortal(false);
 
-  DCHECK(!data.locked_agent_cluster_id)
+  DCHECK(!data.locked_to_sender_agent_cluster)
       << "portal activation is always cross-agent-cluster and should be "
          "diagnosed early";
   MessagePortArray* ports =
@@ -3650,15 +3650,14 @@
 
   // If the agent cluster id had a value it means this was locked when it
   // was serialized.
-  if (message.locked_agent_cluster_id)
+  if (message.locked_to_sender_agent_cluster)
     message_event->LockToAgentCluster();
 
   // Finally dispatch the message to the DOM Window.
   DomWindow()->DispatchMessageEventWithOriginCheck(
       target_security_origin.get(), message_event,
       std::make_unique<SourceLocation>(String(), 0, 0, nullptr),
-      message.locked_agent_cluster_id ? message.locked_agent_cluster_id.value()
-                                      : base::UnguessableToken());
+      message.sender_agent_cluster_id);
 }
 
 void LocalFrame::JavaScriptMethodExecuteRequest(
diff --git a/third_party/blink/renderer/core/html/portal/html_portal_element.cc b/third_party/blink/renderer/core/html/portal/html_portal_element.cc
index b554a4c..d78427d 100644
--- a/third_party/blink/renderer/core/html/portal/html_portal_element.cc
+++ b/third_party/blink/renderer/core/html/portal/html_portal_element.cc
@@ -151,13 +151,13 @@
   BlinkTransferableMessage data;
   data.message = SerializedScriptValue::UndefinedValue();
   data.message->UnregisterMemoryAllocatedWithCurrentScriptContext();
-  data.sender_origin =
-      GetExecutionContext()->GetSecurityOrigin()->IsolatedCopy();
+  data.sender_origin = context->GetSecurityOrigin()->IsolatedCopy();
   if (ThreadDebugger* debugger =
           ThreadDebugger::From(V8PerIsolateData::MainThreadIsolate())) {
     data.sender_stack_trace_id =
         debugger->StoreCurrentStackTrace("activate (implicit)");
   }
+  data.sender_agent_cluster_id = context->GetAgentClusterID();
 
   PortalContents* portal = std::exchange(portal_, nullptr);
   portal->Activate(std::move(data),
@@ -285,6 +285,7 @@
     return {};
 
   msg.sender_origin = execution_context->GetSecurityOrigin()->IsolatedCopy();
+  msg.sender_agent_cluster_id = execution_context->GetAgentClusterID();
 
   // msg.user_activation is left out; we will probably handle user activation
   // explicitly for activate data.
diff --git a/third_party/blink/renderer/core/html/portal/portal_contents.cc b/third_party/blink/renderer/core/html/portal/portal_contents.cc
index f448593..8bae768 100644
--- a/third_party/blink/renderer/core/html/portal/portal_contents.cc
+++ b/third_party/blink/renderer/core/html/portal/portal_contents.cc
@@ -12,6 +12,7 @@
 #include "third_party/blink/public/mojom/portal/portal.mojom-blink-forward.h"
 #include "third_party/blink/renderer/core/dom/increment_load_event_delay_count.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/remote_frame.h"
 #include "third_party/blink/renderer/core/html/portal/document_portals.h"
 #include "third_party/blink/renderer/core/html/portal/html_portal_element.h"
diff --git a/third_party/blink/renderer/core/html/portal/portal_post_message_helper.cc b/third_party/blink/renderer/core/html/portal/portal_post_message_helper.cc
index 50281f8..291cee8 100644
--- a/third_party/blink/renderer/core/html/portal/portal_post_message_helper.cc
+++ b/third_party/blink/renderer/core/html/portal/portal_post_message_helper.cc
@@ -50,6 +50,9 @@
   transferable_message.sender_origin =
       execution_context->GetSecurityOrigin()->IsolatedCopy();
 
+  transferable_message.sender_agent_cluster_id =
+      execution_context->GetAgentClusterID();
+
   if (ThreadDebugger* debugger =
           ThreadDebugger::From(script_state->GetIsolate())) {
     transferable_message.sender_stack_trace_id =
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc
index 564d550..bea3ab3 100644
--- a/third_party/blink/renderer/core/layout/layout_object.cc
+++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -4506,6 +4506,10 @@
   NOT_DESTROYED();
   // Should have already set a full paint invalidation reason.
   DCHECK(IsFullPaintInvalidationReason(full_paint_invalidation_reason_));
+  // Subtree full paint invalidation can't be delayed.
+  if (bitfields_.SubtreeShouldDoFullPaintInvalidation()) {
+    return;
+  }
 
   bitfields_.SetShouldDelayFullPaintInvalidation(true);
   if (!ShouldCheckForPaintInvalidation()) {
diff --git a/third_party/blink/renderer/core/layout/layout_object.h b/third_party/blink/renderer/core/layout/layout_object.h
index 1b455af..68d71a5 100644
--- a/third_party/blink/renderer/core/layout/layout_object.h
+++ b/third_party/blink/renderer/core/layout/layout_object.h
@@ -2854,8 +2854,11 @@
   }
   bool ShouldDoFullPaintInvalidation() const {
     NOT_DESTROYED();
-    if (!ShouldDelayFullPaintInvalidation() &&
-        full_paint_invalidation_reason_ != PaintInvalidationReason::kNone) {
+    if (ShouldDelayFullPaintInvalidation()) {
+      DCHECK(!bitfields_.SubtreeShouldDoFullPaintInvalidation());
+      return false;
+    }
+    if (full_paint_invalidation_reason_ != PaintInvalidationReason::kNone) {
       DCHECK(IsFullPaintInvalidationReason(full_paint_invalidation_reason_));
       DCHECK(ShouldCheckForPaintInvalidation());
       return true;
diff --git a/third_party/blink/renderer/core/layout/layout_object_test.cc b/third_party/blink/renderer/core/layout/layout_object_test.cc
index a8fcf6a..3d9b0e5 100644
--- a/third_party/blink/renderer/core/layout/layout_object_test.cc
+++ b/third_party/blink/renderer/core/layout/layout_object_test.cc
@@ -563,6 +563,49 @@
   EXPECT_FALSE(object->DescendantNeedsPaintPropertyUpdate());
 }
 
+TEST_F(LayoutObjectTest, DelayFullPaintInvalidation) {
+  LayoutObject* object = GetDocument().body()->GetLayoutObject();
+  object->SetShouldDoFullPaintInvalidation();
+  object->SetShouldDelayFullPaintInvalidation();
+  EXPECT_FALSE(object->ShouldDoFullPaintInvalidation());
+  EXPECT_TRUE(object->ShouldDelayFullPaintInvalidation());
+
+  UpdateAllLifecyclePhasesForTest();
+  EXPECT_FALSE(object->ShouldDoFullPaintInvalidation());
+  // ShouldDelayFullPaintInvalidation is not preserved.
+  EXPECT_TRUE(object->ShouldDelayFullPaintInvalidation());
+
+  object->SetShouldDoFullPaintInvalidation();
+  EXPECT_TRUE(object->ShouldDoFullPaintInvalidation());
+  // ShouldDelayFullPaintInvalidation is reset by
+  // SetShouldDoFullPaintInvalidation().
+  EXPECT_FALSE(object->ShouldDelayFullPaintInvalidation());
+
+  UpdateAllLifecyclePhasesForTest();
+  EXPECT_FALSE(object->ShouldDoFullPaintInvalidation());
+  EXPECT_FALSE(object->ShouldDelayFullPaintInvalidation());
+}
+
+TEST_F(LayoutObjectTest, SubtreeAndDelayFullPaintInvalidation) {
+  LayoutObject* object = GetDocument().body()->GetLayoutObject();
+  object->SetShouldDoFullPaintInvalidation();
+  object->SetShouldDelayFullPaintInvalidation();
+  object->SetSubtreeShouldDoFullPaintInvalidation();
+  EXPECT_TRUE(object->SubtreeShouldDoFullPaintInvalidation());
+  EXPECT_TRUE(object->ShouldDoFullPaintInvalidation());
+  EXPECT_FALSE(object->ShouldDelayFullPaintInvalidation());
+
+  object->SetShouldDelayFullPaintInvalidation();
+  EXPECT_TRUE(object->SubtreeShouldDoFullPaintInvalidation());
+  EXPECT_TRUE(object->ShouldDoFullPaintInvalidation());
+  EXPECT_FALSE(object->ShouldDelayFullPaintInvalidation());
+
+  UpdateAllLifecyclePhasesForTest();
+  EXPECT_FALSE(object->SubtreeShouldDoFullPaintInvalidation());
+  EXPECT_FALSE(object->ShouldDoFullPaintInvalidation());
+  EXPECT_FALSE(object->ShouldDelayFullPaintInvalidation());
+}
+
 TEST_F(LayoutObjectTest, SubtreePaintPropertyUpdateReasons) {
   LayoutObject* object = GetDocument().body()->GetLayoutObject();
   object->AddSubtreePaintPropertyUpdateReason(
diff --git a/third_party/blink/renderer/core/messaging/blink_cloneable_message.h b/third_party/blink/renderer/core/messaging/blink_cloneable_message.h
index 8c23cde..d3a4982 100644
--- a/third_party/blink/renderer/core/messaging/blink_cloneable_message.h
+++ b/third_party/blink/renderer/core/messaging/blink_cloneable_message.h
@@ -28,7 +28,8 @@
   scoped_refptr<blink::SerializedScriptValue> message;
   scoped_refptr<const blink::SecurityOrigin> sender_origin;
   v8_inspector::V8StackTraceId sender_stack_trace_id;
-  absl::optional<base::UnguessableToken> locked_agent_cluster_id;
+  base::UnguessableToken sender_agent_cluster_id;
+  bool locked_to_sender_agent_cluster = false;
 
  private:
   DISALLOW_COPY_AND_ASSIGN(BlinkCloneableMessage);
diff --git a/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.cc b/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.cc
index 518ccfa..5ca8a98 100644
--- a/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.cc
+++ b/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.cc
@@ -46,10 +46,11 @@
                      data.stack_trace_debugger_id_second()),
       data.stack_trace_should_pause());
 
-  absl::optional<base::UnguessableToken> locked_agent_cluster_id;
-  if (!data.ReadLockedAgentClusterId(&locked_agent_cluster_id))
+  base::UnguessableToken sender_agent_cluster_id;
+  if (!data.ReadSenderAgentClusterId(&sender_agent_cluster_id))
     return false;
-  out->locked_agent_cluster_id = locked_agent_cluster_id;
+  out->sender_agent_cluster_id = sender_agent_cluster_id;
+  out->locked_to_sender_agent_cluster = data.locked_to_sender_agent_cluster();
 
   Vector<PendingRemote<blink::mojom::blink::FileSystemAccessTransferToken>>&
       tokens = out->message->FileSystemAccessTokens();
diff --git a/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.h b/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.h
index 17db6e1..4134b3d 100644
--- a/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.h
+++ b/third_party/blink/renderer/core/messaging/blink_cloneable_message_mojom_traits.h
@@ -54,9 +54,14 @@
     return input.sender_stack_trace_id.should_pause;
   }
 
-  static const absl::optional<base::UnguessableToken>& locked_agent_cluster_id(
+  static const base::UnguessableToken& sender_agent_cluster_id(
       const blink::BlinkCloneableMessage& input) {
-    return input.locked_agent_cluster_id;
+    return input.sender_agent_cluster_id;
+  }
+
+  static bool locked_to_sender_agent_cluster(
+      const blink::BlinkCloneableMessage& input) {
+    return input.locked_to_sender_agent_cluster;
   }
 
   static Vector<
diff --git a/third_party/blink/renderer/core/messaging/blink_transferable_message.cc b/third_party/blink/renderer/core/messaging/blink_transferable_message.cc
index a0d7076..7a7ce49 100644
--- a/third_party/blink/renderer/core/messaging/blink_transferable_message.cc
+++ b/third_party/blink/renderer/core/messaging/blink_transferable_message.cc
@@ -32,7 +32,8 @@
   result.message = SerializedScriptValue::Create(
       reinterpret_cast<const char*>(message_wire_data.data()),
       message_wire_data.size());
-  result.locked_agent_cluster_id = cluster_id;
+  result.sender_agent_cluster_id =
+      cluster_id ? *cluster_id : base::UnguessableToken();
 
   // Ports
   Vector<MessagePortChannel> ports = message_event->ReleaseChannels();
@@ -142,7 +143,9 @@
       std::make_pair(message.stack_trace_debugger_id_first,
                      message.stack_trace_debugger_id_second),
       message.stack_trace_should_pause);
-  result.locked_agent_cluster_id = message.locked_agent_cluster_id;
+  result.sender_agent_cluster_id = message.sender_agent_cluster_id;
+  result.locked_to_sender_agent_cluster =
+      message.locked_to_sender_agent_cluster;
   result.ports.AppendRange(message.ports.begin(), message.ports.end());
   for (auto& channel : message.stream_channels) {
     result.message->GetStreams().push_back(
@@ -155,6 +158,8 @@
   }
   result.delegate_payment_request = message.delegate_payment_request;
 
+  result.parent_task_id = message.parent_task_id;
+
   if (!message.array_buffer_contents_array.empty()) {
     SerializedScriptValue::ArrayBufferContentsArray array_buffer_contents_array;
     array_buffer_contents_array.ReserveInitialCapacity(
diff --git a/third_party/blink/renderer/core/messaging/blink_transferable_message.h b/third_party/blink/renderer/core/messaging/blink_transferable_message.h
index 0fc940e..c8c4397 100644
--- a/third_party/blink/renderer/core/messaging/blink_transferable_message.h
+++ b/third_party/blink/renderer/core/messaging/blink_transferable_message.h
@@ -8,6 +8,7 @@
 #include "base/macros.h"
 #include "third_party/blink/public/common/messaging/message_port_channel.h"
 #include "third_party/blink/public/common/messaging/transferable_message.h"
+#include "third_party/blink/public/common/scheduler/task_attribution_id.h"
 #include "third_party/blink/public/mojom/messaging/user_activation_snapshot.mojom-blink.h"
 #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
 #include "third_party/blink/renderer/core/core_export.h"
@@ -41,6 +42,8 @@
 
   bool delegate_payment_request = false;
 
+  absl::optional<scheduler::TaskAttributionId> parent_task_id;
+
  private:
   DISALLOW_COPY_AND_ASSIGN(BlinkTransferableMessage);
 };
diff --git a/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h b/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h
index 9fec27d..dc28d6b 100644
--- a/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h
+++ b/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits.h
@@ -10,6 +10,8 @@
 #include "third_party/blink/public/common/messaging/message_port_channel.h"
 #include "third_party/blink/public/common/messaging/message_port_descriptor.h"
 #include "third_party/blink/public/common/messaging/message_port_descriptor_mojom_traits.h"
+#include "third_party/blink/public/common/messaging/task_attribution_id_mojom_traits.h"
+#include "third_party/blink/public/common/scheduler/task_attribution_id.h"
 #include "third_party/blink/public/mojom/blob/blob.mojom-blink.h"
 #include "third_party/blink/public/mojom/messaging/transferable_message.mojom-shared.h"
 #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h"
@@ -64,6 +66,14 @@
     return input.delegate_payment_request;
   }
 
+  static absl::optional<blink::scheduler::TaskAttributionId> parent_task_id(
+      blink::BlinkTransferableMessage& input) {
+    return input.parent_task_id
+               ? absl::make_optional(blink::scheduler::TaskAttributionId(
+                     input.parent_task_id.value()))
+               : absl::nullopt;
+  }
+
   static bool Read(blink::mojom::TransferableMessageDataView,
                    blink::BlinkTransferableMessage* out);
 };
diff --git a/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits_test.cc b/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits_test.cc
index 027689e..7d1a14c 100644
--- a/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits_test.cc
+++ b/third_party/blink/renderer/core/messaging/blink_transferable_message_mojom_traits_test.cc
@@ -60,6 +60,7 @@
     transferables.array_buffers.push_back(array_buffer);
     BlinkTransferableMessage msg;
     msg.sender_origin = SecurityOrigin::CreateUniqueOpaque();
+    msg.sender_agent_cluster_id = base::UnguessableToken::Create();
     msg.message = BuildSerializedScriptValue(scope.GetIsolate(), v8_buffer,
                                              transferables);
     mojo_message = mojom::blink::TransferableMessage::SerializeAsMessage(&msg);
@@ -100,6 +101,7 @@
   transferables.array_buffers.push_back(original_array_buffer);
   BlinkTransferableMessage msg;
   msg.sender_origin = SecurityOrigin::CreateUniqueOpaque();
+  msg.sender_agent_cluster_id = base::UnguessableToken::Create();
   msg.message =
       BuildSerializedScriptValue(scope.GetIsolate(), v8_buffer, transferables);
   mojo::Message mojo_message =
@@ -142,6 +144,7 @@
     transferables.image_bitmaps.push_back(image_bitmap);
     BlinkTransferableMessage msg;
     msg.sender_origin = SecurityOrigin::CreateUniqueOpaque();
+    msg.sender_agent_cluster_id = base::UnguessableToken::Create();
     msg.message =
         BuildSerializedScriptValue(scope.GetIsolate(), wrapper, transferables);
     mojo_message = mojom::blink::TransferableMessage::SerializeAsMessage(&msg);
@@ -168,6 +171,7 @@
   transferables.image_bitmaps.push_back(std::move(original_bitmap));
   BlinkTransferableMessage msg;
   msg.sender_origin = SecurityOrigin::CreateUniqueOpaque();
+  msg.sender_agent_cluster_id = base::UnguessableToken::Create();
   msg.message =
       BuildSerializedScriptValue(scope.GetIsolate(), wrapper, transferables);
   mojo::Message mojo_message =
diff --git a/third_party/blink/renderer/core/messaging/message_port.cc b/third_party/blink/renderer/core/messaging/message_port.cc
index bacf27d..8610f88 100644
--- a/third_party/blink/renderer/core/messaging/message_port.cc
+++ b/third_party/blink/renderer/core/messaging/message_port.cc
@@ -33,6 +33,7 @@
 #include "third_party/blink/public/platform/task_type.h"
 #include "third_party/blink/public/platform/web_string.h"
 #include "third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_post_message_options.h"
 #include "third_party/blink/renderer/core/events/message_event.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
@@ -47,6 +48,7 @@
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/bindings/script_state.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
+#include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h"
 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
 
@@ -117,11 +119,8 @@
   if (debugger)
     msg.sender_stack_trace_id = debugger->StoreCurrentStackTrace("postMessage");
 
-  if (msg.message->IsLockedToAgentCluster()) {
-    msg.locked_agent_cluster_id = GetExecutionContext()->GetAgentClusterID();
-  } else {
-    msg.locked_agent_cluster_id = absl::nullopt;
-  }
+  msg.sender_agent_cluster_id = GetExecutionContext()->GetAgentClusterID();
+  msg.locked_to_sender_agent_cluster = msg.message->IsLockedToAgentCluster();
 
   mojo::Message mojo_message =
       mojom::blink::TransferableMessage::WrapAsMessage(std::move(msg));
@@ -276,16 +275,17 @@
     return false;
   }
 
+  ExecutionContext* context = GetExecutionContext();
   // WorkerGlobalScope::close() in Worker onmessage handler should prevent
   // the next message from dispatching.
-  if (auto* scope = DynamicTo<WorkerGlobalScope>(GetExecutionContext())) {
+  if (auto* scope = DynamicTo<WorkerGlobalScope>(context)) {
     if (scope->IsClosing())
       return true;
   }
 
   Event* evt = CreateMessageEvent(message);
 
-  v8::Isolate* isolate = GetExecutionContext()->GetIsolate();
+  v8::Isolate* isolate = context->GetIsolate();
   ThreadDebugger* debugger = ThreadDebugger::From(isolate);
   if (debugger)
     debugger->ExternalAsyncTaskStarted(message.sender_stack_trace_id);
@@ -307,8 +307,9 @@
     }
   }
 
-  if (message.locked_agent_cluster_id) {
-    if (!context->IsSameAgentCluster(*message.locked_agent_cluster_id)) {
+  if (message.locked_to_sender_agent_cluster) {
+    DCHECK(message.sender_agent_cluster_id);
+    if (!context->IsSameAgentCluster(message.sender_agent_cluster_id)) {
       UseCounter::Count(
           context,
           WebFeature::kMessageEventSharedArrayBufferDifferentAgentCluster);
@@ -333,6 +334,7 @@
         message.user_activation->has_been_active,
         message.user_activation->was_active);
   }
+
   return MessageEvent::Create(ports, std::move(message.message),
                               user_activation);
 }
diff --git a/third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.cc b/third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.cc
index fe77576..6ddd793 100644
--- a/third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.cc
+++ b/third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.cc
@@ -79,6 +79,7 @@
   msg.message = std::move(value);
   msg.sender_origin =
       GetExecutionContext()->GetSecurityOrigin()->IsolatedCopy();
+  msg.sender_agent_cluster_id = GetExecutionContext()->GetAgentClusterID();
   remote_client_->OnMessage(std::move(msg));
 }
 
@@ -109,9 +110,9 @@
 void BroadcastChannel::OnMessage(BlinkCloneableMessage message) {
   // Queue a task to dispatch the event.
   MessageEvent* event;
-  if (!message.locked_agent_cluster_id ||
+  if (!message.locked_to_sender_agent_cluster ||
       GetExecutionContext()->IsSameAgentCluster(
-          *message.locked_agent_cluster_id)) {
+          message.sender_agent_cluster_id)) {
     event = MessageEvent::Create(
         nullptr, std::move(message.message),
         GetExecutionContext()->GetSecurityOrigin()->ToString());
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker.cc b/third_party/blink/renderer/modules/service_worker/service_worker.cc
index a0e37ac..4fbe857 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker.cc
@@ -98,11 +98,8 @@
   if (exception_state.HadException())
     return;
 
-  if (msg.message->IsLockedToAgentCluster()) {
-    msg.locked_agent_cluster_id = GetExecutionContext()->GetAgentClusterID();
-  } else {
-    msg.locked_agent_cluster_id = absl::nullopt;
-  }
+  msg.sender_agent_cluster_id = GetExecutionContext()->GetAgentClusterID();
+  msg.locked_to_sender_agent_cluster = msg.message->IsLockedToAgentCluster();
 
   host_->PostMessageToServiceWorker(std::move(msg));
 }
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_client.cc b/third_party/blink/renderer/modules/service_worker/service_worker_client.cc
index 6110ee2..fee1582 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_client.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_client.cc
@@ -112,11 +112,8 @@
   if (exception_state.HadException())
     return;
 
-  if (msg.message->IsLockedToAgentCluster()) {
-    msg.locked_agent_cluster_id = context->GetAgentClusterID();
-  } else {
-    msg.locked_agent_cluster_id = absl::nullopt;
-  }
+  msg.sender_agent_cluster_id = context->GetAgentClusterID();
+  msg.locked_to_sender_agent_cluster = msg.message->IsLockedToAgentCluster();
 
   To<ServiceWorkerGlobalScope>(context)
       ->GetServiceWorkerHost()
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_container.cc b/third_party/blink/renderer/modules/service_worker/service_worker_container.cc
index 29a82d5..7455d4e 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_container.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_container.cc
@@ -649,9 +649,9 @@
     }
   }
   if (!event) {
-    if (!msg.locked_agent_cluster_id ||
+    if (!msg.locked_to_sender_agent_cluster ||
         GetExecutionContext()->IsSameAgentCluster(
-            *msg.locked_agent_cluster_id)) {
+            msg.sender_agent_cluster_id)) {
       event = MessageEvent::Create(
           ports, std::move(msg.message),
           GetExecutionContext()->GetSecurityOrigin()->ToString(),
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
index 02dfa4f..d010b3e 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
@@ -1418,9 +1418,9 @@
       }
     }
     if (!event_to_dispatch) {
-      if (!msg.locked_agent_cluster_id ||
+      if (!msg.locked_to_sender_agent_cluster ||
           GetExecutionContext()->IsSameAgentCluster(
-              *msg.locked_agent_cluster_id)) {
+              msg.sender_agent_cluster_id)) {
         observer = MakeGarbageCollected<WaitUntilObserver>(
             this, WaitUntilObserver::kMessage, event_id);
         event_to_dispatch = ExtendableMessageEvent::Create(
@@ -1454,9 +1454,10 @@
     }
   }
   if (!event_to_dispatch) {
-    if (!msg.locked_agent_cluster_id ||
+    DCHECK(!msg.locked_to_sender_agent_cluster || msg.sender_agent_cluster_id);
+    if (!msg.locked_to_sender_agent_cluster ||
         GetExecutionContext()->IsSameAgentCluster(
-            *msg.locked_agent_cluster_id)) {
+            msg.sender_agent_cluster_id)) {
       observer = MakeGarbageCollected<WaitUntilObserver>(
           this, WaitUntilObserver::kMessage, event_id);
       event_to_dispatch = ExtendableMessageEvent::Create(
diff --git a/third_party/blink/renderer/platform/image-encoders/image_encoder.cc b/third_party/blink/renderer/platform/image-encoders/image_encoder.cc
index 679c9fb..dc6cc12 100644
--- a/third_party/blink/renderer/platform/image-encoders/image_encoder.cc
+++ b/third_party/blink/renderer/platform/image-encoders/image_encoder.cc
@@ -14,7 +14,7 @@
 
 #include "jpeglib.h"  // for JPEG_MAX_DIMENSION
 
-#include "third_party/libwebp/src/webp/encode.h"  // for WEBP_MAX_DIMENSION
+#include "third_party/libwebp/src/src/webp/encode.h"  // for WEBP_MAX_DIMENSION
 
 namespace blink {
 
diff --git a/third_party/blink/web_tests/wpt_internal/task-tracking/messageport-postmessage-same-origin-iframe.html b/third_party/blink/web_tests/wpt_internal/task-tracking/messageport-postmessage-same-origin-iframe.html
new file mode 100644
index 0000000..7b1883c
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/task-tracking/messageport-postmessage-same-origin-iframe.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Verify that postmessage tasks can be properly tracked.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+promise_test(t => {
+  const scriptId = scheduler.taskId;
+  const channel = new MessageChannel();
+
+  const frame = document.createElement("iframe");
+  frame.addEventListener("load", () => {
+    frame.contentWindow.postMessage("port", "*", [channel.port2]);
+  });
+  frame.src = "resources/messageport-postmessage-iframe.html";
+  document.body.appendChild(frame);
+
+  return new Promise((resolve, reject) => {
+    channel.port1.onmessage = e => {
+      try {
+        assert_equals(scheduler.isAncestor(e.data), "ancestor");
+        resolve();
+      } catch(e) {
+        reject(e);
+      }
+    }
+  });
+}, "Same-origin iframe MessagePort postMessage task properly detects its parent task.");
+
+</script>
+</body>
+</html>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/wpt_internal/task-tracking/resources/messageport-postmessage-iframe.html b/third_party/blink/web_tests/wpt_internal/task-tracking/resources/messageport-postmessage-iframe.html
new file mode 100644
index 0000000..cd36e96
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/task-tracking/resources/messageport-postmessage-iframe.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<html>
+  <script>
+    window.addEventListener('message', e => {
+      const port = e.ports?.[0];
+      port.postMessage(scheduler.taskId);
+    });
+  </script>
+</html>
diff --git a/third_party/blink/web_tests/wpt_internal/task-tracking/resources/messageport-postmessage-iframe.html.headers b/third_party/blink/web_tests/wpt_internal/task-tracking/resources/messageport-postmessage-iframe.html.headers
new file mode 100644
index 0000000..79a20f3
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/task-tracking/resources/messageport-postmessage-iframe.html.headers
@@ -0,0 +1 @@
+Origin-Agent-Cluster: ?1
diff --git a/third_party/blink/web_tests/wpt_internal/task-tracking/track-messageport-postmessage-cross-origin-iframe.html b/third_party/blink/web_tests/wpt_internal/task-tracking/track-messageport-postmessage-cross-origin-iframe.html
new file mode 100644
index 0000000..28bf92d
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/task-tracking/track-messageport-postmessage-cross-origin-iframe.html
@@ -0,0 +1,39 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Verify that postmessage tasks can be properly tracked.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+</head>
+<body>
+<script>
+promise_test(t => {
+  const scriptId = scheduler.taskId;
+  const channel = new MessageChannel();
+  const {REMOTE_ORIGIN} = get_host_info();
+
+  const frame = document.createElement("iframe");
+  frame.addEventListener("load", () => {
+    frame.contentWindow.postMessage("port", "*", [channel.port2]);
+  });
+  frame.src = `${REMOTE_ORIGIN}/wpt_internal/task-tracking/resources/messageport-postmessage-iframe.html`;
+  document.body.appendChild(frame);
+
+  return new Promise((resolve, reject) => {
+    channel.port1.onmessage = e => {
+      try {
+        assert_equals(scheduler.isAncestor(e.data), "not ancestor");
+        resolve();
+      } catch(e) {
+        reject(e);
+      }
+    }
+  });
+}, "Cross-origin iframe MessagePort postMessage task properly detects its parent task.");
+
+</script>
+</body>
+</html>
+
diff --git a/third_party/blink/web_tests/wpt_internal/task-tracking/track-postmessage.html b/third_party/blink/web_tests/wpt_internal/task-tracking/track-postmessage.html
new file mode 100644
index 0000000..8615af0
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/task-tracking/track-postmessage.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<meta charset="utf-8">
+<title>Verify that postmessage tasks can be properly tracked.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<script>
+promise_test(t => {
+  const scriptId = scheduler.taskId;
+  const channel = new MessageChannel();
+
+  return new Promise((resolve, reject) => {
+    channel.port1.onmessage = () => {
+      try {
+        assert_equals(scheduler.isAncestor(scriptId), "ancestor");
+        resolve();
+      } catch(e) {
+        reject(e);
+      }
+    }
+    channel.port2.postMessage("hello");
+  });
+}, "Same document MessagePort postMessage task properly detects its parent.");
+
+</script>
+</body>
+</html>
\ No newline at end of file