VulpesOS/gaia/tests/jsmarionette/plugins/marionette-content-script/index.js
OverSu b38dea0597 Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
2026-09-30 23:13:03 +02:00

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;