Bug 1658313 - Update pdf.js to version 2.6.234. r=bdahl
☠☠ backed out by 51b465c34f8a ☠ ☠
authorRyan VanderMeulen <ryanvm@gmail.com>
Wed, 12 Aug 2020 03:13:14 +0000
changeset 544352 62990ef4ea78c3e957f85d38bae64fe97be329fd
parent 544351 cf8c30f7059c6a5e497bd10286c0186b39308d9c
child 544353 fad66448e049eb8fcebe1b56d172d3b1c61ed6e8
push id123986
push userrvandermeulen@mozilla.com
push dateWed, 12 Aug 2020 03:16:46 +0000
treeherderautoland@62990ef4ea78 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbdahl
bugs1658313
milestone81.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 1658313 - Update pdf.js to version 2.6.234. r=bdahl Differential Revision: https://phabricator.services.mozilla.com/D86557
toolkit/components/pdfjs/README.mozilla
toolkit/components/pdfjs/content/build/pdf.js
toolkit/components/pdfjs/content/build/pdf.worker.js
toolkit/components/pdfjs/content/web/viewer.css
toolkit/components/pdfjs/content/web/viewer.js
toolkit/components/pdfjs/moz.yaml
--- a/toolkit/components/pdfjs/README.mozilla
+++ b/toolkit/components/pdfjs/README.mozilla
@@ -1,5 +1,5 @@
 This is the PDF.js project output, https://github.com/mozilla/pdf.js
 
-Current extension version is: 2.6.207
+Current extension version is: 2.6.234
 
-Taken from upstream commit: 63e33a589
+Taken from upstream commit: 6620861c7
--- a/toolkit/components/pdfjs/content/build/pdf.js
+++ b/toolkit/components/pdfjs/content/build/pdf.js
@@ -330,18 +330,18 @@ var _annotation_layer = __w_pdfjs_requir
 var _api_compatibility = __w_pdfjs_require__(9);
 
 var _worker_options = __w_pdfjs_require__(12);
 
 var _text_layer = __w_pdfjs_require__(20);
 
 var _svg = __w_pdfjs_require__(21);
 
-const pdfjsVersion = '2.6.207';
-const pdfjsBuild = '63e33a589';
+const pdfjsVersion = '2.6.234';
+const pdfjsBuild = '6620861c7';
 ;
 
 /***/ }),
 /* 1 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
@@ -398,22 +398,30 @@ class BaseCanvasFactory {
     canvasAndContext.context = null;
   }
 
 }
 
 exports.BaseCanvasFactory = BaseCanvasFactory;
 
 class DOMCanvasFactory extends BaseCanvasFactory {
+  constructor({
+    ownerDocument = globalThis.document
+  } = {}) {
+    super();
+    this._document = ownerDocument;
+  }
+
   create(width, height) {
     if (width <= 0 || height <= 0) {
       throw new Error("Invalid canvas size");
     }
 
-    const canvas = document.createElement("canvas");
+    const canvas = this._document.createElement("canvas");
+
     const context = canvas.getContext("2d");
     canvas.width = width;
     canvas.height = height;
     return {
       canvas,
       context
     };
   }
@@ -839,16 +847,17 @@ exports.PDFDateString = PDFDateString;
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.arrayByteLength = arrayByteLength;
 exports.arraysToBytes = arraysToBytes;
 exports.assert = assert;
 exports.bytesToString = bytesToString;
 exports.createPromiseCapability = createPromiseCapability;
+exports.escapeString = escapeString;
 exports.getVerbosityLevel = getVerbosityLevel;
 exports.info = info;
 exports.isArrayBuffer = isArrayBuffer;
 exports.isArrayEqual = isArrayEqual;
 exports.isBool = isBool;
 exports.isNum = isNum;
 exports.isString = isString;
 exports.isSameOrigin = isSameOrigin;
@@ -1558,16 +1567,20 @@ function stringToPDFString(str) {
       const code = PDFStringTranslateTable[str.charCodeAt(i)];
       strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
     }
   }
 
   return strBuf.join("");
 }
 
+function escapeString(str) {
+  return str.replace(/([\(\)\\])/g, "\\$1");
+}
+
 function stringToUTF8String(str) {
   return decodeURIComponent(escape(str));
 }
 
 function utf8StringToString(str) {
   return unescape(encodeURIComponent(str));
 }
 
@@ -1800,16 +1813,20 @@ function getDocument(src) {
   if (typeof params.isEvalSupported !== "boolean") {
     params.isEvalSupported = true;
   }
 
   if (typeof params.disableFontFace !== "boolean") {
     params.disableFontFace = _api_compatibility.apiCompatibilityParams.disableFontFace || false;
   }
 
+  if (typeof params.ownerDocument === "undefined") {
+    params.ownerDocument = globalThis.document;
+  }
+
   if (typeof params.disableRange !== "boolean") {
     params.disableRange = false;
   }
 
   if (typeof params.disableStream !== "boolean") {
     params.disableStream = false;
   }
 
@@ -1884,17 +1901,17 @@ function _fetchDocument(worker, source, 
   if (pdfDataRangeTransport) {
     source.length = pdfDataRangeTransport.length;
     source.initialData = pdfDataRangeTransport.initialData;
     source.progressiveDone = pdfDataRangeTransport.progressiveDone;
   }
 
   return worker.messageHandler.sendWithPromise("GetDocRequest", {
     docId,
-    apiVersion: '2.6.207',
+    apiVersion: '2.6.234',
     source: {
       data: source.data,
       url: source.url,
       password: source.password,
       disableAutoFetch: source.disableAutoFetch,
       rangeChunkSize: source.rangeChunkSize,
       length: source.length
     },
@@ -2131,19 +2148,20 @@ class PDFDocumentProxy {
     return this._transport.loadingTask;
   }
 
 }
 
 exports.PDFDocumentProxy = PDFDocumentProxy;
 
 class PDFPageProxy {
-  constructor(pageIndex, pageInfo, transport, pdfBug = false) {
+  constructor(pageIndex, pageInfo, transport, ownerDocument, pdfBug = false) {
     this._pageIndex = pageIndex;
     this._pageInfo = pageInfo;
+    this._ownerDocument = ownerDocument;
     this._transport = transport;
     this._stats = pdfBug ? new _display_utils.StatTimer() : null;
     this._pdfBug = pdfBug;
     this.commonObjs = transport.commonObjs;
     this.objs = new PDFObjects();
     this.cleanupAfterRender = false;
     this.pendingCleanup = false;
     this._intentStates = new Map();
@@ -2230,17 +2248,19 @@ class PDFPageProxy {
       this._intentStates.set(renderingIntent, intentState);
     }
 
     if (intentState.streamReaderCancelTimeout) {
       clearTimeout(intentState.streamReaderCancelTimeout);
       intentState.streamReaderCancelTimeout = null;
     }
 
-    const canvasFactoryInstance = canvasFactory || new DefaultCanvasFactory();
+    const canvasFactoryInstance = canvasFactory || new DefaultCanvasFactory({
+      ownerDocument: this._ownerDocument
+    });
     const webGLContext = new _webgl.WebGLContext({
       enable: enableWebGL
     });
 
     if (!intentState.displayReadyCapability) {
       intentState.displayReadyCapability = (0, _util.createPromiseCapability)();
       intentState.operatorList = {
         fnArray: [],
@@ -2251,17 +2271,17 @@ class PDFPageProxy {
       if (this._stats) {
         this._stats.time("Page Request");
       }
 
       this._pumpOperatorList({
         pageIndex: this._pageIndex,
         intent: renderingIntent,
         renderInteractiveForms: renderInteractiveForms === true,
-        annotationStorage
+        annotationStorage: annotationStorage && annotationStorage.getAll() || null
       });
     }
 
     const complete = error => {
       const i = intentState.renderTasks.indexOf(internalRenderTask);
 
       if (i >= 0) {
         intentState.renderTasks.splice(i, 1);
@@ -3018,17 +3038,18 @@ exports.PDFWorker = PDFWorker;
 
 class WorkerTransport {
   constructor(messageHandler, loadingTask, networkStream, params) {
     this.messageHandler = messageHandler;
     this.loadingTask = loadingTask;
     this.commonObjs = new PDFObjects();
     this.fontLoader = new _font_loader.FontLoader({
       docId: loadingTask.docId,
-      onUnsupportedFeature: this._onUnsupportedFeature.bind(this)
+      onUnsupportedFeature: this._onUnsupportedFeature.bind(this),
+      ownerDocument: params.ownerDocument
     });
     this._params = params;
     this.CMapReaderFactory = new params.CMapReaderFactory({
       baseUrl: params.cMapUrl,
       isCompressed: params.cMapPacked
     });
     this.destroyed = false;
     this.destroyCapability = null;
@@ -3422,17 +3443,17 @@ class WorkerTransport {
 
     const promise = this.messageHandler.sendWithPromise("GetPage", {
       pageIndex
     }).then(pageInfo => {
       if (this.destroyed) {
         throw new Error("Transport destroyed");
       }
 
-      const page = new PDFPageProxy(pageIndex, pageInfo, this, this._params.pdfBug);
+      const page = new PDFPageProxy(pageIndex, pageInfo, this, this._params.ownerDocument, this._params.pdfBug);
       this.pageCache[pageIndex] = page;
       return page;
     });
     this.pagePromises[pageIndex] = promise;
     return promise;
   }
 
   getPageIndex(ref) {
@@ -3785,19 +3806,19 @@ const InternalRenderTask = function Inte
       }
     }
 
   }
 
   return InternalRenderTask;
 }();
 
-const version = '2.6.207';
+const version = '2.6.234';
 exports.version = version;
-const build = '63e33a589';
+const build = '6620861c7';
 exports.build = build;
 
 /***/ }),
 /* 6 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
@@ -3807,49 +3828,53 @@ Object.defineProperty(exports, "__esModu
 });
 exports.FontLoader = exports.FontFaceObject = void 0;
 
 var _util = __w_pdfjs_require__(2);
 
 class BaseFontLoader {
   constructor({
     docId,
-    onUnsupportedFeature
+    onUnsupportedFeature,
+    ownerDocument = globalThis.document
   }) {
     if (this.constructor === BaseFontLoader) {
       (0, _util.unreachable)("Cannot initialize BaseFontLoader.");
     }
 
     this.docId = docId;
     this._onUnsupportedFeature = onUnsupportedFeature;
+    this._document = ownerDocument;
     this.nativeFontFaces = [];
     this.styleElement = null;
   }
 
   addNativeFontFace(nativeFontFace) {
     this.nativeFontFaces.push(nativeFontFace);
-    document.fonts.add(nativeFontFace);
+
+    this._document.fonts.add(nativeFontFace);
   }
 
   insertRule(rule) {
     let styleElement = this.styleElement;
 
     if (!styleElement) {
-      styleElement = this.styleElement = document.createElement("style");
+      styleElement = this.styleElement = this._document.createElement("style");
       styleElement.id = `PDFJS_FONT_STYLE_TAG_${this.docId}`;
-      document.documentElement.getElementsByTagName("head")[0].appendChild(styleElement);
+
+      this._document.documentElement.getElementsByTagName("head")[0].appendChild(styleElement);
     }
 
     const styleSheet = styleElement.sheet;
     styleSheet.insertRule(rule, styleSheet.cssRules.length);
   }
 
   clear() {
-    this.nativeFontFaces.forEach(function (nativeFontFace) {
-      document.fonts.delete(nativeFontFace);
+    this.nativeFontFaces.forEach(nativeFontFace => {
+      this._document.fonts.delete(nativeFontFace);
     });
     this.nativeFontFaces.length = 0;
 
     if (this.styleElement) {
       this.styleElement.remove();
       this.styleElement = null;
     }
   }
@@ -3900,17 +3925,17 @@ class BaseFontLoader {
     }
   }
 
   _queueLoadingCallback(callback) {
     (0, _util.unreachable)("Abstract method `_queueLoadingCallback`.");
   }
 
   get isFontLoadingAPISupported() {
-    const supported = typeof document !== "undefined" && !!document.fonts;
+    const supported = typeof this._document !== "undefined" && !!this._document.fonts;
     return (0, _util.shadow)(this, "isFontLoadingAPISupported", supported);
   }
 
   get isSyncFontLoadingSupported() {
     (0, _util.unreachable)("Abstract method `isSyncFontLoadingSupported`.");
   }
 
   get _loadTestFont() {
@@ -7374,23 +7399,17 @@ class Metadata {
     }
   }
 
   get(name) {
     return this._metadataMap.has(name) ? this._metadataMap.get(name) : null;
   }
 
   getAll() {
-    const obj = Object.create(null);
-
-    for (const [key, value] of this._metadataMap) {
-      obj[key] = value;
-    }
-
-    return obj;
+    return Object.fromEntries(this._metadataMap);
   }
 
   has(name) {
     return this._metadataMap.has(name);
   }
 
 }
 
@@ -9092,29 +9111,36 @@ class WidgetAnnotationElement extends An
 class TextWidgetAnnotationElement extends WidgetAnnotationElement {
   constructor(parameters) {
     const isRenderable = parameters.renderInteractiveForms || !parameters.data.hasAppearance && !!parameters.data.fieldValue;
     super(parameters, isRenderable);
   }
 
   render() {
     const TEXT_ALIGNMENT = ["left", "center", "right"];
+    const storage = this.annotationStorage;
+    const id = this.data.id;
     this.container.className = "textWidgetAnnotation";
     let element = null;
 
     if (this.renderInteractiveForms) {
+      const textContent = storage.getOrCreateValue(id, this.data.fieldValue);
+
       if (this.data.multiLine) {
         element = document.createElement("textarea");
-        element.textContent = this.data.fieldValue;
+        element.textContent = textContent;
       } else {
         element = document.createElement("input");
         element.type = "text";
-        element.setAttribute("value", this.data.fieldValue);
-      }
-
+        element.setAttribute("value", textContent);
+      }
+
+      element.addEventListener("input", function (event) {
+        storage.setValue(id, event.target.value);
+      });
       element.disabled = this.data.readOnly;
       element.name = this.data.fieldName;
 
       if (this.data.maxLen !== null) {
         element.maxLength = this.data.maxLen;
       }
 
       if (this.data.comb) {
@@ -9248,16 +9274,18 @@ class PushButtonWidgetAnnotationElement 
 
 class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
   constructor(parameters) {
     super(parameters, parameters.renderInteractiveForms);
   }
 
   render() {
     this.container.className = "choiceWidgetAnnotation";
+    const storage = this.annotationStorage;
+    const id = this.data.id;
     const selectElement = document.createElement("select");
     selectElement.disabled = this.data.readOnly;
     selectElement.name = this.data.fieldName;
 
     if (!this.data.combo) {
       selectElement.size = this.data.options.length;
 
       if (this.data.multiSelect) {
@@ -9267,21 +9295,27 @@ class ChoiceWidgetAnnotationElement exte
 
     for (const option of this.data.options) {
       const optionElement = document.createElement("option");
       optionElement.textContent = option.displayValue;
       optionElement.value = option.exportValue;
 
       if (this.data.fieldValue.includes(option.displayValue)) {
         optionElement.setAttribute("selected", true);
+        storage.setValue(id, option.displayValue);
       }
 
       selectElement.appendChild(optionElement);
     }
 
+    selectElement.addEventListener("input", function (event) {
+      const options = event.target.options;
+      const value = options[options.selectedIndex].text;
+      storage.setValue(id, value);
+    });
     this.container.appendChild(selectElement);
     return this.container;
   }
 
 }
 
 class PopupAnnotationElement extends AnnotationElement {
   constructor(parameters) {
@@ -10280,16 +10314,17 @@ var renderTextLayer = function renderTex
     viewport,
     textDivs,
     textContentItemsStr,
     enhanceTextSelection
   }) {
     this._textContent = textContent;
     this._textContentStream = textContentStream;
     this._container = container;
+    this._document = container.ownerDocument;
     this._viewport = viewport;
     this._textDivs = textDivs || [];
     this._textContentItemsStr = textContentItemsStr || [];
     this._enhanceTextSelection = !!enhanceTextSelection;
     this._fontInspectorEnabled = !!(globalThis.FontInspector && globalThis.FontInspector.enabled);
     this._reader = null;
     this._layoutTextLastFontSize = null;
     this._layoutTextLastFontFamily = null;
@@ -10386,17 +10421,19 @@ var renderTextLayer = function renderTex
       this._textDivProperties.set(textDiv, textDivProperties);
 
       this._container.appendChild(textDiv);
     },
 
     _render: function TextLayer_render(timeout) {
       const capability = (0, _util.createPromiseCapability)();
       let styleCache = Object.create(null);
-      const canvas = document.createElement("canvas");
+
+      const canvas = this._document.createElement("canvas");
+
       canvas.mozOpaque = true;
       this._layoutTextCtx = canvas.getContext("2d", {
         alpha: false
       });
 
       if (this._textContent) {
         const textItems = this._textContent.items;
         const textStyles = this._textContent.styles;
--- a/toolkit/components/pdfjs/content/build/pdf.worker.js
+++ b/toolkit/components/pdfjs/content/build/pdf.worker.js
@@ -130,18 +130,18 @@ Object.defineProperty(exports, "WorkerMe
   enumerable: true,
   get: function () {
     return _worker.WorkerMessageHandler;
   }
 });
 
 var _worker = __w_pdfjs_require__(1);
 
-const pdfjsVersion = '2.6.207';
-const pdfjsBuild = '63e33a589';
+const pdfjsVersion = '2.6.234';
+const pdfjsBuild = '6620861c7';
 
 /***/ }),
 /* 1 */
 /***/ (function(module, exports, __w_pdfjs_require__) {
 
 "use strict";
 
 
@@ -224,17 +224,17 @@ class WorkerMessageHandler {
 
   static createDocumentHandler(docParams, port) {
     var pdfManager;
     var terminated = false;
     var cancelXHRs = null;
     var WorkerTasks = [];
     const verbosity = (0, _util.getVerbosityLevel)();
     const apiVersion = docParams.apiVersion;
-    const workerVersion = '2.6.207';
+    const workerVersion = '2.6.234';
 
     if (apiVersion !== workerVersion) {
       throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`);
     }
 
     var docId = docParams.docId;
     var docBaseUrl = docParams.docBaseUrl;
     var workerHandlerName = docParams.docId + "_worker";
@@ -680,16 +680,17 @@ if (typeof window === "undefined" && !_i
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.arrayByteLength = arrayByteLength;
 exports.arraysToBytes = arraysToBytes;
 exports.assert = assert;
 exports.bytesToString = bytesToString;
 exports.createPromiseCapability = createPromiseCapability;
+exports.escapeString = escapeString;
 exports.getVerbosityLevel = getVerbosityLevel;
 exports.info = info;
 exports.isArrayBuffer = isArrayBuffer;
 exports.isArrayEqual = isArrayEqual;
 exports.isBool = isBool;
 exports.isNum = isNum;
 exports.isString = isString;
 exports.isSameOrigin = isSameOrigin;
@@ -1399,16 +1400,20 @@ function stringToPDFString(str) {
       const code = PDFStringTranslateTable[str.charCodeAt(i)];
       strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
     }
   }
 
   return strBuf.join("");
 }
 
+function escapeString(str) {
+  return str.replace(/([\(\)\\])/g, "\\$1");
+}
+
 function stringToUTF8String(str) {
   return decodeURIComponent(escape(str));
 }
 
 function utf8StringToString(str) {
   return unescape(encodeURIComponent(str));
 }
 
@@ -19301,24 +19306,165 @@ class WidgetAnnotation extends Annotatio
     return !!(this.data.fieldFlags & flag);
   }
 
   getOperatorList(evaluator, task, renderForms, annotationStorage) {
     if (renderForms) {
       return Promise.resolve(new _operator_list.OperatorList());
     }
 
-    return super.getOperatorList(evaluator, task, renderForms, annotationStorage);
+    if (!this._hasText) {
+      return super.getOperatorList(evaluator, task, renderForms, annotationStorage);
+    }
+
+    return this._getAppearance(evaluator, task, annotationStorage).then(content => {
+      if (this.appearance && content === null) {
+        return super.getOperatorList(evaluator, task, renderForms, annotationStorage);
+      }
+
+      const operatorList = new _operator_list.OperatorList();
+
+      if (!this.data.defaultAppearance || content === null) {
+        return operatorList;
+      }
+
+      const matrix = [1, 0, 0, 1, 0, 0];
+      const bbox = [0, 0, this.data.rect[2] - this.data.rect[0], this.data.rect[3] - this.data.rect[1]];
+      const transform = getTransformMatrix(this.data.rect, bbox, matrix);
+      operatorList.addOp(_util.OPS.beginAnnotation, [this.data.rect, transform, matrix]);
+      const stream = new _stream.StringStream(content);
+      return evaluator.getOperatorList({
+        stream,
+        task,
+        resources: this.fieldResources,
+        operatorList
+      }).then(function () {
+        operatorList.addOp(_util.OPS.endAnnotation, []);
+        return operatorList;
+      });
+    });
+  }
+
+  async _getAppearance(evaluator, task, annotationStorage) {
+    const isPassword = this.hasFieldFlag(_util.AnnotationFieldFlag.PASSWORD);
+
+    if (!annotationStorage || isPassword) {
+      return null;
+    }
+
+    const value = annotationStorage[this.data.id];
+
+    if (value === "") {
+      return "";
+    }
+
+    const defaultPadding = 2;
+    const hPadding = defaultPadding;
+    const totalHeight = this.data.rect[3] - this.data.rect[1];
+    const totalWidth = this.data.rect[2] - this.data.rect[0];
+    const fontInfo = await this._getFontData(evaluator, task);
+    const [font, fontName] = fontInfo;
+    let fontSize = fontInfo[2];
+    fontSize = this._computeFontSize(font, fontName, fontSize, totalHeight);
+    let descent = font.descent;
+
+    if (isNaN(descent)) {
+      descent = 0;
+    }
+
+    const vPadding = defaultPadding + Math.abs(descent) * fontSize;
+    const defaultAppearance = this.data.defaultAppearance;
+    const alignment = this.data.textAlignment;
+
+    if (this.data.comb) {
+      return this._getCombAppearance(defaultAppearance, value, totalWidth, hPadding, vPadding);
+    }
+
+    if (this.data.multiLine) {
+      return this._getMultilineAppearance(defaultAppearance, value, font, fontSize, totalWidth, totalHeight, alignment, hPadding, vPadding);
+    }
+
+    if (alignment === 0 || alignment > 2) {
+      return "/Tx BMC q BT " + defaultAppearance + ` 1 0 0 1 ${hPadding} ${vPadding} Tm (${(0, _util.escapeString)(value)}) Tj` + " ET Q EMC";
+    }
+
+    const renderedText = this._renderText(value, font, fontSize, totalWidth, alignment, hPadding, vPadding);
+
+    return "/Tx BMC q BT " + defaultAppearance + ` 1 0 0 1 0 0 Tm ${renderedText}` + " ET Q EMC";
+  }
+
+  async _getFontData(evaluator, task) {
+    const operatorList = new _operator_list.OperatorList();
+    const initialState = {
+      fontSize: 0,
+      font: null,
+      fontName: null,
+
+      clone() {
+        return this;
+      }
+
+    };
+    await evaluator.getOperatorList({
+      stream: new _stream.StringStream(this.data.defaultAppearance),
+      task,
+      resources: this.fieldResources,
+      operatorList,
+      initialState
+    });
+    return [initialState.font, initialState.fontName, initialState.fontSize];
+  }
+
+  _computeFontSize(font, fontName, fontSize, height) {
+    if (fontSize === null || fontSize === 0) {
+      const em = font.charsToGlyphs("M", true)[0].width / 1000;
+      const capHeight = 0.7 * em;
+      fontSize = Math.max(1, Math.floor(height / (1.5 * capHeight)));
+      let fontRegex = new RegExp(`/${fontName}\\s+[0-9\.]+\\s+Tf`);
+
+      if (this.data.defaultAppearance.search(fontRegex) === -1) {
+        fontRegex = new RegExp(`/${fontName}\\s+Tf`);
+      }
+
+      this.data.defaultAppearance = this.data.defaultAppearance.replace(fontRegex, `/${fontName} ${fontSize} Tf`);
+    }
+
+    return fontSize;
+  }
+
+  _renderText(text, font, fontSize, totalWidth, alignment, hPadding, vPadding) {
+    const glyphs = font.charsToGlyphs(text);
+    const scale = fontSize / 1000;
+    let width = 0;
+
+    for (const glyph of glyphs) {
+      width += glyph.width * scale;
+    }
+
+    let shift;
+
+    if (alignment === 1) {
+      shift = (totalWidth - width) / 2;
+    } else if (alignment === 2) {
+      shift = totalWidth - width - hPadding;
+    } else {
+      shift = hPadding;
+    }
+
+    shift = shift.toFixed(2);
+    vPadding = vPadding.toFixed(2);
+    return `${shift} ${vPadding} Td (${(0, _util.escapeString)(text)}) Tj`;
   }
 
 }
 
 class TextWidgetAnnotation extends WidgetAnnotation {
   constructor(params) {
     super(params);
+    this._hasText = true;
     const dict = params.dict;
     this.data.fieldValue = (0, _util.stringToPDFString)(this.data.fieldValue || "");
     let alignment = (0, _core_utils.getInheritableProperty)({
       dict,
       key: "Q"
     });
 
     if (!Number.isInteger(alignment) || alignment < 0 || alignment > 2) {
@@ -19335,36 +19481,96 @@ class TextWidgetAnnotation extends Widge
       maximumLength = null;
     }
 
     this.data.maxLen = maximumLength;
     this.data.multiLine = this.hasFieldFlag(_util.AnnotationFieldFlag.MULTILINE);
     this.data.comb = this.hasFieldFlag(_util.AnnotationFieldFlag.COMB) && !this.hasFieldFlag(_util.AnnotationFieldFlag.MULTILINE) && !this.hasFieldFlag(_util.AnnotationFieldFlag.PASSWORD) && !this.hasFieldFlag(_util.AnnotationFieldFlag.FILESELECT) && this.data.maxLen !== null;
   }
 
-  getOperatorList(evaluator, task, renderForms, annotationStorage) {
-    if (renderForms || this.appearance) {
-      return super.getOperatorList(evaluator, task, renderForms, annotationStorage);
-    }
-
-    const operatorList = new _operator_list.OperatorList();
-
-    if (!this.data.defaultAppearance) {
-      return Promise.resolve(operatorList);
-    }
-
-    const stream = new _stream.Stream((0, _util.stringToBytes)(this.data.defaultAppearance));
-    return evaluator.getOperatorList({
-      stream,
-      task,
-      resources: this.fieldResources,
-      operatorList
-    }).then(function () {
-      return operatorList;
-    });
+  _getCombAppearance(defaultAppearance, text, width, hPadding, vPadding) {
+    const combWidth = (width / this.data.maxLen).toFixed(2);
+    const buf = [];
+
+    for (const character of text) {
+      buf.push(`(${(0, _util.escapeString)(character)}) Tj`);
+    }
+
+    const renderedComb = buf.join(` ${combWidth} 0 Td `);
+    return "/Tx BMC q BT " + defaultAppearance + ` 1 0 0 1 ${hPadding} ${vPadding} Tm ${renderedComb}` + " ET Q EMC";
+  }
+
+  _getMultilineAppearance(defaultAppearance, text, font, fontSize, width, height, alignment, hPadding, vPadding) {
+    const lines = text.split(/\r\n|\r|\n/);
+    const buf = [];
+    const totalWidth = width - 2 * hPadding;
+
+    for (const line of lines) {
+      const chunks = this._splitLine(line, font, fontSize, totalWidth);
+
+      for (const chunk of chunks) {
+        const padding = buf.length === 0 ? hPadding : 0;
+        buf.push(this._renderText(chunk, font, fontSize, width, alignment, padding, -fontSize));
+      }
+    }
+
+    const renderedText = buf.join("\n");
+    return "/Tx BMC q BT " + defaultAppearance + ` 1 0 0 1 0 ${height} Tm ${renderedText}` + " ET Q EMC";
+  }
+
+  _splitLine(line, font, fontSize, width) {
+    if (line.length <= 1) {
+      return [line];
+    }
+
+    const scale = fontSize / 1000;
+    const whitespace = font.charsToGlyphs(" ", true)[0].width * scale;
+    const chunks = [];
+    let lastSpacePos = -1,
+        startChunk = 0,
+        currentWidth = 0;
+
+    for (let i = 0, ii = line.length; i < ii; i++) {
+      const character = line.charAt(i);
+
+      if (character === " ") {
+        if (currentWidth + whitespace > width) {
+          chunks.push(line.substring(startChunk, i));
+          startChunk = i;
+          currentWidth = whitespace;
+          lastSpacePos = -1;
+        } else {
+          currentWidth += whitespace;
+          lastSpacePos = i;
+        }
+      } else {
+        const charWidth = font.charsToGlyphs(character, false)[0].width * scale;
+
+        if (currentWidth + charWidth > width) {
+          if (lastSpacePos !== -1) {
+            chunks.push(line.substring(startChunk, lastSpacePos + 1));
+            startChunk = i = lastSpacePos + 1;
+            lastSpacePos = -1;
+            currentWidth = 0;
+          } else {
+            chunks.push(line.substring(startChunk, i));
+            startChunk = i;
+            currentWidth = charWidth;
+          }
+        } else {
+          currentWidth += charWidth;
+        }
+      }
+    }
+
+    if (startChunk < line.length) {
+      chunks.push(line.substring(startChunk, line.length));
+    }
+
+    return chunks;
   }
 
 }
 
 class ButtonWidgetAnnotation extends WidgetAnnotation {
   constructor(params) {
     super(params);
     this.checkedAppearance = null;
@@ -19517,16 +19723,17 @@ class ChoiceWidgetAnnotation extends Wid
     }
 
     if (!Array.isArray(this.data.fieldValue)) {
       this.data.fieldValue = [this.data.fieldValue];
     }
 
     this.data.combo = this.hasFieldFlag(_util.AnnotationFieldFlag.COMBO);
     this.data.multiSelect = this.hasFieldFlag(_util.AnnotationFieldFlag.MULTISELECT);
+    this._hasText = true;
   }
 
 }
 
 class TextAnnotation extends MarkupAnnotation {
   constructor(parameters) {
     const DEFAULT_ICON_SIZE = 22;
     super(parameters);
@@ -21088,21 +21295,23 @@ class PartialEvaluator {
         return;
       }
 
       throw reason;
     });
   }
 
   handleSetFont(resources, fontArgs, fontRef, operatorList, task, state) {
-    var fontName;
+    var fontName,
+        fontSize = 0;
 
     if (fontArgs) {
       fontArgs = fontArgs.slice();
       fontName = fontArgs[0].name;
+      fontSize = fontArgs[1];
     }
 
     return this.loadFont(fontName, fontRef, resources).then(translated => {
       if (!translated.font.isType3Font) {
         return translated;
       }
 
       return translated.loadType3Data(this, resources, task).then(function () {
@@ -21116,16 +21325,18 @@ class PartialEvaluator {
           loadedName: "g_font_error",
           font: new _fonts.ErrorFont(`Type3 font load error: ${reason}`),
           dict: translated.font,
           extraProperties: this.options.fontExtraProperties
         });
       });
     }).then(translated => {
       state.font = translated.font;
+      state.fontSize = fontSize;
+      state.fontName = fontName;
       translated.send(this.handler);
       return translated.loadedName;
     });
   }
 
   handleText(chars, state) {
     const font = state.font;
     const glyphs = font.charsToGlyphs(chars);
--- a/toolkit/components/pdfjs/content/web/viewer.css
+++ b/toolkit/components/pdfjs/content/web/viewer.css
@@ -1506,126 +1506,102 @@ a:focus > .thumbnail > .thumbnailSelecti
 }
 
 #outlineView,
 #attachmentsView {
   position: absolute;
   width: calc(100% - 8px);
   top: 0;
   bottom: 0;
+  padding: 4px 4px 0;
   overflow: auto;
   user-select: none;
 }
 
-#outlineView {
-  padding: 4px 4px 0;
-}
-#attachmentsView {
-  padding: 3px 4px 0;
-}
-
-html[dir='ltr'] .outlineWithDeepNesting > .outlineItem,
-html[dir='ltr'] .outlineItem > .outlineItems {
+html[dir='ltr'] .treeWithDeepNesting > .treeItem,
+html[dir='ltr'] .treeItem > .treeItems {
   margin-left: 20px;
 }
 
-html[dir='rtl'] .outlineWithDeepNesting > .outlineItem,
-html[dir='rtl'] .outlineItem > .outlineItems {
+html[dir='rtl'] .treeWithDeepNesting > .treeItem,
+html[dir='rtl'] .treeItem > .treeItems {
   margin-right: 20px;
 }
 
-.outlineItem > a,
-.attachmentsItem > button {
+.treeItem > a {
   text-decoration: none;
   display: inline-block;
   min-width: 95%;
   min-width: calc(100% - 4px); /* Subtract the right padding (left, in RTL mode)
                                   of the container. */
   height: auto;
   margin-bottom: 1px;
   border-radius: 2px;
   color: rgba(255, 255, 255, 0.8);
   font-size: 13px;
   line-height: 15px;
   user-select: none;
   white-space: normal;
+  cursor: pointer;
 }
-
-.attachmentsItem > button {
-  border: 0 none;
-  background: none;
-  cursor: pointer;
-  width: 100%;
-}
-
-html[dir='ltr'] .outlineItem > a {
+html[dir='ltr'] .treeItem > a {
   padding: 2px 0 5px 4px;
 }
-html[dir='ltr'] .attachmentsItem > button {
-  padding: 2px 0 3px 7px;
-  text-align: left;
+html[dir='rtl'] .treeItem > a {
+  padding: 2px 4px 5px 0;
 }
 
-html[dir='rtl'] .outlineItem > a {
-  padding: 2px 4px 5px 0;
-}
-html[dir='rtl'] .attachmentsItem > button {
-  padding: 2px 7px 3px 0;
-  text-align: right;
-}
-
-.outlineItemToggler {
+.treeItemToggler {
   position: relative;
   height: 0;
   width: 0;
   color: rgba(255, 255, 255, 0.5);
 }
-.outlineItemToggler::before {
+.treeItemToggler::before {
   content: url(images/treeitem-expanded.png);
   display: inline-block;
   position: absolute;
 }
-.outlineItemToggler.outlineItemsHidden::before {
+.treeItemToggler.treeItemsHidden::before {
   content: url(images/treeitem-collapsed.png);
 }
-html[dir='rtl'] .outlineItemToggler.outlineItemsHidden::before {
+html[dir='rtl'] .treeItemToggler.treeItemsHidden::before {
   transform: scaleX(-1);
 }
-.outlineItemToggler.outlineItemsHidden ~ .outlineItems {
+.treeItemToggler.treeItemsHidden ~ .treeItems {
   display: none;
 }
-html[dir='ltr'] .outlineItemToggler {
+html[dir='ltr'] .treeItemToggler {
   float: left;
 }
-html[dir='rtl'] .outlineItemToggler {
+html[dir='rtl'] .treeItemToggler {
   float: right;
 }
-html[dir='ltr'] .outlineItemToggler::before {
+html[dir='ltr'] .treeItemToggler::before {
   right: 4px;
 }
-html[dir='rtl'] .outlineItemToggler::before {
+html[dir='rtl'] .treeItemToggler::before {
   left: 4px;
 }
 
-.outlineItemToggler:hover,
-.outlineItemToggler:hover + a,
-.outlineItemToggler:hover ~ .outlineItems,
-.outlineItem > a:hover,
-.attachmentsItem > button:hover {
+.treeItemToggler:hover,
+.treeItemToggler:hover + a,
+.treeItemToggler:hover ~ .treeItems,
+.treeItem > a:hover {
   background-color: rgba(255, 255, 255, 0.02);
   background-image: linear-gradient(rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0));
   background-clip: padding-box;
   box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05) inset,
               0 0 1px rgba(255, 255, 255, 0.2) inset,
               0 0 1px rgba(0, 0, 0, 0.2);
   border-radius: 2px;
   color: rgba(255, 255, 255, 0.9);
 }
 
-.outlineItem.selected {
+.treeItem.selected {
   background-color: rgba(255, 255, 255, 0.08);
   background-image: linear-gradient(rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0));
   background-clip: padding-box;
   box-shadow: 0 1px 0 rgba(255, 255, 255, 0.05) inset,
               0 0 1px rgba(255, 255, 255, 0.1) inset,
               0 0 1px rgba(0, 0, 0, 0.2);
   color: rgba(255, 255, 255, 1);
 }
@@ -2079,31 +2055,31 @@ html[dir='rtl'] #documentPropertiesOverl
   .secondaryToolbarButton.spreadEven::before {
     content: url(images/secondaryToolbarButton-spreadEven@2x.png);
   }
 
   .secondaryToolbarButton.documentProperties::before {
     content: url(images/secondaryToolbarButton-documentProperties@2x.png);
   }
 
-  .outlineItemToggler::before {
+  .treeItemToggler::before {
     transform: scale(0.5);
     top: -1px;
     content: url(images/treeitem-expanded@2x.png);
   }
-  .outlineItemToggler.outlineItemsHidden::before {
+  .treeItemToggler.treeItemsHidden::before {
     content: url(images/treeitem-collapsed@2x.png);
   }
-  html[dir='rtl'] .outlineItemToggler.outlineItemsHidden::before {
+  html[dir='rtl'] .treeItemToggler.treeItemsHidden::before {
     transform: scale(-0.5, 0.5);
   }
-  html[dir='ltr'] .outlineItemToggler::before {
+  html[dir='ltr'] .treeItemToggler::before {
     right: 0;
   }
-  html[dir='rtl'] .outlineItemToggler::before {
+  html[dir='rtl'] .treeItemToggler::before {
     left: 0;
   }
 }
 
 @media print {
   /* General rules for printing. */
   body {
     background: rgba(0, 0, 0, 0) none;
--- a/toolkit/components/pdfjs/content/web/viewer.js
+++ b/toolkit/components/pdfjs/content/web/viewer.js
@@ -115,19 +115,19 @@
 
 ;
 let pdfjsWebApp, pdfjsWebAppOptions;
 {
   pdfjsWebApp = __webpack_require__(1);
   pdfjsWebAppOptions = __webpack_require__(3);
 }
 {
-  __webpack_require__(33);
-
-  __webpack_require__(36);
+  __webpack_require__(34);
+
+  __webpack_require__(37);
 }
 ;
 ;
 ;
 
 function getViewerConfiguration() {
   return {
     appContainer: document.body,
@@ -289,41 +289,41 @@ var _pdf_rendering_queue = __webpack_req
 var _pdf_sidebar = __webpack_require__(9);
 
 var _overlay_manager = __webpack_require__(10);
 
 var _password_prompt = __webpack_require__(11);
 
 var _pdf_attachment_viewer = __webpack_require__(12);
 
-var _pdf_document_properties = __webpack_require__(13);
-
-var _pdf_find_bar = __webpack_require__(14);
-
-var _pdf_find_controller = __webpack_require__(15);
-
-var _pdf_history = __webpack_require__(17);
-
-var _pdf_link_service = __webpack_require__(18);
-
-var _pdf_outline_viewer = __webpack_require__(19);
-
-var _pdf_presentation_mode = __webpack_require__(20);
-
-var _pdf_sidebar_resizer = __webpack_require__(21);
-
-var _pdf_thumbnail_viewer = __webpack_require__(22);
-
-var _pdf_viewer = __webpack_require__(24);
-
-var _secondary_toolbar = __webpack_require__(29);
-
-var _toolbar = __webpack_require__(31);
-
-var _view_history = __webpack_require__(32);
+var _pdf_document_properties = __webpack_require__(14);
+
+var _pdf_find_bar = __webpack_require__(15);
+
+var _pdf_find_controller = __webpack_require__(16);
+
+var _pdf_history = __webpack_require__(18);
+
+var _pdf_link_service = __webpack_require__(19);
+
+var _pdf_outline_viewer = __webpack_require__(20);
+
+var _pdf_presentation_mode = __webpack_require__(21);
+
+var _pdf_sidebar_resizer = __webpack_require__(22);
+
+var _pdf_thumbnail_viewer = __webpack_require__(23);
+
+var _pdf_viewer = __webpack_require__(25);
+
+var _secondary_toolbar = __webpack_require__(30);
+
+var _toolbar = __webpack_require__(32);
+
+var _view_history = __webpack_require__(33);
 
 const DEFAULT_SCALE_DELTA = 1.1;
 const DISABLE_AUTO_FETCH_LOADING_BAR_TIMEOUT = 5000;
 const FORCE_PAGES_LOADED_TIMEOUT = 10000;
 const WHEEL_ZOOM_DISABLED_TIMEOUT = 1000;
 const ENABLE_PERMISSIONS_CLASS = "enablePermissions";
 const ViewOnLoad = {
   UNKNOWN: -1,
@@ -1509,17 +1509,20 @@ const PDFViewerApplication = {
       this.l10n.get("printing_not_ready", null, "Warning: The PDF is not fully loaded for printing.").then(notReadyMessage => {
         window.alert(notReadyMessage);
       });
       return;
     }
 
     const pagesOverview = this.pdfViewer.getPagesOverview();
     const printContainer = this.appConfig.printContainer;
-    const printService = PDFPrintServiceFactory.instance.createPrintService(this.pdfDocument, pagesOverview, printContainer, this.l10n);
+
+    const printResolution = _app_options.AppOptions.get("printResolution");
+
+    const printService = PDFPrintServiceFactory.instance.createPrintService(this.pdfDocument, pagesOverview, printContainer, printResolution, this.l10n);
     this.printService = printService;
     this.forceRendering();
     printService.layout();
     this.externalServices.reportTelemetry({
       type: "print"
     });
   },
 
@@ -4434,36 +4437,32 @@ class PDFSidebar {
       this.eventBus.dispatch("toggleoutlinetree", {
         source: this
       });
     });
     this.attachmentsButton.addEventListener("click", () => {
       this.switchView(SidebarView.ATTACHMENTS);
     });
 
+    const onTreeLoaded = (count, button, view) => {
+      button.disabled = !count;
+
+      if (count) {
+        this._showUINotification(view);
+      } else if (this.active === view) {
+        this.switchView(SidebarView.THUMBS);
+      }
+    };
+
     this.eventBus._on("outlineloaded", evt => {
-      const outlineCount = evt.outlineCount;
-      this.outlineButton.disabled = !outlineCount;
-
-      if (outlineCount) {
-        this._showUINotification(SidebarView.OUTLINE);
-      } else if (this.active === SidebarView.OUTLINE) {
-        this.switchView(SidebarView.THUMBS);
-      }
+      onTreeLoaded(evt.outlineCount, this.outlineButton, SidebarView.OUTLINE);
     });
 
     this.eventBus._on("attachmentsloaded", evt => {
-      const attachmentsCount = evt.attachmentsCount;
-      this.attachmentsButton.disabled = !attachmentsCount;
-
-      if (attachmentsCount) {
-        this._showUINotification(SidebarView.ATTACHMENTS);
-      } else if (this.active === SidebarView.ATTACHMENTS) {
-        this.switchView(SidebarView.THUMBS);
-      }
+      onTreeLoaded(evt.attachmentsCount, this.attachmentsButton, SidebarView.ATTACHMENTS);
     });
 
     this.eventBus._on("presentationmodechanged", evt => {
       if (!evt.active && !evt.switchInProgress && this.isThumbnailViewVisible) {
         this._updateThumbnailViewer();
       }
     });
   }
@@ -4671,33 +4670,29 @@ exports.PasswordPrompt = PasswordPrompt;
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFAttachmentViewer = void 0;
 
 var _pdfjsLib = __webpack_require__(5);
 
-class PDFAttachmentViewer {
-  constructor({
-    container,
-    eventBus,
-    downloadManager
-  }) {
-    this.container = container;
-    this.eventBus = eventBus;
-    this.downloadManager = downloadManager;
-    this.reset();
+var _base_tree_viewer = __webpack_require__(13);
+
+class PDFAttachmentViewer extends _base_tree_viewer.BaseTreeViewer {
+  constructor(options) {
+    super(options);
+    this.downloadManager = options.downloadManager;
 
     this.eventBus._on("fileattachmentannotation", this._appendAttachment.bind(this));
   }
 
   reset(keepRenderedCapability = false) {
-    this.attachments = null;
-    this.container.textContent = "";
+    super.reset();
+    this._attachments = null;
 
     if (!keepRenderedCapability) {
       this._renderedCapability = (0, _pdfjsLib.createPromiseCapability)();
     }
 
     if (this._pendingDispatchEvent) {
       clearTimeout(this._pendingDispatchEvent);
     }
@@ -4725,20 +4720,23 @@ class PDFAttachmentViewer {
     }
 
     this.eventBus.dispatch("attachmentsloaded", {
       source: this,
       attachmentsCount
     });
   }
 
-  _bindPdfLink(button, content, filename) {
+  _bindPdfLink(element, {
+    content,
+    filename
+  }) {
     let blobUrl;
 
-    button.onclick = () => {
+    element.onclick = () => {
       if (!blobUrl) {
         blobUrl = URL.createObjectURL(new Blob([content], {
           type: "application/pdf"
         }));
       }
 
       let viewerUrl;
       viewerUrl = blobUrl + "#filename=" + encodeURIComponent(filename);
@@ -4751,61 +4749,71 @@ class PDFAttachmentViewer {
         blobUrl = null;
         this.downloadManager.downloadData(content, filename, "application/pdf");
       }
 
       return false;
     };
   }
 
-  _bindLink(button, content, filename) {
-    button.onclick = () => {
+  _bindLink(element, {
+    content,
+    filename
+  }) {
+    element.onclick = () => {
       this.downloadManager.downloadData(content, filename, "");
       return false;
     };
   }
 
   render({
     attachments,
     keepRenderedCapability = false
   }) {
-    if (this.attachments) {
-      this.reset(keepRenderedCapability === true);
-    }
-
-    this.attachments = attachments || null;
+    if (this._attachments) {
+      this.reset(keepRenderedCapability);
+    }
+
+    this._attachments = attachments || null;
 
     if (!attachments) {
       this._dispatchEvent(0);
 
       return;
     }
 
     const names = Object.keys(attachments).sort(function (a, b) {
       return a.toLowerCase().localeCompare(b.toLowerCase());
     });
-    const attachmentsCount = names.length;
     const fragment = document.createDocumentFragment();
-
-    for (let i = 0; i < attachmentsCount; i++) {
-      const item = attachments[names[i]];
-      const filename = (0, _pdfjsLib.removeNullCharacters)((0, _pdfjsLib.getFilenameFromUrl)(item.filename));
+    let attachmentsCount = 0;
+
+    for (const name of names) {
+      const item = attachments[name];
+      const filename = (0, _pdfjsLib.getFilenameFromUrl)(item.filename);
       const div = document.createElement("div");
-      div.className = "attachmentsItem";
-      const button = document.createElement("button");
-      button.textContent = filename;
+      div.className = "treeItem";
+      const element = document.createElement("a");
 
       if (/\.pdf$/i.test(filename) && !this.downloadManager.disableCreateObjectURL) {
-        this._bindPdfLink(button, item.content, filename);
+        this._bindPdfLink(element, {
+          content: item.content,
+          filename
+        });
       } else {
-        this._bindLink(button, item.content, filename);
-      }
-
-      div.appendChild(button);
+        this._bindLink(element, {
+          content: item.content,
+          filename
+        });
+      }
+
+      element.textContent = this._normalizeTextContent(filename);
+      div.appendChild(element);
       fragment.appendChild(div);
+      attachmentsCount++;
     }
 
     this.container.appendChild(fragment);
 
     this._dispatchEvent(attachmentsCount);
   }
 
   _appendAttachment({
@@ -4814,17 +4822,17 @@ class PDFAttachmentViewer {
     content
   }) {
     const renderedPromise = this._renderedCapability.promise;
     renderedPromise.then(() => {
       if (renderedPromise !== this._renderedCapability.promise) {
         return;
       }
 
-      let attachments = this.attachments;
+      let attachments = this._attachments;
 
       if (!attachments) {
         attachments = Object.create(null);
       } else {
         for (const name in attachments) {
           if (id === name) {
             return;
           }
@@ -4851,16 +4859,101 @@ exports.PDFAttachmentViewer = PDFAttachm
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
+exports.BaseTreeViewer = void 0;
+
+var _pdfjsLib = __webpack_require__(5);
+
+class BaseTreeViewer {
+  constructor(options) {
+    if (this.constructor === BaseTreeViewer) {
+      throw new Error("Cannot initialize BaseTreeViewer.");
+    }
+
+    this.container = options.container;
+    this.eventBus = options.eventBus;
+    this.reset();
+  }
+
+  reset() {
+    this._lastToggleIsShow = true;
+    this.container.textContent = "";
+    this.container.classList.remove("treeWithDeepNesting");
+  }
+
+  _dispatchEvent(count) {
+    throw new Error("Not implemented: _dispatchEvent");
+  }
+
+  _bindLink(element, params) {
+    throw new Error("Not implemented: _bindLink");
+  }
+
+  _normalizeTextContent(str) {
+    return (0, _pdfjsLib.removeNullCharacters)(str) || "\u2013";
+  }
+
+  _addToggleButton(div, hidden = false) {
+    const toggler = document.createElement("div");
+    toggler.className = "treeItemToggler";
+
+    if (hidden) {
+      toggler.classList.add("treeItemsHidden");
+    }
+
+    toggler.onclick = evt => {
+      evt.stopPropagation();
+      toggler.classList.toggle("treeItemsHidden");
+
+      if (evt.shiftKey) {
+        const shouldShowAll = !toggler.classList.contains("treeItemsHidden");
+
+        this._toggleTreeItem(div, shouldShowAll);
+      }
+    };
+
+    div.insertBefore(toggler, div.firstChild);
+  }
+
+  _toggleTreeItem(root, show = false) {
+    this._lastToggleIsShow = show;
+
+    for (const toggler of root.querySelectorAll(".treeItemToggler")) {
+      toggler.classList.toggle("treeItemsHidden", !show);
+    }
+  }
+
+  _toggleAllTreeItems() {
+    this._toggleTreeItem(this.container, !this._lastToggleIsShow);
+  }
+
+  render(params) {
+    throw new Error("Not implemented: render");
+  }
+
+}
+
+exports.BaseTreeViewer = BaseTreeViewer;
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports, __webpack_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
 exports.PDFDocumentProperties = void 0;
 
 var _pdfjsLib = __webpack_require__(5);
 
 var _ui_utils = __webpack_require__(2);
 
 const DEFAULT_FIELD_CONTENT = "-";
 const NON_METRIC_LOCALES = ["en-us", "en-lr", "my"];
@@ -5137,28 +5230,28 @@ class PDFDocumentProperties {
     return this.l10n.get("document_properties_linearized_" + (isLinearized ? "yes" : "no"), null, isLinearized ? "Yes" : "No");
   }
 
 }
 
 exports.PDFDocumentProperties = PDFDocumentProperties;
 
 /***/ }),
-/* 14 */
+/* 15 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFFindBar = void 0;
 
-var _pdf_find_controller = __webpack_require__(15);
+var _pdf_find_controller = __webpack_require__(16);
 
 var _ui_utils = __webpack_require__(2);
 
 const MATCHES_COUNT_LIMIT = 1000;
 
 class PDFFindBar {
   constructor(options, eventBus, l10n = _ui_utils.NullL10n) {
     this.opened = false;
@@ -5348,30 +5441,30 @@ class PDFFindBar {
     }
   }
 
 }
 
 exports.PDFFindBar = PDFFindBar;
 
 /***/ }),
-/* 15 */
+/* 16 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFFindController = exports.FindState = void 0;
 
 var _pdfjsLib = __webpack_require__(5);
 
-var _pdf_find_utils = __webpack_require__(16);
+var _pdf_find_utils = __webpack_require__(17);
 
 var _ui_utils = __webpack_require__(2);
 
 const FindState = {
   FOUND: 0,
   NOT_FOUND: 1,
   WRAPPED: 2,
   PENDING: 3
@@ -6029,17 +6122,17 @@ class PDFFindController {
     });
   }
 
 }
 
 exports.PDFFindController = PDFFindController;
 
 /***/ }),
-/* 16 */
+/* 17 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
@@ -6125,17 +6218,17 @@ function getCharacterType(charCode) {
   } else if (isHalfwidthKatakana(charCode)) {
     return CharacterType.HALFWIDTH_KATAKANA_LETTER;
   }
 
   return CharacterType.ALPHA_LETTER;
 }
 
 /***/ }),
-/* 17 */
+/* 18 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
@@ -6713,17 +6806,17 @@ function isDestArraysEqual(firstDest, se
       return false;
     }
   }
 
   return true;
 }
 
 /***/ }),
-/* 18 */
+/* 19 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
@@ -7152,50 +7245,42 @@ class SimpleLinkService {
     return true;
   }
 
 }
 
 exports.SimpleLinkService = SimpleLinkService;
 
 /***/ }),
-/* 19 */
+/* 20 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFOutlineViewer = void 0;
 
 var _pdfjsLib = __webpack_require__(5);
 
-const DEFAULT_TITLE = "\u2013";
-
-class PDFOutlineViewer {
-  constructor({
-    container,
-    linkService,
-    eventBus
-  }) {
-    this.container = container;
-    this.linkService = linkService;
-    this.eventBus = eventBus;
-    this.reset();
-
-    eventBus._on("toggleoutlinetree", this.toggleOutlineTree.bind(this));
+var _base_tree_viewer = __webpack_require__(13);
+
+class PDFOutlineViewer extends _base_tree_viewer.BaseTreeViewer {
+  constructor(options) {
+    super(options);
+    this.linkService = options.linkService;
+
+    this.eventBus._on("toggleoutlinetree", this._toggleAllTreeItems.bind(this));
   }
 
   reset() {
-    this.outline = null;
-    this.lastToggleIsShow = true;
-    this.container.textContent = "";
-    this.container.classList.remove("outlineWithDeepNesting");
+    super.reset();
+    this._outline = null;
   }
 
   _dispatchEvent(outlineCount) {
     this.eventBus.dispatch("outlineloaded", {
       source: this,
       outlineCount
     });
   }
@@ -7242,127 +7327,102 @@ class PDFOutlineViewer {
       element.style.fontStyle = "italic";
     }
   }
 
   _addToggleButton(div, {
     count,
     items
   }) {
-    const toggler = document.createElement("div");
-    toggler.className = "outlineItemToggler";
-
-    if (count < 0 && Math.abs(count) === items.length) {
-      toggler.classList.add("outlineItemsHidden");
-    }
-
-    toggler.onclick = evt => {
-      evt.stopPropagation();
-      toggler.classList.toggle("outlineItemsHidden");
-
-      if (evt.shiftKey) {
-        const shouldShowAll = !toggler.classList.contains("outlineItemsHidden");
-
-        this._toggleOutlineItem(div, shouldShowAll);
-      }
-    };
-
-    div.insertBefore(toggler, div.firstChild);
-  }
-
-  _toggleOutlineItem(root, show = false) {
-    this.lastToggleIsShow = show;
-
-    for (const toggler of root.querySelectorAll(".outlineItemToggler")) {
-      toggler.classList.toggle("outlineItemsHidden", !show);
-    }
-  }
-
-  toggleOutlineTree() {
-    if (!this.outline) {
-      return;
-    }
-
-    this._toggleOutlineItem(this.container, !this.lastToggleIsShow);
+    const hidden = count < 0 && Math.abs(count) === items.length;
+
+    super._addToggleButton(div, hidden);
+  }
+
+  _toggleAllTreeItems() {
+    if (!this._outline) {
+      return;
+    }
+
+    super._toggleAllTreeItems();
   }
 
   render({
     outline
   }) {
-    let outlineCount = 0;
-
-    if (this.outline) {
+    if (this._outline) {
       this.reset();
     }
 
-    this.outline = outline || null;
+    this._outline = outline || null;
 
     if (!outline) {
-      this._dispatchEvent(outlineCount);
+      this._dispatchEvent(0);
 
       return;
     }
 
     const fragment = document.createDocumentFragment();
     const queue = [{
       parent: fragment,
-      items: this.outline
+      items: outline
     }];
-    let hasAnyNesting = false;
+    let outlineCount = 0,
+        hasAnyNesting = false;
 
     while (queue.length > 0) {
       const levelData = queue.shift();
 
       for (const item of levelData.items) {
         const div = document.createElement("div");
-        div.className = "outlineItem";
+        div.className = "treeItem";
         const element = document.createElement("a");
 
         this._bindLink(element, item);
 
         this._setStyles(element, item);
 
-        element.textContent = (0, _pdfjsLib.removeNullCharacters)(item.title) || DEFAULT_TITLE;
+        element.textContent = this._normalizeTextContent(item.title);
         div.appendChild(element);
 
         if (item.items.length > 0) {
           hasAnyNesting = true;
 
           this._addToggleButton(div, item);
 
           const itemsDiv = document.createElement("div");
-          itemsDiv.className = "outlineItems";
+          itemsDiv.className = "treeItems";
           div.appendChild(itemsDiv);
           queue.push({
             parent: itemsDiv,
             items: item.items
           });
         }
 
         levelData.parent.appendChild(div);
         outlineCount++;
       }
     }
 
     if (hasAnyNesting) {
-      this.container.classList.add("outlineWithDeepNesting");
-      this.lastToggleIsShow = fragment.querySelectorAll(".outlineItemsHidden").length === 0;
+      this.container.classList.add("treeWithDeepNesting");
+      this._lastToggleIsShow = fragment.querySelectorAll(".treeItemsHidden").length === 0;
     }
 
     this.container.appendChild(fragment);
 
     this._dispatchEvent(outlineCount);
   }
 
 }
 
 exports.PDFOutlineViewer = PDFOutlineViewer;
 
 /***/ }),
-/* 20 */
+/* 21 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
@@ -7757,17 +7817,17 @@ class PDFPresentationMode {
     delete this.fullscreenChangeBind;
   }
 
 }
 
 exports.PDFPresentationMode = PDFPresentationMode;
 
 /***/ }),
-/* 21 */
+/* 22 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
@@ -7900,30 +7960,30 @@ class PDFSidebarResizer {
     });
   }
 
 }
 
 exports.PDFSidebarResizer = PDFSidebarResizer;
 
 /***/ }),
-/* 22 */
+/* 23 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFThumbnailViewer = void 0;
 
 var _ui_utils = __webpack_require__(2);
 
-var _pdf_thumbnail_view = __webpack_require__(23);
+var _pdf_thumbnail_view = __webpack_require__(24);
 
 const THUMBNAIL_SCROLL_MARGIN = -19;
 const THUMBNAIL_SELECTED_CLASS = "selected";
 
 class PDFThumbnailViewer {
   constructor({
     container,
     linkService,
@@ -8157,17 +8217,17 @@ class PDFThumbnailViewer {
     return false;
   }
 
 }
 
 exports.PDFThumbnailViewer = PDFThumbnailViewer;
 
 /***/ }),
-/* 23 */
+/* 24 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
@@ -8571,28 +8631,28 @@ class PDFThumbnailView {
     TempImageFactory.destroyCanvas();
   }
 
 }
 
 exports.PDFThumbnailView = PDFThumbnailView;
 
 /***/ }),
-/* 24 */
+/* 25 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFViewer = void 0;
 
-var _base_viewer = __webpack_require__(25);
+var _base_viewer = __webpack_require__(26);
 
 var _pdfjsLib = __webpack_require__(5);
 
 class PDFViewer extends _base_viewer.BaseViewer {
   get _viewerElement() {
     return (0, _pdfjsLib.shadow)(this, "_viewerElement", this.viewer);
   }
 
@@ -8658,40 +8718,40 @@ class PDFViewer extends _base_viewer.Bas
     this._setCurrentPageNumber(currentId);
   }
 
 }
 
 exports.PDFViewer = PDFViewer;
 
 /***/ }),
-/* 25 */
+/* 26 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.BaseViewer = void 0;
 
 var _ui_utils = __webpack_require__(2);
 
 var _pdf_rendering_queue = __webpack_require__(8);
 
-var _annotation_layer_builder = __webpack_require__(26);
+var _annotation_layer_builder = __webpack_require__(27);
 
 var _pdfjsLib = __webpack_require__(5);
 
-var _pdf_page_view = __webpack_require__(27);
-
-var _pdf_link_service = __webpack_require__(18);
-
-var _text_layer_builder = __webpack_require__(28);
+var _pdf_page_view = __webpack_require__(28);
+
+var _pdf_link_service = __webpack_require__(19);
+
+var _text_layer_builder = __webpack_require__(29);
 
 const DEFAULT_CACHE_SIZE = 10;
 
 function PDFPageViewBuffer(size) {
   const data = [];
 
   this.push = function (view) {
     const i = data.indexOf(view);
@@ -8982,16 +9042,17 @@ class BaseViewer {
     this.pdfDocument = pdfDocument;
 
     if (!pdfDocument) {
       return;
     }
 
     const pagesCount = pdfDocument.numPages;
     const firstPagePromise = pdfDocument.getPage(1);
+    const annotationStorage = pdfDocument.annotationStorage;
 
     this._pagesCapability.promise.then(() => {
       this.eventBus.dispatch("pagesloaded", {
         source: this,
         pagesCount
       });
     });
 
@@ -9031,16 +9092,17 @@ class BaseViewer {
       const textLayerFactory = this.textLayerMode !== _ui_utils.TextLayerMode.DISABLE ? this : null;
 
       for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) {
         const pageView = new _pdf_page_view.PDFPageView({
           container: this._viewerElement,
           eventBus: this.eventBus,
           id: pageNum,
           scale,
+          annotationStorage,
           defaultViewport: viewport.clone(),
           renderingQueue: this.renderingQueue,
           textLayerFactory,
           textLayerMode: this.textLayerMode,
           annotationLayerFactory: this,
           imageResourcesPath: this.imageResourcesPath,
           renderInteractiveForms: this.renderInteractiveForms,
           renderer: this.renderer,
@@ -9614,25 +9676,25 @@ class BaseViewer {
       eventBus,
       pageIndex,
       viewport,
       findController: this.isInPresentationMode ? null : this.findController,
       enhanceTextSelection: this.isInPresentationMode ? false : enhanceTextSelection
     });
   }
 
-  createAnnotationLayerBuilder(pageDiv, pdfPage, imageResourcesPath = "", renderInteractiveForms = false, l10n = _ui_utils.NullL10n) {
+  createAnnotationLayerBuilder(pageDiv, pdfPage, annotationStorage = null, imageResourcesPath = "", renderInteractiveForms = false, l10n = _ui_utils.NullL10n) {
     return new _annotation_layer_builder.AnnotationLayerBuilder({
       pageDiv,
       pdfPage,
+      annotationStorage,
       imageResourcesPath,
       renderInteractiveForms,
       linkService: this.linkService,
       downloadManager: this.downloadManager,
-      annotationStorage: this.pdfDocument.annotationStorage,
       l10n
     });
   }
 
   get hasEqualPageSizes() {
     const firstPageView = this._pages[0];
 
     for (let i = 1, ii = this._pages.length; i < ii; ++i) {
@@ -9778,32 +9840,32 @@ class BaseViewer {
     this.update();
   }
 
 }
 
 exports.BaseViewer = BaseViewer;
 
 /***/ }),
-/* 26 */
+/* 27 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.DefaultAnnotationLayerFactory = exports.AnnotationLayerBuilder = void 0;
 
 var _pdfjsLib = __webpack_require__(5);
 
 var _ui_utils = __webpack_require__(2);
 
-var _pdf_link_service = __webpack_require__(18);
+var _pdf_link_service = __webpack_require__(19);
 
 class AnnotationLayerBuilder {
   constructor({
     pageDiv,
     pdfPage,
     linkService,
     downloadManager,
     annotationStorage = null,
@@ -9893,17 +9955,17 @@ class DefaultAnnotationLayerFactory {
     });
   }
 
 }
 
 exports.DefaultAnnotationLayerFactory = DefaultAnnotationLayerFactory;
 
 /***/ }),
-/* 27 */
+/* 28 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
@@ -9925,16 +9987,17 @@ class PDFPageView {
     const defaultViewport = options.defaultViewport;
     this.id = options.id;
     this.renderingId = "page" + this.id;
     this.pdfPage = null;
     this.pageLabel = null;
     this.rotation = 0;
     this.scale = options.scale || _ui_utils.DEFAULT_SCALE;
     this.viewport = defaultViewport;
+    this._annotationStorage = options.annotationStorage || null;
     this.pdfPageRotate = defaultViewport.rotation;
     this.hasRestrictedScaling = false;
     this.textLayerMode = Number.isInteger(options.textLayerMode) ? options.textLayerMode : _ui_utils.TextLayerMode.ENABLE;
     this.imageResourcesPath = options.imageResourcesPath || "";
     this.renderInteractiveForms = options.renderInteractiveForms || false;
     this.useOnlyCssZoom = options.useOnlyCssZoom || false;
     this.maxCanvasPixels = options.maxCanvasPixels || MAX_CANVAS_PIXELS;
     this.eventBus = options.eventBus;
@@ -10322,17 +10385,17 @@ class PDFPageView {
         }
       });
     }, function (reason) {
       return finishPaintTask(reason);
     });
 
     if (this.annotationLayerFactory) {
       if (!this.annotationLayer) {
-        this.annotationLayer = this.annotationLayerFactory.createAnnotationLayerBuilder(div, pdfPage, this.imageResourcesPath, this.renderInteractiveForms, this.l10n);
+        this.annotationLayer = this.annotationLayerFactory.createAnnotationLayerBuilder(div, pdfPage, this._annotationStorage, this.imageResourcesPath, this.renderInteractiveForms, this.l10n);
       }
 
       this.annotationLayer.render(this.viewport, "display");
     }
 
     div.setAttribute("data-loaded", true);
     this.eventBus.dispatch("pagerender", {
       source: this,
@@ -10462,17 +10525,17 @@ class PDFPageView {
     }
   }
 
 }
 
 exports.PDFPageView = PDFPageView;
 
 /***/ }),
-/* 28 */
+/* 29 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
@@ -10824,32 +10887,32 @@ class DefaultTextLayerFactory {
     });
   }
 
 }
 
 exports.DefaultTextLayerFactory = DefaultTextLayerFactory;
 
 /***/ }),
-/* 29 */
+/* 30 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.SecondaryToolbar = void 0;
 
 var _ui_utils = __webpack_require__(2);
 
 var _pdf_cursor_tools = __webpack_require__(6);
 
-var _pdf_single_page_viewer = __webpack_require__(30);
+var _pdf_single_page_viewer = __webpack_require__(31);
 
 class SecondaryToolbar {
   constructor(options, mainContainer, eventBus) {
     this.toolbar = options.toolbar;
     this.toggleButton = options.toggleButton;
     this.toolbarButtonContainer = options.toolbarButtonContainer;
     this.buttons = [{
       element: options.presentationModeButton,
@@ -11142,28 +11205,28 @@ class SecondaryToolbar {
     this.previousContainerHeight = this.containerHeight;
   }
 
 }
 
 exports.SecondaryToolbar = SecondaryToolbar;
 
 /***/ }),
-/* 30 */
+/* 31 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.PDFSinglePageViewer = void 0;
 
-var _base_viewer = __webpack_require__(25);
+var _base_viewer = __webpack_require__(26);
 
 var _pdfjsLib = __webpack_require__(5);
 
 class PDFSinglePageViewer extends _base_viewer.BaseViewer {
   constructor(options) {
     super(options);
 
     this.eventBus._on("pagesinit", evt => {
@@ -11264,17 +11327,17 @@ class PDFSinglePageViewer extends _base_
 
   _updateSpreadMode() {}
 
 }
 
 exports.PDFSinglePageViewer = PDFSinglePageViewer;
 
 /***/ }),
-/* 31 */
+/* 32 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
@@ -11534,17 +11597,17 @@ class Toolbar {
     canvas = ctx = null;
   }
 
 }
 
 exports.Toolbar = Toolbar;
 
 /***/ }),
-/* 32 */
+/* 33 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
@@ -11630,34 +11693,34 @@ class ViewHistory {
     return values;
   }
 
 }
 
 exports.ViewHistory = ViewHistory;
 
 /***/ }),
-/* 33 */
+/* 34 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.FirefoxCom = exports.DownloadManager = void 0;
 
-__webpack_require__(34);
+__webpack_require__(35);
 
 var _app = __webpack_require__(1);
 
 var _pdfjsLib = __webpack_require__(5);
 
-var _preferences = __webpack_require__(35);
+var _preferences = __webpack_require__(36);
 
 var _ui_utils = __webpack_require__(2);
 
 ;
 
 const FirefoxCom = function FirefoxComClosure() {
   return {
     requestSync(action, data) {
@@ -11988,17 +12051,17 @@ document.mozL10n.setExternalLocalizerSer
 
   getStrings(key) {
     return FirefoxCom.requestSync("getStrings", key);
   }
 
 });
 
 /***/ }),
-/* 34 */
+/* 35 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 (function (window) {
   var gLanguage = "";
   var gExternalLocalizerServices = null;
@@ -12111,17 +12174,17 @@ document.mozL10n.setExternalLocalizerSer
       gReadyState = "complete";
     },
 
     translate: translateFragment
   };
 })(void 0);
 
 /***/ }),
-/* 35 */
+/* 36 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
@@ -12261,39 +12324,36 @@ class BasePreferences {
     return Object.assign(Object.create(null), this.defaults, this.prefs);
   }
 
 }
 
 exports.BasePreferences = BasePreferences;
 
 /***/ }),
-/* 36 */
+/* 37 */
 /***/ (function(module, exports, __webpack_require__) {
 
 "use strict";
 
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.FirefoxPrintService = FirefoxPrintService;
 
-var _app_options = __webpack_require__(3);
-
 var _ui_utils = __webpack_require__(2);
 
 var _app = __webpack_require__(1);
 
 var _pdfjsLib = __webpack_require__(5);
 
-function composePage(pdfDocument, pageNumber, size, printContainer) {
+function composePage(pdfDocument, pageNumber, size, printContainer, printResolution) {
   const canvas = document.createElement("canvas");
-  const PRINT_RESOLUTION = _app_options.AppOptions.get("printResolution") || 150;
-  const PRINT_UNITS = PRINT_RESOLUTION / 72.0;
+  const PRINT_UNITS = printResolution / 72.0;
   canvas.width = Math.floor(size.width * PRINT_UNITS);
   canvas.height = Math.floor(size.height * PRINT_UNITS);
   canvas.style.width = Math.floor(size.width * _ui_utils.CSS_UNITS) + "px";
   canvas.style.height = Math.floor(size.height * _ui_utils.CSS_UNITS) + "px";
   const canvasWrapper = document.createElement("div");
   canvasWrapper.appendChild(canvas);
   printContainer.appendChild(canvasWrapper);
 
@@ -12307,51 +12367,53 @@ function composePage(pdfDocument, pageNu
       const renderContext = {
         canvasContext: ctx,
         transform: [PRINT_UNITS, 0, 0, PRINT_UNITS, 0, 0],
         viewport: pdfPage.getViewport({
           scale: 1,
           rotation: size.rotation
         }),
         intent: "print",
-        annotationStorage: pdfDocument.annotationStorage.getAll()
+        annotationStorage: pdfDocument.annotationStorage
       };
       return pdfPage.render(renderContext).promise;
     }).then(function () {
       obj.done();
     }, function (error) {
       console.error(error);
 
       if ("abort" in obj) {
         obj.abort();
       } else {
         obj.done();
       }
     });
   };
 }
 
-function FirefoxPrintService(pdfDocument, pagesOverview, printContainer) {
+function FirefoxPrintService(pdfDocument, pagesOverview, printContainer, printResolution) {
   this.pdfDocument = pdfDocument;
   this.pagesOverview = pagesOverview;
   this.printContainer = printContainer;
+  this._printResolution = printResolution || 150;
 }
 
 FirefoxPrintService.prototype = {
   layout() {
     const {
       pdfDocument,
       pagesOverview,
-      printContainer
+      printContainer,
+      _printResolution
     } = this;
     const body = document.querySelector("body");
     body.setAttribute("data-pdfjsprinting", true);
 
     for (let i = 0, ii = pagesOverview.length; i < ii; ++i) {
-      composePage(pdfDocument, i + 1, pagesOverview[i], printContainer);
+      composePage(pdfDocument, i + 1, pagesOverview[i], printContainer, _printResolution);
     }
   },
 
   destroy() {
     this.printContainer.textContent = "";
     const body = document.querySelector("body");
     body.removeAttribute("data-pdfjsprinting");
   }
@@ -12359,16 +12421,16 @@ FirefoxPrintService.prototype = {
 };
 _app.PDFPrintServiceFactory.instance = {
   get supportsPrinting() {
     const canvas = document.createElement("canvas");
     const value = ("mozPrintCallback" in canvas);
     return (0, _pdfjsLib.shadow)(this, "supportsPrinting", value);
   },
 
-  createPrintService(pdfDocument, pagesOverview, printContainer) {
-    return new FirefoxPrintService(pdfDocument, pagesOverview, printContainer);
+  createPrintService(pdfDocument, pagesOverview, printContainer, printResolution) {
+    return new FirefoxPrintService(pdfDocument, pagesOverview, printContainer, printResolution);
   }
 
 };
 
 /***/ })
 /******/ ]);
\ No newline at end of file
--- a/toolkit/components/pdfjs/moz.yaml
+++ b/toolkit/components/pdfjs/moz.yaml
@@ -15,15 +15,15 @@ origin:
   description: Portable Document Format (PDF) viewer that is built with HTML5
 
   # Full URL for the package's homepage/etc
   # Usually different from repository url
   url: https://github.com/mozilla/pdf.js
 
   # Human-readable identifier for this version/release
   # Generally "version NNN", "tag SSS", "bookmark SSS"
-  release: version 2.6.207
+  release: version 2.6.234
 
   # The package's license, where possible using the mnemonic from
   # https://spdx.org/licenses/
   # Multiple licenses can be specified (as a YAML list)
   # A "LICENSE" file must exist containing the full license text
   license: Apache-2.0