4786 Commits

Author SHA1 Message Date
Jonas Jenwald
6689097a0a
Merge pull request #21543 from Snuffleupagus/FakeSignatureVerifier
Add a `FakeSignatureVerifier` for development mode and TESTING builds (PR 21247 follow-up)
2026-07-05 23:20:58 +02:00
Tim van der Meij
f0818c1860
Implement a unit test for passing unsupported data types to MurmurHash3_64.update()
This commit brings the coverage of `src/shared/murmurhash3.js` to 100%.
2026-07-05 19:55:06 +02:00
calixteman
bf924ff31b
Merge pull request #21521 from calixteman/issue21520
Use `Intl.Segmenter` for the entire-word search matching
2026-07-05 19:20:36 +02:00
Tim van der Meij
e148b154cd
Merge pull request #21538 from greymoth-jp/fix/font-encodeString-fffe-fffff
Do not drop the character after U+FFFE or U+FFFF in Font.prototype.encodeString
2026-07-05 16:13:19 +02:00
Calixte Denizet
0c97aa7555
Use Intl.Segmenter for the entire-word search matching
`getCharacterType` was a port of the old `WordBreaker::GetClass`,
which has been removed and replaced with ICU4X word segmentation.
Use `Intl.Segmenter` instead, testing each match boundary on the two
adjacent grapheme clusters in isolation like Firefox's find.

It fixes #21520.
2026-07-05 14:37:21 +02:00
Jonas Jenwald
c188012280 Add a FakeSignatureVerifier for development mode and TESTING builds (PR 21247 follow-up)
Despite the `enableSignatureVerification` option/preference being enabled in development mode and TESTING builds, the lack of any `SignatureVerifier` implementation still renders the UI disabled.
This seems unfortunate, since it makes it more difficult to check that the digital signature UI works correctly:
 - That the button is visible when it's supposed to be, and that the panel can be opened/closed.
 - That the UI looks correct, w.r.t. the HTML elements and their CSS rules.
 - Currently the viewer JS code is effectively uncovered, with overall test-coverage dropping from `90` to `89` percent when PR 21247 landed.

To improve the current situation this patch adds a `FakeSignatureVerifier` class, limited to only development mode and TESTING builds, that treats every digital signature as invalid.
This allows easier manual testing, and also the addition of a few *very rudimentary* integration-tests.

*Note:* It probably wouldn't be all that difficult to add additional integration-tests for *valid* certificates, by having the test-cases instruct (during setup) the `FakeSignatureVerifier` how to respond to simulate verified certificates.
2026-07-05 13:43:25 +02:00
Tim van der Meij
330cc4f2f4
Merge pull request #21541 from Snuffleupagus/signature-api-unittests
Add API unit-tests for `getSignatures` and `getSignatureData` (PR 21247 follow-up)
2026-07-05 11:29:47 +02:00
Jonas Jenwald
ac101f0381 Add API unit-tests for getSignatures and getSignatureData (PR 21247 follow-up)
Note that PR 21247 did include "local" unit-tests, however they don't cover all of the relevant API/Worker code-paths (which is noticeable in the coverage data).
The new unit-test added here uses a PDF document already present in the test-suite, and generally speaking testing a real-world PDF shouldn't hurt.
2026-07-04 17:08:39 +02:00
Tim van der Meij
4fd232a124
Update dependencies to the most recent versions
Note that the `prettier` update introduces a handful of formatting
changes (see https://prettier.io/blog/2026/06/27/3.9.0).

Moreover, the `tsc-alias` update requires explicitly defining the root
URL in the compiler options now, otherwise it errors with `tsc-alias
error: compilerOptions.rootDir is required with implicit baseUrl` (see
https://github.com/justkey007/tsc-alias/pull/259/changes).
2026-07-04 14:49:36 +02:00
greymoth-jp
2bbf32d83d Do not drop the character after U+FFFE or U+FFFF in Font.prototype.encodeString
encodeString has the same surrogate-pair guard that encodeToXmlString had
before #21526: `unicode > 0xd7ff && (unicode < 0xe000 || unicode > 0xfffd)`.
That predicate is also true for U+FFFE and U+FFFF, which are single UTF-16
code units, not surrogate pairs. The extra `i++` then steps over the
character that follows them, so it is silently dropped from the
font-encoded output used when saving or printing a PDF.

For example, encoding a string that is U+FFFF followed by "A", with a font
that has a glyph for both, returns an encoded result ending in "A" on this
branch but drops the "A" on master.

Same fix as #21526: the correct test for a real surrogate pair is
`unicode > 0xffff`, since codePointAt only returns a value at or above
0x10000 for an actual pair. This keeps existing behavior for real surrogate
pairs (e.g. emoji) and the U+FFFD boundary, and only stops the character
after U+FFFE/U+FFFF from being dropped.

Added test/unit/fonts_spec.js, since Font.prototype.encodeString had no
direct unit test. It calls the method on a minimal fake `this` (only
toUnicode/cMap are read), since building a full Font requires a complete
properties/font-file setup that this bug doesn't depend on.
2026-07-04 21:37:12 +09:00
Tim van der Meij
c79b005db7
Merge pull request #21511 from Snuffleupagus/eslint-logical-assignment-operators
Enable the unicorn/logical-assignment-operators ESLint plugin rule
2026-07-04 13:46:55 +02:00
Tim van der Meij
9c46f48f88
Merge pull request #21526 from spokodev/w33/pdfjs-encodexml-surrogate
Do not drop the character after U+FFFE or U+FFFF in encodeToXmlString
2026-07-04 13:38:22 +02:00
Jonas Jenwald
046e68d140 Extend the unicorn/logical-assignment-operators rule to if-statements
Please see https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/logical-assignment-operators.md and https://eslint.org/docs/latest/rules/logical-assignment-operators#enforceforifstatements
2026-07-04 12:25:57 +02:00
Tim van der Meij
5b100c4509
Merge pull request #21525 from calixteman/20504_skia_followup
Apply the appearance-stream scale factor when text is shown, not on setFont
2026-07-03 20:17:53 +02:00
Tim van der Meij
cca78c1d32
Merge pull request #21475 from nicolo-ribaudo/babel-8
Update to Babel 8
2026-07-03 20:14:36 +02:00
Tim van der Meij
70c52132af
Merge pull request #21514 from nicolo-ribaudo/remove-selection-conflict-chrome
Avoid text selection workaround in modern Chromium
2026-07-03 20:10:28 +02:00
calixteman
0cc1718b02
Merge pull request #21527 from Snuffleupagus/issue-21523
Add basic support for non-embedded TrebuchetMS fonts (issue 21523)
2026-07-03 10:21:11 +02:00
calixteman
d5dafc3fb3
Merge pull request #21522 from spokodev/w32/pdfjs-escapepdfname
Fix escapePDFName producing malformed name escapes for control characters
2026-07-02 18:11:21 +02:00
Jonas Jenwald
15969fbe19 Add basic support for non-embedded TrebuchetMS fonts (issue 21523) 2026-07-02 15:13:01 +02:00
Yarchik
0aee1d5382 Do not drop the character after U+FFFE or U+FFFF in encodeToXmlString
encodeToXmlString skips surrogate pairs with the guard
`char > 0xd7ff && (char < 0xe000 || char > 0xfffd)` and then does `i++` to step
over the low surrogate. That predicate is also true for U+FFFE and U+FFFF, which
are single UTF-16 code units, not surrogate pairs. The `i++` then skips the
character that follows them, so it is silently dropped.

For example, encodeToXmlString of U+FFFF followed by "A" returned "&#xFFFF;"
instead of "&#xFFFF;A". The function serializes XML text nodes and attribute
values in xml_parser.js and xfa_object.js, so this corrupts round-tripped XML
and XFA content.

The correct test for a surrogate pair is `char > 0xffff`, since codePointAt
returns a value at or above 0x10000 only for a real pair. This preserves the
existing behavior for emoji, the U+FFFD boundary, and lone surrogates, and stops
dropping the character after U+FFFE and U+FFFF.
2026-07-02 14:03:49 +01:00
Calixte Denizet
d9999dcedd Apply the appearance-stream scale factor when text is shown, not on setFont
The font size (Tf) and the text matrix (Tm) can appear in any order in an
appearance stream. Applying the scale factor eagerly in setFont missed the
case where Tf precedes Tm (e.g. Skia-generated FreeText), yielding a wrong
guessed font size.
2026-07-02 14:51:10 +02:00
Yarchik
9710372a1b Fix escapePDFName producing malformed name escapes for control characters
escapePDFName emitted a single hex digit for character codes below 0x10
(TAB became #9, not #09). PDF 32000-1 7.3.5 requires exactly two hex digits
after #. On re-save (annotations, form fields, font names) such a Name is
written malformed and the lexer mis-parses it on reload, dropping bytes.
Pad the hex to two digits; a no-op for codes 0x10 to 0xFF.
2026-07-02 10:48:57 +01:00
calixteman
89836b76f0 Take into account the current transform when getting font size for FreeText
Fixes issue #20504.

And the text position in Arabic FreeText annotations.
2026-07-02 11:04:34 +02:00
Nicolò Ribaudo
ea43bb43fb
Avoid text selection workaround in modern Chromium
Chromium 148+ improved their selection behavior when it comes to absolutely
positioned elements, thus making text selectino in PDF.js much better.

Unfortunately this does not only mean that the workaround we currently have
for Chromium is unnecessary, but it actually become harmful. It conflicts
with Chromium's new behavior, making text selection *worse* on mobile.

As the change has been released in Chrome only a month ago, this patch keeps
the workaround for older Chromium versions. There is no easy way to
feture-detect is, so unfortunately we need to do user agent version detection.
2026-07-01 13:14:34 +02:00
Benjamin Beurdouche
07b1c625e1 Add Digital signature properties verification panel
Adds a new "Digital signature properties" doorhanger to the pdf.js
toolbar that lists every digital signature found in the opened PDF,
verifies each one (via NSS in the Firefox build through a new chrome
bridge), and shows per-signature status + certificate state.

The viewer side parses /Sig dicts in the worker
(`PDFDocument.signatures`), strict-validates the /ByteRange offsets
before slicing, and ships only signature metadata across the worker
boundary. The PKCS#7 blob and signed-data byte spans live in a
worker-side map and are fetched lazily one signature at a time via
a new `getSignatureData(id)` RPC, immediately before verification
runs, so the bytes never sit in main-thread memory for the
document's lifetime.

The panel is feature-gated by `pdfjs.enableSignatureVerification`
(true in MOZCENTRAL/TESTING, off by default in the GENERIC build).
External services expose a `createSignatureVerifier()` factory that
the Firefox build wires up to `nsIX509CertDB.asyncVerifyPKCS7Object`;
GENERIC builds return null and the toolbar button stays hidden.

UI summary:
- Toolbar button states: loading dots while in flight, then green
  check, orange `!`, or red `✕` based on the worst aggregate
  signature status.
- Doorhanger contains a banner summarising the document state, then
  one card per signature with status row + certificate row (sub-
  signatures nested under their outer revision via /ByteRange
  containment).
- Icons are mono SVGs themed via `mask-image` + `background-color`
  so they pick up light/dark/HCM via `--sig-icon-*` vars; flipped
  under RTL via `scaleX(var(--dir-factor))`. The HCM mapping reuses
  the alt-text vocabulary (ButtonFace / ButtonText / ButtonBorder /
  GrayText / AccentColor / LinkText) so this panel reads the same
  as the rest of the editor toolbar in high-contrast mode.
- All visible strings are localized via Fluent
  (`pdfjs-digital-signature-properties-*`); status row, banner, and
  certificate row use explicit lookup tables instead of generated
  ids so a grep finds them.
- Esc + outside-click close the panel through the viewer's existing
  handlers; the manager exposes `isOpen`, `close()`, and
  `shouldCloseOnClick(target)` for that.

This commit also adds a `test/pdfs/sig_corpus/` directory holding a
Python generator that produces a corpus of signed PDFs covering
every visible state of the doorhanger (verified / untrusted /
expired / invalid / unknown / multi-signature variants). The corpus
is intentionally NOT part of the automated test suite — it is a
manual-test tool. Generated `.pdf` files are gitignored; only the
generator, README, and a `user.js.example` snippet are tracked.
The generator shells out to mozilla-central's
`security/manager/tools/pycms.py` (resolved via `--mozilla-central
<path>` or the `MOZILLA_CENTRAL_SRC` env var) and the embedded test
trust anchors (`pdf-sign-ca` / `pdf-sign-ca-expired`), gated by
`security.pdf_signature_verification.enable_test_trust_anchors` so
the test certificates never validate in shipping Firefox.
2026-06-30 13:25:09 +02:00
Nicolò Ribaudo
b9609d0365
Update to Babel 8 2026-06-30 10:45:15 +02:00
Calixte Denizet
3ccc3ec65c Add support for Sound annotations playing embedded audio
Wrap uncompressed PCM sound streams (Raw/Signed, 8/16-bit, mono/stereo)
in WAV and play them through the shared media overlay.
2026-06-29 12:30:48 +02:00
Tim van der Meij
195226e3a6
Merge pull request #21500 from calixteman/bug2050191
Disable selection rendering when backdrop-filter is unsupported (bug 2050191)
2026-06-26 20:12:48 +02:00
Tim van der Meij
d8526132f5
Merge pull request #21487 from calixteman/issue17333
Render non-empty glyph 0 for char code 0
2026-06-26 20:08:51 +02:00
Jonas Jenwald
beb332a245 Change issue17906 to test "forms" rendering
Looking at the coverage data the code-path added in PR 17908 isn't actually covered by tests; note 10844326c7/blob/src/core/annotation.js (L1250)
2026-06-25 11:59:57 +02:00
Calixte Denizet
7f9c54a259 Disable selection rendering when backdrop-filter is unsupported (bug 2050191)
Selection rendering relies on the CSS backdrop-filter property, so it must
be gated on browser support for it.
2026-06-24 20:16:44 +02:00
Jonas Jenwald
f07a106529 Include the catalog instance in the annotationGlobals data
The `FileAttachmentAnnotation` and `MediaAnnotation` code needs to (synchronously) access a `catalog` method, which leads to unnecessarily verbose code.
This can be avoided by including the `catalog` instance in the `annotationGlobals` data, which is safe since it already includes data that's fetched asynchronously from the `catalog` instance.
2026-06-24 10:42:38 +02:00
calixteman
078b96229d
Render non-empty glyph 0 for char code 0
It fixes #17333.
2026-06-23 21:38:57 +02:00
Calixte Denizet
d8ea2afe47 Add support for Screen annotations playing embedded media
Screen annotations whose rendition action resolves to an embedded audio/video
file now play through the same play-button overlay as RichMedia.
Factor the shared resolution logic into a MediaAnnotation base (used by both RichMedia and Screen).

It fixes #6078 and #2787.
2026-06-23 20:48:35 +02:00
Calixte Denizet
d537f5ba4b
Add support for RichMedia annotations
Render `/Subtype /RichMedia` annotations so embedded video and audio can
be played in the viewer.

The core layer parses the `RichMediaContent` dictionary to locate the
primary playable asset and its MIME type. The display layer overlays a
play button on the annotation's poster; clicking it swaps in a
`<video>`/`<audio>` element backed by a `blob:` URL. Presentation mode
lets events reach the media controls instead of advancing the page.

It fixes #2787.
2026-06-22 21:27:52 +02:00
Tim van der Meij
b6469341c1
Merge pull request #21485 from calixteman/bug2046659
Use AES256 for V=5 documents with a mislabeled AESV2 crypt filter (bug 2046659)
2026-06-22 20:44:48 +02:00
Tim van der Meij
7ac6dff4b7
Merge pull request #21483 from calixteman/issue21430
Reset alpha before drawing a colored glyph in type 3 font
2026-06-22 20:40:55 +02:00
Calixte Denizet
7f7e63333d Use AES256 for V=5 documents with a mislabeled AESV2 crypt filter (bug 2046659)
Some producers wrongly set the crypt filter CFM to AESV2 for V=5 documents;
per the spec these must be decrypted with AES256 using the file encryption key directly.
2026-06-22 14:54:24 +02:00
calixteman
1ddf6449ac
Merge pull request #21478 from calixteman/comb-field-vertical-centering
Vertically center the glyphs in comb text fields
2026-06-22 09:57:55 +02:00
calixteman
623e6d9476
Reset alpha before drawing a colored glyph in type 3 font
It fixes #21430.
2026-06-21 23:06:43 +02:00
Calixte Denizet
34516bcec3 Vertically center the glyphs in comb text fields 2026-06-20 18:47:24 +02:00
Jonas Jenwald
bade1f3190 Add a unit-test for relative URI actions specified as /Name instances
The following branch was added to fix issue 4159, however looking at the coverage data it's not actually tested; see 59df671552/src/core/catalog.js (L1866-L1869) and 59df671552/blob/src/core/catalog.js (L1866)
2026-06-19 23:58:50 +02:00
calixteman
07d4c1018a
Avoid too long BlueScale value when rewriting a CFF font
It fixes #21466.
2026-06-18 20:48:13 +02:00
Calixte Denizet
9d9fb06d7f Re-derive annotation attachment content from the xref after cleanup
Annotation-local attachments (those not in the catalog `/Names` tree) were
resolved through a dictionary cache that `Catalog.cleanup` clears, so their
content became unreachable once the idle cleanup had run.

Encode the reference of the embedded content in the attachment id and re-fetch
it from the xref on demand instead of caching the dictionary, so the content
stays reachable without anything having to survive cleanup.

It fixes a regression introduced by #21351.
2026-06-18 16:03:32 +02:00
Calixte Denizet
ece1e2ed0c Add a 'supportsDownloading' browser option to gate saving/downloading
Introduces a 'supportsDownloading' browser option (defaulting to false)
that lets embedders disable the save/download paths entirely. When
disabled:
  - the toolbar and secondary-toolbar download buttons are hidden;
  - PDFViewerApplication.{download,save,downloadOrSave} and the
    "beforeunload" save prompt bail out early;
  - the BaseDownloadManager helpers (download, downloadData,
    openOrDownloadData) and the Firefox/generic _triggerDownload
    implementations no-op.
2026-06-18 14:51:32 +02:00
Jonas Jenwald
2ed018ec2d
Merge pull request #21460 from Snuffleupagus/autolinking-check-every-LinkAnnotation
Check every LinkAnnotation when testing if inferred links overlap (issue 21458)
2026-06-16 22:32:07 +02:00
calixteman
eae42379f2
Merge pull request #21462 from calixteman/bluescale-small-zones
Don't clamp BlueScale up when a font genuinely has small zones
2026-06-16 21:52:25 +02:00
calixteman
d28030f838
Merge pull request #21463 from calixteman/fix_unit_test
Adjust the 'BaseException' unit-test for the 'Error.stack' changes in Firefox
2026-06-16 21:43:49 +02:00
Jonas Jenwald
cbefb334fd Check every LinkAnnotation when testing if inferred links overlap (issue 21458)
Currently we only check LinkAnnotations with URLs, but completely ignore e.g. internal destinations, named actions, attachments, SetOCGState actions, JS actions, and ResetForm actions when testing if inferred links overlap any existing annotation.
This seems conceptually wrong, since it may easily break intended functionality by overlaying the *correct* DOM element with an inferred link (as was the case in issue 21458).
2026-06-16 21:35:44 +02:00
Calixte Denizet
5432642250 Adjust the 'BaseException' unit-test for the 'Error.stack' changes in Firefox
Firefox 154 no longer walks the prototype chain in the `Error.stack`
getter, so `BaseException`-derived instances return an empty string
rather than the prototype `Error`'s stack (see bug 1946559).
2026-06-16 21:30:41 +02:00