Based on <https://hg.mozilla.org/releases/mozilla-esr52/rev/608e76ec5ba2>
Adapted to apply cleanly to GNU IceCat.

# HG changeset patch
# User Ryan VanderMeulen <ryanvm@gmail.com>
# 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
+}));