WebMCP: Queue declarative tool registration and schema calculation [chromium/src : main]

1 view
Skip to first unread message

Dominic Farolino (Gerrit)

unread,
May 7, 2026, 12:54:09 AMMay 7
to android-bu...@system.gserviceaccount.com, Chromium LUCI CQ, Mason Freed, chromium...@chromium.org, Khushal Sagar, devtools-re...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, mfoltz+wa...@chromium.org
Attention needed from Mason Freed

Dominic Farolino voted and added 1 comment

Votes added by Dominic Farolino

Commit-Queue+1

1 comment

Patchset-level comments
File-level comment, Patchset 12 (Latest):
Dominic Farolino . resolved

Found more things I could clean up. As a result of moving to a "queue a task to register/unregister declarative tool" model, I found I could remove all of the `toolchange` task queuing infra in model_context.cc, and move the input schema diffing from there, to the method in HTMLFormElement that performs tool registration.

Open in Gerrit

Related details

Attention is currently required from:
  • Mason Freed
Submit Requirements:
  • requirement satisfiedCode-Coverage
  • requirement 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: I1b933092c9e5e6c023c69172ad961161e647ae99
Gerrit-Change-Number: 7817087
Gerrit-PatchSet: 12
Gerrit-Owner: Dominic Farolino <d...@chromium.org>
Gerrit-Reviewer: Dominic Farolino <d...@chromium.org>
Gerrit-Reviewer: Mason Freed <mas...@chromium.org>
Gerrit-CC: Khushal Sagar <khusha...@chromium.org>
Gerrit-Attention: Mason Freed <mas...@chromium.org>
Gerrit-Comment-Date: Thu, 07 May 2026 04:54:03 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: Yes
satisfied_requirement
unsatisfied_requirement
open
diffy

Fr (Gerrit)

unread,
May 7, 2026, 2:46:25 AMMay 7
to Dominic Farolino, android-bu...@system.gserviceaccount.com, Chromium LUCI CQ, Mason Freed, chromium...@chromium.org, Khushal Sagar, devtools-re...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, mfoltz+wa...@chromium.org
Attention needed from Dominic Farolino and Mason Freed

Fr added 2 comments

File third_party/blink/renderer/core/script_tools/model_context.cc
Line 710, Patchset 13 (Latest): tool_data->RefreshDeclarativeInputSchema();
Fr . unresolved

Is this still needed?

File third_party/blink/web_tests/wpt_internal/webmcp/resources/webmcp-helpers.js
Line 7, Patchset 13 (Latest): navigator.modelContextTesting.ontoolchange = () => {
Fr . unresolved

Shall we use addEventListener instead there in case the test also uses navigator.modelContextTesting.ontoolchange which would be overridden IIUC?

Open in Gerrit

Related details

Attention is currently required from:
  • Dominic Farolino
  • Mason Freed
Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement 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: I1b933092c9e5e6c023c69172ad961161e647ae99
    Gerrit-Change-Number: 7817087
    Gerrit-PatchSet: 13
    Gerrit-Owner: Dominic Farolino <d...@chromium.org>
    Gerrit-Reviewer: Dominic Farolino <d...@chromium.org>
    Gerrit-Reviewer: Mason Freed <mas...@chromium.org>
    Gerrit-CC: Fr <beaufort...@gmail.com>
    Gerrit-Attention: Dominic Farolino <d...@chromium.org>
    Gerrit-Comment-Date: Thu, 07 May 2026 06:46:11 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Philip Pfaffe (Gerrit)

    unread,
    May 7, 2026, 2:54:13 AMMay 7
    to Dominic Farolino, Fr, android-bu...@system.gserviceaccount.com, Chromium LUCI CQ, Mason Freed, chromium...@chromium.org, Khushal Sagar, devtools-re...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, mfoltz+wa...@chromium.org
    Attention needed from Dominic Farolino and Mason Freed

    Philip Pfaffe added 1 comment

    Patchset-level comments
    File-level comment, Patchset 13 (Latest):
    Philip Pfaffe . resolved

    nice!

    Gerrit-CC: Philip Pfaffe <pfa...@chromium.org>
    Gerrit-Attention: Mason Freed <mas...@chromium.org>
    Gerrit-Attention: Dominic Farolino <d...@chromium.org>
    Gerrit-Comment-Date: Thu, 07 May 2026 06:53:53 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Dominic Farolino (Gerrit)

    unread,
    May 7, 2026, 11:16:15 AMMay 7
    to Philip Pfaffe, Fr, android-bu...@system.gserviceaccount.com, Chromium LUCI CQ, Mason Freed, chromium...@chromium.org, Khushal Sagar, devtools-re...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, mfoltz+wa...@chromium.org
    Attention needed from Fr and Mason Freed

    Dominic Farolino voted and added 2 comments

    Votes added by Dominic Farolino

    Commit-Queue+1

    2 comments

    File third_party/blink/renderer/core/script_tools/model_context.cc
    Line 710, Patchset 13: tool_data->RefreshDeclarativeInputSchema();
    Fr . resolved

    Is this still needed?

    Dominic Farolino

    I tried to remove it but some other listTools() tests still rely on it for some subtle reason, and since I'm not focusing on that API as much in this CL, my goal is remove this after without piling onto this CL.

    File third_party/blink/renderer/core/script_tools/model_context_test.cc
    Line 81, Patchset 14 (Latest): model_context_->NotifyToolChange();
    Dominic Farolino . unresolved

    OK this crap is ugly! But necessary to get these unit tests to work since there is no browser process to fire `NotifyToolChange()` in unit tests, so we have to "simulate" one here. It's just a hack to get around that until we move all of these unit tests over to WPTs, which I'll do later (I don't want to block merging this PR back to M149 on this).

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Fr
    • Mason Freed
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement 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: I1b933092c9e5e6c023c69172ad961161e647ae99
    Gerrit-Change-Number: 7817087
    Gerrit-PatchSet: 14
    Gerrit-Owner: Dominic Farolino <d...@chromium.org>
    Gerrit-Reviewer: Dominic Farolino <d...@chromium.org>
    Gerrit-Reviewer: Mason Freed <mas...@chromium.org>
    Gerrit-CC: Fr <beaufort...@gmail.com>
    Gerrit-CC: Khushal Sagar <khusha...@chromium.org>
    Gerrit-CC: Philip Pfaffe <pfa...@chromium.org>
    Gerrit-Attention: Fr <beaufort...@gmail.com>
    Gerrit-Attention: Mason Freed <mas...@chromium.org>
    Gerrit-Comment-Date: Thu, 07 May 2026 15:16:02 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: Yes
    Comment-In-Reply-To: Fr <beaufort...@gmail.com>
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Dominic Farolino (Gerrit)

    unread,
    May 7, 2026, 11:36:20 AMMay 7
    to Philip Pfaffe, Fr, android-bu...@system.gserviceaccount.com, Chromium LUCI CQ, Mason Freed, chromium...@chromium.org, Khushal Sagar, devtools-re...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, mfoltz+wa...@chromium.org
    Attention needed from Fr and Mason Freed

    Dominic Farolino voted and added 1 comment

    Votes added by Dominic Farolino

    Commit-Queue+1

    1 comment

    File third_party/blink/web_tests/wpt_internal/webmcp/resources/webmcp-helpers.js
    Line 7, Patchset 13: navigator.modelContextTesting.ontoolchange = () => {
    Fr . resolved

    Shall we use addEventListener instead there in case the test also uses navigator.modelContextTesting.ontoolchange which would be overridden IIUC?

    Dominic Farolino

    Sounds reasonable. Done.

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Fr
    • Mason Freed
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement 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: I1b933092c9e5e6c023c69172ad961161e647ae99
    Gerrit-Change-Number: 7817087
    Gerrit-PatchSet: 15
    Gerrit-Owner: Dominic Farolino <d...@chromium.org>
    Gerrit-Reviewer: Dominic Farolino <d...@chromium.org>
    Gerrit-Reviewer: Mason Freed <mas...@chromium.org>
    Gerrit-CC: Fr <beaufort...@gmail.com>
    Gerrit-CC: Khushal Sagar <khusha...@chromium.org>
    Gerrit-CC: Philip Pfaffe <pfa...@chromium.org>
    Gerrit-Attention: Fr <beaufort...@gmail.com>
    Gerrit-Attention: Mason Freed <mas...@chromium.org>
    Gerrit-Comment-Date: Thu, 07 May 2026 15:35:39 +0000
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Dominic Farolino (Gerrit)

    unread,
    May 7, 2026, 4:15:13 PMMay 7
    to Philip Pfaffe, Fr, android-bu...@system.gserviceaccount.com, Chromium LUCI CQ, Mason Freed, chromium...@chromium.org, Khushal Sagar, devtools-re...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, mfoltz+wa...@chromium.org
    Attention needed from Fr and Mason Freed

    Dominic Farolino voted Commit-Queue+1

    Commit-Queue+1
    Open in Gerrit

    Related details

    Attention is currently required from:
    • Fr
    • Mason Freed
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement 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: I1b933092c9e5e6c023c69172ad961161e647ae99
    Gerrit-Change-Number: 7817087
    Gerrit-PatchSet: 16
    Gerrit-Owner: Dominic Farolino <d...@chromium.org>
    Gerrit-Reviewer: Dominic Farolino <d...@chromium.org>
    Gerrit-Reviewer: Mason Freed <mas...@chromium.org>
    Gerrit-CC: Fr <beaufort...@gmail.com>
    Gerrit-CC: Khushal Sagar <khusha...@chromium.org>
    Gerrit-CC: Philip Pfaffe <pfa...@chromium.org>
    Gerrit-Attention: Fr <beaufort...@gmail.com>
    Gerrit-Attention: Mason Freed <mas...@chromium.org>
    Gerrit-Comment-Date: Thu, 07 May 2026 20:15:02 +0000
    Gerrit-HasComments: No
    Gerrit-Has-Labels: Yes
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Dominic Farolino (Gerrit)

    unread,
    May 8, 2026, 10:28:28 AMMay 8
    to Philip Pfaffe, Fr, android-bu...@system.gserviceaccount.com, Chromium LUCI CQ, Mason Freed, chromium...@chromium.org, Khushal Sagar, dominicc+...@chromium.org, devtools-re...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, mfoltz+wa...@chromium.org
    Attention needed from Fr and Mason Freed

    Dominic Farolino voted Commit-Queue+1

    Commit-Queue+1
    Open in Gerrit

    Related details

    Attention is currently required from:
    • Fr
    • Mason Freed
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement 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: I1b933092c9e5e6c023c69172ad961161e647ae99
    Gerrit-Change-Number: 7817087
    Gerrit-PatchSet: 20
    Gerrit-Owner: Dominic Farolino <d...@chromium.org>
    Gerrit-Reviewer: Dominic Farolino <d...@chromium.org>
    Gerrit-Reviewer: Mason Freed <mas...@chromium.org>
    Gerrit-CC: Fr <beaufort...@gmail.com>
    Gerrit-CC: Khushal Sagar <khusha...@chromium.org>
    Gerrit-CC: Philip Pfaffe <pfa...@chromium.org>
    Gerrit-Attention: Fr <beaufort...@gmail.com>
    Gerrit-Attention: Mason Freed <mas...@chromium.org>
    Gerrit-Comment-Date: Fri, 08 May 2026 14:28:23 +0000
    Gerrit-HasComments: No
    Gerrit-Has-Labels: Yes
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Mason Freed (Gerrit)

    unread,
    May 8, 2026, 1:40:09 PMMay 8
    to Dominic Farolino, Philip Pfaffe, Fr, android-bu...@system.gserviceaccount.com, Chromium LUCI CQ, chromium...@chromium.org, Khushal Sagar, dominicc+...@chromium.org, devtools-re...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, mfoltz+wa...@chromium.org
    Attention needed from Dominic Farolino and Fr

    Mason Freed added 12 comments

    Patchset-level comments
    File-level comment, Patchset 20 (Latest):
    Mason Freed . resolved

    I think this looks great. Lots of comments, but most are very small.

    Commit Message
    Line 73, Patchset 20 (Latest):to make them wait on `toolchange` being fired before accessing the tool.
    Mason Freed . resolved

    Kudos on the 75 line commit description. 😊

    File third_party/blink/renderer/core/html/forms/html_form_element.h
    Line 365, Patchset 20 (Latest): TaskHandle mcp_registration_task_handle_;
    Mason Freed . unresolved

    nit: maybe just `mcp_registration_task_`?

    Side note, I kind of hate that we mix and match "webmcp" and "mcp" everywhere. But let's not solve that now I guess.

    Line 362, Patchset 20 (Latest): //
    Mason Freed . unresolved

    nit: maybe remove the extra blank line

    Line 57, Patchset 20 (Latest): // regard to `this`, or when a control's attributes are changed. It will only
    // queue a task to register a new tool if `this` already has an existing
    Mason Freed . unresolved

    I wonder if it would be possible to CHECK that it's only called if `this` has a tool?

    File third_party/blink/renderer/core/html/forms/html_form_element.cc
    Line 398, Patchset 20 (Latest): if (!mcp_registration_task_handle_.IsActive()) {
    Mason Freed . unresolved

    This makes me wonder - should we re-schedule it instead of leaving it where it is in the task queue? I can't think of why, but perhaps it's better that you push it out each time we have a new update? (If you can't think of a good reason either, then this is ok as-is.)

    Line 1126, Patchset 20 (Latest): if (name == html_names::kToolnameAttr ||
    name == html_names::kTooldescriptionAttr) {
    if (params.old_value != params.new_value) {
    ScheduleDeclarativeWebMCPToolRegistration();
    }
    }
    Mason Freed . unresolved

    nit:

    ```
    if ((name == html_names::kToolnameAttr ||
    name == html_names::kTooldescriptionAttr) &&
    (params.old_value != params.new_value)) {
    ScheduleDeclarativeWebMCPToolRegistration();
    }
    ```
    Line 1694, Patchset 20 (Latest):void HTMLFormElement::ScheduleWebMCPSchemaUpdate() {
    if (!RuntimeEnabledFeatures::WebMCPEnabled(GetExecutionContext())) {
    return;
    }
    if (!IsValidWebMCPForm()) {
    return;
    }
    ScheduleDeclarativeWebMCPToolRegistration();
    }
    Mason Freed . unresolved

    This is a pretty thin wrapper - perhaps we just remove it and update the few remaining callers to call `ScheduleDeclarativeWebMCPToolRegistration` directly?

    File third_party/blink/renderer/core/script_tools/model_context_test.cc
    Line 81, Patchset 14: model_context_->NotifyToolChange();
    Dominic Farolino . unresolved

    OK this crap is ugly! But necessary to get these unit tests to work since there is no browser process to fire `NotifyToolChange()` in unit tests, so we have to "simulate" one here. It's just a hack to get around that until we move all of these unit tests over to WPTs, which I'll do later (I don't want to block merging this PR back to M149 on this).

    Mason Freed

    Ack. 😊

    File third_party/blink/web_tests/external/wpt/webmcp/declarative/toolchange-on-control-add-remove.https.html
    Line 14, Patchset 20 (Latest): async function waitForFormToolSchemaToMatch(expected_schema) {
    Mason Freed . unresolved

    Maybe move this/these to the utility `.js` files?

    File third_party/blink/web_tests/fast/webmcp/usecounter.html
    Line 42, Patchset 20 (Latest): navigator.modelContextTesting.ontoolchange = check;
    Mason Freed . unresolved

    How come we can't switch these tests to `modelContext` and just use `waitForTool()`?

    File third_party/blink/web_tests/wpt_internal/webmcp/select-multiple-events.https.html
    Line 27, Patchset 20 (Latest):
    Mason Freed . unresolved

    nit: extra blank lines. I'd get rid of both of them. This comment applies to most tests above.

    Also, why not move `assert_true(!!navigator.modelContext);` into `waitForTool()`? Then these are all just one line additions.

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Dominic Farolino
    • Fr
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement 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: I1b933092c9e5e6c023c69172ad961161e647ae99
    Gerrit-Change-Number: 7817087
    Gerrit-PatchSet: 20
    Gerrit-Owner: Dominic Farolino <d...@chromium.org>
    Gerrit-Reviewer: Dominic Farolino <d...@chromium.org>
    Gerrit-Reviewer: Mason Freed <mas...@chromium.org>
    Gerrit-CC: Fr <beaufort...@gmail.com>
    Gerrit-CC: Khushal Sagar <khusha...@chromium.org>
    Gerrit-CC: Philip Pfaffe <pfa...@chromium.org>
    Gerrit-Attention: Fr <beaufort...@gmail.com>
    Gerrit-Attention: Dominic Farolino <d...@chromium.org>
    Gerrit-Comment-Date: Fri, 08 May 2026 17:39:59 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Dominic Farolino <d...@chromium.org>
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Dominic Farolino (Gerrit)

    unread,
    May 8, 2026, 4:01:10 PMMay 8
    to Philip Pfaffe, Fr, android-bu...@system.gserviceaccount.com, Chromium LUCI CQ, Mason Freed, chromium...@chromium.org, Khushal Sagar, dominicc+...@chromium.org, devtools-re...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, mfoltz+wa...@chromium.org
    Attention needed from Fr and Mason Freed

    Dominic Farolino voted and added 10 comments

    Votes added by Dominic Farolino

    Commit-Queue+1

    10 comments

    File third_party/blink/renderer/core/html/forms/html_form_element.h
    Line 365, Patchset 20: TaskHandle mcp_registration_task_handle_;
    Mason Freed . resolved

    nit: maybe just `mcp_registration_task_`?

    Side note, I kind of hate that we mix and match "webmcp" and "mcp" everywhere. But let's not solve that now I guess.

    Dominic Farolino

    Agreed. I have a personal goal to make everything consistently named in the future.

    Line 362, Patchset 20: //
    Mason Freed . resolved

    nit: maybe remove the extra blank line

    Dominic Farolino

    Done, but I also just removed the last two text lines here anyways, since I think they were superfluous.

    Line 57, Patchset 20: // regard to `this`, or when a control's attributes are changed. It will only

    // queue a task to register a new tool if `this` already has an existing
    Mason Freed . unresolved

    I wonder if it would be possible to CHECK that it's only called if `this` has a tool?

    Dominic Farolino

    In the current state, no. That's what [this check protects against](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/html/forms/html_form_element.cc;l=1632-1634;drc=c065efc537674efbf5ed6292606039bcc6a22f6d). A form control can become associated with a form that doesn't have `toolname`/`tooldescription` attributes, and therefore impact the form's input schema, since there is no tool. Does that make sense?

    File third_party/blink/renderer/core/html/forms/html_form_element.cc
    Line 398, Patchset 20: if (!mcp_registration_task_handle_.IsActive()) {
    Mason Freed . resolved

    This makes me wonder - should we re-schedule it instead of leaving it where it is in the task queue? I can't think of why, but perhaps it's better that you push it out each time we have a new update? (If you can't think of a good reason either, then this is ok as-is.)

    Dominic Farolino
    I can't think of a good reason either where it would *actually* matter, and while I kind of like the intuition of "pushing [the task] out" each time, I implemented and it looked a little weird:
    - Either we pull the `.Cancel()` out unconditionally above the `if (!is_valid_mcp_form)` block, or;
    - We duplicate it by keeping it right where it is in there, and ALSO adding it on the line that you made this comment, just before we re-queue.

    I have thoughts on how to simplify and restructure this whole method, so I'll save those for another CL I think, and continue with the current not-pushing-the-task-out approach we have here. Thanks for the comment.

    Line 1126, Patchset 20: if (name == html_names::kToolnameAttr ||

    name == html_names::kTooldescriptionAttr) {
    if (params.old_value != params.new_value) {
    ScheduleDeclarativeWebMCPToolRegistration();
    }
    }
    Mason Freed . resolved

    nit:

    ```
    if ((name == html_names::kToolnameAttr ||
    name == html_names::kTooldescriptionAttr) &&
    (params.old_value != params.new_value)) {
    ScheduleDeclarativeWebMCPToolRegistration();
    }
    ```
    Dominic Farolino

    Done

    Line 1694, Patchset 20:void HTMLFormElement::ScheduleWebMCPSchemaUpdate() {

    if (!RuntimeEnabledFeatures::WebMCPEnabled(GetExecutionContext())) {
    return;
    }
    if (!IsValidWebMCPForm()) {
    return;
    }
    ScheduleDeclarativeWebMCPToolRegistration();
    }
    Mason Freed . unresolved

    This is a pretty thin wrapper - perhaps we just remove it and update the few remaining callers to call `ScheduleDeclarativeWebMCPToolRegistration` directly?

    Dominic Farolino

    Hmm, it is a pretty thing wrapper. However, it does do less work, than `ScheduleDeclarativeWebMCPToolRegistration()`, which is why I assume it exists. For associating of every single for control element, regardless of WebMCP usage, this method runs, so it's best to have it stop after a simple pointer-is-null check (which is what `if (!IsValidWebMCPForm()) {` does), rather than entering `ScheduleDeclarativeWebMCPToolRegistration()` and grabbing attributes and running `isConnected()` all to do nothing in 99.9% of forms, where `is_valid_mcp_tool` is null.

    But maybe the performance implications of entering that method aren't actually bad (the attribute getter does have "fast" in the name). What do you think? Basically I think this indirection exists for performance reasons, but I'm not sure how serious it is.

    File third_party/blink/renderer/core/script_tools/model_context_test.cc
    Line 81, Patchset 14: model_context_->NotifyToolChange();
    Dominic Farolino . resolved

    OK this crap is ugly! But necessary to get these unit tests to work since there is no browser process to fire `NotifyToolChange()` in unit tests, so we have to "simulate" one here. It's just a hack to get around that until we move all of these unit tests over to WPTs, which I'll do later (I don't want to block merging this PR back to M149 on this).

    Mason Freed

    Ack. 😊

    Dominic Farolino

    Done

    File third_party/blink/web_tests/external/wpt/webmcp/declarative/toolchange-on-control-add-remove.https.html
    Line 14, Patchset 20: async function waitForFormToolSchemaToMatch(expected_schema) {
    Mason Freed . resolved

    Maybe move this/these to the utility `.js` files?

    Dominic Farolino

    Created a new `helpers.js` file in `external/wpt/webmcp/resources`, and referenced it from this file. But I think the wpt_internal/ and other tests cannot reference this file, so this is the only test that uses the helper. But once we remove the `modelContextTesting` API and move all the tests here, then others will be able to make use of it.

    File third_party/blink/web_tests/fast/webmcp/usecounter.html
    Line 42, Patchset 20: navigator.modelContextTesting.ontoolchange = check;
    Mason Freed . resolved

    How come we can't switch these tests to `modelContext` and just use `waitForTool()`?

    Dominic Farolino

    The only reason is because `modelContext` is gated on secure context, and this file is not HTTPs. But yeah we can rename it and use the new API accordingly. Done.

    File third_party/blink/web_tests/wpt_internal/webmcp/select-multiple-events.https.html
    Line 27, Patchset 20:
    Mason Freed . resolved

    nit: extra blank lines. I'd get rid of both of them. This comment applies to most tests above.

    Also, why not move `assert_true(!!navigator.modelContext);` into `waitForTool()`? Then these are all just one line additions.

    Dominic Farolino

    Done, and I made it:

    ```
    assert_implements(navigator.modelContextTesting, "modelContext is available");
    ```

    which I think is slightly better.

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Fr
    • Mason Freed
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement 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: I1b933092c9e5e6c023c69172ad961161e647ae99
    Gerrit-Change-Number: 7817087
    Gerrit-PatchSet: 21
    Gerrit-Owner: Dominic Farolino <d...@chromium.org>
    Gerrit-Reviewer: Dominic Farolino <d...@chromium.org>
    Gerrit-Reviewer: Mason Freed <mas...@chromium.org>
    Gerrit-CC: Fr <beaufort...@gmail.com>
    Gerrit-CC: Khushal Sagar <khusha...@chromium.org>
    Gerrit-CC: Philip Pfaffe <pfa...@chromium.org>
    Gerrit-Attention: Mason Freed <mas...@chromium.org>
    Gerrit-Attention: Fr <beaufort...@gmail.com>
    Gerrit-Comment-Date: Fri, 08 May 2026 20:01:04 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: Yes
    Comment-In-Reply-To: Mason Freed <mas...@chromium.org>
    Comment-In-Reply-To: Dominic Farolino <d...@chromium.org>
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Mason Freed (Gerrit)

    unread,
    May 11, 2026, 3:15:44 PMMay 11
    to Dominic Farolino, Philip Pfaffe, Fr, android-bu...@system.gserviceaccount.com, Chromium LUCI CQ, chromium...@chromium.org, Khushal Sagar, dominicc+...@chromium.org, devtools-re...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, mfoltz+wa...@chromium.org
    Attention needed from Dominic Farolino and Fr

    Mason Freed voted and added 6 comments

    Votes added by Mason Freed

    Code-Review+1

    6 comments

    Patchset-level comments
    File third_party/blink/renderer/core/html/forms/html_form_element.h
    Line 57, Patchset 20: // regard to `this`, or when a control's attributes are changed. It will only
    // queue a task to register a new tool if `this` already has an existing
    Mason Freed . resolved

    I wonder if it would be possible to CHECK that it's only called if `this` has a tool?

    Dominic Farolino

    In the current state, no. That's what [this check protects against](https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/html/forms/html_form_element.cc;l=1632-1634;drc=c065efc537674efbf5ed6292606039bcc6a22f6d). A form control can become associated with a form that doesn't have `toolname`/`tooldescription` attributes, and therefore impact the form's input schema, since there is no tool. Does that make sense?

    Mason Freed

    Yep, makes sense. Thanks.

    File third_party/blink/renderer/core/html/forms/html_form_element.cc
    Line 398, Patchset 20: if (!mcp_registration_task_handle_.IsActive()) {
    Mason Freed . resolved

    This makes me wonder - should we re-schedule it instead of leaving it where it is in the task queue? I can't think of why, but perhaps it's better that you push it out each time we have a new update? (If you can't think of a good reason either, then this is ok as-is.)

    Dominic Farolino
    I can't think of a good reason either where it would *actually* matter, and while I kind of like the intuition of "pushing [the task] out" each time, I implemented and it looked a little weird:
    - Either we pull the `.Cancel()` out unconditionally above the `if (!is_valid_mcp_form)` block, or;
    - We duplicate it by keeping it right where it is in there, and ALSO adding it on the line that you made this comment, just before we re-queue.

    I have thoughts on how to simplify and restructure this whole method, so I'll save those for another CL I think, and continue with the current not-pushing-the-task-out approach we have here. Thanks for the comment.

    Mason Freed

    Ok, this is good as-is. Thanks for thinking about it.

    Line 1694, Patchset 20:void HTMLFormElement::ScheduleWebMCPSchemaUpdate() {
    if (!RuntimeEnabledFeatures::WebMCPEnabled(GetExecutionContext())) {
    return;
    }
    if (!IsValidWebMCPForm()) {
    return;
    }
    ScheduleDeclarativeWebMCPToolRegistration();
    }
    Mason Freed . unresolved

    This is a pretty thin wrapper - perhaps we just remove it and update the few remaining callers to call `ScheduleDeclarativeWebMCPToolRegistration` directly?

    Dominic Farolino

    Hmm, it is a pretty thing wrapper. However, it does do less work, than `ScheduleDeclarativeWebMCPToolRegistration()`, which is why I assume it exists. For associating of every single for control element, regardless of WebMCP usage, this method runs, so it's best to have it stop after a simple pointer-is-null check (which is what `if (!IsValidWebMCPForm()) {` does), rather than entering `ScheduleDeclarativeWebMCPToolRegistration()` and grabbing attributes and running `isConnected()` all to do nothing in 99.9% of forms, where `is_valid_mcp_tool` is null.

    But maybe the performance implications of entering that method aren't actually bad (the attribute getter does have "fast" in the name). What do you think? Basically I think this indirection exists for performance reasons, but I'm not sure how serious it is.

    Mason Freed

    Right, I guess I was assuming you'd change the existing (4?) callers of ScheduleWebMCPSchemaUpdate() to something like

    ```
    if (RuntimeEnabledFeatures::WebMCPEnabled(GetExecutionContext()) &&
    IsValidWebMCPForm() {
    ScheduleDeclarativeWebMCPToolRegistration();
    }
    ```

    The feature check is already present in a few cases. Perhaps that's too verbose. I guess at minimum, if you want to leave this, rename it to something like `ScheduleDeclarativeWebMCPToolRegistrationIfActive()` or something? Otherwise, it's a bit confusing to figure out which of the "Schedule*" functions to call at a given location.

    File third_party/blink/web_tests/external/wpt/webmcp/declarative/toolchange-on-control-add-remove.https.html
    Line 14, Patchset 20: async function waitForFormToolSchemaToMatch(expected_schema) {
    Mason Freed . resolved

    Maybe move this/these to the utility `.js` files?

    Dominic Farolino

    Created a new `helpers.js` file in `external/wpt/webmcp/resources`, and referenced it from this file. But I think the wpt_internal/ and other tests cannot reference this file, so this is the only test that uses the helper. But once we remove the `modelContextTesting` API and move all the tests here, then others will be able to make use of it.

    Mason Freed

    Lovely

    File third_party/blink/web_tests/fast/webmcp/usecounter.html
    Line 42, Patchset 20: navigator.modelContextTesting.ontoolchange = check;
    Mason Freed . resolved

    How come we can't switch these tests to `modelContext` and just use `waitForTool()`?

    Dominic Farolino

    The only reason is because `modelContext` is gated on secure context, and this file is not HTTPs. But yeah we can rename it and use the new API accordingly. Done.

    Mason Freed

    Nice, thanks. I didn't realize WebMCP required secure context! TIL.

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Dominic Farolino
    • Fr
    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: I1b933092c9e5e6c023c69172ad961161e647ae99
      Gerrit-Change-Number: 7817087
      Gerrit-PatchSet: 21
      Gerrit-Owner: Dominic Farolino <d...@chromium.org>
      Gerrit-Reviewer: Dominic Farolino <d...@chromium.org>
      Gerrit-Reviewer: Mason Freed <mas...@chromium.org>
      Gerrit-CC: Fr <beaufort...@gmail.com>
      Gerrit-CC: Khushal Sagar <khusha...@chromium.org>
      Gerrit-CC: Philip Pfaffe <pfa...@chromium.org>
      Gerrit-Attention: Fr <beaufort...@gmail.com>
      Gerrit-Attention: Dominic Farolino <d...@chromium.org>
      Gerrit-Comment-Date: Mon, 11 May 2026 19:15:32 +0000
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy

      Fr (Gerrit)

      unread,
      May 12, 2026, 2:43:32 AMMay 12
      to Dominic Farolino, Mason Freed, Philip Pfaffe, android-bu...@system.gserviceaccount.com, Chromium LUCI CQ, chromium...@chromium.org, Khushal Sagar, dominicc+...@chromium.org, devtools-re...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, mfoltz+wa...@chromium.org
      Attention needed from Dominic Farolino

      Fr added 1 comment

      File third_party/blink/web_tests/fast/webmcp/usecounter.html
      Line 42, Patchset 20: navigator.modelContextTesting.ontoolchange = check;
      Mason Freed . resolved

      How come we can't switch these tests to `modelContext` and just use `waitForTool()`?

      Dominic Farolino

      The only reason is because `modelContext` is gated on secure context, and this file is not HTTPs. But yeah we can rename it and use the new API accordingly. Done.

      Mason Freed

      Nice, thanks. I didn't realize WebMCP required secure context! TIL.

      Fr

      FWIW, I've filed https://b.corp.google.com/issues/503588985 last month when I've noticed this.

      Open in Gerrit

      Related details

      Attention is currently required from:
      • Dominic Farolino
      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: I1b933092c9e5e6c023c69172ad961161e647ae99
      Gerrit-Change-Number: 7817087
      Gerrit-PatchSet: 21
      Gerrit-Owner: Dominic Farolino <d...@chromium.org>
      Gerrit-Reviewer: Dominic Farolino <d...@chromium.org>
      Gerrit-Reviewer: Mason Freed <mas...@chromium.org>
      Gerrit-CC: Fr <beaufort...@gmail.com>
      Gerrit-CC: Khushal Sagar <khusha...@chromium.org>
      Gerrit-CC: Philip Pfaffe <pfa...@chromium.org>
      Gerrit-Attention: Dominic Farolino <d...@chromium.org>
      Gerrit-Comment-Date: Tue, 12 May 2026 06:43:15 +0000
      Gerrit-HasComments: Yes
      Gerrit-Has-Labels: No
      satisfied_requirement
      unsatisfied_requirement
      open
      diffy

      Dominic Farolino (Gerrit)

      unread,
      May 14, 2026, 12:49:02 PMMay 14
      to Mason Freed, Philip Pfaffe, Fr, android-bu...@system.gserviceaccount.com, Chromium LUCI CQ, chromium...@chromium.org, Khushal Sagar, dominicc+...@chromium.org, devtools-re...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, mfoltz+wa...@chromium.org

      Dominic Farolino voted and added 1 comment

      Votes added by Dominic Farolino

      Commit-Queue+2

      1 comment

      File third_party/blink/renderer/core/html/forms/html_form_element.cc
      Line 1694, Patchset 20:void HTMLFormElement::ScheduleWebMCPSchemaUpdate() {
      if (!RuntimeEnabledFeatures::WebMCPEnabled(GetExecutionContext())) {
      return;
      }
      if (!IsValidWebMCPForm()) {
      return;
      }
      ScheduleDeclarativeWebMCPToolRegistration();
      }
      Mason Freed . resolved

      This is a pretty thin wrapper - perhaps we just remove it and update the few remaining callers to call `ScheduleDeclarativeWebMCPToolRegistration` directly?

      Dominic Farolino

      Hmm, it is a pretty thing wrapper. However, it does do less work, than `ScheduleDeclarativeWebMCPToolRegistration()`, which is why I assume it exists. For associating of every single for control element, regardless of WebMCP usage, this method runs, so it's best to have it stop after a simple pointer-is-null check (which is what `if (!IsValidWebMCPForm()) {` does), rather than entering `ScheduleDeclarativeWebMCPToolRegistration()` and grabbing attributes and running `isConnected()` all to do nothing in 99.9% of forms, where `is_valid_mcp_tool` is null.

      But maybe the performance implications of entering that method aren't actually bad (the attribute getter does have "fast" in the name). What do you think? Basically I think this indirection exists for performance reasons, but I'm not sure how serious it is.

      Mason Freed

      Right, I guess I was assuming you'd change the existing (4?) callers of ScheduleWebMCPSchemaUpdate() to something like

      ```
      if (RuntimeEnabledFeatures::WebMCPEnabled(GetExecutionContext()) &&
      IsValidWebMCPForm() {
      ScheduleDeclarativeWebMCPToolRegistration();
      }
      ```

      The feature check is already present in a few cases. Perhaps that's too verbose. I guess at minimum, if you want to leave this, rename it to something like `ScheduleDeclarativeWebMCPToolRegistrationIfActive()` or something? Otherwise, it's a bit confusing to figure out which of the "Schedule*" functions to call at a given location.

      Dominic Farolino

      Got it. Allowing `HTMLFormControlElement` to call `IsValidWebMCPForm()` is a little more invasive since we'd have to make that method public, so I slightly prefer renaming this. However, doing that here will wipe the LGTM and I'd like to land this and merge it back this week, so let me take care of that in a follow-up if that's alright. I'll put this on my TODO list.

      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: I1b933092c9e5e6c023c69172ad961161e647ae99
        Gerrit-Change-Number: 7817087
        Gerrit-PatchSet: 21
        Gerrit-Owner: Dominic Farolino <d...@chromium.org>
        Gerrit-Reviewer: Dominic Farolino <d...@chromium.org>
        Gerrit-Reviewer: Mason Freed <mas...@chromium.org>
        Gerrit-CC: Fr <beaufort...@gmail.com>
        Gerrit-CC: Khushal Sagar <khusha...@chromium.org>
        Gerrit-CC: Philip Pfaffe <pfa...@chromium.org>
        Gerrit-Comment-Date: Thu, 14 May 2026 16:48:47 +0000
        Gerrit-HasComments: Yes
        Gerrit-Has-Labels: Yes
        satisfied_requirement
        open
        diffy

        Blink W3C Test Autoroller (Gerrit)

        unread,
        May 14, 2026, 1:14:08 PMMay 14
        to Dominic Farolino, Mason Freed, Philip Pfaffe, Fr, android-bu...@system.gserviceaccount.com, Chromium LUCI CQ, chromium...@chromium.org, Khushal Sagar, dominicc+...@chromium.org, devtools-re...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, mfoltz+wa...@chromium.org

        Message from Blink W3C Test Autoroller

        Exportable changes to web-platform-tests were detected in this CL and a pull request in the upstream repo has been made: https://github.com/web-platform-tests/wpt/pull/59889.

        When this CL lands, the bot will automatically merge the PR on GitHub if the required GitHub checks pass; otherwise, ecosystem-infra@ team will triage the failures and may contact you.

        WPT Export docs:
        https://chromium.googlesource.com/chromium/src/+/main/docs/testing/web_platform_tests.md#Automatic-export-process

        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: I1b933092c9e5e6c023c69172ad961161e647ae99
        Gerrit-Change-Number: 7817087
        Gerrit-PatchSet: 21
        Gerrit-Owner: Dominic Farolino <d...@chromium.org>
        Gerrit-Reviewer: Dominic Farolino <d...@chromium.org>
        Gerrit-Reviewer: Mason Freed <mas...@chromium.org>
        Gerrit-CC: Blink W3C Test Autoroller <blink-w3c-te...@chromium.org>
        Gerrit-Comment-Date: Thu, 14 May 2026 17:13:58 +0000
        Gerrit-HasComments: No
        Gerrit-Has-Labels: No
        satisfied_requirement
        open
        diffy

        Dominic Farolino (Gerrit)

        unread,
        May 14, 2026, 4:21:14 PMMay 14
        to Blink W3C Test Autoroller, Mason Freed, Philip Pfaffe, Fr, android-bu...@system.gserviceaccount.com, Chromium LUCI CQ, chromium...@chromium.org, Khushal Sagar, dominicc+...@chromium.org, devtools-re...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, mfoltz+wa...@chromium.org

        Dominic Farolino voted Commit-Queue+2

        Commit-Queue+2
        Gerrit-Comment-Date: Thu, 14 May 2026 20:21:02 +0000
        Gerrit-HasComments: No
        Gerrit-Has-Labels: Yes
        satisfied_requirement
        open
        diffy

        Mason Freed (Gerrit)

        unread,
        May 14, 2026, 4:31:51 PMMay 14
        to Dominic Farolino, Blink W3C Test Autoroller, Philip Pfaffe, Fr, android-bu...@system.gserviceaccount.com, Chromium LUCI CQ, chromium...@chromium.org, Khushal Sagar, dominicc+...@chromium.org, devtools-re...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, mfoltz+wa...@chromium.org
        Attention needed from Dominic Farolino

        Mason Freed added 1 comment

        File third_party/blink/renderer/core/html/forms/html_form_element.cc
        Line 1694, Patchset 20:void HTMLFormElement::ScheduleWebMCPSchemaUpdate() {
        if (!RuntimeEnabledFeatures::WebMCPEnabled(GetExecutionContext())) {
        return;
        }
        if (!IsValidWebMCPForm()) {
        return;
        }
        ScheduleDeclarativeWebMCPToolRegistration();
        }
        Mason Freed . resolved

        This is a pretty thin wrapper - perhaps we just remove it and update the few remaining callers to call `ScheduleDeclarativeWebMCPToolRegistration` directly?

        Dominic Farolino

        Hmm, it is a pretty thing wrapper. However, it does do less work, than `ScheduleDeclarativeWebMCPToolRegistration()`, which is why I assume it exists. For associating of every single for control element, regardless of WebMCP usage, this method runs, so it's best to have it stop after a simple pointer-is-null check (which is what `if (!IsValidWebMCPForm()) {` does), rather than entering `ScheduleDeclarativeWebMCPToolRegistration()` and grabbing attributes and running `isConnected()` all to do nothing in 99.9% of forms, where `is_valid_mcp_tool` is null.

        But maybe the performance implications of entering that method aren't actually bad (the attribute getter does have "fast" in the name). What do you think? Basically I think this indirection exists for performance reasons, but I'm not sure how serious it is.

        Mason Freed

        Right, I guess I was assuming you'd change the existing (4?) callers of ScheduleWebMCPSchemaUpdate() to something like

        ```
        if (RuntimeEnabledFeatures::WebMCPEnabled(GetExecutionContext()) &&
        IsValidWebMCPForm() {
        ScheduleDeclarativeWebMCPToolRegistration();
        }
        ```

        The feature check is already present in a few cases. Perhaps that's too verbose. I guess at minimum, if you want to leave this, rename it to something like `ScheduleDeclarativeWebMCPToolRegistrationIfActive()` or something? Otherwise, it's a bit confusing to figure out which of the "Schedule*" functions to call at a given location.

        Dominic Farolino

        Got it. Allowing `HTMLFormControlElement` to call `IsValidWebMCPForm()` is a little more invasive since we'd have to make that method public, so I slightly prefer renaming this. However, doing that here will wipe the LGTM and I'd like to land this and merge it back this week, so let me take care of that in a follow-up if that's alright. I'll put this on my TODO list.

        Mason Freed

        Yep, fine by me! 😊

        Open in Gerrit

        Related details

        Attention is currently required from:
        • Dominic Farolino
        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: I1b933092c9e5e6c023c69172ad961161e647ae99
        Gerrit-Change-Number: 7817087
        Gerrit-PatchSet: 21
        Gerrit-Owner: Dominic Farolino <d...@chromium.org>
        Gerrit-Reviewer: Dominic Farolino <d...@chromium.org>
        Gerrit-Reviewer: Mason Freed <mas...@chromium.org>
        Gerrit-CC: Blink W3C Test Autoroller <blink-w3c-te...@chromium.org>
        Gerrit-CC: Fr <beaufort...@gmail.com>
        Gerrit-CC: Khushal Sagar <khusha...@chromium.org>
        Gerrit-CC: Philip Pfaffe <pfa...@chromium.org>
        Gerrit-Attention: Dominic Farolino <d...@chromium.org>
        Gerrit-Comment-Date: Thu, 14 May 2026 20:31:37 +0000
        Gerrit-HasComments: Yes
        Gerrit-Has-Labels: No
        satisfied_requirement
        open
        diffy

        Chromium LUCI CQ (Gerrit)

        unread,
        May 14, 2026, 6:45:59 PMMay 14
        to Dominic Farolino, Blink W3C Test Autoroller, Mason Freed, Philip Pfaffe, Fr, android-bu...@system.gserviceaccount.com, chromium...@chromium.org, Khushal Sagar, dominicc+...@chromium.org, devtools-re...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, mfoltz+wa...@chromium.org

        Chromium LUCI CQ submitted the change

        Change information

        Commit message:
        WebMCP: Queue declarative tool registration and schema calculation

        Before this CL, declarative WebMCP tools were registered synchronously,
        but had their JSON schemas computed lazily, upon (legacy) `listTools()`
        invocation, etc. Tool registration looked like this:
        1. When a form with `toolname` and `tooldescription` was inserted, it
        synchronously registered a tool with `ModelContext` with an empty
        schema
        2. A task was queued to fire the `toolchange` event at both
        modelContext and modelContextTesting.
        3. The `RegisterScriptTool()` IPC is sent to the browser;
        asynchronously later, it sends `NotifyToolChange()` to tell the
        renderer to fire the `toolchange` event (again!)
        4. As form control elements become associated or mutate, the same
        underlying tool is left alone, but a task is queued to:
        1. Fire `toolchange` events
        2. Tell DevTools that the tool has been removed/re-added
        The two above only happen if the control association/mutation is
        deemed to impact the tool's inputSchema.

        So declarative tools are never unregistered as they get built up and as
        their schemas change, and `toolchange`/DevTools notifications happen
        once per batch of changes.

        But right now, the browser process doesn't know how to "update" a tool's
        schema, so to keep it "fresh" after schema-affecting mutations, we must
        unregister/re-register tools accordingly (later we could consider an
        "update" path in the browser process).

        To accomplish this, the CL does a few things:
        - Instead of registering declarative tools immediately with an empty
        schema but queueing a `toolchange` event, this CL queues the
        registration of the form altogether. That way by registration time,
        batched mutations are done, and the form's schema can be computed
        once at the end.
        - When form controls become associated or mutate, they unregister and
        re-register the underlying form tool if it impacts the existing
        tool's schema. Before this CL, they just queued a `toolchange` event
        if the schema was impacted.

        Performing schema diffs at unregistration/registration time allows us to
        delete:
        - ModelContext::OnToolChange(bool force);
        - ModelContext::InvokeToolChangeClosure(bool force);
        - ModelContext::MaybeNotifyToolChanged();

        This also makes declarative tools play nicely with the new `getTools()`
        and `executeTool()` APIs introduced in https://crrev.com/c/7800264 and
        https://crrev.com/c/7808168, because with those APIs.

        Concretely, this CL:
        - Introduces a new TaskHandle for the async task on HTMLFormElement
        - Adds an `HTMLFormElement::ChildrenChanged()` handler which queues the
        tool registration task, so that once form mutations settle, the
        queued task has a full picture of the form and its JSON schema.
        - Renames `UpdateMcpDefinitionsIfNeeded()` to
        `ScheduleDeclarativeWebMCPToolRegistration()`, which does the
        scheduling.
        - Introduces `RegisterDeclarativeWebMCPTool()` which does the actual
        registration and input schema diffing.
        - Updates `ScheduleWebMCPSchemaUpdate()` (called for each new
        form control association/attr change) to call
        `ScheduleDeclarativeWebMCPToolRegistration()`, if the form has a
        registered tool.

        To make this work, this CL modifies a bunch of declarative WebMCP tests

        to make them wait on `toolchange` being fired before accessing the tool.

        R=masonf
        Bug: 502363131
        Change-Id: I1b933092c9e5e6c023c69172ad961161e647ae99
        Commit-Queue: Dominic Farolino <d...@chromium.org>
        Reviewed-by: Mason Freed <mas...@chromium.org>
        Cr-Commit-Position: refs/heads/main@{#1630821}
        Files:
        • M third_party/blink/renderer/core/html/custom/element_internals.cc
        • M third_party/blink/renderer/core/html/forms/html_form_element.cc
        • M third_party/blink/renderer/core/html/forms/html_form_element.h
        • M third_party/blink/renderer/core/html/forms/html_form_mcp_tool_test.cc
        • M third_party/blink/renderer/core/script_tools/model_context.cc
        • M third_party/blink/renderer/core/script_tools/model_context.h
        • M third_party/blink/renderer/core/script_tools/model_context_test.cc
        • A third_party/blink/web_tests/external/wpt/webmcp/declarative/getTools-declarative-schema.https.html
        • M third_party/blink/web_tests/external/wpt/webmcp/declarative/toolchange-on-control-add-remove.https.html
        • A third_party/blink/web_tests/external/wpt/webmcp/resources/helpers.js
        • R third_party/blink/web_tests/fast/webmcp/get_cross_document_script_tool_result.https-expected.txt
        • R third_party/blink/web_tests/fast/webmcp/get_cross_document_script_tool_result.https.html
        • A third_party/blink/web_tests/fast/webmcp/resources/webmcp-helpers.js
        • R third_party/blink/web_tests/fast/webmcp/usecounter.https.html
        • M third_party/blink/web_tests/inspector-protocol/webmcp/declarative-tool-multiple-inputs.js
        • M third_party/blink/web_tests/inspector-protocol/webmcp/list-tools.js
        • M third_party/blink/web_tests/virtual/webmcp/inspector-protocol/webmcp/declarative-tool-multiple-inputs-expected.txt
        • M third_party/blink/web_tests/virtual/webmcp/inspector-protocol/webmcp/list-tools-expected.txt
        • M third_party/blink/web_tests/wpt_internal/script_tools/form_removal_submit_crash.https.html
        • D third_party/blink/web_tests/wpt_internal/webmcp/custom-element-cease-param.html
        • A third_party/blink/web_tests/wpt_internal/webmcp/custom-element-cease-param.https.html
        • R third_party/blink/web_tests/wpt_internal/webmcp/custom-element-fill.https.html
        • R third_party/blink/web_tests/wpt_internal/webmcp/custom-element-invalid-schema.https.html
        • R third_party/blink/web_tests/wpt_internal/webmcp/execute_tool_change_event.https.html
        • R third_party/blink/web_tests/wpt_internal/webmcp/execute_tool_submit_from_js.https.html
        • A third_party/blink/web_tests/wpt_internal/webmcp/resources/webmcp-helpers.js
        • R third_party/blink/web_tests/wpt_internal/webmcp/select-multiple-events.https.html
        Change size: L
        Delta: 27 files changed, 446 insertions(+), 178 deletions(-)
        Branch: refs/heads/main
        Submit Requirements:
        • requirement satisfiedCode-Review: +1 by Mason Freed
        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: I1b933092c9e5e6c023c69172ad961161e647ae99
        Gerrit-Change-Number: 7817087
        Gerrit-PatchSet: 22
        Gerrit-Owner: Dominic Farolino <d...@chromium.org>
        Gerrit-Reviewer: Chromium LUCI CQ <chromiu...@luci-project-accounts.iam.gserviceaccount.com>
        Gerrit-Reviewer: Dominic Farolino <d...@chromium.org>
        Gerrit-Reviewer: Mason Freed <mas...@chromium.org>
        Gerrit-CC: Blink W3C Test Autoroller <blink-w3c-te...@chromium.org>
        open
        diffy
        satisfied_requirement

        Blink W3C Test Autoroller (Gerrit)

        unread,
        May 15, 2026, 5:09:43 PMMay 15
        to Dominic Farolino, Chromium LUCI CQ, Mason Freed, Philip Pfaffe, Fr, android-bu...@system.gserviceaccount.com, chromium...@chromium.org, Khushal Sagar, dominicc+...@chromium.org, devtools-re...@chromium.org, blink-rev...@chromium.org, blink-revie...@chromium.org, blink-...@chromium.org, mfoltz+wa...@chromium.org

        Message from Blink W3C Test Autoroller

        The WPT PR for this CL has been merged upstream! https://github.com/web-platform-tests/wpt/pull/59889

        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: I1b933092c9e5e6c023c69172ad961161e647ae99
        Gerrit-Change-Number: 7817087
        Gerrit-PatchSet: 22
        Gerrit-Owner: Dominic Farolino <d...@chromium.org>
        Gerrit-Reviewer: Chromium LUCI CQ <chromiu...@luci-project-accounts.iam.gserviceaccount.com>
        Gerrit-Reviewer: Dominic Farolino <d...@chromium.org>
        Gerrit-Reviewer: Mason Freed <mas...@chromium.org>
        Gerrit-CC: Blink W3C Test Autoroller <blink-w3c-te...@chromium.org>
        Gerrit-CC: Fr <beaufort...@gmail.com>
        Gerrit-CC: Khushal Sagar <khusha...@chromium.org>
        Gerrit-CC: Philip Pfaffe <pfa...@chromium.org>
        Gerrit-Comment-Date: Fri, 15 May 2026 21:09:37 +0000
        Gerrit-HasComments: No
        Gerrit-Has-Labels: No
        satisfied_requirement
        open
        diffy
        Reply all
        Reply to author
        Forward
        0 new messages