Bug 1237815 - Update pdf.js to version 1.3.161. r=bdahl
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 07 Jan 2016 18:32:09 -0500
changeset 279022 1fa6d18bfe06f73f192db7606de4b7674f433cff
parent 279021 f08d1e52d609f5c785d53e39be1f07bedcaa1e2e
child 279023 45e3fc0e88168ae3ead00832c06e4436fe8b6475
push id29866
push usercbook@mozilla.com
push dateFri, 08 Jan 2016 10:59:19 +0000
treeherdermozilla-central@eb6ba33216d4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbdahl
bugs1237815
milestone46.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1237815 - Update pdf.js to version 1.3.161. r=bdahl
browser/extensions/pdfjs/README.mozilla
browser/extensions/pdfjs/content/build/pdf.js
browser/extensions/pdfjs/content/build/pdf.worker.js
browser/extensions/pdfjs/content/web/viewer.css
browser/extensions/pdfjs/content/web/viewer.js
--- a/browser/extensions/pdfjs/README.mozilla
+++ b/browser/extensions/pdfjs/README.mozilla
@@ -1,3 +1,3 @@
 This is the pdf.js project output, https://github.com/mozilla/pdf.js
 
-Current extension version is: 1.3.142
+Current extension version is: 1.3.161
--- a/browser/extensions/pdfjs/content/build/pdf.js
+++ b/browser/extensions/pdfjs/content/build/pdf.js
@@ -8,31 +8,42 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 /* jshint globalstrict: false */
-/* globals PDFJS, global */
-
-// Initializing PDFJS global object (if still undefined)
-if (typeof PDFJS === 'undefined') {
-  (typeof window !== 'undefined' ? window :
-   typeof global !== 'undefined' ? global : this).PDFJS = {};
-}
-
-PDFJS.version = '1.3.142';
-PDFJS.build = 'e8db825';
-
-(function pdfjsWrapper() {
+/* umdutils ignore */
+
+(function (root, factory) {
+  'use strict';
+  if (typeof define === 'function' && define.amd) {
+define('pdfjs-dist/build/pdf', ['exports'], factory);
+  } else if (typeof exports !== 'undefined') {
+    factory(exports);
+  } else {
+factory((root.pdfjsDistBuildPdf = {}));
+  }
+}(this, function (exports) {
   // Use strict in our context only - users might not want it
   'use strict';
 
+var pdfjsVersion = '1.3.161';
+var pdfjsBuild = '4a215f0';
+
+  var pdfjsFilePath =
+    typeof document !== 'undefined' && document.currentScript ?
+      document.currentScript.src : null;
+
+  var pdfjsLibs = {};
+
+  (function pdfjsWrapper() {
+
 
 
 (function (root, factory) {
   {
     factory((root.pdfjsSharedGlobal = {}));
   }
 }(this, function (exports) {
 
@@ -44,16 +55,23 @@ PDFJS.build = 'e8db825';
 
   // The global PDFJS object exposes the API
   // In production, it will be declared outside a global wrapper
   // In development, it will be declared here
   if (!globalScope.PDFJS) {
     globalScope.PDFJS = {};
   }
 
+  if (typeof pdfjsVersion !== 'undefined') {
+    globalScope.PDFJS.version = pdfjsVersion;
+  }
+  if (typeof pdfjsVersion !== 'undefined') {
+    globalScope.PDFJS.build = pdfjsBuild;
+  }
+
   globalScope.PDFJS.pdfBug = false;
 
   exports.globalScope = globalScope;
   exports.isWorker = isWorker;
   exports.PDFJS = globalScope.PDFJS;
 }));
 
 
@@ -593,16 +611,26 @@ var XRefParseException = (function XRefP
 
   XRefParseException.prototype = new Error();
   XRefParseException.prototype.name = 'XRefParseException';
   XRefParseException.constructor = XRefParseException;
 
   return XRefParseException;
 })();
 
+var NullCharactersRegExp = /\x00/g;
+
+function removeNullCharacters(str) {
+  if (typeof str !== 'string') {
+    warn('The argument for removeNullCharacters must be a string.');
+    return str;
+  }
+  return str.replace(NullCharactersRegExp, '');
+}
+PDFJS.removeNullCharacters = removeNullCharacters;
 
 function bytesToString(bytes) {
   assert(bytes !== null && typeof bytes === 'object' &&
          bytes.length !== undefined, 'Invalid argument for bytesToString');
   var length = bytes.length;
   var MAX_ARGUMENT_COUNT = 8192;
   if (length < MAX_ARGUMENT_COUNT) {
     return String.fromCharCode.apply(null, bytes);
@@ -1457,16 +1485,17 @@ exports.isInt = isInt;
 exports.isNum = isNum;
 exports.isString = isString;
 exports.isValidUrl = isValidUrl;
 exports.loadJpegStream = loadJpegStream;
 exports.log2 = log2;
 exports.readInt8 = readInt8;
 exports.readUint16 = readUint16;
 exports.readUint32 = readUint32;
+exports.removeNullCharacters = removeNullCharacters;
 exports.shadow = shadow;
 exports.string32 = string32;
 exports.stringToBytes = stringToBytes;
 exports.stringToPDFString = stringToPDFString;
 exports.stringToUTF8String = stringToUTF8String;
 exports.utf8StringToString = utf8StringToString;
 exports.warn = warn;
 }));
@@ -1479,16 +1508,17 @@ exports.warn = warn;
   }
 }(this, function (exports, sharedUtil, displayDOMUtils) {
 
 var AnnotationBorderStyleType = sharedUtil.AnnotationBorderStyleType;
 var AnnotationType = sharedUtil.AnnotationType;
 var Util = sharedUtil.Util;
 var isExternalLinkTargetSet = sharedUtil.isExternalLinkTargetSet;
 var LinkTargetStringMap = sharedUtil.LinkTargetStringMap;
+var removeNullCharacters = sharedUtil.removeNullCharacters;
 var warn = sharedUtil.warn;
 var CustomStyle = displayDOMUtils.CustomStyle;
 
 /**
  * @typedef {Object} AnnotationElementParameters
  * @property {Object} data
  * @property {HTMLDivElement} layer
  * @property {PDFPage} page
@@ -1518,19 +1548,28 @@ AnnotationElementFactory.prototype =
         return new TextAnnotationElement(parameters);
 
       case AnnotationType.WIDGET:
         return new WidgetAnnotationElement(parameters);
 
       case AnnotationType.POPUP:
         return new PopupAnnotationElement(parameters);
 
+      case AnnotationType.HIGHLIGHT:
+        return new HighlightAnnotationElement(parameters);
+
       case AnnotationType.UNDERLINE:
         return new UnderlineAnnotationElement(parameters);
 
+      case AnnotationType.SQUIGGLY:
+        return new SquigglyAnnotationElement(parameters);
+
+      case AnnotationType.STRIKEOUT:
+        return new StrikeOutAnnotationElement(parameters);
+
       default:
         throw new Error('Unimplemented annotation type "' + subtype + '"');
     }
   }
 };
 
 /**
  * @class
@@ -1669,17 +1708,18 @@ var LinkAnnotationElement = (function Li
      * @public
      * @memberof LinkAnnotationElement
      * @returns {HTMLSectionElement}
      */
     render: function LinkAnnotationElement_render() {
       this.container.className = 'linkAnnotation';
 
       var link = document.createElement('a');
-      link.href = link.title = this.data.url || '';
+      link.href = link.title = (this.data.url ?
+                                removeNullCharacters(this.data.url) : '');
 
       if (this.data.url && isExternalLinkTargetSet()) {
         link.target = LinkTargetStringMap[PDFJS.externalLinkTarget];
       }
 
       // Strip referrer from the URL.
       if (this.data.url) {
         link.rel = PDFJS.externalLinkRel;
@@ -2051,16 +2091,43 @@ var PopupElement = (function PopupElemen
     }
   };
 
   return PopupElement;
 })();
 
 /**
  * @class
+ * @alias HighlightAnnotationElement
+ */
+var HighlightAnnotationElement = (
+    function HighlightAnnotationElementClosure() {
+  function HighlightAnnotationElement(parameters) {
+    AnnotationElement.call(this, parameters);
+  }
+
+  Util.inherit(HighlightAnnotationElement, AnnotationElement, {
+    /**
+     * Render the highlight annotation's HTML element in the empty container.
+     *
+     * @public
+     * @memberof HighlightAnnotationElement
+     * @returns {HTMLSectionElement}
+     */
+    render: function HighlightAnnotationElement_render() {
+      this.container.className = 'highlightAnnotation';
+      return this.container;
+    }
+  });
+
+  return HighlightAnnotationElement;
+})();
+
+/**
+ * @class
  * @alias UnderlineAnnotationElement
  */
 var UnderlineAnnotationElement = (
     function UnderlineAnnotationElementClosure() {
   function UnderlineAnnotationElement(parameters) {
     AnnotationElement.call(this, parameters);
   }
 
@@ -2077,16 +2144,69 @@ var UnderlineAnnotationElement = (
       return this.container;
     }
   });
 
   return UnderlineAnnotationElement;
 })();
 
 /**
+ * @class
+ * @alias SquigglyAnnotationElement
+ */
+var SquigglyAnnotationElement = (function SquigglyAnnotationElementClosure() {
+  function SquigglyAnnotationElement(parameters) {
+    AnnotationElement.call(this, parameters);
+  }
+
+  Util.inherit(SquigglyAnnotationElement, AnnotationElement, {
+    /**
+     * Render the squiggly annotation's HTML element in the empty container.
+     *
+     * @public
+     * @memberof SquigglyAnnotationElement
+     * @returns {HTMLSectionElement}
+     */
+    render: function SquigglyAnnotationElement_render() {
+      this.container.className = 'squigglyAnnotation';
+      return this.container;
+    }
+  });
+
+  return SquigglyAnnotationElement;
+})();
+
+/**
+ * @class
+ * @alias StrikeOutAnnotationElement
+ */
+var StrikeOutAnnotationElement = (
+    function StrikeOutAnnotationElementClosure() {
+  function StrikeOutAnnotationElement(parameters) {
+    AnnotationElement.call(this, parameters);
+  }
+
+  Util.inherit(StrikeOutAnnotationElement, AnnotationElement, {
+    /**
+     * Render the strikeout annotation's HTML element in the empty container.
+     *
+     * @public
+     * @memberof StrikeOutAnnotationElement
+     * @returns {HTMLSectionElement}
+     */
+    render: function StrikeOutAnnotationElement_render() {
+      this.container.className = 'strikeoutAnnotation';
+      return this.container;
+    }
+  });
+
+  return StrikeOutAnnotationElement;
+})();
+
+/**
  * @typedef {Object} AnnotationLayerParameters
  * @property {PageViewport} viewport
  * @property {HTMLDivElement} div
  * @property {Array} annotations
  * @property {PDFPage} page
  * @property {IPDFLinkService} linkService
  */
 
@@ -5694,20 +5814,20 @@ exports.CanvasGraphics = CanvasGraphics;
 exports.createScratchCanvas = createScratchCanvas;
 }));
 
 
 (function (root, factory) {
   {
     factory((root.pdfjsDisplayAPI = {}), root.pdfjsSharedUtil,
       root.pdfjsDisplayFontLoader, root.pdfjsDisplayCanvas,
-      root.pdfjsSharedGlobal);
+      root.pdfjsDisplayMetadata, root.pdfjsSharedGlobal);
   }
 }(this, function (exports, sharedUtil, displayFontLoader, displayCanvas,
-                  sharedGlobal, amdRequire) {
+                  displayMetadata, sharedGlobal, amdRequire) {
 
 var InvalidPDFException = sharedUtil.InvalidPDFException;
 var MessageHandler = sharedUtil.MessageHandler;
 var MissingPDFException = sharedUtil.MissingPDFException;
 var PasswordResponses = sharedUtil.PasswordResponses;
 var PasswordException = sharedUtil.PasswordException;
 var StatTimer = sharedUtil.StatTimer;
 var UnexpectedResponseException = sharedUtil.UnexpectedResponseException;
@@ -5721,16 +5841,17 @@ var info = sharedUtil.info;
 var isArrayBuffer = sharedUtil.isArrayBuffer;
 var loadJpegStream = sharedUtil.loadJpegStream;
 var stringToBytes = sharedUtil.stringToBytes;
 var warn = sharedUtil.warn;
 var FontFaceObject = displayFontLoader.FontFaceObject;
 var FontLoader = displayFontLoader.FontLoader;
 var CanvasGraphics = displayCanvas.CanvasGraphics;
 var createScratchCanvas = displayCanvas.createScratchCanvas;
+var Metadata = displayMetadata.Metadata;
 var PDFJS = sharedGlobal.PDFJS;
 var globalScope = sharedGlobal.globalScope;
 
 var DEFAULT_RANGE_CHUNK_SIZE = 65536; // 2^16 = 65536
 
   var fakeWorkerFilesLoader = null;
 
 /**
@@ -6839,25 +6960,32 @@ var PDFPageProxy = (function PDFPageProx
  * PDF.js web worker abstraction, it controls instantiation of PDF documents and
  * WorkerTransport for them.  If creation of a web worker is not possible,
  * a "fake" worker will be used instead.
  * @class
  */
 var PDFWorker = (function PDFWorkerClosure() {
   var nextFakeWorkerId = 0;
 
+  function getWorkerSrc() {
+    if (PDFJS.workerSrc) {
+      return PDFJS.workerSrc;
+    }
+    error('No PDFJS.workerSrc specified');
+  }
+
   // Loads worker code into main thread.
   function setupFakeWorkerGlobal() {
     if (!PDFJS.fakeWorkerFilesLoadedCapability) {
       PDFJS.fakeWorkerFilesLoadedCapability = createPromiseCapability();
       // In the developer build load worker_loader which in turn loads all the
       // other files and resolves the promise. In production only the
       // pdf.worker.js file is needed.
       var loader = fakeWorkerFilesLoader || function (callback) {
-        Util.loadScript(PDFJS.workerSrc, callback);
+        Util.loadScript(getWorkerSrc(), callback);
       };
       loader(function () {
         PDFJS.fakeWorkerFilesLoadedCapability.resolve();
       });
     }
     return PDFJS.fakeWorkerFilesLoadedCapability.promise;
   }
 
@@ -6887,20 +7015,17 @@ var PDFWorker = (function PDFWorkerClosu
 
     _initialize: function PDFWorker_initialize() {
       // If worker support isn't disabled explicit and the browser has worker
       // support, create a new web worker and test if it/the browser fullfills
       // all requirements to run parts of pdf.js in a web worker.
       // Right now, the requirement is, that an Uint8Array is still an
       // Uint8Array as it arrives on the worker. (Chrome added this with v.15.)
       if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
-        var workerSrc = PDFJS.workerSrc;
-        if (!workerSrc) {
-          error('No PDFJS.workerSrc specified');
-        }
+        var workerSrc = getWorkerSrc();
 
         try {
           // Some versions of FF can't create a worker on localhost, see:
           // https://bugzilla.mozilla.org/show_bug.cgi?id=683280
           var worker = new Worker(workerSrc);
           var messageHandler = new MessageHandler('main', 'worker', worker);
           messageHandler.on('test', function PDFWorker_test(data) {
             if (this.destroyed) {
@@ -7442,17 +7567,17 @@ var WorkerTransport = (function WorkerTr
       return this.messageHandler.sendWithPromise('GetOutline', null);
     },
 
     getMetadata: function WorkerTransport_getMetadata() {
       return this.messageHandler.sendWithPromise('GetMetadata', null).
         then(function transportMetadata(results) {
         return {
           info: results[0],
-          metadata: (results[1] ? new PDFJS.Metadata(results[1]) : null)
+          metadata: (results[1] ? new Metadata(results[1]) : null)
         };
       });
     },
 
     getStats: function WorkerTransport_getStats() {
       return this.messageHandler.sendWithPromise('GetStats', null);
     },
 
@@ -7775,12 +7900,27 @@ PDFJS.UnsupportedManager = (function Uns
 
 exports.getDocument = PDFJS.getDocument;
 exports.PDFDataRangeTransport = PDFDataRangeTransport;
 exports.PDFDocumentProxy = PDFDocumentProxy;
 exports.PDFPageProxy = PDFPageProxy;
 }));
 
 
-}).call((typeof window === 'undefined') ? this : window);
-
-
-
+  }).call(pdfjsLibs);
+
+  exports.PDFJS = pdfjsLibs.pdfjsSharedGlobal.PDFJS;
+
+  exports.getDocument = pdfjsLibs.pdfjsDisplayAPI.getDocument;
+  exports.PDFDataRangeTransport =
+    pdfjsLibs.pdfjsDisplayAPI.PDFDataRangeTransport;
+  exports.renderTextLayer = pdfjsLibs.pdfjsDisplayTextLayer.renderTextLayer;
+  exports.AnnotationLayer =
+    pdfjsLibs.pdfjsDisplayAnnotationLayer.AnnotationLayer;
+  exports.CustomStyle = pdfjsLibs.pdfjsDisplayDOMUtils.CustomStyle;
+  exports.PasswordResponses = pdfjsLibs.pdfjsSharedUtil.PasswordResponses;
+  exports.InvalidPDFException = pdfjsLibs.pdfjsSharedUtil.InvalidPDFException;
+  exports.MissingPDFException = pdfjsLibs.pdfjsSharedUtil.MissingPDFException;
+  exports.UnexpectedResponseException =
+    pdfjsLibs.pdfjsSharedUtil.UnexpectedResponseException;
+}));
+
+
--- a/browser/extensions/pdfjs/content/build/pdf.worker.js
+++ b/browser/extensions/pdfjs/content/build/pdf.worker.js
@@ -8,31 +8,42 @@
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
 /* jshint globalstrict: false */
-/* globals PDFJS, global */
-
-// Initializing PDFJS global object (if still undefined)
-if (typeof PDFJS === 'undefined') {
-  (typeof window !== 'undefined' ? window :
-   typeof global !== 'undefined' ? global : this).PDFJS = {};
-}
-
-PDFJS.version = '1.3.142';
-PDFJS.build = 'e8db825';
-
-(function pdfjsWrapper() {
+/* umdutils ignore */
+
+(function (root, factory) {
+  'use strict';
+  if (typeof define === 'function' && define.amd) {
+define('pdfjs-dist/build/pdf.worker', ['exports'], factory);
+  } else if (typeof exports !== 'undefined') {
+    factory(exports);
+  } else {
+factory((root.pdfjsDistBuildPdfWorker = {}));
+  }
+}(this, function (exports) {
   // Use strict in our context only - users might not want it
   'use strict';
 
+var pdfjsVersion = '1.3.161';
+var pdfjsBuild = '4a215f0';
+
+  var pdfjsFilePath =
+    typeof document !== 'undefined' && document.currentScript ?
+      document.currentScript.src : null;
+
+  var pdfjsLibs = {};
+
+  (function pdfjsWrapper() {
+
 
 
 (function (root, factory) {
   {
     factory((root.pdfjsCoreArithmeticDecoder = {}));
   }
 }(this, function (exports) {
 
@@ -8733,16 +8744,23 @@ exports.Metrics = Metrics;
 
   // The global PDFJS object exposes the API
   // In production, it will be declared outside a global wrapper
   // In development, it will be declared here
   if (!globalScope.PDFJS) {
     globalScope.PDFJS = {};
   }
 
+  if (typeof pdfjsVersion !== 'undefined') {
+    globalScope.PDFJS.version = pdfjsVersion;
+  }
+  if (typeof pdfjsVersion !== 'undefined') {
+    globalScope.PDFJS.build = pdfjsBuild;
+  }
+
   globalScope.PDFJS.pdfBug = false;
 
   exports.globalScope = globalScope;
   exports.isWorker = isWorker;
   exports.PDFJS = globalScope.PDFJS;
 }));
 
 
@@ -9632,16 +9650,26 @@ var XRefParseException = (function XRefP
 
   XRefParseException.prototype = new Error();
   XRefParseException.prototype.name = 'XRefParseException';
   XRefParseException.constructor = XRefParseException;
 
   return XRefParseException;
 })();
 
+var NullCharactersRegExp = /\x00/g;
+
+function removeNullCharacters(str) {
+  if (typeof str !== 'string') {
+    warn('The argument for removeNullCharacters must be a string.');
+    return str;
+  }
+  return str.replace(NullCharactersRegExp, '');
+}
+PDFJS.removeNullCharacters = removeNullCharacters;
 
 function bytesToString(bytes) {
   assert(bytes !== null && typeof bytes === 'object' &&
          bytes.length !== undefined, 'Invalid argument for bytesToString');
   var length = bytes.length;
   var MAX_ARGUMENT_COUNT = 8192;
   if (length < MAX_ARGUMENT_COUNT) {
     return String.fromCharCode.apply(null, bytes);
@@ -10496,16 +10524,17 @@ exports.isInt = isInt;
 exports.isNum = isNum;
 exports.isString = isString;
 exports.isValidUrl = isValidUrl;
 exports.loadJpegStream = loadJpegStream;
 exports.log2 = log2;
 exports.readInt8 = readInt8;
 exports.readUint16 = readUint16;
 exports.readUint32 = readUint32;
+exports.removeNullCharacters = removeNullCharacters;
 exports.shadow = shadow;
 exports.string32 = string32;
 exports.stringToBytes = stringToBytes;
 exports.stringToPDFString = stringToPDFString;
 exports.stringToUTF8String = stringToUTF8String;
 exports.utf8StringToString = utf8StringToString;
 exports.warn = warn;
 }));
@@ -24010,16 +24039,19 @@ var PDF_GLYPH_SPACE_UNITS = 1000;
 // Hinting is currently disabled due to unknown problems on windows
 // in tracemonkey and various other pdfs with type1 fonts.
 var HINTING_ENABLED = false;
 
 // Accented charactars are not displayed properly on windows, using this flag
 // to control analysis of seac charstrings.
 var SEAC_ANALYSIS_ENABLED = false;
 
+// Maximum subroutine call depth of type 2 chartrings. Matches OTS.
+var MAX_SUBR_NESTING = 10;
+
 var FontFlags = {
   FixedPitch: 1,
   Serif: 2,
   Symbolic: 4,
   Script: 8,
   Nonsymbolic: 32,
   Italic: 64,
   AllCap: 65536,
@@ -30039,20 +30071,17 @@ var CFFParser = (function CFFParserClosu
       cff.topDict = topDict;
       cff.globalSubrIndex = globalSubrIndex.obj;
 
       this.parsePrivateDict(cff.topDict);
 
       cff.isCIDFont = topDict.hasName('ROS');
 
       var charStringOffset = topDict.getByName('CharStrings');
-      var charStringsAndSeacs = this.parseCharStrings(charStringOffset);
-      cff.charStrings = charStringsAndSeacs.charStrings;
-      cff.seacs = charStringsAndSeacs.seacs;
-      cff.widths = charStringsAndSeacs.widths;
+      var charStringIndex = this.parseIndex(charStringOffset).obj;
 
       var fontMatrix = topDict.getByName('FontMatrix');
       if (fontMatrix) {
         properties.fontMatrix = fontMatrix;
       }
 
       var fontBBox = topDict.getByName('FontBBox');
       if (fontBBox) {
@@ -30070,29 +30099,40 @@ var CFFParser = (function CFFParserClosu
           var fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw),
                                          cff.strings);
           this.parsePrivateDict(fontDict);
           cff.fdArray.push(fontDict);
         }
         // cid fonts don't have an encoding
         encoding = null;
         charset = this.parseCharsets(topDict.getByName('charset'),
-                                     cff.charStrings.count, cff.strings, true);
+                                     charStringIndex.count, cff.strings, true);
         cff.fdSelect = this.parseFDSelect(topDict.getByName('FDSelect'),
-                                             cff.charStrings.count);
+                                          charStringIndex.count);
       } else {
         charset = this.parseCharsets(topDict.getByName('charset'),
-                                     cff.charStrings.count, cff.strings, false);
+                                     charStringIndex.count, cff.strings, false);
         encoding = this.parseEncoding(topDict.getByName('Encoding'),
                                       properties,
                                       cff.strings, charset.charset);
       }
+
       cff.charset = charset;
       cff.encoding = encoding;
 
+      var charStringsAndSeacs = this.parseCharStrings(
+                                  charStringIndex,
+                                  topDict.privateDict.subrsIndex,
+                                  globalSubrIndex.obj,
+                                  cff.fdSelect,
+                                  cff.fdArray);
+      cff.charStrings = charStringsAndSeacs.charStrings;
+      cff.seacs = charStringsAndSeacs.seacs;
+      cff.widths = charStringsAndSeacs.widths;
+
       return cff;
     },
     parseHeader: function CFFParser_parseHeader() {
       var bytes = this.bytes;
       var bytesLength = bytes.length;
       var offset = 0;
 
       // Prevent an infinite loop, by checking that the offset is within the
@@ -30257,128 +30297,211 @@ var CFFParser = (function CFFParserClosu
       for (var i = 0, ii = dict.length; i < ii; ++i) {
         var pair = dict[i];
         var key = pair[0];
         var value = pair[1];
         cffDict.setByKey(key, value);
       }
       return cffDict;
     },
-    parseCharStrings: function CFFParser_parseCharStrings(charStringOffset) {
-      var charStrings = this.parseIndex(charStringOffset).obj;
+    parseCharString: function CFFParser_parseCharString(state, data,
+                                                        localSubrIndex,
+                                                        globalSubrIndex) {
+      if (state.callDepth > MAX_SUBR_NESTING) {
+        return false;
+      }
+      var stackSize = state.stackSize;
+      var stack = state.stack;
+
+      var length = data.length;
+
+      for (var j = 0; j < length;) {
+        var value = data[j++];
+        var validationCommand = null;
+        if (value === 12) {
+          var q = data[j++];
+          if (q === 0) {
+            // The CFF specification state that the 'dotsection' command
+            // (12, 0) is deprecated and treated as a no-op, but all Type2
+            // charstrings processors should support them. Unfortunately
+            // the font sanitizer don't. As a workaround the sequence (12, 0)
+            // is replaced by a useless (0, hmoveto).
+            data[j - 2] = 139;
+            data[j - 1] = 22;
+            stackSize = 0;
+          } else {
+            validationCommand = CharstringValidationData12[q];
+          }
+        } else if (value === 28) { // number (16 bit)
+          stack[stackSize] = ((data[j] << 24) | (data[j + 1] << 16)) >> 16;
+          j += 2;
+          stackSize++;
+        } else if (value === 14) {
+          if (stackSize >= 4) {
+            stackSize -= 4;
+            if (SEAC_ANALYSIS_ENABLED) {
+              state.seac = stack.slice(stackSize, stackSize + 4);
+              return false;
+            }
+          }
+          validationCommand = CharstringValidationData[value];
+        } else if (value >= 32 && value <= 246) {  // number
+          stack[stackSize] = value - 139;
+          stackSize++;
+        } else if (value >= 247 && value <= 254) {  // number (+1 bytes)
+          stack[stackSize] = (value < 251 ?
+                              ((value - 247) << 8) + data[j] + 108 :
+                              -((value - 251) << 8) - data[j] - 108);
+          j++;
+          stackSize++;
+        } else if (value === 255) {  // number (32 bit)
+          stack[stackSize] = ((data[j] << 24) | (data[j + 1] << 16) |
+                              (data[j + 2] << 8) | data[j + 3]) / 65536;
+          j += 4;
+          stackSize++;
+        } else if (value === 19 || value === 20) {
+          state.hints += stackSize >> 1;
+          // skipping right amount of hints flag data
+          j += (state.hints + 7) >> 3;
+          stackSize %= 2;
+          validationCommand = CharstringValidationData[value];
+        } else if (value === 10 || value === 29) {
+          var subrsIndex;
+          if (value === 10) {
+            subrsIndex = localSubrIndex;
+          } else {
+            subrsIndex = globalSubrIndex;
+          }
+          if (!subrsIndex) {
+            validationCommand = CharstringValidationData[value];
+            warn('Missing subrsIndex for ' + validationCommand.id);
+            return false;
+          }
+          var bias = 32768;
+          if (subrsIndex.count < 1240) {
+            bias = 107;
+          } else if (subrsIndex.count < 33900) {
+            bias = 1131;
+          }
+          var subrNumber = stack[--stackSize] + bias;
+          if (subrNumber < 0 || subrNumber >= subrsIndex.count) {
+            validationCommand = CharstringValidationData[value];
+            warn('Out of bounds subrIndex for ' + validationCommand.id);
+            return false;
+          }
+          state.stackSize = stackSize;
+          state.callDepth++;
+          var valid = this.parseCharString(state, subrsIndex.get(subrNumber),
+                                           localSubrIndex, globalSubrIndex);
+          if (!valid) {
+            return false;
+          }
+          state.callDepth--;
+          stackSize = state.stackSize;
+          continue;
+        } else if (value === 11) {
+          state.stackSize = stackSize;
+          return true;
+        } else {
+          validationCommand = CharstringValidationData[value];
+        }
+        if (validationCommand) {
+          if (validationCommand.stem) {
+            state.hints += stackSize >> 1;
+          }
+          if ('min' in validationCommand) {
+            if (!state.undefStack && stackSize < validationCommand.min) {
+              warn('Not enough parameters for ' + validationCommand.id +
+                   '; actual: ' + stackSize +
+                   ', expected: ' + validationCommand.min);
+              return false;
+            }
+          }
+          if (state.firstStackClearing && validationCommand.stackClearing) {
+            state.firstStackClearing = false;
+            // the optional character width can be found before the first
+            // stack-clearing command arguments
+            stackSize -= validationCommand.min;
+            if (stackSize >= 2 && validationCommand.stem) {
+              // there are even amount of arguments for stem commands
+              stackSize %= 2;
+            } else if (stackSize > 1) {
+              warn('Found too many parameters for stack-clearing command');
+            }
+            if (stackSize > 0 && stack[stackSize - 1] >= 0) {
+              state.width = stack[stackSize - 1];
+            }
+          }
+          if ('stackDelta' in validationCommand) {
+            if ('stackFn' in validationCommand) {
+              validationCommand.stackFn(stack, stackSize);
+            }
+            stackSize += validationCommand.stackDelta;
+          } else if (validationCommand.stackClearing) {
+            stackSize = 0;
+          } else if (validationCommand.resetStack) {
+            stackSize = 0;
+            state.undefStack = false;
+          } else if (validationCommand.undefStack) {
+            stackSize = 0;
+            state.undefStack = true;
+            state.firstStackClearing = false;
+          }
+        }
+      }
+      state.stackSize = stackSize;
+      return true;
+    },
+    parseCharStrings: function CFFParser_parseCharStrings(charStrings,
+                                                          localSubrIndex,
+                                                          globalSubrIndex,
+                                                          fdSelect,
+                                                          fdArray) {
       var seacs = [];
       var widths = [];
       var count = charStrings.count;
       for (var i = 0; i < count; i++) {
         var charstring = charStrings.get(i);
-
-        var stackSize = 0;
-        var stack = [];
-        var undefStack = true;
-        var hints = 0;
+        var state = {
+          callDepth: 0,
+          stackSize: 0,
+          stack: [],
+          undefStack: true,
+          hints: 0,
+          firstStackClearing: true,
+          seac: null,
+          width: null
+        };
         var valid = true;
-        var data = charstring;
-        var length = data.length;
-        var firstStackClearing = true;
-        for (var j = 0; j < length;) {
-          var value = data[j++];
-          var validationCommand = null;
-          if (value === 12) {
-            var q = data[j++];
-            if (q === 0) {
-              // The CFF specification state that the 'dotsection' command
-              // (12, 0) is deprecated and treated as a no-op, but all Type2
-              // charstrings processors should support them. Unfortunately
-              // the font sanitizer don't. As a workaround the sequence (12, 0)
-              // is replaced by a useless (0, hmoveto).
-              data[j - 2] = 139;
-              data[j - 1] = 22;
-              stackSize = 0;
-            } else {
-              validationCommand = CharstringValidationData12[q];
-            }
-          } else if (value === 28) { // number (16 bit)
-            stack[stackSize] = ((data[j] << 24) | (data[j + 1] << 16)) >> 16;
-            j += 2;
-            stackSize++;
-          } else if (value === 14) {
-            if (stackSize >= 4) {
-              stackSize -= 4;
-              if (SEAC_ANALYSIS_ENABLED) {
-                seacs[i] = stack.slice(stackSize, stackSize + 4);
-                valid = false;
-              }
-            }
-            validationCommand = CharstringValidationData[value];
-          } else if (value >= 32 && value <= 246) {  // number
-            stack[stackSize] = value - 139;
-            stackSize++;
-          } else if (value >= 247 && value <= 254) {  // number (+1 bytes)
-            stack[stackSize] = (value < 251 ?
-                                ((value - 247) << 8) + data[j] + 108 :
-                                -((value - 251) << 8) - data[j] - 108);
-            j++;
-            stackSize++;
-          } else if (value === 255) {  // number (32 bit)
-            stack[stackSize] = ((data[j] << 24) | (data[j + 1] << 16) |
-                                (data[j + 2] << 8) | data[j + 3]) / 65536;
-            j += 4;
-            stackSize++;
-          } else if (value === 19 || value === 20) {
-            hints += stackSize >> 1;
-            j += (hints + 7) >> 3; // skipping right amount of hints flag data
-            stackSize %= 2;
-            validationCommand = CharstringValidationData[value];
-          } else {
-            validationCommand = CharstringValidationData[value];
-          }
-          if (validationCommand) {
-            if (validationCommand.stem) {
-              hints += stackSize >> 1;
-            }
-            if ('min' in validationCommand) {
-              if (!undefStack && stackSize < validationCommand.min) {
-                warn('Not enough parameters for ' + validationCommand.id +
-                     '; actual: ' + stackSize +
-                     ', expected: ' + validationCommand.min);
-                valid = false;
-                break;
-              }
-            }
-            if (firstStackClearing && validationCommand.stackClearing) {
-              firstStackClearing = false;
-              // the optional character width can be found before the first
-              // stack-clearing command arguments
-              stackSize -= validationCommand.min;
-              if (stackSize >= 2 && validationCommand.stem) {
-                // there are even amount of arguments for stem commands
-                stackSize %= 2;
-              } else if (stackSize > 1) {
-                warn('Found too many parameters for stack-clearing command');
-              }
-              if (stackSize > 0 && stack[stackSize - 1] >= 0) {
-                widths[i] = stack[stackSize - 1];
-              }
-            }
-            if ('stackDelta' in validationCommand) {
-              if ('stackFn' in validationCommand) {
-                validationCommand.stackFn(stack, stackSize);
-              }
-              stackSize += validationCommand.stackDelta;
-            } else if (validationCommand.stackClearing) {
-              stackSize = 0;
-            } else if (validationCommand.resetStack) {
-              stackSize = 0;
-              undefStack = false;
-            } else if (validationCommand.undefStack) {
-              stackSize = 0;
-              undefStack = true;
-              firstStackClearing = false;
-            }
-          }
+        var localSubrToUse = null;
+        if (fdSelect && fdArray.length) {
+          var fdIndex = fdSelect.getFDIndex(i);
+          if (fdIndex === -1) {
+            warn('Glyph index is not in fd select.');
+            valid = false;
+          }
+          if (fdIndex >= fdArray.length) {
+            warn('Invalid fd index for glyph index.');
+            valid = false;
+          }
+          if (valid) {
+            localSubrToUse = fdArray[fdIndex].privateDict.subrsIndex;
+          }
+        } else if (localSubrIndex) {
+          localSubrToUse = localSubrIndex;
+        }
+        if (valid) {
+          valid = this.parseCharString(state, charstring, localSubrToUse,
+                                       globalSubrIndex);
+        }
+        if (state.width !== null) {
+          widths[i] = state.width;
+        }
+        if (state.seac !== null) {
+          seacs[i] = state.seac;
         }
         if (!valid) {
           // resetting invalid charstring to single 'endchar'
           charStrings.set(i, new Uint8Array([14]));
         }
       }
       return { charStrings: charStrings, seacs: seacs, widths: widths };
     },
@@ -30863,16 +30986,24 @@ var CFFEncoding = (function CFFEncodingC
   return CFFEncoding;
 })();
 
 var CFFFDSelect = (function CFFFDSelectClosure() {
   function CFFFDSelect(fdSelect, raw) {
     this.fdSelect = fdSelect;
     this.raw = raw;
   }
+  CFFFDSelect.prototype = {
+    getFDIndex: function CFFFDSelect_get(glyphIndex) {
+      if (glyphIndex < 0 || glyphIndex >= this.fdSelect.length) {
+        return -1;
+      }
+      return this.fdSelect[glyphIndex];
+    }
+  };
   return CFFFDSelect;
 })();
 
 // Helper class to keep track of where an offset is within the data and helps
 // filling in that offset once it's known.
 var CFFOffsetTracker = (function CFFOffsetTrackerClosure() {
   function CFFOffsetTracker() {
     this.offsets = {};
@@ -34550,20 +34681,18 @@ var Pattern = (function PatternClosure()
     }
   };
   return Pattern;
 })();
 
 var Shadings = {};
 
 // A small number to offset the first/last color stops so we can insert ones to
-// support extend.  Number.MIN_VALUE appears to be too small and breaks the
-// extend. 1e-7 works in FF but chrome seems to use an even smaller sized number
-// internally so we have to go bigger.
-Shadings.SMALL_NUMBER = 1e-2;
+// support extend. Number.MIN_VALUE is too small and breaks the extend.
+Shadings.SMALL_NUMBER = 1e-6;
 
 // Radial and axial shading have very similar implementations
 // If needed, the implementations can be broken into two classes
 Shadings.RadialAxial = (function RadialAxialClosure() {
   function RadialAxial(dict, matrix, xref, res) {
     this.matrix = matrix;
     this.coordsArr = dict.get('Coords');
     this.shadingType = dict.get('ShadingType');
@@ -38290,19 +38419,28 @@ AnnotationFactory.prototype = /** @lends
         if (isName(fieldType) && fieldType.name === 'Tx') {
           return new TextWidgetAnnotation(parameters);
         }
         return new WidgetAnnotation(parameters);
 
       case 'Popup':
         return new PopupAnnotation(parameters);
 
+      case 'Highlight':
+        return new HighlightAnnotation(parameters);
+
       case 'Underline':
         return new UnderlineAnnotation(parameters);
 
+      case 'Squiggly':
+        return new SquigglyAnnotation(parameters);
+
+      case 'StrikeOut':
+        return new StrikeOutAnnotation(parameters);
+
       default:
         warn('Unimplemented annotation type "' + subtype + '", ' +
              'falling back to base annotation');
         return new Annotation(parameters);
     }
   }
 };
 
@@ -38983,32 +39121,80 @@ var PopupAnnotation = (function PopupAnn
     this.data.hasHtml = (this.data.title || this.data.contents);
   }
 
   Util.inherit(PopupAnnotation, Annotation, {});
 
   return PopupAnnotation;
 })();
 
+var HighlightAnnotation = (function HighlightAnnotationClosure() {
+  function HighlightAnnotation(parameters) {
+    Annotation.call(this, parameters);
+
+    this.data.annotationType = AnnotationType.HIGHLIGHT;
+    this.data.hasHtml = true;
+
+    // PDF viewers completely ignore any border styles.
+    this.data.borderStyle.setWidth(0);
+  }
+
+  Util.inherit(HighlightAnnotation, Annotation, {});
+
+  return HighlightAnnotation;
+})();
+
 var UnderlineAnnotation = (function UnderlineAnnotationClosure() {
   function UnderlineAnnotation(parameters) {
     Annotation.call(this, parameters);
 
     this.data.annotationType = AnnotationType.UNDERLINE;
     this.data.hasHtml = true;
 
     // PDF viewers completely ignore any border styles.
     this.data.borderStyle.setWidth(0);
   }
 
   Util.inherit(UnderlineAnnotation, Annotation, {});
 
   return UnderlineAnnotation;
 })();
 
+var SquigglyAnnotation = (function SquigglyAnnotationClosure() {
+  function SquigglyAnnotation(parameters) {
+    Annotation.call(this, parameters);
+
+    this.data.annotationType = AnnotationType.SQUIGGLY;
+    this.data.hasHtml = true;
+
+    // PDF viewers completely ignore any border styles.
+    this.data.borderStyle.setWidth(0);
+  }
+
+  Util.inherit(SquigglyAnnotation, Annotation, {});
+
+  return SquigglyAnnotation;
+})();
+
+var StrikeOutAnnotation = (function StrikeOutAnnotationClosure() {
+  function StrikeOutAnnotation(parameters) {
+    Annotation.call(this, parameters);
+
+    this.data.annotationType = AnnotationType.STRIKEOUT;
+    this.data.hasHtml = true;
+
+    // PDF viewers completely ignore any border styles.
+    this.data.borderStyle.setWidth(0);
+  }
+
+  Util.inherit(StrikeOutAnnotation, Annotation, {});
+
+  return StrikeOutAnnotation;
+})();
+
 exports.Annotation = Annotation;
 exports.AnnotationBorderStyle = AnnotationBorderStyle;
 exports.AnnotationFactory = AnnotationFactory;
 }));
 
 
 (function (root, factory) {
   {
@@ -40413,12 +40599,15 @@ if (typeof window === 'undefined' &&
   initializeWorker();
 }
 
 exports.WorkerTask = WorkerTask;
 exports.WorkerMessageHandler = WorkerMessageHandler;
 }));
 
 
-}).call((typeof window === 'undefined') ? this : window);
-
-
-
+  }).call(pdfjsLibs);
+
+  exports.PDFJS = pdfjsLibs.pdfjsSharedGlobal.PDFJS;
+
+}));
+
+
--- a/browser/extensions/pdfjs/content/web/viewer.css
+++ b/browser/extensions/pdfjs/content/web/viewer.css
@@ -124,17 +124,20 @@
   border-bottom: 1px solid #000000;
   padding-bottom: 0.2em;
 }
 
 .annotationLayer .popup p {
   padding-top: 0.2em;
 }
 
-.annotationLayer .underlineAnnotation {
+.annotationLayer .highlightAnnotation,
+.annotationLayer .underlineAnnotation,
+.annotationLayer .squigglyAnnotation,
+.annotationLayer .strikeoutAnnotation {
   cursor: pointer;
 }
 
 .pdfViewer .canvasWrapper {
   overflow: hidden;
 }
 
 .pdfViewer .page {
--- a/browser/extensions/pdfjs/content/web/viewer.js
+++ b/browser/extensions/pdfjs/content/web/viewer.js
@@ -47,22 +47,16 @@ var mozL10n = document.mozL10n || docume
 var CSS_UNITS = 96.0 / 72.0;
 var DEFAULT_SCALE_VALUE = 'auto';
 var DEFAULT_SCALE = 1.0;
 var UNKNOWN_SCALE = 0;
 var MAX_AUTO_SCALE = 1.25;
 var SCROLLBAR_PADDING = 40;
 var VERTICAL_PADDING = 5;
 
-var NullCharactersRegExp = /\x00/g;
-
-function removeNullCharacters(str) {
-  return str.replace(NullCharactersRegExp, '');
-}
-
 function getFileName(url) {
   var anchor = url.indexOf('#');
   var query = url.indexOf('?');
   var end = Math.min(
     anchor > 0 ? anchor : url.length,
     query > 0 ? query : url.length);
   return url.substring(url.lastIndexOf('/', end) + 1, end);
 }
@@ -5823,17 +5817,17 @@ var PDFOutlineView = (function PDFOutlin
       while (queue.length > 0) {
         var levelData = queue.shift();
         for (var i = 0, len = levelData.items.length; i < len; i++) {
           var item = levelData.items[i];
           var div = document.createElement('div');
           div.className = 'outlineItem';
           var element = document.createElement('a');
           this._bindLink(element, item);
-          element.textContent = removeNullCharacters(item.title);
+          element.textContent = PDFJS.removeNullCharacters(item.title);
           div.appendChild(element);
 
           if (item.items.length > 0) {
             hasAnyNesting = true;
             this._addToggleButton(div);
 
             var itemsDiv = document.createElement('div');
             itemsDiv.className = 'outlineItems';
@@ -5927,17 +5921,17 @@ var PDFAttachmentView = (function PDFAtt
 
       for (var i = 0; i < attachmentsCount; i++) {
         var item = attachments[names[i]];
         var filename = getFileName(item.filename);
         var div = document.createElement('div');
         div.className = 'attachmentsItem';
         var button = document.createElement('button');
         this._bindLink(button, item.content, filename);
-        button.textContent = removeNullCharacters(filename);
+        button.textContent = PDFJS.removeNullCharacters(filename);
         div.appendChild(button);
         this.container.appendChild(div);
       }
 
       this._dispatchEvent(attachmentsCount);
     }
   };