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.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View file

@ -0,0 +1,102 @@
/* 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;

View file

@ -0,0 +1,6 @@
{
"name": "marionette-content-script",
"version": "0.0.4",
"description": "Preloads a given file into all content contexts",
"main": "index.js"
}

View file

@ -0,0 +1,24 @@
/* global Components, Services, dump */
'use strict';
Components.utils.import('resource://gre/modules/Services.jsm');
try {
Services.obs.addObserver(function(document) {
if (!document || !document.location)
return;
var location = document.location.href;
dump('\n\n' + location + '\n\n');
try {
let window = document.defaultView.wrappedJSObject;
window.navigator.__defineGetter__('I_AM_HACKED', function() {
return 'UNIQUE';
});
} catch (e) {
dump('ERR: ' + e.toString() + '\n');
}
}, 'document-element-inserted', false);
} catch (e) {
dump('ERR: ' + e.toString() + '\n');
}

View file

@ -0,0 +1,69 @@
'use strict';
var assert = require('assert');
marionette('index', function() {
var CLOCK_APP = 'app://clock.gaiamobile.org';
var CALENDAR_APP = 'app://calendar.gaiamobile.org';
marionette.plugin('apps', require('marionette-apps'));
marionette.plugin('contentScript', require('../'));
var client = marionette.client();
suite('#inject', function() {
setup(function() {
client.contentScript.inject(__dirname + '/fixtures/load_everywhere.js');
client.apps.launch(CLOCK_APP);
client.apps.switchToApp(CLOCK_APP);
});
function getCustomProperty() {
return client.executeScript(function() {
return window.wrappedJSObject.navigator.I_AM_HACKED;
});
}
function updatesCustomProperty(message) {
var expectedValue = 'UNIQUE';
assert.equal(
getCustomProperty(),
expectedValue,
message
);
}
test('in a single app', function() {
updatesCustomProperty('I_AM_HACKED is exposed');
});
test('multiple apps', function() {
// back to root frame
client.switchToFrame();
// so we can launch another app
client.apps.launch(CALENDAR_APP);
client.apps.switchToApp(CALENDAR_APP);
updatesCustomProperty('I_AM_HACKED is exposed');
});
suite('system app', function() {
setup(function() {
// go to system app
client.switchToFrame();
});
test('system app is not modified ', function() {
// sanity check
assert.ok(!getCustomProperty(), 'system app is not modified');
});
test('next reload of system app will be modified', function() {
// reload!
client.goUrl(client.getUrl());
updatesCustomProperty();
});
});
});
});