Merge pull request #21429 from Snuffleupagus/getAttachmentContent-fix-unit-test

Fix the unit-tests for on-demand password handling of encrypted attachments (issue 21425)
This commit is contained in:
Jonas Jenwald 2026-06-11 15:13:46 +02:00 committed by GitHub
commit 2466a76ba4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 53 additions and 67 deletions

View File

@ -308,6 +308,27 @@ class WorkerMessageHandler {
return promise;
}
async function getPassword(ex) {
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) {
assert(
ex instanceof PasswordException,
"getPassword - must be a `PasswordException`."
);
}
const task = new WorkerTask(`PasswordException: response ${ex.code}`);
startWorkerTask(task);
try {
const res = await handler.sendWithPromise("PasswordRequest", ex);
return res.password;
} finally {
// Ensure that any `catch` handler runs *before* removing the task.
Promise.resolve().then(() => {
finishWorkerTask(task);
});
}
}
function setupDoc(data) {
function onSuccess(doc) {
ensureNotTerminated();
@ -320,18 +341,12 @@ class WorkerMessageHandler {
}
if (ex instanceof PasswordException) {
const task = new WorkerTask(`PasswordException: response ${ex.code}`);
startWorkerTask(task);
handler
.sendWithPromise("PasswordRequest", ex)
.then(function ({ password }) {
finishWorkerTask(task);
getPassword(ex)
.then(password => {
pdfManager.updatePassword(password);
pdfManagerReady();
})
.catch(function () {
finishWorkerTask(task);
.catch(() => {
handler.send("DocException", ex);
});
} else {
@ -448,36 +463,23 @@ class WorkerMessageHandler {
* Unique attachment identifier (required).
*/
async function (id) {
let passwordEx;
// Loop to prompt again after an incorrect password.
while (true) {
const password = passwordEx ? await getPassword(passwordEx) : null;
try {
if (password) {
pdfManager.updatePassword(password);
}
return await pdfManager.ensureCatalog("attachmentContent", [id]);
} catch (error) {
if (!(error instanceof PasswordException)) {
throw error;
}
const task = new WorkerTask(
`PasswordException: response ${error.code}`
);
startWorkerTask(task);
try {
const { password } = await handler.sendWithPromise(
"PasswordRequest",
error
);
try {
pdfManager.updatePassword(password);
} catch (exception) {
if (exception instanceof PasswordException) {
continue;
}
throw exception;
}
} finally {
finishWorkerTask(task);
} catch (ex) {
if (ex instanceof PasswordException) {
passwordEx = ex;
continue;
}
throw ex;
}
}
}
@ -648,23 +650,12 @@ class WorkerMessageHandler {
warn("extractPages: XRefParseException.");
}
} else if (e instanceof PasswordException) {
const task = new WorkerTask(
`PasswordException: response ${e.code}`
);
startWorkerTask(task);
try {
const { password } = await handler.sendWithPromise(
"PasswordRequest",
e
);
const password = await getPassword(e);
manager.updatePassword(password);
} catch {
isValid = false;
warn("extractPages: invalid password.");
} finally {
finishWorkerTask(task);
}
} else {
isValid = false;

View File

@ -1814,8 +1814,9 @@ describe("api", function () {
it("gets encrypted attachments when password is requested on demand", async function () {
const loadingTask = getDocument(
buildGetDocumentParams("encrypted-attachment.pdf")
buildGetDocumentParams("auth-event-ef-open.pdf")
);
const pdfDoc = await loadingTask.promise;
let passwordRequests = 0;
loadingTask.onPassword = (updatePassword, reason) => {
@ -1824,8 +1825,6 @@ describe("api", function () {
updatePassword("000000");
};
const pdfDoc = await loadingTask.promise;
const attachments = await pdfDoc.getAttachments();
const { description, filename, rawFilename } =
attachments.get("attachment.pdf");
@ -1843,8 +1842,9 @@ describe("api", function () {
it("re-prompts for encrypted attachments after incorrect passwords", async function () {
const loadingTask = getDocument(
buildGetDocumentParams("encrypted-attachment.pdf")
buildGetDocumentParams("auth-event-ef-open.pdf")
);
const pdfDoc = await loadingTask.promise;
/** @type {Array<unknown>} */
const reasons = [];
@ -1858,8 +1858,6 @@ describe("api", function () {
updatePassword("000000");
};
const pdfDoc = await loadingTask.promise;
const attachments = await pdfDoc.getAttachments();
const { description, filename, rawFilename } =
attachments.get("attachment.pdf");
@ -1886,24 +1884,21 @@ describe("api", function () {
);
let embeddedLoadingTask = null;
try {
const pdfDoc = await loadingTask.promise;
const attachments = await pdfDoc.getAttachments();
const attachment = attachments.get("attachment.pdf");
const pdfDoc = await loadingTask.promise;
const attachments = await pdfDoc.getAttachments();
const attachment = attachments.get("attachment.pdf");
expect(attachment).toBeDefined();
expect(attachment.filename).toEqual("attachment.pdf");
expect(attachment).toBeDefined();
expect(attachment.filename).toEqual("attachment.pdf");
const content = await pdfDoc.getAttachmentContent("attachment.pdf");
expect(content).toBeInstanceOf(Uint8Array);
const content = await pdfDoc.getAttachmentContent("attachment.pdf");
expect(content).toBeInstanceOf(Uint8Array);
embeddedLoadingTask = getDocument({ data: content });
const embeddedPdfDoc = await embeddedLoadingTask.promise;
expect(embeddedPdfDoc.numPages).toBe(1);
} finally {
await embeddedLoadingTask?.destroy();
await loadingTask.destroy();
}
embeddedLoadingTask = getDocument({ data: content });
const embeddedPdfDoc = await embeddedLoadingTask.promise;
expect(embeddedPdfDoc.numPages).toBe(1);
await Promise.all([embeddedLoadingTask.destroy(), loadingTask.destroy()]);
});
it("gets javascript with printing instructions (JS action)", async function () {