Pass the AgentClusterKey from the browser process [chromium/src : main]

115 views
Skip to first unread message

AI Code Reviewer (Gerrit)

unread,
Oct 14, 2025, 12:08:41 PM10/14/25
to Camille Lamy, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org

AI Code Reviewer added 3 comments

File third_party/blink/renderer/core/execution_context/agent.h
Line 100, Patchset 2 (Latest): AgentClusterKey* agent_cluster_key);
AI Code Reviewer . unresolved

Blink Style Guide: Naming - May leave obvious parameter names out of function declarations. The parameter name `agent_cluster_key` can be omitted from the function declaration in the header file as the type `AgentClusterKey*` is self-descriptive.

_To keep this interaction as brief and non-intrusive as possible, please consider responding with one of following options:
**Done** | **Won't fix**: reason | **b/<bug_id>** | **Invalid:** reason

This comment was generated by [Experimental Blink C++ Code Review Agent](http://go/blink-c++-code-review-agent).AI reviews can sometimes be inaccurate; We appreciate your 🙏 feedback 🙏 to help us improve.[File a bug](http://go/blink-c++-code-review-agent-feedback) | [Provide feedback on chat](https://chat.google.com/room/AAQA0zhQHe0?cls=4) | [Opt-out](https://ganpati2.corp.google.com/group/peep-genai-blink-agent-optout.prod)_

File third_party/blink/renderer/core/execution_context/window_agent.h
Line 38, Patchset 2 (Latest): WindowAgent(AgentGroupScheduler& agent_group_scheduler,
AI Code Reviewer . unresolved

Blink Style Guide: Naming - May leave obvious parameter names out of function declarations. The parameter name `agent_cluster_key` can be omitted from the function declaration in the header file as the type `AgentClusterKey*` is self-descriptive.

_To keep this interaction as brief and non-intrusive as possible, please consider responding with one of following options:
**Done** | **Won't fix**: reason | **b/<bug_id>** | **Invalid:** reason

This comment was generated by [Experimental Blink C++ Code Review Agent](http://go/blink-c++-code-review-agent).AI reviews can sometimes be inaccurate; We appreciate your 🙏 feedback 🙏 to help us improve.[File a bug](http://go/blink-c++-code-review-agent-feedback) | [Provide feedback on chat](https://chat.google.com/room/AAQA0zhQHe0?cls=4) | [Opt-out](https://ganpati2.corp.google.com/group/peep-genai-blink-agent-optout.prod)_

File third_party/blink/renderer/core/execution_context/window_agent_factory.h
Line 42, Patchset 2 (Latest): WindowAgent* GetAgentForAgentClusterKey(
AI Code Reviewer . unresolved

Blink Style Guide: Prefer enums or StrongAliases to bare bools for function parameters. Consider using an enum for `has_potential_universal_access_privilege` to improve clarity at call sites, for example: `enum class UniversalAccessPrivilege { kNo, kYes };`.

_To keep this interaction as brief and non-intrusive as possible, please consider responding with one of following options:
**Done** | **Won't fix**: reason | **b/<bug_id>** | **Invalid:** reason

This comment was generated by [Experimental Blink C++ Code Review Agent](http://go/blink-c++-code-review-agent).AI reviews can sometimes be inaccurate; We appreciate your 🙏 feedback 🙏 to help us improve.[File a bug](http://go/blink-c++-code-review-agent-feedback) | [Provide feedback on chat](https://chat.google.com/room/AAQA0zhQHe0?cls=4) | [Opt-out](https://ganpati2.corp.google.com/group/peep-genai-blink-agent-optout.prod)_

Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
  • requirement satisfiedCode-Coverage
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedNo-Unresolved-Comments
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: chromium/src
Gerrit-Branch: main
Gerrit-Change-Id: Ibb98071005816e53e766fbcbe3fbcb642ee17592
Gerrit-Change-Number: 7041044
Gerrit-PatchSet: 2
Gerrit-Owner: Camille Lamy <cl...@chromium.org>
Gerrit-Reviewer: Camille Lamy <cl...@chromium.org>
Gerrit-CC: AI Code Reviewer <peep-gen...@system.gserviceaccount.com>
Gerrit-CC: Hiroki Nakagawa <nhi...@chromium.org>
Gerrit-CC: Kentaro Hara <har...@chromium.org>
Gerrit-CC: Nate Chapin <jap...@chromium.org>
Gerrit-CC: Raphael Kubo da Costa <ku...@igalia.com>
Gerrit-Comment-Date: Tue, 14 Oct 2025 16:08:36 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
satisfied_requirement
unsatisfied_requirement
open
diffy

Camille Lamy (Gerrit)

unread,
Oct 24, 2025, 10:38:57 AM10/24/25
to AI Code Reviewer, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org

Camille Lamy added 3 comments

File third_party/blink/renderer/core/execution_context/agent.h
Line 100, Patchset 2: AgentClusterKey* agent_cluster_key);
AI Code Reviewer . resolved

Blink Style Guide: Naming - May leave obvious parameter names out of function declarations. The parameter name `agent_cluster_key` can be omitted from the function declaration in the header file as the type `AgentClusterKey*` is self-descriptive.

_To keep this interaction as brief and non-intrusive as possible, please consider responding with one of following options:
**Done** | **Won't fix**: reason | **b/<bug_id>** | **Invalid:** reason

This comment was generated by [Experimental Blink C++ Code Review Agent](http://go/blink-c++-code-review-agent).AI reviews can sometimes be inaccurate; We appreciate your 🙏 feedback 🙏 to help us improve.[File a bug](http://go/blink-c++-code-review-agent-feedback) | [Provide feedback on chat](https://chat.google.com/room/AAQA0zhQHe0?cls=4) | [Opt-out](https://ganpati2.corp.google.com/group/peep-genai-blink-agent-optout.prod)_

Camille Lamy

Done

File third_party/blink/renderer/core/execution_context/window_agent.h
Line 38, Patchset 2: WindowAgent(AgentGroupScheduler& agent_group_scheduler,
AI Code Reviewer . resolved

Blink Style Guide: Naming - May leave obvious parameter names out of function declarations. The parameter name `agent_cluster_key` can be omitted from the function declaration in the header file as the type `AgentClusterKey*` is self-descriptive.

_To keep this interaction as brief and non-intrusive as possible, please consider responding with one of following options:
**Done** | **Won't fix**: reason | **b/<bug_id>** | **Invalid:** reason

This comment was generated by [Experimental Blink C++ Code Review Agent](http://go/blink-c++-code-review-agent).AI reviews can sometimes be inaccurate; We appreciate your 🙏 feedback 🙏 to help us improve.[File a bug](http://go/blink-c++-code-review-agent-feedback) | [Provide feedback on chat](https://chat.google.com/room/AAQA0zhQHe0?cls=4) | [Opt-out](https://ganpati2.corp.google.com/group/peep-genai-blink-agent-optout.prod)_

Camille Lamy

Done

File third_party/blink/renderer/core/execution_context/window_agent_factory.h
Line 42, Patchset 2: WindowAgent* GetAgentForAgentClusterKey(
AI Code Reviewer . resolved

Blink Style Guide: Prefer enums or StrongAliases to bare bools for function parameters. Consider using an enum for `has_potential_universal_access_privilege` to improve clarity at call sites, for example: `enum class UniversalAccessPrivilege { kNo, kYes };`.

_To keep this interaction as brief and non-intrusive as possible, please consider responding with one of following options:
**Done** | **Won't fix**: reason | **b/<bug_id>** | **Invalid:** reason

This comment was generated by [Experimental Blink C++ Code Review Agent](http://go/blink-c++-code-review-agent).AI reviews can sometimes be inaccurate; We appreciate your 🙏 feedback 🙏 to help us improve.[File a bug](http://go/blink-c++-code-review-agent-feedback) | [Provide feedback on chat](https://chat.google.com/room/AAQA0zhQHe0?cls=4) | [Opt-out](https://ganpati2.corp.google.com/group/peep-genai-blink-agent-optout.prod)_

Camille Lamy

Acknowledged

Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: chromium/src
    Gerrit-Branch: main
    Gerrit-Change-Id: Ibb98071005816e53e766fbcbe3fbcb642ee17592
    Gerrit-Change-Number: 7041044
    Gerrit-PatchSet: 12
    Gerrit-Owner: Camille Lamy <cl...@chromium.org>
    Gerrit-Reviewer: Camille Lamy <cl...@chromium.org>
    Gerrit-CC: AI Code Reviewer <peep-gen...@system.gserviceaccount.com>
    Gerrit-CC: Hiroki Nakagawa <nhi...@chromium.org>
    Gerrit-CC: Kentaro Hara <har...@chromium.org>
    Gerrit-CC: Nate Chapin <jap...@chromium.org>
    Gerrit-CC: Raphael Kubo da Costa <ku...@igalia.com>
    Gerrit-Comment-Date: Fri, 24 Oct 2025 14:38:44 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: AI Code Reviewer <peep-gen...@system.gserviceaccount.com>
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Camille Lamy (Gerrit)

    unread,
    Oct 24, 2025, 11:27:58 AM10/24/25
    to Alex Moshchuk, Daniel Cheng, AI Code Reviewer, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org
    Attention needed from Alex Moshchuk and Daniel Cheng

    Camille Lamy added 4 comments

    Patchset-level comments
    File-level comment, Patchset 13 (Latest):
    Camille Lamy . resolved

    @Alex: PTAL. This is moving the agent cluster decision in the browser process and passing it to the renderer process. I have taken the option to try to use the AgentClusterKey from SiteInfo as much as possible, as I think we want to move to using it most of the time eventually. However, if we want to keep closer to the current code, we could also just check whether we have an origin-keyed/site-keyed/COI key and always update the origin/site of the key.

    File content/browser/renderer_host/navigation_request.cc
    Line 4011, Patchset 13 (Latest): // Now build the appropriate AgentClusterKey for commit, starting with the
    Camille Lamy . unresolved

    I have been considering moving all the code below to SiteInfo, as it essentially undoes all the special cases of GetAgentClusterKeyForURL, so maybe having the two in the same place to compare would be nice.

    Line 4136, Patchset 13 (Latest): bool is_navigation_to_existing_entry =
    Camille Lamy . unresolved

    I still have one test failing for this specific case. I think it's a case of a subframe navigation to an existing subframe NavigationEntry. I'm not sure how to write the condition for it.

    File third_party/blink/public/web/web_agent_cluster_key.h
    Line 23, Patchset 13 (Latest): mojom::CrossOriginIsolationMode cross_origin_isolation_mode)
    Camille Lamy . unresolved

    The presubmit checks complain about non-Blink mojom usage, but since this is the public interface that seems to be the correct thing to do to eventually translate into Blink mojom types. I'm not sure where I need to authorize this as I would have imagined that third_party/blink/public/web would not be covered by the check.

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Alex Moshchuk
    • Daniel Cheng
    Submit Requirements:
      • requirement satisfiedCode-Coverage
      • requirement is not satisfiedCode-Owners
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement is not satisfiedReview-Enforcement
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: chromium/src
      Gerrit-Branch: main
      Gerrit-Change-Id: Ibb98071005816e53e766fbcbe3fbcb642ee17592
      Gerrit-Change-Number: 7041044
      Gerrit-PatchSet: 13
      Gerrit-Owner: Camille Lamy <cl...@chromium.org>
      Gerrit-Reviewer: Alex Moshchuk <ale...@chromium.org>
      Gerrit-Reviewer: Camille Lamy <cl...@chromium.org>
      Gerrit-Reviewer: Daniel Cheng <dch...@chromium.org>
      Gerrit-CC: AI Code Reviewer <peep-gen...@system.gserviceaccount.com>
      Gerrit-CC: Hiroki Nakagawa <nhi...@chromium.org>
      Gerrit-CC: Kentaro Hara <har...@chromium.org>
      Gerrit-CC: Nate Chapin <jap...@chromium.org>
      Gerrit-CC: Raphael Kubo da Costa <ku...@igalia.com>
      Gerrit-Attention: Alex Moshchuk <ale...@chromium.org>
      Gerrit-Attention: Daniel Cheng <dch...@chromium.org>
      Gerrit-Comment-Date: Fri, 24 Oct 2025 15:27:41 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy

      Daniel Cheng (Gerrit)

      unread,
      Oct 27, 2025, 7:09:19 PM10/27/25
      to Camille Lamy, Alex Moshchuk, Daniel Cheng, AI Code Reviewer, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org
      Attention needed from Alex Moshchuk and Camille Lamy

      Daniel Cheng added 10 comments

      File content/browser/service_worker/service_worker_test_utils.cc
      Line 284, Patchset 13 (Latest): commit_params->agent_cluster_key = blink::mojom::AgentClusterKey::New();
      Daniel Cheng . unresolved

      Should `blink::CreateCommitNavigationParams()` also just set this? Seems like it's not really optional anyway.

      (Though I guess it becomes messy if we make the agent cluster key a union as I suggested below–does the agent cluster key actually have three distinct states? Site, origin, and neither? Though based off the WebAgentClusterKey class... I'm not actually sure)

      File content/public/test/render_view_test.cc
      Line 758, Patchset 13 (Latest): commit_params->agent_cluster_key = blink::mojom::AgentClusterKey::New();
      Daniel Cheng . resolved

      And that would help with some of the boilerplate elsewhere I think

      File third_party/blink/public/mojom/frame/agent_cluster_key.mojom
      Line 10, Patchset 13 (Latest):// Indicates if cross-origin isolation gives access to cross-origin isolated
      Daniel Cheng . unresolved

      Nit: extra space

      Line 24, Patchset 13 (Latest): // when cross-origin sioaltion is enabled by COOP + COEP. When cross-origin
      Daniel Cheng . unresolved

      Nit: isolation.

      Line 42, Patchset 13 (Latest): // Additionally, the AgentClusterKey might have a CrossOriginIsolationKey is
      Daniel Cheng . unresolved

      if

      Line 37, Patchset 13 (Latest): // The AgentClusterKey has either a site URL or an origin. In the first case,
      // the AgentClusterKey is site keyed, in the second case, it is origin keyed.
      url.mojom.Url? url;
      url.mojom.Origin? origin;

      // Additionally, the AgentClusterKey might have a CrossOriginIsolationKey is
      // the context is cross-origin isolated. In this case, the AgentClusterKey
      // must be origin-keyed.
      // https://wicg.github.io/document-isolation-policy/#coi-agent-cluster-key
      CrossOriginIsolationKey? isolation_key;
      Daniel Cheng . unresolved

      It seems like maybe this should be a union consisting of either a `url.mojom.Url` or a `OriginKeyedAgentClusterKey` struct containing a `url.mojom.Origin` and a `CrossOriginIsolationKey` (not sure if the COI key is required in the case of origin-keyed origins)

      File third_party/blink/public/web/web_agent_cluster_key.h
      Line 40, Patchset 13 (Latest): std::optional<WebCrossOriginIsolationKey> isolation_key;
      Daniel Cheng . unresolved

      As noted above, can we restructure this so it's a variant of a WebURL and a struct containing a WebSecurityOrigin and an optional key?

      Line 23, Patchset 13 (Latest): mojom::CrossOriginIsolationMode cross_origin_isolation_mode)
      Camille Lamy . unresolved

      The presubmit checks complain about non-Blink mojom usage, but since this is the public interface that seems to be the correct thing to do to eventually translate into Blink mojom types. I'm not sure where I need to authorize this as I would have imagined that third_party/blink/public/web would not be covered by the check.

      Daniel Cheng

      I agree this is fine; can you link me to an example of the presubmit warning?

      File third_party/blink/renderer/core/execution_context/agent_cluster_key.h
      Line 33, Patchset 13 (Latest): AgentClusterKey();
      Daniel Cheng . unresolved

      What does this create by default? Is it site keyed, origin keyed, or neither?

      File third_party/blink/renderer/platform/weborigin/security_origin.h
      Line 414, Patchset 13 (Latest): // the custom HashTraits defined at the end of this file.
      Daniel Cheng . unresolved

      I don't think we should have both--or at the very least, one should delegate to the other.
      Can you file a TODO to clean this up? Is there a failing test someone can run when they are trying to figure out what's going wrong here?

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Alex Moshchuk
      • Camille Lamy
      Gerrit-Attention: Camille Lamy <cl...@chromium.org>
      Gerrit-Comment-Date: Mon, 27 Oct 2025 23:09:10 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Camille Lamy <cl...@chromium.org>
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy

      Alex Moshchuk (Gerrit)

      unread,
      Oct 31, 2025, 8:20:11 PM10/31/25
      to Camille Lamy, Code Review Nudger, Daniel Cheng, AI Code Reviewer, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org
      Attention needed from Camille Lamy

      Alex Moshchuk added 11 comments

      Patchset-level comments
      Alex Moshchuk . resolved

      Thanks! I'll defer to Daniel on the blink changes; a few comments on the content side.

      File content/browser/agent_cluster_key.h
      Line 36, Patchset 13 (Latest):class CONTENT_EXPORT AgentClusterKey {
      Alex Moshchuk . unresolved

      I guess I'm a bit worried that we now have 3-4 places that define AgentClusterKeys (here, mojo, WebAgentClusterKey, and blink::AgentClusterKey), and they might get out of sync. Maybe it's intentional that the browser-side and renderer-side keys aren't going to be identical (e.g., the renderer doesn't need oac_status_), though we could at least add comments reminding what else must be updated when someone wants to add something to the AgentClusterKey? And maybe we could use LINT.IfChange to enforce that things stay updated together where it makes sense?

      Line 35, Patchset 13 (Latest):// SiteInfo, as it will only duplicate the information in AgentClusterKey.
      Alex Moshchuk . unresolved

      Might be worth updating this documentation to mention the other definitions of agent cluster key used in the renderer (and for sending this key to the renderer), and how they differ practically from this key.

      File content/browser/renderer_host/navigation_request.cc
      Line 4011, Patchset 13 (Latest): // Now build the appropriate AgentClusterKey for commit, starting with the
      Camille Lamy . unresolved

      I have been considering moving all the code below to SiteInfo, as it essentially undoes all the special cases of GetAgentClusterKeyForURL, so maybe having the two in the same place to compare would be nice.

      Alex Moshchuk

      Yes, it might be worth moving this code into a separate helper, and maybe SiteInfo is a better place for it, as this function is getting long. It might be worth keeping the focus of this function on the OAC stuff as before, and then computing the key_to_commit as a separate step.

      One high-level concern I have with the content/browser side of this CL is indeed about introducing another place for handling these special cases, and moreover trying to reconstruct how we computed a SiteInfo based on the AgentClusterKey after the fact, which seems fragile (and potentially hard to maintain for future changes to the process model). Do you think it could be better to compute both the agent cluster key for SiteInfo and the agent cluster key to send to the renderer in the same place in GetAgentClusterKeyForURL? Basically, have all the special cases in one place, but computing two keys? Or at least compute the should_update_origin_or_site bit there, so that we know that the site URL we ended up with in SiteInfo is a Chrome-process-model specific URL and not what the actual agent cluster key should be per spec.

      (I'm not sure this is better or even feasible, just curious if it's worth thinking about at all.)

      Line 4019, Patchset 13 (Latest): // isolation key. Currently, pages cross-origin isolated through COOP and COEP
      // are not given a cross-origin isolated AgentClusterKey. Override the
      Alex Moshchuk . unresolved

      It seems that this will be addressed by your https://chromium-review.googlesource.com/c/chromium/src/+/6516176? Will you be landing this CL before or after that?

      Line 4022, Patchset 13 (Latest): // the document already as a cross-origin isolated AgentClusterKey, which
      Alex Moshchuk . unresolved

      has

      Line 4122, Patchset 13 (Latest): origin.scheme())) {
      Alex Moshchuk . unresolved

      Is this to undo the case [here](https://source.chromium.org/chromium/chromium/src/+/main:content/browser/site_info.cc;l=791;drc=7ce25d3420a0eb77c46618536b3434f7b9ceef66)? Does it matter that this only applies to top-chrome WebUIs and not all WebUIs? Should it be more restricted to IsWebUIAndUsesTLDForProcessLockURL cases?

      Line 4129, Patchset 13 (Latest): should_update_origin_or_site = true;
      Alex Moshchuk . unresolved

      I guess we don't have this problem with features::kDefaultSiteInstanceGroups?

      Line 4134, Patchset 13 (Latest): // redirect causes the response URL to no longer match the original
      // SiteInstance. In that case, create a new AgentClusterKey.
      Alex Moshchuk . unresolved

      Is this actually intended behavior and not a bug? I think we try to disqualify the original SiteInstance in the NavigationEntry from being reused if it's no longer suitable for the redirected URL, with things like RenderFrameHostManager::CanUseDestinationInstance(). I'm surprised it would need its own condition here, as it seems like it might be violating our SiteInstance assignment rules.

      Line 4166, Patchset 13 (Latest): if (key_to_commit.IsSiteKeyed()) {
      Alex Moshchuk . unresolved

      Can there be some sort of conversion function to populate a mojo AgentClusterKey from a normal one, ideally in agent_cluster_key.*?

      File content/browser/renderer_host/render_process_host_impl.cc
      Line 3370, Patchset 13 (Latest): process_lock.agent_cluster_key().IsCrossOriginIsolated();
      Alex Moshchuk . unresolved

      Can this be cleaned up independently, or does it depend on something in this CL?

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Camille Lamy
      Submit Requirements:
      • requirement satisfiedCode-Coverage
      • requirement is not satisfiedCode-Owners
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement is not satisfiedReview-Enforcement
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: chromium/src
      Gerrit-Branch: main
      Gerrit-Change-Id: Ibb98071005816e53e766fbcbe3fbcb642ee17592
      Gerrit-Change-Number: 7041044
      Gerrit-PatchSet: 13
      Gerrit-Owner: Camille Lamy <cl...@chromium.org>
      Gerrit-Reviewer: Alex Moshchuk <ale...@chromium.org>
      Gerrit-Reviewer: Camille Lamy <cl...@chromium.org>
      Gerrit-Reviewer: Daniel Cheng <dch...@chromium.org>
      Gerrit-CC: AI Code Reviewer <peep-gen...@system.gserviceaccount.com>
      Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
      Gerrit-CC: Hiroki Nakagawa <nhi...@chromium.org>
      Gerrit-CC: Kentaro Hara <har...@chromium.org>
      Gerrit-CC: Nate Chapin <jap...@chromium.org>
      Gerrit-CC: Raphael Kubo da Costa <ku...@igalia.com>
      Gerrit-Attention: Camille Lamy <cl...@chromium.org>
      Gerrit-Comment-Date: Sat, 01 Nov 2025 00:20:00 +0000
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy

      Camille Lamy (Gerrit)

      unread,
      Nov 6, 2025, 11:23:46 AM11/6/25
      to Code Review Nudger, Alex Moshchuk, Daniel Cheng, AI Code Reviewer, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, ajwong...@chromium.org, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org
      Attention needed from Alex Moshchuk and Daniel Cheng

      Camille Lamy voted and added 21 comments

      Votes added by Camille Lamy

      Commit-Queue+1

      21 comments

      Patchset-level comments
      File-level comment, Patchset 21 (Latest):
      Camille Lamy . resolved

      Thanks!

      File content/browser/agent_cluster_key.h
      Line 36, Patchset 13:class CONTENT_EXPORT AgentClusterKey {
      Alex Moshchuk . unresolved

      I guess I'm a bit worried that we now have 3-4 places that define AgentClusterKeys (here, mojo, WebAgentClusterKey, and blink::AgentClusterKey), and they might get out of sync. Maybe it's intentional that the browser-side and renderer-side keys aren't going to be identical (e.g., the renderer doesn't need oac_status_), though we could at least add comments reminding what else must be updated when someone wants to add something to the AgentClusterKey? And maybe we could use LINT.IfChange to enforce that things stay updated together where it makes sense?

      Camille Lamy

      I don't think we should pass the oac_status to the renderer process. I have added a LINT.IfChange comment (not sure of the usage, this is my first time using it).

      I agree that the duplication is unfortunate, but this is a side effect of the CommitNavigation not being sent to Blink directly. Otherwise, we could have had just the mojo struct, and used a typemap to map this struct to the Mojo struct.

      Line 35, Patchset 13:// SiteInfo, as it will only duplicate the information in AgentClusterKey.
      Alex Moshchuk . resolved

      Might be worth updating this documentation to mention the other definitions of agent cluster key used in the renderer (and for sending this key to the renderer), and how they differ practically from this key.

      Camille Lamy

      Done

      File content/browser/renderer_host/navigation_request.cc
      Line 4011, Patchset 13: // Now build the appropriate AgentClusterKey for commit, starting with the
      Camille Lamy . unresolved

      I have been considering moving all the code below to SiteInfo, as it essentially undoes all the special cases of GetAgentClusterKeyForURL, so maybe having the two in the same place to compare would be nice.

      Alex Moshchuk

      Yes, it might be worth moving this code into a separate helper, and maybe SiteInfo is a better place for it, as this function is getting long. It might be worth keeping the focus of this function on the OAC stuff as before, and then computing the key_to_commit as a separate step.

      One high-level concern I have with the content/browser side of this CL is indeed about introducing another place for handling these special cases, and moreover trying to reconstruct how we computed a SiteInfo based on the AgentClusterKey after the fact, which seems fragile (and potentially hard to maintain for future changes to the process model). Do you think it could be better to compute both the agent cluster key for SiteInfo and the agent cluster key to send to the renderer in the same place in GetAgentClusterKeyForURL? Basically, have all the special cases in one place, but computing two keys? Or at least compute the should_update_origin_or_site bit there, so that we know that the site URL we ended up with in SiteInfo is a Chrome-process-model specific URL and not what the actual agent cluster key should be per spec.

      (I'm not sure this is better or even feasible, just curious if it's worth thinking about at all.)

      Camille Lamy

      I have added a member to AgentClusterKey tracking whether we should update its origin/site URL before sending it. This allows to set it to true in all the edge cases we have in GetAgentClusterKeyForURL. This covers pretty much every edge case, except 4:

      • logical OAC (computed after we compute the AgentClusterKey)
      • opaque origins that are not data URLs -> we only pass the non opaque URL to SiteInfo, so it doesn't know the origin is actually opaque.
      • cross-origin isolated contexts when COI comes from COOP + COEP (temporary, will go away once we create AgentClusterKeys with COIKeys)
      • navigation to an existing SiteInstance without SiteIsolation when there is a redirect. See more about this one in the comment about this behavior.

      Wdyt of the new version?

      Line 4019, Patchset 13: // isolation key. Currently, pages cross-origin isolated through COOP and COEP

      // are not given a cross-origin isolated AgentClusterKey. Override the
      Alex Moshchuk . unresolved

      It seems that this will be addressed by your https://chromium-review.googlesource.com/c/chromium/src/+/6516176? Will you be landing this CL before or after that?

      Camille Lamy

      Yes the other CL will fix it, but I'd like to land this one first. This CL is needed for DIP on Android while the other isn't. And to land the other, I need to do more investigation on why the preparatory CLs failed, which I have pushed back until after I get DIP on Android.

      Line 4022, Patchset 13: // the document already as a cross-origin isolated AgentClusterKey, which
      Alex Moshchuk . resolved

      has

      Camille Lamy

      Done

      Line 4122, Patchset 13: origin.scheme())) {
      Alex Moshchuk . resolved

      Is this to undo the case [here](https://source.chromium.org/chromium/chromium/src/+/main:content/browser/site_info.cc;l=791;drc=7ce25d3420a0eb77c46618536b3434f7b9ceef66)? Does it matter that this only applies to top-chrome WebUIs and not all WebUIs? Should it be more restricted to IsWebUIAndUsesTLDForProcessLockURL cases?

      Camille Lamy

      Marked as resolved.

      Line 4129, Patchset 13: should_update_origin_or_site = true;
      Alex Moshchuk . resolved

      I guess we don't have this problem with features::kDefaultSiteInstanceGroups?

      Camille Lamy

      No kDefaultSiteInstanceGroups properly creates SiteInstances.

      Line 4134, Patchset 13: // redirect causes the response URL to no longer match the original

      // SiteInstance. In that case, create a new AgentClusterKey.
      Alex Moshchuk . unresolved

      Is this actually intended behavior and not a bug? I think we try to disqualify the original SiteInstance in the NavigationEntry from being reused if it's no longer suitable for the redirected URL, with things like RenderFrameHostManager::CanUseDestinationInstance(). I'm surprised it would need its own condition here, as it seems like it might be violating our SiteInstance assignment rules.

      Camille Lamy

      The test NavigationControllerBrowserTest.SiteInstanceChangeOnHistoryNavigation has expectations of the SiteInstance not changing when SiteIsolation is not enabled and the navigation to an existing SiteInstance encounters a cross-site reload.

      After further investigation, RenderFrameHostManager::CanUseDestinationInstance() will call SiteInstanceImpl::IsSuitableForUrlInfo. This in turns calls RenderProcessHostImpl::IsSuitableHost. In the non-Site Isolation case, the RPH is unlocked and the destination does not require a locked process, so the SiteInstance is deemed suitable and reused, even if the SiteInstance is not the default SiteInstance and its AgentClusterKey does not match the URL of the navigation.

      Line 4136, Patchset 13: bool is_navigation_to_existing_entry =
      Camille Lamy . resolved

      I still have one test failing for this specific case. I think it's a case of a subframe navigation to an existing subframe NavigationEntry. I'm not sure how to write the condition for it.

      Camille Lamy

      Done

      Line 4166, Patchset 13: if (key_to_commit.IsSiteKeyed()) {
      Alex Moshchuk . resolved

      Can there be some sort of conversion function to populate a mojo AgentClusterKey from a normal one, ideally in agent_cluster_key.*?

      Camille Lamy

      Done

      File content/browser/renderer_host/render_process_host_impl.cc
      Line 3370, Patchset 13: process_lock.agent_cluster_key().IsCrossOriginIsolated();
      Alex Moshchuk . unresolved

      Can this be cleaned up independently, or does it depend on something in this CL?

      Camille Lamy

      It could be done beforehand. Basically, I changed the CrossOriginIsolationMode enum to be a blink mojo enum, so the old code does not compile. I could just change the enum to the new version, but since we introduced the helper function in the meantime I thought it'd be cleaner to use the helper function.

      File content/browser/service_worker/service_worker_test_utils.cc
      Line 284, Patchset 13: commit_params->agent_cluster_key = blink::mojom::AgentClusterKey::New();
      Daniel Cheng . resolved

      Should `blink::CreateCommitNavigationParams()` also just set this? Seems like it's not really optional anyway.

      (Though I guess it becomes messy if we make the agent cluster key a union as I suggested below–does the agent cluster key actually have three distinct states? Site, origin, and neither? Though based off the WebAgentClusterKey class... I'm not actually sure)

      Camille Lamy

      Yes it makes sense to have blink::CreateCommitNavigationParams() create this. The AgentClusterKey has two states, site keyed or origin-keyed, now represented by a union. I think creating a default site keyed to GURL is fine, it can be replaced later down the road by the proper one.

      File third_party/blink/public/mojom/frame/agent_cluster_key.mojom
      Line 10, Patchset 13:// Indicates if cross-origin isolation gives access to cross-origin isolated
      Daniel Cheng . resolved

      Nit: extra space

      Camille Lamy

      Done

      Line 24, Patchset 13: // when cross-origin sioaltion is enabled by COOP + COEP. When cross-origin
      Daniel Cheng . resolved

      Nit: isolation.

      Camille Lamy

      Done

      Line 42, Patchset 13: // Additionally, the AgentClusterKey might have a CrossOriginIsolationKey is
      Daniel Cheng . resolved

      if

      Camille Lamy

      Done

      Line 37, Patchset 13: // The AgentClusterKey has either a site URL or an origin. In the first case,

      // the AgentClusterKey is site keyed, in the second case, it is origin keyed.
      url.mojom.Url? url;
      url.mojom.Origin? origin;

      // Additionally, the AgentClusterKey might have a CrossOriginIsolationKey is
      // the context is cross-origin isolated. In this case, the AgentClusterKey
      // must be origin-keyed.
      // https://wicg.github.io/document-isolation-policy/#coi-agent-cluster-key
      CrossOriginIsolationKey? isolation_key;
      Daniel Cheng . resolved

      It seems like maybe this should be a union consisting of either a `url.mojom.Url` or a `OriginKeyedAgentClusterKey` struct containing a `url.mojom.Origin` and a `CrossOriginIsolationKey` (not sure if the COI key is required in the case of origin-keyed origins)

      Camille Lamy

      Done

      File third_party/blink/public/web/web_agent_cluster_key.h
      Line 40, Patchset 13: std::optional<WebCrossOriginIsolationKey> isolation_key;
      Daniel Cheng . resolved

      As noted above, can we restructure this so it's a variant of a WebURL and a struct containing a WebSecurityOrigin and an optional key?

      Camille Lamy

      Done

      Line 23, Patchset 13: mojom::CrossOriginIsolationMode cross_origin_isolation_mode)
      Camille Lamy . resolved

      The presubmit checks complain about non-Blink mojom usage, but since this is the public interface that seems to be the correct thing to do to eventually translate into Blink mojom types. I'm not sure where I need to authorize this as I would have imagined that third_party/blink/public/web would not be covered by the check.

      Daniel Cheng

      I agree this is fine; can you link me to an example of the presubmit warning?

      Camille Lamy

      It seems it's no longer trigerring.

      File third_party/blink/renderer/core/execution_context/agent_cluster_key.h
      Line 33, Patchset 13: AgentClusterKey();
      Daniel Cheng . unresolved

      What does this create by default? Is it site keyed, origin keyed, or neither?

      Camille Lamy

      A site-keyed AgentClusterKey with KURL(). It's only there so that it works with the map. Added comments to clarify.

      File third_party/blink/renderer/platform/weborigin/security_origin.h
      Line 414, Patchset 13: // the custom HashTraits defined at the end of this file.
      Daniel Cheng . resolved

      I don't think we should have both--or at the very least, one should delegate to the other.
      Can you file a TODO to clean this up? Is there a failing test someone can run when they are trying to figure out what's going wrong here?

      Camille Lamy

      Removed this. Adding an import of third_party/blink/renderer/platform/weborigin/security_origin.h in the file using the HashTraits seems to have fixed the issue.

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Alex Moshchuk
      • Daniel Cheng
      Submit Requirements:
      • requirement satisfiedCode-Coverage
      • requirement is not satisfiedCode-Owners
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement is not satisfiedReview-Enforcement
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: chromium/src
      Gerrit-Branch: main
      Gerrit-Change-Id: Ibb98071005816e53e766fbcbe3fbcb642ee17592
      Gerrit-Change-Number: 7041044
      Gerrit-PatchSet: 21
      Gerrit-Owner: Camille Lamy <cl...@chromium.org>
      Gerrit-Reviewer: Alex Moshchuk <ale...@chromium.org>
      Gerrit-Reviewer: Camille Lamy <cl...@chromium.org>
      Gerrit-Reviewer: Daniel Cheng <dch...@chromium.org>
      Gerrit-CC: AI Code Reviewer <peep-gen...@system.gserviceaccount.com>
      Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
      Gerrit-CC: Hiroki Nakagawa <nhi...@chromium.org>
      Gerrit-CC: Kentaro Hara <har...@chromium.org>
      Gerrit-CC: Nate Chapin <jap...@chromium.org>
      Gerrit-CC: Raphael Kubo da Costa <ku...@igalia.com>
      Gerrit-Attention: Alex Moshchuk <ale...@chromium.org>
      Gerrit-Attention: Daniel Cheng <dch...@chromium.org>
      Gerrit-Comment-Date: Thu, 06 Nov 2025 16:23:31 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: Yes
      Comment-In-Reply-To: Alex Moshchuk <ale...@chromium.org>
      Comment-In-Reply-To: Camille Lamy <cl...@chromium.org>
      Comment-In-Reply-To: Daniel Cheng <dch...@chromium.org>
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy

      Alex Moshchuk (Gerrit)

      unread,
      Nov 12, 2025, 8:57:38 PM11/12/25
      to Camille Lamy, Code Review Nudger, Daniel Cheng, AI Code Reviewer, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, ajwong...@chromium.org, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org
      Attention needed from Camille Lamy and Daniel Cheng

      Alex Moshchuk added 18 comments

      Patchset-level comments
      Alex Moshchuk . resolved

      Thanks, and sorry it took a while to find enough focus time for this!

      File content/browser/agent_cluster_key.h
      Line 287, Patchset 21 (Latest): // manner. However, the proper origin or site URL of the navigation should
      Alex Moshchuk . unresolved

      Maybe give an example here, and mention that ideally this wouldn't be needed if we always created spec-compliant AgentClusterKeys and used SiteInstanceGroups to handle process allocation?

      Line 231, Patchset 21 (Latest): void set_update_key_before_sending(bool update_key_before_sending) {
      Alex Moshchuk . unresolved

      Do we need to pass a value, or can we assume it's always true? Seems like there'd be no use case for forcing this to be off.

      Line 231, Patchset 21 (Latest): void set_update_key_before_sending(bool update_key_before_sending) {
      Alex Moshchuk . unresolved

      It'd be nice if the name reflected something about this being for the renderer process, or that the renderer version of the key will differ. Some alternatives:

      • set_update_key_before_sending_to_renderer()
      • set_key_update_required_for_renderer() or set_should_update_key_for_renderer()
      • mark_for_renderer_key_correction() or set_needs_renderer_key_correction()
      • or maybe even set_key_is_not_spec_compliant() (maybe this isn't accurate though)
      Line 230, Patchset 21 (Latest): // before being sent to the renderer process.
      Alex Moshchuk . unresolved

      Mention how ideally all browser-side AgentClusterKeys would match those that we send to the renderer, but we have some cases where the browser-side AgentClusterKey will be set according to process allocation decisions, rather than what is required per spec, and we want to keep this transparent to the renderer and send it an idealized version of this key.

      Line 226, Patchset 21 (Latest): bool force_update,
      Alex Moshchuk . unresolved

      Let's also describe what this param is for in the comment. Also, is it needed? Could we get the same behavior by calling set_update_key_before_sending() on the key when this is true, before calling this function? (Or do we want to avoid modifying the key for these cases?)

      Line 36, Patchset 13:class CONTENT_EXPORT AgentClusterKey {
      Alex Moshchuk . resolved

      I guess I'm a bit worried that we now have 3-4 places that define AgentClusterKeys (here, mojo, WebAgentClusterKey, and blink::AgentClusterKey), and they might get out of sync. Maybe it's intentional that the browser-side and renderer-side keys aren't going to be identical (e.g., the renderer doesn't need oac_status_), though we could at least add comments reminding what else must be updated when someone wants to add something to the AgentClusterKey? And maybe we could use LINT.IfChange to enforce that things stay updated together where it makes sense?

      Camille Lamy

      I don't think we should pass the oac_status to the renderer process. I have added a LINT.IfChange comment (not sure of the usage, this is my first time using it).

      I agree that the duplication is unfortunate, but this is a side effect of the CommitNavigation not being sent to Blink directly. Otherwise, we could have had just the mojo struct, and used a typemap to map this struct to the Mojo struct.

      Alex Moshchuk

      Acknowledged

      File content/browser/agent_cluster_key.cc
      Line 159, Patchset 21 (Latest): const url::Origin& navigation_origin,
      Alex Moshchuk . unresolved

      origin_to_commit might be clearer?

      File content/browser/renderer_host/navigation_request.cc
      Line 4011, Patchset 13: // Now build the appropriate AgentClusterKey for commit, starting with the
      Camille Lamy . unresolved

      I have been considering moving all the code below to SiteInfo, as it essentially undoes all the special cases of GetAgentClusterKeyForURL, so maybe having the two in the same place to compare would be nice.

      Alex Moshchuk

      Yes, it might be worth moving this code into a separate helper, and maybe SiteInfo is a better place for it, as this function is getting long. It might be worth keeping the focus of this function on the OAC stuff as before, and then computing the key_to_commit as a separate step.

      One high-level concern I have with the content/browser side of this CL is indeed about introducing another place for handling these special cases, and moreover trying to reconstruct how we computed a SiteInfo based on the AgentClusterKey after the fact, which seems fragile (and potentially hard to maintain for future changes to the process model). Do you think it could be better to compute both the agent cluster key for SiteInfo and the agent cluster key to send to the renderer in the same place in GetAgentClusterKeyForURL? Basically, have all the special cases in one place, but computing two keys? Or at least compute the should_update_origin_or_site bit there, so that we know that the site URL we ended up with in SiteInfo is a Chrome-process-model specific URL and not what the actual agent cluster key should be per spec.

      (I'm not sure this is better or even feasible, just curious if it's worth thinking about at all.)

      Camille Lamy

      I have added a member to AgentClusterKey tracking whether we should update its origin/site URL before sending it. This allows to set it to true in all the edge cases we have in GetAgentClusterKeyForURL. This covers pretty much every edge case, except 4:

      • logical OAC (computed after we compute the AgentClusterKey)
      • opaque origins that are not data URLs -> we only pass the non opaque URL to SiteInfo, so it doesn't know the origin is actually opaque.
      • cross-origin isolated contexts when COI comes from COOP + COEP (temporary, will go away once we create AgentClusterKeys with COIKeys)
      • navigation to an existing SiteInstance without SiteIsolation when there is a redirect. See more about this one in the comment about this behavior.

      Wdyt of the new version?

      Alex Moshchuk

      Thanks, this looks better to me. It's a bit unfortunate that these decisions are still pretty spread out (e.g., the four exception cases you mentioned are here, most cases are special-cased in GetAgentClusterKeyForURL(), some are in special-case SiteInfo constructors (e.g. CreateForErrorPage), and then the last redirect case is in an entirely different place. I don't know if there's fundamentally a better organization, though, given all the constraints and how everything is structured at the moment. E.g., computing the renderer-side key closer to the place where we compute the browser-side key may not be possible without additional context for some cases (e.g., the data URL or the redirect cases you mentioned).

      I do have a couple of questions:

      • One SiteInstance might get reused by several possibly concurrent navigations (e.g., in several subframes). Is it a problem that we might set the new flag for one navigation and then a different navigation for different URL/origin might look at it at commit time, and incorrectly rely on the value of that flag that was computed for a different navigation? Or do we expect that all navigations in a particular SiteInstance that's marked as having a non-compliant key will need to recompute the AgentClusterKey?
      • Could we actually compute the renderer key from scratch at commit time, instead of basing it off of the browser-side key? We already have the origin to commit and at least some of the inputs for when it needs to be origin-keyed and/or cross-origin-isolated. Could that be simpler than trying to decide what pieces of the browser-side key can be reused?
      Line 4019, Patchset 13: // isolation key. Currently, pages cross-origin isolated through COOP and COEP
      // are not given a cross-origin isolated AgentClusterKey. Override the
      Alex Moshchuk . resolved

      It seems that this will be addressed by your https://chromium-review.googlesource.com/c/chromium/src/+/6516176? Will you be landing this CL before or after that?

      Camille Lamy

      Yes the other CL will fix it, but I'd like to land this one first. This CL is needed for DIP on Android while the other isn't. And to land the other, I need to do more investigation on why the preparatory CLs failed, which I have pushed back until after I get DIP on Android.

      Alex Moshchuk

      Acknowledged

      Line 4134, Patchset 13: // redirect causes the response URL to no longer match the original
      // SiteInstance. In that case, create a new AgentClusterKey.
      Alex Moshchuk . unresolved

      Is this actually intended behavior and not a bug? I think we try to disqualify the original SiteInstance in the NavigationEntry from being reused if it's no longer suitable for the redirected URL, with things like RenderFrameHostManager::CanUseDestinationInstance(). I'm surprised it would need its own condition here, as it seems like it might be violating our SiteInstance assignment rules.

      Camille Lamy

      The test NavigationControllerBrowserTest.SiteInstanceChangeOnHistoryNavigation has expectations of the SiteInstance not changing when SiteIsolation is not enabled and the navigation to an existing SiteInstance encounters a cross-site reload.

      After further investigation, RenderFrameHostManager::CanUseDestinationInstance() will call SiteInstanceImpl::IsSuitableForUrlInfo. This in turns calls RenderProcessHostImpl::IsSuitableHost. In the non-Site Isolation case, the RPH is unlocked and the destination does not require a locked process, so the SiteInstance is deemed suitable and reused, even if the SiteInstance is not the default SiteInstance and its AgentClusterKey does not match the URL of the navigation.

      Alex Moshchuk

      Thanks, that helps. When site isolation is not enabled, I wonder if this case should instead create a new SiteInstance (with a SiteInfo that reflects the post-redirect URL) in the same SiteInstanceGroup, instead of staying in the old SiteInstance? Would doing that fix this issue, at least when we're using DefaultSiteInstanceGroups (which should be everywhere except Android Webview at this point)? The point of DefaultSiteInstanceGroups is to keep meaningful site URLs in cases like this, which this test case seems to violate, so might be worth filing this as a separate bug in DefaultSiteInstanceGroups.

      File content/browser/renderer_host/render_frame_host_manager.cc
      Line 3452, Patchset 21 (Latest): url::Origin origin = url::Origin::Create(dest_url_info.url);
      Alex Moshchuk . unresolved

      Hmm, this seems like it might not be correct in corner cases like sandboxed frames or about:blank or error pages, or cases where dest_url_info.origin is set. I'm not sure exactly how to fix it, but it feels it should use NavigationRequest::GetOriginToCommit() (or GetTentativeOriginAtRequestTime() if this is called prior to ready-to-commit), which is what we use later to pass to GetAgentClusterKeyForNavigationCommit().

      File content/browser/renderer_host/render_process_host_impl.cc
      Line 3370, Patchset 13: process_lock.agent_cluster_key().IsCrossOriginIsolated();
      Alex Moshchuk . resolved

      Can this be cleaned up independently, or does it depend on something in this CL?

      Camille Lamy

      It could be done beforehand. Basically, I changed the CrossOriginIsolationMode enum to be a blink mojo enum, so the old code does not compile. I could just change the enum to the new version, but since we introduced the helper function in the meantime I thought it'd be cleaner to use the helper function.

      Alex Moshchuk

      Acknowledged

      File content/browser/site_info.h
      Line 413, Patchset 21 (Latest): // origin or URL of the AgentClusterKey.
      Alex Moshchuk . unresolved

      Nit: these and similar comments might benefit from a simple concrete example of where they differ (e.g., special-case site URLs like chrome-error or data:nonce). (I know there'll be some duplication and that you do have examples elsewhere...)

      File content/browser/site_info.cc
      Line 162, Patchset 21 (Latest): /*update_key_before_sending=*/true);
      Alex Moshchuk . unresolved

      This probably needs a quick comment to explain that error pages commit in chrome-error:// SiteInstances, which is Chrome's process model behavior that shouldn't be reflected in the key exposed to the renderer.

      Actually, what is the renderer-side AgentClusterKey for error pages? Is it based on an opaque origin?

      Line 205, Patchset 21 (Latest): /*update_key_before_sending=*/true);
      Alex Moshchuk . unresolved

      This probably needs a comment to explain why default SiteInstances set this to true (because by definition their Site URL will be shared among potentially multiple cross-site documents and won't match a particular navigation's site.)

      Line 210, Patchset 21 (Latest): /*update_key_before_sending=*/true);
      Alex Moshchuk . unresolved

      I'm on the fence about passing this new arg when creating every new AgentClusterKey. It seems the cases where we have to set this to true should gradually disappear as we roll out more uses of SiteInstanceGroups, right?

      While requiring it as an explicit param is useful to force all callers to reason about it, I also think that we shouldn't add new exceptions going forward, and that all new code should use SiteInstanceGroups rather than add an exception that forces this update. So, maybe we can rely on a separate call to set_update_key_before_sending() for setting this flag, on newly created AgentClusterKeys that need this? That would also provide a more convenient place to add a comment to explain why each particular use case needs this set, and would also make it easier to identify all places that we'd want to eventually update to use SiteInstanceGroups.

      If we wanted to keep call sites that return a create key right away, we could also consider making the function that sets this flag internally also return the key it just modified, or creating alternate versions of the constructors, e.g. CreateNonSpecCompliantSiteKeyed().

      Line 977, Patchset 21 (Latest): true);
      Alex Moshchuk . unresolved

      Why does this need to update the key? Is it because we're creating a site-keyed key but the site URL might not actually be a site but rather an (isolated) origin? Let's explain in a comment if so.

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Camille Lamy
      • Daniel Cheng
      Gerrit-Attention: Camille Lamy <cl...@chromium.org>
      Gerrit-Attention: Daniel Cheng <dch...@chromium.org>
      Gerrit-Comment-Date: Thu, 13 Nov 2025 01:57:27 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy

      Camille Lamy (Gerrit)

      unread,
      Dec 4, 2025, 8:12:31 AM12/4/25
      to Code Review Nudger, Alex Moshchuk, Daniel Cheng, AI Code Reviewer, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, ajwong...@chromium.org, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org
      Attention needed from Alex Moshchuk and Daniel Cheng

      Camille Lamy added 15 comments

      Patchset-level comments
      File-level comment, Patchset 24 (Latest):
      Camille Lamy . resolved

      Thanks for the review! It took me quite a while to answer as I was OOO for three weeks. Following your suggestion, I have modified the CL to always create the AgentClusterKey we pass to the renderer process from scratch. It does make things a lot simpler. It's a bit unfortunate. However, maybe when more edge cases get migrated to using SiteInstanceGroup we might attempt to use the AgentClusterKey from the SiteInstance.

      File content/browser/agent_cluster_key.h
      Line 287, Patchset 21: // manner. However, the proper origin or site URL of the navigation should
      Alex Moshchuk . resolved

      Maybe give an example here, and mention that ideally this wouldn't be needed if we always created spec-compliant AgentClusterKeys and used SiteInstanceGroups to handle process allocation?

      Camille Lamy

      This parameter no longer exists.

      Line 231, Patchset 21: void set_update_key_before_sending(bool update_key_before_sending) {
      Alex Moshchuk . resolved

      Do we need to pass a value, or can we assume it's always true? Seems like there'd be no use case for forcing this to be off.

      Camille Lamy

      This parameter no longer exists.

      Line 231, Patchset 21: void set_update_key_before_sending(bool update_key_before_sending) {
      Alex Moshchuk . resolved

      It'd be nice if the name reflected something about this being for the renderer process, or that the renderer version of the key will differ. Some alternatives:

      • set_update_key_before_sending_to_renderer()
      • set_key_update_required_for_renderer() or set_should_update_key_for_renderer()
      • mark_for_renderer_key_correction() or set_needs_renderer_key_correction()
      • or maybe even set_key_is_not_spec_compliant() (maybe this isn't accurate though)
      Camille Lamy

      This parameter no longer exists.

      Line 230, Patchset 21: // before being sent to the renderer process.
      Alex Moshchuk . resolved

      Mention how ideally all browser-side AgentClusterKeys would match those that we send to the renderer, but we have some cases where the browser-side AgentClusterKey will be set according to process allocation decisions, rather than what is required per spec, and we want to keep this transparent to the renderer and send it an idealized version of this key.

      Camille Lamy

      This parameter no longer exists.

      Line 226, Patchset 21: bool force_update,
      Alex Moshchuk . resolved

      Let's also describe what this param is for in the comment. Also, is it needed? Could we get the same behavior by calling set_update_key_before_sending() on the key when this is true, before calling this function? (Or do we want to avoid modifying the key for these cases?)

      Camille Lamy

      This parameter is no longer present in the latest version.

      File content/browser/agent_cluster_key.cc
      Line 159, Patchset 21: const url::Origin& navigation_origin,
      Alex Moshchuk . resolved

      origin_to_commit might be clearer?

      Camille Lamy

      Done

      File content/browser/renderer_host/navigation_request.cc
      Line 4011, Patchset 13: // Now build the appropriate AgentClusterKey for commit, starting with the
      Camille Lamy . unresolved

      I have been considering moving all the code below to SiteInfo, as it essentially undoes all the special cases of GetAgentClusterKeyForURL, so maybe having the two in the same place to compare would be nice.

      Alex Moshchuk

      Yes, it might be worth moving this code into a separate helper, and maybe SiteInfo is a better place for it, as this function is getting long. It might be worth keeping the focus of this function on the OAC stuff as before, and then computing the key_to_commit as a separate step.

      One high-level concern I have with the content/browser side of this CL is indeed about introducing another place for handling these special cases, and moreover trying to reconstruct how we computed a SiteInfo based on the AgentClusterKey after the fact, which seems fragile (and potentially hard to maintain for future changes to the process model). Do you think it could be better to compute both the agent cluster key for SiteInfo and the agent cluster key to send to the renderer in the same place in GetAgentClusterKeyForURL? Basically, have all the special cases in one place, but computing two keys? Or at least compute the should_update_origin_or_site bit there, so that we know that the site URL we ended up with in SiteInfo is a Chrome-process-model specific URL and not what the actual agent cluster key should be per spec.

      (I'm not sure this is better or even feasible, just curious if it's worth thinking about at all.)

      Camille Lamy

      I have added a member to AgentClusterKey tracking whether we should update its origin/site URL before sending it. This allows to set it to true in all the edge cases we have in GetAgentClusterKeyForURL. This covers pretty much every edge case, except 4:

      • logical OAC (computed after we compute the AgentClusterKey)
      • opaque origins that are not data URLs -> we only pass the non opaque URL to SiteInfo, so it doesn't know the origin is actually opaque.
      • cross-origin isolated contexts when COI comes from COOP + COEP (temporary, will go away once we create AgentClusterKeys with COIKeys)
      • navigation to an existing SiteInstance without SiteIsolation when there is a redirect. See more about this one in the comment about this behavior.

      Wdyt of the new version?

      Alex Moshchuk

      Thanks, this looks better to me. It's a bit unfortunate that these decisions are still pretty spread out (e.g., the four exception cases you mentioned are here, most cases are special-cased in GetAgentClusterKeyForURL(), some are in special-case SiteInfo constructors (e.g. CreateForErrorPage), and then the last redirect case is in an entirely different place. I don't know if there's fundamentally a better organization, though, given all the constraints and how everything is structured at the moment. E.g., computing the renderer-side key closer to the place where we compute the browser-side key may not be possible without additional context for some cases (e.g., the data URL or the redirect cases you mentioned).

      I do have a couple of questions:

      • One SiteInstance might get reused by several possibly concurrent navigations (e.g., in several subframes). Is it a problem that we might set the new flag for one navigation and then a different navigation for different URL/origin might look at it at commit time, and incorrectly rely on the value of that flag that was computed for a different navigation? Or do we expect that all navigations in a particular SiteInstance that's marked as having a non-compliant key will need to recompute the AgentClusterKey?
      • Could we actually compute the renderer key from scratch at commit time, instead of basing it off of the browser-side key? We already have the origin to commit and at least some of the inputs for when it needs to be origin-keyed and/or cross-origin-isolated. Could that be simpler than trying to decide what pieces of the browser-side key can be reused?
      Camille Lamy

      Following your suggestion, I am now computing the renderer key from scratch. It's a bit unfortunate that we can't use the browser one, but there seems to be too many edge cases right now that introduce complexity. What do you think of the computation from scratch version?

      Line 4134, Patchset 13: // redirect causes the response URL to no longer match the original
      // SiteInstance. In that case, create a new AgentClusterKey.
      Alex Moshchuk . resolved

      Is this actually intended behavior and not a bug? I think we try to disqualify the original SiteInstance in the NavigationEntry from being reused if it's no longer suitable for the redirected URL, with things like RenderFrameHostManager::CanUseDestinationInstance(). I'm surprised it would need its own condition here, as it seems like it might be violating our SiteInstance assignment rules.

      Camille Lamy

      The test NavigationControllerBrowserTest.SiteInstanceChangeOnHistoryNavigation has expectations of the SiteInstance not changing when SiteIsolation is not enabled and the navigation to an existing SiteInstance encounters a cross-site reload.

      After further investigation, RenderFrameHostManager::CanUseDestinationInstance() will call SiteInstanceImpl::IsSuitableForUrlInfo. This in turns calls RenderProcessHostImpl::IsSuitableHost. In the non-Site Isolation case, the RPH is unlocked and the destination does not require a locked process, so the SiteInstance is deemed suitable and reused, even if the SiteInstance is not the default SiteInstance and its AgentClusterKey does not match the URL of the navigation.

      Alex Moshchuk

      Thanks, that helps. When site isolation is not enabled, I wonder if this case should instead create a new SiteInstance (with a SiteInfo that reflects the post-redirect URL) in the same SiteInstanceGroup, instead of staying in the old SiteInstance? Would doing that fix this issue, at least when we're using DefaultSiteInstanceGroups (which should be everywhere except Android Webview at this point)? The point of DefaultSiteInstanceGroups is to keep meaningful site URLs in cases like this, which this test case seems to violate, so might be worth filing this as a separate bug in DefaultSiteInstanceGroups.

      Camille Lamy

      Yes that would probably be better. I have filed https://g-issues.chromium.org/issues/466026066 to keep track of the issue. In the meantime, the concern no longer applies since we're now always creating the AgentClusterKey for commit from scratch, so I am going to close this.

      File content/browser/renderer_host/render_frame_host_manager.cc
      Line 3452, Patchset 21: url::Origin origin = url::Origin::Create(dest_url_info.url);
      Alex Moshchuk . resolved

      Hmm, this seems like it might not be correct in corner cases like sandboxed frames or about:blank or error pages, or cases where dest_url_info.origin is set. I'm not sure exactly how to fix it, but it feels it should use NavigationRequest::GetOriginToCommit() (or GetTentativeOriginAtRequestTime() if this is called prior to ready-to-commit), which is what we use later to pass to GetAgentClusterKeyForNavigationCommit().

      Camille Lamy

      We no longer have to track this since we are re-creating the AgentClusterKey from scratch at commit time.

      File content/browser/site_info.h
      Line 413, Patchset 21: // origin or URL of the AgentClusterKey.
      Alex Moshchuk . resolved

      Nit: these and similar comments might benefit from a simple concrete example of where they differ (e.g., special-case site URLs like chrome-error or data:nonce). (I know there'll be some duplication and that you do have examples elsewhere...)

      Camille Lamy

      This function no longer exists.

      File content/browser/site_info.cc
      Line 162, Patchset 21: /*update_key_before_sending=*/true);
      Alex Moshchuk . resolved

      This probably needs a quick comment to explain that error pages commit in chrome-error:// SiteInstances, which is Chrome's process model behavior that shouldn't be reflected in the key exposed to the renderer.

      Actually, what is the renderer-side AgentClusterKey for error pages? Is it based on an opaque origin?

      Camille Lamy

      This parameter no longer exists.

      The renderer-side AgentClysterKey for error pages is just going to be a regular AgentClusterKey with the origin/site URL of the error page I believe. I don't think there is any code to commit the error page with an opaque origin.

      Line 205, Patchset 21: /*update_key_before_sending=*/true);
      Alex Moshchuk . resolved

      This probably needs a comment to explain why default SiteInstances set this to true (because by definition their Site URL will be shared among potentially multiple cross-site documents and won't match a particular navigation's site.)

      Camille Lamy

      This parameter no longer exists.

      Line 210, Patchset 21: /*update_key_before_sending=*/true);
      Alex Moshchuk . resolved

      I'm on the fence about passing this new arg when creating every new AgentClusterKey. It seems the cases where we have to set this to true should gradually disappear as we roll out more uses of SiteInstanceGroups, right?

      While requiring it as an explicit param is useful to force all callers to reason about it, I also think that we shouldn't add new exceptions going forward, and that all new code should use SiteInstanceGroups rather than add an exception that forces this update. So, maybe we can rely on a separate call to set_update_key_before_sending() for setting this flag, on newly created AgentClusterKeys that need this? That would also provide a more convenient place to add a comment to explain why each particular use case needs this set, and would also make it easier to identify all places that we'd want to eventually update to use SiteInstanceGroups.

      If we wanted to keep call sites that return a create key right away, we could also consider making the function that sets this flag internally also return the key it just modified, or creating alternate versions of the constructors, e.g. CreateNonSpecCompliantSiteKeyed().

      Camille Lamy

      This parameter no longer exists.

      Line 977, Patchset 21: true);
      Alex Moshchuk . resolved

      Why does this need to update the key? Is it because we're creating a site-keyed key but the site URL might not actually be a site but rather an (isolated) origin? Let's explain in a comment if so.

      Camille Lamy

      This parameter no longer exists. The reason why it was set to true is indeed because it's a site-keyed key which does not use the regular site URL but the isolated origin.

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Alex Moshchuk
      • Daniel Cheng
      Submit Requirements:
      • requirement satisfiedCode-Coverage
      • requirement is not satisfiedCode-Owners
      • requirement is not satisfiedCode-Review
      • requirement is not satisfiedNo-Unresolved-Comments
      • requirement is not satisfiedReview-Enforcement
      Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
      Gerrit-MessageType: comment
      Gerrit-Project: chromium/src
      Gerrit-Branch: main
      Gerrit-Change-Id: Ibb98071005816e53e766fbcbe3fbcb642ee17592
      Gerrit-Change-Number: 7041044
      Gerrit-PatchSet: 24
      Gerrit-Owner: Camille Lamy <cl...@chromium.org>
      Gerrit-Reviewer: Alex Moshchuk <ale...@chromium.org>
      Gerrit-Reviewer: Camille Lamy <cl...@chromium.org>
      Gerrit-Reviewer: Daniel Cheng <dch...@chromium.org>
      Gerrit-CC: AI Code Reviewer <peep-gen...@system.gserviceaccount.com>
      Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
      Gerrit-CC: Hiroki Nakagawa <nhi...@chromium.org>
      Gerrit-CC: Kentaro Hara <har...@chromium.org>
      Gerrit-CC: Nate Chapin <jap...@chromium.org>
      Gerrit-CC: Raphael Kubo da Costa <ku...@igalia.com>
      Gerrit-Attention: Alex Moshchuk <ale...@chromium.org>
      Gerrit-Attention: Daniel Cheng <dch...@chromium.org>
      Gerrit-Comment-Date: Thu, 04 Dec 2025 13:12:15 +0000
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy

      Alex Moshchuk (Gerrit)

      unread,
      Dec 5, 2025, 9:35:29 PM12/5/25
      to Camille Lamy, Code Review Nudger, Daniel Cheng, AI Code Reviewer, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, ajwong...@chromium.org, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org
      Attention needed from Alex Moshchuk and Daniel Cheng

      Alex Moshchuk added 1 comment

      Patchset-level comments
      Camille Lamy . resolved

      Thanks for the review! It took me quite a while to answer as I was OOO for three weeks. Following your suggestion, I have modified the CL to always create the AgentClusterKey we pass to the renderer process from scratch. It does make things a lot simpler. It's a bit unfortunate. However, maybe when more edge cases get migrated to using SiteInstanceGroup we might attempt to use the AgentClusterKey from the SiteInstance.

      Alex Moshchuk

      Thanks! I'm looking forward to reviewing this simpler version (looks very nice after a quick skim!), but just to set expectations, we've in the middle of our CSA hackathon and I may not be able to get to this review for another few days. I'll get to it when I can, and please let me know if there's any urgency or time constraints here to be aware of.

      Gerrit-Comment-Date: Sat, 06 Dec 2025 02:35:17 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      Comment-In-Reply-To: Camille Lamy <cl...@chromium.org>
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy

      Camille Lamy (Gerrit)

      unread,
      Dec 11, 2025, 4:32:04 AM12/11/25
      to Code Review Nudger, Alex Moshchuk, Daniel Cheng, AI Code Reviewer, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, ajwong...@chromium.org, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org
      Attention needed from Alex Moshchuk and Daniel Cheng

      Camille Lamy added 1 comment

      Patchset-level comments
      Camille Lamy . resolved

      Thanks for the review! It took me quite a while to answer as I was OOO for three weeks. Following your suggestion, I have modified the CL to always create the AgentClusterKey we pass to the renderer process from scratch. It does make things a lot simpler. It's a bit unfortunate. However, maybe when more edge cases get migrated to using SiteInstanceGroup we might attempt to use the AgentClusterKey from the SiteInstance.

      Alex Moshchuk

      Thanks! I'm looking forward to reviewing this simpler version (looks very nice after a quick skim!), but just to set expectations, we've in the middle of our CSA hackathon and I may not be able to get to this review for another few days. I'll get to it when I can, and please let me know if there's any urgency or time constraints here to be aware of.

      Camille Lamy

      Thanks! It's not urgent, but if possible I'd like to get this CL and its follow-up CL in before the holidays. I don't think you will need to review the follow-up CL if you're in hackathon period, so teh part of interest to you in the next one is very small (removing teh tracking of COI from RenderProcessHost).

      Gerrit-Comment-Date: Thu, 11 Dec 2025 09:31:50 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy

      Alex Moshchuk (Gerrit)

      unread,
      Dec 12, 2025, 6:41:15 PM12/12/25
      to Camille Lamy, Code Review Nudger, Daniel Cheng, AI Code Reviewer, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, ajwong...@chromium.org, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org
      Attention needed from Camille Lamy and Daniel Cheng

      Alex Moshchuk voted and added 11 comments

      Votes added by Alex Moshchuk

      Code-Review+1

      11 comments

      Patchset-level comments
      File-level comment, Patchset 25 (Latest):
      Alex Moshchuk . resolved

      Thanks, the new version makes content/ much simpler! content/ LGTM with some minor comments below. (Sorry again that it took me a while to get to this, due to the CSA hackathon and being out sick most of the week.)

      File content/browser/agent_cluster_key.h
      Line 260, Patchset 25 (Latest):// LINT.ThenChange(third_party/blink/public/mojom/frame/agent_cluster_key.mojom)
      Alex Moshchuk . unresolved

      Would it make sense to also list the two Blink files here for WebAgentClusterKey and blink::AgentClusterKey? Seems this can be a comma-separate list, per this [example](https://source.chromium.org/chromium/chromium/src/+/main:components/supervised_user/core/browser/proto/families_common.proto;l=40;drc=a96634cfe21812aa33b986ca36fdb5d01666f5be).

      Line 210, Patchset 25 (Latest): bool use_origin_keying,
      Alex Moshchuk . unresolved

      Maybe "is_origin_keyed"?

      Line 202, Patchset 25 (Latest): // |use_orgiin_keying| is false, an origin keyed will still be returned if a
      Alex Moshchuk . unresolved

      origin

      Line 202, Patchset 25 (Latest): // |use_orgiin_keying| is false, an origin keyed will still be returned if a
      Alex Moshchuk . unresolved

      nit: insert key

      Line 39, Patchset 25 (Latest):// done entirely in the browser process. |update_key_before_sending| is also not
      Alex Moshchuk . unresolved

      Update this comment, now that this no longer exists.

      File content/browser/renderer_host/navigation_request.cc
      Line 4011, Patchset 13: // Now build the appropriate AgentClusterKey for commit, starting with the
      Camille Lamy . resolved

      I have been considering moving all the code below to SiteInfo, as it essentially undoes all the special cases of GetAgentClusterKeyForURL, so maybe having the two in the same place to compare would be nice.

      Alex Moshchuk

      Yes, it might be worth moving this code into a separate helper, and maybe SiteInfo is a better place for it, as this function is getting long. It might be worth keeping the focus of this function on the OAC stuff as before, and then computing the key_to_commit as a separate step.

      One high-level concern I have with the content/browser side of this CL is indeed about introducing another place for handling these special cases, and moreover trying to reconstruct how we computed a SiteInfo based on the AgentClusterKey after the fact, which seems fragile (and potentially hard to maintain for future changes to the process model). Do you think it could be better to compute both the agent cluster key for SiteInfo and the agent cluster key to send to the renderer in the same place in GetAgentClusterKeyForURL? Basically, have all the special cases in one place, but computing two keys? Or at least compute the should_update_origin_or_site bit there, so that we know that the site URL we ended up with in SiteInfo is a Chrome-process-model specific URL and not what the actual agent cluster key should be per spec.

      (I'm not sure this is better or even feasible, just curious if it's worth thinking about at all.)

      Camille Lamy

      I have added a member to AgentClusterKey tracking whether we should update its origin/site URL before sending it. This allows to set it to true in all the edge cases we have in GetAgentClusterKeyForURL. This covers pretty much every edge case, except 4:

      • logical OAC (computed after we compute the AgentClusterKey)
      • opaque origins that are not data URLs -> we only pass the non opaque URL to SiteInfo, so it doesn't know the origin is actually opaque.
      • cross-origin isolated contexts when COI comes from COOP + COEP (temporary, will go away once we create AgentClusterKeys with COIKeys)
      • navigation to an existing SiteInstance without SiteIsolation when there is a redirect. See more about this one in the comment about this behavior.

      Wdyt of the new version?

      Alex Moshchuk

      Thanks, this looks better to me. It's a bit unfortunate that these decisions are still pretty spread out (e.g., the four exception cases you mentioned are here, most cases are special-cased in GetAgentClusterKeyForURL(), some are in special-case SiteInfo constructors (e.g. CreateForErrorPage), and then the last redirect case is in an entirely different place. I don't know if there's fundamentally a better organization, though, given all the constraints and how everything is structured at the moment. E.g., computing the renderer-side key closer to the place where we compute the browser-side key may not be possible without additional context for some cases (e.g., the data URL or the redirect cases you mentioned).

      I do have a couple of questions:

      • One SiteInstance might get reused by several possibly concurrent navigations (e.g., in several subframes). Is it a problem that we might set the new flag for one navigation and then a different navigation for different URL/origin might look at it at commit time, and incorrectly rely on the value of that flag that was computed for a different navigation? Or do we expect that all navigations in a particular SiteInstance that's marked as having a non-compliant key will need to recompute the AgentClusterKey?
      • Could we actually compute the renderer key from scratch at commit time, instead of basing it off of the browser-side key? We already have the origin to commit and at least some of the inputs for when it needs to be origin-keyed and/or cross-origin-isolated. Could that be simpler than trying to decide what pieces of the browser-side key can be reused?
      Camille Lamy

      Following your suggestion, I am now computing the renderer key from scratch. It's a bit unfortunate that we can't use the browser one, but there seems to be too many edge cases right now that introduce complexity. What do you think of the computation from scratch version?

      Alex Moshchuk

      This seems much simpler to me indeed. Glad that this worked out. Let's go with this approach, and maybe in the future if/when we have fewer corner cases, we might be able to revisit using the browser-side key.

      Line 4055, Patchset 25 (Latest): bool use_origin_agent_cluster = is_opaque_origin_because_sandbox ||
      Alex Moshchuk . unresolved

      maybe rename to something like is_origin_keyed_for_renderer? (Because it's covering more than OAC?)

      Line 4057, Patchset 25 (Latest): GetRenderFrameHost()
      ->GetSiteInstance()
      ->GetSiteInfo()
      .agent_cluster_key()
      .IsOriginKeyed();
      Alex Moshchuk . unresolved

      I forget, would this introduce any new cases for which the renderer would see an origin-keyed key, which it wasn't seeing before?

      Line 4065, Patchset 25 (Latest): // are not given a cross-origin isolated AgentClusterKey. Create one to send
      Alex Moshchuk . unresolved

      add "in their SiteInstance" or something like that, to be clear about which key this is describing?

      File third_party/blink/renderer/core/execution_context/window_agent_factory.cc
      Line 39, Patchset 25 (Latest): if (origin->IsLocal()) {
      Alex Moshchuk . unresolved

      Double-checking the file: URL flow: I'm not sure if I'm following this correctly, but the new code in DocumentLoader::InitializeWindow() seems to [create](https://chromium-review.googlesource.com/c/chromium/src/+/7041044/25/third_party/blink/renderer/core/loader/document_loader.cc#2650) a default blink::AgentClusterKey() for the origin->IsLocal case. IIRC, this default key is site-keyed with an empty URL. So how will we still end up with an origin for which IsLocal() is true here and use file_url_agent_?

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Camille Lamy
      • Daniel Cheng
      Submit Requirements:
        • requirement satisfiedCode-Coverage
        • requirement is not satisfiedCode-Owners
        • requirement satisfiedCode-Review
        • requirement is not satisfiedNo-Unresolved-Comments
        • requirement satisfiedReview-Enforcement
        Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
        Gerrit-MessageType: comment
        Gerrit-Project: chromium/src
        Gerrit-Branch: main
        Gerrit-Change-Id: Ibb98071005816e53e766fbcbe3fbcb642ee17592
        Gerrit-Change-Number: 7041044
        Gerrit-PatchSet: 25
        Gerrit-Owner: Camille Lamy <cl...@chromium.org>
        Gerrit-Reviewer: Alex Moshchuk <ale...@chromium.org>
        Gerrit-Reviewer: Camille Lamy <cl...@chromium.org>
        Gerrit-Reviewer: Daniel Cheng <dch...@chromium.org>
        Gerrit-CC: AI Code Reviewer <peep-gen...@system.gserviceaccount.com>
        Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
        Gerrit-CC: Hiroki Nakagawa <nhi...@chromium.org>
        Gerrit-CC: Kentaro Hara <har...@chromium.org>
        Gerrit-CC: Nate Chapin <jap...@chromium.org>
        Gerrit-CC: Raphael Kubo da Costa <ku...@igalia.com>
        Gerrit-Attention: Camille Lamy <cl...@chromium.org>
        Gerrit-Attention: Daniel Cheng <dch...@chromium.org>
        Gerrit-Comment-Date: Fri, 12 Dec 2025 23:41:03 +0000
        Gerrit-HasComments: Yes
        Gerrit-Has-Labels: Yes
        satisfied_requirement
        unsatisfied_requirement
        open
        diffy

        Camille Lamy (Gerrit)

        unread,
        Dec 16, 2025, 8:32:44 AM12/16/25
        to Alex Moshchuk, Code Review Nudger, Daniel Cheng, AI Code Reviewer, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, ajwong...@chromium.org, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org
        Attention needed from Alex Moshchuk and Daniel Cheng

        Camille Lamy added 9 comments

        Camille Lamy . resolved

        Thanks for the review!

        File content/browser/agent_cluster_key.h
        Line 260, Patchset 25:// LINT.ThenChange(third_party/blink/public/mojom/frame/agent_cluster_key.mojom)
        Alex Moshchuk . resolved

        Would it make sense to also list the two Blink files here for WebAgentClusterKey and blink::AgentClusterKey? Seems this can be a comma-separate list, per this [example](https://source.chromium.org/chromium/chromium/src/+/main:components/supervised_user/core/browser/proto/families_common.proto;l=40;drc=a96634cfe21812aa33b986ca36fdb5d01666f5be).

        Camille Lamy

        Done

        Line 210, Patchset 25: bool use_origin_keying,
        Alex Moshchuk . resolved

        Maybe "is_origin_keyed"?

        Camille Lamy

        Done

        Line 202, Patchset 25: // |use_orgiin_keying| is false, an origin keyed will still be returned if a
        Alex Moshchuk . resolved

        origin

        Camille Lamy

        Done

        Line 202, Patchset 25: // |use_orgiin_keying| is false, an origin keyed will still be returned if a
        Alex Moshchuk . resolved

        nit: insert key

        Camille Lamy

        Done

        Line 39, Patchset 25:// done entirely in the browser process. |update_key_before_sending| is also not
        Alex Moshchuk . resolved

        Update this comment, now that this no longer exists.

        Camille Lamy

        Done

        File content/browser/renderer_host/navigation_request.cc
        Line 4055, Patchset 25: bool use_origin_agent_cluster = is_opaque_origin_because_sandbox ||
        Alex Moshchuk . resolved

        maybe rename to something like is_origin_keyed_for_renderer? (Because it's covering more than OAC?)

        Camille Lamy

        Done

        Line 4057, Patchset 25: GetRenderFrameHost()

        ->GetSiteInstance()
        ->GetSiteInfo()
        .agent_cluster_key()
        .IsOriginKeyed();
        Alex Moshchuk . unresolved

        I forget, would this introduce any new cases for which the renderer would see an origin-keyed key, which it wasn't seeing before?

        Camille Lamy

        In terms of blink internals yes, but in terms in web visible behavior no.
        Basically, even if cross-origin isolated Agents were not marked as origin keyed, we already have code that prevent document.domain from working in cross-origin isolated documents. And we also had code that would expose the agent as origin keyed to JS when the Agent is cross-origin isolated (there's a test for that somewhere that failed at one point when developing this). So this would not be an issue for the web visible behavior, in fact it's aligning more closely Blink's internals with what we actually expose to the page.

        Line 4065, Patchset 25: // are not given a cross-origin isolated AgentClusterKey. Create one to send
        Alex Moshchuk . resolved

        add "in their SiteInstance" or something like that, to be clear about which key this is describing?

        Camille Lamy

        Done

        Open in Gerrit

        Related details

        Attention is currently required from:
        • Alex Moshchuk
        • Daniel Cheng
        Submit Requirements:
        • requirement satisfiedCode-Coverage
        • requirement is not satisfiedCode-Owners
        • requirement satisfiedCode-Review
        • requirement is not satisfiedNo-Unresolved-Comments
        • requirement satisfiedReview-Enforcement
        Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
        Gerrit-MessageType: comment
        Gerrit-Project: chromium/src
        Gerrit-Branch: main
        Gerrit-Change-Id: Ibb98071005816e53e766fbcbe3fbcb642ee17592
        Gerrit-Change-Number: 7041044
        Gerrit-PatchSet: 26
        Gerrit-Owner: Camille Lamy <cl...@chromium.org>
        Gerrit-Reviewer: Alex Moshchuk <ale...@chromium.org>
        Gerrit-Reviewer: Camille Lamy <cl...@chromium.org>
        Gerrit-Reviewer: Daniel Cheng <dch...@chromium.org>
        Gerrit-CC: AI Code Reviewer <peep-gen...@system.gserviceaccount.com>
        Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
        Gerrit-CC: Hiroki Nakagawa <nhi...@chromium.org>
        Gerrit-CC: Kentaro Hara <har...@chromium.org>
        Gerrit-CC: Nate Chapin <jap...@chromium.org>
        Gerrit-CC: Raphael Kubo da Costa <ku...@igalia.com>
        Gerrit-Attention: Alex Moshchuk <ale...@chromium.org>
        Gerrit-Attention: Daniel Cheng <dch...@chromium.org>
        Gerrit-Comment-Date: Tue, 16 Dec 2025 13:32:26 +0000
        satisfied_requirement
        unsatisfied_requirement
        open
        diffy

        Alex Moshchuk (Gerrit)

        unread,
        Dec 16, 2025, 12:39:00 PM12/16/25
        to Camille Lamy, Code Review Nudger, Daniel Cheng, AI Code Reviewer, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, ajwong...@chromium.org, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org
        Attention needed from Camille Lamy and Daniel Cheng

        Alex Moshchuk voted and added 3 comments

        Votes added by Alex Moshchuk

        Code-Review+1

        3 comments

        Patchset-level comments
        Alex Moshchuk . resolved

        (content/ still lgtm)

        File content/browser/renderer_host/navigation_request.cc
        Line 4057, Patchset 25: GetRenderFrameHost()
        ->GetSiteInstance()
        ->GetSiteInfo()
        .agent_cluster_key()
        .IsOriginKeyed();
        Alex Moshchuk . unresolved

        I forget, would this introduce any new cases for which the renderer would see an origin-keyed key, which it wasn't seeing before?

        Camille Lamy

        In terms of blink internals yes, but in terms in web visible behavior no.
        Basically, even if cross-origin isolated Agents were not marked as origin keyed, we already have code that prevent document.domain from working in cross-origin isolated documents. And we also had code that would expose the agent as origin keyed to JS when the Agent is cross-origin isolated (there's a test for that somewhere that failed at one point when developing this). So this would not be an issue for the web visible behavior, in fact it's aligning more closely Blink's internals with what we actually expose to the page.

        Alex Moshchuk

        Thanks, makes sense. This might be worth mentioning in the last sentence of the CL description, since it's a little more nuanced than a pure refactoring CL.

        File third_party/blink/renderer/core/execution_context/window_agent_factory.cc
        Line 39, Patchset 25: if (origin->IsLocal()) {
        Alex Moshchuk . unresolved

        Double-checking the file: URL flow: I'm not sure if I'm following this correctly, but the new code in DocumentLoader::InitializeWindow() seems to [create](https://chromium-review.googlesource.com/c/chromium/src/+/7041044/25/third_party/blink/renderer/core/loader/document_loader.cc#2650) a default blink::AgentClusterKey() for the origin->IsLocal case. IIRC, this default key is site-keyed with an empty URL. So how will we still end up with an origin for which IsLocal() is true here and use file_url_agent_?

        Alex Moshchuk

        Ping on this question, though I actually defer to Daniel for blink things :)

        Open in Gerrit

        Related details

        Attention is currently required from:
        • Camille Lamy
        • Daniel Cheng
        Gerrit-Attention: Camille Lamy <cl...@chromium.org>
        Gerrit-Attention: Daniel Cheng <dch...@chromium.org>
        Gerrit-Comment-Date: Tue, 16 Dec 2025 17:38:45 +0000
        satisfied_requirement
        unsatisfied_requirement
        open
        diffy

        Camille Lamy (Gerrit)

        unread,
        Jan 6, 2026, 1:36:24 PM (10 days ago) Jan 6
        to Alex Moshchuk, Code Review Nudger, Daniel Cheng, AI Code Reviewer, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, ajwong...@chromium.org, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org
        Attention needed from Alex Moshchuk and Daniel Cheng

        Camille Lamy added 1 comment

        File third_party/blink/renderer/core/execution_context/window_agent_factory.cc
        Line 39, Patchset 25: if (origin->IsLocal()) {
        Alex Moshchuk . unresolved

        Double-checking the file: URL flow: I'm not sure if I'm following this correctly, but the new code in DocumentLoader::InitializeWindow() seems to [create](https://chromium-review.googlesource.com/c/chromium/src/+/7041044/25/third_party/blink/renderer/core/loader/document_loader.cc#2650) a default blink::AgentClusterKey() for the origin->IsLocal case. IIRC, this default key is site-keyed with an empty URL. So how will we still end up with an origin for which IsLocal() is true here and use file_url_agent_?

        Alex Moshchuk

        Ping on this question, though I actually defer to Daniel for blink things :)

        Camille Lamy

        Right this was indeed an issue and we did not go into this code block. I now create a site-keyed AgentClusterKey in the file case using the file URL, so we do hit that. As explained in the comment below, the AgentCluster is created with the first file AgentClusterKey the WindowAgentFactory encounters. We do need a key with a file URL stored in the AgentCluster so that an about blank document inherits a key that will be recognized as local and put in the same AgentCluster. It does work since all file URLs get assigned to this special AgentCluster, but it also means that the URL we stored in the AgentClusterKey might not match that of later documents.

        Open in Gerrit

        Related details

        Attention is currently required from:
        • Alex Moshchuk
        • Daniel Cheng
        Submit Requirements:
        • requirement satisfiedCode-Coverage
        • requirement is not satisfiedCode-Owners
        • requirement satisfiedCode-Review
        • requirement is not satisfiedNo-Unresolved-Comments
        • requirement satisfiedReview-Enforcement
        Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
        Gerrit-MessageType: comment
        Gerrit-Project: chromium/src
        Gerrit-Branch: main
        Gerrit-Change-Id: Ibb98071005816e53e766fbcbe3fbcb642ee17592
        Gerrit-Change-Number: 7041044
        Gerrit-PatchSet: 30
        Gerrit-Owner: Camille Lamy <cl...@chromium.org>
        Gerrit-Reviewer: Alex Moshchuk <ale...@chromium.org>
        Gerrit-Reviewer: Camille Lamy <cl...@chromium.org>
        Gerrit-Reviewer: Daniel Cheng <dch...@chromium.org>
        Gerrit-CC: AI Code Reviewer <peep-gen...@system.gserviceaccount.com>
        Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
        Gerrit-CC: Hiroki Nakagawa <nhi...@chromium.org>
        Gerrit-CC: Kentaro Hara <har...@chromium.org>
        Gerrit-CC: Nate Chapin <jap...@chromium.org>
        Gerrit-CC: Raphael Kubo da Costa <ku...@igalia.com>
        Gerrit-Attention: Alex Moshchuk <ale...@chromium.org>
        Gerrit-Attention: Daniel Cheng <dch...@chromium.org>
        Gerrit-Comment-Date: Tue, 06 Jan 2026 18:36:08 +0000
        satisfied_requirement
        unsatisfied_requirement
        open
        diffy

        Daniel Cheng (Gerrit)

        unread,
        Jan 6, 2026, 4:33:36 PM (10 days ago) Jan 6
        to Camille Lamy, Alex Moshchuk, Code Review Nudger, Daniel Cheng, AI Code Reviewer, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, ajwong...@chromium.org, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org
        Attention needed from Alex Moshchuk and Camille Lamy

        Daniel Cheng added 33 comments

        Patchset-level comments
        File-level comment, Patchset 30 (Latest):
        Daniel Cheng . resolved

        Sorry for the long delay here. Most of the comments are around some plumbing and (hopefully) simplification; a few comments about the file: question.

        File third_party/blink/public/mojom/frame/agent_cluster_key.mojom
        Line 22, Patchset 30 (Latest): // The origin of the document which triggered cross-origin isolation. It
        // might be different from the origin associated with the AgentClusterKey
        // when cross-origin isolation is enabled by COOP + COEP. When cross-origin
        Daniel Cheng . unresolved

        It might be nice to give a concrete example or link to an example of what this would look like in practice, or give some background about why it works this way.

        Line 27, Patchset 30 (Latest): url.mojom.Origin common_coi_origin;

        CrossOriginIsolationMode cross_origin_isolation_mode;
        Daniel Cheng . unresolved
        ```suggestion
        url.mojom.Origin common_origin;
          CrossOriginIsolationMode mode;
        ```

        Since "cross origin isolation" mode is already in the type name, and otherwise, the field names are internally inconsistent.

        File third_party/blink/public/web/web_agent_cluster_key.h
        Line 46, Patchset 30 (Latest): std::variant<WebOriginKeyedAgentClusterKey, WebURL> key;
        Daniel Cheng . unresolved

        It's a bit unusual to provide constructors and also provide direct field access.

        I would probably make this one a class and add the conversion operators for AgentClusterKey here (similarly to how it works for `WebSecurityOrigin` and `WebURL`, which define conversion operators if `INSIDE_BLINK` is defined) so we don't need to add any getters. No reason for people to use the fields directly once it's constructed, since it only goes from //content into Blink anyway.

        Line 34, Patchset 30 (Latest): const std::optional<WebCrossOriginIsolationKey>& isolation_key)
        Daniel Cheng . unresolved

        Nit: it would be better to pass as `const WebCrossOriginIsolationKey*` or as `base::optional_ref<const WebCrossOriginIsolationKey>`; passing by `const std::optional<T>&` is prone to "copies by implicit conversions". I don't have a strong preference which.

        https://google.github.io/styleguide/cppguide.html#Inputs_and_Outputs: "Generally, use std::optional to represent optional by-value inputs, and use a const pointer when the non-optional form would have used a reference."

        However, even better here is to omit the constructors here and use designated initialisers; see my example down below.

        Line 31, Patchset 30 (Latest):struct WebOriginKeyedAgentClusterKey {
        Daniel Cheng . unresolved

        Nit: add a comment here

        Line 27, Patchset 30 (Latest): WebSecurityOrigin common_coi_origin;
        mojom::CrossOriginIsolationMode cross_origin_isolation_mode;
        };
        Daniel Cheng . unresolved

        1. It's a bit inconsistent that one field is named "coi" and the other expands the acronym.
        2. cross origin isolation is in the type name already.

        So I'd suggest:


        ```suggestion
        WebSecurityOrigin common_origin;
        mojom::CrossOriginIsolationMode mode;
        };
        ```
        Line 21, Patchset 30 (Latest): WebCrossOriginIsolationKey(
        Daniel Cheng . unresolved

        Let's just use designated initialisers.

        File third_party/blink/renderer/core/execution_context/agent_cluster_key.h
        Line 181, Patchset 30 (Latest): static AgentClusterKey EmptyValue() { return AgentClusterKey::CreateEmpty(); }
        Daniel Cheng . unresolved

        Nit: I think these can return const refs, since `AgentClusterKey` is somewhat large and not completely free to copy.

        Line 157, Patchset 30 (Latest): key_status += (1 << 1);
        Daniel Cheng . unresolved

        Very minor nit: I would expect to see |= for bitmasks.

        Line 123, Patchset 30 (Latest): std::variant<KURL, scoped_refptr<SecurityOrigin>> key_;

        // This is used by DocumentIsolationPolicy and COOP and COEP to isolate
        // execution contexts with extra-capabilities in an agent cluster with the
        // appropriate cross-origin isolation status. Setting this to nullopt means
        // that the AgentClusterKey is not cross-origin isolated.
        std::optional<CrossOriginIsolationKey> isolation_key_;
        Daniel Cheng . unresolved

        A slightly more compact representation would be to have an inner `struct Empty` and `struct Deleted` instead of the bool fields. It's probably worth doing.

        I think we should also group the origin-keyed info together like we do for the Web version, so this gives us:

        ```suggestion
        // Tombstone markers for `blink::HashTraits`.
        struct Empty {};
        struct Deleted {};
        struct OriginKey {
        scoped_refptr<SecurityOrigin> origin;
        std::optional<CrossOriginIsolationKey> isolation_key;
        };
        std::variant<KURL, OriginKey, Empty, Deleted> key_;
        ```
        Line 101, Patchset 30 (Latest): bool GetIsEmpty() const { return is_empty_; }
        Daniel Cheng . unresolved

        Similarly let's restrict this to the `HashTraits`.

        Line 81, Patchset 30 (Latest): static AgentClusterKey CreateDeleted();
        Daniel Cheng . unresolved

        Can we use passkey to restrict this to the HashTraits, since no "normal" code should be creating these values ever?

        Line 73, Patchset 30 (Latest): const std::optional<CrossOriginIsolationKey>& isolation_key);
        Daniel Cheng . unresolved

        Similar comment about using `base::optional_ref` or a pointer here.

        But given the fact that we have `CreateOriginKeyed()` above, I'm wondering if this even needs to be optional; the call in the .cc file always passes a `std::optional` with an engaged value.

        Line 61, Patchset 30 (Latest): scoped_refptr<SecurityOrigin> common_coi_origin;
        Daniel Cheng . unresolved

        Naming-wise, it's a bit inconsistent that we use "common_coi_origin" here and "cross_origin_isolation_mode" below.

        Given the name of the class, I would suggest simplifying things and just calling this `common_origin` and `mode`; that makes the names a bit shorter, since "cross origin isolation" is already in the type name.

        Line 43, Patchset 30 (Latest): scoped_refptr<SecurityOrigin> origin);
        Daniel Cheng . unresolved

        Throughout this class, I think we probably want `scoped_refptr<const SecurityOrigin>`, which will remove the need for `IsolatedCopy()`.

        This will have transitive effects elsewhere in Blink code, but it means that the SecurityOrigin can't change from underneath us which is good.

        Line 31, Patchset 30 (Latest): DISALLOW_NEW();
        Daniel Cheng . unresolved

        This doesn't really hurt, but I'm also wondering if it's needed? There's nothing that needs to be traced, and it makes things a bit more complicated elsewhere (e.g. DisallowNewWrapper)

        Line 33, Patchset 13: AgentClusterKey();
        Daniel Cheng . unresolved

        What does this create by default? Is it site keyed, origin keyed, or neither?

        Camille Lamy

        A site-keyed AgentClusterKey with KURL(). It's only there so that it works with the map. Added comments to clarify.

        Daniel Cheng

        I don't quite get why this is needed for map still; what am I missing? :)

        File third_party/blink/renderer/core/execution_context/agent_cluster_key.cc
        Line 23, Patchset 30 (Latest): return AgentClusterKey(origin, std::nullopt);
        Daniel Cheng . unresolved

        Nit: std::move() (and include `<utility>`)

        Line 29, Patchset 30 (Latest): : common_coi_origin(common_coi_origin),
        Daniel Cheng . unresolved

        Nit: std::move()

        Line 50, Patchset 30 (Latest): return AgentClusterKey(origin, isolation_key);
        Daniel Cheng . unresolved

        Nit: std::move()

        Line 54, Patchset 30 (Latest):AgentClusterKey AgentClusterKey::CreateFromWebAgentClusterKey(
        Daniel Cheng . unresolved

        Let's define these helpers as conversion operators on `WebAgentClusterKey` instead of here.

        Line 56, Patchset 30 (Latest): if (std::holds_alternative<WebURL>(web_ac_key.key)) {
        return AgentClusterKey::CreateSiteKeyed(std::get<WebURL>(web_ac_key.key));
        }

        CHECK(std::holds_alternative<WebOriginKeyedAgentClusterKey>(web_ac_key.key));
        const auto& origin_keyed_key =
        std::get<WebOriginKeyedAgentClusterKey>(web_ac_key.key);
        if (origin_keyed_key.isolation_key.has_value()) {
        std::optional<CrossOriginIsolationKey> coi_key = CrossOriginIsolationKey(
        origin_keyed_key.isolation_key->common_coi_origin.Get()->IsolatedCopy(),
        origin_keyed_key.isolation_key->cross_origin_isolation_mode);
        return AgentClusterKey::CreateWithCrossOriginIsolationKey(
        origin_keyed_key.origin.Get()->IsolatedCopy(), coi_key);
        }

        return AgentClusterKey::CreateOriginKeyed(
        origin_keyed_key.origin.Get()->IsolatedCopy());
        Daniel Cheng . unresolved
        Note: I dropped the `IsolatedCopy()` calls below since it's not clear they're actually needed.
        ```suggestion
        return std::visit(absl::Overload {
        [] (const WebURL& site_url) {
        return AgentClusterKey::CreateSiteKeyed(site_url);
        },
        [] (const WebOriginKeyedAgentClusterKey& cluster_key) {
        if (cluster_key.isolation_key.has_value()) {
        std::optional<CrossOriginIsolationKey> coi_key =
        CrossOriginIsolationKey(
        cluster_key.isolation_key->common_coi_origin,
        cluster_key.isolation_key->cross_origin_isolation_mode);
        return AgentClusterKey::CreateWithCrossOriginIsolationKey(
        cluster_key.origin, coi_key);
        }
        return AgentClusterKey::CreateOriginKeyed(
        cluster_key.origin);
        }, web_ac_key.key);
        ```
        Line 86, Patchset 30 (Latest): WebAgentClusterKey web_ac_key;
        if (IsSiteKeyed()) {
        web_ac_key.key = std::get<KURL>(key_);
        return web_ac_key;
        }

        std::optional<WebCrossOriginIsolationKey> coi_key;
        if (isolation_key_.has_value()) {
        coi_key = WebCrossOriginIsolationKey(
        WebSecurityOrigin(isolation_key_->common_coi_origin),
        isolation_key_->cross_origin_isolation_mode);
        }

        web_ac_key.key = WebOriginKeyedAgentClusterKey(
        WebSecurityOrigin(std::get<scoped_refptr<SecurityOrigin>>(key_)),
        coi_key);

        return web_ac_key;
        Daniel Cheng . unresolved

        Similarly let's use `std::visit()` here:

        ```suggestion
        return std::visit(absl::Overload {
        [] (const KURL& site_url) {
        return WebAgentClusterKey(site_url);
        },
        // Assuming we group the origin params into a struct
        [] (const OriginKey& key) {
        if (key.isolation_key.has_value()) {
        // Assuming we use designated initialisers.
        return WebAgentClusterKey(
        WebOriginKeyedAgentClusterKey {
        .origin = key.origin,
        .isolation_key = {
        .common_coi_origin = key.isolation_key_->common_coi_origin,
        .cross_origin_isolation_mode =
        key.isolation_key_->cross_origin_isolation_mode
        }
        });
        }
        return WebOriginKeyedAgentClusterKey(
        WebOriginKeyedAgentClusterKey { .origin = key.origin, });
        },
        [] (const auto&) { NOTREACHED(); },
        },
        });
        ```
        Line 115, Patchset 30 (Latest): if (is_deleted_ != b.is_deleted_ || is_empty_ != b.is_empty_) {
        return false;
        }

        if (IsSiteKeyed()) {
        if (!b.IsSiteKeyed()) {
        return false;
        }
        CHECK(!GetCrossOriginIsolationKey().has_value() &&
        !b.GetCrossOriginIsolationKey().has_value());
        return GetURL() == b.GetURL();
        }

        CHECK(IsOriginKeyed());

        if (!b.IsOriginKeyed()) {
        return false;
        }

        if (!GetOrigin()->IsSameOriginWith(b.GetOrigin())) {
        return false;
        }

        if (GetCrossOriginIsolationKey().has_value() !=
        b.GetCrossOriginIsolationKey().has_value()) {
        return false;
        }

        if (GetCrossOriginIsolationKey().has_value()) {
        return GetCrossOriginIsolationKey().value() ==
        b.GetCrossOriginIsolationKey().value();
        }

        return true;
        Daniel Cheng . unresolved

        If we define operator== for all the types in `std::variant`, then I think we can simplify this (or default it)

        Line 159, Patchset 30 (Latest): : key_(origin), isolation_key_(isolation_key) {}
        Daniel Cheng . unresolved

        Nit: std::move()

        File third_party/blink/renderer/core/execution_context/window_agent_factory.h
        Line 57, Patchset 30 (Latest): using AgentsMap = HeapHashMap<AgentClusterKey,
        WeakMember<WindowAgent>,
        HashTraits<AgentClusterKey>>;
        Daniel Cheng . unresolved
        ```suggestion
        using AgentsMap = HeapHashMap<AgentClusterKey,
        WeakMember<WindowAgent>>;
        ```

        (I think the explicit HashTraits here is already the default anyway)

        Line 34, Patchset 30 (Latest): // Returns an instance of WindowAgent for |agent_cluster_key|.
        Daniel Cheng . unresolved
        Very minor nit: since we're changing this, let's use backticks.
        ```suggestion
        // Returns an instance of WindowAgent for `agent_cluster_key`.
        ```
        File third_party/blink/renderer/core/execution_context/window_agent_factory.cc
        Line 34, Patchset 24: // For `file:` scheme origins.
        Daniel Cheng . unresolved

        This comment should be a few lines down.

        Line 38, Patchset 30 (Latest): : SecurityOrigin::Create(agent_cluster_key.GetURL());
        Daniel Cheng . unresolved

        Do we really need to keep the site URL around, if we end up turning it into an origin here?

        Line 39, Patchset 25: if (origin->IsLocal()) {
        Alex Moshchuk . unresolved

        Double-checking the file: URL flow: I'm not sure if I'm following this correctly, but the new code in DocumentLoader::InitializeWindow() seems to [create](https://chromium-review.googlesource.com/c/chromium/src/+/7041044/25/third_party/blink/renderer/core/loader/document_loader.cc#2650) a default blink::AgentClusterKey() for the origin->IsLocal case. IIRC, this default key is site-keyed with an empty URL. So how will we still end up with an origin for which IsLocal() is true here and use file_url_agent_?

        Alex Moshchuk

        Ping on this question, though I actually defer to Daniel for blink things :)

        Camille Lamy

        Right this was indeed an issue and we did not go into this code block. I now create a site-keyed AgentClusterKey in the file case using the file URL, so we do hit that. As explained in the comment below, the AgentCluster is created with the first file AgentClusterKey the WindowAgentFactory encounters. We do need a key with a file URL stored in the AgentCluster so that an about blank document inherits a key that will be recognized as local and put in the same AgentCluster. It does work since all file URLs get assigned to this special AgentCluster, but it also means that the URL we stored in the AgentClusterKey might not match that of later documents.

        Daniel Cheng

        ... yeah it's a bit weird but maybe it's "okay"? But see my question above; I'm wondering if we should be passing down site keys as a URL at all, or if it should just be an origin. If it was a file: origin, maybe that'd prevent the mismatch from happening at all?

        Line 55, Patchset 30 (Latest): // For all other cases, we rely on the provided AgentClusterKey.
        Daniel Cheng . unresolved

        This comment seems out of place, since the extensions special case is right below it.

        Line 57, Patchset 30 (Latest): if (CommonSchemeRegistry::IsExtensionScheme(origin->Protocol().Ascii())) {
        Daniel Cheng . unresolved

        Should we keep the comment for the extension case?

        Open in Gerrit

        Related details

        Attention is currently required from:
        • Alex Moshchuk
        • Camille Lamy
        Gerrit-Attention: Camille Lamy <cl...@chromium.org>
        Gerrit-Comment-Date: Tue, 06 Jan 2026 21:33:22 +0000
        Gerrit-HasComments: Yes
        Gerrit-Has-Labels: No
        Comment-In-Reply-To: Alex Moshchuk <ale...@chromium.org>
        satisfied_requirement
        unsatisfied_requirement
        open
        diffy

        Camille Lamy (Gerrit)

        unread,
        Jan 9, 2026, 11:08:17 AM (7 days ago) Jan 9
        to Alex Moshchuk, Code Review Nudger, Daniel Cheng, AI Code Reviewer, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, ajwong...@chromium.org, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org
        Attention needed from Alex Moshchuk and Daniel Cheng

        Camille Lamy added 34 comments

        Patchset-level comments
        File-level comment, Patchset 33 (Latest):
        Camille Lamy . resolved

        Thanks!

        File content/browser/renderer_host/navigation_request.cc
        Line 4057, Patchset 25: GetRenderFrameHost()
        ->GetSiteInstance()
        ->GetSiteInfo()
        .agent_cluster_key()
        .IsOriginKeyed();
        Alex Moshchuk . resolved

        I forget, would this introduce any new cases for which the renderer would see an origin-keyed key, which it wasn't seeing before?

        Camille Lamy

        In terms of blink internals yes, but in terms in web visible behavior no.
        Basically, even if cross-origin isolated Agents were not marked as origin keyed, we already have code that prevent document.domain from working in cross-origin isolated documents. And we also had code that would expose the agent as origin keyed to JS when the Agent is cross-origin isolated (there's a test for that somewhere that failed at one point when developing this). So this would not be an issue for the web visible behavior, in fact it's aligning more closely Blink's internals with what we actually expose to the page.

        Alex Moshchuk

        Thanks, makes sense. This might be worth mentioning in the last sentence of the CL description, since it's a little more nuanced than a pure refactoring CL.

        Camille Lamy

        I have added a detailed explanation of the change.

        File third_party/blink/public/mojom/frame/agent_cluster_key.mojom
        Line 22, Patchset 30: // The origin of the document which triggered cross-origin isolation. It

        // might be different from the origin associated with the AgentClusterKey
        // when cross-origin isolation is enabled by COOP + COEP. When cross-origin
        Daniel Cheng . unresolved

        It might be nice to give a concrete example or link to an example of what this would look like in practice, or give some background about why it works this way.

        Camille Lamy

        I have added extra details.

        Line 27, Patchset 30: url.mojom.Origin common_coi_origin;

        CrossOriginIsolationMode cross_origin_isolation_mode;
        Daniel Cheng . resolved
        ```suggestion
        url.mojom.Origin common_origin;
          CrossOriginIsolationMode mode;
        ```

        Since "cross origin isolation" mode is already in the type name, and otherwise, the field names are internally inconsistent.

        Camille Lamy

        Done

        File third_party/blink/public/web/web_agent_cluster_key.h
        Line 46, Patchset 30: std::variant<WebOriginKeyedAgentClusterKey, WebURL> key;
        Daniel Cheng . resolved

        It's a bit unusual to provide constructors and also provide direct field access.

        I would probably make this one a class and add the conversion operators for AgentClusterKey here (similarly to how it works for `WebSecurityOrigin` and `WebURL`, which define conversion operators if `INSIDE_BLINK` is defined) so we don't need to add any getters. No reason for people to use the fields directly once it's constructed, since it only goes from //content into Blink anyway.

        Camille Lamy

        Done

        Line 34, Patchset 30: const std::optional<WebCrossOriginIsolationKey>& isolation_key)
        Daniel Cheng . resolved

        Nit: it would be better to pass as `const WebCrossOriginIsolationKey*` or as `base::optional_ref<const WebCrossOriginIsolationKey>`; passing by `const std::optional<T>&` is prone to "copies by implicit conversions". I don't have a strong preference which.

        https://google.github.io/styleguide/cppguide.html#Inputs_and_Outputs: "Generally, use std::optional to represent optional by-value inputs, and use a const pointer when the non-optional form would have used a reference."

        However, even better here is to omit the constructors here and use designated initialisers; see my example down below.

        Camille Lamy

        Done

        Line 31, Patchset 30:struct WebOriginKeyedAgentClusterKey {
        Daniel Cheng . resolved

        Nit: add a comment here

        Camille Lamy

        Done

        Line 27, Patchset 30: WebSecurityOrigin common_coi_origin;
        mojom::CrossOriginIsolationMode cross_origin_isolation_mode;
        };
        Daniel Cheng . resolved

        1. It's a bit inconsistent that one field is named "coi" and the other expands the acronym.
        2. cross origin isolation is in the type name already.

        So I'd suggest:


        ```suggestion
        WebSecurityOrigin common_origin;
        mojom::CrossOriginIsolationMode mode;
        };
        ```
        Camille Lamy

        Done

        Line 21, Patchset 30: WebCrossOriginIsolationKey(
        Daniel Cheng . resolved

        Let's just use designated initialisers.

        Camille Lamy

        Done

        File third_party/blink/renderer/core/execution_context/agent_cluster_key.h
        Line 181, Patchset 30: static AgentClusterKey EmptyValue() { return AgentClusterKey::CreateEmpty(); }
        Daniel Cheng . unresolved

        Nit: I think these can return const refs, since `AgentClusterKey` is somewhat large and not completely free to copy.

        Camille Lamy

        If I were to return const refs, I would need to define a static value whose reference I return, right? However, to do so I would generally use DEFINE_STATIC_LOCAL which does not work with factory methods like AgentClusterKey::CreateEmpty. I'd like to keep the factory methods, so not sure how to define the static variable in that case. Or am I missing something?

        Line 157, Patchset 30: key_status += (1 << 1);
        Daniel Cheng . resolved

        Very minor nit: I would expect to see |= for bitmasks.

        Camille Lamy

        Done

        Line 123, Patchset 30: std::variant<KURL, scoped_refptr<SecurityOrigin>> key_;


        // This is used by DocumentIsolationPolicy and COOP and COEP to isolate
        // execution contexts with extra-capabilities in an agent cluster with the
        // appropriate cross-origin isolation status. Setting this to nullopt means
        // that the AgentClusterKey is not cross-origin isolated.
        std::optional<CrossOriginIsolationKey> isolation_key_;
        Daniel Cheng . resolved

        A slightly more compact representation would be to have an inner `struct Empty` and `struct Deleted` instead of the bool fields. It's probably worth doing.

        I think we should also group the origin-keyed info together like we do for the Web version, so this gives us:

        ```suggestion
        // Tombstone markers for `blink::HashTraits`.
        struct Empty {};
        struct Deleted {};
        struct OriginKey {
        scoped_refptr<SecurityOrigin> origin;
        std::optional<CrossOriginIsolationKey> isolation_key;
        };
        std::variant<KURL, OriginKey, Empty, Deleted> key_;
        ```
        Camille Lamy

        Done

        Line 101, Patchset 30: bool GetIsEmpty() const { return is_empty_; }
        Daniel Cheng . resolved

        Similarly let's restrict this to the `HashTraits`.

        Camille Lamy

        Done

        Line 81, Patchset 30: static AgentClusterKey CreateDeleted();
        Daniel Cheng . resolved

        Can we use passkey to restrict this to the HashTraits, since no "normal" code should be creating these values ever?

        Camille Lamy

        Done

        Line 73, Patchset 30: const std::optional<CrossOriginIsolationKey>& isolation_key);
        Daniel Cheng . resolved

        Similar comment about using `base::optional_ref` or a pointer here.

        But given the fact that we have `CreateOriginKeyed()` above, I'm wondering if this even needs to be optional; the call in the .cc file always passes a `std::optional` with an engaged value.

        Camille Lamy

        Done

        Line 61, Patchset 30: scoped_refptr<SecurityOrigin> common_coi_origin;
        Daniel Cheng . resolved

        Naming-wise, it's a bit inconsistent that we use "common_coi_origin" here and "cross_origin_isolation_mode" below.

        Given the name of the class, I would suggest simplifying things and just calling this `common_origin` and `mode`; that makes the names a bit shorter, since "cross origin isolation" is already in the type name.

        Camille Lamy

        Done

        Line 43, Patchset 30: scoped_refptr<SecurityOrigin> origin);
        Daniel Cheng . resolved

        Throughout this class, I think we probably want `scoped_refptr<const SecurityOrigin>`, which will remove the need for `IsolatedCopy()`.

        This will have transitive effects elsewhere in Blink code, but it means that the SecurityOrigin can't change from underneath us which is good.

        Camille Lamy

        Done

        Line 31, Patchset 30: DISALLOW_NEW();
        Daniel Cheng . resolved

        This doesn't really hurt, but I'm also wondering if it's needed? There's nothing that needs to be traced, and it makes things a bit more complicated elsewhere (e.g. DisallowNewWrapper)

        Camille Lamy

        Done

        Line 33, Patchset 13: AgentClusterKey();
        Daniel Cheng . resolved

        What does this create by default? Is it site keyed, origin keyed, or neither?

        Camille Lamy

        A site-keyed AgentClusterKey with KURL(). It's only there so that it works with the map. Added comments to clarify.

        Daniel Cheng

        I don't quite get why this is needed for map still; what am I missing? :)

        Camille Lamy

        Ok it seems that it is indeed not needed so I have removed it.

        File third_party/blink/renderer/core/execution_context/agent_cluster_key.cc
        Line 23, Patchset 30: return AgentClusterKey(origin, std::nullopt);
        Daniel Cheng . resolved

        Nit: std::move() (and include `<utility>`)

        Camille Lamy

        Done

        Line 29, Patchset 30: : common_coi_origin(common_coi_origin),
        Daniel Cheng . resolved

        Nit: std::move()

        Camille Lamy

        Done

        Line 50, Patchset 30: return AgentClusterKey(origin, isolation_key);
        Daniel Cheng . resolved

        Nit: std::move()

        Camille Lamy

        Done

        Line 54, Patchset 30:AgentClusterKey AgentClusterKey::CreateFromWebAgentClusterKey(
        Daniel Cheng . resolved

        Let's define these helpers as conversion operators on `WebAgentClusterKey` instead of here.

        Camille Lamy

        Done

        Line 56, Patchset 30: if (std::holds_alternative<WebURL>(web_ac_key.key)) {

        return AgentClusterKey::CreateSiteKeyed(std::get<WebURL>(web_ac_key.key));
        }

        CHECK(std::holds_alternative<WebOriginKeyedAgentClusterKey>(web_ac_key.key));
        const auto& origin_keyed_key =
        std::get<WebOriginKeyedAgentClusterKey>(web_ac_key.key);
        if (origin_keyed_key.isolation_key.has_value()) {
        std::optional<CrossOriginIsolationKey> coi_key = CrossOriginIsolationKey(
        origin_keyed_key.isolation_key->common_coi_origin.Get()->IsolatedCopy(),
        origin_keyed_key.isolation_key->cross_origin_isolation_mode);
        return AgentClusterKey::CreateWithCrossOriginIsolationKey(
        origin_keyed_key.origin.Get()->IsolatedCopy(), coi_key);
        }

        return AgentClusterKey::CreateOriginKeyed(
        origin_keyed_key.origin.Get()->IsolatedCopy());
        Daniel Cheng . resolved
        Note: I dropped the `IsolatedCopy()` calls below since it's not clear they're actually needed.
        ```suggestion
        return std::visit(absl::Overload {
        [] (const WebURL& site_url) {
        return AgentClusterKey::CreateSiteKeyed(site_url);
        },
        [] (const WebOriginKeyedAgentClusterKey& cluster_key) {
        if (cluster_key.isolation_key.has_value()) {
        std::optional<CrossOriginIsolationKey> coi_key =
        CrossOriginIsolationKey(
        cluster_key.isolation_key->common_coi_origin,
        cluster_key.isolation_key->cross_origin_isolation_mode);
        return AgentClusterKey::CreateWithCrossOriginIsolationKey(
        cluster_key.origin, coi_key);
        }
        return AgentClusterKey::CreateOriginKeyed(
        cluster_key.origin);
        }, web_ac_key.key);
        ```
        Camille Lamy

        Done

        Line 86, Patchset 30: WebAgentClusterKey web_ac_key;

        if (IsSiteKeyed()) {
        web_ac_key.key = std::get<KURL>(key_);
        return web_ac_key;
        }

        std::optional<WebCrossOriginIsolationKey> coi_key;
        if (isolation_key_.has_value()) {
        coi_key = WebCrossOriginIsolationKey(
        WebSecurityOrigin(isolation_key_->common_coi_origin),
        isolation_key_->cross_origin_isolation_mode);
        }

        web_ac_key.key = WebOriginKeyedAgentClusterKey(
        WebSecurityOrigin(std::get<scoped_refptr<SecurityOrigin>>(key_)),
        coi_key);

        return web_ac_key;
        Daniel Cheng . resolved

        Similarly let's use `std::visit()` here:

        ```suggestion
        return std::visit(absl::Overload {
        [] (const KURL& site_url) {
        return WebAgentClusterKey(site_url);
        },
        // Assuming we group the origin params into a struct
        [] (const OriginKey& key) {
        if (key.isolation_key.has_value()) {
        // Assuming we use designated initialisers.
        return WebAgentClusterKey(
        WebOriginKeyedAgentClusterKey {
        .origin = key.origin,
        .isolation_key = {
        .common_coi_origin = key.isolation_key_->common_coi_origin,
        .cross_origin_isolation_mode =
        key.isolation_key_->cross_origin_isolation_mode
        }
        });
        }
        return WebOriginKeyedAgentClusterKey(
        WebOriginKeyedAgentClusterKey { .origin = key.origin, });
        },
        [] (const auto&) { NOTREACHED(); },
        },
        });
        ```
        Camille Lamy

        Done

        Line 115, Patchset 30: if (is_deleted_ != b.is_deleted_ || is_empty_ != b.is_empty_) {

        return false;
        }

        if (IsSiteKeyed()) {
        if (!b.IsSiteKeyed()) {
        return false;
        }
        CHECK(!GetCrossOriginIsolationKey().has_value() &&
        !b.GetCrossOriginIsolationKey().has_value());
        return GetURL() == b.GetURL();
        }

        CHECK(IsOriginKeyed());

        if (!b.IsOriginKeyed()) {
        return false;
        }

        if (!GetOrigin()->IsSameOriginWith(b.GetOrigin())) {
        return false;
        }

        if (GetCrossOriginIsolationKey().has_value() !=
        b.GetCrossOriginIsolationKey().has_value()) {
        return false;
        }

        if (GetCrossOriginIsolationKey().has_value()) {
        return GetCrossOriginIsolationKey().value() ==
        b.GetCrossOriginIsolationKey().value();
        }

        return true;
        Daniel Cheng . resolved

        If we define operator== for all the types in `std::variant`, then I think we can simplify this (or default it)

        Camille Lamy

        Done

        Line 159, Patchset 30: : key_(origin), isolation_key_(isolation_key) {}
        Daniel Cheng . resolved

        Nit: std::move()

        Camille Lamy

        This constructor no longer exists.

        File third_party/blink/renderer/core/execution_context/window_agent_factory.h
        Line 57, Patchset 30: using AgentsMap = HeapHashMap<AgentClusterKey,

        WeakMember<WindowAgent>,
        HashTraits<AgentClusterKey>>;
        Daniel Cheng . resolved
        ```suggestion
        using AgentsMap = HeapHashMap<AgentClusterKey,
        WeakMember<WindowAgent>>;
        ```

        (I think the explicit HashTraits here is already the default anyway)

        Camille Lamy

        Done

        Line 34, Patchset 30: // Returns an instance of WindowAgent for |agent_cluster_key|.
        Daniel Cheng . resolved
        Very minor nit: since we're changing this, let's use backticks.
        ```suggestion
        // Returns an instance of WindowAgent for `agent_cluster_key`.
        ```
        Camille Lamy

        Done

        File third_party/blink/renderer/core/execution_context/window_agent_factory.cc
        Line 34, Patchset 24: // For `file:` scheme origins.
        Daniel Cheng . resolved

        This comment should be a few lines down.

        Camille Lamy

        Done

        Line 38, Patchset 30: : SecurityOrigin::Create(agent_cluster_key.GetURL());
        Daniel Cheng . unresolved

        Do we really need to keep the site URL around, if we end up turning it into an origin here?

        Camille Lamy

        We do need to distinguish between site keyed and origin keyed AgentClusterKeys as it has web visible implications. Technically, we could store a site key as an origin, but I think it makes AgentClusterKey less readable:

        • now key is a std::variant<scoped_refptr<const SecurityOrigin>, OriginKey, Empty, Deleted> where OriginKey corresponds to the origin-keyed situation while scoped_refptr<const SecurityOrigin> is in fact the site-keyed key.
        • this also mimics what we're doing in the browser process
        • we have to go reintroduce a more complex comparison operator in AgentClusterKey as scoped_refptr<const SecurityOrigin>::== does a pointer comparison, while we want a IsSameOriginWith comparison.

        So overall, I think it's better to keep the std::variant<KURL, OriginKey, Empty, Deleted>.

        Now if the question is whether we can create the universal file AgentClusterKey as origin-keyed, the answer is no as some tests expect it to be site keyed in this case.

        Line 39, Patchset 25: if (origin->IsLocal()) {
        Alex Moshchuk . unresolved

        Double-checking the file: URL flow: I'm not sure if I'm following this correctly, but the new code in DocumentLoader::InitializeWindow() seems to [create](https://chromium-review.googlesource.com/c/chromium/src/+/7041044/25/third_party/blink/renderer/core/loader/document_loader.cc#2650) a default blink::AgentClusterKey() for the origin->IsLocal case. IIRC, this default key is site-keyed with an empty URL. So how will we still end up with an origin for which IsLocal() is true here and use file_url_agent_?

        Alex Moshchuk

        Ping on this question, though I actually defer to Daniel for blink things :)

        Camille Lamy

        Right this was indeed an issue and we did not go into this code block. I now create a site-keyed AgentClusterKey in the file case using the file URL, so we do hit that. As explained in the comment below, the AgentCluster is created with the first file AgentClusterKey the WindowAgentFactory encounters. We do need a key with a file URL stored in the AgentCluster so that an about blank document inherits a key that will be recognized as local and put in the same AgentCluster. It does work since all file URLs get assigned to this special AgentCluster, but it also means that the URL we stored in the AgentClusterKey might not match that of later documents.

        Daniel Cheng

        ... yeah it's a bit weird but maybe it's "okay"? But see my question above; I'm wondering if we should be passing down site keys as a URL at all, or if it should just be an origin. If it was a file: origin, maybe that'd prevent the mismatch from happening at all?

        Camille Lamy

        I don't think this would solve the issue? Basically, the problem is that we require that when have two documents hosting two different file URLs they must use the same AgentCluster. But the two files could technically have different hosts, which would be reflected both in origin and URL. FWIW, I don't think it is an issue as the URL/Origin in AgentClusterKey is just here to select an AgentCluster, so if we need to special case this one case, this should be fine.

        Line 55, Patchset 30: // For all other cases, we rely on the provided AgentClusterKey.
        Daniel Cheng . resolved

        This comment seems out of place, since the extensions special case is right below it.

        Camille Lamy

        Done

        Line 57, Patchset 30: if (CommonSchemeRegistry::IsExtensionScheme(origin->Protocol().Ascii())) {
        Daniel Cheng . resolved

        Should we keep the comment for the extension case?

        Camille Lamy

        Done

        Open in Gerrit

        Related details

        Attention is currently required from:
        • Alex Moshchuk
        • Daniel Cheng
        Submit Requirements:
          • requirement satisfiedCode-Coverage
          • requirement is not satisfiedCode-Owners
          • requirement is not satisfiedCode-Review
          • requirement is not satisfiedNo-Unresolved-Comments
          • requirement is not satisfiedReview-Enforcement
          Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
          Gerrit-MessageType: comment
          Gerrit-Project: chromium/src
          Gerrit-Branch: main
          Gerrit-Change-Id: Ibb98071005816e53e766fbcbe3fbcb642ee17592
          Gerrit-Change-Number: 7041044
          Gerrit-PatchSet: 33
          Gerrit-Owner: Camille Lamy <cl...@chromium.org>
          Gerrit-Reviewer: Alex Moshchuk <ale...@chromium.org>
          Gerrit-Reviewer: Camille Lamy <cl...@chromium.org>
          Gerrit-Reviewer: Daniel Cheng <dch...@chromium.org>
          Gerrit-CC: AI Code Reviewer <peep-gen...@system.gserviceaccount.com>
          Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
          Gerrit-CC: Hiroki Nakagawa <nhi...@chromium.org>
          Gerrit-CC: Kentaro Hara <har...@chromium.org>
          Gerrit-CC: Nate Chapin <jap...@chromium.org>
          Gerrit-CC: Raphael Kubo da Costa <ku...@igalia.com>
          Gerrit-Attention: Alex Moshchuk <ale...@chromium.org>
          Gerrit-Attention: Daniel Cheng <dch...@chromium.org>
          Gerrit-Comment-Date: Fri, 09 Jan 2026 16:08:00 +0000
          satisfied_requirement
          unsatisfied_requirement
          open
          diffy

          Daniel Cheng (Gerrit)

          unread,
          Jan 12, 2026, 1:24:10 AM (5 days ago) Jan 12
          to Camille Lamy, Daniel Cheng, Alex Moshchuk, Code Review Nudger, AI Code Reviewer, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, ajwong...@chromium.org, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org
          Attention needed from Alex Moshchuk and Camille Lamy

          Daniel Cheng voted and added 5 comments

          Votes added by Daniel Cheng

          Code-Review+1

          5 comments

          Patchset-level comments
          Daniel Cheng . resolved

          LGTM w/nits

          (If we do anything about the comments that require bigger changes, I would prefer a followup so we can land this)

          File third_party/blink/renderer/core/execution_context/agent_cluster_key.h
          Line 181, Patchset 30: static AgentClusterKey EmptyValue() { return AgentClusterKey::CreateEmpty(); }
          Daniel Cheng . unresolved

          Nit: I think these can return const refs, since `AgentClusterKey` is somewhat large and not completely free to copy.

          Camille Lamy

          If I were to return const refs, I would need to define a static value whose reference I return, right? However, to do so I would generally use DEFINE_STATIC_LOCAL which does not work with factory methods like AgentClusterKey::CreateEmpty. I'd like to keep the factory methods, so not sure how to define the static variable in that case. Or am I missing something?

          Daniel Cheng

          It should be able to write something like:

          ```
          DEFINE_STATIC_LOCAL(
          AgentClusterKey, kEmpty, AgentClusterKey::CreateEmpty(PassKey()));

          ```

          Example: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/page/page.cc;l=177;drc=01f8a61320df2e79eaad27a372416dfbeea8533f

          File third_party/blink/renderer/core/execution_context/window_agent_factory.cc
          Line 38, Patchset 30: : SecurityOrigin::Create(agent_cluster_key.GetURL());
          Daniel Cheng . unresolved

          Do we really need to keep the site URL around, if we end up turning it into an origin here?

          Camille Lamy

          We do need to distinguish between site keyed and origin keyed AgentClusterKeys as it has web visible implications. Technically, we could store a site key as an origin, but I think it makes AgentClusterKey less readable:

          • now key is a std::variant<scoped_refptr<const SecurityOrigin>, OriginKey, Empty, Deleted> where OriginKey corresponds to the origin-keyed situation while scoped_refptr<const SecurityOrigin> is in fact the site-keyed key.
          • this also mimics what we're doing in the browser process
          • we have to go reintroduce a more complex comparison operator in AgentClusterKey as scoped_refptr<const SecurityOrigin>::== does a pointer comparison, while we want a IsSameOriginWith comparison.

          So overall, I think it's better to keep the std::variant<KURL, OriginKey, Empty, Deleted>.

          Now if the question is whether we can create the universal file AgentClusterKey as origin-keyed, the answer is no as some tests expect it to be site keyed in this case.

          Daniel Cheng

          I'm not going to push strongly about it in this CL, but I think we should consider if it makes sense to use an origin to represent the site URL.

          In a **site** URL, everything other than the scheme, host, and port are meaningless, right? But by allowing the caller to pass a URL, it implies that the path and other URL components might have a meaning (similar to a regular URL).

          We can reduce the confusion by using something like `StrongAlias` and then only using an aliased name for it.

          Line 39, Patchset 25: if (origin->IsLocal()) {
          Alex Moshchuk . unresolved

          Double-checking the file: URL flow: I'm not sure if I'm following this correctly, but the new code in DocumentLoader::InitializeWindow() seems to [create](https://chromium-review.googlesource.com/c/chromium/src/+/7041044/25/third_party/blink/renderer/core/loader/document_loader.cc#2650) a default blink::AgentClusterKey() for the origin->IsLocal case. IIRC, this default key is site-keyed with an empty URL. So how will we still end up with an origin for which IsLocal() is true here and use file_url_agent_?

          Alex Moshchuk

          Ping on this question, though I actually defer to Daniel for blink things :)

          Camille Lamy

          Right this was indeed an issue and we did not go into this code block. I now create a site-keyed AgentClusterKey in the file case using the file URL, so we do hit that. As explained in the comment below, the AgentCluster is created with the first file AgentClusterKey the WindowAgentFactory encounters. We do need a key with a file URL stored in the AgentCluster so that an about blank document inherits a key that will be recognized as local and put in the same AgentCluster. It does work since all file URLs get assigned to this special AgentCluster, but it also means that the URL we stored in the AgentClusterKey might not match that of later documents.

          Daniel Cheng

          ... yeah it's a bit weird but maybe it's "okay"? But see my question above; I'm wondering if we should be passing down site keys as a URL at all, or if it should just be an origin. If it was a file: origin, maybe that'd prevent the mismatch from happening at all?

          Camille Lamy

          I don't think this would solve the issue? Basically, the problem is that we require that when have two documents hosting two different file URLs they must use the same AgentCluster. But the two files could technically have different hosts, which would be reflected both in origin and URL. FWIW, I don't think it is an issue as the URL/Origin in AgentClusterKey is just here to select an AgentCluster, so if we need to special case this one case, this should be fine.

          Daniel Cheng

          I kind of wonder if that means AgentClusterKey should have a file-specific variant... since COI can't apply to the file agent cluster can it? And it's not a traditional site URL either, since we allow all files to share.

          (But in the interest of getting this landed, I think this should be a followup as well, if we decide it is actionable)

          File third_party/blink/renderer/core/exported/web_agent_cluster_key.cc
          Line 19, Patchset 33 (Latest):WebAgentClusterKey::WebAgentClusterKey(const AgentClusterKey& key) {
          key_ = std::visit(

          absl::Overload{
          [](const KURL& site_url) {
          return std::variant<WebOriginKeyedAgentClusterKey, WebURL>(
          site_url);
          },
          [](const AgentClusterKey::OriginKey& origin_key) {
          if (origin_key.isolation_key.has_value()) {
          return std::variant<WebOriginKeyedAgentClusterKey, WebURL>(
          WebOriginKeyedAgentClusterKey{
          .origin = origin_key.origin,
          .isolation_key = WebCrossOriginIsolationKey{
          .common_origin =
          origin_key.isolation_key->common_origin,
          .mode = origin_key.isolation_key->mode}});
          }
          return std::variant<WebOriginKeyedAgentClusterKey, WebURL>(
          WebOriginKeyedAgentClusterKey{
          .origin = origin_key.origin,

          });
          },
          [](const auto&) {
          NOTREACHED();
          return std::variant<WebOriginKeyedAgentClusterKey, WebURL>();
          },
          },
          key.key_);
          }
          Daniel Cheng . unresolved

          Nit: can we move this to the initializer list? Otherwise, it technically gets default-initialized to the first subvariant, before we then overwrite it. Sometimes the compiler can optimize it out, but not always.

          The other suggestion is to use an explicit return type to simplify the lambdas. By having an explicit return type, this simplifies the lambdas a bit: the second lambda doesn't need to repeat the variant name twice, and the third lambda doesn't need to have a `return` statement that isn't reachable.

          The two ways to do this are `decltype()` (which I've provided in the suggested edit) or providing a `private` alias for the variant type (maybe `KeyVariant`) and then using it below. `decltype()` is "clever"–possibly too clever. But I think it's acceptable.

          ```suggestion
          WebAgentClusterKey::WebAgentClusterKey(const AgentClusterKey& key)
          : key_(std::visit(
          absl::Overload{
          [](const KURL& site_url) -> decltype(key_) {
          return WebURL(site_url);
          },
          [](const AgentClusterKey::OriginKey& origin_key)
          -> decltype(key_) {
          if (origin_key.isolation_key.has_value()) {
          return WebOriginKeyedAgentClusterKey{
          .origin = origin_key.origin,
          .isolation_key = WebCrossOriginIsolationKey{
          .common_origin =
          origin_key.isolation_key->common_origin,
          .mode = origin_key.isolation_key->mode}});
          }
          return WebOriginKeyedAgentClusterKey{
          .origin = origin_key.origin});
          },
          [](const auto&) -> decltype(key_) {
          NOTREACHED();
          },
          },
          key.key_)) {
          }
          ```
          Open in Gerrit

          Related details

          Attention is currently required from:
          • Alex Moshchuk
          • Camille Lamy
          Submit Requirements:
          • requirement satisfiedCode-Coverage
          • requirement satisfiedCode-Owners
          • requirement satisfiedCode-Review
          • requirement is not satisfiedNo-Unresolved-Comments
          • requirement satisfiedReview-Enforcement
          Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
          Gerrit-MessageType: comment
          Gerrit-Project: chromium/src
          Gerrit-Branch: main
          Gerrit-Change-Id: Ibb98071005816e53e766fbcbe3fbcb642ee17592
          Gerrit-Change-Number: 7041044
          Gerrit-PatchSet: 33
          Gerrit-Owner: Camille Lamy <cl...@chromium.org>
          Gerrit-Reviewer: Alex Moshchuk <ale...@chromium.org>
          Gerrit-Reviewer: Camille Lamy <cl...@chromium.org>
          Gerrit-Reviewer: Daniel Cheng <dch...@chromium.org>
          Gerrit-CC: AI Code Reviewer <peep-gen...@system.gserviceaccount.com>
          Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
          Gerrit-CC: Hiroki Nakagawa <nhi...@chromium.org>
          Gerrit-CC: Kentaro Hara <har...@chromium.org>
          Gerrit-CC: Nate Chapin <jap...@chromium.org>
          Gerrit-CC: Raphael Kubo da Costa <ku...@igalia.com>
          Gerrit-Attention: Alex Moshchuk <ale...@chromium.org>
          Gerrit-Attention: Camille Lamy <cl...@chromium.org>
          Gerrit-Comment-Date: Mon, 12 Jan 2026 06:23:57 +0000
          Gerrit-HasComments: Yes
          Gerrit-Has-Labels: Yes
          satisfied_requirement
          unsatisfied_requirement
          open
          diffy

          Alex Moshchuk (Gerrit)

          unread,
          Jan 12, 2026, 9:11:24 PM (4 days ago) Jan 12
          to Camille Lamy, Daniel Cheng, Code Review Nudger, AI Code Reviewer, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, ajwong...@chromium.org, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org
          Attention needed from Camille Lamy

          Alex Moshchuk voted and added 1 comment

          Votes added by Alex Moshchuk

          Code-Review+1

          1 comment

          Patchset-level comments
          Alex Moshchuk . resolved

          content/ still LGTM, thanks!

          Open in Gerrit

          Related details

          Attention is currently required from:
          • Camille Lamy
          Gerrit-Attention: Camille Lamy <cl...@chromium.org>
          Gerrit-Comment-Date: Tue, 13 Jan 2026 02:11:11 +0000
          Gerrit-HasComments: Yes
          Gerrit-Has-Labels: Yes
          satisfied_requirement
          unsatisfied_requirement
          open
          diffy

          Camille Lamy (Gerrit)

          unread,
          10:37 AM (4 hours ago) 10:37 AM
          to Alex Moshchuk, Daniel Cheng, Code Review Nudger, AI Code Reviewer, AyeAye, Chromium LUCI CQ, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, ajwong...@chromium.org, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org

          Camille Lamy voted and added 6 comments

          Votes added by Camille Lamy

          Commit-Queue+2

          6 comments

          Patchset-level comments
          File-level comment, Patchset 34 (Latest):
          Camille Lamy . resolved

          Thanks for the review! As mentioned in the comments, I'll work on the remaining comments in a follow-up CL.

          File third_party/blink/public/mojom/frame/agent_cluster_key.mojom
          Line 22, Patchset 30: // The origin of the document which triggered cross-origin isolation. It
          // might be different from the origin associated with the AgentClusterKey
          // when cross-origin isolation is enabled by COOP + COEP. When cross-origin
          Daniel Cheng . resolved

          It might be nice to give a concrete example or link to an example of what this would look like in practice, or give some background about why it works this way.

          Camille Lamy

          I have added extra details.

          Camille Lamy

          Done

          File third_party/blink/renderer/core/execution_context/agent_cluster_key.h
          Line 181, Patchset 30: static AgentClusterKey EmptyValue() { return AgentClusterKey::CreateEmpty(); }
          Daniel Cheng . resolved

          Nit: I think these can return const refs, since `AgentClusterKey` is somewhat large and not completely free to copy.

          Camille Lamy

          If I were to return const refs, I would need to define a static value whose reference I return, right? However, to do so I would generally use DEFINE_STATIC_LOCAL which does not work with factory methods like AgentClusterKey::CreateEmpty. I'd like to keep the factory methods, so not sure how to define the static variable in that case. Or am I missing something?

          Daniel Cheng

          It should be able to write something like:

          ```
          DEFINE_STATIC_LOCAL(
          AgentClusterKey, kEmpty, AgentClusterKey::CreateEmpty(PassKey()));

          ```

          Example: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/page/page.cc;l=177;drc=01f8a61320df2e79eaad27a372416dfbeea8533f

          Camille Lamy
          Ah it compiles but only if you write
          ```
          DEFINE_STATIC_LOCAL(
          AgentClusterKey, kEmpty, (AgentClusterKey::CreateEmpty(PassKey())));
          ```
          With parenthesis around the factory method. Otherwise it doesn't. Changed to the const ref as requested.
          File third_party/blink/renderer/core/execution_context/window_agent_factory.cc
          Line 38, Patchset 30: : SecurityOrigin::Create(agent_cluster_key.GetURL());
          Daniel Cheng . resolved

          Do we really need to keep the site URL around, if we end up turning it into an origin here?

          Camille Lamy

          We do need to distinguish between site keyed and origin keyed AgentClusterKeys as it has web visible implications. Technically, we could store a site key as an origin, but I think it makes AgentClusterKey less readable:

          • now key is a std::variant<scoped_refptr<const SecurityOrigin>, OriginKey, Empty, Deleted> where OriginKey corresponds to the origin-keyed situation while scoped_refptr<const SecurityOrigin> is in fact the site-keyed key.
          • this also mimics what we're doing in the browser process
          • we have to go reintroduce a more complex comparison operator in AgentClusterKey as scoped_refptr<const SecurityOrigin>::== does a pointer comparison, while we want a IsSameOriginWith comparison.

          So overall, I think it's better to keep the std::variant<KURL, OriginKey, Empty, Deleted>.

          Now if the question is whether we can create the universal file AgentClusterKey as origin-keyed, the answer is no as some tests expect it to be site keyed in this case.

          Daniel Cheng

          I'm not going to push strongly about it in this CL, but I think we should consider if it makes sense to use an origin to represent the site URL.

          In a **site** URL, everything other than the scheme, host, and port are meaningless, right? But by allowing the caller to pass a URL, it implies that the path and other URL components might have a meaning (similar to a regular URL).

          We can reduce the confusion by using something like `StrongAlias` and then only using an aliased name for it.

          Camille Lamy

          I have filed crbug.com/476389699 to track that this should be improved in a follow-up CL.

          Line 39, Patchset 25: if (origin->IsLocal()) {
          Alex Moshchuk . resolved

          Double-checking the file: URL flow: I'm not sure if I'm following this correctly, but the new code in DocumentLoader::InitializeWindow() seems to [create](https://chromium-review.googlesource.com/c/chromium/src/+/7041044/25/third_party/blink/renderer/core/loader/document_loader.cc#2650) a default blink::AgentClusterKey() for the origin->IsLocal case. IIRC, this default key is site-keyed with an empty URL. So how will we still end up with an origin for which IsLocal() is true here and use file_url_agent_?

          Alex Moshchuk

          Ping on this question, though I actually defer to Daniel for blink things :)

          Camille Lamy

          Right this was indeed an issue and we did not go into this code block. I now create a site-keyed AgentClusterKey in the file case using the file URL, so we do hit that. As explained in the comment below, the AgentCluster is created with the first file AgentClusterKey the WindowAgentFactory encounters. We do need a key with a file URL stored in the AgentCluster so that an about blank document inherits a key that will be recognized as local and put in the same AgentCluster. It does work since all file URLs get assigned to this special AgentCluster, but it also means that the URL we stored in the AgentClusterKey might not match that of later documents.

          Daniel Cheng

          ... yeah it's a bit weird but maybe it's "okay"? But see my question above; I'm wondering if we should be passing down site keys as a URL at all, or if it should just be an origin. If it was a file: origin, maybe that'd prevent the mismatch from happening at all?

          Camille Lamy

          I don't think this would solve the issue? Basically, the problem is that we require that when have two documents hosting two different file URLs they must use the same AgentCluster. But the two files could technically have different hosts, which would be reflected both in origin and URL. FWIW, I don't think it is an issue as the URL/Origin in AgentClusterKey is just here to select an AgentCluster, so if we need to special case this one case, this should be fine.

          Daniel Cheng

          I kind of wonder if that means AgentClusterKey should have a file-specific variant... since COI can't apply to the file agent cluster can it? And it's not a traditional site URL either, since we allow all files to share.

          (But in the interest of getting this landed, I think this should be a followup as well, if we decide it is actionable)

          Camille Lamy

          I have filed crbug.com/476389699 to track that this should be improved in a follow-up CL.

          File third_party/blink/renderer/core/exported/web_agent_cluster_key.cc
          Line 19, Patchset 33:WebAgentClusterKey::WebAgentClusterKey(const AgentClusterKey& key) {
          Daniel Cheng . resolved
          Camille Lamy

          Done

          Open in Gerrit

          Related details

          Attention set is empty
          Submit Requirements:
            • requirement satisfiedCode-Coverage
            • requirement satisfiedCode-Owners
            • requirement satisfiedCode-Review
            • requirement satisfiedReview-Enforcement
            Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
            Gerrit-MessageType: comment
            Gerrit-Project: chromium/src
            Gerrit-Branch: main
            Gerrit-Change-Id: Ibb98071005816e53e766fbcbe3fbcb642ee17592
            Gerrit-Change-Number: 7041044
            Gerrit-PatchSet: 34
            Gerrit-Owner: Camille Lamy <cl...@chromium.org>
            Gerrit-Reviewer: Alex Moshchuk <ale...@chromium.org>
            Gerrit-Reviewer: Camille Lamy <cl...@chromium.org>
            Gerrit-Reviewer: Daniel Cheng <dch...@chromium.org>
            Gerrit-CC: AI Code Reviewer <peep-gen...@system.gserviceaccount.com>
            Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
            Gerrit-CC: Hiroki Nakagawa <nhi...@chromium.org>
            Gerrit-CC: Kentaro Hara <har...@chromium.org>
            Gerrit-CC: Nate Chapin <jap...@chromium.org>
            Gerrit-CC: Raphael Kubo da Costa <ku...@igalia.com>
            Gerrit-Comment-Date: Fri, 16 Jan 2026 15:37:02 +0000
            Gerrit-HasComments: Yes
            Gerrit-Has-Labels: Yes
            satisfied_requirement
            open
            diffy

            Chromium LUCI CQ (Gerrit)

            unread,
            11:27 AM (3 hours ago) 11:27 AM
            to Camille Lamy, Alex Moshchuk, Daniel Cheng, Code Review Nudger, AI Code Reviewer, AyeAye, chromium...@chromium.org, Kentaro Hara, Nate Chapin, Raphael Kubo da Costa, Hiroki Nakagawa, ajwong...@chromium.org, alexmo...@chromium.org, blink-re...@chromium.org, blink-revie...@chromium.org, blink-re...@chromium.org, blink-revi...@chromium.org, blink-...@chromium.org, blink-work...@chromium.org, creis...@chromium.org, gavinp...@chromium.org, horo+...@chromium.org, ipc-securi...@chromium.org, kinuko+ser...@chromium.org, kinuko...@chromium.org, loading...@chromium.org, navigation...@chromium.org, servicewor...@chromium.org, shimazu+se...@chromium.org

            Chromium LUCI CQ submitted the change with unreviewed changes

            Unreviewed changes

            33 is the latest approved patch-set.
            The change was submitted with unreviewed changes in the following files:

            ```
            The name of the file: third_party/blink/renderer/core/execution_context/agent_cluster_key.h
            Insertions: 8, Deletions: 4.

            @@ -182,11 +182,15 @@
            return StringHasher::HashMemory(base::as_byte_span(hash_codes));
            }

            - static AgentClusterKey EmptyValue() {
            - return AgentClusterKey::CreateEmpty(PassKey());
            + static AgentClusterKey& EmptyValue() {
            + DEFINE_STATIC_LOCAL(AgentClusterKey, kEmpty,
            + (AgentClusterKey::CreateEmpty(PassKey())));
            + return kEmpty;
            }
            - static AgentClusterKey DeletedValue() {
            - return AgentClusterKey::CreateDeleted(PassKey());
            + static AgentClusterKey& DeletedValue() {
            + DEFINE_STATIC_LOCAL(AgentClusterKey, kDeleted,
            + (AgentClusterKey::CreateDeleted(PassKey())));
            + return kDeleted;
            }
            };

            ```
            ```
            The name of the file: third_party/blink/renderer/core/exported/web_agent_cluster_key.cc
            Insertions: 17, Deletions: 23.

            @@ -16,35 +16,29 @@
            WebAgentClusterKey::WebAgentClusterKey(const WebOriginKeyedAgentClusterKey& key)
            : key_(key) {}

            -WebAgentClusterKey::WebAgentClusterKey(const AgentClusterKey& key) {
            - key_ = std::visit(
            - absl::Overload{
            - [](const KURL& site_url) {
            - return std::variant<WebOriginKeyedAgentClusterKey, WebURL>(
            - site_url);
            - },
            - [](const AgentClusterKey::OriginKey& origin_key) {
            - if (origin_key.isolation_key.has_value()) {
            - return std::variant<WebOriginKeyedAgentClusterKey, WebURL>(
            - WebOriginKeyedAgentClusterKey{
            +WebAgentClusterKey::WebAgentClusterKey(const AgentClusterKey& key)
            + : key_(std::visit(
            + absl::Overload{
            + [](const KURL& site_url) -> decltype(key_) {
            + return WebURL(site_url);
            + },
            + [](const AgentClusterKey::OriginKey& origin_key)
            + -> decltype(key_) {
            + if (origin_key.isolation_key.has_value()) {
            + return WebOriginKeyedAgentClusterKey{

            .origin = origin_key.origin,
            .isolation_key = WebCrossOriginIsolationKey{
            .common_origin =
            origin_key.isolation_key->common_origin,
            -                          .mode = origin_key.isolation_key->mode}});
            - }
            - return std::variant<WebOriginKeyedAgentClusterKey, WebURL>(
            - WebOriginKeyedAgentClusterKey{
            + .mode = origin_key.isolation_key->mode}};
            + }
            + return WebOriginKeyedAgentClusterKey{
            .origin = origin_key.origin,
            - });
            + };
            + },
            + [](const auto&) -> decltype(key_) { NOTREACHED(); },
            },
            - [](const auto&) {
            - NOTREACHED();
            - return std::variant<WebOriginKeyedAgentClusterKey, WebURL>();
            - },
            - },
            - key.key_);
            -}
            + key.key_)) {}

            WebAgentClusterKey::operator AgentClusterKey() const {
            return std::visit(
            ```

            Change information

            Commit message:
            Pass the AgentClusterKey from the browser process

            This CL refactors the tracking of origin-keyed agent clusters in Blink.
            Instead of passing booleans requiring origin-keyed agent clusters during
            the navigation commit, the browser will pass an AgentClusterKey (which
            may be site-keyed or origin-keyed). This AgentClusterKey will then be
            used as a key in the map of Agents in WindowAgentFactory, replacing the
            three separate maps of origin-keyed agents, opaque origin agents and
            site-keyed agents.

            This is mostly a refactoring CL which has no web-visible impact. However, it
            does introduce one change to the code, where AgentClusters for cross-origin
            isolated contexts are now marked as origin-keyed. Previously, they were marked
            as site keyed, though they were exposed as origin-keyed to JavaScript by
            overriding the origin-keyed status of the AgentCluster in cross-origin isolated
            context. document.domain was also already forbidden in cross-origin isolated
            context, so marking the AgentClusters as origin-keyed (which they are per spec)
            should not result in any web-visible behavior change and should make the code
            clearer.

            'NO_IFTTT=Initializing the LINT block'
            Bug: 342365078
            Change-Id: Ibb98071005816e53e766fbcbe3fbcb642ee17592
            Reviewed-by: Daniel Cheng <dch...@chromium.org>
            Reviewed-by: Alex Moshchuk <ale...@chromium.org>
            Commit-Queue: Camille Lamy <cl...@chromium.org>
            Cr-Commit-Position: refs/heads/main@{#1570405}
            Files:
            • M content/browser/BUILD.gn
            • M content/browser/agent_cluster_key.cc
            • M content/browser/agent_cluster_key.h
            • M content/browser/agent_cluster_key_unittest.cc
            • M content/browser/renderer_host/navigation_controller_impl.cc
            • M content/browser/renderer_host/navigation_entry_impl.cc
            • M content/browser/renderer_host/navigation_request.cc
            • M content/browser/renderer_host/navigation_request.h
            • M content/browser/renderer_host/render_process_host_impl.cc
            • D content/browser/security/coop/cross_origin_isolation_mode.h
            • M content/browser/site_info.cc
            • M content/browser/url_info.cc
            • M content/renderer/render_frame_impl.cc
            • M third_party/blink/common/navigation/navigation_params.cc
            • M third_party/blink/public/BUILD.gn
            • M third_party/blink/public/mojom/BUILD.gn
            • A third_party/blink/public/mojom/frame/agent_cluster_key.mojom
            • M third_party/blink/public/mojom/navigation/navigation_params.mojom
            • A third_party/blink/public/web/web_agent_cluster_key.h
            • M third_party/blink/public/web/web_navigation_params.h
            • M third_party/blink/renderer/bindings/core/v8/binding_security.cc
            • M third_party/blink/renderer/core/dom/document.cc
            • M third_party/blink/renderer/core/execution_context/agent.cc
            • M third_party/blink/renderer/core/execution_context/agent.h
            • A third_party/blink/renderer/core/execution_context/agent_cluster_key.cc
            • A third_party/blink/renderer/core/execution_context/agent_cluster_key.h
            • M third_party/blink/renderer/core/execution_context/build.gni
            • M third_party/blink/renderer/core/execution_context/window_agent.cc
            • M third_party/blink/renderer/core/execution_context/window_agent.h
            • M third_party/blink/renderer/core/execution_context/window_agent_factory.cc
            • M third_party/blink/renderer/core/execution_context/window_agent_factory.h
            • M third_party/blink/renderer/core/exported/build.gni
            • A third_party/blink/renderer/core/exported/web_agent_cluster_key.cc
            • M third_party/blink/renderer/core/frame/local_dom_window.cc
            • M third_party/blink/renderer/core/frame/web_local_frame_impl.cc
            • M third_party/blink/renderer/core/loader/document_loader.cc
            • M third_party/blink/renderer/core/loader/document_loader.h
            • M third_party/blink/tools/blinkpy/presubmit/audit_non_blink_usage.py
            Change size: XL
            Delta: 38 files changed, 799 insertions(+), 334 deletions(-)
            Branch: refs/heads/main
            Submit Requirements:
            • requirement satisfiedCode-Review: +1 by Daniel Cheng, +1 by Alex Moshchuk
            Open in Gerrit
            Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
            Gerrit-MessageType: merged
            Gerrit-Project: chromium/src
            Gerrit-Branch: main
            Gerrit-Change-Id: Ibb98071005816e53e766fbcbe3fbcb642ee17592
            Gerrit-Change-Number: 7041044
            Gerrit-PatchSet: 35
            Gerrit-Owner: Camille Lamy <cl...@chromium.org>
            Gerrit-Reviewer: Alex Moshchuk <ale...@chromium.org>
            Gerrit-Reviewer: Camille Lamy <cl...@chromium.org>
            Gerrit-Reviewer: Chromium LUCI CQ <chromiu...@luci-project-accounts.iam.gserviceaccount.com>
            Gerrit-Reviewer: Daniel Cheng <dch...@chromium.org>
            Gerrit-CC: AI Code Reviewer <peep-gen...@system.gserviceaccount.com>
            open
            diffy
            satisfied_requirement
            Reply all
            Reply to author
            Forward
            0 new messages