Skip to content

SingleFile snapshot capture fails in Safari Lockdown Mode, and save-as-webpage reports the whole save as failed #636

Description

@dstillman

Reported at https://forums.zotero.org/discussion/133295/ (Safari 27.0 on macOS 27 beta, Lockdown Mode enabled):

TypeError: undefined is not a constructor (evaluating 'new AC')

The analysis below is from Claude, based on code reading -- not yet reproduced under Lockdown Mode.

AC is globalThis.FileReader in the minified lib/SingleFile/single-file.js. Lockdown Mode disables the File API and FileReader API entirely (WebKit blog), and this evidently applies to extension content scripts running in locked-down pages, not just the page world.

SingleFile uses FileReader.readAsDataURL() to convert every inlined binary subresource (images, fonts, favicons) to a data: URI, so capture fails on essentially any real page: the first binary resource hits new FileReader with the constructor missing and the capture rejects.

Impact

The severity depends on the save path:

  • Translator save to client -- _executeSingleFile() (src/common/itemSaver.js) catches the error, so the item and PDF/EPUB attachments save normally and only the snapshot attachment shows as failed. Acceptable.
  • Save as webpage to client -- in _saveAsWebpage() (src/common/inject/pageSaving.js), the saveSnapshot connector call succeeds and creates the item in Zotero, but _saveSingleFile() then throws inside the same try block, so the progress window reports unexpectedError for the entire save. On a page without a translator, every save appears to fail even though the item was actually created. This likely reads as "the connector is unusable" to a Lockdown Mode user.
  • Server save -- _saveAttachmentsToServer() (src/common/itemSaver.js) calls retrievePageData() outside the per-attachment try/catch, so a capture failure abandons the whole attachment loop, not just the snapshot.

Proposed fixes

  1. Shim FileReader for SingleFile -- readAsDataURL is replaceable with a manual base64 encoding (blob.arrayBuffer() + btoa + data:<mime>;base64, prefix). A small shim defined before single-file.js is injected would make snapshots actually work under Lockdown Mode. (Also worth reporting upstream, since this presumably breaks SingleFile in every browser's Lockdown Mode equivalent.) Needs testing to confirm nothing else SingleFile uses is stripped in Lockdown Mode.
  2. Graceful degradation regardless -- restructure the paths above so a snapshot-capture failure fails only the snapshot: wrap the _saveSingleFile() calls in saveAsWebpage() in their own try/catch that marks the snapshot row failed but still reports the save as successful, and move the retrievePageData() call in _saveAttachmentsToServer() inside the per-attachment error handling.

The forum report also includes duplicate-variable errors from content-script re-injection and _locales/en_US fallback noise -- those are separate issues.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions