Merge pull request #10334 from Snuffleupagus/OpenAction-dest

[api-minor] Add support for OpenAction destinations (issue 10332)
This commit is contained in:
Tim van der Meij 2018-12-23 20:49:50 +01:00 committed by GitHub
commit 103f4616ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 99 additions and 10 deletions

View File

@ -117,6 +117,10 @@
], ],
"default": 0 "default": 0
}, },
"disableOpenActionDestination": {
"type": "boolean",
"default": true
},
"disablePageLabels": { "disablePageLabels": {
"type": "boolean", "type": "boolean",
"default": false "default": false

View File

@ -392,6 +392,28 @@ class Catalog {
return shadow(this, 'pageMode', pageMode); return shadow(this, 'pageMode', pageMode);
} }
get openActionDestination() {
const obj = this.catDict.get('OpenAction');
let openActionDest = null;
if (isDict(obj)) {
// Convert the OpenAction dictionary into a format that works with
// `parseDestDictionary`, to avoid having to re-implement those checks.
const destDict = new Dict(this.xref);
destDict.set('A', obj);
const resultObj = { url: null, dest: null, };
Catalog.parseDestDictionary({ destDict, resultObj, });
if (Array.isArray(resultObj.dest)) {
openActionDest = resultObj.dest;
}
} else if (Array.isArray(obj)) {
openActionDest = obj;
}
return shadow(this, 'openActionDestination', openActionDest);
}
get attachments() { get attachments() {
const obj = this.catDict.get('Names'); const obj = this.catDict.get('Names');
let attachments = null; let attachments = null;

View File

@ -531,6 +531,10 @@ var WorkerMessageHandler = {
return pdfManager.ensureCatalog('pageMode'); return pdfManager.ensureCatalog('pageMode');
}); });
handler.on('getOpenActionDestination', function(data) {
return pdfManager.ensureCatalog('openActionDestination');
});
handler.on('GetAttachments', handler.on('GetAttachments',
function wphSetupGetAttachments(data) { function wphSetupGetAttachments(data) {
return pdfManager.ensureCatalog('attachments'); return pdfManager.ensureCatalog('attachments');

View File

@ -650,6 +650,14 @@ class PDFDocumentProxy {
return this._transport.getPageMode(); return this._transport.getPageMode();
} }
/**
* @return {Promise} A promise that is resolved with an {Array} containing the
* destination, or `null` when no open action is present in the PDF file.
*/
getOpenActionDestination() {
return this._transport.getOpenActionDestination();
}
/** /**
* @return {Promise} A promise that is resolved with a lookup table for * @return {Promise} A promise that is resolved with a lookup table for
* mapping named attachments to their content. * mapping named attachments to their content.
@ -2167,6 +2175,11 @@ class WorkerTransport {
return this.messageHandler.sendWithPromise('GetPageMode', null); return this.messageHandler.sendWithPromise('GetPageMode', null);
} }
getOpenActionDestination() {
return this.messageHandler.sendWithPromise('getOpenActionDestination',
null);
}
getAttachments() { getAttachments() {
return this.messageHandler.sendWithPromise('GetAttachments', null); return this.messageHandler.sendWithPromise('GetAttachments', null);
} }

View File

@ -650,6 +650,24 @@ describe('api', function() {
}).catch(done.fail); }).catch(done.fail);
}); });
it('gets default open action destination', function(done) {
var loadingTask = getDocument(buildGetDocumentParams('tracemonkey.pdf'));
loadingTask.promise.then(function(pdfDocument) {
return pdfDocument.getOpenActionDestination();
}).then(function(dest) {
expect(dest).toEqual(null);
loadingTask.destroy().then(done);
}).catch(done.fail);
});
it('gets non-default open action destination', function(done) {
doc.getOpenActionDestination().then(function(dest) {
expect(dest).toEqual([{ num: 15, gen: 0, }, { name: 'FitH', }, null]);
done();
}).catch(done.fail);
});
it('gets non-existent attachments', function(done) { it('gets non-existent attachments', function(done) {
var promise = doc.getAttachments(); var promise = doc.getAttachments();
promise.then(function (data) { promise.then(function (data) {

View File

@ -867,7 +867,9 @@ let PDFViewerApplication = {
// Since the `setInitialView` call below depends on this being resolved, // Since the `setInitialView` call below depends on this being resolved,
// fetch it early to avoid delaying initial rendering of the PDF document. // fetch it early to avoid delaying initial rendering of the PDF document.
let pageModePromise = pdfDocument.getPageMode().catch( const pageModePromise = pdfDocument.getPageMode().catch(
function() { /* Avoid breaking initial rendering; ignoring errors. */ });
const openActionDestPromise = pdfDocument.getOpenActionDestination().catch(
function() { /* Avoid breaking initial rendering; ignoring errors. */ }); function() { /* Avoid breaking initial rendering; ignoring errors. */ });
this.toolbar.setPagesCount(pdfDocument.numPages, false); this.toolbar.setPagesCount(pdfDocument.numPages, false);
@ -923,8 +925,17 @@ let PDFViewerApplication = {
}).catch(() => { /* Unable to read from storage; ignoring errors. */ }); }).catch(() => { /* Unable to read from storage; ignoring errors. */ });
Promise.all([ Promise.all([
storePromise, pageModePromise, storePromise, pageModePromise, openActionDestPromise,
]).then(async ([values = {}, pageMode]) => { ]).then(async ([values = {}, pageMode, openActionDest]) => {
if (openActionDest && !this.initialBookmark &&
!AppOptions.get('disableOpenActionDestination')) {
// Always let the browser history/document hash take precedence.
this.initialBookmark = JSON.stringify(openActionDest);
// TODO: Re-factor the `PDFHistory` initialization to remove this hack
// that's currently necessary to prevent weird initial history state.
this.pdfHistory.push({ explicitDest: openActionDest,
pageNumber: null, });
}
const initialBookmark = this.initialBookmark; const initialBookmark = this.initialBookmark;
// Initialize the default values, from user preferences. // Initialize the default values, from user preferences.
const zoom = AppOptions.get('defaultZoomValue'); const zoom = AppOptions.get('defaultZoomValue');

View File

@ -48,6 +48,11 @@ const defaultOptions = {
value: false, value: false,
kind: OptionKind.VIEWER, kind: OptionKind.VIEWER,
}, },
disableOpenActionDestination: {
/** @type {boolean} */
value: true,
kind: OptionKind.VIEWER,
},
disablePageLabels: { disablePageLabels: {
/** @type {boolean} */ /** @type {boolean} */
value: false, value: false,

View File

@ -16,6 +16,7 @@
"renderer": "canvas", "renderer": "canvas",
"renderInteractiveForms": false, "renderInteractiveForms": false,
"enablePrintAutoRotate": false, "enablePrintAutoRotate": false,
"disableOpenActionDestination": true,
"disablePageMode": false, "disablePageMode": false,
"disablePageLabels": false, "disablePageLabels": false,
"scrollModeOnLoad": 0, "scrollModeOnLoad": 0,

View File

@ -94,7 +94,7 @@ class IPDFHistory {
/** /**
* @param {Object} params * @param {Object} params
*/ */
push({ namedDest, explicitDest, pageNumber, }) {} push({ namedDest = null, explicitDest, pageNumber, }) {}
pushCurrentPosition() {} pushCurrentPosition() {}

View File

@ -158,16 +158,27 @@ class PDFHistory {
* Push an internal destination to the browser history. * Push an internal destination to the browser history.
* @param {PushParameters} * @param {PushParameters}
*/ */
push({ namedDest, explicitDest, pageNumber, }) { push({ namedDest = null, explicitDest, pageNumber, }) {
if (!this.initialized) { if (!this.initialized) {
return; return;
} }
if ((namedDest && typeof namedDest !== 'string') || if (namedDest && typeof namedDest !== 'string') {
!Array.isArray(explicitDest) || console.error('PDFHistory.push: ' +
!(Number.isInteger(pageNumber) && `"${namedDest}" is not a valid namedDest parameter.`);
pageNumber > 0 && pageNumber <= this.linkService.pagesCount)) {
console.error('PDFHistory.push: Invalid parameters.');
return; return;
} else if (!Array.isArray(explicitDest)) {
console.error('PDFHistory.push: ' +
`"${explicitDest}" is not a valid explicitDest parameter.`);
return;
} else if (!(Number.isInteger(pageNumber) &&
pageNumber > 0 && pageNumber <= this.linkService.pagesCount)) {
// Allow an unset `pageNumber` if and only if the history is still empty;
// please refer to the `this._destination.page = null;` comment above.
if (pageNumber !== null || this._destination) {
console.error('PDFHistory.push: ' +
`"${pageNumber}" is not a valid pageNumber parameter.`);
return;
}
} }
let hash = namedDest || JSON.stringify(explicitDest); let hash = namedDest || JSON.stringify(explicitDest);