Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
102 lines
2.9 KiB
JavaScript
Executable file
102 lines
2.9 KiB
JavaScript
Executable file
/* global Components, XPCOMUtils, Services */
|
|
'use strict';
|
|
/**
|
|
* This is a very blunt instrument designed to load some JS (encoded in dataURI)
|
|
* before each and every content page load (apps, browser tabs, etc...)
|
|
*
|
|
* Its critical to remember this will _not_ run in the node process.
|
|
*
|
|
* @param {String} dataURI encoded javascript.
|
|
*/
|
|
function xpcomLoadFrameScript(dataURI) {
|
|
(function() {
|
|
var Cu = Components.utils;
|
|
var Ci = Components.interfaces;
|
|
|
|
Cu.import('resource://gre/modules/Services.jsm');
|
|
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
|
|
|
|
XPCOMUtils.defineLazyServiceGetter(this, 'ppmm',
|
|
'@mozilla.org/parentprocessmessagemanager;1', 'nsIMessageBroadcaster');
|
|
|
|
// TODO: Remove `legacyLoader`.
|
|
// See "Bug 952177 - [marionette-content-script] Remove listeners for
|
|
// deprecated Service notifications"
|
|
var legacyLoader = {
|
|
init: function() {
|
|
Services.obs.addObserver(
|
|
this, 'remote-browser-frame-show', false
|
|
);
|
|
|
|
Services.obs.addObserver(
|
|
this, 'in-process-browser-or-app-frame-shown', false
|
|
);
|
|
},
|
|
|
|
observe: function(subject, topic, data) {
|
|
var frameLoader = subject.QueryInterface(Ci.nsIFrameLoader);
|
|
var mm = frameLoader.messageManager;
|
|
|
|
mm.loadFrameScript(
|
|
dataURI,
|
|
true
|
|
);
|
|
}
|
|
};
|
|
|
|
legacyLoader.init();
|
|
|
|
var Loader = function() {};
|
|
Loader.prototype.attach = function(service) {
|
|
service.addObserver(this, 'remote-browser-shown', false);
|
|
service.addObserver(this, 'inprocess-browser-shown', false);
|
|
};
|
|
Loader.prototype.observe = function(subject, topic, data) {
|
|
var frameLoader = subject.QueryInterface(Ci.nsIFrameLoader);
|
|
|
|
// The 'remote-browser-shown' and 'inprocess-browser-shown' notifications
|
|
// are sent from all frames. Ignore all but those originating from a
|
|
// "browser or app" frame.
|
|
if (!frameLoader.ownerIsBrowserOrAppFrame) {
|
|
return;
|
|
}
|
|
|
|
legacyLoader.observe.apply(null, arguments);
|
|
};
|
|
|
|
var loader = new Loader();
|
|
loader.attach(Services.obs);
|
|
}());
|
|
}
|
|
|
|
var fs = require('fs');
|
|
|
|
/**
|
|
* @param {String} file to encode.
|
|
* @return {String} base64 encoded javascript data:uri.
|
|
*/
|
|
function loadEncodedJS(file) {
|
|
// sync read just like `require` (it needs to a datauri so gecko will loads it
|
|
// as javascript).
|
|
return 'data:text/javascript;base64,' + fs.readFileSync(file, 'base64');
|
|
|
|
}
|
|
|
|
/**
|
|
* Node wrapper around load frame script.
|
|
*
|
|
* @param {Marionette.Client} client to use.
|
|
* @param {String} path of file to load.
|
|
* @param {Function} callback optional callback.
|
|
*/
|
|
function loadFrameScript(client, path, callback) {
|
|
client.executeScript(xpcomLoadFrameScript, [loadEncodedJS(path)], callback);
|
|
}
|
|
|
|
function plugin(client, options) {
|
|
var chrome = client.scope({ context: 'chrome' });
|
|
var inject = loadFrameScript.bind(this, chrome);
|
|
return { inject: inject };
|
|
}
|
|
|
|
module.exports = plugin;
|