[WebInstallAPI] Re-verify user activation in WebInstallService [chromium/src : main]

0 views
Skip to first unread message

Lia Hiscock (Gerrit)

unread,
Jun 23, 2026, 8:42:34 PM (5 days ago) Jun 23
to android-bu...@system.gserviceaccount.com, Chromium Metrics Reviews, Lu Huang, Chromium LUCI CQ, chromium...@chromium.org, asvitkine...@chromium.org, blink-re...@chromium.org, blink-rev...@chromium.org, ipc-securi...@chromium.org, kinuko...@chromium.org, aixba+wat...@chromium.org, blink-...@chromium.org, dibyapal+wa...@chromium.org, dmurph+watc...@chromium.org, japhet+...@chromium.org, kuragin+web-ap...@chromium.org, loyso...@chromium.org, mek+w...@chromium.org, mgiuca...@chromium.org, philli...@chromium.org, webap...@microsoft.com, zelin+watch-we...@chromium.org
Attention needed from Lu Huang

Lia Hiscock added 4 comments

File chrome/browser/web_applications/web_install_service_impl.cc
Line 327, Patchset 1: // Both renderer entry points (NavigatorWebInstall::InstallImpl and
// HTMLInstallElement::OnActivated) require user activation before sending
Lu Huang . resolved

Not really my wheelhouse but AI review surfaced this comment nit:

HTMLInstallElement::OnActivated  doesn't check transient activation — the element path gates on HTMLCapabilityElementBase::HandleActivation  via  event.IsFullyTrusted()  (a trusted activation event) plus a debounce. A trusted DOMActivate normally coincides with transient activation, but they can diverge (activation consumed/expired by other in-flight work while the trusted event is processed), in which case this new check could reject a legitimately user-initiated element activation. Suggest rewording, e.g. "The JS path checks transient activation; the  <install>  element path requires a trusted activation event. Re-verify transient activation here as the authoritative browser-side gate — and the only one before the dialog for the element path, which skips the permission prompt."

Lia Hiscock

lots to unpack here. concretely - i've updated the comment to explain the divergence and potential risk.

re. the potential risk (of rejecting legit <install> invocations) -

1 - risk of expiry - Tl;DR uncommon but not impossible (depends on how much work is between activation and this check)

2 - consumed by someone else - sneakier (apparently) - activation is frame-wide and single-shot - requires the page to deliberately (or accidentally) wire 2 activation-gated actions to 1 gesture

3 - realistically, this should be rare to never under normal use - we have no network or async UI between the trusted <install> event and this check.

`vr_service_impl` takes this same risk.
```
if (!has_user_activation) {
// User activation is verified blink-side, so this should never fail
// (everything that happens up to this point should not take enough time for
// the user activation to expire). Treat lack of user activation as unknown
// failure:
RejectSession(std::move(callback), options->trace_id,
```

There are 2 established patterns for browser verification

1 - CHECK, dont consume (this CL approach) - used by frame_sensor_provider_proxy, vr_service_impl, file_system_access_file_handle_impl, eye_dropper_chooser_impl)

2 - snapshot the activation bit early, never recheck - used for flows that span slow, async work and must not false-reject a legitimate gesture

  • FedCM stores `has_transient_user_activation` at entry and reuses it throughout.

**For us, pattern A is the right tradeoff. since we have a UMA now, we can monitor for spikes and reevaluate.**

Line 332, Patchset 1: std::move(callback).Run(blink::mojom::WebInstallServiceResult::kAbortError,
Lu Huang . resolved

Potential inconsistency: renderer-side missing activation throws NotAllowedError, but this browser-side path (the expiry/race case) returns kAbortError, which  OnInstallResponse maps to JS AbortError. Same condition → two different errors depending on timing. Consider adding an enum value to disambiguate?

Lia Hiscock

ah good catch. added `WebInstallServiceResult::kMissingActivationError`

Line 331, Patchset 1: if (!render_frame_host().HasTransientUserActivation()) {
std::move(callback).Run(blink::mojom::WebInstallServiceResult::kAbortError,
GURL());
return;
}
Lu Huang . unresolved

Is it true that now neither side consumes the activation? Within the transient-activation window (~5s) a page can call `navigator.install()` repeatedly?

Lia Hiscock

yes, true. I also called that out to my agent. Because we're checking on both sides now, trying to consume activation anywhere would likely cause a race between checking/consuming. Agent said it's worth the tradeoff to get the browser guarantee that activation was actually there.

And yes, technically a page could spam. We have a 2nd layer of defense with the `IsInstallInProgress` guard though.

Given this, are you still wanting additional protections?

Line 343, Patchset 1: EmitInstallResultUma(triggered_from_element,
Lu Huang . resolved

The new rejection is placed before EmitInstallTypeUma , so it's invisible to metrics (the new tests assert zero UMA). Do we need to know how often it's happening?

Lia Hiscock

might as well! missing user activation doesn't *technically* feel like it's a WebInstall*Service*Result, but not worth making a new enum, so I threw it on the end

Open in Gerrit

Related details

Attention is currently required from:
  • Lu Huang
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: I4e1e84131090f45252b898bcf8fb45f7f8bb8cf8
Gerrit-Change-Number: 7980839
Gerrit-PatchSet: 2
Gerrit-Owner: Lia Hiscock <liahi...@microsoft.com>
Gerrit-Reviewer: Lia Hiscock <liahi...@microsoft.com>
Gerrit-Reviewer: Lu Huang <lu...@microsoft.com>
Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
Gerrit-Attention: Lu Huang <lu...@microsoft.com>
Gerrit-Comment-Date: Wed, 24 Jun 2026 00:42:28 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Lu Huang <lu...@microsoft.com>
satisfied_requirement
unsatisfied_requirement
open
diffy

Lu Huang (Gerrit)

unread,
Jun 24, 2026, 5:26:12 AM (5 days ago) Jun 24
to Lia Hiscock, android-bu...@system.gserviceaccount.com, Chromium Metrics Reviews, Chromium LUCI CQ, chromium...@chromium.org, asvitkine...@chromium.org, blink-re...@chromium.org, blink-rev...@chromium.org, ipc-securi...@chromium.org, kinuko...@chromium.org, aixba+wat...@chromium.org, blink-...@chromium.org, dibyapal+wa...@chromium.org, dmurph+watc...@chromium.org, japhet+...@chromium.org, kuragin+web-ap...@chromium.org, loyso...@chromium.org, mek+w...@chromium.org, mgiuca...@chromium.org, philli...@chromium.org, webap...@microsoft.com, zelin+watch-we...@chromium.org
Attention needed from Lia Hiscock

Lu Huang voted and added 1 comment

Votes added by Lu Huang

Code-Review+1

1 comment

File chrome/browser/web_applications/web_install_service_impl.cc
Line 331, Patchset 1: if (!render_frame_host().HasTransientUserActivation()) {
std::move(callback).Run(blink::mojom::WebInstallServiceResult::kAbortError,
GURL());
return;
}
Lu Huang . unresolved

Is it true that now neither side consumes the activation? Within the transient-activation window (~5s) a page can call `navigator.install()` repeatedly?

Lia Hiscock

yes, true. I also called that out to my agent. Because we're checking on both sides now, trying to consume activation anywhere would likely cause a race between checking/consuming. Agent said it's worth the tradeoff to get the browser guarantee that activation was actually there.

And yes, technically a page could spam. We have a 2nd layer of defense with the `IsInstallInProgress` guard though.

Given this, are you still wanting additional protections?

Lu Huang

IsInstallInProgress helps but doesn't prevent a site from calling Install multiple times within the duration of the transient activation if the activation is never consumed, if they allow each call to complete.

I'm ok with this but I don't think this should be my call to make.

Open in Gerrit

Related details

Attention is currently required from:
  • Lia Hiscock
Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement 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: I4e1e84131090f45252b898bcf8fb45f7f8bb8cf8
    Gerrit-Change-Number: 7980839
    Gerrit-PatchSet: 2
    Gerrit-Owner: Lia Hiscock <liahi...@microsoft.com>
    Gerrit-Reviewer: Lia Hiscock <liahi...@microsoft.com>
    Gerrit-Reviewer: Lu Huang <lu...@microsoft.com>
    Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
    Gerrit-Attention: Lia Hiscock <liahi...@microsoft.com>
    Gerrit-Comment-Date: Wed, 24 Jun 2026 09:25:49 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: Yes
    Comment-In-Reply-To: Lu Huang <lu...@microsoft.com>
    Comment-In-Reply-To: Lia Hiscock <liahi...@microsoft.com>
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Lia Hiscock (Gerrit)

    unread,
    Jun 24, 2026, 1:04:16 PM (4 days ago) Jun 24
    to Lu Huang, android-bu...@system.gserviceaccount.com, Chromium Metrics Reviews, Chromium LUCI CQ, chromium...@chromium.org, asvitkine...@chromium.org, blink-re...@chromium.org, blink-rev...@chromium.org, ipc-securi...@chromium.org, kinuko...@chromium.org, aixba+wat...@chromium.org, blink-...@chromium.org, dibyapal+wa...@chromium.org, dmurph+watc...@chromium.org, japhet+...@chromium.org, kuragin+web-ap...@chromium.org, loyso...@chromium.org, mek+w...@chromium.org, mgiuca...@chromium.org, philli...@chromium.org, webap...@microsoft.com, zelin+watch-we...@chromium.org
    Attention needed from Lu Huang

    Lia Hiscock added 1 comment

    File chrome/browser/web_applications/web_install_service_impl.cc
    Line 331, Patchset 1: if (!render_frame_host().HasTransientUserActivation()) {
    std::move(callback).Run(blink::mojom::WebInstallServiceResult::kAbortError,
    GURL());
    return;
    }
    Lu Huang . unresolved

    Is it true that now neither side consumes the activation? Within the transient-activation window (~5s) a page can call `navigator.install()` repeatedly?

    Lia Hiscock

    yes, true. I also called that out to my agent. Because we're checking on both sides now, trying to consume activation anywhere would likely cause a race between checking/consuming. Agent said it's worth the tradeoff to get the browser guarantee that activation was actually there.

    And yes, technically a page could spam. We have a 2nd layer of defense with the `IsInstallInProgress` guard though.

    Given this, are you still wanting additional protections?

    Lu Huang

    IsInstallInProgress helps but doesn't prevent a site from calling Install multiple times within the duration of the transient activation if the activation is never consumed, if they allow each call to complete.

    I'm ok with this but I don't think this should be my call to make.

    Lia Hiscock

    No, it doesn't prevent that. I guess what's the risk though? The service impl will reject all but the first, right?

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Lu Huang
    Submit Requirements:
    • requirement satisfiedCode-Coverage
    • requirement is not satisfiedCode-Owners
    • requirement 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: I4e1e84131090f45252b898bcf8fb45f7f8bb8cf8
    Gerrit-Change-Number: 7980839
    Gerrit-PatchSet: 2
    Gerrit-Owner: Lia Hiscock <liahi...@microsoft.com>
    Gerrit-Reviewer: Lia Hiscock <liahi...@microsoft.com>
    Gerrit-Reviewer: Lu Huang <lu...@microsoft.com>
    Gerrit-CC: Chromium Metrics Reviews <chromium-met...@google.com>
    Gerrit-Attention: Lu Huang <lu...@microsoft.com>
    Gerrit-Comment-Date: Wed, 24 Jun 2026 17:04:03 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy
    Reply all
    Reply to author
    Forward
    0 new messages