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

--HG--
extra : rebase_source : bc90a1720323c5a768d2c03a05bbb8e2a2d1ea60
This commit is contained in:
Andreas Tolfsen 2018-01-27 19:34:32 +00:00
Родитель aa4f63e6a1
Коммит 6d8cae5183
1 изменённых файлов: 42 добавлений и 3 удалений

Просмотреть файл

@ -46,6 +46,9 @@ const ENV_ENABLED = "MOZ_MARIONETTE";
// 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([
@ -137,7 +140,7 @@ const prefs = {
},
};
class MarionetteComponent {
class MarionetteMainProcess {
constructor() {
this.server = null;
@ -154,6 +157,7 @@ class MarionetteComponent {
this.enabled = env.exists(ENV_ENABLED);
Services.prefs.addObserver(PREF_ENABLED, this);
Services.ppmm.addMessageListener("Marionette:IsRunning", this);
}
get running() {
@ -168,6 +172,17 @@ class MarionetteComponent {
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}`);
@ -311,14 +326,38 @@ class MarionetteComponent {
}
}
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);
},
};