Skip to content

Improve spec compliance of Blob Url store: resolve entry as part of URL parsing #25226

@gterzian

Description

@gterzian

We've got a couple of wpt failures that are the result of a "race condition" of sorts between revoking and resolving a url.

[url-with-fetch.any.worker.html]
  [Revoke blob URL after creating Request, will fetch]
    expected: FAIL


[url-with-fetch.any.html]
  [Revoke blob URL after creating Request, will fetch]
    expected: FAIL

[url-in-tags-revoke.window.html]
  expected: TIMEOUT
  [Fetching a blob URL immediately before revoking it works in an iframe.]
    expected: FAIL

  [Fetching a blob URL immediately before revoking it works in an iframe navigation.]
    expected: FAIL

  [Opening a blob URL in a new window immediately before revoking it works.]
    expected: TIMEOUT

  [Opening a blob URL in a noopener about:blank window immediately before revoking it works.]
    expected: FAIL

  [Opening a blob URL in a new window by clicking an <a> tag works immediately before revoking the URL.]
    expected: FAIL

And there a few new intermittents:

  ▶ Unexpected subtest result in /FileAPI/url/url-with-fetch.any.worker.html:
  │ FAIL [expected PASS] Revoke blob URL after calling fetch, fetch should succeed
  └   → promise_test: Unhandled rejection with value: object "TypeError: Network error occurred"

  ▶ Unexpected subtest result in /FileAPI/url/url-in-tags-revoke.window.html:
  │ TIMEOUT [expected PASS] Fetching a blob URL immediately before revoking it works in <script> tags.
  └   → Test timed out

What happens in all these cases is that the resolving of the blob url happens "too late", by the time the entry has already been revoked.

"Resolving" the blob url is currently done inside scheme_fetch whereas the URL spec says this should be done as part of URL parsing, at https://url.spec.whatwg.org/#ref-for-concept-url-blob-entry.

So that's why those WPT tests expect the fetch to succeed if for example the request is created before revoking the blob url, since per the spec by then the blob url should already have been resolved, even though fetch hasn't even started yet.

In the other cases, the intermittency is due to the fact that a fetch is started on a thread-pool, while the revoking is done immediately when the FileManagerThreadMsg::RevokeBlobURL is handled by the filemanager.

So in a given task on a script event-loop, with the following operations:

  1. Start a fetch with blob url,
  2. Revoke blob url.

While the two IPC messages to the net components are sent and received in order, sometimes that fetch, running on the fetch thread pool, resolves the blob url before the subsequent revoke message is handled by the "main thread" of the net component where the filemanager is running, and sometimes it doesn't.

I think this requires changing the resolve/revoke model of the FileManagerStore, where resolving means script acquiring some sort of token from net(perhaps via a sync IPC call as in RevokeObjectURL), which would later be used in a scheme fetch and give it access to the underlying FileImpl even after the URL would have been revoked. With revoking meaning you can't acquire anymore tokens. And you would only remove the file impl from the store if they are no more outstanding tokens.

Spec for the general concept of Blob URL store: https://w3c.github.io/FileAPI/#url-model

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-content/scriptRelated to the script threadA-networkB-high-valueRepresents work that would have a big impactB-interesting-projectRepresents work that is expected to be interesting in some fashionC-has-patch

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions