Bug 1169290 - Make Marionette component safe to load in child process. r?maja_zf
The Marionette XPCOM component is loaded once per process, but
only ever initialised in the main process. A subprocess that calls
nsIMarionette.running will always see it return false because loading
the MarionetteComponent class resets the MarionetteComponent#server
property to null, causing MarionetteComponent#running to return false.
To report the correct value in child processes they need to query
the main process for the running state. This patch introduces a
synchronous IPC message call to the main process using the child
process message manager (CPMM). Because nsIMarionette is currently
never used in a subprocess it is considered acceptable to use sync
IPC in this case, especially given the circumstances that Marionette
instruments the browser and is not tied to any frontend Firefox UX.
MozReview-Commit-ID: 93xtZN4MvWq
--- a/testing/marionette/components/marionette.js
+++ b/testing/marionette/components/marionette.js
@@ -41,16 +41,19 @@ const ENV_ENABLED = "MOZ_MARIONETTE";
// a different profile in order to test things like Firefox refresh.
// The environment variable itself, if present, is interpreted as a
// JSON structure, with the keys mapping to preference names in the
// "marionette." branch, and the values to the values of those prefs. So
// something like {"port": 4444} would result in the marionette.port
// pref being set to 4444.
const ENV_PRESERVE_PREFS = "MOZ_MARIONETTE_PREF_STATE_ACROSS_RESTARTS";
+const isRemote = Services.appinfo.processType ==
+ Services.appinfo.PROCESS_TYPE_CONTENT;
+
const LogLevel = {
get(level) {
let levels = new Map([
["fatal", Log.Level.Fatal],
["error", Log.Level.Error],
["warn", Log.Level.Warn],
["info", Log.Level.Info],
["config", Log.Level.Config],
@@ -132,47 +135,59 @@ const prefs = {
for (let prefName of Object.keys(prefs)) {
Preferences.set(prefName, prefs[prefName]);
}
}
}
},
};
-class MarionetteComponent {
+class MarionetteMainProcess {
constructor() {
this.server = null;
// holds reference to ChromeWindow
// used to run GFX sanity tests on Windows
this.gfxWindow = null;
// indicates that all pending window checks have been completed
// and that we are ready to start the Marionette server
this.finalUIStartup = false;
log.level = prefs.logLevel;
this.enabled = env.exists(ENV_ENABLED);
Services.prefs.addObserver(PREF_ENABLED, this);
+ Services.ppmm.addMessageListener("Marionette:IsRunning", this);
}
get running() {
return this.server && this.server.alive;
}
set enabled(value) {
Services.prefs.setBoolPref(PREF_ENABLED, value);
}
get enabled() {
return Services.prefs.getBoolPref(PREF_ENABLED);
}
+ receiveMessage({name}) {
+ switch (name) {
+ case "Marionette:IsRunning":
+ return this.running;
+
+ default:
+ log.warn("Unknown IPC message to main process: " + name);
+ return null;
+ }
+ }
+
observe(subject, topic) {
log.debug(`Received observer notification ${topic}`);
switch (topic) {
case "nsPref:changed":
if (Services.prefs.getBoolPref(PREF_ENABLED)) {
this.init();
} else {
@@ -306,24 +321,48 @@ class MarionetteComponent {
return XPCOMUtils.generateQI([
Ci.nsICommandLineHandler,
Ci.nsIMarionette,
Ci.nsIObserver,
]);
}
}
+class MarionetteContentProcess {
+ get running() {
+ let reply = Services.cpmm.sendSyncMessage("Marionette:IsRunning");
+ if (reply.length == 0) {
+ log.warn("No reply from main process");
+ return false;
+ }
+ return reply[0];
+ }
+
+ get QueryInterface() {
+ return XPCOMUtils.generateQI([Ci.nsIMarionette]);
+ }
+}
+
const MarionetteFactory = {
+ instance_: null,
+
createInstance(outer, iid) {
if (outer) {
throw Cr.NS_ERROR_NO_AGGREGATION;
}
- let marionette = new MarionetteComponent();
- return marionette.QueryInterface(iid);
+ if (!this.instance_) {
+ if (isRemote) {
+ this.instance_ = new MarionetteContentProcess();
+ } else {
+ this.instance_ = new MarionetteMainProcess();
+ }
+ }
+
+ return this.instance_.QueryInterface(iid);
},
};
function Marionette() {}
Marionette.prototype = {
classDescription: "Marionette component",
classID: Components.ID("{786a1369-dca5-4adc-8486-33d23c88010a}"),