зеркало из https://github.com/mozilla/gecko-dev.git
Bug 752676: Add pdf.js as an internal handler for pdfjs (1/2); r=mak77
This commit is contained in:
Родитель
629833639f
Коммит
84b2bdb784
|
@ -1160,6 +1160,18 @@ pref("full-screen-api.approval-required", true);
|
|||
// (this pref has no effect if more than 6 hours have passed since the last crash)
|
||||
pref("toolkit.startup.max_resumed_crashes", 3);
|
||||
|
||||
// Completely disable pdf.js as an option to preview pdfs within firefox.
|
||||
// Note: if this is not disabled it does not necessarily mean pdf.js is the pdf
|
||||
// handler just that it is an option.
|
||||
pref("pdfjs.disabled", false);
|
||||
// Used by pdf.js to know the first time firefox is run with it installed so it
|
||||
// can become the default pdf viewer.
|
||||
pref("pdfjs.firstRun", true);
|
||||
// The values of preferredAction and alwaysAskBeforeHandling before pdf.js
|
||||
// became the default.
|
||||
pref("pdfjs.previousHandler.preferredAction", 0);
|
||||
pref("pdfjs.previousHandler.alwaysAskBeforeHandling", false);
|
||||
|
||||
// The maximum amount of decoded image data we'll willingly keep around (we
|
||||
// might keep around more than this, but we'll try to get down to this value).
|
||||
// (This is intentionally on the high side; see bug 746055.)
|
||||
|
|
|
@ -31,6 +31,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "webappsUI",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs",
|
||||
"resource:///modules/PageThumbs.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "PdfJs",
|
||||
"resource://pdf.js/PdfJs.jsm");
|
||||
|
||||
const PREF_PLUGINS_NOTIFYUSER = "plugins.update.notifyUser";
|
||||
const PREF_PLUGINS_UPDATEURL = "plugins.update.url";
|
||||
|
||||
|
@ -329,6 +332,8 @@ BrowserGlue.prototype = {
|
|||
|
||||
PageThumbs.init();
|
||||
|
||||
PdfJs.init();
|
||||
|
||||
Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
|
||||
},
|
||||
|
||||
|
|
|
@ -17,10 +17,15 @@ var Cr = Components.results;
|
|||
/*
|
||||
#endif
|
||||
*/
|
||||
Components.utils.import('resource://gre/modules/Services.jsm');
|
||||
|
||||
const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
|
||||
const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
|
||||
const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
|
||||
const TYPE_PDF = "application/pdf";
|
||||
|
||||
const PREF_PDFJS_DISABLED = "pdfjs.disabled";
|
||||
const TOPIC_PDFJS_HANDLER_CHANGED = "pdfjs:handlerChanged";
|
||||
|
||||
const PREF_DISABLED_PLUGIN_TYPES = "plugin.disable_full_page_plugin_for_types";
|
||||
|
||||
|
@ -810,6 +815,46 @@ var audioFeedHandlerInfo = {
|
|||
_appPrefLabel: "audioPodcastFeed"
|
||||
}
|
||||
|
||||
/**
|
||||
* InternalHandlerInfoWrapper provides a basic mechanism to create an internal
|
||||
* mime type handler that can be enabled/disabled in the applications preference
|
||||
* menu.
|
||||
*/
|
||||
function InternalHandlerInfoWrapper(aMIMEType) {
|
||||
var mimeSvc = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
|
||||
var handlerInfo = mimeSvc.getFromTypeAndExtension(aMIMEType, null);
|
||||
|
||||
HandlerInfoWrapper.call(this, aMIMEType, handlerInfo);
|
||||
}
|
||||
|
||||
InternalHandlerInfoWrapper.prototype = {
|
||||
__proto__: HandlerInfoWrapper.prototype,
|
||||
|
||||
// Override store so we so we can notify any code listening for registration
|
||||
// or unregistration of this handler.
|
||||
store: function() {
|
||||
HandlerInfoWrapper.prototype.store.call(this);
|
||||
Services.obs.notifyObservers(null, this._handlerChanged, null);
|
||||
},
|
||||
|
||||
get enabled() {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
get description() {
|
||||
return this.element("bundlePreferences").getString(this._appPrefLabel);
|
||||
}
|
||||
};
|
||||
|
||||
var pdfHandlerInfo = {
|
||||
__proto__: new InternalHandlerInfoWrapper(TYPE_PDF),
|
||||
_handlerChanged: TOPIC_PDFJS_HANDLER_CHANGED,
|
||||
_appPrefLabel: "portableDocumentFormat",
|
||||
get enabled() {
|
||||
return !Services.prefs.getBoolPref(PREF_PDFJS_DISABLED);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
//****************************************************************************//
|
||||
// Prefpane Controller
|
||||
|
@ -999,6 +1044,7 @@ var gApplicationsPane = {
|
|||
|
||||
_loadData: function() {
|
||||
this._loadFeedHandler();
|
||||
this._loadInternalHandlers();
|
||||
this._loadPluginHandlers();
|
||||
this._loadApplicationHandlers();
|
||||
},
|
||||
|
@ -1014,6 +1060,19 @@ var gApplicationsPane = {
|
|||
audioFeedHandlerInfo.handledOnlyByPlugin = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Load higher level internal handlers so they can be turned on/off in the
|
||||
* applications menu.
|
||||
*/
|
||||
_loadInternalHandlers: function() {
|
||||
var internalHandlers = [pdfHandlerInfo];
|
||||
for (let internalHandler of internalHandlers) {
|
||||
if (internalHandler.enabled) {
|
||||
this._handledTypes[internalHandler.type] = internalHandler;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Load the set of handlers defined by plugins.
|
||||
*
|
||||
|
@ -1216,9 +1275,15 @@ var gApplicationsPane = {
|
|||
|
||||
case Ci.nsIHandlerInfo.handleInternally:
|
||||
// For the feed type, handleInternally means live bookmarks.
|
||||
if (isFeedType(aHandlerInfo.type))
|
||||
if (isFeedType(aHandlerInfo.type)) {
|
||||
return this._prefsBundle.getFormattedString("addLiveBookmarksInApp",
|
||||
[this._brandShortName]);
|
||||
}
|
||||
|
||||
if (aHandlerInfo instanceof InternalHandlerInfoWrapper) {
|
||||
return this._prefsBundle.getFormattedString("previewInApp",
|
||||
[this._brandShortName]);
|
||||
}
|
||||
|
||||
// For other types, handleInternally looks like either useHelperApp
|
||||
// or useSystemDefault depending on whether or not there's a preferred
|
||||
|
@ -1319,6 +1384,18 @@ var gApplicationsPane = {
|
|||
while (menuPopup.hasChildNodes())
|
||||
menuPopup.removeChild(menuPopup.lastChild);
|
||||
|
||||
// Add the "Preview in Firefox" option for optional internal handlers.
|
||||
if (handlerInfo instanceof InternalHandlerInfoWrapper) {
|
||||
var internalMenuItem = document.createElement("menuitem");
|
||||
internalMenuItem.setAttribute("action", Ci.nsIHandlerInfo.handleInternally);
|
||||
let label = this._prefsBundle.getFormattedString("previewInApp",
|
||||
[this._brandShortName]);
|
||||
internalMenuItem.setAttribute("label", label);
|
||||
internalMenuItem.setAttribute("tooltiptext", label);
|
||||
internalMenuItem.setAttribute(APP_ICON_ATTR_NAME, "ask");
|
||||
menuPopup.appendChild(internalMenuItem);
|
||||
}
|
||||
|
||||
{
|
||||
var askMenuItem = document.createElement("menuitem");
|
||||
askMenuItem.setAttribute("alwaysAsk", "true");
|
||||
|
@ -1739,6 +1816,9 @@ var gApplicationsPane = {
|
|||
if (isFeedType(aHandlerInfo.type)) {
|
||||
aElement.setAttribute(APP_ICON_ATTR_NAME, "feed");
|
||||
return true;
|
||||
} else if (aHandlerInfo instanceof InternalHandlerInfoWrapper) {
|
||||
aElement.setAttribute(APP_ICON_ATTR_NAME, "ask");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -5,9 +5,14 @@
|
|||
//****************************************************************************//
|
||||
// Constants & Enumeration Values
|
||||
|
||||
Components.utils.import('resource://gre/modules/Services.jsm');
|
||||
const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
|
||||
const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
|
||||
const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
|
||||
const TYPE_PDF = "application/pdf";
|
||||
|
||||
const PREF_PDFJS_DISABLED = "pdfjs.disabled";
|
||||
const TOPIC_PDFJS_HANDLER_CHANGED = "pdfjs:handlerChanged";
|
||||
|
||||
const PREF_DISABLED_PLUGIN_TYPES = "plugin.disable_full_page_plugin_for_types";
|
||||
|
||||
|
@ -797,6 +802,46 @@ var audioFeedHandlerInfo = {
|
|||
_appPrefLabel: "audioPodcastFeed"
|
||||
}
|
||||
|
||||
/**
|
||||
* InternalHandlerInfoWrapper provides a basic mechanism to create an internal
|
||||
* mime type handler that can be enabled/disabled in the applications preference
|
||||
* menu.
|
||||
*/
|
||||
function InternalHandlerInfoWrapper(aMIMEType) {
|
||||
var mimeSvc = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
|
||||
var handlerInfo = mimeSvc.getFromTypeAndExtension(aMIMEType, null);
|
||||
|
||||
HandlerInfoWrapper.call(this, aMIMEType, handlerInfo);
|
||||
}
|
||||
|
||||
InternalHandlerInfoWrapper.prototype = {
|
||||
__proto__: HandlerInfoWrapper.prototype,
|
||||
|
||||
// Override store so we so we can notify any code listening for registration
|
||||
// or unregistration of this handler.
|
||||
store: function() {
|
||||
HandlerInfoWrapper.prototype.store.call(this);
|
||||
Services.obs.notifyObservers(null, this._handlerChanged, null);
|
||||
},
|
||||
|
||||
get enabled() {
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
},
|
||||
|
||||
get description() {
|
||||
return this.element("bundlePreferences").getString(this._appPrefLabel);
|
||||
}
|
||||
};
|
||||
|
||||
var pdfHandlerInfo = {
|
||||
__proto__: new InternalHandlerInfoWrapper(TYPE_PDF),
|
||||
_handlerChanged: TOPIC_PDFJS_HANDLER_CHANGED,
|
||||
_appPrefLabel: "portableDocumentFormat",
|
||||
get enabled() {
|
||||
return !Services.prefs.getBoolPref(PREF_PDFJS_DISABLED);
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
//****************************************************************************//
|
||||
// Prefpane Controller
|
||||
|
@ -986,6 +1031,7 @@ var gApplicationsPane = {
|
|||
|
||||
_loadData: function() {
|
||||
this._loadFeedHandler();
|
||||
this._loadInternalHandlers();
|
||||
this._loadPluginHandlers();
|
||||
this._loadApplicationHandlers();
|
||||
},
|
||||
|
@ -1001,6 +1047,19 @@ var gApplicationsPane = {
|
|||
audioFeedHandlerInfo.handledOnlyByPlugin = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Load higher level internal handlers so they can be turned on/off in the
|
||||
* applications menu.
|
||||
*/
|
||||
_loadInternalHandlers: function() {
|
||||
var internalHandlers = [pdfHandlerInfo];
|
||||
for (let internalHandler of internalHandlers) {
|
||||
if (internalHandler.enabled) {
|
||||
this._handledTypes[internalHandler.type] = internalHandler;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Load the set of handlers defined by plugins.
|
||||
*
|
||||
|
@ -1203,9 +1262,15 @@ var gApplicationsPane = {
|
|||
|
||||
case Ci.nsIHandlerInfo.handleInternally:
|
||||
// For the feed type, handleInternally means live bookmarks.
|
||||
if (isFeedType(aHandlerInfo.type))
|
||||
if (isFeedType(aHandlerInfo.type)) {
|
||||
return this._prefsBundle.getFormattedString("addLiveBookmarksInApp",
|
||||
[this._brandShortName]);
|
||||
}
|
||||
|
||||
if (aHandlerInfo instanceof InternalHandlerInfoWrapper) {
|
||||
return this._prefsBundle.getFormattedString("previewInApp",
|
||||
[this._brandShortName]);
|
||||
}
|
||||
|
||||
// For other types, handleInternally looks like either useHelperApp
|
||||
// or useSystemDefault depending on whether or not there's a preferred
|
||||
|
@ -1306,6 +1371,18 @@ var gApplicationsPane = {
|
|||
while (menuPopup.hasChildNodes())
|
||||
menuPopup.removeChild(menuPopup.lastChild);
|
||||
|
||||
// Add the "Preview in Firefox" option for optional internal handlers.
|
||||
if (handlerInfo instanceof InternalHandlerInfoWrapper) {
|
||||
var internalMenuItem = document.createElement("menuitem");
|
||||
internalMenuItem.setAttribute("action", Ci.nsIHandlerInfo.handleInternally);
|
||||
let label = this._prefsBundle.getFormattedString("previewInApp",
|
||||
[this._brandShortName]);
|
||||
internalMenuItem.setAttribute("label", label);
|
||||
internalMenuItem.setAttribute("tooltiptext", label);
|
||||
internalMenuItem.setAttribute(APP_ICON_ATTR_NAME, "ask");
|
||||
menuPopup.appendChild(internalMenuItem);
|
||||
}
|
||||
|
||||
{
|
||||
var askMenuItem = document.createElement("menuitem");
|
||||
askMenuItem.setAttribute("alwaysAsk", "true");
|
||||
|
@ -1726,6 +1803,9 @@ var gApplicationsPane = {
|
|||
if (isFeedType(aHandlerInfo.type)) {
|
||||
aElement.setAttribute(APP_ICON_ATTR_NAME, "feed");
|
||||
return true;
|
||||
} else if (aHandlerInfo instanceof InternalHandlerInfoWrapper) {
|
||||
aElement.setAttribute(APP_ICON_ATTR_NAME, "ask");
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
This is the pdf.js project output, https://github.com/mozilla/pdf.js
|
||||
|
||||
Current extension version is: 0.3.266
|
||||
Current extension version is: 0.3.345
|
||||
|
||||
|
|
|
@ -9,9 +9,11 @@ const Cc = Components.classes;
|
|||
const Ci = Components.interfaces;
|
||||
const Cr = Components.results;
|
||||
const Cu = Components.utils;
|
||||
// True only if this is the version of pdf.js that is included with firefox.
|
||||
const MOZ_CENTRAL = true;
|
||||
const PDFJS_EVENT_ID = 'pdf.js.message';
|
||||
const PDF_CONTENT_TYPE = 'application/pdf';
|
||||
const EXT_PREFIX = 'extensions.uriloader@pdf.js';
|
||||
const PREF_PREFIX = 'pdfjs';
|
||||
const MAX_DATABASE_LENGTH = 4096;
|
||||
const FIREFOX_ID = '{ec8030f7-c20a-464f-9b0e-13a3a9e97384}';
|
||||
const SEAMONKEY_ID = '{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}';
|
||||
|
@ -20,9 +22,14 @@ Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
|||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
Cu.import('resource://gre/modules/NetUtil.jsm');
|
||||
|
||||
|
||||
let appInfo = Cc['@mozilla.org/xre/app-info;1']
|
||||
.getService(Ci.nsIXULAppInfo);
|
||||
let privateBrowsing, inPrivateBrowsing;
|
||||
let Svc = {};
|
||||
XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
|
||||
'@mozilla.org/mime;1',
|
||||
'nsIMIMEService');
|
||||
|
||||
if (appInfo.ID === FIREFOX_ID) {
|
||||
privateBrowsing = Cc['@mozilla.org/privatebrowsing;1']
|
||||
|
@ -57,7 +64,7 @@ function getStringPref(pref, def) {
|
|||
}
|
||||
|
||||
function log(aMsg) {
|
||||
if (!getBoolPref(EXT_PREFIX + '.pdfBugEnabled', false))
|
||||
if (!getBoolPref(PREF_PREFIX + '.pdfBugEnabled', false))
|
||||
return;
|
||||
let msg = 'PdfStreamConverter.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
|
||||
Services.console.logStringMessage(msg);
|
||||
|
@ -70,6 +77,23 @@ function getDOMWindow(aChannel) {
|
|||
return win;
|
||||
}
|
||||
|
||||
function isEnabled() {
|
||||
if (MOZ_CENTRAL) {
|
||||
var disabled = getBoolPref(PREF_PREFIX + '.disabled', false);
|
||||
if (disabled)
|
||||
return false;
|
||||
// To also be considered enabled the "Preview in Firefox" option must be
|
||||
// selected in the Application preferences.
|
||||
var handlerInfo = Svc.mime
|
||||
.getFromTypeAndExtension('application/pdf', 'pdf');
|
||||
return handlerInfo.alwaysAskBeforeHandling == false &&
|
||||
handlerInfo.preferredAction == Ci.nsIHandlerInfo.handleInternally;
|
||||
}
|
||||
// Always returns true for the extension since enabling/disabling is handled
|
||||
// by the add-on manager.
|
||||
return true;
|
||||
}
|
||||
|
||||
function getLocalizedStrings(path) {
|
||||
var stringBundle = Cc['@mozilla.org/intl/stringbundle;1'].
|
||||
getService(Ci.nsIStringBundleService).
|
||||
|
@ -91,16 +115,22 @@ function getLocalizedStrings(path) {
|
|||
}
|
||||
return map;
|
||||
}
|
||||
function getLocalizedString(strings, id, property) {
|
||||
property = property || 'textContent';
|
||||
if (id in strings)
|
||||
return strings[id][property];
|
||||
return id;
|
||||
}
|
||||
|
||||
// All the priviledged actions.
|
||||
function ChromeActions() {
|
||||
function ChromeActions(domWindow) {
|
||||
this.domWindow = domWindow;
|
||||
}
|
||||
|
||||
ChromeActions.prototype = {
|
||||
download: function(data) {
|
||||
let mimeService = Cc['@mozilla.org/mime;1'].getService(Ci.nsIMIMEService);
|
||||
var handlerInfo = mimeService.
|
||||
getFromTypeAndExtension('application/pdf', 'pdf');
|
||||
var handlerInfo = Svc.mime
|
||||
.getFromTypeAndExtension('application/pdf', 'pdf');
|
||||
var uri = NetUtil.newURI(data);
|
||||
|
||||
var extHelperAppSvc =
|
||||
|
@ -136,12 +166,12 @@ ChromeActions.prototype = {
|
|||
// Protect against something sending tons of data to setDatabase.
|
||||
if (data.length > MAX_DATABASE_LENGTH)
|
||||
return;
|
||||
setStringPref(EXT_PREFIX + '.database', data);
|
||||
setStringPref(PREF_PREFIX + '.database', data);
|
||||
},
|
||||
getDatabase: function() {
|
||||
if (inPrivateBrowsing)
|
||||
return '{}';
|
||||
return getStringPref(EXT_PREFIX + '.database', '{}');
|
||||
return getStringPref(PREF_PREFIX + '.database', '{}');
|
||||
},
|
||||
getLocale: function() {
|
||||
return getStringPref('general.useragent.locale', 'en-US');
|
||||
|
@ -160,11 +190,34 @@ ChromeActions.prototype = {
|
|||
}
|
||||
},
|
||||
pdfBugEnabled: function() {
|
||||
return getBoolPref(EXT_PREFIX + '.pdfBugEnabled', false);
|
||||
return getBoolPref(PREF_PREFIX + '.pdfBugEnabled', false);
|
||||
},
|
||||
searchEnabled: function() {
|
||||
return getBoolPref(PREF_PREFIX + '.searchEnabled', false);
|
||||
},
|
||||
fallback: function(url) {
|
||||
var self = this;
|
||||
var domWindow = this.domWindow;
|
||||
var strings = getLocalizedStrings('chrome.properties');
|
||||
var message = getLocalizedString(strings, 'unsupported_feature');
|
||||
|
||||
var win = Services.wm.getMostRecentWindow('navigator:browser');
|
||||
var browser = win.gBrowser.getBrowserForDocument(domWindow.top.document);
|
||||
var notificationBox = win.gBrowser.getNotificationBox(browser);
|
||||
var buttons = [{
|
||||
label: getLocalizedString(strings, 'open_with_different_viewer'),
|
||||
accessKey: getLocalizedString(strings, 'open_with_different_viewer',
|
||||
'accessKey'),
|
||||
callback: function() {
|
||||
self.download(url);
|
||||
}
|
||||
}];
|
||||
notificationBox.appendNotification(message, 'pdfjs-fallback', null,
|
||||
notificationBox.PRIORITY_WARNING_LOW,
|
||||
buttons);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Event listener to trigger chrome privedged code.
|
||||
function RequestListener(actions) {
|
||||
this.actions = actions;
|
||||
|
@ -190,7 +243,7 @@ function PdfStreamConverter() {
|
|||
PdfStreamConverter.prototype = {
|
||||
|
||||
// properties required for XPCOM registration:
|
||||
classID: Components.ID('{6457a96b-2d68-439a-bcfa-44465fbcdbb1}'),
|
||||
classID: Components.ID('{d0c5195d-e798-49d4-b1d3-9324328b2291}'),
|
||||
classDescription: 'pdf.js Component',
|
||||
contractID: '@mozilla.org/streamconv;1?from=application/pdf&to=*/*',
|
||||
|
||||
|
@ -218,6 +271,8 @@ PdfStreamConverter.prototype = {
|
|||
|
||||
// nsIStreamConverter::asyncConvertData
|
||||
asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
|
||||
if (!isEnabled())
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
// Ignoring HTTP POST requests -- pdf.js has to repeat the request.
|
||||
var skipConversion = false;
|
||||
try {
|
||||
|
@ -267,7 +322,8 @@ PdfStreamConverter.prototype = {
|
|||
var domWindow = getDOMWindow(channel);
|
||||
// Double check the url is still the correct one.
|
||||
if (domWindow.document.documentURIObject.equals(aRequest.URI)) {
|
||||
let requestListener = new RequestListener(new ChromeActions);
|
||||
let requestListener = new RequestListener(
|
||||
new ChromeActions(domWindow));
|
||||
domWindow.addEventListener(PDFJS_EVENT_ID, function(event) {
|
||||
requestListener.receive(event);
|
||||
}, false, true);
|
||||
|
|
|
@ -0,0 +1,142 @@
|
|||
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_FIRST_RUN = PREF_PREFIX + '.firstRun';
|
||||
const PREF_PREVIOUS_ACTION = PREF_PREFIX + '.previousHandler.preferredAction';
|
||||
const PREF_PREVIOUS_ASK = PREF_PREFIX + '.previousHandler.alwaysAskBeforeHandling';
|
||||
const TOPIC_PDFJS_HANDLER_CHANGED = 'pdfjs:handlerChanged';
|
||||
|
||||
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
||||
Cu.import('resource://gre/modules/Services.jsm');
|
||||
Cu.import('resource://pdf.js.components/PdfStreamConverter.js');
|
||||
|
||||
let Svc = {};
|
||||
XPCOMUtils.defineLazyServiceGetter(Svc, 'mime',
|
||||
'@mozilla.org/mime;1',
|
||||
'nsIMIMEService');
|
||||
|
||||
function getBoolPref(aPref, aDefaultValue) {
|
||||
try {
|
||||
return Services.prefs.getBoolPref(aPref);
|
||||
} catch (ex) {
|
||||
return aDefaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
// Register/unregister a constructor as a component.
|
||||
let Factory = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]),
|
||||
_targetConstructor: null,
|
||||
|
||||
register: function register(targetConstructor) {
|
||||
this._targetConstructor = targetConstructor;
|
||||
var proto = targetConstructor.prototype;
|
||||
var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
registrar.registerFactory(proto.classID, proto.classDescription,
|
||||
proto.contractID, this);
|
||||
},
|
||||
|
||||
unregister: function unregister() {
|
||||
var proto = this._targetConstructor.prototype;
|
||||
var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
|
||||
registrar.unregisterFactory(proto.classID, this);
|
||||
this._targetConstructor = null;
|
||||
},
|
||||
|
||||
// nsIFactory
|
||||
createInstance: function createInstance(aOuter, iid) {
|
||||
if (aOuter !== null)
|
||||
throw Cr.NS_ERROR_NO_AGGREGATION;
|
||||
return (new (this._targetConstructor)).QueryInterface(iid);
|
||||
},
|
||||
|
||||
// nsIFactory
|
||||
lockFactory: function lockFactory(lock) {
|
||||
// No longer used as of gecko 1.7.
|
||||
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
};
|
||||
|
||||
let PdfJs = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver]),
|
||||
_registered: false,
|
||||
|
||||
init: function init() {
|
||||
// On first run make pdf.js the default handler.
|
||||
if (!getBoolPref(PREF_DISABLED, true) && getBoolPref(PREF_FIRST_RUN, false)) {
|
||||
Services.prefs.setBoolPref(PREF_FIRST_RUN, false);
|
||||
|
||||
let handlerInfo = Svc.mime.getFromTypeAndExtension('application/pdf', 'pdf');
|
||||
// Store the previous settings of preferredAction and
|
||||
// alwaysAskBeforeHandling in case we need to revert them in a hotfix that
|
||||
// would turn pdf.js off.
|
||||
Services.prefs.setIntPref(PREF_PREVIOUS_ACTION, handlerInfo.preferredAction);
|
||||
Services.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);
|
||||
}
|
||||
|
||||
if (this.enabled)
|
||||
this._ensureRegistered();
|
||||
else
|
||||
this._ensureUnregistered();
|
||||
|
||||
// Listen for when pdf.js is completely disabled or a different pdf handler
|
||||
// is chosen.
|
||||
Services.prefs.addObserver(PREF_DISABLED, this, false);
|
||||
Services.obs.addObserver(this, TOPIC_PDFJS_HANDLER_CHANGED, false);
|
||||
},
|
||||
|
||||
// nsIObserver
|
||||
observe: function observe(aSubject, aTopic, aData) {
|
||||
if (this.enabled)
|
||||
this._ensureRegistered();
|
||||
else
|
||||
this._ensureUnregistered();
|
||||
},
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
var handlerInfo = Svc.mime.
|
||||
getFromTypeAndExtension('application/pdf', 'pdf');
|
||||
return handlerInfo.alwaysAskBeforeHandling == false &&
|
||||
handlerInfo.preferredAction == Ci.nsIHandlerInfo.handleInternally;
|
||||
},
|
||||
|
||||
_ensureRegistered: function _ensureRegistered() {
|
||||
if (this._registered)
|
||||
return;
|
||||
|
||||
Factory.register(PdfStreamConverter);
|
||||
this._registered = true;
|
||||
},
|
||||
|
||||
_ensureUnregistered: function _ensureUnregistered() {
|
||||
if (!this._registered)
|
||||
return;
|
||||
|
||||
Factory.unregister();
|
||||
this._registered = false;
|
||||
}
|
||||
};
|
|
@ -22,7 +22,7 @@ var PDFJS = {};
|
|||
// Use strict in our context only - users might not want it
|
||||
'use strict';
|
||||
|
||||
PDFJS.build = '5ac7513';
|
||||
PDFJS.build = '121040a';
|
||||
|
||||
// Files are inserted below - see Makefile
|
||||
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const RELATIVE_DIR = "browser/extensions/pdfjs/test/";
|
||||
const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
|
||||
|
@ -8,6 +7,16 @@ const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
|
|||
function test() {
|
||||
var tab;
|
||||
|
||||
let handlerService = Cc["@mozilla.org/uriloader/handler-service;1"].getService(Ci.nsIHandlerService);
|
||||
let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
|
||||
let handlerInfo = mimeService.getFromTypeAndExtension('application/pdf', 'pdf');
|
||||
|
||||
// Make sure pdf.js is the default handler.
|
||||
is(handlerInfo.alwaysAskBeforeHandling, false, 'pdf handler defaults to always-ask is false');
|
||||
is(handlerInfo.preferredAction, Ci.nsIHandlerInfo.handleInternally, 'pdf handler defaults to internal');
|
||||
|
||||
info('Pref action: ' + handlerInfo.preferredAction);
|
||||
|
||||
waitForExplicitFinish();
|
||||
registerCleanupFunction(function() {
|
||||
gBrowser.removeTab(tab);
|
||||
|
@ -23,13 +32,14 @@ function test() {
|
|||
|
||||
// Runs tests after all 'load' event handlers have fired off
|
||||
setTimeout(function() {
|
||||
runTests(document, window);
|
||||
runTests(document, window, finish);
|
||||
}, 0);
|
||||
}, true);
|
||||
}
|
||||
|
||||
|
||||
function runTests(document, window) {
|
||||
function runTests(document, window, callback) {
|
||||
|
||||
//
|
||||
// Overall sanity tests
|
||||
//
|
||||
|
@ -67,5 +77,5 @@ function runTests(document, window) {
|
|||
viewBookmark.click();
|
||||
ok(viewBookmark.href.length > 0, 'viewBookmark button has href');
|
||||
|
||||
finish();
|
||||
callback();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const RELATIVE_DIR = "browser/extensions/pdfjs/test/";
|
||||
const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
|
||||
|
||||
function test() {
|
||||
var oldAction = changeMimeHandler(Ci.nsIHandlerInfo.useSystemDefault, true);
|
||||
var tab = gBrowser.addTab(TESTROOT + "file_pdfjs_test.pdf");
|
||||
//
|
||||
// Test: "Open with" dialog comes up when pdf.js is not selected as the default
|
||||
// handler.
|
||||
//
|
||||
addWindowListener('chrome://mozapps/content/downloads/unknownContentType.xul', finish);
|
||||
|
||||
waitForExplicitFinish();
|
||||
registerCleanupFunction(function() {
|
||||
changeMimeHandler(oldAction[0], oldAction[1]);
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
}
|
||||
|
||||
function changeMimeHandler(preferredAction, alwaysAskBeforeHandling) {
|
||||
let handlerService = Cc["@mozilla.org/uriloader/handler-service;1"].getService(Ci.nsIHandlerService);
|
||||
let mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
|
||||
let handlerInfo = mimeService.getFromTypeAndExtension('application/pdf', 'pdf');
|
||||
var oldAction = [handlerInfo.preferredAction, handlerInfo.alwaysAskBeforeHandling];
|
||||
|
||||
// Change and save mime handler settings
|
||||
handlerInfo.alwaysAskBeforeHandling = alwaysAskBeforeHandling;
|
||||
handlerInfo.preferredAction = preferredAction;
|
||||
handlerService.store(handlerInfo);
|
||||
|
||||
Services.obs.notifyObservers(null, 'pdfjs:handlerChanged', null);
|
||||
|
||||
// Refresh data
|
||||
handlerInfo = mimeService.getFromTypeAndExtension('application/pdf', 'pdf');
|
||||
|
||||
//
|
||||
// Test: Mime handler was updated
|
||||
//
|
||||
is(handlerInfo.alwaysAskBeforeHandling, alwaysAskBeforeHandling, 'always-ask prompt change successful');
|
||||
is(handlerInfo.preferredAction, preferredAction, 'mime handler change successful');
|
||||
|
||||
return oldAction;
|
||||
}
|
||||
|
||||
function addWindowListener(aURL, aCallback) {
|
||||
Services.wm.addListener({
|
||||
onOpenWindow: function(aXULWindow) {
|
||||
info("window opened, waiting for focus");
|
||||
Services.wm.removeListener(this);
|
||||
|
||||
var domwindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIDOMWindow);
|
||||
waitForFocus(function() {
|
||||
is(domwindow.document.location.href, aURL, "should have seen the right window open");
|
||||
domwindow.close();
|
||||
aCallback();
|
||||
}, domwindow);
|
||||
},
|
||||
onCloseWindow: function(aXULWindow) { },
|
||||
onWindowTitleChange: function(aXULWindow, aNewTitle) { }
|
||||
});
|
||||
}
|
|
@ -63,6 +63,7 @@ webFeed=Web Feed
|
|||
videoPodcastFeed=Video Podcast
|
||||
audioPodcastFeed=Podcast
|
||||
alwaysAsk=Always ask
|
||||
portableDocumentFormat=Portable Document Format (PDF)
|
||||
|
||||
# LOCALIZATION NOTE (usePluginIn):
|
||||
# %1$S = plugin name (for example "QuickTime Plugin-in 7.2")
|
||||
|
|
|
@ -489,7 +489,7 @@ HandlerService.prototype = {
|
|||
return Ci.nsIHandlerInfo.useSystemDefault;
|
||||
|
||||
if (this._getValue(aInfoID, NC_HANDLE_INTERNALLY) == "true")
|
||||
return Ci.nsIHandlerInfo.handleInternal;
|
||||
return Ci.nsIHandlerInfo.handleInternally;
|
||||
|
||||
return Ci.nsIHandlerInfo.useHelperApp;
|
||||
},
|
||||
|
|
Загрузка…
Ссылка в новой задаче