Add global pref to enable/disable. Control pdf.js in application preferences. Add Artur's mochi tests.

This commit is contained in:
Brendan Dahl 2012-05-31 11:16:06 -07:00
parent 2a9efa8acc
commit 3d7f01d9ca
8 changed files with 250 additions and 8 deletions

View File

@ -1,4 +1,3 @@
content/
metadata.inc
chrome.manifest.inc
locale/

View File

@ -1,3 +1,2 @@
resource pdf.js content/
component {d0c5195d-e798-49d4-b1d3-9324328b2291} components/PdfStreamConverter.js
contract @mozilla.org/streamconv;1?from=application/pdf&to=*/* {d0c5195d-e798-49d4-b1d3-9324328b2291}
resource pdf.js.components components/

View File

@ -9,6 +9,7 @@ const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
const Cu = Components.utils;
const MOZ_CENTRAL = PDFJSSCRIPT_MOZ_CENTRAL;
const PDFJS_EVENT_ID = 'pdf.js.message';
const PDF_CONTENT_TYPE = 'application/pdf';
const PREF_PREFIX = 'PDFJSSCRIPT_PREF_PREFIX';
@ -19,11 +20,12 @@ const SEAMONKEY_ID = '{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}';
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/NetUtil.jsm');
Cu.import('resource://gre/modules/AddonManager.jsm');
let appInfo = Cc['@mozilla.org/xre/app-info;1']
.getService(Ci.nsIXULAppInfo);
let privateBrowsing, inPrivateBrowsing;
let mimeService = Cc['@mozilla.org/mime;1']
.getService(Ci.nsIMIMEService);
if (appInfo.ID === FIREFOX_ID) {
privateBrowsing = Cc['@mozilla.org/privatebrowsing;1']
@ -71,6 +73,23 @@ function getDOMWindow(aChannel) {
return win;
}
function isEnabled() {
if (MOZ_CENTRAL) {
var enabled = getBoolPref(PREF_PREFIX + '.enabled', false);
if (!enabled)
return false;
// To also be considered enabled the "Preview in Firefox" option must be
// selected in the Application preferences.
var handlerInfo = mimeService.
getFromTypeAndExtension('application/pdf', 'pdf');
return handlerInfo && (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).
@ -248,6 +267,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 {

View File

@ -0,0 +1,105 @@
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_ENABLED = PREF_PREFIX + '.enabled';
const PDFJS_HANDLER_CHANGED = 'pdfjs:handlerChanged';
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://pdf.js.components/PdfStreamConverter.js');
let mimeService = Cc["@mozilla.org/mime;1"]
.getService(Ci.nsIMIMEService);
function getBoolPref(pref, def) {
try {
return Services.prefs.getBoolPref(pref);
} catch (ex) {
return def;
}
}
// Register/unregister a class as a component.
let Factory = {
registrar: null,
aClass: null,
register: function(aClass) {
if (this.aClass) {
dump('Cannot register more than one class');
return;
}
this.registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar);
this.aClass = aClass;
var proto = aClass.prototype;
this.registrar.registerFactory(proto.classID, proto.classDescription,
proto.contractID, this);
},
unregister: function() {
if (!this.aClass) {
dump('Class was never registered.');
return;
}
var proto = this.aClass.prototype;
this.registrar.unregisterFactory(proto.classID, this);
this.aClass = null;
},
// nsIFactory::createInstance
createInstance: function(outer, iid) {
if (outer !== null)
throw Cr.NS_ERROR_NO_AGGREGATION;
return (new (this.aClass)).QueryInterface(iid);
}
};
let PdfJs = {
_registered: false,
init: function() {
if (this.enabled)
this._register();
else
this._unregister();
// Listen for when pdf.js is completely disabled or a different pdf handler
// is chosen.
Services.prefs.addObserver(PREF_ENABLED, this, false);
Services.obs.addObserver(this, PDFJS_HANDLER_CHANGED, false);
},
observe: function(subject, topic, data) {
if (topic != 'nsPref:changed' && topic != PDFJS_HANDLER_CHANGED)
return;
if (this.enabled)
this._register();
else
this._unregister();
},
// pdf.js is only enabled if we're both selected as the pdf viewer and if the
// global switch enabling us is true.
get enabled() {
var handlerInfo = mimeService.
getFromTypeAndExtension('application/pdf', 'pdf');
var selectedAsHandler = handlerInfo && (handlerInfo.alwaysAskBeforeHandling == false &&
handlerInfo.preferredAction == Ci.nsIHandlerInfo.handleInternally);
return getBoolPref(PREF_ENABLED, false) && selectedAsHandler;
},
_register: function() {
if (this._registered)
return;
Factory.register(PdfStreamConverter);
this._registered = true;
},
_unregister: function() {
if (!this._registered)
return;
Factory.unregister();
this._registered = false;
}
};

View File

@ -358,6 +358,7 @@ target.firefox = function() {
sed('-i', /PDFJSSCRIPT_STREAM_CONVERTER_ID/, FIREFOX_STREAM_CONVERTER_ID, FIREFOX_BUILD_DIR + 'components/PdfStreamConverter.js');
sed('-i', /PDFJSSCRIPT_PREF_PREFIX/, FIREFOX_PREF_PREFIX, FIREFOX_BUILD_DIR + 'components/PdfStreamConverter.js');
sed('-i', /PDFJSSCRIPT_MOZ_CENTRAL/, 'false', FIREFOX_BUILD_DIR + 'components/PdfStreamConverter.js');
// Update localized metadata
var localizedMetadata = cat(EXTENSION_SRC_DIR + '/firefox/metadata.inc');
@ -421,6 +422,8 @@ target.mozcentral = function() {
mkdir('-p', MOZCENTRAL_CONTENT_DIR + BUILD_DIR);
mkdir('-p', MOZCENTRAL_CONTENT_DIR + '/web');
cp(FIREFOX_CONTENT_DIR + 'PdfJs.jsm', MOZCENTRAL_CONTENT_DIR)
// Copy extension files
cd('extensions/firefox');
cp('-R', FIREFOX_EXTENSION_FILES_TO_COPY, ROOT_DIR + MOZCENTRAL_EXTENSION_DIR);
@ -461,6 +464,7 @@ target.mozcentral = function() {
sed('-i', /PDFJSSCRIPT_STREAM_CONVERTER_ID/, MOZCENTRAL_STREAM_CONVERTER_ID, MOZCENTRAL_EXTENSION_DIR + 'components/PdfStreamConverter.js');
sed('-i', /PDFJSSCRIPT_PREF_PREFIX/, MOZCENTRAL_PREF_PREFIX, MOZCENTRAL_EXTENSION_DIR + 'components/PdfStreamConverter.js');
sed('-i', /PDFJSSCRIPT_MOZ_CENTRAL/, 'true', MOZCENTRAL_EXTENSION_DIR + 'components/PdfStreamConverter.js');
// List all files for mozilla-central
cd(MOZCENTRAL_EXTENSION_DIR);

View File

@ -13,6 +13,7 @@ include $(topsrcdir)/config/rules.mk
_BROWSER_TEST_FILES = \
browser_pdfjs_main.js \
browser_pdfjs_savedialog.js \
file_pdfjs_test.pdf \
$(NULL)

View File

@ -6,7 +6,17 @@ const RELATIVE_DIR = "browser/extensions/pdfjs/test/";
const TESTROOT = "http://example.com/browser/" + RELATIVE_DIR;
function test() {
var tab;
var tab, oldAction;
oldAction = changeMimeHandler();
const Cc = Components.classes;
const Ci = Components.interfaces;
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');
info('Pref action: ' + handlerInfo.preferredAction);
waitForExplicitFinish();
registerCleanupFunction(function() {
@ -23,13 +33,62 @@ function test() {
// Runs tests after all 'load' event handlers have fired off
setTimeout(function() {
runTests(document, window);
runTests(document, window, function() {
revertMimeHandler(oldAction);
finish();
});
}, 0);
}, true);
}
function runTests(document, window) {
function changeMimeHandler() {
let oldAction;
const Cc = Components.classes;
const Ci = Components.interfaces;
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');
oldAction = handlerInfo.preferredAction;
// Change and save mime handler settings
handlerInfo.alwaysAskBeforeHandling = false;
handlerInfo.preferredAction = Ci.nsIHandlerInfo.handleInternally;
handlerService.store(handlerInfo);
Services.obs.notifyObservers(null, 'pdfjs:handlerChanged', null);
// Refresh data
mimeService = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService);
handlerInfo = mimeService.getFromTypeAndExtension('application/pdf', 'pdf');
//
// Test: Mime handler was updated
//
is(handlerInfo.alwaysAskBeforeHandling, false, 'always-ask prompt change successful');
is(handlerInfo.preferredAction, Ci.nsIHandlerInfo.handleInternally, 'mime handler change successful');
return oldAction;
}
function revertMimeHandler(oldAction) {
const Cc = Components.classes;
const Ci = Components.interfaces;
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');
// Change and save mime handler settings
handlerInfo.alwaysAskBeforeHandling = true;
handlerInfo.preferredAction = oldAction;
handlerService.store(handlerInfo);
}
function runTests(document, window, callback) {
//
// Overall sanity tests
//
@ -67,5 +126,5 @@ function runTests(document, window) {
viewBookmark.click();
ok(viewBookmark.href.length > 0, 'viewBookmark button has href');
finish();
callback();
}

View File

@ -0,0 +1,54 @@
/* 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 tab;
const Cc = Components.classes;
const Ci = Components.interfaces;
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');
//
// Test: Default mime handler
//
is(handlerInfo.alwaysAskBeforeHandling, true, 'mime handler: default is always-ask prompt');
//
// Test: "Open with" dialog comes up
//
addWindowListener('chrome://mozapps/content/downloads/unknownContentType.xul', finish);
waitForExplicitFinish();
registerCleanupFunction(function() {
gBrowser.removeTab(tab);
});
tab = gBrowser.addTab(TESTROOT + "file_pdfjs_test.pdf");
var newTabBrowser = gBrowser.getBrowserForTab(tab);
}
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) { }
});
}