Based on Adapted to apply cleanly to GNU IceCat. # HG changeset patch # User Ryan VanderMeulen # Date 1523630807 14400 # Node ID 608e76ec5ba25cec2271d2b400c7bce2d4c5ef79 # Parent 10b7f43b536f93151201d44d304c991aa9af5d0c Bug 1452075 - Backport some upstream pdf.js fixes to ESR52. r=bdahl, r=yury, a=RyanVM diff --git a/browser/extensions/pdfjs/content/PdfStreamConverter.jsm b/browser/extensions/pdfjs/content/PdfStreamConverter.jsm --- a/browser/extensions/pdfjs/content/PdfStreamConverter.jsm +++ b/browser/extensions/pdfjs/content/PdfStreamConverter.jsm @@ -24,17 +24,18 @@ const Cc = Components.classes; const Ci = Components.interfaces; const Cr = Components.results; const Cu = Components.utils; // True only if this is the version of pdf.js that is included with icecat. const MOZ_CENTRAL = JSON.parse('true'); const PDFJS_EVENT_ID = 'pdf.js.message'; const PDF_CONTENT_TYPE = 'application/pdf'; const PREF_PREFIX = 'pdfjs'; -const PDF_VIEWER_WEB_PAGE = 'resource://pdf.js/web/viewer.html'; +const PDF_VIEWER_ORIGIN = "resource://pdf.js"; +const PDF_VIEWER_WEB_PAGE = "resource://pdf.js/web/viewer.html"; const MAX_NUMBER_OF_PREFS = 50; const MAX_STRING_PREF_LENGTH = 128; Cu.import('resource://gre/modules/XPCOMUtils.jsm'); Cu.import('resource://gre/modules/Services.jsm'); Cu.import('resource://gre/modules/NetUtil.jsm'); XPCOMUtils.defineLazyModuleGetter(this, 'NetworkManager', @@ -105,21 +106,25 @@ function log(aMsg) { if (!getBoolPref(PREF_PREFIX + '.pdfBugEnabled', false)) { return; } var msg = 'PdfStreamConverter.js: ' + (aMsg.join ? aMsg.join('') : aMsg); Services.console.logStringMessage(msg); dump(msg + '\n'); } -function getDOMWindow(aChannel) { +function getDOMWindow(aChannel, aPrincipal) { var requestor = aChannel.notificationCallbacks ? aChannel.notificationCallbacks : aChannel.loadGroup.notificationCallbacks; var win = requestor.getInterface(Components.interfaces.nsIDOMWindow); + // Ensure the window wasn't navigated to something that is not PDF.js. + if (!win.document.nodePrincipal.equals(aPrincipal)) { + return null; + } return win; } function getLocalizedStrings(path) { var stringBundle = Cc['@mozilla.org/intl/stringbundle;1']. getService(Ci.nsIStringBundleService). createBundle('chrome://pdf.js/locale/' + path); @@ -627,31 +632,31 @@ var RangedChromeActions = (function Rang data = this.dataListener.readData(); this.dataListener.onprogress = function (loaded, total) { self.domWindow.postMessage({ pdfjsLoadAction: 'progressiveRead', loaded: loaded, total: total, chunk: self.dataListener.readData() - }, '*'); + }, PDF_VIEWER_ORIGIN); }; this.dataListener.oncomplete = function () { self.dataListener = null; }; } this.domWindow.postMessage({ pdfjsLoadAction: 'supportsRangedLoading', rangeEnabled: this.rangeEnabled, streamingEnabled: this.streamingEnabled, pdfUrl: this.pdfUrl, length: this.contentLength, data: data - }, '*'); + }, PDF_VIEWER_ORIGIN); return true; }; proto.requestDataRange = function RangedChromeActions_requestDataRange(args) { if (!this.rangeEnabled) { return; } @@ -663,23 +668,23 @@ var RangedChromeActions = (function Rang // errors from chrome code for non-range requests, so this doesn't // seem high-pri this.networkManager.requestRange(begin, end, { onDone: function RangedChromeActions_onDone(args) { domWindow.postMessage({ pdfjsLoadAction: 'range', begin: args.begin, chunk: args.chunk - }, '*'); + }, PDF_VIEWER_ORIGIN); }, onProgress: function RangedChromeActions_onProgress(evt) { domWindow.postMessage({ pdfjsLoadAction: 'rangeProgress', loaded: evt.loaded, - }, '*'); + }, PDF_VIEWER_ORIGIN); } }); }; proto.abortLoading = function RangedChromeActions_abortLoading() { this.networkManager.abortAllRequests(); if (this.originalRequest) { this.originalRequest.cancel(Cr.NS_BINDING_ABORTED); @@ -718,26 +723,26 @@ var StandardChromeActions = (function St var self = this; this.dataListener.onprogress = function ChromeActions_dataListenerProgress( loaded, total) { self.domWindow.postMessage({ pdfjsLoadAction: 'progress', loaded: loaded, total: total - }, '*'); + }, PDF_VIEWER_ORIGIN); }; this.dataListener.oncomplete = function StandardChromeActions_dataListenerComplete(data, errorCode) { self.domWindow.postMessage({ pdfjsLoadAction: 'complete', data: data, errorCode: errorCode - }, '*'); + }, PDF_VIEWER_ORIGIN); self.dataListener = null; self.originalRequest = null; }; return true; }; @@ -972,31 +977,35 @@ PdfStreamConverter.prototype = { var proxy = { onStartRequest: function(request, context) { listener.onStartRequest(aRequest, aContext); }, onDataAvailable: function(request, context, inputStream, offset, count) { listener.onDataAvailable(aRequest, aContext, inputStream, offset, count); }, - onStopRequest: function(request, context, statusCode) { - // We get the DOM window here instead of before the request since it - // may have changed during a redirect. - var domWindow = getDOMWindow(channel); + onStopRequest(request, context, statusCode) { + var domWindow = getDOMWindow(channel, resourcePrincipal); + if (!Components.isSuccessCode(statusCode) || !domWindow) { + // The request may have been aborted and the document may have been + // replaced with something that is not PDF.js, abort attaching. + listener.onStopRequest(aRequest, context, statusCode); + return; + } var actions; if (rangeRequest || streamRequest) { actions = new RangedChromeActions( domWindow, contentDispositionFilename, aRequest, rangeRequest, streamRequest, dataListener); } else { actions = new StandardChromeActions( domWindow, contentDispositionFilename, aRequest, dataListener); } var requestListener = new RequestListener(actions); - domWindow.addEventListener(PDFJS_EVENT_ID, function(event) { + domWindow.document.addEventListener(PDFJS_EVENT_ID, function(event) { requestListener.receive(event); }, false, true); if (actions.supportsIntegratedFind()) { var findEventManager = new FindEventManager(domWindow); findEventManager.bind(); } listener.onStopRequest(aRequest, aContext, statusCode); diff --git a/browser/extensions/pdfjs/content/build/pdf.worker.js b/browser/extensions/pdfjs/content/build/pdf.worker.js --- a/browser/extensions/pdfjs/content/build/pdf.worker.js +++ b/browser/extensions/pdfjs/content/build/pdf.worker.js @@ -41648,16 +41648,32 @@ var error = sharedUtil.error; var info = sharedUtil.info; var isArray = sharedUtil.isArray; var isBool = sharedUtil.isBool; var isDict = corePrimitives.isDict; var isStream = corePrimitives.isStream; var PostScriptLexer = corePsParser.PostScriptLexer; var PostScriptParser = corePsParser.PostScriptParser; + function toNumberArray(arr) { + if (!Array.isArray(arr)) { + return null; + } + var length = arr.length; + for (var i = 0; i < length; i++) { + if (typeof arr[i] !== 'number') { + var result = new Array(length); + for (var j = 0; j < length; j++) { + result[j] = +arr[j]; + } + return result; + } + } + return arr; + } var PDFFunction = function PDFFunctionClosure() { var CONSTRUCT_SAMPLED = 0; var CONSTRUCT_INTERPOLATED = 2; var CONSTRUCT_STICHED = 3; var CONSTRUCT_POSTSCRIPT = 4; return { getSampleArray: function PDFFunction_getSampleArray(size, outputSize, bps, str) { var i, ii; @@ -41747,43 +41763,43 @@ out[index] = [ arr[i], arr[i + 1] ]; ++index; } return out; } - var domain = dict.getArray('Domain'); - var range = dict.getArray('Range'); + var domain = toNumberArray(dict.getArray('Domain')); + var range = toNumberArray(dict.getArray('Range')); if (!domain || !range) { error('No domain or range'); } var inputSize = domain.length / 2; var outputSize = range.length / 2; domain = toMultiArray(domain); range = toMultiArray(range); - var size = dict.get('Size'); + var size = toNumberArray(dict.get('Size')); var bps = dict.get('BitsPerSample'); var order = dict.get('Order') || 1; if (order !== 1) { // No description how cubic spline interpolation works in PDF32000:2008 // As in poppler, ignoring order, linear interpolation may work as good info('No support for cubic spline interpolation: ' + order); } - var encode = dict.getArray('Encode'); + var encode = toNumberArray(dict.getArray('Encode')); if (!encode) { encode = []; for (var i = 0; i < inputSize; ++i) { - encode.push(0); - encode.push(size[i] - 1); - } - } - encode = toMultiArray(encode); - var decode = dict.getArray('Decode'); + encode.push([0, size[i] - 1]); + } + } else { + encode = toMultiArray(encode); + } + var decode = toNumberArray(dict.getArray('Decode')); if (!decode) { decode = range; } else { decode = toMultiArray(decode); } var samples = this.getSampleArray(size, outputSize, bps, str); return [ CONSTRUCT_SAMPLED, @@ -41868,22 +41884,19 @@ // Decode_2j, Decode_2j+1) rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]); // y_j = min(max(r_j, range_2j), range_2j+1) dest[destOffset + j] = Math.min(Math.max(rj, range[j][0]), range[j][1]); } }; }, constructInterpolated: function PDFFunction_constructInterpolated(str, dict) { - var c0 = dict.getArray('C0') || [0]; - var c1 = dict.getArray('C1') || [1]; + var c0 = toNumberArray(dict.getArray('C0')) || [0]; + var c1 = toNumberArray(dict.getArray('C1')) || [1]; var n = dict.get('N'); - if (!isArray(c0) || !isArray(c1)) { - error('Illegal dictionary for interpolated function'); - } var length = c0.length; var diff = []; for (var i = 0; i < length; ++i) { diff.push(c1[i] - c0[i]); } return [ CONSTRUCT_INTERPOLATED, c0, @@ -41899,49 +41912,45 @@ return function constructInterpolatedFromIRResult(src, srcOffset, dest, destOffset) { var x = n === 1 ? src[srcOffset] : Math.pow(src[srcOffset], n); for (var j = 0; j < length; ++j) { dest[destOffset + j] = c0[j] + x * diff[j]; } }; }, constructStiched: function PDFFunction_constructStiched(fn, dict, xref) { - var domain = dict.getArray('Domain'); + var domain = toNumberArray(dict.getArray('Domain')); if (!domain) { error('No domain'); } var inputSize = domain.length / 2; if (inputSize !== 1) { error('Bad domain for stiched function'); } var fnRefs = dict.get('Functions'); var fns = []; for (var i = 0, ii = fnRefs.length; i < ii; ++i) { - fns.push(PDFFunction.getIR(xref, xref.fetchIfRef(fnRefs[i]))); - } - var bounds = dict.getArray('Bounds'); - var encode = dict.getArray('Encode'); + fns.push(PDFFunction.parse(xref, xref.fetchIfRef(fnRefs[i]))); + } + var bounds = toNumberArray(dict.getArray('Bounds')); + var encode = toNumberArray(dict.getArray('Encode')); return [ CONSTRUCT_STICHED, domain, bounds, encode, fns ]; }, constructStichedFromIR: function PDFFunction_constructStichedFromIR(IR) { var domain = IR[1]; var bounds = IR[2]; var encode = IR[3]; - var fnsIR = IR[4]; - var fns = []; + var fns = IR[4]; var tmpBuf = new Float32Array(1); - for (var i = 0, ii = fnsIR.length; i < ii; i++) { - fns.push(PDFFunction.fromIR(fnsIR[i])); - } return function constructStichedFromIRResult(src, srcOffset, dest, destOffset) { var clip = function constructStichedFromIRClip(v, min, max) { if (v > max) { v = max; } else if (v < min) { v = min; } return v; @@ -41968,18 +41977,18 @@ // Prevent the value from becoming NaN as a result // of division by zero (fixes issue6113.pdf). tmpBuf[0] = dmin === dmax ? rmin : rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin); // call the appropriate function fns[i](tmpBuf, 0, dest, destOffset); }; }, constructPostScript: function PDFFunction_constructPostScript(fn, dict, xref) { - var domain = dict.getArray('Domain'); - var range = dict.getArray('Range'); + var domain = toNumberArray(dict.getArray('Domain')); + var range = toNumberArray(dict.getArray('Range')); if (!domain) { error('No domain.'); } if (!range) { error('No range.'); } var lexer = new PostScriptLexer(fn); var parser = new PostScriptParser(lexer); @@ -42928,18 +42937,18 @@ case 'IndexedCS': var baseIndexedCS = IR[1]; var hiVal = IR[2]; var lookup = IR[3]; return new IndexedCS(ColorSpace.fromIR(baseIndexedCS), hiVal, lookup); case 'AlternateCS': var numComps = IR[1]; var alt = IR[2]; - var tintFnIR = IR[3]; - return new AlternateCS(numComps, ColorSpace.fromIR(alt), PDFFunction.fromIR(tintFnIR)); + var tintFn = IR[3]; + return new AlternateCS(numComps, ColorSpace.fromIR(alt), tintFn); case 'LabCS': whitePoint = IR[1]; blackPoint = IR[2]; var range = IR[3]; return new LabCS(whitePoint, blackPoint, range); default: error('Unknown name ' + name); } @@ -43067,22 +43076,22 @@ var name = xref.fetchIfRef(cs[1]); numComps = 1; if (isName(name)) { numComps = 1; } else if (isArray(name)) { numComps = name.length; } alt = ColorSpace.parseToIR(cs[2], xref, res); - var tintFnIR = PDFFunction.getIR(xref, xref.fetchIfRef(cs[3])); + var tintFn = PDFFunction.parse(xref, xref.fetchIfRef(cs[3])); return [ 'AlternateCS', numComps, alt, - tintFnIR + tintFn ]; case 'Lab': params = xref.fetchIfRef(cs[1]); whitePoint = params.getArray('WhitePoint'); blackPoint = params.getArray('BlackPoint'); var range = params.getArray('Range'); return [ 'LabCS', @@ -52483,9 +52492,9 @@ initializeWorker(); } exports.setPDFNetworkStreamClass = setPDFNetworkStreamClass; exports.WorkerTask = WorkerTask; exports.WorkerMessageHandler = WorkerMessageHandler; })); }.call(pdfjsLibs)); exports.WorkerMessageHandler = pdfjsLibs.pdfjsCoreWorker.WorkerMessageHandler; -})); \ No newline at end of file +}));