Bug 1464469 - Shorthands for setting up Marionette logger. r?whimboo
This patch generalises logger setup and access by providing
one interface with specialised implementations for the main-
and child processes. This will mean we can get rid of ad-hoc
logger setup in testing/marionette/components/marionette.js and
testing/marionette/listener.js.
In the case for the component file, the log level and the stdout
dump appender is set up when you request the logger. The same is
true when requesting the logger in a child process, but it will
additionally request the log level from the main process.
Usage:
const {Log} = ChromeUtils.import("chrome://marionette/content/log.js", {});
let log = Log.get();
MozReview-Commit-ID: 8Ha5FSaoGXp
new file mode 100644
--- /dev/null
+++ b/testing/marionette/doc/internals/log.rst
@@ -0,0 +1,4 @@
+log module
+==========
+.. js:autoclass:: Log
+ :members:
--- a/testing/marionette/jar.mn
+++ b/testing/marionette/jar.mn
@@ -19,16 +19,17 @@ marionette.jar:
content/error.js (error.js)
content/evaluate.js (evaluate.js)
content/event.js (event.js)
content/format.js (format.js)
content/interaction.js (interaction.js)
content/l10n.js (l10n.js)
content/legacyaction.js (legacyaction.js)
content/listener.js (listener.js)
+ content/log.js (log.js)
content/message.js (message.js)
content/modal.js (modal.js)
content/navigate.js (navigate.js)
content/packets.js (packets.js)
content/prefs.js (prefs.js)
content/proxy.js (proxy.js)
content/reftest.js (reftest.js)
content/reftest.xul (reftest.xul)
new file mode 100644
--- /dev/null
+++ b/testing/marionette/log.js
@@ -0,0 +1,94 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+ChromeUtils.import("resource://gre/modules/Services.jsm");
+const StdLog = ChromeUtils.import("resource://gre/modules/Log.jsm", {}).Log;
+
+const {MarionettePrefs} = ChromeUtils.import("chrome://marionette/content/prefs.js", {});
+
+this.EXPORTED_SYMBOLS = ["Log"];
+
+const isChildProcess = Services.appinfo.processType ==
+ Services.appinfo.PROCESS_TYPE_CONTENT;
+
+/**
+ * Shorthand for accessing the Marionette logging repository.
+ *
+ * Using this class to retrieve the `Log.jsm` repository for
+ * Marionette will ensure the logger is set up correctly with the
+ * appropriate stdout dumper and with the correct log level.
+ *
+ * Unlike `Log.jsm` this logger is E10s safe, meaning repository
+ * configuration for appenders and logging levels are communicated
+ * across processes.
+ *
+ * @name Log
+ */
+class MarionetteLog {
+ /**
+ * Obtain the `Marionette` logger.
+ *
+ * The returned {@link Logger} instance is shared among all
+ * callers in the same process.
+ *
+ * @return {Logger}
+ */
+ static get() {
+ let logger = StdLog.repository.getLogger("Marionette");
+ if (logger.ownAppenders.length == 0) {
+ logger.addAppender(new StdLog.DumpAppender());
+ }
+ logger.level = MarionettePrefs.logLevel;
+ return logger;
+ }
+
+ /**
+ * Obtain a logger that logs all messages with a prefix.
+ *
+ * Unlike {@link LoggerRepository.getLoggerWithMessagePrefix()}
+ * this function will ensure invoke {@link #get()} first to ensure
+ * the logger has been properly set up first.
+ *
+ * This returns a new object with a prototype chain that chains
+ * up the original {@link Logger} instance. The new prototype has
+ * log functions that prefix `prefix` to each message.
+ *
+ * @param {string} prefix
+ * String to prefix each logged message with.
+ *
+ * @return {Proxy.<Logger>}
+ */
+ static getWithPrefix(prefix) {
+ this.get();
+ return StdLog.repository.getLoggerWithMessagePrefix("Marionette", `[${prefix}] `);
+ }
+}
+
+class ParentProcessLog extends MarionetteLog {
+ static get() {
+ let logger = super.get();
+ Services.ppmm.initialProcessData["Marionette:Log"] = {level: logger.level};
+ return logger;
+ }
+}
+
+class ChildProcessLog extends MarionetteLog {
+ static get() {
+ let logger = super.get();
+
+ // Log.jsm is not e10s compatible (see https://bugzil.la/1411513)
+ // so loading it in a new child process will reset the repository config
+ logger.level = Services.cpmm.initialProcessData["Marionette:Log"] || StdLog.Level.Info;
+
+ return logger;
+ }
+}
+
+if (isChildProcess) {
+ this.Log = ChildProcessLog;
+} else {
+ this.Log = ParentProcessLog;
+}
--- a/testing/marionette/prefs.js
+++ b/testing/marionette/prefs.js
@@ -121,24 +121,16 @@ class Branch {
* potentially malformed input. In the `marionette.log.level` example,
* `DEBUG`, `Debug`, and `dEbUg` are considered valid inputs and the
* `LogBranch` specialisation deserialises the string value to the
* correct `Log.Level` by sanitising the input data first.
*
* A further complication is that we cannot rely on `Preferences.jsm`
* in Marionette. See https://bugzilla.mozilla.org/show_bug.cgi?id=1357517
* for further details.
- *
- * Usage::
- *
- * ChromeUtils.import("resource://gre/modules/Log.jsm");
- * const {MarionettePrefs} = ChromeUtils.import("chrome://marionette/content/prefs.js", {});
- *
- * const log = Log.repository.getLogger("Marionette");
- * log.level = MarionettePrefs.log.level;
*/
class MarionetteBranch extends Branch {
constructor(branch = "marionette.") {
super(branch);
}
/**
* The `marionette.enabled` preference. When it returns true,