749 Commits

Author SHA1 Message Date
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
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
2550b91be9 Resolve checkbox/radio export values from the 'Opt' entry
For checkbox and radio button fields, the export value can differ from the
appearance-state name: the field's inheritable `Opt` array holds the real
export values (used for non-Latin text, or values shared between buttons).
We previously exposed the appearance-state name as the export value.
2026-06-15 18:23:26 +02:00
Tim van der Meij
8560125056
Merge pull request #21448 from timvandermeij/comment-intermittent
Fix intermittent failure in the `must check that the comment sidebar is resizable` comment integration test
2026-06-14 16:35:20 +02:00
Jonas Jenwald
2dc73ad2a7 Collect coverage data from all workers when closing integration-tests
The "Merge PDF" integration-tests will (indirectly) invoke `PDFViewerApplication.open` as part of loading the new PDF document, which will end up creating a new `PDFWorker` instance.
Currently worker coverage is only collected at the end of each integration-test, which means that in these cases we miss the coverage data from any "previous" workers.
2026-06-14 13:27:06 +02:00
Jonas Jenwald
feec28583d Add an integration-test for merging a password-protected PDF
Looking at the coverage data the password-handling part of the merge functionality wasn't being tested; see e75a7cfd62/blob/src/core/worker.js (L652)
2026-06-14 13:17:33 +02:00
Jonas Jenwald
e1c930adfe Add an integration-test for merging a corrupt PDF
Currently when opening a PDF document the following code is used, where `checkFirstPage`/`checkLastPage` helps detect XRef corruption; note 86a18bd5fe/src/core/worker.js (L167-L176)

However when merging a PDF into an existing document the parsing is only "partial"; note 86a18bd5fe/src/core/worker.js (L632-L634)

It seems a little strange to not support corrupt PDFs in a consistent manner in the code-base, hence this patch adds a new `BasePdfManager` helper that handles all the relevant parsing/checking and re-uses that when merging PDFs.
2026-06-14 09:49:23 +02:00
Tim van der Meij
d305b542df
Fix intermittent failure in the must check that the comment sidebar is resizable comment integration test
We use the generic `page.mouse.move(x, y, { steps }` API, but that purely
performs the mouse move steps without having knowledge about if/how the
application handles any events caused by it, so it doesn't wait for the
sidebar to render before moving on. This causes intermittent failures if
the sidebar didn't get enough time to render before the next mouse move
is initiated (which can happen in slower environments).

This commit fixes the issue by doing the mouse move steps ourselves and
by waiting for a browser trip between each of them to make sure that the
sidebar got a chance to render.

Fixes #21447.
Relates to #21044 / #21045 / 24e5377.
2026-06-13 21:32:00 +02:00
Calixte Denizet
069b757998 Use the checkboxes and radio button appearances as defined in the pdf to render them in the annotation layer (bug 1802506)
The idea is to generate two operator lists for the Yes/Off states and render them on a separate canvas.
These canvases are then attached the annotation and we modify their display depending on the input state.

It fixes #18021.
2026-06-12 20:10:56 +02:00
Calixte Denizet
5ca6026d80
Drop 'unsafe-inline' from the CSP style-src directives
The print service injected the per-PDF `@page { size }` rule as an inline
<style> element, which required 'unsafe-inline' on style-src-elem.

Inject it through a constructable CSSStyleSheet attached to
document.adoptedStyleSheets instead. Constructable stylesheets aren't
subject to style-src's inline restrictions in browsers.
2026-06-09 22:08:08 +02:00
Calixte Denizet
ecd43bc8e1 Fix form fields with their own canvas updated on non-rendered pages
When a read-only field (which has its own canvas) is updated by the
sandbox while its page isn't rendered, showElementAndHideCanvas
isn't called, so once the page is finally rendered the field still
shows its outdated canvas instead of the new value.

Replace the imperative canvas/element toggling with a `sandboxModified`
class, set from the annotation storage both at render time and on
sandbox updates, and let the CSS show the element and hide the canvas.
2026-06-08 17:22:11 +02:00
Jonas Jenwald
ae30748956 Add basic integration-tests for the PDFCursorTools functionality 2026-06-06 14:32:15 +02:00
Titus Wormer
4db9e45b8c
Add support for /AuthEvent, on-demand decryption
Normally entire PDFs are encrypted (or not).
But it is also possible to only encrypt attachments.
It is then also possible to *only* prompt for a password when the user opens
them.

In the existing flow, prompting for passwords happens because things are decrypted.
A specific error is thrown, caught, and the user is prompted.
To keep this flow working, this PR changes to decrypting attachments on demand,
instead of eagerly.
This sounds logical: to not read attachments on startup.

I’ve extensively tested this, not only with regular attachments, but also with outline items
and attachments in annotations.

This PR builds on GH-21234.
It’s an alternative to the naïve GH-20732.

Closes GH-20049.
2026-06-03 16:44:57 +02:00
Tim van der Meij
e9ee61f67c
Merge pull request #21347 from calixteman/issue21240
Restore editor layer state for unchanged pages after page mutations
2026-06-02 20:08:14 +02:00
Tim van der Meij
27b345a61e
Merge pull request #21361 from timvandermeij/is-canvas-monochrome
Fix intermittent failure in the "must check that a freetext is still here after having updated it and scroll the doc" freetext editor integration test
2026-06-02 20:01:24 +02:00
Jonas Jenwald
4e6b7be4d7 Add an integration-test for clicking on internal links in presentation mode 2026-06-01 14:25:55 +02:00
Tim van der Meij
add30f3ca0
Fix intermittent failure in the "must check that a freetext is still there after having updated it and scroll the doc" freetext editor integration test
The problem is that we screenshot the page itself rather than the
canvas, even though we specifically care about the latter according to
the comment, which means that we manually have to take care of hiding and
showing the annotation editor. This is problematic because even though
we signal that the annotation editor should be hidden, we don't wait
until that is actually done, which leads to a situation where we can
take the screenshot before the annotation editor is actually invisible
in the view.

This commit fixes the issue by screenshotting the canvas instead, which
avoids the need for manually hiding/showing the annotation editor. This
makes the test less fragile, and matches other tests better.
2026-05-31 11:36:44 +02:00
Jonas Jenwald
74db085794 Re-factor how "internal" EventBus listeners are handled in the viewer
Currently the viewer uses semi-private `EventBus.prototype.{_on, _off}` methods, to try and ensure that all internal viewer state is updated *before* any "external" listeners are invoked.
For all use-cases outside of the viewer, e.g in the integration-tests, the `EventBus.prototype.{on, off}` methods are supposed to be used instead.

Unfortunately this isn't currently enforced in any way, except (hopefully) during review, and generally speaking it's not really possible to prevent the semi-private methods being used (e.g. by third-party users).
Hence this patch adds a new `INTERNAL_EVT` property which is *not* exposed anywhere (neither in the API nor globally), and whose value is generated at build-time, that the viewer uses to mark its `EventBus` listeners are internal.
This allows us to remove the semi-private `EventBus` methods, which helps to simplify that class a little bit.
2026-05-29 22:11:58 +02:00
Calixte Denizet
600986b51d Allow inserting an image as a new page when editing a PDF
Image files dropped on or selected via the thumbnail viewer's
"add file" picker are now accepted alongside PDFs and inserted
as synthetic pages sized to the document's modal page dimensions.

The image-encoding helper previously embedded in StampAnnotation has
moved to src/core/editor/pdf_images.js so it can be shared between
stamp annotations and page synthesis.
2026-05-28 22:11:13 +02:00
Calixte Denizet
8e6e35473f Restore editor layer state for unchanged pages after page mutations
It fixes #21240.
2026-05-26 22:27:35 +02:00
Calixte Denizet
6b92ad5924 Allow merging several PDFs at once via the picker or drag-and-drop 2026-05-25 21:09:42 +02:00
Tim van der Meij
d1c85f87f7
Merge pull request #21330 from calixteman/fix_regex
Enable 'eslint-plugin-regexp' and fix existing findings
2026-05-25 18:22:21 +02:00
calixteman
164ffb9042
Merge pull request #21321 from danyalahmed1995/fix/issue-21259-text-layer-spacing
Prevent inherited spacing from affecting text layer
2026-05-25 14:36:22 +02:00
Calixte Denizet
7bda0fc97c Enable 'eslint-plugin-regexp' and fix existing findings
Enable the recommended preset and fix or per-line-disable the 78
findings it surfaces. Most are equivalent rewrites, intentional
patterns (control chars, the whatwg email regex, autolinker URL regex)
keep their behavior via targeted disables.
2026-05-25 14:31:55 +02:00
Danyal Ahmed
4ee9c39fc8 Prevent inherited spacing from affecting text layer
Fixes #21259.

Reset letter-spacing and word-spacing on the text layer and hidden measurement canvas so inherited page styles do not affect text layer alignment. Add an integration regression test for inherited spacing.
2026-05-24 23:56:23 +05:00
Jonas Jenwald
057507f6ce Use Uint8Array.fromBase64 in the test/integration/highlight_editor_spec.mjs file 2026-05-24 10:56:51 +02:00
Tim van der Meij
52d574c539
Merge pull request #21306 from calixteman/dnd_pdf_merging
Allow merging a PDF by dropping it onto the thumbnail viewer
2026-05-21 21:01:42 +02:00
Tim van der Meij
9b5cd3db64
Merge pull request #21304 from Snuffleupagus/PdfTextExtractor-tests
Add basic integration-tests for the `PdfTextExtractor` class
2026-05-21 20:27:53 +02:00
Tim van der Meij
42db304268
Merge pull request #21305 from Snuffleupagus/integration-test-EventBus-on
Don't use "internal" `EventBus` methods in the integration-tests
2026-05-21 20:17:28 +02:00
Calixte Denizet
0f90987927 Fix 'Select all' after #20981 2026-05-21 16:39:34 +02:00
Calixte Denizet
d79043b3af Allow merging a PDF by dropping it onto the thumbnail viewer
Drop an external PDF anywhere in the views-manager thumbnail
sidebar to merge it at the cursor, rather than always inserting
after the current page via the "Add file" button.

The drop reuses the blue separator from page-move drag so the
user can see exactly where the inserted pages will land, and the
merge path is shared with the existing picker so post-merge
selection/current-page behavior stays consistent.
2026-05-20 18:06:55 +02:00
Jonas Jenwald
429b469ecb Add basic integration-tests for the PdfTextExtractor class 2026-05-20 17:26:50 +02:00
Jonas Jenwald
abe8b564a3 Don't use "internal" EventBus methods in the integration-tests
This way *guarantees* that any and all internal viewer state has been updated first, before any test-specific code runs.
2026-05-20 16:39:21 +02:00
calixteman
5a4d93a238
Merge pull request #20981 from wooorm/wooorm/hcm
Make text selection more visible (bug 1879559)
2026-05-20 15:49:01 +02:00
Titus Wormer
957e004e38
Make text selection more visible (bug 1879559)
References <https://bugzilla.mozilla.org/show_bug.cgi?id=1879559>
(“In HCM, the text selection is barely visible”).

Continues work from @calixteman who had a partial patch.

This PR improves viewer text-selection highlighting by rendering
selection shapes in the draw layer.

* add selection overlay rendering in the draw layer
  * significant code relates to selections spanning multiple text
    layers/pages, and edges/end-of-content boundaries
* clear selection on rotate/scale/scroll/spread changes

My main question is: how should it appear?
I don’t have access to the Figma file linked on bugzilla.

In the CSS (`draw_layer-builder.css`) there are 3 blocks:

* default
* `@supports` for browsers supporting `backdrop-filter`
* `forced-colors` mode

So it’s possible to design for those (or more).
Personally, the `backdrop-filter: invert(1)` is the most contrast,
so perhaps it’s better to use something else as the default,
and to use `invert(1)` if high contrast mode is used (maybe with a
`prefers-contrast` media query instead)?
2026-05-19 21:10:12 +02:00
Tim van der Meij
0d69cc4dcf
Introduce integration tests for the presentation mode functionality
This commit provides coverage for the happy flows of basic operations
like entering/exiting and changing pages.
2026-05-18 20:52:00 +02:00
Tim van der Meij
00af75905f
Merge pull request #21295 from Snuffleupagus/PDFDocumentProperties-more-tests
Add more integration-tests, with multi-page documents, for the `PDFDocumentProperties` dialog
2026-05-18 20:24:41 +02:00
calixteman
abb8e31408
Merge pull request #21261 from calixteman/bug1960363
Add a Content-Security-Policy to pdf.js' viewer.html (bug 1960363)
2026-05-18 18:24:38 +02:00
Jonas Jenwald
1e62f01773 Improve handling of corrupt pages in the PDFDocumentProperties dialog
If the active page is corrupt that currently results in the entire dialog being "blank", thus providing no information, which seems unfortunate and it's easy enough to only skip `pageSizeField` in that rare case.
2026-05-18 17:38:43 +02:00
Jonas Jenwald
e05b6d6f59 Add more integration-tests, with multi-page documents, for the PDFDocumentProperties dialog
Improve test coverage for multi-page documents, to ensure that:
 - Unnecessary re-parsing is avoided where possible.
 - Rotation, in the viewer, is handled correctly.
 - Different page sizes are handled correctly.
2026-05-18 14:24:05 +02:00
Jonas Jenwald
1e9e8fad7e Add helper functions for opening/closing the document properties dialog during testing
This reduces duplication in the various integration-tests.
2026-05-18 13:31:26 +02:00
Tim van der Meij
2fb2bc13e0
Merge pull request #21275 from timvandermeij/integration-tests-optimize
Optimize runtime and memory usage of the integration tests
2026-05-17 20:41:43 +02:00
Tim van der Meij
f2bf57f444
Merge pull request #21288 from timvandermeij/unskip-test
Enable the `must check that an existing highlight is ignored on hovering` integration test on Windows
2026-05-17 20:19:42 +02:00
Jonas Jenwald
2cef900834 Add an integration-test for documents without contentLength available in the PDFDocumentProperties dialog 2026-05-17 16:55:48 +02:00
Tim van der Meij
af65d7f930
Enable the must check that an existing highlight is ignored on hovering integration test on Windows
It looks like this test passes consistently again, most likely after a
combination of browser/Puppeteer/configuration updates and the completed
switch to the WebDriver BiDi protocol.

Fixes #20136.
2026-05-17 14:47:14 +02:00
Jonas Jenwald
afa9b6ef9b Add an integration-test for the page-name fuzzy matching in the PDFDocumentProperties dialog
Also, test that closing the dialog works correctly.
2026-05-17 14:40:09 +02:00
Tim van der Meij
600a4bb1ee
Fix missing page closing for two viewer integration tests
This caused the tab to remain open after the tests ran, which meant
that a total of ~120 MB of memory was not being freed.
2026-05-16 19:30:42 +02:00
Tim van der Meij
62b88aa56e
Use Puppeteer's ElementHandle.boundingBox() API in the integration tests
The custom solution for obtaining the bounding box of a given element
that we have now was necessary during the original introduction of the
integration tests because at the time the `ElementHandle.boundingBox()`
API in Puppeteer didn't work correctly in Chrome.

However, `getRect`, where this is used, is a hot utility function
because most tests call it multiple times, either directly or indirectly
via other utility functions, and it turns out that the approach we use
is slower than the native `ElementHandle.boundingBox()` API.

Fortunately, most likely after a combination of Chrome/Puppeteer updates
and the conversion to the formalized WebDriver BiDi protocol the custom
solution is no longer necessary because all tests pass without it too,
so this commit converts `getRect` to use `ElementHandle.boundingBox()`
instead to speed up the tests.
2026-05-16 19:30:34 +02:00
Calixte Denizet
94de952b65
Add a Content-Security-Policy to pdf.js' viewer.html (bug 1960363) 2026-05-14 12:50:07 +02:00
Tim van der Meij
26dc195a65
Collect coverage information for the integration tests
Note that for the integration tests the coverage information ends up
being processed in the Node.js context where `window` is not available,
so we use `globalThis` instead for the function that merges individual
test's coverage information into the global object because that is
available in all contexts we support. For clarity we also rename said
function since we're not exclusively dealing with `window` nor worker
data anymore.
2026-05-14 12:34:12 +02:00