[soft-navs] SoftNavigationContext created in terms of Interactions. [chromium/src : main]

0 views
Skip to first unread message

Michal Mocny (Gerrit)

unread,
Mar 5, 2026, 7:46:57 PM (yesterday) Mar 5
to Scott Haseley, Chromium LUCI CQ, Nate Chapin, AyeAye, jmedle...@chromium.org, speed-metrics...@chromium.org, dtapuska+...@chromium.org, gavinp...@chromium.org, blink-rev...@chromium.org, loading...@chromium.org, blink-re...@chromium.org, blink-...@chromium.org, blink-revi...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, core-timi...@chromium.org
Attention needed from Scott Haseley

Michal Mocny voted Commit-Queue+1

Commit-Queue+1
Open in Gerrit

Related details

Attention is currently required from:
  • Scott Haseley
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: I32c2c09584340e17b9b7707650041eda6a6a6964
Gerrit-Change-Number: 7638455
Gerrit-PatchSet: 4
Gerrit-Owner: Michal Mocny <mmo...@chromium.org>
Gerrit-Reviewer: Michal Mocny <mmo...@chromium.org>
Gerrit-Reviewer: Scott Haseley <shas...@chromium.org>
Gerrit-CC: Nate Chapin <jap...@chromium.org>
Gerrit-Attention: Scott Haseley <shas...@chromium.org>
Gerrit-Comment-Date: Fri, 06 Mar 2026 00:46:51 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: Yes
satisfied_requirement
unsatisfied_requirement
open
diffy

Scott Haseley (Gerrit)

unread,
Mar 5, 2026, 11:57:52 PM (23 hours ago) Mar 5
to Michal Mocny, Chromium LUCI CQ, Nate Chapin, AyeAye, jmedle...@chromium.org, speed-metrics...@chromium.org, dtapuska+...@chromium.org, gavinp...@chromium.org, blink-rev...@chromium.org, loading...@chromium.org, blink-re...@chromium.org, blink-...@chromium.org, blink-revi...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, core-timi...@chromium.org
Attention needed from Michal Mocny

Scott Haseley added 19 comments

Patchset-level comments
File-level comment, Patchset 5 (Latest):
Scott Haseley . resolved

This looks quite reasonable, but I need to read SNH again with a fresh brain in the morning. Some of the failed tests / crashes look interesting, but I didn't look into them.

File third_party/blink/renderer/core/events/pop_state_event.h
Line 90, Patchset 5 (Latest): const PerformanceTimelineEntryIdInfo interaction_id_ =
Scott Haseley . unresolved

I know it's rather innocuous having this, but I think it would be better to push this to the patch it's used in, unless you can do a stack and you think we'll get them both in before branch. Same for HashChangeEvent.

File third_party/blink/renderer/core/frame/history.cc
Line 401, Patchset 5 (Latest): /*is_browser_initiated=*/false, /*is_synchronously_committed=*/true);
Scott Haseley . unresolved

Are these needed or should can they continue using the default values?

File third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
Line 1510, Patchset 5 (Latest): /*is_synchronously_committed=*/true);
Scott Haseley . unresolved

Is this needed, or should it just continue using the default value?

File third_party/blink/renderer/core/navigation_api/navigation_api.cc
Line 868, Patchset 5 (Latest): if (auto id = event_timing_scope.GetInteractionIdInfo()) {
Scott Haseley . unresolved

style nit: this might be clearer without auto since the type isn't obvious
(see https://google.github.io/styleguide/cppguide.html#Type_deduction).

File third_party/blink/renderer/core/timing/soft_navigation_context.cc
Line 41, Patchset 5 (Latest): CHECK(entry);
CHECK(entry->IsKnownToBeAnInteraction());
Scott Haseley . unresolved

Should these checks also be applied to the `initial_event_timing_`?

Line 277, Patchset 5 (Latest): uint64_t interaction_id = initial_event_timing_->interactionId();
Scott Haseley . unresolved

nit: consider inlining below since this is only used once.

Line 307, Patchset 5 (Latest): CHECK(window_);
Scott Haseley . unresolved

Why move these up? FWIW I had the CHECK(window_) below the flag check because I didn't want the check to fail in prod without the feature enabled.

Line 315, Patchset 5 (Latest): uint64_t interaction_id = initial_event_timing_->interactionId();
Scott Haseley . unresolved

nit: same here - consider inlining below since this is only used once.

File third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
Line 167, Patchset 5 (Parent): if (!event.IsFullyTrusted()) {
return std::nullopt;
}
Scott Haseley . unresolved

Do we lose this check? I think this is problematic since that was added to fix a crash / unexpected behavior for creating contexts during simulated events.

Line 209, Patchset 5 (Latest): if (context) {
Scott Haseley . unresolved

How can this be null? Entries should be automatically removed by GC and never null.

Line 227, Patchset 5 (Latest): // is tracking it. If the context comes from a task that crossed from
// another, we might have a different SNH instance. This seems to fail
Scott Haseley . unresolved

nit: removing "created in one window" makes sound unclear to me now.

Line 234, Patchset 5 (Latest): for (const auto& tracked_context : interaction_id_to_context_.Values()) {
Scott Haseley . unresolved

I think we need to treat this as a hot path (dom mods where we have a context), and I'm worried about iterating here. Maybe it's time to put a back-link on context to the heuristics its associated with?

Line 292, Patchset 5 (Latest): SoftNavigationContext* context_for_task =
Scott Haseley . unresolved

Move above line 287 and use that in the ternary expression?

Line 454, Patchset 5 (Latest): if (context && context->OnPaintFinished()) {
Scott Haseley . unresolved

I don't think this can be null

Line 586, Patchset 5 (Latest): TRACE_EVENT_BEGIN("loading", "SoftNavigation",
Scott Haseley . unresolved

We really should move this into SNC...

File third_party/blink/renderer/core/timing/soft_navigation_heuristics_test_util.h
Line 17, Patchset 5 (Latest):class PerformanceEventTiming;
Scott Haseley . unresolved

nit: merge with other forward declarations above.

File third_party/blink/renderer/core/timing/soft_navigation_heuristics_test_util.cc
Line 30, Patchset 5 (Latest): reporting_info.processing_end_time = start_time;
Scott Haseley . unresolved

Worth giving this some kind of duration?

Line 35, Patchset 5 (Latest): /*navigation_id=*/1, PerformanceTimelineEntryIdInfo(1, 1));
Scott Haseley . unresolved

We could also, not necessarily now, make a base class for tests with an id generator member and this as a method, and each interaction could use this (or use the same ID via a "should_increment" parameter or something).

Open in Gerrit

Related details

Attention is currently required from:
  • Michal Mocny
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: I32c2c09584340e17b9b7707650041eda6a6a6964
    Gerrit-Change-Number: 7638455
    Gerrit-PatchSet: 5
    Gerrit-Owner: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Scott Haseley <shas...@chromium.org>
    Gerrit-CC: Nate Chapin <jap...@chromium.org>
    Gerrit-Attention: Michal Mocny <mmo...@chromium.org>
    Gerrit-Comment-Date: Fri, 06 Mar 2026 04:57:43 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Michal Mocny (Gerrit)

    unread,
    6:49 AM (17 hours ago) 6:49 AM
    to Scott Haseley, Chromium LUCI CQ, Nate Chapin, AyeAye, jmedle...@chromium.org, speed-metrics...@chromium.org, dtapuska+...@chromium.org, gavinp...@chromium.org, blink-rev...@chromium.org, loading...@chromium.org, blink-re...@chromium.org, blink-...@chromium.org, blink-revi...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, core-timi...@chromium.org
    Attention needed from Scott Haseley

    Michal Mocny added 16 comments

    Patchset-level comments
    Michal Mocny . resolved

    Ty for review!

    Replies first, will work on addressing these next...

    File third_party/blink/renderer/core/events/pop_state_event.h
    Line 90, Patchset 5 (Latest): const PerformanceTimelineEntryIdInfo interaction_id_ =
    Scott Haseley . unresolved

    I know it's rather innocuous having this, but I think it would be better to push this to the patch it's used in, unless you can do a stack and you think we'll get them both in before branch. Same for HashChangeEvent.

    Michal Mocny

    Sg. This was more of an "initial direction" that proved unneeded.

    File third_party/blink/renderer/core/frame/history.cc
    Line 401, Patchset 5 (Latest): /*is_browser_initiated=*/false, /*is_synchronously_committed=*/true);
    Scott Haseley . unresolved

    Are these needed or should can they continue using the default values?

    Michal Mocny

    good eye-- I had added interaction_id to last param initially, then switched the order specifically to get to do that-- but forgot to make this change :P

    File third_party/blink/renderer/core/timing/soft_navigation_context.h
    Line 74, Patchset 5 (Latest): // Soft LCP. It is the startTime of the last event timing entry before first
    // paint.
    Michal Mocny . unresolved

    this changed. It is now first event timing.

    Pray I do not change it further :)

    File third_party/blink/renderer/core/timing/soft_navigation_context.cc
    Line 41, Patchset 5 (Latest): CHECK(entry);
    CHECK(entry->IsKnownToBeAnInteraction());
    Scott Haseley . unresolved

    Should these checks also be applied to the `initial_event_timing_`?

    Michal Mocny

    In the constructor? Good idea!

    Line 277, Patchset 5 (Latest): uint64_t interaction_id = initial_event_timing_->interactionId();
    Scott Haseley . unresolved

    nit: consider inlining below since this is only used once.

    Michal Mocny

    I added `GetInteractionIdInfo` to this class specifically so I wouldn't need to hard-code things like this here, but missed this one. ty

    Scott Haseley . unresolved

    Why move these up? FWIW I had the CHECK(window_) below the flag check because I didn't want the check to fail in prod without the feature enabled.

    Michal Mocny

    Oh I thought SoftNavigationHeuristicsEnabled needed `window_` and so moved up... ty for noticing

    File third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
    Line 167, Patchset 5 (Parent): if (!event.IsFullyTrusted()) {
    return std::nullopt;
    }
    Scott Haseley . unresolved

    Do we lose this check? I think this is problematic since that was added to fix a crash / unexpected behavior for creating contexts during simulated events.

    Michal Mocny

    I can add the check back, but my expectation was that this check was part of the mini-interaction-event-scope machinery that SNH tried to minic and is being wholesale replaced.

    I didn't think that ICP should apply to a subset of Interactions only, and that all the semantics should be up in Event Timing.

    So, if this indeed still fails, I think it would be better to move up to the Event Timing scope and prevent such events from being Interactions.

    ---

    You mention this applies to simulated events-- if you mean web automation tools, then maybe we need to keep allowing Event TIming to measure those, but should just turn off the context and leave here.

    If you mean real user simulated events, if there is some gap where event timing isn't filtering enough, then we certainly should move up there.

    WDYT?

    Line 227, Patchset 5 (Latest): // is tracking it. If the context comes from a task that crossed from
    // another, we might have a different SNH instance. This seems to fail
    Scott Haseley . unresolved

    nit: removing "created in one window" makes sound unclear to me now.

    Michal Mocny

    sg.

    I wonder if EnsureContextForCurrentWindow should just be folded into GetSoftNavigationContextForCurrentTask() now that we don't pass context* around?

    The only other call site is `ReportSoftNavigationToMetrics` but that is already after we emit to perf timeline and have a whole bunch of effects, so probably not needed there.

    (Ill leave for this patch)

    Line 234, Patchset 5 (Latest): for (const auto& tracked_context : interaction_id_to_context_.Values()) {
    Scott Haseley . unresolved

    I think we need to treat this as a hot path (dom mods where we have a context), and I'm worried about iterating here. Maybe it's time to put a back-link on context to the heuristics its associated with?

    Michal Mocny

    Let me see if understand what you mean:

    • A task can become scheduled on a window
    • That task might have state which has a context*
    • That task might modify dom (etc) and call into SNH static members
    • Now we need to check, which can be expensive, if this SNH map for *this* window was *the* window for this context

    But if we just stored the back pointer from SNC to SNC we could just check directly on the one context.

    SGTM.

    Line 245, Patchset 5 (Latest): uint64_t interaction_id) const {
    Michal Mocny . unresolved

    TODO: try to pass the full typed struct where possible.

    Line 292, Patchset 5 (Latest): SoftNavigationContext* context_for_task =
    Scott Haseley . unresolved

    Move above line 287 and use that in the ternary expression?

    Michal Mocny

    sg, originally I didnt even have this but some of the tests failed because I made mistakes while setting them up so added this guard. It will be possible to remove completely, I just wanted to check the try-bots with it. Should have left a comment.

    I could also leave this in, but add NotFatal? since the worst effect of this getting wrong is that we assign the wrong id/starttime to the wrong context. We should know, but maybe not worth crashing.

    Line 586, Patchset 5 (Latest): TRACE_EVENT_BEGIN("loading", "SoftNavigation",
    Scott Haseley . unresolved

    We really should move this into SNC...

    Michal Mocny

    I can do that. I think there are a few other reporting things in here that could, but I'll limit the moves for now.

    File third_party/blink/renderer/core/timing/soft_navigation_heuristics_test_util.cc
    Line 30, Patchset 5 (Latest): reporting_info.processing_end_time = start_time;
    Scott Haseley . unresolved

    Worth giving this some kind of duration?

    Michal Mocny

    Yeah. Even better would be to merge the Utils that window_performance_test.cc uses (which has a lot more careful setup of invarients and simulation for lifecycle)...

    Might have to move/rename util files around, but for now I think I'll just duplicate the code.

    Line 35, Patchset 5 (Latest): /*navigation_id=*/1, PerformanceTimelineEntryIdInfo(1, 1));
    Michal Mocny . unresolved

    (From AI reviewer:)

    Hardcoding the interaction ID to (1, 1) can lead to incorrect test behavior. For example, in `SoftNavigationHeuristicsTest.HeuristicNotResetDuringGCWithActiveContext`, two separate click events are simulated, but they will end up with the same interaction ID and reuse the same `SoftNavigationContext`, which is likely not the intent.

    Consider using an ID generator here, or passing the ID in as a parameter, similar to the fix in `InteractionEffectsMonitorTest`.

    Line 35, Patchset 5 (Latest): /*navigation_id=*/1, PerformanceTimelineEntryIdInfo(1, 1));
    Scott Haseley . resolved

    We could also, not necessarily now, make a base class for tests with an id generator member and this as a method, and each interaction could use this (or use the same ID via a "should_increment" parameter or something).

    Michal Mocny

    I think that the InteractionID Unittest base in window_performance_test.cc does some of this and probably the soft nav / icp tests should eventually become a subclass of that... But yeah, larger test refactor for later.

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Scott Haseley
    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: I32c2c09584340e17b9b7707650041eda6a6a6964
    Gerrit-Change-Number: 7638455
    Gerrit-PatchSet: 5
    Gerrit-Owner: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Scott Haseley <shas...@chromium.org>
    Gerrit-CC: Nate Chapin <jap...@chromium.org>
    Gerrit-Attention: Scott Haseley <shas...@chromium.org>
    Gerrit-Comment-Date: Fri, 06 Mar 2026 11:49:31 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Scott Haseley <shas...@chromium.org>
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Michal Mocny (Gerrit)

    unread,
    7:01 AM (16 hours ago) 7:01 AM
    to Scott Haseley, Chromium LUCI CQ, Nate Chapin, AyeAye, jmedle...@chromium.org, speed-metrics...@chromium.org, dtapuska+...@chromium.org, gavinp...@chromium.org, blink-rev...@chromium.org, loading...@chromium.org, blink-re...@chromium.org, blink-...@chromium.org, blink-revi...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, core-timi...@chromium.org
    Attention needed from Scott Haseley

    Michal Mocny added 1 comment

    Patchset-level comments
    Michal Mocny . resolved

    Also, found the bug that caused tests to crash:

    I added `PerformanceEventTiming::IsKnownToBeAnInteraction` but theres a subtle bug: some interactions which have an id>0 are "ignored" and treated as 0 anyway-- like autoscroll, which is where the tests were failing.

    We were accidentally trying to create context with id==0 which the hashmap didn't like using as a key. Good catch, bots!

    (There autoscroll are distinct from gesture scroll, which we wont count for different reasons)

    Gerrit-Comment-Date: Fri, 06 Mar 2026 12:01:18 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Michal Mocny (Gerrit)

    unread,
    8:27 AM (15 hours ago) 8:27 AM
    to Scott Haseley, Chromium LUCI CQ, Nate Chapin, AyeAye, jmedle...@chromium.org, speed-metrics...@chromium.org, dtapuska+...@chromium.org, gavinp...@chromium.org, blink-rev...@chromium.org, loading...@chromium.org, blink-re...@chromium.org, blink-...@chromium.org, blink-revi...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, core-timi...@chromium.org
    Attention needed from Scott Haseley

    Michal Mocny added 1 comment

    File third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
    Line 234, Patchset 5: for (const auto& tracked_context : interaction_id_to_context_.Values()) {
    Scott Haseley . unresolved

    I think we need to treat this as a hot path (dom mods where we have a context), and I'm worried about iterating here. Maybe it's time to put a back-link on context to the heuristics its associated with?

    Michal Mocny

    Let me see if understand what you mean:

    • A task can become scheduled on a window
    • That task might have state which has a context*
    • That task might modify dom (etc) and call into SNH static members
    • Now we need to check, which can be expensive, if this SNH map for *this* window was *the* window for this context

    But if we just stored the back pointer from SNC to SNC we could just check directly on the one context.

    SGTM.

    Michal Mocny

    I added this, because I think its useful to have a backpointer... but I noticed that SNC already has a window_ and I think we can get SNH from window_, and the goal is to check for this window is the original window... I think

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Scott Haseley
    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: I32c2c09584340e17b9b7707650041eda6a6a6964
    Gerrit-Change-Number: 7638455
    Gerrit-PatchSet: 6
    Gerrit-Owner: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Scott Haseley <shas...@chromium.org>
    Gerrit-CC: Nate Chapin <jap...@chromium.org>
    Gerrit-Attention: Scott Haseley <shas...@chromium.org>
    Gerrit-Comment-Date: Fri, 06 Mar 2026 13:27:00 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Scott Haseley <shas...@chromium.org>
    Comment-In-Reply-To: Michal Mocny <mmo...@chromium.org>
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Michal Mocny (Gerrit)

    unread,
    11:17 AM (12 hours ago) 11:17 AM
    to Scott Haseley, Chromium LUCI CQ, Nate Chapin, AyeAye, jmedle...@chromium.org, speed-metrics...@chromium.org, dtapuska+...@chromium.org, gavinp...@chromium.org, blink-rev...@chromium.org, loading...@chromium.org, blink-re...@chromium.org, blink-...@chromium.org, blink-revi...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, core-timi...@chromium.org
    Attention needed from Scott Haseley

    Michal Mocny added 17 comments

    File third_party/blink/renderer/core/frame/history.cc
    Line 401, Patchset 5: /*is_browser_initiated=*/false, /*is_synchronously_committed=*/true);
    Scott Haseley . resolved

    Are these needed or should can they continue using the default values?

    Michal Mocny

    good eye-- I had added interaction_id to last param initially, then switched the order specifically to get to do that-- but forgot to make this change :P

    Michal Mocny

    Done

    File third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
    Line 1510, Patchset 5: /*is_synchronously_committed=*/true);
    Scott Haseley . resolved

    Is this needed, or should it just continue using the default value?

    Michal Mocny

    Done

    File third_party/blink/renderer/core/navigation_api/navigation_api.cc
    Line 868, Patchset 5: if (auto id = event_timing_scope.GetInteractionIdInfo()) {
    Scott Haseley . resolved

    style nit: this might be clearer without auto since the type isn't obvious
    (see https://google.github.io/styleguide/cppguide.html#Type_deduction).

    Michal Mocny

    Done

    File third_party/blink/renderer/core/timing/soft_navigation_context.h
    Line 74, Patchset 5: // Soft LCP. It is the startTime of the last event timing entry before first
    // paint.
    Michal Mocny . resolved

    this changed. It is now first event timing.

    Pray I do not change it further :)

    Michal Mocny

    Done

    File third_party/blink/renderer/core/timing/soft_navigation_context.cc
    Line 41, Patchset 5: CHECK(entry);
    CHECK(entry->IsKnownToBeAnInteraction());
    Scott Haseley . resolved

    Should these checks also be applied to the `initial_event_timing_`?

    Michal Mocny

    In the constructor? Good idea!

    Michal Mocny

    Done

    Line 269, Patchset 6 (Parent): // `heuristics` will be null if the `window_` was detached but this context
    Michal Mocny . unresolved

    restore this

    Line 277, Patchset 5: uint64_t interaction_id = initial_event_timing_->interactionId();
    Scott Haseley . resolved

    nit: consider inlining below since this is only used once.

    Michal Mocny

    I added `GetInteractionIdInfo` to this class specifically so I wouldn't need to hard-code things like this here, but missed this one. ty

    Michal Mocny

    Done

    Line 307, Patchset 5: CHECK(window_);
    Scott Haseley . resolved

    Why move these up? FWIW I had the CHECK(window_) below the flag check because I didn't want the check to fail in prod without the feature enabled.

    Michal Mocny

    Oh I thought SoftNavigationHeuristicsEnabled needed `window_` and so moved up... ty for noticing

    Michal Mocny

    Done

    Line 315, Patchset 5: uint64_t interaction_id = initial_event_timing_->interactionId();
    Scott Haseley . resolved

    nit: same here - consider inlining below since this is only used once.

    Michal Mocny

    Done

    File third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
    Line 209, Patchset 5: if (context) {
    Scott Haseley . resolved

    How can this be null? Entries should be automatically removed by GC and never null.

    Michal Mocny

    Done

    Line 227, Patchset 5: // is tracking it. If the context comes from a task that crossed from

    // another, we might have a different SNH instance. This seems to fail
    Scott Haseley . resolved

    nit: removing "created in one window" makes sound unclear to me now.

    Michal Mocny

    sg.

    I wonder if EnsureContextForCurrentWindow should just be folded into GetSoftNavigationContextForCurrentTask() now that we don't pass context* around?

    The only other call site is `ReportSoftNavigationToMetrics` but that is already after we emit to perf timeline and have a whole bunch of effects, so probably not needed there.

    (Ill leave for this patch)

    Michal Mocny

    After the change to the "hot path" check for SNH, this function became a one liner-- so I just inlined it and remvoed it.

    Line 234, Patchset 5: for (const auto& tracked_context : interaction_id_to_context_.Values()) {
    Scott Haseley . resolved

    I think we need to treat this as a hot path (dom mods where we have a context), and I'm worried about iterating here. Maybe it's time to put a back-link on context to the heuristics its associated with?

    Michal Mocny

    Let me see if understand what you mean:

    • A task can become scheduled on a window
    • That task might have state which has a context*
    • That task might modify dom (etc) and call into SNH static members
    • Now we need to check, which can be expensive, if this SNH map for *this* window was *the* window for this context

    But if we just stored the back pointer from SNC to SNC we could just check directly on the one context.

    SGTM.

    Michal Mocny

    I added this, because I think its useful to have a backpointer... but I noticed that SNC already has a window_ and I think we can get SNH from window_, and the goal is to check for this window is the original window... I think

    Michal Mocny

    Done

    Line 245, Patchset 5: uint64_t interaction_id) const {
    Michal Mocny . resolved

    TODO: try to pass the full typed struct where possible.

    Michal Mocny

    Done

    Line 454, Patchset 5: if (context && context->OnPaintFinished()) {
    Scott Haseley . resolved

    I don't think this can be null

    Michal Mocny

    Done

    Line 586, Patchset 5: TRACE_EVENT_BEGIN("loading", "SoftNavigation",
    Scott Haseley . resolved

    We really should move this into SNC...

    Michal Mocny

    I can do that. I think there are a few other reporting things in here that could, but I'll limit the moves for now.

    Michal Mocny

    I moved a small amount of tracing now, but added a comment to the crbug to followup

    File third_party/blink/renderer/core/timing/soft_navigation_heuristics_test_util.h
    Line 17, Patchset 5:class PerformanceEventTiming;
    Scott Haseley . resolved

    nit: merge with other forward declarations above.

    Michal Mocny

    Done

    File third_party/blink/renderer/core/timing/soft_navigation_heuristics_test_util.cc
    Line 30, Patchset 5: reporting_info.processing_end_time = start_time;
    Scott Haseley . resolved

    Worth giving this some kind of duration?

    Michal Mocny

    Yeah. Even better would be to merge the Utils that window_performance_test.cc uses (which has a lot more careful setup of invarients and simulation for lifecycle)...

    Might have to move/rename util files around, but for now I think I'll just duplicate the code.

    Michal Mocny

    fixed a small amount here, but added comment to crbug to followup with a larger unification here.

    Gerrit-Comment-Date: Fri, 06 Mar 2026 16:17:10 +0000
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Scott Haseley (Gerrit)

    unread,
    11:28 AM (12 hours ago) 11:28 AM
    to Michal Mocny, Chromium LUCI CQ, Nate Chapin, AyeAye, jmedle...@chromium.org, speed-metrics...@chromium.org, dtapuska+...@chromium.org, gavinp...@chromium.org, blink-rev...@chromium.org, loading...@chromium.org, blink-re...@chromium.org, blink-...@chromium.org, blink-revi...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, core-timi...@chromium.org

    Scott Haseley added 4 comments

    Patchset-level comments
    File-level comment, Patchset 6 (Latest):
    Scott Haseley . resolved

    Still catching up. Brain-dumping my sleep thoughts before I grab breakfast.

    File third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
    Line 167, Patchset 5 (Parent): if (!event.IsFullyTrusted()) {
    return std::nullopt;
    }
    Scott Haseley . unresolved

    Do we lose this check? I think this is problematic since that was added to fix a crash / unexpected behavior for creating contexts during simulated events.

    Michal Mocny

    I can add the check back, but my expectation was that this check was part of the mini-interaction-event-scope machinery that SNH tried to minic and is being wholesale replaced.

    I didn't think that ICP should apply to a subset of Interactions only, and that all the semantics should be up in Event Timing.

    So, if this indeed still fails, I think it would be better to move up to the Event Timing scope and prevent such events from being Interactions.

    ---

    You mention this applies to simulated events-- if you mean web automation tools, then maybe we need to keep allowing Event TIming to measure those, but should just turn off the context and leave here.

    If you mean real user simulated events, if there is some gap where event timing isn't filtering enough, then we certainly should move up there.

    WDYT?

    Scott Haseley

    The problem was simulated event (untrusted) causing a trusted event. This happens because of form controls. See https://chromium-review.googlesource.com/c/chromium/src/+/7466724 (if you're passing that test, this might be okay now)

    Line 234, Patchset 5: for (const auto& tracked_context : interaction_id_to_context_.Values()) {
    Scott Haseley . unresolved

    I think we need to treat this as a hot path (dom mods where we have a context), and I'm worried about iterating here. Maybe it's time to put a back-link on context to the heuristics its associated with?

    Michal Mocny

    Let me see if understand what you mean:

    • A task can become scheduled on a window
    • That task might have state which has a context*
    • That task might modify dom (etc) and call into SNH static members
    • Now we need to check, which can be expensive, if this SNH map for *this* window was *the* window for this context

    But if we just stored the back pointer from SNC to SNC we could just check directly on the one context.

    SGTM.

    Michal Mocny

    I added this, because I think its useful to have a backpointer... but I noticed that SNC already has a window_ and I think we can get SNH from window_, and the goal is to check for this window is the original window... I think

    Scott Haseley

    Thought of that at 4AM in my sleep too... Yeah I think we can just check context->GetWindow() == Window() (making these up). That was why this was added IIRC (cross-window main frame case w/ window.opener()).

    If we want to (eventually) exclude other contexts (e.g. if we shutdown early), we can check if they've been shutdown or whatever.

    Line 578, Patchset 6 (Latest): SoftNavigationContext* context = GetRelevantContext(interaction_id);
    Scott Haseley . unresolved

    Since the map holds WeakMember<context>, I think there's an edge case where we can create multiple contexts for the same interaction_id. Not sure if you thought about this? I think most won't matter in practice, but the retainer dependency is a bit gnarly (it relies on the paint attribution tracker to manage lifetime).

    Okay example:
    - keydown
    - dom update
    - paint tracker holds strong reference
    - keyup
    finds context
    Benign example:
    - keydown, create context
    - keydown does nothing
    - GC happens -- context GCed
    - keyup
    - new context
    Edge case:
    - keydown, create context; hold key (same can happen once pointer down gets id)
    - update some dom
    - paint
    - emit ICP
    - ...
    - remove said updated dom
    - GC
    - context GCed because no more retainers
    - keyup
    - no matching context for id, new context
    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: I32c2c09584340e17b9b7707650041eda6a6a6964
    Gerrit-Change-Number: 7638455
    Gerrit-PatchSet: 6
    Gerrit-Owner: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Scott Haseley <shas...@chromium.org>
    Gerrit-CC: Nate Chapin <jap...@chromium.org>
    Gerrit-Comment-Date: Fri, 06 Mar 2026 16:28:25 +0000
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Michal Mocny (Gerrit)

    unread,
    12:58 PM (10 hours ago) 12:58 PM
    to Scott Haseley, Chromium LUCI CQ, Nate Chapin, AyeAye, jmedle...@chromium.org, speed-metrics...@chromium.org, dtapuska+...@chromium.org, gavinp...@chromium.org, blink-rev...@chromium.org, loading...@chromium.org, blink-re...@chromium.org, blink-...@chromium.org, blink-revi...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, core-timi...@chromium.org
    Attention needed from Scott Haseley

    Michal Mocny voted and added 1 comment

    Votes added by Michal Mocny

    Commit-Queue+1

    1 comment

    File third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
    Line 292, Patchset 5: SoftNavigationContext* context_for_task =
    Scott Haseley . resolved

    Move above line 287 and use that in the ternary expression?

    Michal Mocny

    sg, originally I didnt even have this but some of the tests failed because I made mistakes while setting them up so added this guard. It will be possible to remove completely, I just wanted to check the try-bots with it. Should have left a comment.

    I could also leave this in, but add NotFatal? since the worst effect of this getting wrong is that we assign the wrong id/starttime to the wrong context. We should know, but maybe not worth crashing.

    Michal Mocny

    Done

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Scott Haseley
    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: I32c2c09584340e17b9b7707650041eda6a6a6964
    Gerrit-Change-Number: 7638455
    Gerrit-PatchSet: 7
    Gerrit-Owner: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Scott Haseley <shas...@chromium.org>
    Gerrit-CC: Nate Chapin <jap...@chromium.org>
    Gerrit-Attention: Scott Haseley <shas...@chromium.org>
    Gerrit-Comment-Date: Fri, 06 Mar 2026 17:58:14 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: Yes
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Johannes Henkel (Gerrit)

    unread,
    2:43 PM (9 hours ago) 2:43 PM
    to Michal Mocny, Scott Haseley, Chromium LUCI CQ, Nate Chapin, AyeAye, jmedle...@chromium.org, speed-metrics...@chromium.org, dtapuska+...@chromium.org, gavinp...@chromium.org, blink-rev...@chromium.org, loading...@chromium.org, blink-re...@chromium.org, blink-...@chromium.org, blink-revi...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, core-timi...@chromium.org
    Attention needed from Michal Mocny and Scott Haseley

    Johannes Henkel added 1 comment

    Patchset-level comments
    File-level comment, Patchset 7 (Latest):
    Johannes Henkel . resolved

    https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/web_tests/http/tests/inspector-protocol/tracing/soft-navigations-expected.txt;l=38

    Looks that this line (processingEnd) needs to be deleted, to reflect that it's no longer part of the SoftNavigation object.

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Michal Mocny
    • Scott Haseley
    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: I32c2c09584340e17b9b7707650041eda6a6a6964
    Gerrit-Change-Number: 7638455
    Gerrit-PatchSet: 7
    Gerrit-Owner: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Scott Haseley <shas...@chromium.org>
    Gerrit-CC: Johannes Henkel <joha...@chromium.org>
    Gerrit-CC: Nate Chapin <jap...@chromium.org>
    Gerrit-Attention: Scott Haseley <shas...@chromium.org>
    Gerrit-Attention: Michal Mocny <mmo...@chromium.org>
    Gerrit-Comment-Date: Fri, 06 Mar 2026 19:43:02 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Scott Haseley (Gerrit)

    unread,
    3:18 PM (8 hours ago) 3:18 PM
    to Michal Mocny, Johannes Henkel, Chromium LUCI CQ, Nate Chapin, AyeAye, jmedle...@chromium.org, speed-metrics...@chromium.org, dtapuska+...@chromium.org, gavinp...@chromium.org, blink-rev...@chromium.org, loading...@chromium.org, blink-re...@chromium.org, blink-...@chromium.org, blink-revi...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, core-timi...@chromium.org
    Attention needed from Michal Mocny

    Scott Haseley added 5 comments

    Patchset-level comments
    Scott Haseley . resolved

    Just a couple comments, will review again after lunch.

    File third_party/blink/renderer/core/timing/soft_navigation_context.h
    Line 74, Patchset 5: // Soft LCP. It is the startTime of the last event timing entry before first
    // paint.
    Michal Mocny . resolved

    this changed. It is now first event timing.

    Pray I do not change it further :)

    Michal Mocny

    Done

    Scott Haseley

    😄

    File third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
    Line 167, Patchset 5 (Parent): if (!event.IsFullyTrusted()) {
    return std::nullopt;
    }
    Scott Haseley . unresolved

    Do we lose this check? I think this is problematic since that was added to fix a crash / unexpected behavior for creating contexts during simulated events.

    Michal Mocny

    I can add the check back, but my expectation was that this check was part of the mini-interaction-event-scope machinery that SNH tried to minic and is being wholesale replaced.

    I didn't think that ICP should apply to a subset of Interactions only, and that all the semantics should be up in Event Timing.

    So, if this indeed still fails, I think it would be better to move up to the Event Timing scope and prevent such events from being Interactions.

    ---

    You mention this applies to simulated events-- if you mean web automation tools, then maybe we need to keep allowing Event TIming to measure those, but should just turn off the context and leave here.

    If you mean real user simulated events, if there is some gap where event timing isn't filtering enough, then we certainly should move up there.

    WDYT?

    Scott Haseley

    The problem was simulated event (untrusted) causing a trusted event. This happens because of form controls. See https://chromium-review.googlesource.com/c/chromium/src/+/7466724 (if you're passing that test, this might be okay now)

    Scott Haseley

    Ah, yeah it's still failing.

    The problem is that if you dispatch a simulated click to an element with a target, we dispatch a trusted click to the target. So we create EventTimings for such events, but soft navs filters them out.

    I suspect these should be filtered out from EventTiming as well, and maybe that's relatively safe to do? Not sure.

    The test case: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/web_tests/wpt_internal/task-tracking/soft-navigation-heuristics/non-fully-trusted-click.html

    Line 227, Patchset 5: // is tracking it. If the context comes from a task that crossed from
    // another, we might have a different SNH instance. This seems to fail
    Scott Haseley . resolved

    nit: removing "created in one window" makes sound unclear to me now.

    Michal Mocny

    sg.

    I wonder if EnsureContextForCurrentWindow should just be folded into GetSoftNavigationContextForCurrentTask() now that we don't pass context* around?

    The only other call site is `ReportSoftNavigationToMetrics` but that is already after we emit to perf timeline and have a whole bunch of effects, so probably not needed there.

    (Ill leave for this patch)

    Michal Mocny

    After the change to the "hot path" check for SNH, this function became a one liner-- so I just inlined it and remvoed it.

    Scott Haseley

    Sweet!

    Line 248, Patchset 7 (Latest): // TODO(crbug.com/40871933): We don't care to support datetime modals, but
    // this behaviour might be similar for iframes, and might be worth
    // supporting.
    Scott Haseley . unresolved

    note: We ran into this in practice with window.open(), in which case you get two main frames in the same process that can script each other.

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Michal Mocny
    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: I32c2c09584340e17b9b7707650041eda6a6a6964
    Gerrit-Change-Number: 7638455
    Gerrit-PatchSet: 7
    Gerrit-Owner: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Scott Haseley <shas...@chromium.org>
    Gerrit-CC: Johannes Henkel <joha...@chromium.org>
    Gerrit-CC: Nate Chapin <jap...@chromium.org>
    Gerrit-Attention: Michal Mocny <mmo...@chromium.org>
    Gerrit-Comment-Date: Fri, 06 Mar 2026 20:18:42 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Michal Mocny (Gerrit)

    unread,
    3:23 PM (8 hours ago) 3:23 PM
    to Johannes Henkel, Scott Haseley, Chromium LUCI CQ, Nate Chapin, AyeAye, jmedle...@chromium.org, speed-metrics...@chromium.org, dtapuska+...@chromium.org, gavinp...@chromium.org, blink-rev...@chromium.org, loading...@chromium.org, blink-re...@chromium.org, blink-...@chromium.org, blink-revi...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, core-timi...@chromium.org
    Attention needed from Scott Haseley

    Michal Mocny added 6 comments

    File third_party/blink/renderer/core/timing/soft_navigation_context.cc
    Line 269, Patchset 6 (Parent): // `heuristics` will be null if the `window_` was detached but this context
    Michal Mocny . resolved

    restore this

    Michal Mocny

    Done

    File third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
    Line 167, Patchset 5 (Parent): if (!event.IsFullyTrusted()) {
    return std::nullopt;
    }
    Scott Haseley . resolved

    Do we lose this check? I think this is problematic since that was added to fix a crash / unexpected behavior for creating contexts during simulated events.

    Michal Mocny

    I can add the check back, but my expectation was that this check was part of the mini-interaction-event-scope machinery that SNH tried to minic and is being wholesale replaced.

    I didn't think that ICP should apply to a subset of Interactions only, and that all the semantics should be up in Event Timing.

    So, if this indeed still fails, I think it would be better to move up to the Event Timing scope and prevent such events from being Interactions.

    ---

    You mention this applies to simulated events-- if you mean web automation tools, then maybe we need to keep allowing Event TIming to measure those, but should just turn off the context and leave here.

    If you mean real user simulated events, if there is some gap where event timing isn't filtering enough, then we certainly should move up there.

    WDYT?

    Scott Haseley

    The problem was simulated event (untrusted) causing a trusted event. This happens because of form controls. See https://chromium-review.googlesource.com/c/chromium/src/+/7466724 (if you're passing that test, this might be okay now)

    Michal Mocny

    Done

    Line 234, Patchset 5: for (const auto& tracked_context : interaction_id_to_context_.Values()) {
    Scott Haseley . resolved

    I think we need to treat this as a hot path (dom mods where we have a context), and I'm worried about iterating here. Maybe it's time to put a back-link on context to the heuristics its associated with?

    Michal Mocny

    Let me see if understand what you mean:

    • A task can become scheduled on a window
    • That task might have state which has a context*
    • That task might modify dom (etc) and call into SNH static members
    • Now we need to check, which can be expensive, if this SNH map for *this* window was *the* window for this context

    But if we just stored the back pointer from SNC to SNC we could just check directly on the one context.

    SGTM.

    Michal Mocny

    I added this, because I think its useful to have a backpointer... but I noticed that SNC already has a window_ and I think we can get SNH from window_, and the goal is to check for this window is the original window... I think

    Scott Haseley

    Thought of that at 4AM in my sleep too... Yeah I think we can just check context->GetWindow() == Window() (making these up). That was why this was added IIRC (cross-window main frame case w/ window.opener()).

    If we want to (eventually) exclude other contexts (e.g. if we shutdown early), we can check if they've been shutdown or whatever.

    Michal Mocny

    Done

    Line 248, Patchset 7 (Latest): // TODO(crbug.com/40871933): We don't care to support datetime modals, but
    // this behaviour might be similar for iframes, and might be worth
    // supporting.
    Scott Haseley . resolved

    note: We ran into this in practice with window.open(), in which case you get two main frames in the same process that can script each other.

    Michal Mocny

    (this comment just moved from somewhere earlier, I didn't add it-- I hope nothing abut the specifics change here.)

    Line 578, Patchset 6: SoftNavigationContext* context = GetRelevantContext(interaction_id);
    Michal Mocny

    Great points-- but I think this would be WAI and the fact that each attempt to get a context by id with an event timing doesn't assume there was a past event means this should just work.

    Or do you spot a problem?

    We should add tests for it afterwards!

    File third_party/blink/renderer/core/timing/soft_navigation_heuristics_test_util.cc
    Line 35, Patchset 5: /*navigation_id=*/1, PerformanceTimelineEntryIdInfo(1, 1));
    Michal Mocny . resolved

    (From AI reviewer:)

    Hardcoding the interaction ID to (1, 1) can lead to incorrect test behavior. For example, in `SoftNavigationHeuristicsTest.HeuristicNotResetDuringGCWithActiveContext`, two separate click events are simulated, but they will end up with the same interaction ID and reuse the same `SoftNavigationContext`, which is likely not the intent.

    Consider using an ID generator here, or passing the ID in as a parameter, similar to the fix in `InteractionEffectsMonitorTest`.

    Michal Mocny

    Cannot use a generator here, but we will move this into a test base that will do this, in a subsequent patch. The tests that need separate ids can manually set them, for now.

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Scott Haseley
    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: I32c2c09584340e17b9b7707650041eda6a6a6964
    Gerrit-Change-Number: 7638455
    Gerrit-PatchSet: 7
    Gerrit-Owner: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Scott Haseley <shas...@chromium.org>
    Gerrit-CC: Johannes Henkel <joha...@chromium.org>
    Gerrit-CC: Nate Chapin <jap...@chromium.org>
    Gerrit-Attention: Scott Haseley <shas...@chromium.org>
    Gerrit-Comment-Date: Fri, 06 Mar 2026 20:23:10 +0000
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Michal Mocny (Gerrit)

    unread,
    3:51 PM (7 hours ago) 3:51 PM
    to Johannes Henkel, Scott Haseley, Chromium LUCI CQ, Nate Chapin, AyeAye, jmedle...@chromium.org, speed-metrics...@chromium.org, dtapuska+...@chromium.org, gavinp...@chromium.org, blink-rev...@chromium.org, loading...@chromium.org, blink-re...@chromium.org, blink-...@chromium.org, blink-revi...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, core-timi...@chromium.org
    Attention needed from Johannes Henkel and Scott Haseley

    Michal Mocny voted and added 1 comment

    Votes added by Michal Mocny

    Commit-Queue+1

    1 comment

    Patchset-level comments
    Johannes Henkel . resolved

    https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/web_tests/http/tests/inspector-protocol/tracing/soft-navigations-expected.txt;l=38

    Looks that this line (processingEnd) needs to be deleted, to reflect that it's no longer part of the SoftNavigation object.

    Michal Mocny

    I added it back to tracing for now, I thought it wasn't needed at all but forgot about these tests.

    We could also expose more of the event timings if we want... or even the full list of them.

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Johannes Henkel
    • Scott Haseley
    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: I32c2c09584340e17b9b7707650041eda6a6a6964
    Gerrit-Change-Number: 7638455
    Gerrit-PatchSet: 9
    Gerrit-Owner: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Scott Haseley <shas...@chromium.org>
    Gerrit-CC: Johannes Henkel <joha...@chromium.org>
    Gerrit-CC: Nate Chapin <jap...@chromium.org>
    Gerrit-Attention: Johannes Henkel <joha...@chromium.org>
    Gerrit-Attention: Scott Haseley <shas...@chromium.org>
    Gerrit-Comment-Date: Fri, 06 Mar 2026 20:51:39 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: Yes
    Comment-In-Reply-To: Johannes Henkel <joha...@chromium.org>
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Scott Haseley (Gerrit)

    unread,
    7:59 PM (3 hours ago) 7:59 PM
    to Michal Mocny, Daniel Cheng, Johannes Henkel, Chromium LUCI CQ, Nate Chapin, AyeAye, android-web...@chromium.org, ashleynewson+w...@chromium.org, jmedle...@chromium.org, speed-metrics...@chromium.org, dtapuska+...@chromium.org, gavinp...@chromium.org, blink-rev...@chromium.org, loading...@chromium.org, blink-re...@chromium.org, blink-...@chromium.org, blink-revi...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, core-timi...@chromium.org
    Attention needed from Johannes Henkel and Michal Mocny

    Scott Haseley added 13 comments

    File third_party/blink/renderer/core/loader/document_loader.cc
    Line 1628, Patchset 11 (Latest): InteractionContextWrapperScope interaction_context_wrapper;
    Scott Haseley . unresolved

    nit/optional: maybe comment that browser-initiated navigations are considered interactions and this scope sets up handling that for metrics?

    Line 1697, Patchset 11 (Latest): }
    Scott Haseley . unresolved

    ultra-nit: probably keep the newline before this and add one after to separate the task-attribution block

    File third_party/blink/renderer/core/timing/event_timing.h
    Line 34, Patchset 11 (Latest):// is wrapper in this scope, it std::move() the task_scope up to it instead.
    Scott Haseley . unresolved

    ```suggestion
    // is wrapped in this scope, it std::move()d the task_scope up to it instead.
    ```

    Line 31, Patchset 11 (Latest):// This class is used to "hoist" a `TaskAttributionTracker::TaskScope` up to the
    Scott Haseley . unresolved

    Thinking about this a bit more, I think the hoisting is a problem. Having the outer scope is nice, but it would need to initialize the state. The invariant is supposed to be that all TaskScopes are "properly nested", like trace events, and I think this breaks that.

    For example, suppose you have A() calls B() calls C().

     - A() runs, creating an outer InteractionContextWrapperScope scope, initially with the nullopt TaskScope
    - A() calls B(), which sets a task state variable (new TaskScope). That scope will capture the current task state (nothing) and restore that upon completion
    - B() calls C(), which initializes the outer scope's TaskScope. The current task state (B's state) is captured as the "state to restore".
    - C() ends
    - B() ends. The null state is restored --> (outer scope is borked!)
    - A() ends. B's state is restored --> state leak!

    (I actually think I need to nix the TaskScope move c'tors!)

    File third_party/blink/renderer/core/timing/event_timing.cc
    Line 74, Patchset 11 (Latest): if (!event.IsFullyTrusted()) {
    Scott Haseley . unresolved

    Do you know if there's a spec issue for this? This could be a compat issue.

    File third_party/blink/renderer/core/timing/soft_navigation_context.h
    Line 142, Patchset 11 (Latest): void AddEventTiming(PerformanceEventTiming* entry);
    Scott Haseley . unresolved

    Can we remove this? `last_event_timing_` doesn't matter anymore now that you're using the first one.

    Line 47, Patchset 11 (Latest): explicit SoftNavigationContext(LocalDOMWindow& window,
    Scott Haseley . unresolved

    nit: can be removed now

    File third_party/blink/renderer/core/timing/soft_navigation_context.cc
    Line 37, Patchset 11 (Latest): TRACE_EVENT_BEGIN("loading", "SoftNavigation",
    Scott Haseley . resolved

    nice

    Line 67, Patchset 11 (Latest): CHECK(initial_event_timing_);
    Scott Haseley . unresolved

    nit: You could probably (?) make `initial_event_timing_` const and/or remove this check, since it's already guaranteed to be valid in the c'tor and we don't change it.

    Line 171, Patchset 11 (Latest): if (auto* heuristics = window_->GetSoftNavigationHeuristics()) {
    Scott Haseley . unresolved
    Did something change that can make this null now, like in tests? Previously, the heuristics was guaranteed to be valid because:
    - It's created by the heuristics class (except in tests)
    - if window_ had a heuristics, it's guaranteed to stay until detach
    - This is shut down on detatch, and OnPaintFinished() shouldn't be called after detach
    Line 307, Patchset 11 (Latest): if (auto* heuristics = window_->GetSoftNavigationHeuristics()) {
    Scott Haseley . resolved

    You didn't like my style? :P

    (FWIW I did that to be consistent with the `if (!condition) { return }` and have the actual logic at the end, as is somewhat idiomatic in chrome (not always tho..))

    Line 341, Patchset 11 (Latest): if (auto* heuristics = window_->GetSoftNavigationHeuristics()) {
    Scott Haseley . unresolved

    Similar question, have the guarantees changed? This should never be called after detach.

    File third_party/blink/renderer/core/timing/soft_navigation_heuristics.cc
    Scott Haseley

    The problem with the last one is the non-determinism -- sometimes things are grouped, sometimes they're not, depending on GC.

    I think it's fine for OT_v1 and shouldn't block this, but I think there's a disconnect in the layering that maybe we can fix when InteractionContext moves out of soft navs, like maybe the context creation and mapping needs to be built into the responsiveness metrics state machine (w/ stronger lifetime guarantees).

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Johannes Henkel
    • Michal Mocny
    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: I32c2c09584340e17b9b7707650041eda6a6a6964
    Gerrit-Change-Number: 7638455
    Gerrit-PatchSet: 11
    Gerrit-Owner: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Michal Mocny <mmo...@chromium.org>
    Gerrit-Reviewer: Scott Haseley <shas...@chromium.org>
    Gerrit-CC: Daniel Cheng <dch...@chromium.org>
    Gerrit-CC: Johannes Henkel <joha...@chromium.org>
    Gerrit-CC: Nate Chapin <jap...@chromium.org>
    Gerrit-Attention: Johannes Henkel <joha...@chromium.org>
    Gerrit-Attention: Michal Mocny <mmo...@chromium.org>
    Gerrit-Comment-Date: Sat, 07 Mar 2026 00:58:59 +0000
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Scott Haseley (Gerrit)

    unread,
    11:00 PM (21 minutes ago) 11:00 PM
    to Michal Mocny, Daniel Cheng, Johannes Henkel, Chromium LUCI CQ, Nate Chapin, AyeAye, android-web...@chromium.org, ashleynewson+w...@chromium.org, jmedle...@chromium.org, speed-metrics...@chromium.org, dtapuska+...@chromium.org, gavinp...@chromium.org, blink-rev...@chromium.org, loading...@chromium.org, blink-re...@chromium.org, blink-...@chromium.org, blink-revi...@chromium.org, blink-revi...@chromium.org, blink-rev...@chromium.org, core-timi...@chromium.org
    Attention needed from Johannes Henkel and Michal Mocny

    Scott Haseley added 1 comment

    File third_party/blink/renderer/core/timing/event_timing.h
    Line 31, Patchset 11 (Latest):// This class is used to "hoist" a `TaskAttributionTracker::TaskScope` up to the
    Scott Haseley . unresolved

    Thinking about this a bit more, I think the hoisting is a problem. Having the outer scope is nice, but it would need to initialize the state. The invariant is supposed to be that all TaskScopes are "properly nested", like trace events, and I think this breaks that.

    For example, suppose you have A() calls B() calls C().

     - A() runs, creating an outer InteractionContextWrapperScope scope, initially with the nullopt TaskScope
    - A() calls B(), which sets a task state variable (new TaskScope). That scope will capture the current task state (nothing) and restore that upon completion
    - B() calls C(), which initializes the outer scope's TaskScope. The current task state (B's state) is captured as the "state to restore".
    - C() ends
    - B() ends. The null state is restored --> (outer scope is borked!)
    - A() ends. B's state is restored --> state leak!

    (I actually think I need to nix the TaskScope move c'tors!)

    Scott Haseley

    Update: I think this is something task attribution should solve, not event timing. Really this is a problem with propagating task state from the intercept() to handler(), which is clear causation. Let me try to add that.

    Gerrit-Comment-Date: Sat, 07 Mar 2026 04:00:08 +0000
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy
    Reply all
    Reply to author
    Forward
    0 new messages