From 1c8cacd6b941d3076d85c4a8b3315dd775c7bc8b Mon Sep 17 00:00:00 2001 From: Rob Wu Date: Sun, 14 Jan 2018 00:34:46 +0100 Subject: [PATCH] Limit PDFFetchStream to http(s) in the Chrome extension The `fetch` API is only supported for http(s), even in Chrome extensions. Because of this limitation, we should use the XMLHttpRequest API when the requested URL is not a http(s) URL. Fixes #9361 --- src/display/api.js | 26 ++++++++++++++++++-------- src/pdf.js | 34 +++++++++++++++++++++++++++------- test/unit/jasmine-boot.js | 8 ++++++-- 3 files changed, 51 insertions(+), 17 deletions(-) diff --git a/src/display/api.js b/src/display/api.js index 2c5b339cb89ae..828985b28fc1a 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -83,15 +83,25 @@ if (typeof PDFJSDev !== 'undefined' && }) : null; } -/** @type IPDFStream */ -var PDFNetworkStream; +/** + * @typedef {function} IPDFStreamFactory + * @param {DocumentInitParameters} params The document initialization + * parameters. The "url" key is always present. + * @return {IPDFStream} + */ + +/** @type IPDFStreamFactory */ +var createPDFNetworkStream; /** - * Sets PDFNetworkStream class to be used as alternative PDF data transport. - * @param {IPDFStream} cls - the PDF data transport. + * Sets the function that instantiates a IPDFStream as an alternative PDF data + * transport. + * @param {IPDFStreamFactory} pdfNetworkStreamFactory - the factory function + * that takes document initialization parameters (including a "url") and returns + * an instance of IPDFStream. */ -function setPDFNetworkStreamClass(cls) { - PDFNetworkStream = cls; +function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) { + createPDFNetworkStream = pdfNetworkStreamFactory; } /** @@ -252,7 +262,7 @@ function getDocument(src) { if (rangeTransport) { networkStream = new PDFDataTransportStream(params, rangeTransport); } else if (!params.data) { - networkStream = new PDFNetworkStream(params); + networkStream = createPDFNetworkStream(params); } var messageHandler = new MessageHandler(docId, workerId, worker.port); @@ -2344,7 +2354,7 @@ export { PDFWorker, PDFDocumentProxy, PDFPageProxy, - setPDFNetworkStreamClass, + setPDFNetworkStreamFactory, version, build, }; diff --git a/src/pdf.js b/src/pdf.js index b0e90b3aab699..8ef2263dce644 100644 --- a/src/pdf.js +++ b/src/pdf.js @@ -30,19 +30,39 @@ var pdfjsDisplayDOMUtils = require('./display/dom_utils.js'); var pdfjsDisplaySVG = require('./display/svg.js'); if (typeof PDFJSDev === 'undefined' || - !PDFJSDev.test('FIREFOX || MOZCENTRAL')) { + !PDFJSDev.test('FIREFOX || MOZCENTRAL || CHROME')) { const isNodeJS = require('./shared/is_node.js'); if (isNodeJS()) { - var PDFNodeStream = require('./display/node_stream.js').PDFNodeStream; - pdfjsDisplayAPI.setPDFNetworkStreamClass(PDFNodeStream); + let PDFNodeStream = require('./display/node_stream.js').PDFNodeStream; + pdfjsDisplayAPI.setPDFNetworkStreamFactory((params) => { + return new PDFNodeStream(params); + }); } else if (typeof Response !== 'undefined' && 'body' in Response.prototype && typeof ReadableStream !== 'undefined') { - var PDFFetchStream = require('./display/fetch_stream.js').PDFFetchStream; - pdfjsDisplayAPI.setPDFNetworkStreamClass(PDFFetchStream); + let PDFFetchStream = require('./display/fetch_stream.js').PDFFetchStream; + pdfjsDisplayAPI.setPDFNetworkStreamFactory((params) => { + return new PDFFetchStream(params); + }); } else { - var PDFNetworkStream = require('./display/network.js').PDFNetworkStream; - pdfjsDisplayAPI.setPDFNetworkStreamClass(PDFNetworkStream); + let PDFNetworkStream = require('./display/network.js').PDFNetworkStream; + pdfjsDisplayAPI.setPDFNetworkStreamFactory((params) => { + return new PDFNetworkStream(params); + }); } +} else if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('CHROME')) { + let PDFNetworkStream = require('./display/network.js').PDFNetworkStream; + let PDFFetchStream; + if (typeof Response !== 'undefined' && 'body' in Response.prototype && + typeof ReadableStream !== 'undefined') { + PDFFetchStream = require('./display/fetch_stream.js').PDFFetchStream; + } + pdfjsDisplayAPI.setPDFNetworkStreamFactory((params) => { + if (PDFFetchStream && /^https?:/i.test(params.url)) { + // "fetch" is only supported for http(s), not file/ftp. + return new PDFFetchStream(params); + } + return new PDFNetworkStream(params); + }); } exports.PDFJS = pdfjsDisplayGlobal.PDFJS; diff --git a/test/unit/jasmine-boot.js b/test/unit/jasmine-boot.js index 3392b56a30d36..fbf85b1cdbb81 100644 --- a/test/unit/jasmine-boot.js +++ b/test/unit/jasmine-boot.js @@ -85,9 +85,13 @@ function initializePDFJS(callback) { // Set network stream class for unit tests. if (typeof Response !== 'undefined' && 'body' in Response.prototype && typeof ReadableStream !== 'undefined') { - displayApi.setPDFNetworkStreamClass(PDFFetchStream); + displayApi.setPDFNetworkStreamFactory(function(params) { + return new PDFFetchStream(params); + }); } else { - displayApi.setPDFNetworkStreamClass(PDFNetworkStream); + displayApi.setPDFNetworkStreamFactory(function(params) { + return new PDFNetworkStream(params); + }); } // Configure the worker.