[Basilisk] Update pdf.js to 1.7.348 from Firefox 54.0.1

This commit is contained in:
Basilisk-Dev 2023-09-11 22:43:12 -04:00 • committed by roytam1
commit c5d109556c
14 changed files with 63753 additions and 63745 deletions

View file

@ -1,3 +1,3 @@
This is the pdf.js project output, https://github.com/mozilla/pdf.js This is the pdf.js project output, https://github.com/mozilla/pdf.js
Current extension version is: 1.6.467 Current extension version is: 1.7.348

View file

@ -15,9 +15,9 @@
/* globals Components, Services, XPCOMUtils, PdfjsChromeUtils, /* globals Components, Services, XPCOMUtils, PdfjsChromeUtils,
PdfjsContentUtils, PdfStreamConverter */ PdfjsContentUtils, PdfStreamConverter */
'use strict'; "use strict";
var EXPORTED_SYMBOLS = ['PdfJs']; var EXPORTED_SYMBOLS = ["PdfJs"];
const Cc = Components.classes; const Cc = Components.classes;
const Ci = Components.interfaces; const Ci = Components.interfaces;
@ -25,32 +25,32 @@ const Cr = Components.results;
const Cm = Components.manager; const Cm = Components.manager;
const Cu = Components.utils; const Cu = Components.utils;
const PREF_PREFIX = 'pdfjs'; const PREF_PREFIX = "pdfjs";
const PREF_DISABLED = PREF_PREFIX + '.disabled'; const PREF_DISABLED = PREF_PREFIX + ".disabled";
const PREF_MIGRATION_VERSION = PREF_PREFIX + '.migrationVersion'; const PREF_MIGRATION_VERSION = PREF_PREFIX + ".migrationVersion";
const PREF_PREVIOUS_ACTION = PREF_PREFIX + '.previousHandler.preferredAction'; const PREF_PREVIOUS_ACTION = PREF_PREFIX + ".previousHandler.preferredAction";
const PREF_PREVIOUS_ASK = PREF_PREFIX + const PREF_PREVIOUS_ASK = PREF_PREFIX +
'.previousHandler.alwaysAskBeforeHandling'; ".previousHandler.alwaysAskBeforeHandling";
const PREF_DISABLED_PLUGIN_TYPES = 'plugin.disable_full_page_plugin_for_types'; const PREF_DISABLED_PLUGIN_TYPES = "plugin.disable_full_page_plugin_for_types";
const TOPIC_PDFJS_HANDLER_CHANGED = 'pdfjs:handlerChanged'; const TOPIC_PDFJS_HANDLER_CHANGED = "pdfjs:handlerChanged";
const TOPIC_PLUGINS_LIST_UPDATED = 'plugins-list-updated'; const TOPIC_PLUGINS_LIST_UPDATED = "plugins-list-updated";
const TOPIC_PLUGIN_INFO_UPDATED = 'plugin-info-updated'; const TOPIC_PLUGIN_INFO_UPDATED = "plugin-info-updated";
const PDF_CONTENT_TYPE = 'application/pdf'; const PDF_CONTENT_TYPE = "application/pdf";
Cu.import('resource://gre/modules/XPCOMUtils.jsm'); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import('resource://gre/modules/Services.jsm'); Cu.import("resource://gre/modules/Services.jsm");
var Svc = {}; var Svc = {};
XPCOMUtils.defineLazyServiceGetter(Svc, 'mime', XPCOMUtils.defineLazyServiceGetter(Svc, "mime",
'@mozilla.org/mime;1', "@mozilla.org/mime;1",
'nsIMIMEService'); "nsIMIMEService");
XPCOMUtils.defineLazyServiceGetter(Svc, 'pluginHost', XPCOMUtils.defineLazyServiceGetter(Svc, "pluginHost",
'@mozilla.org/plugin/host;1', "@mozilla.org/plugin/host;1",
'nsIPluginHost'); "nsIPluginHost");
XPCOMUtils.defineLazyModuleGetter(this, 'PdfjsChromeUtils', XPCOMUtils.defineLazyModuleGetter(this, "PdfjsChromeUtils",
'resource://pdf.js/PdfjsChromeUtils.jsm'); "resource://pdf.js/PdfjsChromeUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, 'PdfjsContentUtils', XPCOMUtils.defineLazyModuleGetter(this, "PdfjsContentUtils",
'resource://pdf.js/PdfjsContentUtils.jsm'); "resource://pdf.js/PdfjsContentUtils.jsm");
function getBoolPref(aPref, aDefaultValue) { function getBoolPref(aPref, aDefaultValue) {
try { try {
@ -94,22 +94,23 @@ function initializeDefaultPreferences() {
"enhanceTextSelection": false, "enhanceTextSelection": false,
"renderer": "canvas", "renderer": "canvas",
"renderInteractiveForms": false, "renderInteractiveForms": false,
"enablePrintAutoRotate": false,
"disablePageLabels": false "disablePageLabels": false
} }
var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.'); var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + ".");
var defaultValue; var defaultValue;
for (var key in DEFAULT_PREFERENCES) { for (var key in DEFAULT_PREFERENCES) {
defaultValue = DEFAULT_PREFERENCES[key]; defaultValue = DEFAULT_PREFERENCES[key];
switch (typeof defaultValue) { switch (typeof defaultValue) {
case 'boolean': case "boolean":
defaultBranch.setBoolPref(key, defaultValue); defaultBranch.setBoolPref(key, defaultValue);
break; break;
case 'number': case "number":
defaultBranch.setIntPref(key, defaultValue); defaultBranch.setIntPref(key, defaultValue);
break; break;
case 'string': case "string":
defaultBranch.setCharPref(key, defaultValue); defaultBranch.setCharPref(key, defaultValue);
break; break;
} }
@ -155,8 +156,8 @@ var PdfJs = {
init: function init(remote) { init: function init(remote) {
if (Services.appinfo.processType !== if (Services.appinfo.processType !==
Services.appinfo.PROCESS_TYPE_DEFAULT) { Services.appinfo.PROCESS_TYPE_DEFAULT) {
throw new Error('PdfJs.init should only get called ' + throw new Error("PdfJs.init should only get called " +
'in the parent process.'); "in the parent process.");
} }
PdfjsChromeUtils.init(); PdfjsChromeUtils.init();
if (!remote) { if (!remote) {
@ -219,13 +220,13 @@ var PdfJs = {
} }
if (currentVersion < 2) { if (currentVersion < 2) {
// cleaning up of unused database preference (see #3994) // cleaning up of unused database preference (see #3994)
Services.prefs.clearUserPref(PREF_PREFIX + '.database'); Services.prefs.clearUserPref(PREF_PREFIX + ".database");
} }
Services.prefs.setIntPref(PREF_MIGRATION_VERSION, VERSION); Services.prefs.setIntPref(PREF_MIGRATION_VERSION, VERSION);
}, },
_becomeHandler: function _becomeHandler() { _becomeHandler: function _becomeHandler() {
let handlerInfo = Svc.mime.getFromTypeAndExtension(PDF_CONTENT_TYPE, 'pdf'); let handlerInfo = Svc.mime.getFromTypeAndExtension(PDF_CONTENT_TYPE, "pdf");
let prefs = Services.prefs; let prefs = Services.prefs;
if (handlerInfo.preferredAction !== Ci.nsIHandlerInfo.handleInternally && if (handlerInfo.preferredAction !== Ci.nsIHandlerInfo.handleInternally &&
handlerInfo.preferredAction !== false) { handlerInfo.preferredAction !== false) {
@ -236,7 +237,7 @@ var PdfJs = {
prefs.setBoolPref(PREF_PREVIOUS_ASK, handlerInfo.alwaysAskBeforeHandling); prefs.setBoolPref(PREF_PREVIOUS_ASK, handlerInfo.alwaysAskBeforeHandling);
} }
let handlerService = Cc['@mozilla.org/uriloader/handler-service;1']. let handlerService = Cc["@mozilla.org/uriloader/handler-service;1"].
getService(Ci.nsIHandlerService); getService(Ci.nsIHandlerService);
// Change and save mime handler settings. // Change and save mime handler settings.
@ -245,24 +246,24 @@ var PdfJs = {
handlerService.store(handlerInfo); handlerService.store(handlerInfo);
// Also disable any plugins for pdfs. // Also disable any plugins for pdfs.
var stringTypes = ''; var stringTypes = "";
var types = []; var types = [];
if (prefs.prefHasUserValue(PREF_DISABLED_PLUGIN_TYPES)) { if (prefs.prefHasUserValue(PREF_DISABLED_PLUGIN_TYPES)) {
stringTypes = prefs.getCharPref(PREF_DISABLED_PLUGIN_TYPES); stringTypes = prefs.getCharPref(PREF_DISABLED_PLUGIN_TYPES);
} }
if (stringTypes !== '') { if (stringTypes !== "") {
types = stringTypes.split(','); types = stringTypes.split(",");
} }
if (types.indexOf(PDF_CONTENT_TYPE) === -1) { if (types.indexOf(PDF_CONTENT_TYPE) === -1) {
types.push(PDF_CONTENT_TYPE); types.push(PDF_CONTENT_TYPE);
} }
prefs.setCharPref(PREF_DISABLED_PLUGIN_TYPES, types.join(',')); prefs.setCharPref(PREF_DISABLED_PLUGIN_TYPES, types.join(","));
// Update the category manager in case the plugins are already loaded. // Update the category manager in case the plugins are already loaded.
let categoryManager = Cc['@mozilla.org/categorymanager;1']; let categoryManager = Cc["@mozilla.org/categorymanager;1"];
categoryManager.getService(Ci.nsICategoryManager). categoryManager.getService(Ci.nsICategoryManager).
deleteCategoryEntry('Gecko-Content-Viewers', deleteCategoryEntry("Gecko-Content-Viewers",
PDF_CONTENT_TYPE, PDF_CONTENT_TYPE,
false); false);
}, },
@ -272,7 +273,7 @@ var PdfJs = {
this.updateRegistration(); this.updateRegistration();
if (Services.appinfo.processType === if (Services.appinfo.processType ===
Services.appinfo.PROCESS_TYPE_DEFAULT) { Services.appinfo.PROCESS_TYPE_DEFAULT) {
let jsm = 'resource://pdf.js/PdfjsChromeUtils.jsm'; let jsm = "resource://pdf.js/PdfjsChromeUtils.jsm";
let PdfjsChromeUtils = Components.utils.import(jsm, {}).PdfjsChromeUtils; let PdfjsChromeUtils = Components.utils.import(jsm, {}).PdfjsChromeUtils;
PdfjsChromeUtils.notifyChildOfSettingsChange(); PdfjsChromeUtils.notifyChildOfSettingsChange();
} }
@ -297,7 +298,7 @@ var PdfJs = {
// Check if we have disabled plugin handling of 'application/pdf' in prefs // Check if we have disabled plugin handling of 'application/pdf' in prefs
if (Services.prefs.prefHasUserValue(PREF_DISABLED_PLUGIN_TYPES)) { if (Services.prefs.prefHasUserValue(PREF_DISABLED_PLUGIN_TYPES)) {
let disabledPluginTypes = let disabledPluginTypes =
Services.prefs.getCharPref(PREF_DISABLED_PLUGIN_TYPES).split(','); Services.prefs.getCharPref(PREF_DISABLED_PLUGIN_TYPES).split(",");
if (disabledPluginTypes.indexOf(PDF_CONTENT_TYPE) >= 0) { if (disabledPluginTypes.indexOf(PDF_CONTENT_TYPE) >= 0) {
return true; return true;
} }
@ -306,7 +307,7 @@ var PdfJs = {
// Check if there is an enabled pdf plugin. // Check if there is an enabled pdf plugin.
// Note: this check is performed last because getPluginTags() triggers // Note: this check is performed last because getPluginTags() triggers
// costly plugin list initialization (bug 881575) // costly plugin list initialization (bug 881575)
let tags = Cc['@mozilla.org/plugin/host;1']. let tags = Cc["@mozilla.org/plugin/host;1"].
getService(Ci.nsIPluginHost). getService(Ci.nsIPluginHost).
getPluginTags(); getPluginTags();
let enabledPluginFound = tags.some(function(tag) { let enabledPluginFound = tags.some(function(tag) {
@ -328,7 +329,7 @@ var PdfJs = {
return; return;
} }
this._pdfStreamConverterFactory = new Factory(); this._pdfStreamConverterFactory = new Factory();
Cu.import('resource://pdf.js/PdfStreamConverter.jsm'); Cu.import("resource://pdf.js/PdfStreamConverter.jsm");
this._pdfStreamConverterFactory.register(PdfStreamConverter); this._pdfStreamConverterFactory.register(PdfStreamConverter);
this._registered = true; this._registered = true;
@ -339,7 +340,7 @@ var PdfJs = {
return; return;
} }
this._pdfStreamConverterFactory.unregister(); this._pdfStreamConverterFactory.unregister();
Cu.unload('resource://pdf.js/PdfStreamConverter.jsm'); Cu.unload("resource://pdf.js/PdfStreamConverter.jsm");
delete this._pdfStreamConverterFactory; delete this._pdfStreamConverterFactory;
this._registered = false; this._registered = false;

View file

@ -14,23 +14,37 @@
*/ */
/* globals Components, Services */ /* globals Components, Services */
'use strict'; "use strict";
Components.utils.import('resource://gre/modules/Services.jsm'); Components.utils.import("resource://gre/modules/Services.jsm");
var EXPORTED_SYMBOLS = ['NetworkManager']; var EXPORTED_SYMBOLS = ["NetworkManager"];
function log(aMsg) { function log(aMsg) {
var msg = 'network.js: ' + (aMsg.join ? aMsg.join('') : aMsg); var msg = "PdfJsNetwork.jsm: " + (aMsg.join ? aMsg.join("") : aMsg);
Services.console.logStringMessage(msg); Services.console.logStringMessage(msg);
} }
var NetworkManager = (function NetworkManagerClosure() { var NetworkManager = (function NetworkManagerClosure() {
var OK_RESPONSE = 200; const OK_RESPONSE = 200;
var PARTIAL_CONTENT_RESPONSE = 206; const PARTIAL_CONTENT_RESPONSE = 206;
function NetworkManager(url, args) { function getArrayBuffer(xhr) {
var data = xhr.response;
if (typeof data !== "string") {
return data;
}
var length = data.length;
var array = new Uint8Array(length);
for (var i = 0; i < length; i++) {
array[i] = data.charCodeAt(i) & 0xFF;
}
return array.buffer;
}
class NetworkManagerClass {
constructor(url, args) {
this.url = url; this.url = url;
args = args || {}; args = args || {};
this.isHttp = /^https?:/i.test(url); this.isHttp = /^https?:/i.test(url);
@ -46,54 +60,40 @@ var NetworkManager = (function NetworkManagerClosure() {
this.loadedRequests = Object.create(null); this.loadedRequests = Object.create(null);
} }
function getArrayBuffer(xhr) { requestRange(begin, end, listeners) {
var data = xhr.response;
if (typeof data !== 'string') {
return data;
}
var length = data.length;
var array = new Uint8Array(length);
for (var i = 0; i < length; i++) {
array[i] = data.charCodeAt(i) & 0xFF;
}
return array.buffer;
}
NetworkManager.prototype = {
requestRange: function NetworkManager_requestRange(begin, end, listeners) {
var args = { var args = {
begin: begin, begin,
end: end end,
}; };
for (var prop in listeners) { for (var prop in listeners) {
args[prop] = listeners[prop]; args[prop] = listeners[prop];
} }
return this.request(args); return this.request(args);
}, }
requestFull: function NetworkManager_requestFull(listeners) { requestFull(listeners) {
return this.request(listeners); return this.request(listeners);
}, }
request: function NetworkManager_request(args) { request(args) {
var xhr = this.getXhr(); var xhr = this.getXhr();
var xhrId = this.currXhrId++; var xhrId = this.currXhrId++;
var pendingRequest = this.pendingRequests[xhrId] = { var pendingRequest = this.pendingRequests[xhrId] = {
xhr: xhr xhr,
}; };
xhr.open('GET', this.url); xhr.open("GET", this.url);
xhr.withCredentials = this.withCredentials; xhr.withCredentials = this.withCredentials;
for (var property in this.httpHeaders) { for (var property in this.httpHeaders) {
var value = this.httpHeaders[property]; var value = this.httpHeaders[property];
if (typeof value === 'undefined') { if (typeof value === "undefined") {
continue; continue;
} }
xhr.setRequestHeader(property, value); xhr.setRequestHeader(property, value);
} }
if (this.isHttp && 'begin' in args && 'end' in args) { if (this.isHttp && "begin" in args && "end" in args) {
var rangeStr = args.begin + '-' + (args.end - 1); var rangeStr = args.begin + "-" + (args.end - 1);
xhr.setRequestHeader('Range', 'bytes=' + rangeStr); xhr.setRequestHeader("Range", "bytes=" + rangeStr);
pendingRequest.expectedStatus = 206; pendingRequest.expectedStatus = 206;
} else { } else {
pendingRequest.expectedStatus = 200; pendingRequest.expectedStatus = 200;
@ -101,11 +101,11 @@ var NetworkManager = (function NetworkManagerClosure() {
var useMozChunkedLoading = !!args.onProgressiveData; var useMozChunkedLoading = !!args.onProgressiveData;
if (useMozChunkedLoading) { if (useMozChunkedLoading) {
xhr.responseType = 'moz-chunked-arraybuffer'; xhr.responseType = "moz-chunked-arraybuffer";
pendingRequest.onProgressiveData = args.onProgressiveData; pendingRequest.onProgressiveData = args.onProgressiveData;
pendingRequest.mozChunked = true; pendingRequest.mozChunked = true;
} else { } else {
xhr.responseType = 'arraybuffer'; xhr.responseType = "arraybuffer";
} }
if (args.onError) { if (args.onError) {
@ -124,9 +124,9 @@ var NetworkManager = (function NetworkManagerClosure() {
xhr.send(null); xhr.send(null);
return xhrId; return xhrId;
}, }
onProgress: function NetworkManager_onProgress(xhrId, evt) { onProgress(xhrId, evt) {
var pendingRequest = this.pendingRequests[xhrId]; var pendingRequest = this.pendingRequests[xhrId];
if (!pendingRequest) { if (!pendingRequest) {
// Maybe abortRequest was called... // Maybe abortRequest was called...
@ -142,9 +142,9 @@ var NetworkManager = (function NetworkManagerClosure() {
if (onProgress) { if (onProgress) {
onProgress(evt); onProgress(evt);
} }
}, }
onStateChange: function NetworkManager_onStateChange(xhrId, evt) { onStateChange(xhrId, evt) {
var pendingRequest = this.pendingRequests[xhrId]; var pendingRequest = this.pendingRequests[xhrId];
if (!pendingRequest) { if (!pendingRequest) {
// Maybe abortRequest was called... // Maybe abortRequest was called...
@ -197,61 +197,61 @@ var NetworkManager = (function NetworkManagerClosure() {
var chunk = getArrayBuffer(xhr); var chunk = getArrayBuffer(xhr);
if (xhrStatus === PARTIAL_CONTENT_RESPONSE) { if (xhrStatus === PARTIAL_CONTENT_RESPONSE) {
var rangeHeader = xhr.getResponseHeader('Content-Range'); var rangeHeader = xhr.getResponseHeader("Content-Range");
var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader); var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
var begin = parseInt(matches[1], 10); var begin = parseInt(matches[1], 10);
pendingRequest.onDone({ pendingRequest.onDone({
begin: begin, begin,
chunk: chunk chunk,
}); });
} else if (pendingRequest.onProgressiveData) { } else if (pendingRequest.onProgressiveData) {
pendingRequest.onDone(null); pendingRequest.onDone(null);
} else if (chunk) { } else if (chunk) {
pendingRequest.onDone({ pendingRequest.onDone({
begin: 0, begin: 0,
chunk: chunk chunk,
}); });
} else if (pendingRequest.onError) { } else if (pendingRequest.onError) {
pendingRequest.onError(xhr.status); pendingRequest.onError(xhr.status);
} }
}, }
hasPendingRequests: function NetworkManager_hasPendingRequests() { hasPendingRequests() {
for (var xhrId in this.pendingRequests) { for (var xhrId in this.pendingRequests) {
return true; return true;
} }
return false; return false;
}, }
getRequestXhr: function NetworkManager_getXhr(xhrId) { getRequestXhr(xhrId) {
return this.pendingRequests[xhrId].xhr; return this.pendingRequests[xhrId].xhr;
}, }
isStreamingRequest: function NetworkManager_isStreamingRequest(xhrId) { isStreamingRequest(xhrId) {
return !!(this.pendingRequests[xhrId].onProgressiveData); return !!(this.pendingRequests[xhrId].onProgressiveData);
}, }
isPendingRequest: function NetworkManager_isPendingRequest(xhrId) { isPendingRequest(xhrId) {
return xhrId in this.pendingRequests; return xhrId in this.pendingRequests;
}, }
isLoadedRequest: function NetworkManager_isLoadedRequest(xhrId) { isLoadedRequest(xhrId) {
return xhrId in this.loadedRequests; return xhrId in this.loadedRequests;
}, }
abortAllRequests: function NetworkManager_abortAllRequests() { abortAllRequests() {
for (var xhrId in this.pendingRequests) { for (var xhrId in this.pendingRequests) {
this.abortRequest(xhrId | 0); this.abortRequest(xhrId | 0);
} }
}, }
abortRequest: function NetworkManager_abortRequest(xhrId) { abortRequest(xhrId) {
var xhr = this.pendingRequests[xhrId].xhr; var xhr = this.pendingRequests[xhrId].xhr;
delete this.pendingRequests[xhrId]; delete this.pendingRequests[xhrId];
xhr.abort(); xhr.abort();
} }
}; }
return NetworkManager; return NetworkManagerClass;
})(); })();

View file

@ -15,40 +15,39 @@
/* globals Components, Services, XPCOMUtils, NetUtil, PrivateBrowsingUtils, /* globals Components, Services, XPCOMUtils, NetUtil, PrivateBrowsingUtils,
dump, NetworkManager, PdfjsContentUtils */ dump, NetworkManager, PdfjsContentUtils */
'use strict'; "use strict";
var EXPORTED_SYMBOLS = ['PdfStreamConverter']; var EXPORTED_SYMBOLS = ["PdfStreamConverter"];
const Cc = Components.classes; const Cc = Components.classes;
const Ci = Components.interfaces; const Ci = Components.interfaces;
const Cr = Components.results; const Cr = Components.results;
const Cu = Components.utils; const Cu = Components.utils;
// True only if this is the version of pdf.js that is included with firefox.
const MOZ_CENTRAL = JSON.parse('true'); const PDFJS_EVENT_ID = "pdf.js.message";
const PDFJS_EVENT_ID = 'pdf.js.message'; const PDF_CONTENT_TYPE = "application/pdf";
const PDF_CONTENT_TYPE = 'application/pdf'; const PREF_PREFIX = "pdfjs";
const PREF_PREFIX = 'pdfjs'; const PDF_VIEWER_WEB_PAGE = "resource://pdf.js/web/viewer.html";
const PDF_VIEWER_WEB_PAGE = 'resource://pdf.js/web/viewer.html';
const MAX_NUMBER_OF_PREFS = 50; const MAX_NUMBER_OF_PREFS = 50;
const MAX_STRING_PREF_LENGTH = 128; const MAX_STRING_PREF_LENGTH = 128;
Cu.import('resource://gre/modules/XPCOMUtils.jsm'); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import('resource://gre/modules/Services.jsm'); Cu.import("resource://gre/modules/Services.jsm");
Cu.import('resource://gre/modules/NetUtil.jsm'); Cu.import("resource://gre/modules/NetUtil.jsm");
XPCOMUtils.defineLazyModuleGetter(this, 'NetworkManager', XPCOMUtils.defineLazyModuleGetter(this, "NetworkManager",
'resource://pdf.js/PdfJsNetwork.jsm'); "resource://pdf.js/PdfJsNetwork.jsm");
XPCOMUtils.defineLazyModuleGetter(this, 'PrivateBrowsingUtils', XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
'resource://gre/modules/PrivateBrowsingUtils.jsm'); "resource://gre/modules/PrivateBrowsingUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, 'PdfjsContentUtils', XPCOMUtils.defineLazyModuleGetter(this, "PdfjsContentUtils",
'resource://pdf.js/PdfjsContentUtils.jsm'); "resource://pdf.js/PdfjsContentUtils.jsm");
var Svc = {}; var Svc = {};
XPCOMUtils.defineLazyServiceGetter(Svc, 'mime', XPCOMUtils.defineLazyServiceGetter(Svc, "mime",
'@mozilla.org/mime;1', "@mozilla.org/mime;1",
'nsIMIMEService'); "nsIMIMEService");
function getContainingBrowser(domWindow) { function getContainingBrowser(domWindow) {
return domWindow.QueryInterface(Ci.nsIInterfaceRequestor) return domWindow.QueryInterface(Ci.nsIInterfaceRequestor)
@ -59,7 +58,7 @@ function getContainingBrowser(domWindow) {
function getFindBar(domWindow) { function getFindBar(domWindow) {
if (PdfjsContentUtils.isRemote) { if (PdfjsContentUtils.isRemote) {
throw new Error('FindBar is not accessible from the content process.'); throw new Error("FindBar is not accessible from the content process.");
} }
try { try {
var browser = getContainingBrowser(domWindow); var browser = getContainingBrowser(domWindow);
@ -98,12 +97,12 @@ function getStringPref(pref, def) {
} }
function log(aMsg) { function log(aMsg) {
if (!getBoolPref(PREF_PREFIX + '.pdfBugEnabled', false)) { if (!getBoolPref(PREF_PREFIX + ".pdfBugEnabled", false)) {
return; return;
} }
var msg = 'PdfStreamConverter.js: ' + (aMsg.join ? aMsg.join('') : aMsg); var msg = "PdfStreamConverter.js: " + (aMsg.join ? aMsg.join("") : aMsg);
Services.console.logStringMessage(msg); Services.console.logStringMessage(msg);
dump(msg + '\n'); dump(msg + "\n");
} }
function getDOMWindow(aChannel) { function getDOMWindow(aChannel) {
@ -115,16 +114,16 @@ function getDOMWindow(aChannel) {
} }
function getLocalizedStrings(path) { function getLocalizedStrings(path) {
var stringBundle = Cc['@mozilla.org/intl/stringbundle;1']. var stringBundle = Cc["@mozilla.org/intl/stringbundle;1"].
getService(Ci.nsIStringBundleService). getService(Ci.nsIStringBundleService).
createBundle('chrome://pdf.js/locale/' + path); createBundle("chrome://pdf.js/locale/" + path);
var map = {}; var map = {};
var enumerator = stringBundle.getSimpleEnumeration(); var enumerator = stringBundle.getSimpleEnumeration();
while (enumerator.hasMoreElements()) { while (enumerator.hasMoreElements()) {
var string = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement); var string = enumerator.getNext().QueryInterface(Ci.nsIPropertyElement);
var key = string.key, property = 'textContent'; var key = string.key, property = "textContent";
var i = key.lastIndexOf('.'); var i = key.lastIndexOf(".");
if (i >= 0) { if (i >= 0) {
property = key.substring(i + 1); property = key.substring(i + 1);
key = key.substring(0, i); key = key.substring(0, i);
@ -137,7 +136,7 @@ function getLocalizedStrings(path) {
return map; return map;
} }
function getLocalizedString(strings, id, property) { function getLocalizedString(strings, id, property) {
property = property || 'textContent'; property = property || "textContent";
if (id in strings) { if (id in strings) {
return strings[id][property]; return strings[id][property];
} }
@ -187,7 +186,7 @@ PdfDataListener.prototype = {
this.oncompleteCallback(null, errorCode); this.oncompleteCallback(null, errorCode);
} }
}, },
onprogress: function() {}, onprogress() {},
get oncomplete() { get oncomplete() {
return this.oncompleteCallback; return this.oncompleteCallback;
}, },
@ -202,17 +201,20 @@ PdfDataListener.prototype = {
} }
}; };
// All the priviledged actions. /**
function ChromeActions(domWindow, contentDispositionFilename) { * All the privileged actions.
*/
class ChromeActions {
constructor(domWindow, contentDispositionFilename) {
this.domWindow = domWindow; this.domWindow = domWindow;
this.contentDispositionFilename = contentDispositionFilename; this.contentDispositionFilename = contentDispositionFilename;
} }
ChromeActions.prototype = { isInPrivateBrowsing() {
isInPrivateBrowsing: function() {
return PrivateBrowsingUtils.isContentWindowPrivate(this.domWindow); return PrivateBrowsingUtils.isContentWindowPrivate(this.domWindow);
}, }
download: function(data, sendResponse) {
download(data, sendResponse) {
var self = this; var self = this;
var originalUrl = data.originalUrl; var originalUrl = data.originalUrl;
var blobUrl = data.blobUrl || originalUrl; var blobUrl = data.blobUrl || originalUrl;
@ -220,13 +222,13 @@ ChromeActions.prototype = {
// the original url. // the original url.
var originalUri = NetUtil.newURI(originalUrl); var originalUri = NetUtil.newURI(originalUrl);
var filename = data.filename; var filename = data.filename;
if (typeof filename !== 'string' || if (typeof filename !== "string" ||
(!/\.pdf$/i.test(filename) && !data.isAttachment)) { (!/\.pdf$/i.test(filename) && !data.isAttachment)) {
filename = 'document.pdf'; filename = "document.pdf";
} }
var blobUri = NetUtil.newURI(blobUrl); var blobUri = NetUtil.newURI(blobUrl);
var extHelperAppSvc = var extHelperAppSvc =
Cc['@mozilla.org/uriloader/external-helper-app-service;1']. Cc["@mozilla.org/uriloader/external-helper-app-service;1"].
getService(Ci.nsIExternalHelperAppService); getService(Ci.nsIExternalHelperAppService);
var docIsPrivate = this.isInPrivateBrowsing(); var docIsPrivate = this.isInPrivateBrowsing();
@ -234,7 +236,7 @@ ChromeActions.prototype = {
uri: blobUri, uri: blobUri,
loadUsingSystemPrincipal: true, loadUsingSystemPrincipal: true,
}); });
if ('nsIPrivateBrowsingChannel' in Ci && if ("nsIPrivateBrowsingChannel" in Ci &&
netChannel instanceof Ci.nsIPrivateBrowsingChannel) { netChannel instanceof Ci.nsIPrivateBrowsingChannel) {
netChannel.setPrivate(docIsPrivate); netChannel.setPrivate(docIsPrivate);
} }
@ -247,7 +249,7 @@ ChromeActions.prototype = {
} }
// Create a nsIInputStreamChannel so we can set the url on the channel // Create a nsIInputStreamChannel so we can set the url on the channel
// so the filename will be correct. // so the filename will be correct.
var channel = Cc['@mozilla.org/network/input-stream-channel;1']. var channel = Cc["@mozilla.org/network/input-stream-channel;1"].
createInstance(Ci.nsIInputStreamChannel); createInstance(Ci.nsIInputStreamChannel);
channel.QueryInterface(Ci.nsIChannel); channel.QueryInterface(Ci.nsIChannel);
try { try {
@ -262,25 +264,25 @@ ChromeActions.prototype = {
channel.setURI(originalUri); channel.setURI(originalUri);
channel.loadInfo = netChannel.loadInfo; channel.loadInfo = netChannel.loadInfo;
channel.contentStream = aInputStream; channel.contentStream = aInputStream;
if ('nsIPrivateBrowsingChannel' in Ci && if ("nsIPrivateBrowsingChannel" in Ci &&
channel instanceof Ci.nsIPrivateBrowsingChannel) { channel instanceof Ci.nsIPrivateBrowsingChannel) {
channel.setPrivate(docIsPrivate); channel.setPrivate(docIsPrivate);
} }
var listener = { var listener = {
extListener: null, extListener: null,
onStartRequest: function(aRequest, aContext) { onStartRequest(aRequest, aContext) {
var loadContext = self.domWindow var loadContext = self.domWindow
.QueryInterface(Ci.nsIInterfaceRequestor) .QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation) .getInterface(Ci.nsIWebNavigation)
.QueryInterface(Ci.nsILoadContext); .QueryInterface(Ci.nsILoadContext);
this.extListener = extHelperAppSvc.doContent( this.extListener = extHelperAppSvc.doContent(
(data.isAttachment ? 'application/octet-stream' : (data.isAttachment ? "application/octet-stream" :
'application/pdf'), "application/pdf"),
aRequest, loadContext, false); aRequest, loadContext, false);
this.extListener.onStartRequest(aRequest, aContext); this.extListener.onStartRequest(aRequest, aContext);
}, },
onStopRequest: function(aRequest, aContext, aStatusCode) { onStopRequest(aRequest, aContext, aStatusCode) {
if (this.extListener) { if (this.extListener) {
this.extListener.onStopRequest(aRequest, aContext, aStatusCode); this.extListener.onStopRequest(aRequest, aContext, aStatusCode);
} }
@ -289,33 +291,35 @@ ChromeActions.prototype = {
sendResponse(false); sendResponse(false);
} }
}, },
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, onDataAvailable(aRequest, aContext, aDataInputStream, aOffset, aCount) {
aCount) { this.extListener.onDataAvailable(aRequest, aContext, aDataInputStream,
this.extListener.onDataAvailable(aRequest, aContext, aInputStream,
aOffset, aCount); aOffset, aCount);
} }
}; };
channel.asyncOpen2(listener); channel.asyncOpen2(listener);
}); });
}, }
getLocale: function() {
return getStringPref('general.useragent.locale', 'en-US'); getLocale() {
}, return getStringPref("general.useragent.locale", "en-US");
getStrings: function(data) { }
getStrings(data) {
try { try {
// Lazy initialization of localizedStrings // Lazy initialization of localizedStrings
if (!('localizedStrings' in this)) { if (!("localizedStrings" in this)) {
this.localizedStrings = getLocalizedStrings('viewer.properties'); this.localizedStrings = getLocalizedStrings("viewer.properties");
} }
var result = this.localizedStrings[data]; var result = this.localizedStrings[data];
return JSON.stringify(result || null); return JSON.stringify(result || null);
} catch (e) { } catch (e) {
log('Unable to retrieve localized strings: ' + e); log("Unable to retrieve localized strings: " + e);
return 'null'; return "null";
} }
}, }
supportsIntegratedFind: function() {
supportsIntegratedFind() {
// Integrated find is only supported when we're not in a frame // Integrated find is only supported when we're not in a frame
if (this.domWindow.frameElement !== null) { if (this.domWindow.frameElement !== null) {
return false; return false;
@ -328,54 +332,61 @@ ChromeActions.prototype = {
// ... or when the new find events code exists. // ... or when the new find events code exists.
var findBar = getFindBar(this.domWindow); var findBar = getFindBar(this.domWindow);
return !!findBar && ('updateControlState' in findBar); return !!findBar && ("updateControlState" in findBar);
}, }
supportsDocumentFonts: function() {
var prefBrowser = getIntPref('browser.display.use_document_fonts', 1); supportsDocumentFonts() {
var prefGfx = getBoolPref('gfx.downloadable_fonts.enabled', true); var prefBrowser = getIntPref("browser.display.use_document_fonts", 1);
return (!!prefBrowser && prefGfx); var prefGfx = getBoolPref("gfx.downloadable_fonts.enabled", true);
}, return (!!prefBrowser && prefGfx);
supportsDocumentColors: function() { }
return getIntPref('browser.display.document_color_use', 0) !== 2;
}, supportsDocumentColors() {
supportedMouseWheelZoomModifierKeys: function() { return getIntPref("browser.display.document_color_use", 0) !== 2;
return { }
ctrlKey: getIntPref('mousewheel.with_control.action', 3) === 3,
metaKey: getIntPref('mousewheel.with_meta.action', 1) === 3, supportedMouseWheelZoomModifierKeys() {
}; return {
}, ctrlKey: getIntPref("mousewheel.with_control.action", 3) === 3,
fallback: function(args, sendResponse) { metaKey: getIntPref("mousewheel.with_meta.action", 1) === 3,
var featureId = args.featureId; };
var url = args.url; }
/**
* @param {Object} args - Object with `featureId` and `url` properties.
* @param {function} sendResponse - Callback function.
*/
fallback(args, sendResponse) {
var featureId = args.featureId;
var self = this;
var domWindow = this.domWindow; var domWindow = this.domWindow;
var strings = getLocalizedStrings('chrome.properties'); var strings = getLocalizedStrings("chrome.properties");
var message; var message;
if (featureId === 'forms') { if (featureId === "forms") {
message = getLocalizedString(strings, 'unsupported_feature_forms'); message = getLocalizedString(strings, "unsupported_feature_forms");
} else { } else {
message = getLocalizedString(strings, 'unsupported_feature'); message = getLocalizedString(strings, "unsupported_feature");
} }
PdfjsContentUtils.displayWarning(domWindow, message, PdfjsContentUtils.displayWarning(domWindow, message,
getLocalizedString(strings, 'open_with_different_viewer'), getLocalizedString(strings, "open_with_different_viewer"),
getLocalizedString(strings, 'open_with_different_viewer', 'accessKey')); getLocalizedString(strings, "open_with_different_viewer", "accessKey"));
let winmm = domWindow.QueryInterface(Ci.nsIInterfaceRequestor) let winmm = domWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell) .getInterface(Ci.nsIDocShell)
.QueryInterface(Ci.nsIInterfaceRequestor) .QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIContentFrameMessageManager); .getInterface(Ci.nsIContentFrameMessageManager);
winmm.addMessageListener('PDFJS:Child:fallbackDownload', winmm.addMessageListener("PDFJS:Child:fallbackDownload",
function fallbackDownload(msg) { function fallbackDownload(msg) {
let data = msg.data; let data = msg.data;
sendResponse(data.download); sendResponse(data.download);
winmm.removeMessageListener('PDFJS:Child:fallbackDownload', winmm.removeMessageListener("PDFJS:Child:fallbackDownload",
fallbackDownload); fallbackDownload);
}); });
}, }
updateFindControlState: function(data) {
updateFindControlState(data) {
if (!this.supportsIntegratedFind()) { if (!this.supportsIntegratedFind()) {
return; return;
} }
@ -383,8 +394,8 @@ ChromeActions.prototype = {
var result = data.result; var result = data.result;
var findPrevious = data.findPrevious; var findPrevious = data.findPrevious;
var findPreviousType = typeof findPrevious; var findPreviousType = typeof findPrevious;
if ((typeof result !== 'number' || result < 0 || result > 3) || if ((typeof result !== "number" || result < 0 || result > 3) ||
(findPreviousType !== 'undefined' && findPreviousType !== 'boolean')) { (findPreviousType !== "undefined" && findPreviousType !== "boolean")) {
return; return;
} }
@ -393,33 +404,34 @@ ChromeActions.prototype = {
.QueryInterface(Ci.nsIInterfaceRequestor) .QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIContentFrameMessageManager); .getInterface(Ci.nsIContentFrameMessageManager);
winmm.sendAsyncMessage('PDFJS:Parent:updateControlState', data); winmm.sendAsyncMessage("PDFJS:Parent:updateControlState", data);
}, }
setPreferences: function(prefs, sendResponse) {
var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.'); setPreferences(prefs, sendResponse) {
var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + ".");
var numberOfPrefs = 0; var numberOfPrefs = 0;
var prefValue, prefName; var prefValue, prefName;
for (var key in prefs) { for (var key in prefs) {
if (++numberOfPrefs > MAX_NUMBER_OF_PREFS) { if (++numberOfPrefs > MAX_NUMBER_OF_PREFS) {
log('setPreferences - Exceeded the maximum number of preferences ' + log("setPreferences - Exceeded the maximum number of preferences " +
'that is allowed to be set at once.'); "that is allowed to be set at once.");
break; break;
} else if (!defaultBranch.getPrefType(key)) { } else if (!defaultBranch.getPrefType(key)) {
continue; continue;
} }
prefValue = prefs[key]; prefValue = prefs[key];
prefName = (PREF_PREFIX + '.' + key); prefName = (PREF_PREFIX + "." + key);
switch (typeof prefValue) { switch (typeof prefValue) {
case 'boolean': case "boolean":
PdfjsContentUtils.setBoolPref(prefName, prefValue); PdfjsContentUtils.setBoolPref(prefName, prefValue);
break; break;
case 'number': case "number":
PdfjsContentUtils.setIntPref(prefName, prefValue); PdfjsContentUtils.setIntPref(prefName, prefValue);
break; break;
case 'string': case "string":
if (prefValue.length > MAX_STRING_PREF_LENGTH) { if (prefValue.length > MAX_STRING_PREF_LENGTH) {
log('setPreferences - Exceeded the maximum allowed length ' + log("setPreferences - Exceeded the maximum allowed length " +
'for a string preference.'); "for a string preference.");
} else { } else {
PdfjsContentUtils.setStringPref(prefName, prefValue); PdfjsContentUtils.setStringPref(prefName, prefValue);
} }
@ -429,50 +441,50 @@ ChromeActions.prototype = {
if (sendResponse) { if (sendResponse) {
sendResponse(true); sendResponse(true);
} }
}, }
getPreferences: function(prefs, sendResponse) {
var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.'); getPreferences(prefs, sendResponse) {
var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + ".");
var currentPrefs = {}, numberOfPrefs = 0; var currentPrefs = {}, numberOfPrefs = 0;
var prefValue, prefName; var prefValue, prefName;
for (var key in prefs) { for (var key in prefs) {
if (++numberOfPrefs > MAX_NUMBER_OF_PREFS) { if (++numberOfPrefs > MAX_NUMBER_OF_PREFS) {
log('getPreferences - Exceeded the maximum number of preferences ' + log("getPreferences - Exceeded the maximum number of preferences " +
'that is allowed to be fetched at once.'); "that is allowed to be fetched at once.");
break; break;
} else if (!defaultBranch.getPrefType(key)) { } else if (!defaultBranch.getPrefType(key)) {
continue; continue;
} }
prefValue = prefs[key]; prefValue = prefs[key];
prefName = (PREF_PREFIX + '.' + key); prefName = (PREF_PREFIX + "." + key);
switch (typeof prefValue) { switch (typeof prefValue) {
case 'boolean': case "boolean":
currentPrefs[key] = getBoolPref(prefName, prefValue); currentPrefs[key] = getBoolPref(prefName, prefValue);
break; break;
case 'number': case "number":
currentPrefs[key] = getIntPref(prefName, prefValue); currentPrefs[key] = getIntPref(prefName, prefValue);
break; break;
case 'string': case "string":
currentPrefs[key] = getStringPref(prefName, prefValue); currentPrefs[key] = getStringPref(prefName, prefValue);
break; break;
} }
} }
let result = JSON.stringify(currentPrefs);
if (sendResponse) { if (sendResponse) {
sendResponse(JSON.stringify(currentPrefs)); sendResponse(result);
} else {
return JSON.stringify(currentPrefs);
} }
return result;
} }
}; }
var RangedChromeActions = (function RangedChromeActionsClosure() { /**
/** * This is for range requests.
* This is for range requests
*/ */
function RangedChromeActions( class RangedChromeActions extends ChromeActions {
domWindow, contentDispositionFilename, originalRequest, constructor(domWindow, contentDispositionFilename, originalRequest,
rangeEnabled, streamingEnabled, dataListener) { rangeEnabled, streamingEnabled, dataListener) {
ChromeActions.call(this, domWindow, contentDispositionFilename); super(domWindow, contentDispositionFilename);
this.dataListener = dataListener; this.dataListener = dataListener;
this.originalRequest = originalRequest; this.originalRequest = originalRequest;
this.rangeEnabled = rangeEnabled; this.rangeEnabled = rangeEnabled;
@ -484,8 +496,8 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
// Pass all the headers from the original request through // Pass all the headers from the original request through
var httpHeaderVisitor = { var httpHeaderVisitor = {
headers: {}, headers: {},
visitHeader: function(aHeader, aValue) { visitHeader(aHeader, aValue) {
if (aHeader === 'Range') { if (aHeader === "Range") {
// When loading the PDF from cache, firefox seems to set the Range // When loading the PDF from cache, firefox seems to set the Range
// request header to fetch only the unfetched portions of the file // request header to fetch only the unfetched portions of the file
// (e.g. 'Range: bytes=1024-'). However, we want to set this header // (e.g. 'Range: bytes=1024-'). However, we want to set this header
@ -503,7 +515,7 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
var xhr_onreadystatechange = function xhr_onreadystatechange() { var xhr_onreadystatechange = function xhr_onreadystatechange() {
if (this.readyState === 1) { // LOADING if (this.readyState === 1) { // LOADING
var netChannel = this.channel; var netChannel = this.channel;
if ('nsIPrivateBrowsingChannel' in Ci && if ("nsIPrivateBrowsingChannel" in Ci &&
netChannel instanceof Ci.nsIPrivateBrowsingChannel) { netChannel instanceof Ci.nsIPrivateBrowsingChannel) {
var docIsPrivate = self.isInPrivateBrowsing(); var docIsPrivate = self.isInPrivateBrowsing();
netChannel.setPrivate(docIsPrivate); netChannel.setPrivate(docIsPrivate);
@ -512,31 +524,26 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
}; };
var getXhr = function getXhr() { var getXhr = function getXhr() {
const XMLHttpRequest = Components.Constructor( const XMLHttpRequest = Components.Constructor(
'@mozilla.org/xmlextras/xmlhttprequest;1'); "@mozilla.org/xmlextras/xmlhttprequest;1");
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();
xhr.addEventListener('readystatechange', xhr_onreadystatechange); xhr.addEventListener("readystatechange", xhr_onreadystatechange);
return xhr; return xhr;
}; };
this.networkManager = new NetworkManager(this.pdfUrl, { this.networkManager = new NetworkManager(this.pdfUrl, {
httpHeaders: httpHeaderVisitor.headers, httpHeaders: httpHeaderVisitor.headers,
getXhr: getXhr getXhr,
}); });
// If we are in range request mode, this means we manually issued xhr // If we are in range request mode, this means we manually issued xhr
// requests, which we need to abort when we leave the page // requests, which we need to abort when we leave the page
domWindow.addEventListener('unload', function unload(e) { domWindow.addEventListener("unload", function unload(e) {
domWindow.removeEventListener(e.type, unload); domWindow.removeEventListener(e.type, unload);
self.abortLoading(); self.abortLoading();
}); });
} }
RangedChromeActions.prototype = Object.create(ChromeActions.prototype); initPassiveLoading() {
var proto = RangedChromeActions.prototype;
proto.constructor = RangedChromeActions;
proto.initPassiveLoading = function RangedChromeActions_initPassiveLoading() {
var self = this;
var data; var data;
if (!this.streamingEnabled) { if (!this.streamingEnabled) {
this.originalRequest.cancel(Cr.NS_BINDING_ABORTED); this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
@ -546,32 +553,32 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
} else { } else {
data = this.dataListener.readData(); data = this.dataListener.readData();
this.dataListener.onprogress = function (loaded, total) { this.dataListener.onprogress = (loaded, total) => {
self.domWindow.postMessage({ this.domWindow.postMessage({
pdfjsLoadAction: 'progressiveRead', pdfjsLoadAction: "progressiveRead",
loaded: loaded, loaded,
total: total, total,
chunk: self.dataListener.readData() chunk: this.dataListener.readData(),
}, '*'); }, "*");
}; };
this.dataListener.oncomplete = function () { this.dataListener.oncomplete = () => {
self.dataListener = null; this.dataListener = null;
}; };
} }
this.domWindow.postMessage({ this.domWindow.postMessage({
pdfjsLoadAction: 'supportsRangedLoading', pdfjsLoadAction: "supportsRangedLoading",
rangeEnabled: this.rangeEnabled, rangeEnabled: this.rangeEnabled,
streamingEnabled: this.streamingEnabled, streamingEnabled: this.streamingEnabled,
pdfUrl: this.pdfUrl, pdfUrl: this.pdfUrl,
length: this.contentLength, length: this.contentLength,
data: data data,
}, '*'); }, "*");
return true; return true;
}; }
proto.requestDataRange = function RangedChromeActions_requestDataRange(args) { requestDataRange(args) {
if (!this.rangeEnabled) { if (!this.rangeEnabled) {
return; return;
} }
@ -583,101 +590,89 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
// errors from chrome code for non-range requests, so this doesn't // errors from chrome code for non-range requests, so this doesn't
// seem high-pri // seem high-pri
this.networkManager.requestRange(begin, end, { this.networkManager.requestRange(begin, end, {
onDone: function RangedChromeActions_onDone(args) { onDone: function RangedChromeActions_onDone(aArgs) {
domWindow.postMessage({ domWindow.postMessage({
pdfjsLoadAction: 'range', pdfjsLoadAction: "range",
begin: args.begin, begin: aArgs.begin,
chunk: args.chunk chunk: aArgs.chunk,
}, '*'); }, "*");
}, },
onProgress: function RangedChromeActions_onProgress(evt) { onProgress: function RangedChromeActions_onProgress(evt) {
domWindow.postMessage({ domWindow.postMessage({
pdfjsLoadAction: 'rangeProgress', pdfjsLoadAction: "rangeProgress",
loaded: evt.loaded, loaded: evt.loaded,
}, '*'); }, "*");
} }
}); });
}; }
proto.abortLoading = function RangedChromeActions_abortLoading() { abortLoading() {
this.networkManager.abortAllRequests(); this.networkManager.abortAllRequests();
if (this.originalRequest) { if (this.originalRequest) {
this.originalRequest.cancel(Cr.NS_BINDING_ABORTED); this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
this.originalRequest = null; this.originalRequest = null;
} }
this.dataListener = null; this.dataListener = null;
}; }
}
return RangedChromeActions; /**
})(); * This is for a single network stream.
var StandardChromeActions = (function StandardChromeActionsClosure() {
/**
* This is for a single network stream
*/ */
function StandardChromeActions(domWindow, contentDispositionFilename, class StandardChromeActions extends ChromeActions {
originalRequest, dataListener) { constructor(domWindow, contentDispositionFilename, originalRequest,
dataListener) {
ChromeActions.call(this, domWindow, contentDispositionFilename); super(domWindow, contentDispositionFilename);
this.originalRequest = originalRequest; this.originalRequest = originalRequest;
this.dataListener = dataListener; this.dataListener = dataListener;
} }
StandardChromeActions.prototype = Object.create(ChromeActions.prototype); initPassiveLoading() {
var proto = StandardChromeActions.prototype;
proto.constructor = StandardChromeActions;
proto.initPassiveLoading =
function StandardChromeActions_initPassiveLoading() {
if (!this.dataListener) { if (!this.dataListener) {
return false; return false;
} }
var self = this; this.dataListener.onprogress = (loaded, total) => {
this.domWindow.postMessage({
this.dataListener.onprogress = function ChromeActions_dataListenerProgress( pdfjsLoadAction: "progress",
loaded, total) { loaded,
self.domWindow.postMessage({ total,
pdfjsLoadAction: 'progress', }, "*");
loaded: loaded,
total: total
}, '*');
}; };
this.dataListener.oncomplete = this.dataListener.oncomplete = (data, errorCode) => {
function StandardChromeActions_dataListenerComplete(data, errorCode) { this.domWindow.postMessage({
self.domWindow.postMessage({ pdfjsLoadAction: "complete",
pdfjsLoadAction: 'complete', data,
data: data, errorCode,
errorCode: errorCode }, "*");
}, '*');
self.dataListener = null; this.dataListener = null;
self.originalRequest = null; this.originalRequest = null;
}; };
return true; return true;
}; }
proto.abortLoading = function StandardChromeActions_abortLoading() { abortLoading() {
if (this.originalRequest) { if (this.originalRequest) {
this.originalRequest.cancel(Cr.NS_BINDING_ABORTED); this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
this.originalRequest = null; this.originalRequest = null;
} }
this.dataListener = null; this.dataListener = null;
}; }
return StandardChromeActions;
})();
// Event listener to trigger chrome privileged code.
function RequestListener(actions) {
this.actions = actions;
} }
// Receive an event and synchronously or asynchronously responds.
RequestListener.prototype.receive = function(event) { /**
* Event listener to trigger chrome privileged code.
*/
class RequestListener {
constructor(actions) {
this.actions = actions;
}
// Receive an event and synchronously or asynchronously responds.
receive(event) {
var message = event.target; var message = event.target;
var doc = message.ownerDocument; var doc = message.ownerDocument;
var action = event.detail.action; var action = event.detail.action;
@ -685,7 +680,7 @@ RequestListener.prototype.receive = function(event) {
var sync = event.detail.sync; var sync = event.detail.sync;
var actions = this.actions; var actions = this.actions;
if (!(action in actions)) { if (!(action in actions)) {
log('Unknown action: ' + action); log("Unknown action: " + action);
return; return;
} }
var response; var response;
@ -697,11 +692,11 @@ RequestListener.prototype.receive = function(event) {
doc.documentElement.removeChild(message); doc.documentElement.removeChild(message);
response = null; response = null;
} else { } else {
response = function sendResponse(response) { response = function sendResponse(aResponse) {
try { try {
var listener = doc.createEvent('CustomEvent'); var listener = doc.createEvent("CustomEvent");
let detail = Cu.cloneInto({ response: response }, doc.defaultView); let detail = Cu.cloneInto({ response: aResponse }, doc.defaultView);
listener.initCustomEvent('pdf.js.response', true, false, detail); listener.initCustomEvent("pdf.js.response", true, false, detail);
return message.dispatchEvent(listener); return message.dispatchEvent(listener);
} catch (e) { } catch (e) {
// doc is no longer accessible because the requestor is already // doc is no longer accessible because the requestor is already
@ -712,47 +707,52 @@ RequestListener.prototype.receive = function(event) {
} }
actions[action].call(this.actions, data, response); actions[action].call(this.actions, data, response);
} }
}; }
}
// Forwards events from the eventElement to the contentWindow only if the /**
// content window matches the currently selected browser window. * Forwards events from the eventElement to the contentWindow only if the
function FindEventManager(contentWindow) { * content window matches the currently selected browser window.
*/
class FindEventManager {
constructor(contentWindow) {
this.contentWindow = contentWindow; this.contentWindow = contentWindow;
this.winmm = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor) this.winmm = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell) .getInterface(Ci.nsIDocShell)
.QueryInterface(Ci.nsIInterfaceRequestor) .QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIContentFrameMessageManager); .getInterface(Ci.nsIContentFrameMessageManager);
} }
FindEventManager.prototype.bind = function() { bind() {
var unload = function(e) { var unload = function(e) {
this.unbind(); this.unbind();
this.contentWindow.removeEventListener(e.type, unload); this.contentWindow.removeEventListener(e.type, unload);
}.bind(this); }.bind(this);
this.contentWindow.addEventListener('unload', unload); this.contentWindow.addEventListener("unload", unload);
// We cannot directly attach listeners to for the find events // We cannot directly attach listeners to for the find events
// since the FindBar is in the parent process. Instead we're // since the FindBar is in the parent process. Instead we're
// asking the PdfjsChromeUtils to do it for us and forward // asking the PdfjsChromeUtils to do it for us and forward
// all the find events to us. // all the find events to us.
this.winmm.sendAsyncMessage('PDFJS:Parent:addEventListener'); this.winmm.sendAsyncMessage("PDFJS:Parent:addEventListener");
this.winmm.addMessageListener('PDFJS:Child:handleEvent', this); this.winmm.addMessageListener("PDFJS:Child:handleEvent", this);
}; }
FindEventManager.prototype.receiveMessage = function(msg) { receiveMessage(msg) {
var detail = msg.data.detail; var detail = msg.data.detail;
var type = msg.data.type; var type = msg.data.type;
var contentWindow = this.contentWindow; var contentWindow = this.contentWindow;
detail = Cu.cloneInto(detail, contentWindow); detail = Cu.cloneInto(detail, contentWindow);
var forward = contentWindow.document.createEvent('CustomEvent'); var forward = contentWindow.document.createEvent("CustomEvent");
forward.initCustomEvent(type, true, true, detail); forward.initCustomEvent(type, true, true, detail);
contentWindow.dispatchEvent(forward); contentWindow.dispatchEvent(forward);
}; }
FindEventManager.prototype.unbind = function() { unbind() {
this.winmm.sendAsyncMessage('PDFJS:Parent:removeEventListener'); this.winmm.sendAsyncMessage("PDFJS:Parent:removeEventListener");
}; }
}
function PdfStreamConverter() { function PdfStreamConverter() {
} }
@ -760,12 +760,12 @@ function PdfStreamConverter() {
PdfStreamConverter.prototype = { PdfStreamConverter.prototype = {
// properties required for XPCOM registration: // properties required for XPCOM registration:
classID: Components.ID('{d0c5195d-e798-49d4-b1d3-9324328b2291}'), classID: Components.ID("{d0c5195d-e798-49d4-b1d3-9324328b2291}"),
classDescription: 'pdf.js Component', classDescription: "pdf.js Component",
contractID: '@mozilla.org/streamconv;1?from=application/pdf&to=*/*', contractID: "@mozilla.org/streamconv;1?from=application/pdf&to=*/*",
classID2: Components.ID('{d0c5195d-e798-49d4-b1d3-9324328b2292}'), classID2: Components.ID("{d0c5195d-e798-49d4-b1d3-9324328b2292}"),
contractID2: '@mozilla.org/streamconv;1?from=application/pdf&to=text/html', contractID2: "@mozilla.org/streamconv;1?from=application/pdf&to=text/html",
QueryInterface: XPCOMUtils.generateQI([ QueryInterface: XPCOMUtils.generateQI([
Ci.nsISupports, Ci.nsISupports,
@ -791,18 +791,18 @@ PdfStreamConverter.prototype = {
*/ */
// nsIStreamConverter::convert // nsIStreamConverter::convert
convert: function(aFromStream, aFromType, aToType, aCtxt) { convert(aFromStream, aFromType, aToType, aCtxt) {
throw Cr.NS_ERROR_NOT_IMPLEMENTED; throw Cr.NS_ERROR_NOT_IMPLEMENTED;
}, },
// nsIStreamConverter::asyncConvertData // nsIStreamConverter::asyncConvertData
asyncConvertData: function(aFromType, aToType, aListener, aCtxt) { asyncConvertData(aFromType, aToType, aListener, aCtxt) {
// Store the listener passed to us // Store the listener passed to us
this.listener = aListener; this.listener = aListener;
}, },
// nsIStreamListener::onDataAvailable // nsIStreamListener::onDataAvailable
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) { onDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount) {
if (!this.dataListener) { if (!this.dataListener) {
return; return;
} }
@ -814,7 +814,7 @@ PdfStreamConverter.prototype = {
}, },
// nsIRequestObserver::onStartRequest // nsIRequestObserver::onStartRequest
onStartRequest: function(aRequest, aContext) { onStartRequest(aRequest, aContext) {
// Setup the request so we can use it below. // Setup the request so we can use it below.
var isHttpRequest = false; var isHttpRequest = false;
try { try {
@ -825,29 +825,29 @@ PdfStreamConverter.prototype = {
var rangeRequest = false; var rangeRequest = false;
var streamRequest = false; var streamRequest = false;
if (isHttpRequest) { if (isHttpRequest) {
var contentEncoding = 'identity'; var contentEncoding = "identity";
try { try {
contentEncoding = aRequest.getResponseHeader('Content-Encoding'); contentEncoding = aRequest.getResponseHeader("Content-Encoding");
} catch (e) {} } catch (e) {}
var acceptRanges; var acceptRanges;
try { try {
acceptRanges = aRequest.getResponseHeader('Accept-Ranges'); acceptRanges = aRequest.getResponseHeader("Accept-Ranges");
} catch (e) {} } catch (e) {}
var hash = aRequest.URI.ref; var hash = aRequest.URI.ref;
var isPDFBugEnabled = getBoolPref(PREF_PREFIX + '.pdfBugEnabled', false); var isPDFBugEnabled = getBoolPref(PREF_PREFIX + ".pdfBugEnabled", false);
rangeRequest = contentEncoding === 'identity' && rangeRequest = contentEncoding === "identity" &&
acceptRanges === 'bytes' && acceptRanges === "bytes" &&
aRequest.contentLength >= 0 && aRequest.contentLength >= 0 &&
!getBoolPref(PREF_PREFIX + '.disableRange', false) && !getBoolPref(PREF_PREFIX + ".disableRange", false) &&
(!isPDFBugEnabled || (!isPDFBugEnabled ||
hash.toLowerCase().indexOf('disablerange=true') < 0); hash.toLowerCase().indexOf("disablerange=true") < 0);
streamRequest = contentEncoding === 'identity' && streamRequest = contentEncoding === "identity" &&
aRequest.contentLength >= 0 && aRequest.contentLength >= 0 &&
!getBoolPref(PREF_PREFIX + '.disableStream', false) && !getBoolPref(PREF_PREFIX + ".disableStream", false) &&
(!isPDFBugEnabled || (!isPDFBugEnabled ||
hash.toLowerCase().indexOf('disablestream=true') < 0); hash.toLowerCase().indexOf("disablestream=true") < 0);
} }
aRequest.QueryInterface(Ci.nsIChannel); aRequest.QueryInterface(Ci.nsIChannel);
@ -860,21 +860,21 @@ PdfStreamConverter.prototype = {
} catch (e) {} } catch (e) {}
// Change the content type so we don't get stuck in a loop. // Change the content type so we don't get stuck in a loop.
aRequest.setProperty('contentType', aRequest.contentType); aRequest.setProperty("contentType", aRequest.contentType);
aRequest.contentType = 'text/html'; aRequest.contentType = "text/html";
if (isHttpRequest) { if (isHttpRequest) {
// We trust PDF viewer, using no CSP // We trust PDF viewer, using no CSP
aRequest.setResponseHeader('Content-Security-Policy', '', false); aRequest.setResponseHeader("Content-Security-Policy", "", false);
aRequest.setResponseHeader('Content-Security-Policy-Report-Only', '', aRequest.setResponseHeader("Content-Security-Policy-Report-Only", "",
false); false);
// The viewer does not need to handle HTTP Refresh header. // The viewer does not need to handle HTTP Refresh header.
aRequest.setResponseHeader('Refresh', '', false); aRequest.setResponseHeader("Refresh", "", false);
} }
// Creating storage for PDF data // Creating storage for PDF data
var contentLength = aRequest.contentLength; var contentLength = aRequest.contentLength;
this.dataListener = new PdfDataListener(contentLength); this.dataListener = new PdfDataListener(contentLength);
this.binaryStream = Cc['@mozilla.org/binaryinputstream;1'] this.binaryStream = Cc["@mozilla.org/binaryinputstream;1"]
.createInstance(Ci.nsIBinaryInputStream); .createInstance(Ci.nsIBinaryInputStream);
// Create a new channel that is viewer loaded as a resource. // Create a new channel that is viewer loaded as a resource.
@ -890,14 +890,14 @@ PdfStreamConverter.prototype = {
// request(aRequest) below so we don't overwrite the original channel and // request(aRequest) below so we don't overwrite the original channel and
// trigger an assertion. // trigger an assertion.
var proxy = { var proxy = {
onStartRequest: function(request, context) { onStartRequest(request, context) {
listener.onStartRequest(aRequest, aContext); listener.onStartRequest(aRequest, aContext);
}, },
onDataAvailable: function(request, context, inputStream, offset, count) { onDataAvailable(request, context, inputStream, offset, count) {
listener.onDataAvailable(aRequest, aContext, inputStream, listener.onDataAvailable(aRequest, aContext, inputStream,
offset, count); offset, count);
}, },
onStopRequest: function(request, context, statusCode) { onStopRequest(request, context, statusCode) {
// We get the DOM window here instead of before the request since it // We get the DOM window here instead of before the request since it
// may have changed during a redirect. // may have changed during a redirect.
var domWindow = getDOMWindow(channel); var domWindow = getDOMWindow(channel);
@ -921,8 +921,8 @@ PdfStreamConverter.prototype = {
listener.onStopRequest(aRequest, aContext, statusCode); listener.onStopRequest(aRequest, aContext, statusCode);
if (domWindow.frameElement) { if (domWindow.frameElement) {
var isObjectEmbed = domWindow.frameElement.tagName !== 'IFRAME' || var isObjectEmbed = domWindow.frameElement.tagName !== "IFRAME" ||
domWindow.frameElement.className === 'previewPluginContentFrame'; domWindow.frameElement.className === "previewPluginContentFrame";
} }
} }
}; };
@ -935,7 +935,7 @@ PdfStreamConverter.prototype = {
// We can use the resource principal when data is fetched by the chrome, // We can use the resource principal when data is fetched by the chrome,
// e.g. useful for NoScript. Make make sure we reuse the origin attributes // e.g. useful for NoScript. Make make sure we reuse the origin attributes
// from the request channel to keep isolation consistent. // from the request channel to keep isolation consistent.
var ssm = Cc['@mozilla.org/scriptsecuritymanager;1'] var ssm = Cc["@mozilla.org/scriptsecuritymanager;1"]
.getService(Ci.nsIScriptSecurityManager); .getService(Ci.nsIScriptSecurityManager);
var uri = NetUtil.newURI(PDF_VIEWER_WEB_PAGE); var uri = NetUtil.newURI(PDF_VIEWER_WEB_PAGE);
var resourcePrincipal = var resourcePrincipal =
@ -946,7 +946,7 @@ PdfStreamConverter.prototype = {
}, },
// nsIRequestObserver::onStopRequest // nsIRequestObserver::onStopRequest
onStopRequest: function(aRequest, aContext, aStatusCode) { onStopRequest(aRequest, aContext, aStatusCode) {
if (!this.dataListener) { if (!this.dataListener) {
// Do nothing // Do nothing
return; return;

View file

@ -14,25 +14,25 @@
*/ */
/* globals Components, Services, XPCOMUtils */ /* globals Components, Services, XPCOMUtils */
'use strict'; "use strict";
var EXPORTED_SYMBOLS = ['PdfjsChromeUtils']; var EXPORTED_SYMBOLS = ["PdfjsChromeUtils"];
const Cc = Components.classes; const Cc = Components.classes;
const Ci = Components.interfaces; const Ci = Components.interfaces;
const Cr = Components.results; const Cr = Components.results;
const Cu = Components.utils; const Cu = Components.utils;
const PREF_PREFIX = 'pdfjs'; const PREF_PREFIX = "pdfjs";
const PDF_CONTENT_TYPE = 'application/pdf'; const PDF_CONTENT_TYPE = "application/pdf";
Cu.import('resource://gre/modules/XPCOMUtils.jsm'); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import('resource://gre/modules/Services.jsm'); Cu.import("resource://gre/modules/Services.jsm");
var Svc = {}; var Svc = {};
XPCOMUtils.defineLazyServiceGetter(Svc, 'mime', XPCOMUtils.defineLazyServiceGetter(Svc, "mime",
'@mozilla.org/mime;1', "@mozilla.org/mime;1",
'nsIMIMEService'); "nsIMIMEService");
var DEFAULT_PREFERENCES = var DEFAULT_PREFERENCES =
{ {
@ -52,6 +52,7 @@ var DEFAULT_PREFERENCES =
"enhanceTextSelection": false, "enhanceTextSelection": false,
"renderer": "canvas", "renderer": "canvas",
"renderInteractiveForms": false, "renderInteractiveForms": false,
"enablePrintAutoRotate": false,
"disablePageLabels": false "disablePageLabels": false
} }
@ -67,50 +68,50 @@ var PdfjsChromeUtils = {
* Public API * Public API
*/ */
init: function () { init() {
this._browsers = new WeakSet(); this._browsers = new WeakSet();
if (!this._ppmm) { if (!this._ppmm) {
// global parent process message manager (PPMM) // global parent process message manager (PPMM)
this._ppmm = Cc['@mozilla.org/parentprocessmessagemanager;1']. this._ppmm = Cc["@mozilla.org/parentprocessmessagemanager;1"].
getService(Ci.nsIMessageBroadcaster); getService(Ci.nsIMessageBroadcaster);
this._ppmm.addMessageListener('PDFJS:Parent:clearUserPref', this); this._ppmm.addMessageListener("PDFJS:Parent:clearUserPref", this);
this._ppmm.addMessageListener('PDFJS:Parent:setIntPref', this); this._ppmm.addMessageListener("PDFJS:Parent:setIntPref", this);
this._ppmm.addMessageListener('PDFJS:Parent:setBoolPref', this); this._ppmm.addMessageListener("PDFJS:Parent:setBoolPref", this);
this._ppmm.addMessageListener('PDFJS:Parent:setCharPref', this); this._ppmm.addMessageListener("PDFJS:Parent:setCharPref", this);
this._ppmm.addMessageListener('PDFJS:Parent:setStringPref', this); this._ppmm.addMessageListener("PDFJS:Parent:setStringPref", this);
this._ppmm.addMessageListener('PDFJS:Parent:isDefaultHandlerApp', this); this._ppmm.addMessageListener("PDFJS:Parent:isDefaultHandlerApp", this);
// global dom message manager (MMg) // global dom message manager (MMg)
this._mmg = Cc['@mozilla.org/globalmessagemanager;1']. this._mmg = Cc["@mozilla.org/globalmessagemanager;1"].
getService(Ci.nsIMessageListenerManager); getService(Ci.nsIMessageListenerManager);
this._mmg.addMessageListener('PDFJS:Parent:displayWarning', this); this._mmg.addMessageListener("PDFJS:Parent:displayWarning", this);
this._mmg.addMessageListener('PDFJS:Parent:addEventListener', this); this._mmg.addMessageListener("PDFJS:Parent:addEventListener", this);
this._mmg.addMessageListener('PDFJS:Parent:removeEventListener', this); this._mmg.addMessageListener("PDFJS:Parent:removeEventListener", this);
this._mmg.addMessageListener('PDFJS:Parent:updateControlState', this); this._mmg.addMessageListener("PDFJS:Parent:updateControlState", this);
// observer to handle shutdown // observer to handle shutdown
Services.obs.addObserver(this, 'quit-application', false); Services.obs.addObserver(this, "quit-application", false);
} }
}, },
uninit: function () { uninit() {
if (this._ppmm) { if (this._ppmm) {
this._ppmm.removeMessageListener('PDFJS:Parent:clearUserPref', this); this._ppmm.removeMessageListener("PDFJS:Parent:clearUserPref", this);
this._ppmm.removeMessageListener('PDFJS:Parent:setIntPref', this); this._ppmm.removeMessageListener("PDFJS:Parent:setIntPref", this);
this._ppmm.removeMessageListener('PDFJS:Parent:setBoolPref', this); this._ppmm.removeMessageListener("PDFJS:Parent:setBoolPref", this);
this._ppmm.removeMessageListener('PDFJS:Parent:setCharPref', this); this._ppmm.removeMessageListener("PDFJS:Parent:setCharPref", this);
this._ppmm.removeMessageListener('PDFJS:Parent:setStringPref', this); this._ppmm.removeMessageListener("PDFJS:Parent:setStringPref", this);
this._ppmm.removeMessageListener('PDFJS:Parent:isDefaultHandlerApp', this._ppmm.removeMessageListener("PDFJS:Parent:isDefaultHandlerApp",
this); this);
this._mmg.removeMessageListener('PDFJS:Parent:displayWarning', this); this._mmg.removeMessageListener("PDFJS:Parent:displayWarning", this);
this._mmg.removeMessageListener('PDFJS:Parent:addEventListener', this); this._mmg.removeMessageListener("PDFJS:Parent:addEventListener", this);
this._mmg.removeMessageListener('PDFJS:Parent:removeEventListener', this); this._mmg.removeMessageListener("PDFJS:Parent:removeEventListener", this);
this._mmg.removeMessageListener('PDFJS:Parent:updateControlState', this); this._mmg.removeMessageListener("PDFJS:Parent:updateControlState", this);
Services.obs.removeObserver(this, 'quit-application'); Services.obs.removeObserver(this, "quit-application");
this._mmg = null; this._mmg = null;
this._ppmm = null; this._ppmm = null;
@ -123,7 +124,7 @@ var PdfjsChromeUtils = {
* instruct the child to refresh its configuration and (possibly) * instruct the child to refresh its configuration and (possibly)
* the module's registration. * the module's registration.
*/ */
notifyChildOfSettingsChange: function () { notifyChildOfSettingsChange() {
if (Services.appinfo.processType === if (Services.appinfo.processType ===
Services.appinfo.PROCESS_TYPE_DEFAULT && this._ppmm) { Services.appinfo.PROCESS_TYPE_DEFAULT && this._ppmm) {
// XXX kinda bad, we want to get the parent process mm associated // XXX kinda bad, we want to get the parent process mm associated
@ -131,7 +132,7 @@ var PdfjsChromeUtils = {
// manager, which means this is going to fire to every child process // manager, which means this is going to fire to every child process
// we have open. Unfortunately I can't find a way to get at that // we have open. Unfortunately I can't find a way to get at that
// process specific mm from js. // process specific mm from js.
this._ppmm.broadcastAsyncMessage('PDFJS:Child:refreshSettings', {}); this._ppmm.broadcastAsyncMessage("PDFJS:Child:refreshSettings", {});
} }
}, },
@ -139,63 +140,63 @@ var PdfjsChromeUtils = {
* Events * Events
*/ */
observe: function(aSubject, aTopic, aData) { observe(aSubject, aTopic, aData) {
if (aTopic === 'quit-application') { if (aTopic === "quit-application") {
this.uninit(); this.uninit();
} }
}, },
receiveMessage: function (aMsg) { receiveMessage(aMsg) {
switch (aMsg.name) { switch (aMsg.name) {
case 'PDFJS:Parent:clearUserPref': case "PDFJS:Parent:clearUserPref":
this._clearUserPref(aMsg.data.name); this._clearUserPref(aMsg.data.name);
break; break;
case 'PDFJS:Parent:setIntPref': case "PDFJS:Parent:setIntPref":
this._setIntPref(aMsg.data.name, aMsg.data.value); this._setIntPref(aMsg.data.name, aMsg.data.value);
break; break;
case 'PDFJS:Parent:setBoolPref': case "PDFJS:Parent:setBoolPref":
this._setBoolPref(aMsg.data.name, aMsg.data.value); this._setBoolPref(aMsg.data.name, aMsg.data.value);
break; break;
case 'PDFJS:Parent:setCharPref': case "PDFJS:Parent:setCharPref":
this._setCharPref(aMsg.data.name, aMsg.data.value); this._setCharPref(aMsg.data.name, aMsg.data.value);
break; break;
case 'PDFJS:Parent:setStringPref': case "PDFJS:Parent:setStringPref":
this._setStringPref(aMsg.data.name, aMsg.data.value); this._setStringPref(aMsg.data.name, aMsg.data.value);
break; break;
case 'PDFJS:Parent:isDefaultHandlerApp': case "PDFJS:Parent:isDefaultHandlerApp":
return this.isDefaultHandlerApp(); return this.isDefaultHandlerApp();
case 'PDFJS:Parent:displayWarning': case "PDFJS:Parent:displayWarning":
this._displayWarning(aMsg); this._displayWarning(aMsg);
break; break;
case "PDFJS:Parent:updateControlState":
case 'PDFJS:Parent:updateControlState':
return this._updateControlState(aMsg); return this._updateControlState(aMsg);
case 'PDFJS:Parent:addEventListener': case "PDFJS:Parent:addEventListener":
return this._addEventListener(aMsg); return this._addEventListener(aMsg);
case 'PDFJS:Parent:removeEventListener': case "PDFJS:Parent:removeEventListener":
return this._removeEventListener(aMsg); return this._removeEventListener(aMsg);
} }
return undefined;
}, },
/* /*
* Internal * Internal
*/ */
_findbarFromMessage: function(aMsg) { _findbarFromMessage(aMsg) {
let browser = aMsg.target; let browser = aMsg.target;
let tabbrowser = browser.getTabBrowser(); let tabbrowser = browser.getTabBrowser();
let tab = tabbrowser.getTabForBrowser(browser); let tab = tabbrowser.getTabForBrowser(browser);
return tabbrowser.getFindBar(tab); return tabbrowser.getFindBar(tab);
}, },
_updateControlState: function (aMsg) { _updateControlState(aMsg) {
let data = aMsg.data; let data = aMsg.data;
this._findbarFromMessage(aMsg) this._findbarFromMessage(aMsg)
.updateControlState(data.result, data.findPrevious); .updateControlState(data.result, data.findPrevious);
}, },
handleEvent: function(aEvent) { handleEvent(aEvent) {
// To avoid forwarding the message as a CPOW, create a structured cloneable // To avoid forwarding the message as a CPOW, create a structured cloneable
// version of the event for both performance, and ease of usage, reasons. // version of the event for both performance, and ease of usage, reasons.
let type = aEvent.type; let type = aEvent.type;
@ -208,26 +209,25 @@ var PdfjsChromeUtils = {
let browser = aEvent.currentTarget.browser; let browser = aEvent.currentTarget.browser;
if (!this._browsers.has(browser)) { if (!this._browsers.has(browser)) {
throw new Error('FindEventManager was not bound ' + throw new Error("FindEventManager was not bound " +
'for the current browser.'); "for the current browser.");
} }
// Only forward the events if the current browser is a registered browser. // Only forward the events if the current browser is a registered browser.
let mm = browser.messageManager; let mm = browser.messageManager;
mm.sendAsyncMessage('PDFJS:Child:handleEvent', mm.sendAsyncMessage("PDFJS:Child:handleEvent", { type, detail, });
{ type: type, detail: detail });
aEvent.preventDefault(); aEvent.preventDefault();
}, },
_types: ['find', _types: ["find",
'findagain', "findagain",
'findhighlightallchange', "findhighlightallchange",
'findcasesensitivitychange'], "findcasesensitivitychange"],
_addEventListener: function (aMsg) { _addEventListener(aMsg) {
let browser = aMsg.target; let browser = aMsg.target;
if (this._browsers.has(browser)) { if (this._browsers.has(browser)) {
throw new Error('FindEventManager was bound 2nd time ' + throw new Error("FindEventManager was bound 2nd time " +
'without unbinding it first.'); "without unbinding it first.");
} }
// Since this jsm is global, we need to store all the browsers // Since this jsm is global, we need to store all the browsers
@ -242,10 +242,10 @@ var PdfjsChromeUtils = {
} }
}, },
_removeEventListener: function (aMsg) { _removeEventListener(aMsg) {
let browser = aMsg.target; let browser = aMsg.target;
if (!this._browsers.has(browser)) { if (!this._browsers.has(browser)) {
throw new Error('FindEventManager was unbound without binding it first.'); throw new Error("FindEventManager was unbound without binding it first.");
} }
this._browsers.delete(browser); this._browsers.delete(browser);
@ -258,39 +258,39 @@ var PdfjsChromeUtils = {
} }
}, },
_ensurePreferenceAllowed: function (aPrefName) { _ensurePreferenceAllowed(aPrefName) {
let unPrefixedName = aPrefName.split(PREF_PREFIX + '.'); let unPrefixedName = aPrefName.split(PREF_PREFIX + ".");
if (unPrefixedName[0] !== '' || if (unPrefixedName[0] !== "" ||
this._allowedPrefNames.indexOf(unPrefixedName[1]) === -1) { this._allowedPrefNames.indexOf(unPrefixedName[1]) === -1) {
let msg = '"' + aPrefName + '" ' + let msg = "\"" + aPrefName + "\" " +
'can\'t be accessed from content. See PdfjsChromeUtils.'; "can't be accessed from content. See PdfjsChromeUtils.";
throw new Error(msg); throw new Error(msg);
} }
}, },
_clearUserPref: function (aPrefName) { _clearUserPref(aPrefName) {
this._ensurePreferenceAllowed(aPrefName); this._ensurePreferenceAllowed(aPrefName);
Services.prefs.clearUserPref(aPrefName); Services.prefs.clearUserPref(aPrefName);
}, },
_setIntPref: function (aPrefName, aPrefValue) { _setIntPref(aPrefName, aPrefValue) {
this._ensurePreferenceAllowed(aPrefName); this._ensurePreferenceAllowed(aPrefName);
Services.prefs.setIntPref(aPrefName, aPrefValue); Services.prefs.setIntPref(aPrefName, aPrefValue);
}, },
_setBoolPref: function (aPrefName, aPrefValue) { _setBoolPref(aPrefName, aPrefValue) {
this._ensurePreferenceAllowed(aPrefName); this._ensurePreferenceAllowed(aPrefName);
Services.prefs.setBoolPref(aPrefName, aPrefValue); Services.prefs.setBoolPref(aPrefName, aPrefValue);
}, },
_setCharPref: function (aPrefName, aPrefValue) { _setCharPref(aPrefName, aPrefValue) {
this._ensurePreferenceAllowed(aPrefName); this._ensurePreferenceAllowed(aPrefName);
Services.prefs.setCharPref(aPrefName, aPrefValue); Services.prefs.setCharPref(aPrefName, aPrefValue);
}, },
_setStringPref: function (aPrefName, aPrefValue) { _setStringPref(aPrefName, aPrefValue) {
this._ensurePreferenceAllowed(aPrefName); this._ensurePreferenceAllowed(aPrefName);
let str = Cc['@mozilla.org/supports-string;1'] let str = Cc["@mozilla.org/supports-string;1"]
.createInstance(Ci.nsISupportsString); .createInstance(Ci.nsISupportsString);
str.data = aPrefValue; str.data = aPrefValue;
Services.prefs.setComplexValue(aPrefName, Ci.nsISupportsString, str); Services.prefs.setComplexValue(aPrefName, Ci.nsISupportsString, str);
@ -301,8 +301,8 @@ var PdfjsChromeUtils = {
* we bounce this pdfjs enabled configuration check over to the * we bounce this pdfjs enabled configuration check over to the
* parent. * parent.
*/ */
isDefaultHandlerApp: function () { isDefaultHandlerApp() {
var handlerInfo = Svc.mime.getFromTypeAndExtension(PDF_CONTENT_TYPE, 'pdf'); var handlerInfo = Svc.mime.getFromTypeAndExtension(PDF_CONTENT_TYPE, "pdf");
return (!handlerInfo.alwaysAskBeforeHandling && return (!handlerInfo.alwaysAskBeforeHandling &&
handlerInfo.preferredAction === Ci.nsIHandlerInfo.handleInternally); handlerInfo.preferredAction === Ci.nsIHandlerInfo.handleInternally);
}, },
@ -311,7 +311,7 @@ var PdfjsChromeUtils = {
* Display a notification warning when the renderer isn't sure * Display a notification warning when the renderer isn't sure
* a pdf displayed correctly. * a pdf displayed correctly.
*/ */
_displayWarning: function (aMsg) { _displayWarning(aMsg) {
let data = aMsg.data; let data = aMsg.data;
let browser = aMsg.target; let browser = aMsg.target;
@ -324,24 +324,23 @@ var PdfjsChromeUtils = {
let messageSent = false; let messageSent = false;
function sendMessage(download) { function sendMessage(download) {
let mm = browser.messageManager; let mm = browser.messageManager;
mm.sendAsyncMessage('PDFJS:Child:fallbackDownload', mm.sendAsyncMessage("PDFJS:Child:fallbackDownload", { download, });
{ download: download });
} }
let buttons = [{ let buttons = [{
label: data.label, label: data.label,
accessKey: data.accessKey, accessKey: data.accessKey,
callback: function() { callback() {
messageSent = true; messageSent = true;
sendMessage(true); sendMessage(true);
} }
}]; }];
notificationBox.appendNotification(data.message, 'pdfjs-fallback', null, notificationBox.appendNotification(data.message, "pdfjs-fallback", null,
notificationBox.PRIORITY_INFO_LOW, notificationBox.PRIORITY_INFO_LOW,
buttons, buttons,
function eventsCallback(eventType) { function eventsCallback(eventType) {
// Currently there is only one event "removed" but if there are any other // Currently there is only one event "removed" but if there are any other
// added in the future we still only care about removed at the moment. // added in the future we still only care about removed at the moment.
if (eventType !== 'removed') { if (eventType !== "removed") {
return; return;
} }
// Don't send a response again if we already responded when the button was // Don't send a response again if we already responded when the button was

View file

@ -14,17 +14,17 @@
*/ */
/* globals Components, Services, XPCOMUtils */ /* globals Components, Services, XPCOMUtils */
'use strict'; "use strict";
var EXPORTED_SYMBOLS = ['PdfjsContentUtils']; var EXPORTED_SYMBOLS = ["PdfjsContentUtils"];
const Cc = Components.classes; const Cc = Components.classes;
const Ci = Components.interfaces; const Ci = Components.interfaces;
const Cr = Components.results; const Cr = Components.results;
const Cu = Components.utils; const Cu = Components.utils;
Cu.import('resource://gre/modules/XPCOMUtils.jsm'); Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import('resource://gre/modules/Services.jsm'); Cu.import("resource://gre/modules/Services.jsm");
var PdfjsContentUtils = { var PdfjsContentUtils = {
_mm: null, _mm: null,
@ -38,21 +38,21 @@ var PdfjsContentUtils = {
Services.appinfo.PROCESS_TYPE_CONTENT); Services.appinfo.PROCESS_TYPE_CONTENT);
}, },
init: function () { init() {
// child *process* mm, or when loaded into the parent for in-content // child *process* mm, or when loaded into the parent for in-content
// support the psuedo child process mm 'child PPMM'. // support the psuedo child process mm 'child PPMM'.
if (!this._mm) { if (!this._mm) {
this._mm = Cc['@mozilla.org/childprocessmessagemanager;1']. this._mm = Cc["@mozilla.org/childprocessmessagemanager;1"].
getService(Ci.nsISyncMessageSender); getService(Ci.nsISyncMessageSender);
this._mm.addMessageListener('PDFJS:Child:refreshSettings', this); this._mm.addMessageListener("PDFJS:Child:refreshSettings", this);
Services.obs.addObserver(this, 'quit-application', false); Services.obs.addObserver(this, "quit-application", false);
} }
}, },
uninit: function () { uninit() {
if (this._mm) { if (this._mm) {
this._mm.removeMessageListener('PDFJS:Child:refreshSettings', this); this._mm.removeMessageListener("PDFJS:Child:refreshSettings", this);
Services.obs.removeObserver(this, 'quit-application'); Services.obs.removeObserver(this, "quit-application");
} }
this._mm = null; this._mm = null;
}, },
@ -63,35 +63,35 @@ var PdfjsContentUtils = {
* approved pdfjs prefs in chrome utils. * approved pdfjs prefs in chrome utils.
*/ */
clearUserPref: function (aPrefName) { clearUserPref(aPrefName) {
this._mm.sendSyncMessage('PDFJS:Parent:clearUserPref', { this._mm.sendSyncMessage("PDFJS:Parent:clearUserPref", {
name: aPrefName name: aPrefName
}); });
}, },
setIntPref: function (aPrefName, aPrefValue) { setIntPref(aPrefName, aPrefValue) {
this._mm.sendSyncMessage('PDFJS:Parent:setIntPref', { this._mm.sendSyncMessage("PDFJS:Parent:setIntPref", {
name: aPrefName, name: aPrefName,
value: aPrefValue value: aPrefValue
}); });
}, },
setBoolPref: function (aPrefName, aPrefValue) { setBoolPref(aPrefName, aPrefValue) {
this._mm.sendSyncMessage('PDFJS:Parent:setBoolPref', { this._mm.sendSyncMessage("PDFJS:Parent:setBoolPref", {
name: aPrefName, name: aPrefName,
value: aPrefValue value: aPrefValue
}); });
}, },
setCharPref: function (aPrefName, aPrefValue) { setCharPref(aPrefName, aPrefValue) {
this._mm.sendSyncMessage('PDFJS:Parent:setCharPref', { this._mm.sendSyncMessage("PDFJS:Parent:setCharPref", {
name: aPrefName, name: aPrefName,
value: aPrefValue value: aPrefValue
}); });
}, },
setStringPref: function (aPrefName, aPrefValue) { setStringPref(aPrefName, aPrefValue) {
this._mm.sendSyncMessage('PDFJS:Parent:setStringPref', { this._mm.sendSyncMessage("PDFJS:Parent:setStringPref", {
name: aPrefName, name: aPrefName,
value: aPrefValue value: aPrefValue
}); });
@ -101,24 +101,24 @@ var PdfjsContentUtils = {
* Forwards default app query to the parent where we check various * Forwards default app query to the parent where we check various
* handler app settings only available in the parent process. * handler app settings only available in the parent process.
*/ */
isDefaultHandlerApp: function () { isDefaultHandlerApp() {
return this._mm.sendSyncMessage('PDFJS:Parent:isDefaultHandlerApp')[0]; return this._mm.sendSyncMessage("PDFJS:Parent:isDefaultHandlerApp")[0];
}, },
/* /*
* Request the display of a notification warning in the associated window * Request the display of a notification warning in the associated window
* when the renderer isn't sure a pdf displayed correctly. * when the renderer isn't sure a pdf displayed correctly.
*/ */
displayWarning: function (aWindow, aMessage, aLabel, accessKey) { displayWarning(aWindow, aMessage, aLabel, aAccessKey) {
// the child's dom frame mm associated with the window. // the child's dom frame mm associated with the window.
let winmm = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) let winmm = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell) .getInterface(Ci.nsIDocShell)
.QueryInterface(Ci.nsIInterfaceRequestor) .QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIContentFrameMessageManager); .getInterface(Ci.nsIContentFrameMessageManager);
winmm.sendAsyncMessage('PDFJS:Parent:displayWarning', { winmm.sendAsyncMessage("PDFJS:Parent:displayWarning", {
message: aMessage, message: aMessage,
label: aLabel, label: aLabel,
accessKey: accessKey accessKey: aAccessKey,
}); });
}, },
@ -126,19 +126,19 @@ var PdfjsContentUtils = {
* Events * Events
*/ */
observe: function(aSubject, aTopic, aData) { observe(aSubject, aTopic, aData) {
if (aTopic === 'quit-application') { if (aTopic === "quit-application") {
this.uninit(); this.uninit();
} }
}, },
receiveMessage: function (aMsg) { receiveMessage(aMsg) {
switch (aMsg.name) { switch (aMsg.name) {
case 'PDFJS:Child:refreshSettings': case "PDFJS:Child:refreshSettings":
// Only react to this if we are remote. // Only react to this if we are remote.
if (Services.appinfo.processType === if (Services.appinfo.processType ===
Services.appinfo.PROCESS_TYPE_CONTENT) { Services.appinfo.PROCESS_TYPE_CONTENT) {
let jsm = 'resource://pdf.js/PdfJs.jsm'; let jsm = "resource://pdf.js/PdfJs.jsm";
let pdfjs = Components.utils.import(jsm, {}).PdfJs; let pdfjs = Components.utils.import(jsm, {}).PdfJs;
pdfjs.updateRegistration(); pdfjs.updateRegistration();
} }

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,617 +0,0 @@
/* Copyright 2012 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* 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.
*/
// NOTE: Be careful what goes in this file, as it is also used from the context
// of the addon. So using warn/error in here will break the addon.
'use strict';
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define('pdfjs/core/network', ['exports', 'pdfjs/shared/util',
'pdfjs/core/worker'], factory);
} else if (typeof exports !== 'undefined') {
factory(exports, require('../shared/util.js'), require('./worker.js'));
} else {
factory((root.pdfjsCoreNetwork = {}), root.pdfjsSharedUtil,
root.pdfjsCoreWorker);
}
}(this, function (exports, sharedUtil, coreWorker) {
if (typeof PDFJSDev !== 'undefined' && PDFJSDev.test('FIREFOX || MOZCENTRAL')) {
throw new Error('Module "pdfjs/core/network" shall not ' +
'be used with FIREFOX or MOZCENTRAL build.');
}
var OK_RESPONSE = 200;
var PARTIAL_CONTENT_RESPONSE = 206;
function NetworkManager(url, args) {
this.url = url;
args = args || {};
this.isHttp = /^https?:/i.test(url);
this.httpHeaders = (this.isHttp && args.httpHeaders) || {};
this.withCredentials = args.withCredentials || false;
this.getXhr = args.getXhr ||
function NetworkManager_getXhr() {
return new XMLHttpRequest();
};
this.currXhrId = 0;
this.pendingRequests = Object.create(null);
this.loadedRequests = Object.create(null);
}
function getArrayBuffer(xhr) {
var data = xhr.response;
if (typeof data !== 'string') {
return data;
}
var length = data.length;
var array = new Uint8Array(length);
for (var i = 0; i < length; i++) {
array[i] = data.charCodeAt(i) & 0xFF;
}
return array.buffer;
}
var supportsMozChunked =
typeof PDFJSDev !== 'undefined' && PDFJSDev.test('CHROME') ? false :
(function supportsMozChunkedClosure() {
try {
var x = new XMLHttpRequest();
// Firefox 37- required .open() to be called before setting responseType.
// https://bugzilla.mozilla.org/show_bug.cgi?id=707484
// Even though the URL is not visited, .open() could fail if the URL is
// blocked, e.g. via the connect-src CSP directive or the NoScript addon.
// When this error occurs, this feature detection method will mistakenly
// report that moz-chunked-arraybuffer is not supported in Firefox 37-.
x.open('GET', 'https://example.com');
x.responseType = 'moz-chunked-arraybuffer';
return x.responseType === 'moz-chunked-arraybuffer';
} catch (e) {
return false;
}
})();
NetworkManager.prototype = {
requestRange: function NetworkManager_requestRange(begin, end, listeners) {
var args = {
begin: begin,
end: end
};
for (var prop in listeners) {
args[prop] = listeners[prop];
}
return this.request(args);
},
requestFull: function NetworkManager_requestFull(listeners) {
return this.request(listeners);
},
request: function NetworkManager_request(args) {
var xhr = this.getXhr();
var xhrId = this.currXhrId++;
var pendingRequest = this.pendingRequests[xhrId] = {
xhr: xhr
};
xhr.open('GET', this.url);
xhr.withCredentials = this.withCredentials;
for (var property in this.httpHeaders) {
var value = this.httpHeaders[property];
if (typeof value === 'undefined') {
continue;
}
xhr.setRequestHeader(property, value);
}
if (this.isHttp && 'begin' in args && 'end' in args) {
var rangeStr = args.begin + '-' + (args.end - 1);
xhr.setRequestHeader('Range', 'bytes=' + rangeStr);
pendingRequest.expectedStatus = 206;
} else {
pendingRequest.expectedStatus = 200;
}
var useMozChunkedLoading = supportsMozChunked && !!args.onProgressiveData;
if (useMozChunkedLoading) {
xhr.responseType = 'moz-chunked-arraybuffer';
pendingRequest.onProgressiveData = args.onProgressiveData;
pendingRequest.mozChunked = true;
} else {
xhr.responseType = 'arraybuffer';
}
if (args.onError) {
xhr.onerror = function(evt) {
args.onError(xhr.status);
};
}
xhr.onreadystatechange = this.onStateChange.bind(this, xhrId);
xhr.onprogress = this.onProgress.bind(this, xhrId);
pendingRequest.onHeadersReceived = args.onHeadersReceived;
pendingRequest.onDone = args.onDone;
pendingRequest.onError = args.onError;
pendingRequest.onProgress = args.onProgress;
xhr.send(null);
return xhrId;
},
onProgress: function NetworkManager_onProgress(xhrId, evt) {
var pendingRequest = this.pendingRequests[xhrId];
if (!pendingRequest) {
// Maybe abortRequest was called...
return;
}
if (pendingRequest.mozChunked) {
var chunk = getArrayBuffer(pendingRequest.xhr);
pendingRequest.onProgressiveData(chunk);
}
var onProgress = pendingRequest.onProgress;
if (onProgress) {
onProgress(evt);
}
},
onStateChange: function NetworkManager_onStateChange(xhrId, evt) {
var pendingRequest = this.pendingRequests[xhrId];
if (!pendingRequest) {
// Maybe abortRequest was called...
return;
}
var xhr = pendingRequest.xhr;
if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) {
pendingRequest.onHeadersReceived();
delete pendingRequest.onHeadersReceived;
}
if (xhr.readyState !== 4) {
return;
}
if (!(xhrId in this.pendingRequests)) {
// The XHR request might have been aborted in onHeadersReceived()
// callback, in which case we should abort request
return;
}
delete this.pendingRequests[xhrId];
// success status == 0 can be on ftp, file and other protocols
if (xhr.status === 0 && this.isHttp) {
if (pendingRequest.onError) {
pendingRequest.onError(xhr.status);
}
return;
}
var xhrStatus = xhr.status || OK_RESPONSE;
// From http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.2:
// "A server MAY ignore the Range header". This means it's possible to
// get a 200 rather than a 206 response from a range request.
var ok_response_on_range_request =
xhrStatus === OK_RESPONSE &&
pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE;
if (!ok_response_on_range_request &&
xhrStatus !== pendingRequest.expectedStatus) {
if (pendingRequest.onError) {
pendingRequest.onError(xhr.status);
}
return;
}
this.loadedRequests[xhrId] = true;
var chunk = getArrayBuffer(xhr);
if (xhrStatus === PARTIAL_CONTENT_RESPONSE) {
var rangeHeader = xhr.getResponseHeader('Content-Range');
var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
var begin = parseInt(matches[1], 10);
pendingRequest.onDone({
begin: begin,
chunk: chunk
});
} else if (pendingRequest.onProgressiveData) {
pendingRequest.onDone(null);
} else if (chunk) {
pendingRequest.onDone({
begin: 0,
chunk: chunk
});
} else if (pendingRequest.onError) {
pendingRequest.onError(xhr.status);
}
},
hasPendingRequests: function NetworkManager_hasPendingRequests() {
for (var xhrId in this.pendingRequests) {
return true;
}
return false;
},
getRequestXhr: function NetworkManager_getXhr(xhrId) {
return this.pendingRequests[xhrId].xhr;
},
isStreamingRequest: function NetworkManager_isStreamingRequest(xhrId) {
return !!(this.pendingRequests[xhrId].onProgressiveData);
},
isPendingRequest: function NetworkManager_isPendingRequest(xhrId) {
return xhrId in this.pendingRequests;
},
isLoadedRequest: function NetworkManager_isLoadedRequest(xhrId) {
return xhrId in this.loadedRequests;
},
abortAllRequests: function NetworkManager_abortAllRequests() {
for (var xhrId in this.pendingRequests) {
this.abortRequest(xhrId | 0);
}
},
abortRequest: function NetworkManager_abortRequest(xhrId) {
var xhr = this.pendingRequests[xhrId].xhr;
delete this.pendingRequests[xhrId];
xhr.abort();
}
};
var assert = sharedUtil.assert;
var createPromiseCapability = sharedUtil.createPromiseCapability;
var isInt = sharedUtil.isInt;
var MissingPDFException = sharedUtil.MissingPDFException;
var UnexpectedResponseException = sharedUtil.UnexpectedResponseException;
/** @implements {IPDFStream} */
function PDFNetworkStream(options) {
this._options = options;
var source = options.source;
this._manager = new NetworkManager(source.url, {
httpHeaders: source.httpHeaders,
withCredentials: source.withCredentials
});
this._rangeChunkSize = source.rangeChunkSize;
this._fullRequestReader = null;
this._rangeRequestReaders = [];
}
PDFNetworkStream.prototype = {
_onRangeRequestReaderClosed:
function PDFNetworkStream_onRangeRequestReaderClosed(reader) {
var i = this._rangeRequestReaders.indexOf(reader);
if (i >= 0) {
this._rangeRequestReaders.splice(i, 1);
}
},
getFullReader: function PDFNetworkStream_getFullReader() {
assert(!this._fullRequestReader);
this._fullRequestReader =
new PDFNetworkStreamFullRequestReader(this._manager, this._options);
return this._fullRequestReader;
},
getRangeReader: function PDFNetworkStream_getRangeReader(begin, end) {
var reader = new PDFNetworkStreamRangeRequestReader(this._manager,
begin, end);
reader.onClosed = this._onRangeRequestReaderClosed.bind(this);
this._rangeRequestReaders.push(reader);
return reader;
},
cancelAllRequests: function PDFNetworkStream_cancelAllRequests(reason) {
if (this._fullRequestReader) {
this._fullRequestReader.cancel(reason);
}
var readers = this._rangeRequestReaders.slice(0);
readers.forEach(function (reader) {
reader.cancel(reason);
});
}
};
/** @implements {IPDFStreamReader} */
function PDFNetworkStreamFullRequestReader(manager, options) {
this._manager = manager;
var source = options.source;
var args = {
onHeadersReceived: this._onHeadersReceived.bind(this),
onProgressiveData: source.disableStream ? null :
this._onProgressiveData.bind(this),
onDone: this._onDone.bind(this),
onError: this._onError.bind(this),
onProgress: this._onProgress.bind(this)
};
this._url = source.url;
this._fullRequestId = manager.requestFull(args);
this._headersReceivedCapability = createPromiseCapability();
this._disableRange = options.disableRange || false;
this._contentLength = source.length; // optional
this._rangeChunkSize = source.rangeChunkSize;
if (!this._rangeChunkSize && !this._disableRange) {
this._disableRange = true;
}
this._isStreamingSupported = false;
this._isRangeSupported = false;
this._cachedChunks = [];
this._requests = [];
this._done = false;
this._storedError = undefined;
this.onProgress = null;
}
PDFNetworkStreamFullRequestReader.prototype = {
_validateRangeRequestCapabilities: function
PDFNetworkStreamFullRequestReader_validateRangeRequestCapabilities() {
if (this._disableRange) {
return false;
}
var networkManager = this._manager;
if (!networkManager.isHttp) {
return false;
}
var fullRequestXhrId = this._fullRequestId;
var fullRequestXhr = networkManager.getRequestXhr(fullRequestXhrId);
if (fullRequestXhr.getResponseHeader('Accept-Ranges') !== 'bytes') {
return false;
}
var contentEncoding =
fullRequestXhr.getResponseHeader('Content-Encoding') || 'identity';
if (contentEncoding !== 'identity') {
return false;
}
var length = fullRequestXhr.getResponseHeader('Content-Length');
length = parseInt(length, 10);
if (!isInt(length)) {
return false;
}
this._contentLength = length; // setting right content length
if (length <= 2 * this._rangeChunkSize) {
// The file size is smaller than the size of two chunks, so it does
// not make any sense to abort the request and retry with a range
// request.
return false;
}
return true;
},
_onHeadersReceived:
function PDFNetworkStreamFullRequestReader_onHeadersReceived() {
if (this._validateRangeRequestCapabilities()) {
this._isRangeSupported = true;
}
var networkManager = this._manager;
var fullRequestXhrId = this._fullRequestId;
if (networkManager.isStreamingRequest(fullRequestXhrId)) {
// We can continue fetching when progressive loading is enabled,
// and we don't need the autoFetch feature.
this._isStreamingSupported = true;
} else if (this._isRangeSupported) {
// NOTE: by cancelling the full request, and then issuing range
// requests, there will be an issue for sites where you can only
// request the pdf once. However, if this is the case, then the
// server should not be returning that it can support range
// requests.
networkManager.abortRequest(fullRequestXhrId);
}
this._headersReceivedCapability.resolve();
},
_onProgressiveData:
function PDFNetworkStreamFullRequestReader_onProgressiveData(chunk) {
if (this._requests.length > 0) {
var requestCapability = this._requests.shift();
requestCapability.resolve({value: chunk, done: false});
} else {
this._cachedChunks.push(chunk);
}
},
_onDone: function PDFNetworkStreamFullRequestReader_onDone(args) {
if (args) {
this._onProgressiveData(args.chunk);
}
this._done = true;
if (this._cachedChunks.length > 0) {
return;
}
this._requests.forEach(function (requestCapability) {
requestCapability.resolve({value: undefined, done: true});
});
this._requests = [];
},
_onError: function PDFNetworkStreamFullRequestReader_onError(status) {
var url = this._url;
var exception;
if (status === 404 || status === 0 && /^file:/.test(url)) {
exception = new MissingPDFException('Missing PDF "' + url + '".');
} else {
exception = new UnexpectedResponseException(
'Unexpected server response (' + status +
') while retrieving PDF "' + url + '".', status);
}
this._storedError = exception;
this._headersReceivedCapability.reject(exception);
this._requests.forEach(function (requestCapability) {
requestCapability.reject(exception);
});
this._requests = [];
this._cachedChunks = [];
},
_onProgress: function PDFNetworkStreamFullRequestReader_onProgress(data) {
if (this.onProgress) {
this.onProgress({
loaded: data.loaded,
total: data.lengthComputable ? data.total : this._contentLength
});
}
},
get isRangeSupported() {
return this._isRangeSupported;
},
get isStreamingSupported() {
return this._isStreamingSupported;
},
get contentLength() {
return this._contentLength;
},
get headersReady() {
return this._headersReceivedCapability.promise;
},
read: function PDFNetworkStreamFullRequestReader_read() {
if (this._storedError) {
return Promise.reject(this._storedError);
}
if (this._cachedChunks.length > 0) {
var chunk = this._cachedChunks.shift();
return Promise.resolve(chunk);
}
if (this._done) {
return Promise.resolve({value: undefined, done: true});
}
var requestCapability = createPromiseCapability();
this._requests.push(requestCapability);
return requestCapability.promise;
},
cancel: function PDFNetworkStreamFullRequestReader_cancel(reason) {
this._done = true;
this._headersReceivedCapability.reject(reason);
this._requests.forEach(function (requestCapability) {
requestCapability.resolve({value: undefined, done: true});
});
this._requests = [];
if (this._manager.isPendingRequest(this._fullRequestId)) {
this._manager.abortRequest(this._fullRequestId);
}
this._fullRequestReader = null;
}
};
/** @implements {IPDFStreamRangeReader} */
function PDFNetworkStreamRangeRequestReader(manager, begin, end) {
this._manager = manager;
var args = {
onDone: this._onDone.bind(this),
onProgress: this._onProgress.bind(this)
};
this._requestId = manager.requestRange(begin, end, args);
this._requests = [];
this._queuedChunk = null;
this._done = false;
this.onProgress = null;
this.onClosed = null;
}
PDFNetworkStreamRangeRequestReader.prototype = {
_close: function PDFNetworkStreamRangeRequestReader_close() {
if (this.onClosed) {
this.onClosed(this);
}
},
_onDone: function PDFNetworkStreamRangeRequestReader_onDone(data) {
var chunk = data.chunk;
if (this._requests.length > 0) {
var requestCapability = this._requests.shift();
requestCapability.resolve({value: chunk, done: false});
} else {
this._queuedChunk = chunk;
}
this._done = true;
this._requests.forEach(function (requestCapability) {
requestCapability.resolve({value: undefined, done: true});
});
this._requests = [];
this._close();
},
_onProgress: function PDFNetworkStreamRangeRequestReader_onProgress(evt) {
if (!this.isStreamingSupported && this.onProgress) {
this.onProgress({
loaded: evt.loaded
});
}
},
get isStreamingSupported() {
return false; // TODO allow progressive range bytes loading
},
read: function PDFNetworkStreamRangeRequestReader_read() {
if (this._queuedChunk !== null) {
var chunk = this._queuedChunk;
this._queuedChunk = null;
return Promise.resolve({value: chunk, done: false});
}
if (this._done) {
return Promise.resolve({value: undefined, done: true});
}
var requestCapability = createPromiseCapability();
this._requests.push(requestCapability);
return requestCapability.promise;
},
cancel: function PDFNetworkStreamRangeRequestReader_cancel(reason) {
this._done = true;
this._requests.forEach(function (requestCapability) {
requestCapability.resolve({value: undefined, done: true});
});
this._requests = [];
if (this._manager.isPendingRequest(this._requestId)) {
this._manager.abortRequest(this._requestId);
}
this._close();
}
};
coreWorker.setPDFNetworkStreamClass(PDFNetworkStream);
exports.PDFNetworkStream = PDFNetworkStream;
exports.NetworkManager = NetworkManager;
}));

View file

@ -14,16 +14,16 @@
*/ */
/* globals Components, PdfjsContentUtils, PdfJs, Services */ /* globals Components, PdfjsContentUtils, PdfJs, Services */
'use strict'; "use strict";
/* /*
* pdfjschildbootstrap.js loads into the content process to take care of * pdfjschildbootstrap.js loads into the content process to take care of
* initializing our built-in version of pdfjs when running remote. * initializing our built-in version of pdfjs when running remote.
*/ */
Components.utils.import('resource://gre/modules/Services.jsm'); Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import('resource://pdf.js/PdfJs.jsm'); Components.utils.import("resource://pdf.js/PdfJs.jsm");
Components.utils.import('resource://pdf.js/PdfjsContentUtils.jsm'); Components.utils.import("resource://pdf.js/PdfjsContentUtils.jsm");
// init content utils shim pdfjs will use to access privileged apis. // init content utils shim pdfjs will use to access privileged apis.
PdfjsContentUtils.init(); PdfjsContentUtils.init();
@ -32,4 +32,3 @@ if (Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_CONTENT) {
// register various pdfjs factories that hook us into content loading. // register various pdfjs factories that hook us into content loading.
PdfJs.updateRegistration(); PdfJs.updateRegistration();
} }

View file

@ -387,7 +387,9 @@ var Stepper = (function StepperClosure() {
this.table.appendChild(chunk); this.table.appendChild(chunk);
}, },
getNextBreakPoint: function getNextBreakPoint() { getNextBreakPoint: function getNextBreakPoint() {
this.breakPoints.sort(function(a, b) { return a - b; }); this.breakPoints.sort(function(a, b) {
return a - b;
});
for (var i = 0; i < this.breakPoints.length; i++) { for (var i = 0; i < this.breakPoints.length; i++) {
if (this.breakPoints[i] > this.currentIdx) { if (this.breakPoints[i] > this.currentIdx) {
return this.breakPoints[i]; return this.breakPoints[i];
@ -484,7 +486,9 @@ var Stats = (function Stats() {
wrapper.appendChild(title); wrapper.appendChild(title);
wrapper.appendChild(statsDiv); wrapper.appendChild(statsDiv);
stats.push({ pageNumber: pageNumber, div: wrapper }); stats.push({ pageNumber: pageNumber, div: wrapper });
stats.sort(function(a, b) { return a.pageNumber - b.pageNumber; }); stats.sort(function(a, b) {
return a.pageNumber - b.pageNumber;
});
clear(this.panel); clear(this.panel);
for (var i = 0, ii = stats.length; i < ii; ++i) { for (var i = 0, ii = stats.length; i < ii; ++i) {
this.panel.appendChild(stats[i].div); this.panel.appendChild(stats[i].div);

View file

@ -1,17 +1,17 @@
'use strict'; "use strict";
// Small subset of the webL10n API by Fabien Cazenave for pdf.js extension. // Small subset of the webL10n API by Fabien Cazenave for pdf.js extension.
(function(window) { (function(window) {
var gLanguage = ''; var gLanguage = "";
var gExternalLocalizerServices = null; var gExternalLocalizerServices = null;
var gReadyState = 'loading'; var gReadyState = "loading";
// fetch an l10n objects // fetch an l10n objects
function getL10nData(key) { function getL10nData(key) {
var response = gExternalLocalizerServices.getStrings(key); var response = gExternalLocalizerServices.getStrings(key);
var data = JSON.parse(response); var data = JSON.parse(response);
if (!data) { if (!data) {
console.warn('[l10n] #' + key + ' missing for [' + gLanguage + ']'); console.warn("[l10n] #" + key + " missing for [" + gLanguage + "]");
} }
return data; return data;
} }
@ -22,25 +22,25 @@
return text; return text;
} }
return text.replace(/\{\{\s*(\w+)\s*\}\}/g, function(all, name) { return text.replace(/\{\{\s*(\w+)\s*\}\}/g, function(all, name) {
return (name in args ? args[name] : '{{' + name + '}}'); return (name in args ? args[name] : "{{" + name + "}}");
}); });
} }
// translate a string // translate a string
function translateString(key, args, fallback) { function translateString(key, args, fallback) {
var i = key.lastIndexOf('.'); var i = key.lastIndexOf(".");
var name, property; var name, property;
if (i >= 0) { if (i >= 0) {
name = key.substring(0, i); name = key.substring(0, i);
property = key.substring(i + 1); property = key.substring(i + 1);
} else { } else {
name = key; name = key;
property = 'textContent'; property = "textContent";
} }
var data = getL10nData(name); var data = getL10nData(name);
var value = (data && data[property]) || fallback; var value = (data && data[property]) || fallback;
if (!value) { if (!value) {
return '{{' + key + '}}'; return "{{" + key + "}}";
} }
return substArguments(value, args); return substArguments(value, args);
} }
@ -65,7 +65,7 @@
try { try {
args = JSON.parse(element.dataset.l10nArgs); args = JSON.parse(element.dataset.l10nArgs);
} catch (e) { } catch (e) {
console.warn('[l10n] could not parse arguments for #' + key + ''); console.warn("[l10n] could not parse arguments for #" + key + "");
} }
} }
@ -79,10 +79,10 @@
// translate an HTML subtree // translate an HTML subtree
function translateFragment(element) { function translateFragment(element) {
element = element || document.querySelector('html'); element = element || document.querySelector("html");
// check all translatable children (= w/ a `data-l10n-id' attribute) // check all translatable children (= w/ a `data-l10n-id' attribute)
var children = element.querySelectorAll('*[data-l10n-id]'); var children = element.querySelectorAll("*[data-l10n-id]");
var elementCount = children.length; var elementCount = children.length;
for (var i = 0; i < elementCount; i++) { for (var i = 0; i < elementCount; i++) {
translateElement(children[i]); translateElement(children[i]);
@ -99,16 +99,16 @@
translateFragment(); translateFragment();
gReadyState = 'complete'; gReadyState = "complete";
// fire a 'localized' DOM event // fire a 'localized' DOM event
var evtObject = document.createEvent('Event'); var evtObject = document.createEvent("Event");
evtObject.initEvent('localized', false, false); evtObject.initEvent("localized", false, false);
evtObject.language = gLanguage; evtObject.language = gLanguage;
window.dispatchEvent(evtObject); window.dispatchEvent(evtObject);
} }
window.addEventListener('DOMContentLoaded', function() { window.addEventListener("DOMContentLoaded", function() {
if (gExternalLocalizerServices) { if (gExternalLocalizerServices) {
translateDocument(); translateDocument();
} }
@ -121,30 +121,32 @@
get: translateString, get: translateString,
// get the document language // get the document language
getLanguage: function() { getLanguage() {
return gLanguage; return gLanguage;
}, },
// get the direction (ltr|rtl) of the current language // get the direction (ltr|rtl) of the current language
getDirection: function() { getDirection() {
// http://www.w3.org/International/questions/qa-scripts // http://www.w3.org/International/questions/qa-scripts
// Arabic, Hebrew, Farsi, Pashto, Urdu // Arabic, Hebrew, Farsi, Pashto, Urdu
var rtlList = ['ar', 'he', 'fa', 'ps', 'ur']; var rtlList = ["ar", "he", "fa", "ps", "ur"];
// use the short language code for "full" codes like 'ar-sa' (issue 5440) // use the short language code for "full" codes like 'ar-sa' (issue 5440)
var shortCode = gLanguage.split('-')[0]; var shortCode = gLanguage.split("-")[0];
return (rtlList.indexOf(shortCode) >= 0) ? 'rtl' : 'ltr'; return (rtlList.indexOf(shortCode) >= 0) ? "rtl" : "ltr";
}, },
getReadyState: function() { return gReadyState; }, getReadyState() {
return gReadyState;
},
setExternalLocalizerServices: function (externalLocalizerServices) { setExternalLocalizerServices(externalLocalizerServices) {
gExternalLocalizerServices = externalLocalizerServices; gExternalLocalizerServices = externalLocalizerServices;
// ... in case if we missed DOMContentLoaded above. // ... in case if we missed DOMContentLoaded above.
if (window.document.readyState === 'interactive' || if (window.document.readyState === "interactive" ||
window.document.readyState === 'complete') { window.document.readyState === "complete") {
translateDocument(); translateDocument();
} }
}, },

View file

@ -1084,6 +1084,24 @@ html[dir="rtl"] #viewOutline.toolbarButton::before {
content: url(images/toolbarButton-search.png); content: url(images/toolbarButton-search.png);
} }
.toolbarButton.pdfSidebarNotification::after {
position: absolute;
display: inline-block;
top: 1px;
/* Create a filled circle, with a diameter of 9 pixels, using only CSS: */
content: '';
background-color: #70DB55;
height: 9px;
width: 9px;
border-radius: 50%;
}
html[dir='ltr'] .toolbarButton.pdfSidebarNotification::after {
left: 17px;
}
html[dir='rtl'] .toolbarButton.pdfSidebarNotification::after {
right: 17px;
}
.secondaryToolbarButton { .secondaryToolbarButton {
position: relative; position: relative;
margin: 0 0 4px 0; margin: 0 0 4px 0;

File diff suppressed because it is too large Load diff