2011-09-28 04:15:06 +09:00
|
|
|
/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
2011-09-07 07:00:24 +09:00
|
|
|
const Cc = Components.classes;
|
|
|
|
const Ci = Components.interfaces;
|
|
|
|
const Cr = Components.results;
|
|
|
|
const Cu = Components.utils;
|
2012-01-28 03:53:07 +09:00
|
|
|
const PDFJS_EVENT_ID = 'pdf.js.message';
|
2011-09-28 04:15:06 +09:00
|
|
|
const PDF_CONTENT_TYPE = 'application/pdf';
|
2012-01-28 03:53:07 +09:00
|
|
|
const NS_ERROR_NOT_IMPLEMENTED = 0x80004001;
|
|
|
|
const EXT_PREFIX = 'extensions.uriloader@pdf.js';
|
2011-09-07 07:00:24 +09:00
|
|
|
|
2011-09-28 04:15:06 +09:00
|
|
|
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
|
|
|
Cu.import('resource://gre/modules/Services.jsm');
|
2011-09-07 07:00:24 +09:00
|
|
|
|
|
|
|
function log(aMsg) {
|
2012-01-28 04:02:27 +09:00
|
|
|
let msg = 'PdfStreamConverter.js: ' + (aMsg.join ? aMsg.join('') : aMsg);
|
2012-02-04 09:49:44 +09:00
|
|
|
Services.console.logStringMessage(msg);
|
2011-09-28 04:15:06 +09:00
|
|
|
dump(msg + '\n');
|
|
|
|
}
|
2012-01-28 03:53:07 +09:00
|
|
|
let application = Cc['@mozilla.org/fuel/application;1']
|
|
|
|
.getService(Ci.fuelIApplication);
|
|
|
|
let privateBrowsing = Cc['@mozilla.org/privatebrowsing;1']
|
|
|
|
.getService(Ci.nsIPrivateBrowsingService);
|
|
|
|
let inPrivateBrowswing = privateBrowsing.privateBrowsingEnabled;
|
|
|
|
|
|
|
|
// All the priviledged actions.
|
|
|
|
function ChromeActions() {
|
|
|
|
this.inPrivateBrowswing = privateBrowsing.privateBrowsingEnabled;
|
|
|
|
}
|
|
|
|
ChromeActions.prototype = {
|
|
|
|
download: function(data) {
|
|
|
|
Services.wm.getMostRecentWindow('navigator:browser').saveURL(data);
|
|
|
|
},
|
2012-02-01 10:53:42 +09:00
|
|
|
setDatabase: function(data) {
|
2012-01-28 03:53:07 +09:00
|
|
|
if (this.inPrivateBrowswing)
|
|
|
|
return;
|
|
|
|
application.prefs.setValue(EXT_PREFIX + '.database', data);
|
|
|
|
},
|
|
|
|
getDatabase: function() {
|
|
|
|
if (this.inPrivateBrowswing)
|
|
|
|
return '{}';
|
|
|
|
return application.prefs.getValue(EXT_PREFIX + '.database', '{}');
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Event listener to trigger chrome privedged code.
|
|
|
|
function RequestListener(actions) {
|
|
|
|
this.actions = actions;
|
|
|
|
}
|
2012-02-01 10:53:42 +09:00
|
|
|
// Receive an event and synchronously responds.
|
|
|
|
RequestListener.prototype.receive = function(event) {
|
2012-01-28 03:53:07 +09:00
|
|
|
var message = event.target;
|
|
|
|
var action = message.getUserData('action');
|
|
|
|
var data = message.getUserData('data');
|
|
|
|
var actions = this.actions;
|
|
|
|
if (!(action in actions)) {
|
|
|
|
log('Unknown action: ' + action);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var response = actions[action].call(this.actions, data);
|
|
|
|
message.setUserData('response', response, null);
|
|
|
|
};
|
2011-09-07 07:00:24 +09:00
|
|
|
|
2012-01-24 09:50:45 +09:00
|
|
|
|
2012-01-28 04:02:27 +09:00
|
|
|
function PdfStreamConverter() {
|
2012-01-24 10:52:53 +09:00
|
|
|
}
|
2011-09-07 07:00:24 +09:00
|
|
|
|
2012-01-28 04:02:27 +09:00
|
|
|
PdfStreamConverter.prototype = {
|
2011-09-07 07:00:24 +09:00
|
|
|
|
2012-01-24 09:50:45 +09:00
|
|
|
// properties required for XPCOM registration:
|
2012-01-28 04:02:27 +09:00
|
|
|
classID: Components.ID('{6457a96b-2d68-439a-bcfa-44465fbcdbb1}'),
|
2012-01-24 09:50:45 +09:00
|
|
|
classDescription: 'pdf.js Component',
|
|
|
|
contractID: '@mozilla.org/streamconv;1?from=application/pdf&to=*/*',
|
2012-01-24 10:52:53 +09:00
|
|
|
|
2012-01-24 09:50:45 +09:00
|
|
|
QueryInterface: XPCOMUtils.generateQI([
|
|
|
|
Ci.nsISupports,
|
|
|
|
Ci.nsIStreamConverter,
|
|
|
|
Ci.nsIStreamListener,
|
|
|
|
Ci.nsIRequestObserver
|
|
|
|
]),
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This component works as such:
|
|
|
|
* 1. asyncConvertData stores the listener
|
|
|
|
* 2. onStartRequest creates a new channel, streams the viewer and cancels
|
|
|
|
* the request so pdf.js can do the request
|
|
|
|
* Since the request is cancelled onDataAvailable should not be called. The
|
|
|
|
* onStopRequest does nothing. The convert function just returns the stream,
|
|
|
|
* it's just the synchronous version of asyncConvertData.
|
|
|
|
*/
|
|
|
|
|
|
|
|
// nsIStreamConverter::convert
|
2012-01-24 10:52:53 +09:00
|
|
|
convert: function(aFromStream, aFromType, aToType, aCtxt) {
|
2012-01-26 10:40:08 +09:00
|
|
|
return aFromStream;
|
2012-01-24 09:50:45 +09:00
|
|
|
},
|
2011-09-07 07:00:24 +09:00
|
|
|
|
2012-01-24 09:50:45 +09:00
|
|
|
// nsIStreamConverter::asyncConvertData
|
2012-01-24 10:52:53 +09:00
|
|
|
asyncConvertData: function(aFromType, aToType, aListener, aCtxt) {
|
2012-01-26 10:40:08 +09:00
|
|
|
if (!Services.prefs.getBoolPref('extensions.pdf.js.active'))
|
|
|
|
throw NS_ERROR_NOT_IMPLEMENTED;
|
2012-01-24 09:50:45 +09:00
|
|
|
// Store the listener passed to us
|
|
|
|
this.listener = aListener;
|
|
|
|
},
|
2011-10-19 10:20:50 +09:00
|
|
|
|
2012-01-24 09:50:45 +09:00
|
|
|
// nsIStreamListener::onDataAvailable
|
2012-01-24 10:52:53 +09:00
|
|
|
onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
|
2012-01-24 09:50:45 +09:00
|
|
|
// Do nothing since all the data loading is handled by the viewer.
|
2012-01-24 10:52:53 +09:00
|
|
|
log('SANITY CHECK: onDataAvailable SHOULD NOT BE CALLED!');
|
2012-01-24 09:50:45 +09:00
|
|
|
},
|
2011-10-19 10:20:50 +09:00
|
|
|
|
2012-01-24 09:50:45 +09:00
|
|
|
// nsIRequestObserver::onStartRequest
|
2012-01-24 10:52:53 +09:00
|
|
|
onStartRequest: function(aRequest, aContext) {
|
2012-01-28 03:53:07 +09:00
|
|
|
|
2012-01-24 09:50:45 +09:00
|
|
|
// Setup the request so we can use it below.
|
|
|
|
aRequest.QueryInterface(Ci.nsIChannel);
|
2012-01-25 14:33:03 +09:00
|
|
|
// Cancel the request so the viewer can handle it.
|
|
|
|
aRequest.cancel(Cr.NS_BINDING_ABORTED);
|
|
|
|
|
2012-01-24 09:50:45 +09:00
|
|
|
// Create a new channel that is viewer loaded as a resource.
|
2012-02-04 09:49:44 +09:00
|
|
|
var ioService = Services.io;
|
2012-01-24 09:50:45 +09:00
|
|
|
var channel = ioService.newChannel(
|
|
|
|
'resource://pdf.js/web/viewer.html', null, null);
|
2012-01-28 03:53:07 +09:00
|
|
|
|
2012-01-24 09:50:45 +09:00
|
|
|
// Keep the URL the same so the browser sees it as the same.
|
2012-02-03 09:29:08 +09:00
|
|
|
channel.originalURI = aRequest.URI;
|
2012-01-24 09:50:45 +09:00
|
|
|
channel.asyncOpen(this.listener, aContext);
|
2012-01-28 03:53:07 +09:00
|
|
|
|
|
|
|
// Setup a global listener waiting for the next DOM to be created and verfiy
|
|
|
|
// that its the one we want by its URL. When the correct DOM is found create
|
|
|
|
// an event listener on that window for the pdf.js events that require
|
|
|
|
// chrome priviledges.
|
2012-02-03 09:29:08 +09:00
|
|
|
var url = aRequest.URI.spec;
|
2012-01-28 03:53:07 +09:00
|
|
|
var gb = Services.wm.getMostRecentWindow('navigator:browser');
|
|
|
|
var domListener = function domListener(event) {
|
|
|
|
var doc = event.originalTarget;
|
|
|
|
var win = doc.defaultView;
|
|
|
|
if (doc.location.href === url) {
|
|
|
|
gb.removeEventListener('DOMContentLoaded', domListener);
|
|
|
|
var requestListener = new RequestListener(new ChromeActions());
|
|
|
|
win.addEventListener(PDFJS_EVENT_ID, function(event) {
|
2012-02-01 10:53:42 +09:00
|
|
|
requestListener.receive(event);
|
2012-01-28 03:53:07 +09:00
|
|
|
}, false, true);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
gb.addEventListener('DOMContentLoaded', domListener, false);
|
2011-09-07 07:00:24 +09:00
|
|
|
},
|
|
|
|
|
2012-01-24 09:50:45 +09:00
|
|
|
// nsIRequestObserver::onStopRequest
|
2012-01-24 10:52:53 +09:00
|
|
|
onStopRequest: function(aRequest, aContext, aStatusCode) {
|
2012-01-24 09:50:45 +09:00
|
|
|
// Do nothing.
|
|
|
|
}
|
2011-09-07 07:00:24 +09:00
|
|
|
};
|
|
|
|
|
2012-01-28 04:02:27 +09:00
|
|
|
var NSGetFactory = XPCOMUtils.generateNSGetFactory([PdfStreamConverter]);
|