First commit

This commit is contained in:
Pierre Hubert
2016-11-19 12:08:12 +01:00
commit 990540b2b9
4706 changed files with 931207 additions and 0 deletions

View File

@ -0,0 +1,27 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* 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.
*/
/* jshint esnext:true, maxlen:100 */
'use strict';
// Don't remove this file. FF15+ expects PdfJs module to be present at resource://pdf.js/PdfJs.jsm
// See https://mxr.mozilla.org/mozilla-central/source/browser/components/nsBrowserGlue.js
var EXPORTED_SYMBOLS = ['PdfJs'];
let PdfJs = {
init: function PdfJs_init() {}
};

View File

@ -0,0 +1,334 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* 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.
*/
/* jshint esnext:true */
/* globals Components, Services, XPCOMUtils, PdfjsChromeUtils, PdfRedirector,
PdfjsContentUtils, DEFAULT_PREFERENCES, PdfStreamConverter */
'use strict';
var EXPORTED_SYMBOLS = ['PdfJs'];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cm = Components.manager;
const Cu = Components.utils;
const PREF_PREFIX = 'pdfjs';
const PREF_DISABLED = PREF_PREFIX + '.disabled';
const PREF_MIGRATION_VERSION = PREF_PREFIX + '.migrationVersion';
const PREF_PREVIOUS_ACTION = PREF_PREFIX + '.previousHandler.preferredAction';
const PREF_PREVIOUS_ASK = PREF_PREFIX +
'.previousHandler.alwaysAskBeforeHandling';
const PREF_DISABLED_PLUGIN_TYPES = 'plugin.disable_full_page_plugin_for_types';
const TOPIC_PDFJS_HANDLER_CHANGED = 'pdfjs:handlerChanged';
const TOPIC_PLUGINS_LIST_UPDATED = 'plugins-list-updated';
const TOPIC_PLUGIN_INFO_UPDATED = 'plugin-info-updated';
const PDF_CONTENT_TYPE = 'application/pdf';
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
let Svc = {};
XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
'@mozilla.org/mime;1',
'nsIMIMEService');
XPCOMUtils.defineLazyServiceGetter(Svc, 'pluginHost',
'@mozilla.org/plugin/host;1',
'nsIPluginHost');
XPCOMUtils.defineLazyModuleGetter(this, 'PdfjsChromeUtils',
'resource://pdf.js/PdfjsChromeUtils.jsm');
XPCOMUtils.defineLazyModuleGetter(this, 'PdfjsContentUtils',
'resource://pdf.js/PdfjsContentUtils.jsm');
function getBoolPref(aPref, aDefaultValue) {
try {
return Services.prefs.getBoolPref(aPref);
} catch (ex) {
return aDefaultValue;
}
}
function getIntPref(aPref, aDefaultValue) {
try {
return Services.prefs.getIntPref(aPref);
} catch (ex) {
return aDefaultValue;
}
}
function isDefaultHandler() {
if (Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_CONTENT) {
return PdfjsContentUtils.isDefaultHandlerApp();
}
return PdfjsChromeUtils.isDefaultHandlerApp();
}
function initializeDefaultPreferences() {
//#include ../../../web/default_preferences.js
var defaultBranch = Services.prefs.getDefaultBranch(PREF_PREFIX + '.');
var defaultValue;
for (var key in DEFAULT_PREFERENCES) {
defaultValue = DEFAULT_PREFERENCES[key];
switch (typeof defaultValue) {
case 'boolean':
defaultBranch.setBoolPref(key, defaultValue);
break;
case 'number':
defaultBranch.setIntPref(key, defaultValue);
break;
case 'string':
defaultBranch.setCharPref(key, defaultValue);
break;
}
}
}
// Register/unregister a constructor as a factory.
function Factory() {}
Factory.prototype = {
register: function register(targetConstructor) {
var proto = targetConstructor.prototype;
this._classID = proto.classID;
var factory = XPCOMUtils._getFactory(targetConstructor);
this._factory = factory;
var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
registrar.registerFactory(proto.classID, proto.classDescription,
proto.contractID, factory);
},
unregister: function unregister() {
var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
registrar.unregisterFactory(this._classID, this._factory);
this._factory = null;
}
};
let PdfJs = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
_registered: false,
_initialized: false,
init: function init(remote) {
if (Services.appinfo.processType !==
Services.appinfo.PROCESS_TYPE_DEFAULT) {
throw new Error('PdfJs.init should only get called ' +
'in the parent process.');
}
PdfjsChromeUtils.init();
if (!remote) {
PdfjsContentUtils.init();
}
this.initPrefs();
this.updateRegistration();
},
initPrefs: function initPrefs() {
if (this._initialized) {
return;
}
this._initialized = true;
if (!getBoolPref(PREF_DISABLED, true)) {
this._migrate();
}
// Listen for when pdf.js is completely disabled or a different pdf handler
// is chosen.
Services.prefs.addObserver(PREF_DISABLED, this, false);
Services.prefs.addObserver(PREF_DISABLED_PLUGIN_TYPES, this, false);
Services.obs.addObserver(this, TOPIC_PDFJS_HANDLER_CHANGED, false);
Services.obs.addObserver(this, TOPIC_PLUGINS_LIST_UPDATED, false);
Services.obs.addObserver(this, TOPIC_PLUGIN_INFO_UPDATED, false);
initializeDefaultPreferences();
},
updateRegistration: function updateRegistration() {
if (this.enabled) {
this._ensureRegistered();
} else {
this._ensureUnregistered();
}
},
uninit: function uninit() {
if (this._initialized) {
Services.prefs.removeObserver(PREF_DISABLED, this, false);
Services.prefs.removeObserver(PREF_DISABLED_PLUGIN_TYPES, this, false);
Services.obs.removeObserver(this, TOPIC_PDFJS_HANDLER_CHANGED, false);
Services.obs.removeObserver(this, TOPIC_PLUGINS_LIST_UPDATED, false);
Services.obs.removeObserver(this, TOPIC_PLUGIN_INFO_UPDATED, false);
this._initialized = false;
}
this._ensureUnregistered();
},
_migrate: function migrate() {
const VERSION = 2;
var currentVersion = getIntPref(PREF_MIGRATION_VERSION, 0);
if (currentVersion >= VERSION) {
return;
}
// Make pdf.js the default pdf viewer on the first migration.
if (currentVersion < 1) {
this._becomeHandler();
}
if (currentVersion < 2) {
// cleaning up of unused database preference (see #3994)
Services.prefs.clearUserPref(PREF_PREFIX + '.database');
}
Services.prefs.setIntPref(PREF_MIGRATION_VERSION, VERSION);
},
_becomeHandler: function _becomeHandler() {
let handlerInfo = Svc.mime.getFromTypeAndExtension(PDF_CONTENT_TYPE, 'pdf');
let prefs = Services.prefs;
if (handlerInfo.preferredAction !== Ci.nsIHandlerInfo.handleInternally &&
handlerInfo.preferredAction !== false) {
// Store the previous settings of preferredAction and
// alwaysAskBeforeHandling in case we need to revert them in a hotfix that
// would turn pdf.js off.
prefs.setIntPref(PREF_PREVIOUS_ACTION, handlerInfo.preferredAction);
prefs.setBoolPref(PREF_PREVIOUS_ASK, handlerInfo.alwaysAskBeforeHandling);
}
let handlerService = Cc['@mozilla.org/uriloader/handler-service;1'].
getService(Ci.nsIHandlerService);
// Change and save mime handler settings.
handlerInfo.alwaysAskBeforeHandling = false;
handlerInfo.preferredAction = Ci.nsIHandlerInfo.handleInternally;
handlerService.store(handlerInfo);
// Also disable any plugins for pdfs.
var stringTypes = '';
var types = [];
if (prefs.prefHasUserValue(PREF_DISABLED_PLUGIN_TYPES)) {
stringTypes = prefs.getCharPref(PREF_DISABLED_PLUGIN_TYPES);
}
if (stringTypes !== '') {
types = stringTypes.split(',');
}
if (types.indexOf(PDF_CONTENT_TYPE) === -1) {
types.push(PDF_CONTENT_TYPE);
}
prefs.setCharPref(PREF_DISABLED_PLUGIN_TYPES, types.join(','));
// Update the category manager in case the plugins are already loaded.
let categoryManager = Cc['@mozilla.org/categorymanager;1'];
categoryManager.getService(Ci.nsICategoryManager).
deleteCategoryEntry('Gecko-Content-Viewers',
PDF_CONTENT_TYPE,
false);
},
// nsIObserver
observe: function observe(aSubject, aTopic, aData) {
this.updateRegistration();
if (Services.appinfo.processType ===
Services.appinfo.PROCESS_TYPE_DEFAULT) {
let jsm = 'resource://pdf.js/PdfjsChromeUtils.jsm';
let PdfjsChromeUtils = Components.utils.import(jsm, {}).PdfjsChromeUtils;
PdfjsChromeUtils.notifyChildOfSettingsChange();
}
},
/**
* pdf.js is only enabled if it is both selected as the pdf viewer and if the
* global switch enabling it is true.
* @return {boolean} Wether or not it's enabled.
*/
get enabled() {
var disabled = getBoolPref(PREF_DISABLED, true);
if (disabled) {
return false;
}
// Check if the 'application/pdf' preview handler is configured properly.
if (!isDefaultHandler()) {
return false;
}
// Check if we have disabled plugin handling of 'application/pdf' in prefs
if (Services.prefs.prefHasUserValue(PREF_DISABLED_PLUGIN_TYPES)) {
let disabledPluginTypes =
Services.prefs.getCharPref(PREF_DISABLED_PLUGIN_TYPES).split(',');
if (disabledPluginTypes.indexOf(PDF_CONTENT_TYPE) >= 0) {
return true;
}
}
// Check if there is an enabled pdf plugin.
// Note: this check is performed last because getPluginTags() triggers
// costly plugin list initialization (bug 881575)
let tags = Cc['@mozilla.org/plugin/host;1'].
getService(Ci.nsIPluginHost).
getPluginTags();
let enabledPluginFound = tags.some(function(tag) {
if (tag.disabled) {
return false;
}
let mimeTypes = tag.getMimeTypes();
return mimeTypes.some(function(mimeType) {
return mimeType === PDF_CONTENT_TYPE;
});
});
// Use pdf.js if pdf plugin is not present or disabled
return !enabledPluginFound;
},
_ensureRegistered: function _ensureRegistered() {
if (this._registered) {
return;
}
this._pdfStreamConverterFactory = new Factory();
Cu.import('resource://pdf.js/PdfStreamConverter.jsm');
this._pdfStreamConverterFactory.register(PdfStreamConverter);
this._pdfRedirectorFactory = new Factory();
Cu.import('resource://pdf.js/PdfRedirector.jsm');
this._pdfRedirectorFactory.register(PdfRedirector);
Svc.pluginHost.registerPlayPreviewMimeType(PDF_CONTENT_TYPE, true,
'data:application/x-moz-playpreview-pdfjs;,');
this._registered = true;
},
_ensureUnregistered: function _ensureUnregistered() {
if (!this._registered) {
return;
}
this._pdfStreamConverterFactory.unregister();
Cu.unload('resource://pdf.js/PdfStreamConverter.jsm');
delete this._pdfStreamConverterFactory;
this._pdfRedirectorFactory.unregister();
Cu.unload('resource://pdf.js/PdfRedirector.jsm');
delete this._pdfRedirectorFactory;
Svc.pluginHost.unregisterPlayPreviewMimeType(PDF_CONTENT_TYPE);
this._registered = false;
}
};

View File

@ -0,0 +1,113 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* Copyright 2013 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.
*/
/* jshint esnext:true, maxlen:120 */
/* globals Components, Services */
'use strict';
this.EXPORTED_SYMBOLS = ['PdfJsTelemetry'];
const Cu = Components.utils;
Cu.import('resource://gre/modules/Services.jsm');
const ADDON_ID = 'uriloader@pdf.js';
var Telemetry = Services.telemetry;
var registerAddonHistogram = Telemetry.registerAddonHistogram;
try {
// Swapping arguments of the registerAddonHistogram for older Firefox versions.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1069953.
var ffVersion = parseInt(Services.appinfo.platformVersion);
var oldTelemetryAPI = ffVersion < 36;
if (ffVersion === 36) {
// Probing FF36 to check if it has new API.
try {
Telemetry.registerAddonHistogram(ADDON_ID, 'PDF_36',
Telemetry.HISTOGRAM_LINEAR, 1, 40, 41);
var histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_36');
histogram.add(36);
} catch (e) {
oldTelemetryAPI = true;
}
}
if (oldTelemetryAPI) {
registerAddonHistogram = function (p1, p2, p3, p4, p5, p6) {
return Telemetry.registerAddonHistogram(p1, p2, p4, p5, p6, p3);
};
}
} catch (ex) { }
registerAddonHistogram(ADDON_ID, 'PDF_VIEWER_USED', Telemetry.HISTOGRAM_BOOLEAN, 1, 2, 3);
registerAddonHistogram(ADDON_ID, 'PDF_VIEWER_FALLBACK_SHOWN', Telemetry.HISTOGRAM_BOOLEAN, 1, 2, 3);
registerAddonHistogram(ADDON_ID, 'PDF_VIEWER_DOCUMENT_VERSION', Telemetry.HISTOGRAM_LINEAR, 1, 10, 11);
registerAddonHistogram(ADDON_ID, 'PDF_VIEWER_DOCUMENT_GENERATOR', Telemetry.HISTOGRAM_LINEAR, 1, 25, 26);
registerAddonHistogram(ADDON_ID, 'PDF_VIEWER_DOCUMENT_SIZE_KB', Telemetry.HISTOGRAM_EXPONENTIAL, 2, 64 * 1024, 20);
registerAddonHistogram(ADDON_ID, 'PDF_VIEWER_EMBED', Telemetry.HISTOGRAM_BOOLEAN, 1, 2, 3);
registerAddonHistogram(ADDON_ID, 'PDF_VIEWER_FONT_TYPES', Telemetry.HISTOGRAM_LINEAR, 1, 19, 20);
registerAddonHistogram(ADDON_ID, 'PDF_VIEWER_FORM', Telemetry.HISTOGRAM_BOOLEAN, 1, 2, 3);
registerAddonHistogram(ADDON_ID, 'PDF_VIEWER_PRINT', Telemetry.HISTOGRAM_BOOLEAN, 1, 2, 3);
registerAddonHistogram(ADDON_ID, 'PDF_VIEWER_STREAM_TYPES', Telemetry.HISTOGRAM_LINEAR, 1, 19, 20);
registerAddonHistogram(ADDON_ID, 'PDF_VIEWER_TIME_TO_VIEW_MS', Telemetry.HISTOGRAM_EXPONENTIAL, 1, 10000, 50);
this.PdfJsTelemetry = {
onViewerIsUsed: function () {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_USED');
histogram.add(true);
},
onFallback: function () {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_FALLBACK_SHOWN');
histogram.add(true);
},
onDocumentSize: function (size) {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_DOCUMENT_SIZE_KB');
histogram.add(size / 1024);
},
onDocumentVersion: function (versionId) {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_DOCUMENT_VERSION');
histogram.add(versionId);
},
onDocumentGenerator: function (generatorId) {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_DOCUMENT_GENERATOR');
histogram.add(generatorId);
},
onEmbed: function (isObject) {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_EMBED');
histogram.add(isObject);
},
onFontType: function (fontTypeId) {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_FONT_TYPES');
histogram.add(fontTypeId);
},
onForm: function (isAcroform) {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_FORM');
histogram.add(isAcroform);
},
onPrint: function () {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_PRINT');
histogram.add(true);
},
onStreamType: function (streamTypeId) {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_STREAM_TYPES');
histogram.add(streamTypeId);
},
onTimeToView: function (ms) {
let histogram = Telemetry.getAddonHistogram(ADDON_ID, 'PDF_VIEWER_TIME_TO_VIEW_MS');
histogram.add(ms);
}
};

View File

@ -0,0 +1,72 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* Copyright 2013 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.
*/
/* jshint esnext:true, maxlen: 100 */
/* globals Components, Services */
'use strict';
this.EXPORTED_SYMBOLS = ['PdfJsTelemetry'];
const Cu = Components.utils;
Cu.import('resource://gre/modules/Services.jsm');
this.PdfJsTelemetry = {
onViewerIsUsed: function () {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_USED');
histogram.add(true);
},
onFallback: function () {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_FALLBACK_SHOWN');
histogram.add(true);
},
onDocumentSize: function (size) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_DOCUMENT_SIZE_KB');
histogram.add(size / 1024);
},
onDocumentVersion: function (versionId) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_DOCUMENT_VERSION');
histogram.add(versionId);
},
onDocumentGenerator: function (generatorId) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_DOCUMENT_GENERATOR');
histogram.add(generatorId);
},
onEmbed: function (isObject) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_EMBED');
histogram.add(isObject);
},
onFontType: function (fontTypeId) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_FONT_TYPES');
histogram.add(fontTypeId);
},
onForm: function (isAcroform) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_FORM');
histogram.add(isAcroform);
},
onPrint: function () {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_PRINT');
histogram.add(true);
},
onStreamType: function (streamTypeId) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_STREAM_TYPES');
histogram.add(streamTypeId);
},
onTimeToView: function (ms) {
let histogram = Services.telemetry.getHistogramById('PDF_VIEWER_TIME_TO_VIEW_MS');
histogram.add(ms);
}
};

View File

@ -0,0 +1,137 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* 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.
*/
/* jshint esnext:true */
/* globals Components, Services, XPCOMUtils, NetUtil, dump */
'use strict';
var EXPORTED_SYMBOLS = ['PdfRedirector'];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
const PDF_CONTENT_TYPE = 'application/pdf';
const FIREFOX_ID = '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}';
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/NetUtil.jsm');
function getDOMWindow(aChannel) {
var requestor = aChannel.notificationCallbacks ?
aChannel.notificationCallbacks :
aChannel.loadGroup.notificationCallbacks;
var win = requestor.getInterface(Components.interfaces.nsIDOMWindow);
return win;
}
function getObjectUrl(window) {
// PlayPreview overlay "belongs" to the embed/object tag and consists of DIV
// and IFRAME. Starting from IFRAME and looking for first object tag.
var element = window.frameElement, containerElement;
if (!element) {
return null; // iframe tag
}
var tagName = element.nodeName;
while (tagName !== 'EMBED' && tagName !== 'OBJECT') {
containerElement = element;
element = element.parentNode;
if (!element) {
return null; // object tag was not found
}
tagName = element.nodeName;
}
// Checking if overlay is a proper PlayPreview overlay.
if (element.displayedType !== element.TYPE_NULL ||
element.pluginFallbackType !== element.PLUGIN_PLAY_PREVIEW) {
return null; // invalid plugin element overlay state
}
for (var i = 0; i < element.children.length; i++) {
if (element.children[i] === containerElement) {
return null; // invalid plugin element overlay
}
}
return element.srcURI.spec;
}
function PdfRedirector() {
}
PdfRedirector.prototype = {
// properties required for XPCOM registration:
classID: Components.ID('{8cbfd8d0-2042-4976-b3ef-d9dee1efb975}'),
classDescription: 'pdf.js Redirector',
contractID:
'@mozilla.org/streamconv;1?from=application/x-moz-playpreview-pdfjs&to=*/*',
QueryInterface: XPCOMUtils.generateQI([
Ci.nsIStreamConverter,
Ci.nsIStreamListener,
Ci.nsIRequestObserver
]),
// nsIStreamConverter::convert
convert: function(aFromStream, aFromType, aToType, aCtxt) {
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
},
// nsIStreamConverter::asyncConvertData
asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
// Store the listener passed to us
this.listener = aListener;
},
// nsIStreamListener::onDataAvailable
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
// Do nothing since all the data loading is handled by the viewer.
},
// nsIRequestObserver::onStartRequest
onStartRequest: function(aRequest, aContext) {
// Setup the request so we can use it below.
aRequest.QueryInterface(Ci.nsIChannel);
// Cancel the request so the viewer can handle it.
aRequest.cancel(Cr.NS_BINDING_ABORTED);
var domWindow = getDOMWindow(aRequest);
var pdfUrl = getObjectUrl(domWindow);
if (!pdfUrl) {
Services.console.logStringMessage(
'PdfRedirector.js: PDF location is not specified for OBJECT/EMBED tag');
return;
}
// Create a new channel that is viewer loaded as a resource.
var ioService = Services.io;
var channel = ioService.newChannel(pdfUrl, null, null);
channel.loadGroup = aRequest.loadGroup;
channel.asyncOpen(this.listener, aContext);
},
// nsIRequestObserver::onStopRequest
onStopRequest: function(aRequest, aContext, aStatusCode) {
// Do nothing
}
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,344 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* 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.
*/
/* jshint esnext:true */
/* globals Components, Services, XPCOMUtils, DEFAULT_PREFERENCES */
'use strict';
var EXPORTED_SYMBOLS = ['PdfjsChromeUtils'];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
const PREF_PREFIX = 'PDFJSSCRIPT_PREF_PREFIX';
const PDF_CONTENT_TYPE = 'application/pdf';
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
let Svc = {};
XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
'@mozilla.org/mime;1',
'nsIMIMEService');
//#include ../../../web/default_preferences.js
let PdfjsChromeUtils = {
// For security purposes when running remote, we restrict preferences
// content can access.
_allowedPrefNames: Object.keys(DEFAULT_PREFERENCES),
_ppmm: null,
_mmg: null,
/*
* Public API
*/
init: function () {
this._browsers = new Set();
if (!this._ppmm) {
// global parent process message manager (PPMM)
this._ppmm = Cc['@mozilla.org/parentprocessmessagemanager;1'].
getService(Ci.nsIMessageBroadcaster);
this._ppmm.addMessageListener('PDFJS:Parent:clearUserPref', this);
this._ppmm.addMessageListener('PDFJS:Parent:setIntPref', this);
this._ppmm.addMessageListener('PDFJS:Parent:setBoolPref', this);
this._ppmm.addMessageListener('PDFJS:Parent:setCharPref', this);
this._ppmm.addMessageListener('PDFJS:Parent:setStringPref', this);
this._ppmm.addMessageListener('PDFJS:Parent:isDefaultHandlerApp', this);
// global dom message manager (MMg)
this._mmg = Cc['@mozilla.org/globalmessagemanager;1'].
getService(Ci.nsIMessageListenerManager);
this._mmg.addMessageListener('PDFJS:Parent:displayWarning', this);
this._mmg.addMessageListener('PDFJS:Parent:addEventListener', this);
this._mmg.addMessageListener('PDFJS:Parent:removeEventListener', this);
this._mmg.addMessageListener('PDFJS:Parent:updateControlState', this);
// observer to handle shutdown
Services.obs.addObserver(this, 'quit-application', false);
}
},
uninit: function () {
if (this._ppmm) {
this._ppmm.removeMessageListener('PDFJS:Parent:clearUserPref', this);
this._ppmm.removeMessageListener('PDFJS:Parent:setIntPref', this);
this._ppmm.removeMessageListener('PDFJS:Parent:setBoolPref', this);
this._ppmm.removeMessageListener('PDFJS:Parent:setCharPref', this);
this._ppmm.removeMessageListener('PDFJS:Parent:setStringPref', this);
this._ppmm.removeMessageListener('PDFJS:Parent:isDefaultHandlerApp',
this);
this._mmg.removeMessageListener('PDFJS:Parent:displayWarning', this);
this._mmg.removeMessageListener('PDFJS:Parent:addEventListener', this);
this._mmg.removeMessageListener('PDFJS:Parent:removeEventListener', this);
this._mmg.removeMessageListener('PDFJS:Parent:updateControlState', this);
Services.obs.removeObserver(this, 'quit-application', false);
this._mmg = null;
this._ppmm = null;
}
},
/*
* Called by the main module when preference changes are picked up
* in the parent process. Observers don't propagate so we need to
* instruct the child to refresh its configuration and (possibly)
* the module's registration.
*/
notifyChildOfSettingsChange: function () {
if (Services.appinfo.processType ===
Services.appinfo.PROCESS_TYPE_DEFAULT && this._ppmm) {
// XXX kinda bad, we want to get the parent process mm associated
// with the content process. _ppmm is currently the global 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
// process specific mm from js.
this._ppmm.broadcastAsyncMessage('PDFJS:Child:refreshSettings', {});
}
},
/*
* Events
*/
observe: function(aSubject, aTopic, aData) {
if (aTopic === 'quit-application') {
this.uninit();
}
},
receiveMessage: function (aMsg) {
switch (aMsg.name) {
case 'PDFJS:Parent:clearUserPref':
this._clearUserPref(aMsg.data.name);
break;
case 'PDFJS:Parent:setIntPref':
this._setIntPref(aMsg.data.name, aMsg.data.value);
break;
case 'PDFJS:Parent:setBoolPref':
this._setBoolPref(aMsg.data.name, aMsg.data.value);
break;
case 'PDFJS:Parent:setCharPref':
this._setCharPref(aMsg.data.name, aMsg.data.value);
break;
case 'PDFJS:Parent:setStringPref':
this._setStringPref(aMsg.data.name, aMsg.data.value);
break;
case 'PDFJS:Parent:isDefaultHandlerApp':
return this.isDefaultHandlerApp();
case 'PDFJS:Parent:displayWarning':
this._displayWarning(aMsg);
break;
case 'PDFJS:Parent:updateControlState':
return this._updateControlState(aMsg);
case 'PDFJS:Parent:addEventListener':
return this._addEventListener(aMsg);
case 'PDFJS:Parent:removeEventListener':
return this._removeEventListener(aMsg);
}
},
/*
* Internal
*/
_findbarFromMessage: function(aMsg) {
let browser = aMsg.target;
let tabbrowser = browser.getTabBrowser();
let tab;
//#if MOZCENTRAL
tab = tabbrowser.getTabForBrowser(browser);
//#else
if (tabbrowser.getTabForBrowser) {
tab = tabbrowser.getTabForBrowser(browser);
} else {
// _getTabForBrowser is deprecated in Firefox 35, see
// https://bugzilla.mozilla.org/show_bug.cgi?id=1039500.
tab = tabbrowser._getTabForBrowser(browser);
}
//#endif
return tabbrowser.getFindBar(tab);
},
_updateControlState: function (aMsg) {
let data = aMsg.data;
this._findbarFromMessage(aMsg)
.updateControlState(data.result, data.findPrevious);
},
handleEvent: function(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;
let detail = {
query: aEvent.detail.query,
caseSensitive: aEvent.detail.caseSensitive,
highlightAll: aEvent.detail.highlightAll,
findPrevious: aEvent.detail.findPrevious
};
let browser = aEvent.currentTarget.browser;
if (!this._browsers.has(browser)) {
throw new Error('FindEventManager was not bound ' +
'for the current browser.');
}
// 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 });
aEvent.preventDefault();
},
_types: ['find',
'findagain',
'findhighlightallchange',
'findcasesensitivitychange'],
_addEventListener: function (aMsg) {
let browser = aMsg.target;
if (this._browsers.has(browser)) {
throw new Error('FindEventManager was bound 2nd time ' +
'without unbinding it first.');
}
// Since this jsm is global, we need to store all the browsers
// we have to forward the messages for.
this._browsers.add(browser);
// And we need to start listening to find events.
for (var i = 0; i < this._types.length; i++) {
var type = this._types[i];
this._findbarFromMessage(aMsg)
.addEventListener(type, this, true);
}
},
_removeEventListener: function (aMsg) {
let browser = aMsg.target;
if (!this._browsers.has(browser)) {
throw new Error('FindEventManager was unbound without binding it first.');
}
this._browsers.delete(browser);
// No reason to listen to find events any longer.
for (var i = 0; i < this._types.length; i++) {
var type = this._types[i];
this._findbarFromMessage(aMsg)
.removeEventListener(type, this, true);
}
},
_ensurePreferenceAllowed: function (aPrefName) {
let unPrefixedName = aPrefName.split(PREF_PREFIX + '.');
if (unPrefixedName[0] !== '' ||
this._allowedPrefNames.indexOf(unPrefixedName[1]) === -1) {
let msg = '"' + aPrefName + '" ' +
'can\'t be accessed from content. See PdfjsChromeUtils.';
throw new Error(msg);
}
},
_clearUserPref: function (aPrefName) {
this._ensurePreferenceAllowed(aPrefName);
Services.prefs.clearUserPref(aPrefName);
},
_setIntPref: function (aPrefName, aPrefValue) {
this._ensurePreferenceAllowed(aPrefName);
Services.prefs.setIntPref(aPrefName, aPrefValue);
},
_setBoolPref: function (aPrefName, aPrefValue) {
this._ensurePreferenceAllowed(aPrefName);
Services.prefs.setBoolPref(aPrefName, aPrefValue);
},
_setCharPref: function (aPrefName, aPrefValue) {
this._ensurePreferenceAllowed(aPrefName);
Services.prefs.setCharPref(aPrefName, aPrefValue);
},
_setStringPref: function (aPrefName, aPrefValue) {
this._ensurePreferenceAllowed(aPrefName);
let str = Cc['@mozilla.org/supports-string;1']
.createInstance(Ci.nsISupportsString);
str.data = aPrefValue;
Services.prefs.setComplexValue(aPrefName, Ci.nsISupportsString, str);
},
/*
* Svc.mime doesn't have profile information in the child, so
* we bounce this pdfjs enabled configuration check over to the
* parent.
*/
isDefaultHandlerApp: function () {
var handlerInfo = Svc.mime.getFromTypeAndExtension(PDF_CONTENT_TYPE, 'pdf');
return (!handlerInfo.alwaysAskBeforeHandling &&
handlerInfo.preferredAction === Ci.nsIHandlerInfo.handleInternally);
},
/*
* Display a notification warning when the renderer isn't sure
* a pdf displayed correctly.
*/
_displayWarning: function (aMsg) {
let json = aMsg.data;
let browser = aMsg.target;
let cpowCallback = aMsg.objects.callback;
let tabbrowser = browser.getTabBrowser();
let notificationBox = tabbrowser.getNotificationBox(browser);
// Flag so we don't call the response callback twice, since if the user
// clicks open with different viewer both the button callback and
// eventCallback will be called.
let responseSent = false;
let buttons = [{
label: json.label,
accessKey: json.accessKey,
callback: function() {
responseSent = true;
cpowCallback(true);
}
}];
notificationBox.appendNotification(json.message, 'pdfjs-fallback', null,
notificationBox.PRIORITY_INFO_LOW,
buttons,
function eventsCallback(eventType) {
// 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.
if (eventType !== 'removed') {
return;
}
// Don't send a response again if we already responded when the button was
// clicked.
if (responseSent) {
return;
}
cpowCallback(false);
});
}
};

View File

@ -0,0 +1,153 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* 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.
*/
/* jshint esnext:true */
/* globals Components, Services, XPCOMUtils */
'use strict';
var EXPORTED_SYMBOLS = ['PdfjsContentUtils'];
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
let PdfjsContentUtils = {
_mm: null,
/*
* Public API
*/
get isRemote() {
return (Services.appinfo.processType ===
Services.appinfo.PROCESS_TYPE_CONTENT);
},
init: function () {
// child *process* mm, or when loaded into the parent for in-content
// support the psuedo child process mm 'child PPMM'.
if (!this._mm) {
this._mm = Cc['@mozilla.org/childprocessmessagemanager;1'].
getService(Ci.nsISyncMessageSender);
this._mm.addMessageListener('PDFJS:Child:refreshSettings', this);
Services.obs.addObserver(this, 'quit-application', false);
}
},
uninit: function () {
if (this._mm) {
this._mm.removeMessageListener('PDFJS:Child:refreshSettings', this);
Services.obs.removeObserver(this, 'quit-application');
}
this._mm = null;
},
/*
* prefs utilities - the child does not have write access to prefs.
* note, the pref names here are cross-checked against a list of
* approved pdfjs prefs in chrome utils.
*/
clearUserPref: function (aPrefName) {
this._mm.sendSyncMessage('PDFJS:Parent:clearUserPref', {
name: aPrefName
});
},
setIntPref: function (aPrefName, aPrefValue) {
this._mm.sendSyncMessage('PDFJS:Parent:setIntPref', {
name: aPrefName,
value: aPrefValue
});
},
setBoolPref: function (aPrefName, aPrefValue) {
this._mm.sendSyncMessage('PDFJS:Parent:setBoolPref', {
name: aPrefName,
value: aPrefValue
});
},
setCharPref: function (aPrefName, aPrefValue) {
this._mm.sendSyncMessage('PDFJS:Parent:setCharPref', {
name: aPrefName,
value: aPrefValue
});
},
setStringPref: function (aPrefName, aPrefValue) {
this._mm.sendSyncMessage('PDFJS:Parent:setStringPref', {
name: aPrefName,
value: aPrefValue
});
},
/*
* Forwards default app query to the parent where we check various
* handler app settings only available in the parent process.
*/
isDefaultHandlerApp: function () {
return this._mm.sendSyncMessage('PDFJS:Parent:isDefaultHandlerApp')[0];
},
/*
* 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, aCallback, aLabel, accessKey) {
// the child's dom frame mm associated with the window.
let winmm = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDocShell)
.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIContentFrameMessageManager);
winmm.sendAsyncMessage('PDFJS:Parent:displayWarning', {
message: aMessage,
label: aLabel,
accessKey: accessKey
}, {
callback: aCallback
});
},
/*
* Events
*/
observe: function(aSubject, aTopic, aData) {
if (aTopic === 'quit-application') {
this.uninit();
}
},
receiveMessage: function (aMsg) {
switch (aMsg.name) {
case 'PDFJS:Child:refreshSettings':
// Only react to this if we are remote.
if (Services.appinfo.processType ===
Services.appinfo.PROCESS_TYPE_CONTENT) {
let jsm = 'resource://pdf.js/PdfJs.jsm';
let pdfjs = Components.utils.import(jsm, {}).PdfJs;
pdfjs.updateRegistration();
}
break;
}
}
};

View File

@ -0,0 +1,37 @@
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
/* Copyright 2014 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.
*/
/* jshint esnext:true */
/* globals Components, PdfjsContentUtils, PdfJs, Services */
'use strict';
/*
* pdfjschildbootstrap.js loads into the content process to take care of
* initializing our built-in version of pdfjs when running remote.
*/
Components.utils.import('resource://gre/modules/Services.jsm');
Components.utils.import('resource://pdf.js/PdfJs.jsm');
Components.utils.import('resource://pdf.js/PdfjsContentUtils.jsm');
// init content utils shim pdfjs will use to access privileged apis.
PdfjsContentUtils.init();
if (Services.appinfo.processType === Services.appinfo.PROCESS_TYPE_CONTENT) {
// register various pdfjs factories that hook us into content loading.
PdfJs.updateRegistration();
}