[Firefox addon] Convert the code to be ES6 friendly, in order to better agree with mozilla-central coding conventions (issue 7957)

*Please note: ignoring whitespace changes is most likely necessary for the diff to be readable.*

This patch addresses all the current, in `mozilla-central`, linting failures in the addon. It should thus be possible to change the `.eslintignore` entry for PDF.js in `mozilla-central` from `browser/extensions/pdfjs/**` to `browser/extensions/pdfjs/build/**` and `browser/extensions/pdfjs/web/**` instead.
Note that we cannot, for backwards compatibility reason of the general PDF.js library, at this time make similar changes for files residing in the `build` and `web` directories in `mozilla-central`.

The main changes in this patch are that we now use [classes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes) instead of our previous "class-like" functions, and also use the more compact [object shorthand notation](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Object_initializer#New_notations_in_ECMAScript_2015).
A couple of functions were also converted to [arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions), to reduced usages of `bind(this)` and `var self = this`.

One caveat with ES6 classes is that it's not (yet) possible to define private constants/helper functions within them, which is why the `NetworkManagerClosure` was kept to not change the visibility of those constant/functions.

Besides testing in Firefox Nightly 53, this patch has also been tested in Firefox ESR 45 and SeaMonkey 2.46.
However, I'd gladly welcome help with testing the patch more, to ensure that nothing has gone wrong during the refactoring.

Fixes the first bullet point of issue 7957.
This commit is contained in:
Jonas Jenwald 2017-01-22 18:07:53 +01:00
parent 1948a53ebb
commit 3ec99f0e12
10 changed files with 340 additions and 312 deletions

View File

@ -119,4 +119,6 @@
}
}],
},
// ECMAScript 6
}

View File

@ -6,4 +6,28 @@
"parserOptions": {
"ecmaVersion": 6
},
"rules": {
// Variables
"no-shadow": "error",
"no-unused-vars": ["error", {
"vars": "local",
"varsIgnorePattern": "^Cc|Ci|Cu|Cr|EXPORTED_SYMBOLS",
"args": "none",
}],
// Stylistic Issues
"space-before-function-paren": ["error", "never"],
// ECMAScript 6
"arrow-body-style": ["error", "as-needed"],
"arrow-parens": ["error", "always"],
"arrow-spacing": ["error", { "before": true, "after": true, }],
"constructor-super": "error",
"no-confusing-arrow": "error",
"no-const-assign": "error",
"no-dupe-class-members": "error",
"no-useless-constructor": "error",
"object-shorthand": ["error", "always", { "avoidQuotes": true }],
},
}

View File

@ -32,7 +32,7 @@
var isRemote = Services.appinfo.processType ===
Services.appinfo.PROCESS_TYPE_CONTENT;
// Factory that registers/unregisters a constructor as a component.
// Factory that registers/unregisters a constructor as a component.
function Factory() {
}
@ -93,7 +93,7 @@
if (isRemote) {
startup();
addMessageListener('PDFJS:Child:shutdown', function (e) {
addMessageListener('PDFJS:Child:shutdown', function() {
shutdown();
});
}

View File

@ -27,24 +27,8 @@ function log(aMsg) {
var NetworkManager = (function NetworkManagerClosure() {
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);
}
const OK_RESPONSE = 200;
const PARTIAL_CONTENT_RESPONSE = 206;
function getArrayBuffer(xhr) {
var data = xhr.response;
@ -59,27 +43,43 @@ var NetworkManager = (function NetworkManagerClosure() {
return array.buffer;
}
NetworkManager.prototype = {
requestRange: function NetworkManager_requestRange(begin, end, listeners) {
class NetworkManagerClass {
constructor(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);
}
requestRange(begin, end, listeners) {
var args = {
begin: begin,
end: end
begin,
end,
};
for (var prop in listeners) {
args[prop] = listeners[prop];
}
return this.request(args);
},
}
requestFull: function NetworkManager_requestFull(listeners) {
requestFull(listeners) {
return this.request(listeners);
},
}
request: function NetworkManager_request(args) {
request(args) {
var xhr = this.getXhr();
var xhrId = this.currXhrId++;
var pendingRequest = this.pendingRequests[xhrId] = {
xhr: xhr
xhr,
};
xhr.open('GET', this.url);
@ -124,9 +124,9 @@ var NetworkManager = (function NetworkManagerClosure() {
xhr.send(null);
return xhrId;
},
}
onProgress: function NetworkManager_onProgress(xhrId, evt) {
onProgress(xhrId, evt) {
var pendingRequest = this.pendingRequests[xhrId];
if (!pendingRequest) {
// Maybe abortRequest was called...
@ -142,9 +142,9 @@ var NetworkManager = (function NetworkManagerClosure() {
if (onProgress) {
onProgress(evt);
}
},
}
onStateChange: function NetworkManager_onStateChange(xhrId, evt) {
onStateChange(xhrId, evt) {
var pendingRequest = this.pendingRequests[xhrId];
if (!pendingRequest) {
// Maybe abortRequest was called...
@ -201,56 +201,56 @@ var NetworkManager = (function NetworkManagerClosure() {
var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
var begin = parseInt(matches[1], 10);
pendingRequest.onDone({
begin: begin,
chunk: chunk
begin,
chunk,
});
} else if (pendingRequest.onProgressiveData) {
pendingRequest.onDone(null);
} else if (chunk) {
pendingRequest.onDone({
begin: 0,
chunk: chunk
chunk,
});
} else if (pendingRequest.onError) {
pendingRequest.onError(xhr.status);
}
},
}
hasPendingRequests: function NetworkManager_hasPendingRequests() {
hasPendingRequests() {
for (var xhrId in this.pendingRequests) {
return true;
}
return false;
},
}
getRequestXhr: function NetworkManager_getXhr(xhrId) {
getRequestXhr(xhrId) {
return this.pendingRequests[xhrId].xhr;
},
}
isStreamingRequest: function NetworkManager_isStreamingRequest(xhrId) {
isStreamingRequest(xhrId) {
return !!(this.pendingRequests[xhrId].onProgressiveData);
},
}
isPendingRequest: function NetworkManager_isPendingRequest(xhrId) {
isPendingRequest(xhrId) {
return xhrId in this.pendingRequests;
},
}
isLoadedRequest: function NetworkManager_isLoadedRequest(xhrId) {
isLoadedRequest(xhrId) {
return xhrId in this.loadedRequests;
},
}
abortAllRequests: function NetworkManager_abortAllRequests() {
abortAllRequests() {
for (var xhrId in this.pendingRequests) {
this.abortRequest(xhrId | 0);
}
},
}
abortRequest: function NetworkManager_abortRequest(xhrId) {
abortRequest(xhrId) {
var xhr = this.pendingRequests[xhrId].xhr;
delete this.pendingRequests[xhrId];
xhr.abort();
}
};
}
return NetworkManager;
return NetworkManagerClass;
})();

View File

@ -41,47 +41,47 @@ registerAddonHistogram(ADDON_ID, 'PDF_VIEWER_TIME_TO_VIEW_MS', Telemetry.HISTOGR
this.PdfJsTelemetry = {
onViewerIsUsed: function () {
onViewerIsUsed() {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_USED');
histogram.add(true);
},
onFallback: function () {
onFallback() {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_FALLBACK_SHOWN');
histogram.add(true);
},
onDocumentSize: function (size) {
onDocumentSize(size) {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_DOCUMENT_SIZE_KB');
histogram.add(size / 1024);
},
onDocumentVersion: function (versionId) {
onDocumentVersion(versionId) {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_DOCUMENT_VERSION');
histogram.add(versionId);
},
onDocumentGenerator: function (generatorId) {
onDocumentGenerator(generatorId) {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_DOCUMENT_GENERATOR');
histogram.add(generatorId);
},
onEmbed: function (isObject) {
onEmbed(isObject) {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_EMBED');
histogram.add(isObject);
},
onFontType: function (fontTypeId) {
onFontType(fontTypeId) {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_FONT_TYPES');
histogram.add(fontTypeId);
},
onForm: function (isAcroform) {
onForm(isAcroform) {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_FORM');
histogram.add(isAcroform);
},
onPrint: function () {
onPrint() {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_PRINT');
histogram.add(true);
},
onStreamType: function (streamTypeId) {
onStreamType(streamTypeId) {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_STREAM_TYPES');
histogram.add(streamTypeId);
},
onTimeToView: function (ms) {
onTimeToView(ms) {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_TIME_TO_VIEW_MS');
histogram.add(ms);
}

View File

@ -23,47 +23,47 @@ const Cu = Components.utils;
Cu.import('resource://gre/modules/Services.jsm');
this.PdfJsTelemetry = {
onViewerIsUsed: function () {
onViewerIsUsed() {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_USED');
histogram.add(true);
},
onFallback: function () {
onFallback() {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_FALLBACK_SHOWN');
histogram.add(true);
},
onDocumentSize: function (size) {
onDocumentSize(size) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_DOCUMENT_SIZE_KB');
histogram.add(size / 1024);
},
onDocumentVersion: function (versionId) {
onDocumentVersion(versionId) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_DOCUMENT_VERSION');
histogram.add(versionId);
},
onDocumentGenerator: function (generatorId) {
onDocumentGenerator(generatorId) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_DOCUMENT_GENERATOR');
histogram.add(generatorId);
},
onEmbed: function (isObject) {
onEmbed(isObject) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_EMBED');
histogram.add(isObject);
},
onFontType: function (fontTypeId) {
onFontType(fontTypeId) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_FONT_TYPES');
histogram.add(fontTypeId);
},
onForm: function (isAcroform) {
onForm(isAcroform) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_FORM');
histogram.add(isAcroform);
},
onPrint: function () {
onPrint() {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_PRINT');
histogram.add(true);
},
onStreamType: function (streamTypeId) {
onStreamType(streamTypeId) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_STREAM_TYPES');
histogram.add(streamTypeId);
},
onTimeToView: function (ms) {
onTimeToView(ms) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_TIME_TO_VIEW_MS');
histogram.add(ms);
}

View File

@ -190,7 +190,7 @@ PdfDataListener.prototype = {
this.oncompleteCallback(null, errorCode);
}
},
onprogress: function() {},
onprogress() {},
get oncomplete() {
return this.oncompleteCallback;
},
@ -205,24 +205,27 @@ PdfDataListener.prototype = {
}
};
// All the priviledged actions.
function ChromeActions(domWindow, contentDispositionFilename) {
this.domWindow = domWindow;
this.contentDispositionFilename = contentDispositionFilename;
this.telemetryState = {
documentInfo: false,
firstPageInfo: false,
streamTypesUsed: [],
fontTypesUsed: [],
startAt: Date.now()
};
}
/**
* All the privileged actions.
*/
class ChromeActions {
constructor(domWindow, contentDispositionFilename) {
this.domWindow = domWindow;
this.contentDispositionFilename = contentDispositionFilename;
this.telemetryState = {
documentInfo: false,
firstPageInfo: false,
streamTypesUsed: [],
fontTypesUsed: [],
startAt: Date.now()
};
}
ChromeActions.prototype = {
isInPrivateBrowsing: function() {
isInPrivateBrowsing() {
return PrivateBrowsingUtils.isContentWindowPrivate(this.domWindow);
},
download: function(data, sendResponse) {
}
download(data, sendResponse) {
var self = this;
var originalUrl = data.originalUrl;
var blobUrl = data.blobUrl || originalUrl;
@ -279,7 +282,7 @@ ChromeActions.prototype = {
var listener = {
extListener: null,
onStartRequest: function(aRequest, aContext) {
onStartRequest(aRequest, aContext) {
var loadContext = self.domWindow
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIWebNavigation)
@ -290,7 +293,7 @@ ChromeActions.prototype = {
aRequest, loadContext, false);
this.extListener.onStartRequest(aRequest, aContext);
},
onStopRequest: function(aRequest, aContext, aStatusCode) {
onStopRequest(aRequest, aContext, aStatusCode) {
if (this.extListener) {
this.extListener.onStopRequest(aRequest, aContext, aStatusCode);
}
@ -299,20 +302,21 @@ ChromeActions.prototype = {
sendResponse(false);
}
},
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset,
aCount) {
this.extListener.onDataAvailable(aRequest, aContext, aInputStream,
onDataAvailable(aRequest, aContext, aDataInputStream, aOffset, aCount) {
this.extListener.onDataAvailable(aRequest, aContext, aDataInputStream,
aOffset, aCount);
}
};
channel.asyncOpen2(listener);
});
},
getLocale: function() {
}
getLocale() {
return getStringPref('general.useragent.locale', 'en-US');
},
getStrings: function(data) {
}
getStrings(data) {
try {
// Lazy initialization of localizedStrings
if (!('localizedStrings' in this)) {
@ -324,8 +328,9 @@ ChromeActions.prototype = {
log('Unable to retrieve localized strings: ' + e);
return 'null';
}
},
supportsIntegratedFind: function() {
}
supportsIntegratedFind() {
// Integrated find is only supported when we're not in a frame
if (this.domWindow.frameElement !== null) {
return false;
@ -339,22 +344,26 @@ ChromeActions.prototype = {
// ... or when the new find events code exists.
var findBar = getFindBar(this.domWindow);
return !!findBar && ('updateControlState' in findBar);
},
supportsDocumentFonts: function() {
}
supportsDocumentFonts() {
var prefBrowser = getIntPref('browser.display.use_document_fonts', 1);
var prefGfx = getBoolPref('gfx.downloadable_fonts.enabled', true);
return (!!prefBrowser && prefGfx);
},
supportsDocumentColors: function() {
}
supportsDocumentColors() {
return getIntPref('browser.display.document_color_use', 0) !== 2;
},
supportedMouseWheelZoomModifierKeys: function() {
}
supportedMouseWheelZoomModifierKeys() {
return {
ctrlKey: getIntPref('mousewheel.with_control.action', 3) === 3,
metaKey: getIntPref('mousewheel.with_meta.action', 1) === 3,
};
},
reportTelemetry: function (data) {
}
reportTelemetry(data) {
var probeInfo = JSON.parse(data);
switch (probeInfo.type) {
case 'documentInfo':
@ -409,12 +418,15 @@ ChromeActions.prototype = {
PdfJsTelemetry.onPrint();
break;
}
},
fallback: function(args, sendResponse) {
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 strings = getLocalizedStrings('chrome.properties');
var message;
@ -441,8 +453,9 @@ ChromeActions.prototype = {
winmm.removeMessageListener('PDFJS:Child:fallbackDownload',
fallbackDownload);
});
},
updateFindControlState: function(data) {
}
updateFindControlState(data) {
if (!this.supportsIntegratedFind()) {
return;
}
@ -461,8 +474,9 @@ ChromeActions.prototype = {
.getInterface(Ci.nsIContentFrameMessageManager);
winmm.sendAsyncMessage('PDFJS:Parent:updateControlState', data);
},
setPreferences: function(prefs, sendResponse) {
}
setPreferences(prefs, sendResponse) {
var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.');
var numberOfPrefs = 0;
var prefValue, prefName;
@ -496,8 +510,9 @@ ChromeActions.prototype = {
if (sendResponse) {
sendResponse(true);
}
},
getPreferences: function(prefs, sendResponse) {
}
getPreferences(prefs, sendResponse) {
var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.');
var currentPrefs = {}, numberOfPrefs = 0;
var prefValue, prefName;
@ -529,17 +544,16 @@ ChromeActions.prototype = {
return JSON.stringify(currentPrefs);
}
}
};
}
var RangedChromeActions = (function RangedChromeActionsClosure() {
/**
* This is for range requests
*/
function RangedChromeActions(
domWindow, contentDispositionFilename, originalRequest,
/**
* This is for range requests.
*/
class RangedChromeActions extends ChromeActions {
constructor(domWindow, contentDispositionFilename, originalRequest,
rangeEnabled, streamingEnabled, dataListener) {
ChromeActions.call(this, domWindow, contentDispositionFilename);
super(domWindow, contentDispositionFilename);
this.dataListener = dataListener;
this.originalRequest = originalRequest;
this.rangeEnabled = rangeEnabled;
@ -551,7 +565,7 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
// Pass all the headers from the original request through
var httpHeaderVisitor = {
headers: {},
visitHeader: function(aHeader, aValue) {
visitHeader(aHeader, aValue) {
if (aHeader === 'Range') {
// When loading the PDF from cache, firefox seems to set the Range
// request header to fetch only the unfetched portions of the file
@ -587,7 +601,7 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
this.networkManager = new NetworkManager(this.pdfUrl, {
httpHeaders: httpHeaderVisitor.headers,
getXhr: getXhr
getXhr,
});
// If we are in range request mode, this means we manually issued xhr
@ -598,12 +612,7 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
});
}
RangedChromeActions.prototype = Object.create(ChromeActions.prototype);
var proto = RangedChromeActions.prototype;
proto.constructor = RangedChromeActions;
proto.initPassiveLoading = function RangedChromeActions_initPassiveLoading() {
var self = this;
initPassiveLoading() {
var data;
if (!this.streamingEnabled) {
this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
@ -613,16 +622,16 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
} else {
data = this.dataListener.readData();
this.dataListener.onprogress = function (loaded, total) {
self.domWindow.postMessage({
this.dataListener.onprogress = (loaded, total) => {
this.domWindow.postMessage({
pdfjsLoadAction: 'progressiveRead',
loaded: loaded,
total: total,
chunk: self.dataListener.readData()
loaded,
total,
chunk: this.dataListener.readData(),
}, '*');
};
this.dataListener.oncomplete = function () {
self.dataListener = null;
this.dataListener.oncomplete = () => {
this.dataListener = null;
};
}
@ -632,13 +641,13 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
streamingEnabled: this.streamingEnabled,
pdfUrl: this.pdfUrl,
length: this.contentLength,
data: data
data,
}, '*');
return true;
};
}
proto.requestDataRange = function RangedChromeActions_requestDataRange(args) {
requestDataRange(args) {
if (!this.rangeEnabled) {
return;
}
@ -650,11 +659,11 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
// errors from chrome code for non-range requests, so this doesn't
// seem high-pri
this.networkManager.requestRange(begin, end, {
onDone: function RangedChromeActions_onDone(args) {
onDone: function RangedChromeActions_onDone(aArgs) {
domWindow.postMessage({
pdfjsLoadAction: 'range',
begin: args.begin,
chunk: args.chunk
begin: aArgs.begin,
chunk: aArgs.chunk,
}, '*');
},
onProgress: function RangedChromeActions_onProgress(evt) {
@ -664,162 +673,155 @@ var RangedChromeActions = (function RangedChromeActionsClosure() {
}, '*');
}
});
};
}
proto.abortLoading = function RangedChromeActions_abortLoading() {
abortLoading() {
this.networkManager.abortAllRequests();
if (this.originalRequest) {
this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
this.originalRequest = null;
}
this.dataListener = null;
};
}
}
return RangedChromeActions;
})();
var StandardChromeActions = (function StandardChromeActionsClosure() {
/**
* This is for a single network stream
*/
function StandardChromeActions(domWindow, contentDispositionFilename,
originalRequest, dataListener) {
ChromeActions.call(this, domWindow, contentDispositionFilename);
/**
* This is for a single network stream.
*/
class StandardChromeActions extends ChromeActions {
constructor(domWindow, contentDispositionFilename, originalRequest,
dataListener) {
super(domWindow, contentDispositionFilename);
this.originalRequest = originalRequest;
this.dataListener = dataListener;
}
StandardChromeActions.prototype = Object.create(ChromeActions.prototype);
var proto = StandardChromeActions.prototype;
proto.constructor = StandardChromeActions;
proto.initPassiveLoading =
function StandardChromeActions_initPassiveLoading() {
initPassiveLoading() {
if (!this.dataListener) {
return false;
}
var self = this;
this.dataListener.onprogress = function ChromeActions_dataListenerProgress(
loaded, total) {
self.domWindow.postMessage({
this.dataListener.onprogress = (loaded, total) => {
this.domWindow.postMessage({
pdfjsLoadAction: 'progress',
loaded: loaded,
total: total
loaded,
total,
}, '*');
};
this.dataListener.oncomplete =
function StandardChromeActions_dataListenerComplete(data, errorCode) {
self.domWindow.postMessage({
this.dataListener.oncomplete = (data, errorCode) => {
this.domWindow.postMessage({
pdfjsLoadAction: 'complete',
data: data,
errorCode: errorCode
data,
errorCode,
}, '*');
self.dataListener = null;
self.originalRequest = null;
this.dataListener = null;
this.originalRequest = null;
};
return true;
};
}
proto.abortLoading = function StandardChromeActions_abortLoading() {
abortLoading() {
if (this.originalRequest) {
this.originalRequest.cancel(Cr.NS_BINDING_ABORTED);
this.originalRequest = 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) {
var message = event.target;
var doc = message.ownerDocument;
var action = event.detail.action;
var data = event.detail.data;
var sync = event.detail.sync;
var actions = this.actions;
if (!(action in actions)) {
log('Unknown action: ' + action);
return;
}
var response;
if (sync) {
response = actions[action].call(this.actions, data);
event.detail.response = Cu.cloneInto(response, doc.defaultView);
} else {
if (!event.detail.responseExpected) {
doc.documentElement.removeChild(message);
response = null;
} else {
response = function sendResponse(response) {
try {
var listener = doc.createEvent('CustomEvent');
let detail = Cu.cloneInto({ response: response }, doc.defaultView);
listener.initCustomEvent('pdf.js.response', true, false, detail);
return message.dispatchEvent(listener);
} catch (e) {
// doc is no longer accessible because the requestor is already
// gone. unloaded content cannot receive the response anyway.
return false;
}
};
}
/**
* 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 doc = message.ownerDocument;
var action = event.detail.action;
var data = event.detail.data;
var sync = event.detail.sync;
var actions = this.actions;
if (!(action in actions)) {
log('Unknown action: ' + action);
return;
}
var response;
if (sync) {
response = actions[action].call(this.actions, data);
event.detail.response = Cu.cloneInto(response, doc.defaultView);
} else {
if (!event.detail.responseExpected) {
doc.documentElement.removeChild(message);
response = null;
} else {
response = function sendResponse(aResponse) {
try {
var listener = doc.createEvent('CustomEvent');
let detail = Cu.cloneInto({ response: aResponse }, doc.defaultView);
listener.initCustomEvent('pdf.js.response', true, false, detail);
return message.dispatchEvent(listener);
} catch (e) {
// doc is no longer accessible because the requestor is already
// gone. unloaded content cannot receive the response anyway.
return false;
}
};
}
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.
function FindEventManager(contentWindow) {
this.contentWindow = contentWindow;
this.winmm = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell)
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIContentFrameMessageManager);
}
FindEventManager.prototype.bind = function() {
var unload = function(e) {
this.unbind();
this.contentWindow.removeEventListener(e.type, unload);
}.bind(this);
this.contentWindow.addEventListener('unload', unload);
/**
* Forwards events from the eventElement to the contentWindow only if the
* content window matches the currently selected browser window.
*/
class FindEventManager {
constructor(contentWindow) {
this.contentWindow = contentWindow;
this.winmm = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell)
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIContentFrameMessageManager);
}
// We cannot directly attach listeners to for the find events
// since the FindBar is in the parent process. Instead we're
// asking the PdfjsChromeUtils to do it for us and forward
// all the find events to us.
this.winmm.sendAsyncMessage('PDFJS:Parent:addEventListener');
this.winmm.addMessageListener('PDFJS:Child:handleEvent', this);
};
bind() {
var unload = function(e) {
this.unbind();
this.contentWindow.removeEventListener(e.type, unload);
}.bind(this);
this.contentWindow.addEventListener('unload', unload);
FindEventManager.prototype.receiveMessage = function(msg) {
var detail = msg.data.detail;
var type = msg.data.type;
var contentWindow = this.contentWindow;
// We cannot directly attach listeners to for the find events
// since the FindBar is in the parent process. Instead we're
// asking the PdfjsChromeUtils to do it for us and forward
// all the find events to us.
this.winmm.sendAsyncMessage('PDFJS:Parent:addEventListener');
this.winmm.addMessageListener('PDFJS:Child:handleEvent', this);
}
detail = Cu.cloneInto(detail, contentWindow);
var forward = contentWindow.document.createEvent('CustomEvent');
forward.initCustomEvent(type, true, true, detail);
contentWindow.dispatchEvent(forward);
};
receiveMessage(msg) {
var detail = msg.data.detail;
var type = msg.data.type;
var contentWindow = this.contentWindow;
FindEventManager.prototype.unbind = function() {
this.winmm.sendAsyncMessage('PDFJS:Parent:removeEventListener');
};
detail = Cu.cloneInto(detail, contentWindow);
var forward = contentWindow.document.createEvent('CustomEvent');
forward.initCustomEvent(type, true, true, detail);
contentWindow.dispatchEvent(forward);
}
unbind() {
this.winmm.sendAsyncMessage('PDFJS:Parent:removeEventListener');
}
}
function PdfStreamConverter() {
}
@ -858,18 +860,18 @@ PdfStreamConverter.prototype = {
*/
// nsIStreamConverter::convert
convert: function(aFromStream, aFromType, aToType, aCtxt) {
convert(aFromStream, aFromType, aToType, aCtxt) {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
// nsIStreamConverter::asyncConvertData
asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
asyncConvertData(aFromType, aToType, aListener, aCtxt) {
// Store the listener passed to us
this.listener = aListener;
},
// nsIStreamListener::onDataAvailable
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
onDataAvailable(aRequest, aContext, aInputStream, aOffset, aCount) {
if (!this.dataListener) {
return;
}
@ -881,7 +883,7 @@ PdfStreamConverter.prototype = {
},
// nsIRequestObserver::onStartRequest
onStartRequest: function(aRequest, aContext) {
onStartRequest(aRequest, aContext) {
// Setup the request so we can use it below.
var isHttpRequest = false;
try {
@ -960,14 +962,14 @@ PdfStreamConverter.prototype = {
// request(aRequest) below so we don't overwrite the original channel and
// trigger an assertion.
var proxy = {
onStartRequest: function(request, context) {
onStartRequest(request, context) {
listener.onStartRequest(aRequest, aContext);
},
onDataAvailable: function(request, context, inputStream, offset, count) {
onDataAvailable(request, context, inputStream, offset, count) {
listener.onDataAvailable(aRequest, aContext, inputStream,
offset, count);
},
onStopRequest: function(request, context, statusCode) {
onStopRequest(request, context, statusCode) {
// We get the DOM window here instead of before the request since it
// may have changed during a redirect.
var domWindow = getDOMWindow(channel);
@ -1017,7 +1019,7 @@ PdfStreamConverter.prototype = {
},
// nsIRequestObserver::onStopRequest
onStopRequest: function(aRequest, aContext, aStatusCode) {
onStopRequest(aRequest, aContext, aStatusCode) {
if (!this.dataListener) {
// Do nothing
return;

View File

@ -51,7 +51,7 @@ var PdfjsChromeUtils = {
* Public API
*/
init: function () {
init() {
this._browsers = new WeakSet();
if (!this._ppmm) {
// global parent process message manager (PPMM)
@ -78,7 +78,7 @@ var PdfjsChromeUtils = {
}
},
uninit: function () {
uninit() {
if (this._ppmm) {
this._ppmm.removeMessageListener('PDFJS:Parent:clearUserPref', this);
this._ppmm.removeMessageListener('PDFJS:Parent:setIntPref', this);
@ -107,7 +107,7 @@ var PdfjsChromeUtils = {
* instruct the child to refresh its configuration and (possibly)
* the module's registration.
*/
notifyChildOfSettingsChange: function () {
notifyChildOfSettingsChange() {
if (Services.appinfo.processType ===
Services.appinfo.PROCESS_TYPE_DEFAULT && this._ppmm) {
// XXX kinda bad, we want to get the parent process mm associated
@ -123,13 +123,13 @@ var PdfjsChromeUtils = {
* Events
*/
observe: function(aSubject, aTopic, aData) {
observe(aSubject, aTopic, aData) {
if (aTopic === 'quit-application') {
this.uninit();
}
},
receiveMessage: function (aMsg) {
receiveMessage(aMsg) {
switch (aMsg.name) {
case 'PDFJS:Parent:clearUserPref':
this._clearUserPref(aMsg.data.name);
@ -166,20 +166,20 @@ var PdfjsChromeUtils = {
* Internal
*/
_findbarFromMessage: function(aMsg) {
_findbarFromMessage(aMsg) {
let browser = aMsg.target;
let tabbrowser = browser.getTabBrowser();
let tab = tabbrowser.getTabForBrowser(browser);
return tabbrowser.getFindBar(tab);
},
_updateControlState: function (aMsg) {
_updateControlState(aMsg) {
let data = aMsg.data;
this._findbarFromMessage(aMsg)
.updateControlState(data.result, data.findPrevious);
},
handleEvent: function(aEvent) {
handleEvent(aEvent) {
// To avoid forwarding the message as a CPOW, create a structured cloneable
// version of the event for both performance, and ease of usage, reasons.
let type = aEvent.type;
@ -197,8 +197,7 @@ var PdfjsChromeUtils = {
}
// Only forward the events if the current browser is a registered browser.
let mm = browser.messageManager;
mm.sendAsyncMessage('PDFJS:Child:handleEvent',
{ type: type, detail: detail });
mm.sendAsyncMessage('PDFJS:Child:handleEvent', { type, detail, });
aEvent.preventDefault();
},
@ -207,7 +206,7 @@ var PdfjsChromeUtils = {
'findhighlightallchange',
'findcasesensitivitychange'],
_addEventListener: function (aMsg) {
_addEventListener(aMsg) {
let browser = aMsg.target;
if (this._browsers.has(browser)) {
throw new Error('FindEventManager was bound 2nd time ' +
@ -226,7 +225,7 @@ var PdfjsChromeUtils = {
}
},
_removeEventListener: function (aMsg) {
_removeEventListener(aMsg) {
let browser = aMsg.target;
if (!this._browsers.has(browser)) {
throw new Error('FindEventManager was unbound without binding it first.');
@ -242,7 +241,7 @@ var PdfjsChromeUtils = {
}
},
_ensurePreferenceAllowed: function (aPrefName) {
_ensurePreferenceAllowed(aPrefName) {
let unPrefixedName = aPrefName.split(PREF_PREFIX + '.');
if (unPrefixedName[0] !== '' ||
this._allowedPrefNames.indexOf(unPrefixedName[1]) === -1) {
@ -252,27 +251,27 @@ var PdfjsChromeUtils = {
}
},
_clearUserPref: function (aPrefName) {
_clearUserPref(aPrefName) {
this._ensurePreferenceAllowed(aPrefName);
Services.prefs.clearUserPref(aPrefName);
},
_setIntPref: function (aPrefName, aPrefValue) {
_setIntPref(aPrefName, aPrefValue) {
this._ensurePreferenceAllowed(aPrefName);
Services.prefs.setIntPref(aPrefName, aPrefValue);
},
_setBoolPref: function (aPrefName, aPrefValue) {
_setBoolPref(aPrefName, aPrefValue) {
this._ensurePreferenceAllowed(aPrefName);
Services.prefs.setBoolPref(aPrefName, aPrefValue);
},
_setCharPref: function (aPrefName, aPrefValue) {
_setCharPref(aPrefName, aPrefValue) {
this._ensurePreferenceAllowed(aPrefName);
Services.prefs.setCharPref(aPrefName, aPrefValue);
},
_setStringPref: function (aPrefName, aPrefValue) {
_setStringPref(aPrefName, aPrefValue) {
this._ensurePreferenceAllowed(aPrefName);
let str = Cc['@mozilla.org/supports-string;1']
.createInstance(Ci.nsISupportsString);
@ -285,7 +284,7 @@ var PdfjsChromeUtils = {
* we bounce this pdfjs enabled configuration check over to the
* parent.
*/
isDefaultHandlerApp: function () {
isDefaultHandlerApp() {
var handlerInfo = Svc.mime.getFromTypeAndExtension(PDF_CONTENT_TYPE, 'pdf');
return (!handlerInfo.alwaysAskBeforeHandling &&
handlerInfo.preferredAction === Ci.nsIHandlerInfo.handleInternally);
@ -295,7 +294,7 @@ var PdfjsChromeUtils = {
* Display a notification warning when the renderer isn't sure
* a pdf displayed correctly.
*/
_displayWarning: function (aMsg) {
_displayWarning(aMsg) {
let data = aMsg.data;
let browser = aMsg.target;
@ -308,13 +307,12 @@ var PdfjsChromeUtils = {
let messageSent = false;
function sendMessage(download) {
let mm = browser.messageManager;
mm.sendAsyncMessage('PDFJS:Child:fallbackDownload',
{ download: download });
mm.sendAsyncMessage('PDFJS:Child:fallbackDownload', { download, });
}
let buttons = [{
label: data.label,
accessKey: data.accessKey,
callback: function() {
callback() {
messageSent = true;
sendMessage(true);
}

View File

@ -38,7 +38,7 @@ var PdfjsContentUtils = {
Services.appinfo.PROCESS_TYPE_CONTENT);
},
init: function () {
init() {
// child *process* mm, or when loaded into the parent for in-content
// support the psuedo child process mm 'child PPMM'.
if (!this._mm) {
@ -49,7 +49,7 @@ var PdfjsContentUtils = {
}
},
uninit: function () {
uninit() {
if (this._mm) {
this._mm.removeMessageListener('PDFJS:Child:refreshSettings', this);
Services.obs.removeObserver(this, 'quit-application');
@ -63,34 +63,34 @@ var PdfjsContentUtils = {
* approved pdfjs prefs in chrome utils.
*/
clearUserPref: function (aPrefName) {
clearUserPref(aPrefName) {
this._mm.sendSyncMessage('PDFJS:Parent:clearUserPref', {
name: aPrefName
});
},
setIntPref: function (aPrefName, aPrefValue) {
setIntPref(aPrefName, aPrefValue) {
this._mm.sendSyncMessage('PDFJS:Parent:setIntPref', {
name: aPrefName,
value: aPrefValue
});
},
setBoolPref: function (aPrefName, aPrefValue) {
setBoolPref(aPrefName, aPrefValue) {
this._mm.sendSyncMessage('PDFJS:Parent:setBoolPref', {
name: aPrefName,
value: aPrefValue
});
},
setCharPref: function (aPrefName, aPrefValue) {
setCharPref(aPrefName, aPrefValue) {
this._mm.sendSyncMessage('PDFJS:Parent:setCharPref', {
name: aPrefName,
value: aPrefValue
});
},
setStringPref: function (aPrefName, aPrefValue) {
setStringPref(aPrefName, aPrefValue) {
this._mm.sendSyncMessage('PDFJS:Parent:setStringPref', {
name: aPrefName,
value: aPrefValue
@ -101,7 +101,7 @@ var PdfjsContentUtils = {
* Forwards default app query to the parent where we check various
* handler app settings only available in the parent process.
*/
isDefaultHandlerApp: function () {
isDefaultHandlerApp() {
return this._mm.sendSyncMessage('PDFJS:Parent:isDefaultHandlerApp')[0];
},
@ -109,7 +109,7 @@ var PdfjsContentUtils = {
* Request the display of a notification warning in the associated window
* 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.
let winmm = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell)
@ -118,7 +118,7 @@ var PdfjsContentUtils = {
winmm.sendAsyncMessage('PDFJS:Parent:displayWarning', {
message: aMessage,
label: aLabel,
accessKey: accessKey
accessKey: aAccessKey,
});
},
@ -126,13 +126,13 @@ var PdfjsContentUtils = {
* Events
*/
observe: function(aSubject, aTopic, aData) {
observe(aSubject, aTopic, aData) {
if (aTopic === 'quit-application') {
this.uninit();
}
},
receiveMessage: function (aMsg) {
receiveMessage(aMsg) {
switch (aMsg.name) {
case 'PDFJS:Child:refreshSettings':
// Only react to this if we are remote.

View File

@ -121,12 +121,12 @@
get: translateString,
// get the document language
getLanguage: function() {
getLanguage() {
return gLanguage;
},
// get the direction (ltr|rtl) of the current language
getDirection: function() {
getDirection() {
// http://www.w3.org/International/questions/qa-scripts
// Arabic, Hebrew, Farsi, Pashto, Urdu
var rtlList = ['ar', 'he', 'fa', 'ps', 'ur'];
@ -137,9 +137,11 @@
return (rtlList.indexOf(shortCode) >= 0) ? 'rtl' : 'ltr';
},
getReadyState: function() { return gReadyState; },
getReadyState() {
return gReadyState;
},
setExternalLocalizerServices: function (externalLocalizerServices) {
setExternalLocalizerServices(externalLocalizerServices) {
gExternalLocalizerServices = externalLocalizerServices;
// ... in case if we missed DOMContentLoaded above.