Backed out 5 changesets (bug 1452200) for mochitest-chrome failures on Android on a CLOSED TREE
authorGurzau Raul <rgurzau@mozilla.com>
Sun, 15 Apr 2018 09:19:04 +0300
changeset 466960 e96685584bf7d3c1d7a4c1861716da89fd650c51
parent 466959 af50acbd6c2884dbbb26b3c8053475318fd57697
child 466961 fdcb9f2ec9d9b6d1a291d9969249d5a3c0cb054e
child 467350 db377658f683c663faac4c808c433c043082895f
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1452200
milestone61.0a1
backs outed07fb947b5e6c14b93c00a6596b756b37d306c0
b03e9dc6ecd7751d56be0d68ac3b338dcee2cc2c
e4cdad2cd3d2e21fd0994ba523f743a7b7f43896
8ac249bdc7726ab42cb4e381aae09a573e454e81
225bb7ed5f712d457e7207360cf618cf44a66ed4
first release with
nightly linux32
e96685584bf7 / 61.0a1 / 20180415100032 / files
nightly linux64
e96685584bf7 / 61.0a1 / 20180415100032 / files
nightly mac
e96685584bf7 / 61.0a1 / 20180415100032 / files
nightly win32
e96685584bf7 / 61.0a1 / 20180415100032 / files
nightly win64
e96685584bf7 / 61.0a1 / 20180415100032 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 5 changesets (bug 1452200) for mochitest-chrome failures on Android on a CLOSED TREE Backed out changeset ed07fb947b5e (bug 1452200) Backed out changeset b03e9dc6ecd7 (bug 1452200) Backed out changeset e4cdad2cd3d2 (bug 1452200) Backed out changeset 8ac249bdc772 (bug 1452200) Backed out changeset 225bb7ed5f71 (bug 1452200)
mobile/android/chrome/geckoview/ErrorPageEventHandler.js
mobile/android/chrome/geckoview/GeckoViewContent.js
mobile/android/chrome/geckoview/GeckoViewContentSettings.js
mobile/android/chrome/geckoview/GeckoViewNavigationContent.js
mobile/android/chrome/geckoview/GeckoViewScrollContent.js
mobile/android/chrome/geckoview/GeckoViewSelectionActionContent.js
mobile/android/chrome/geckoview/geckoview.js
mobile/android/components/geckoview/GeckoViewExternalAppService.js
mobile/android/modules/geckoview/.eslintrc.js
mobile/android/modules/geckoview/AndroidLog.jsm
mobile/android/modules/geckoview/GeckoViewContent.jsm
mobile/android/modules/geckoview/GeckoViewContentModule.jsm
mobile/android/modules/geckoview/GeckoViewModule.jsm
mobile/android/modules/geckoview/GeckoViewNavigation.jsm
mobile/android/modules/geckoview/GeckoViewProgress.jsm
mobile/android/modules/geckoview/GeckoViewRemoteDebugger.jsm
mobile/android/modules/geckoview/GeckoViewScroll.jsm
mobile/android/modules/geckoview/GeckoViewSelectionAction.jsm
mobile/android/modules/geckoview/GeckoViewSettings.jsm
mobile/android/modules/geckoview/GeckoViewTab.jsm
mobile/android/modules/geckoview/GeckoViewTrackingProtection.jsm
mobile/android/modules/geckoview/GeckoViewUtils.jsm
toolkit/modules/Log.jsm
toolkit/modules/tests/xpcshell/test_Log.js
--- a/mobile/android/chrome/geckoview/ErrorPageEventHandler.js
+++ b/mobile/android/chrome/geckoview/ErrorPageEventHandler.js
@@ -1,18 +1,14 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* 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/. */
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-ChromeUtils.import("resource://gre/modules/GeckoViewUtils.jsm");
-
-/* global debug:false, warn:false */
-GeckoViewUtils.initLogging("GeckoView.ErrorPageEventHandler", this);
 
 ChromeUtils.defineModuleGetter(this, "SSLExceptions",
                                "resource://gre/modules/SSLExceptions.jsm");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
   Services: "resource://gre/modules/Services.jsm",
 });
 
@@ -41,17 +37,17 @@ var ErrorPageEventHandler = {
               let uri = Services.io.newURI(errorDoc.location.href);
               let sslExceptions = new SSLExceptions();
 
               if (target == perm)
                 sslExceptions.addPermanentException(uri, errorDoc.defaultView);
               else
                 sslExceptions.addTemporaryException(uri, errorDoc.defaultView);
             } catch (e) {
-              warn `Failed to set cert exception: ${e}`;
+              dump("Failed to set cert exception: " + e + "\n");
             }
             errorDoc.location.reload();
           } else if (target == errorDoc.getElementById("getMeOutOfHereButton")) {
             errorDoc.location = "about:home";
           }
         }
         break;
       }
--- a/mobile/android/chrome/geckoview/GeckoViewContent.js
+++ b/mobile/android/chrome/geckoview/GeckoViewContent.js
@@ -5,19 +5,27 @@
 
 ChromeUtils.import("resource://gre/modules/GeckoViewContentModule.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
   Services: "resource://gre/modules/Services.jsm",
 });
 
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+    ChromeUtils.import("resource://gre/modules/AndroidLog.jsm",
+                       {}).AndroidLog.d.bind(null, "ViewContent"));
+
+function debug(aMsg) {
+  // dump(aMsg);
+}
+
 class GeckoViewContent extends GeckoViewContentModule {
   onEnable() {
-    debug `onEnable`;
+    debug("onEnable");
 
     addEventListener("DOMTitleChanged", this, false);
     addEventListener("DOMWindowFocus", this, false);
     addEventListener("DOMWindowClose", this, false);
     addEventListener("MozDOMFullscreen:Entered", this, false);
     addEventListener("MozDOMFullscreen:Exit", this, false);
     addEventListener("MozDOMFullscreen:Exited", this, false);
     addEventListener("MozDOMFullscreen:Request", this, false);
@@ -27,17 +35,17 @@ class GeckoViewContent extends GeckoView
                                            this);
     this.messageManager.addMessageListener("GeckoView:DOMFullscreenExited",
                                            this);
     this.messageManager.addMessageListener("GeckoView:ZoomToInput",
                                            this);
   }
 
   onDisable() {
-    debug `onDisable`;
+    debug("onDisable");
 
     removeEventListener("DOMTitleChanged", this);
     removeEventListener("DOMWindowFocus", this);
     removeEventListener("DOMWindowClose", this);
     removeEventListener("MozDOMFullscreen:Entered", this);
     removeEventListener("MozDOMFullscreen:Exit", this);
     removeEventListener("MozDOMFullscreen:Exited", this);
     removeEventListener("MozDOMFullscreen:Request", this);
@@ -47,17 +55,17 @@ class GeckoViewContent extends GeckoView
                                               this);
     this.messageManager.removeMessageListener("GeckoView:DOMFullscreenExited",
                                               this);
     this.messageManager.removeMessageListener("GeckoView:ZoomToInput",
                                               this);
   }
 
   receiveMessage(aMsg) {
-    debug `receiveMessage: ${aMsg.name}`;
+    debug("receiveMessage " + aMsg.name);
 
     switch (aMsg.name) {
       case "GeckoView:DOMFullscreenEntered":
         if (content) {
           content.QueryInterface(Ci.nsIInterfaceRequestor)
                  .getInterface(Ci.nsIDOMWindowUtils)
                  .handleFullscreenRequests();
         }
@@ -112,17 +120,17 @@ class GeckoViewContent extends GeckoView
           }
         }, 500);
       }
       break;
     }
   }
 
   handleEvent(aEvent) {
-    debug `handleEvent: ${aEvent.type}`;
+    debug("handleEvent " + aEvent.type);
 
     switch (aEvent.type) {
       case "contextmenu":
         function nearestParentHref(node) {
           while (node && !node.href) {
             node = node.parentNode;
           }
           return node && node.href;
@@ -184,10 +192,9 @@ class GeckoViewContent extends GeckoView
         this.eventDispatcher.sendRequest({
           type: "GeckoView:DOMWindowClose"
         });
         break;
     }
   }
 }
 
-let {debug, warn} = GeckoViewContent.initLogging("GeckoViewContent");
-let module = GeckoViewContent.create(this);
+var contentListener = new GeckoViewContent("GeckoViewContent", this);
--- a/mobile/android/chrome/geckoview/GeckoViewContentSettings.js
+++ b/mobile/android/chrome/geckoview/GeckoViewContentSettings.js
@@ -5,27 +5,35 @@
 
 ChromeUtils.import("resource://gre/modules/GeckoViewContentModule.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
   GeckoViewUtils: "resource://gre/modules/GeckoViewUtils.jsm",
 });
 
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+    ChromeUtils.import("resource://gre/modules/AndroidLog.jsm",
+                       {}).AndroidLog.d.bind(null, "ViewSettings[C]"));
+
+function debug(aMsg) {
+  // dump(aMsg);
+}
+
 // Handles GeckoView content settings including:
 // * tracking protection
 // * desktop mode
 class GeckoViewContentSettings extends GeckoViewContentModule {
   onInit() {
-    debug `onInit`;
+    debug("onInit");
     this._useDesktopMode = false;
   }
 
   onSettingsUpdate() {
-    debug `onSettingsUpdate`;
+    debug("onSettingsUpdate");
 
     this.displayMode = this.settings.displayMode;
     this.useTrackingProtection = !!this.settings.useTrackingProtection;
     this.useDesktopMode = !!this.settings.useDesktopMode;
   }
 
   get useTrackingProtection() {
     return docShell.useTrackingProtection;
@@ -58,10 +66,9 @@ class GeckoViewContentSettings extends G
   set displayMode(aMode) {
     const docShell = content && GeckoViewUtils.getRootDocShell(content);
     if (docShell) {
       docShell.displayMode = aMode;
     }
   }
 }
 
-let {debug, warn} = GeckoViewContentSettings.initLogging("GeckoViewSettings");
-let module = GeckoViewContentSettings.create(this);
+var settings = new GeckoViewContentSettings("GeckoViewSettings", this);
--- a/mobile/android/chrome/geckoview/GeckoViewNavigationContent.js
+++ b/mobile/android/chrome/geckoview/GeckoViewNavigationContent.js
@@ -6,40 +6,45 @@
 ChromeUtils.import("resource://gre/modules/GeckoViewContentModule.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
   ErrorPageEventHandler: "chrome://geckoview/content/ErrorPageEventHandler.js",
   LoadURIDelegate: "resource://gre/modules/LoadURIDelegate.jsm",
 });
 
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+  ChromeUtils.import("resource://gre/modules/AndroidLog.jsm",
+                     {}).AndroidLog.d.bind(null, "ViewNavigation[C]"));
+
+function debug(aMsg) {
+  // dump(aMsg);
+}
+
 // Implements nsILoadURIDelegate.
 class GeckoViewNavigationContent extends GeckoViewContentModule {
   onEnable() {
-    debug `onEnable`;
+    debug("onEnable");
 
     docShell.loadURIDelegate = this;
   }
 
   onDisable() {
-    debug `onDisable`;
+    debug("onDisable");
 
     docShell.loadURIDelegate = null;
   }
 
   // nsILoadURIDelegate.
   loadURI(aUri, aWhere, aFlags, aTriggeringPrincipal) {
-    debug `loadURI: uri=${ aUri && aUri.spec
-                  } where=${ aWhere
-                  } flags=${ aFlags }`;
+    debug("loadURI " + (aUri && aUri.spec) + " " + aWhere + " " + aFlags);
 
     // TODO: Remove this when we have a sensible error API.
     if (aUri && aUri.displaySpec.startsWith("about:certerror")) {
       addEventListener("click", ErrorPageEventHandler, true);
     }
 
     return LoadURIDelegate.load(this.eventDispatcher, aUri, aWhere, aFlags,
                                 aTriggeringPrincipal);
   }
 }
 
-let {debug, warn} = GeckoViewNavigationContent.initLogging("GeckoViewNavigation");
-let module = GeckoViewNavigationContent.create(this);
+var navigationListener = new GeckoViewNavigationContent("GeckoViewNavigation", this);
--- a/mobile/android/chrome/geckoview/GeckoViewScrollContent.js
+++ b/mobile/android/chrome/geckoview/GeckoViewScrollContent.js
@@ -1,39 +1,46 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* 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/. */
 
 ChromeUtils.import("resource://gre/modules/GeckoViewContentModule.jsm");
+ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+    ChromeUtils.import("resource://gre/modules/AndroidLog.jsm",
+                       {}).AndroidLog.d.bind(null, "ViewScrollContent"));
+
+function debug(aMsg) {
+  // dump(aMsg);
+}
 
 class GeckoViewScrollContent extends GeckoViewContentModule {
   onEnable() {
-    debug `onEnable`;
+    debug("onEnable");
     addEventListener("scroll", this, false);
   }
 
   onDisable() {
-    debug `onDisable`;
+    debug("onDisable");
     removeEventListener("scroll", this);
   }
 
   handleEvent(aEvent) {
     if (aEvent.originalTarget.defaultView != content) {
       return;
     }
 
-    debug `handleEvent: ${aEvent.type}`;
+    debug("handleEvent " + aEvent.type);
 
     switch (aEvent.type) {
       case "scroll":
         this.eventDispatcher.sendRequest({
           type: "GeckoView:ScrollChanged",
           scrollX: Math.round(content.scrollX),
           scrollY: Math.round(content.scrollY)
         });
         break;
     }
   }
 }
-
-let {debug, warn} = GeckoViewScrollContent.initLogging("GeckoViewScroll");
-let module = GeckoViewScrollContent.create(this);
+var scrollListener = new GeckoViewScrollContent("GeckoViewScroll", this);
--- a/mobile/android/chrome/geckoview/GeckoViewSelectionActionContent.js
+++ b/mobile/android/chrome/geckoview/GeckoViewSelectionActionContent.js
@@ -5,16 +5,24 @@
 
 ChromeUtils.import("resource://gre/modules/GeckoViewContentModule.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
   Services: "resource://gre/modules/Services.jsm",
 });
 
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+    ChromeUtils.import("resource://gre/modules/AndroidLog.jsm",
+                       {}).AndroidLog.d.bind(null, "ViewSelectionActionContent"));
+
+function debug(aMsg) {
+  // dump(aMsg);
+}
+
 // Dispatches GeckoView:ShowSelectionAction and GeckoView:HideSelectionAction to
 // the GeckoSession on accessible caret changes.
 class GeckoViewSelectionActionContent extends GeckoViewContentModule {
   constructor(aModuleName, aMessageManager) {
     super(aModuleName, aMessageManager);
 
     this._seqNo = 0;
     this._isActive = false;
@@ -116,22 +124,22 @@ class GeckoViewSelectionActionContent ex
         break;
       }
     }
 
     return offset;
   }
 
   onEnable() {
-    debug `onEnable`;
+    debug("onEnable");
     addEventListener("mozcaretstatechanged", this, { mozSystemGroup: true });
   }
 
   onDisable() {
-    debug `onDisable`;
+    debug("onDisable");
     removeEventListener("mozcaretstatechanged", this, { mozSystemGroup: true });
   }
 
   /**
    * Receive and act on AccessibleCarets caret state-change
    * (mozcaretstatechanged) events.
    */
   handleEvent(aEvent) {
@@ -148,17 +156,17 @@ class GeckoViewSelectionActionContent ex
                reason !== "longpressonemptycontent" &&
                reason !== "taponcaret") {
       // Don't show selection actions when merely focusing on an editor or
       // repositioning the cursor. Wait until long press or the caret is tapped
       // in order to match Android behavior.
       reason = "visibilitychange";
     }
 
-    debug `handleEvent: ${reason}`;
+    debug("handleEvent " + reason + " " + aEvent);
 
     if (["longpressonemptycontent",
          "releasecaret",
          "taponcaret",
          "updateposition"].includes(reason)) {
 
       const actions = this._actions.filter(
           action => action.predicate.call(this, aEvent));
@@ -194,29 +202,31 @@ class GeckoViewSelectionActionContent ex
         // Don't call again if we're already active and things haven't changed.
         return;
       }
 
       msg.seqNo = ++this._seqNo;
       this._isActive = true;
       this._previousMessage = JSON.stringify(msg);
 
+      debug("onShowSelectionAction " + JSON.stringify(msg));
+
       // This event goes to GeckoViewSelectionAction.jsm, where the data is
       // further transformed and then sent to GeckoSession.
       this.eventDispatcher.sendRequest(msg, {
         onSuccess: response => {
           if (response.seqNo !== this._seqNo) {
             // Stale action.
             return;
           }
           let action = actions.find(action => action.id === response.id);
           if (action) {
             action.perform.call(this, aEvent, response);
           } else {
-            warn `Invalid action ${response.id}`;
+            dump("Invalid action " + response.id);
           }
         },
         onError: _ => {
           // Do nothing; we can get here if the delegate was just unregistered.
         },
       });
 
     } else if (["invisibleselection",
@@ -238,16 +248,15 @@ class GeckoViewSelectionActionContent ex
       }
 
       this.eventDispatcher.sendRequest({
         type: "GeckoView:HideSelectionAction",
         reason: reason,
       });
 
     } else {
-      warn `Unknown reason: ${reason}`;
+      dump("Unknown reason: " + reason);
     }
   }
 }
 
-let {debug, warn} =
-    GeckoViewSelectionActionContent.initLogging("GeckoViewSelectionAction");
-let module = GeckoViewSelectionActionContent.create(this);
+var selectionActionListener =
+    new GeckoViewSelectionActionContent("GeckoViewSelectionAction", this);
--- a/mobile/android/chrome/geckoview/geckoview.js
+++ b/mobile/android/chrome/geckoview/geckoview.js
@@ -1,44 +1,44 @@
 /* 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/AppConstants.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
-XPCOMUtils.defineLazyModuleGetters(this, {
-  EventDispatcher: "resource://gre/modules/Messaging.jsm",
-  GeckoViewUtils: "resource://gre/modules/GeckoViewUtils.jsm",
-  Services: "resource://gre/modules/Services.jsm",
-});
-
+ChromeUtils.defineModuleGetter(this, "EventDispatcher",
+  "resource://gre/modules/Messaging.jsm");
+ChromeUtils.defineModuleGetter(this, "Services",
+  "resource://gre/modules/Services.jsm");
 XPCOMUtils.defineLazyGetter(this, "WindowEventDispatcher",
   () => EventDispatcher.for(window));
 
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+    ChromeUtils.import("resource://gre/modules/AndroidLog.jsm",
+                       {}).AndroidLog.d.bind(null, "View"));
+
 // Creates and manages GeckoView modules.
 // A module must extend GeckoViewModule.
 // Instantiate a module by calling
 //   add(<resource path>, <type name>)
 // and remove by calling
 //   remove(<type name>)
 var ModuleManager = {
   init: function(aBrowser) {
     this.browser = aBrowser;
     this.modules = new Map();
   },
 
   add: function(aResource, aType, ...aArgs) {
     this.remove(aType);
-
-    const scope = {};
-    const global = ChromeUtils.import(aResource, scope);
-    const tag = aType.replace("GeckoView", "GeckoView.");
-    GeckoViewUtils.initLogging(tag, global);
+    let scope = {};
+    ChromeUtils.import(aResource, scope);
 
     this.modules.set(aType, new scope[aType](
       aType, window, this.browser, WindowEventDispatcher, ...aArgs
     ));
   },
 
   remove: function(aType) {
     this.modules.delete(aType);
@@ -53,18 +53,16 @@ function createBrowser() {
   const browser = window.browser = document.createElement("browser");
   browser.setAttribute("type", "content");
   browser.setAttribute("primary", "true");
   browser.setAttribute("flex", "1");
   return browser;
 }
 
 function startup() {
-  GeckoViewUtils.initLogging("GeckoView.XUL", window);
-
   const browser = createBrowser();
   ModuleManager.init(browser);
 
   ModuleManager.add("resource://gre/modules/GeckoViewNavigation.jsm",
                     "GeckoViewNavigation");
   ModuleManager.add("resource://gre/modules/GeckoViewSettings.jsm",
                     "GeckoViewSettings");
   ModuleManager.add("resource://gre/modules/GeckoViewContent.jsm",
--- a/mobile/android/components/geckoview/GeckoViewExternalAppService.js
+++ b/mobile/android/components/geckoview/GeckoViewExternalAppService.js
@@ -1,53 +1,55 @@
 /* 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/XPCOMUtils.jsm");
-ChromeUtils.import("resource://gre/modules/GeckoViewUtils.jsm");
-
-/* global debug:false, warn:false */
-GeckoViewUtils.initLogging("GeckoView.ExternalAppService", this);
 
 ChromeUtils.defineModuleGetter(this, "EventDispatcher",
   "resource://gre/modules/Messaging.jsm");
 
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+    ChromeUtils.import("resource://gre/modules/AndroidLog.jsm",
+                       {}).AndroidLog.d.bind(null, "ViewContent"));
+
+function debug(aMsg) {
+  // dump(aMsg);
+}
+
 function ExternalAppService() {
   this.wrappedJSObject = this;
 }
 
 ExternalAppService.prototype = {
   classID: Components.ID("{a89eeec6-6608-42ee-a4f8-04d425992f45}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIExternalHelperAppService]),
 
   doContent(mimeType, request, context, forceSave) {
     const channel = request.QueryInterface(Ci.nsIChannel);
     const mm = context.QueryInterface(Ci.nsIDocShell).tabChild.messageManager;
 
-    debug `doContent: uri=${ channel.URI.displaySpec
-                    } contentType=${ channel.contentType }`;
+    debug(`doContent() URI=${channel.URI.displaySpec}, contentType=${channel.contentType}`);
 
     EventDispatcher.forMessageManager(mm).sendRequest({
       type: "GeckoView:ExternalResponse",
       uri: channel.URI.displaySpec,
       contentType: channel.contentType,
       contentLength: channel.contentLength,
       filename: channel.contentDispositionFilename
     });
 
     request.cancel(Cr.NS_ERROR_ABORT);
     Components.returnCode = Cr.NS_ERROR_ABORT;
   },
 
   applyDecodingForExtension(ext, encoding) {
-    debug `applyDecodingForExtension: extension=${ ext
-                                    } encoding=${ encoding }`;
+    debug(`applyDecodingForExtension() extension=${ext}, encoding=${encoding}`);
 
     // This doesn't matter for us right now because
     // we shouldn't end up reading the stream.
     return true;
   }
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ExternalAppService]);
deleted file mode 100644
--- a/mobile/android/modules/geckoview/.eslintrc.js
+++ /dev/null
@@ -1,8 +0,0 @@
-"use strict";
-
-module.exports = {
-  "globals": {
-    "debug": false,
-    "warn": false,
-  },
-};
--- a/mobile/android/modules/geckoview/AndroidLog.jsm
+++ b/mobile/android/modules/geckoview/AndroidLog.jsm
@@ -48,36 +48,36 @@ if (typeof Components != "undefined") {
 // From <https://android.googlesource.com/platform/system/core/+/master/include/android/log.h>.
 const ANDROID_LOG_VERBOSE = 2;
 const ANDROID_LOG_DEBUG = 3;
 const ANDROID_LOG_INFO = 4;
 const ANDROID_LOG_WARN = 5;
 const ANDROID_LOG_ERROR = 6;
 
 // android.util.Log.isLoggable throws IllegalArgumentException if a tag length
-// exceeds 23 characters, and we prepend five characters ("Gecko") to every tag.
-// However, __android_log_write itself and other android.util.Log methods don't
-// seem to mind longer tags.
+// exceeds 23 characters, and we prepend five characters ("Gecko") to every tag,
+// so we truncate tags exceeding 18 characters (although __android_log_write
+// itself and other android.util.Log methods don't seem to mind longer tags).
 const MAX_TAG_LENGTH = 18;
 
 var liblog = ctypes.open("liblog.so"); // /system/lib/liblog.so
 var __android_log_write = liblog.declare("__android_log_write",
                                          ctypes.default_abi,
                                          ctypes.int, // return value: num bytes logged
                                          ctypes.int, // priority (ANDROID_LOG_* constant)
                                          ctypes.char.ptr, // tag
                                          ctypes.char.ptr); // message
 
 var AndroidLog = {
   MAX_TAG_LENGTH: MAX_TAG_LENGTH,
-  v: (tag, msg) => __android_log_write(ANDROID_LOG_VERBOSE, "Gecko" + tag, msg),
-  d: (tag, msg) => __android_log_write(ANDROID_LOG_DEBUG, "Gecko" + tag, msg),
-  i: (tag, msg) => __android_log_write(ANDROID_LOG_INFO, "Gecko" + tag, msg),
-  w: (tag, msg) => __android_log_write(ANDROID_LOG_WARN, "Gecko" + tag, msg),
-  e: (tag, msg) => __android_log_write(ANDROID_LOG_ERROR, "Gecko" + tag, msg),
+  v: (tag, msg) => __android_log_write(ANDROID_LOG_VERBOSE, "Gecko" + tag.substring(0, MAX_TAG_LENGTH), msg),
+  d: (tag, msg) => __android_log_write(ANDROID_LOG_DEBUG, "Gecko" + tag.substring(0, MAX_TAG_LENGTH), msg),
+  i: (tag, msg) => __android_log_write(ANDROID_LOG_INFO, "Gecko" + tag.substring(0, MAX_TAG_LENGTH), msg),
+  w: (tag, msg) => __android_log_write(ANDROID_LOG_WARN, "Gecko" + tag.substring(0, MAX_TAG_LENGTH), msg),
+  e: (tag, msg) => __android_log_write(ANDROID_LOG_ERROR, "Gecko" + tag.substring(0, MAX_TAG_LENGTH), msg),
 
   bind: function(tag) {
     return {
       MAX_TAG_LENGTH: MAX_TAG_LENGTH,
       v: AndroidLog.v.bind(null, tag),
       d: AndroidLog.d.bind(null, tag),
       i: AndroidLog.i.bind(null, tag),
       w: AndroidLog.w.bind(null, tag),
--- a/mobile/android/modules/geckoview/GeckoViewContent.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewContent.jsm
@@ -4,16 +4,24 @@
 
 "use strict";
 
 var EXPORTED_SYMBOLS = ["GeckoViewContent"];
 
 ChromeUtils.import("resource://gre/modules/GeckoViewModule.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+    ChromeUtils.import("resource://gre/modules/AndroidLog.jsm",
+                       {}).AndroidLog.d.bind(null, "ViewContent"));
+
+function debug(aMsg) {
+  // dump(aMsg);
+}
+
 class GeckoViewContent extends GeckoViewModule {
   onInit() {
     this.eventDispatcher.registerListener(this, [
       "GeckoView:SetActive"
     ]);
   }
 
   onEnable() {
@@ -42,18 +50,17 @@ class GeckoViewContent extends GeckoView
     this.unregisterListener();
 
     this.messageManager.removeMessageListener("GeckoView:DOMFullscreenExit", this);
     this.messageManager.removeMessageListener("GeckoView:DOMFullscreenRequest", this);
   }
 
   // Bundle event handler.
   onEvent(aEvent, aData, aCallback) {
-    debug `onEvent: event=${aEvent}, data=${aData}`;
-
+    debug("onEvent: " + aEvent);
     switch (aEvent) {
       case "GeckoViewContent:ExitFullScreen":
         this.messageManager.sendAsyncMessage("GeckoView:DOMFullscreenExited");
         break;
       case "GeckoView:ZoomToInput":
         this.messageManager.sendAsyncMessage(aEvent);
         break;
       case "GeckoView:SetActive":
@@ -67,34 +74,34 @@ class GeckoViewContent extends GeckoView
           this.browser.blur();
         }
         break;
     }
   }
 
   // DOM event handler
   handleEvent(aEvent) {
-    debug `handleEvent: ${aEvent.type}`;
+    debug("handleEvent: aEvent.type=" + aEvent.type);
 
     switch (aEvent.type) {
       case "MozDOMFullscreen:Entered":
         if (this.browser == aEvent.target) {
           // Remote browser; dispatch to content process.
           this.messageManager.sendAsyncMessage("GeckoView:DOMFullscreenEntered");
         }
         break;
       case "MozDOMFullscreen:Exited":
         this.messageManager.sendAsyncMessage("GeckoView:DOMFullscreenExited");
         break;
     }
   }
 
   // Message manager event handler.
   receiveMessage(aMsg) {
-    debug `receiveMessage: ${aMsg.name}`;
+    debug("receiveMessage " + aMsg.name);
 
     switch (aMsg.name) {
       case "GeckoView:DOMFullscreenExit":
         this.window.QueryInterface(Ci.nsIInterfaceRequestor)
                    .getInterface(Ci.nsIDOMWindowUtils)
                    .remoteFrameFullscreenReverted();
         break;
       case "GeckoView:DOMFullscreenRequest":
--- a/mobile/android/modules/geckoview/GeckoViewContentModule.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewContentModule.jsm
@@ -2,34 +2,29 @@
  * 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";
 
 var EXPORTED_SYMBOLS = ["GeckoViewContentModule"];
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-ChromeUtils.import("resource://gre/modules/GeckoViewUtils.jsm");
-
-GeckoViewUtils.initLogging("GeckoView.Module.[C]", this);
 
 ChromeUtils.defineModuleGetter(this, "EventDispatcher",
   "resource://gre/modules/Messaging.jsm");
 
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+    ChromeUtils.import("resource://gre/modules/AndroidLog.jsm",
+                       {}).AndroidLog.d.bind(null, "ViewContentModule"));
+
+// function debug(aMsg) {
+//   dump(aMsg);
+// }
+
 class GeckoViewContentModule {
-  static initLogging(aModuleName) {
-    this._moduleName = aModuleName;
-    const tag = aModuleName.replace("GeckoView", "GeckoView.") + ".[C]";
-    return GeckoViewUtils.initLogging(tag, {});
-  }
-
-  static create(aGlobal, aModuleName) {
-    return new this(aModuleName || this._moduleName, aGlobal);
-  }
-
   constructor(aModuleName, aMessageManager) {
     this.moduleName = aModuleName;
     this.messageManager = aMessageManager;
     this.eventDispatcher = EventDispatcher.forMessageManager(aMessageManager);
 
     this.messageManager.addMessageListener(
       "GeckoView:UpdateSettings",
       aMsg => {
--- a/mobile/android/modules/geckoview/GeckoViewModule.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewModule.jsm
@@ -2,19 +2,24 @@
  * 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";
 
 var EXPORTED_SYMBOLS = ["GeckoViewModule"];
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-ChromeUtils.import("resource://gre/modules/GeckoViewUtils.jsm");
 
-GeckoViewUtils.initLogging("GeckoView.Module", this);
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+    ChromeUtils.import("resource://gre/modules/AndroidLog.jsm",
+                       {}).AndroidLog.d.bind(null, "ViewModule"));
+
+// function debug(aMsg) {
+//   dump(aMsg);
+// }
 
 class GeckoViewModule {
   constructor(aModuleName, aWindow, aBrowser, aEventDispatcher) {
     this.isRegistered = false;
     this.window = aWindow;
     this.browser = aBrowser;
     this.eventDispatcher = aEventDispatcher;
     this.moduleName = aModuleName;
@@ -126,53 +131,53 @@ class EventProxy {
     this.listener = aListener;
     this.eventDispatcher = aEventDispatcher;
     this._eventQueue = [];
     this._registeredEvents = [];
     this._enableQueuing = false;
   }
 
   registerListener(aEventList) {
-    debug `registerListener ${aEventList}`;
+    debug("register " + aEventList);
     this.eventDispatcher.registerListener(this, aEventList);
     this._registeredEvents = this._registeredEvents.concat(aEventList);
   }
 
   unregisterListener() {
-    debug `unregisterListener`;
+    debug("unregister");
     if (this._registeredEvents.length === 0) {
       return;
     }
     this.eventDispatcher.unregisterListener(this, this._registeredEvents);
     this._registeredEvents = [];
   }
 
   onEvent(aEvent, aData, aCallback) {
     if (this._enableQueuing) {
-      debug `queue ${aEvent}, data=${aData}`;
+      debug("queue " + aEvent + ", aData=" + JSON.stringify(aData));
       this._eventQueue.unshift(arguments);
     } else {
       this._dispatch(...arguments);
     }
   }
 
   enableQueuing(aEnable) {
-    debug `enableQueuing ${aEnable}`;
+    debug("enableQueuing " + aEnable);
     this._enableQueuing = aEnable;
   }
 
   _dispatch(aEvent, aData, aCallback) {
-    debug `dispatch ${aEvent}, data=${aData}`;
+    debug("dispatch " + aEvent + ", aData=" + JSON.stringify(aData));
     if (this.listener.onEvent) {
       this.listener.onEvent(...arguments);
     } else {
       this.listener(...arguments);
     }
   }
 
   dispatchQueuedEvents() {
-    debug `dispatchQueued`;
+    debug("dispatchQueued");
     while (this._eventQueue.length) {
       const args = this._eventQueue.pop();
       this._dispatch(...args);
     }
   }
 }
--- a/mobile/android/modules/geckoview/GeckoViewNavigation.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewNavigation.jsm
@@ -13,16 +13,24 @@ ChromeUtils.defineModuleGetter(this, "Br
                                "resource://gre/modules/BrowserUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
   EventDispatcher: "resource://gre/modules/Messaging.jsm",
   LoadURIDelegate: "resource://gre/modules/LoadURIDelegate.jsm",
   Services: "resource://gre/modules/Services.jsm",
 });
 
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+    ChromeUtils.import("resource://gre/modules/AndroidLog.jsm",
+                       {}).AndroidLog.d.bind(null, "ViewNavigation"));
+
+function debug(aMsg) {
+  // dump(aMsg);
+}
+
 // Handles navigation requests between Gecko and a GeckoView.
 // Handles GeckoView:GoBack and :GoForward requests dispatched by
 // GeckoView.goBack and .goForward.
 // Dispatches GeckoView:LocationChange to the GeckoView on location change when
 // active.
 // Implements nsIBrowserDOMWindow.
 class GeckoViewNavigation extends GeckoViewModule {
   onInitBrowser() {
@@ -41,17 +49,17 @@ class GeckoViewNavigation extends GeckoV
       "GeckoView:LoadUri",
       "GeckoView:Reload",
       "GeckoView:Stop"
     ]);
   }
 
   // Bundle event handler.
   onEvent(aEvent, aData, aCallback) {
-    debug `onEvent: event=${aEvent}, data=${aData}`;
+    debug("onEvent: aEvent=" + aEvent + ", aData=" + JSON.stringify(aData));
 
     switch (aEvent) {
       case "GeckoView:GoBack":
         this.browser.goBack();
         break;
       case "GeckoView:GoForward":
         this.browser.goForward();
         break;
@@ -88,17 +96,17 @@ class GeckoViewNavigation extends GeckoV
       case "GeckoView:Stop":
         this.browser.stop();
         break;
     }
   }
 
   // Message manager event handler.
   receiveMessage(aMsg) {
-    debug `receiveMessage: ${aMsg.name}`;
+    debug("receiveMessage " + aMsg.name);
   }
 
   waitAndSetOpener(aSessionId, aOpener) {
     if (!aSessionId) {
       return Promise.resolve(null);
     }
 
     return new Promise(resolve => {
@@ -115,19 +123,19 @@ class GeckoViewNavigation extends GeckoV
       };
 
       // This event is emitted from createBrowser() in geckoview.js
       Services.obs.addObserver(handler, "geckoview-window-created");
     });
   }
 
   handleNewSession(aUri, aOpener, aWhere, aFlags, aTriggeringPrincipal) {
-    debug `handleNewSession: uri=${ aUri && aUri.spec
-                           } where=${ aWhere
-                           } flags=${ aFlags }`;
+    debug("handleNewSession: aUri=" + (aUri && aUri.spec) +
+          " aWhere=" + aWhere +
+          " aFlags=" + aFlags);
 
     if (!this.isRegistered) {
       return null;
     }
 
     const message = {
       type: "GeckoView:OnNewSession",
       uri: aUri ? aUri.displaySpec : ""
@@ -145,19 +153,19 @@ class GeckoViewNavigation extends GeckoV
 
     // Wait indefinitely for app to respond with a browser or null
     Services.tm.spinEventLoopUntil(() => browser !== undefined);
     return browser;
   }
 
   // nsIBrowserDOMWindow.
   createContentWindow(aUri, aOpener, aWhere, aFlags, aTriggeringPrincipal) {
-    debug `createContentWindow: uri=${ aUri && aUri.spec
-                              } where=${ aWhere
-                              } flags=${ aFlags }`;
+    debug("createContentWindow: aUri=" + (aUri && aUri.spec) +
+          " aWhere=" + aWhere +
+          " aFlags=" + aFlags);
 
     if (LoadURIDelegate.load(this.eventDispatcher, aUri, aWhere, aFlags,
                              aTriggeringPrincipal)) {
       // The app has handled the load, abort open-window handling.
       Components.returnCode = Cr.NS_ERROR_ABORT;
       return null;
     }
 
@@ -169,22 +177,22 @@ class GeckoViewNavigation extends GeckoV
     }
 
     return browser.contentWindow;
   }
 
   // nsIBrowserDOMWindow.
   createContentWindowInFrame(aUri, aParams, aWhere, aFlags, aNextTabParentId,
                              aName) {
-    debug `createContentWindowInFrame: uri=${ aUri && aUri.spec
-                                     } params=${ aParams
-                                     } where=${ aWhere
-                                     } flags=${ aFlags
-                                     } nextTabParentId=${ aNextTabParentId
-                                     } name=${ aName }`;
+    debug("createContentWindowInFrame: aUri=" + (aUri && aUri.spec) +
+          " aParams=" + aParams +
+          " aWhere=" + aWhere +
+          " aFlags=" + aFlags +
+          " aNextTabParentId=" + aNextTabParentId +
+          " aName=" + aName);
 
     if (LoadURIDelegate.load(this.eventDispatcher, aUri, aWhere, aFlags, null)) {
       // The app has handled the load, abort open-window handling.
       Components.returnCode = Cr.NS_ERROR_ABORT;
       return null;
     }
 
     const browser = this.handleNewSession(aUri, null, aWhere, aFlags, null);
@@ -194,19 +202,19 @@ class GeckoViewNavigation extends GeckoV
     }
 
     browser.setAttribute("nextTabParentId", aNextTabParentId);
     return browser;
   }
 
   handleOpenUri(aUri, aOpener, aWhere, aFlags, aTriggeringPrincipal,
                 aNextTabParentId) {
-    debug `handleOpenUri: uri=${ aUri && aUri.spec
-                        } where=${ aWhere
-                        } flags=${ aFlags }`;
+    debug("handleOpenUri: aUri=" + (aUri && aUri.spec) +
+          " aWhere=" + aWhere +
+          " aFlags=" + aFlags);
 
     if (LoadURIDelegate.load(this.eventDispatcher, aUri, aWhere, aFlags,
                              aTriggeringPrincipal)) {
       return null;
     }
 
     let browser = this.browser;
 
@@ -241,57 +249,59 @@ class GeckoViewNavigation extends GeckoV
 
   // nsIBrowserDOMWindow.
   isTabContentWindow(aWindow) {
     return this.browser.contentWindow === aWindow;
   }
 
   // nsIBrowserDOMWindow.
   canClose() {
-    debug `canClose`;
+    debug("canClose");
     return true;
   }
 
   onEnable() {
-    debug `onEnable`;
+    debug("onEnable");
 
     this.registerContent(
       "chrome://geckoview/content/GeckoViewNavigationContent.js");
 
     let flags = Ci.nsIWebProgress.NOTIFY_LOCATION;
     this.progressFilter =
       Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
       .createInstance(Ci.nsIWebProgress);
     this.progressFilter.addProgressListener(this, flags);
     this.browser.addProgressListener(this.progressFilter, flags);
   }
 
   onDisable() {
-    debug `onDisable`;
+    debug("onDisable");
 
     if (!this.progressFilter) {
       return;
     }
     this.progressFilter.removeProgressListener(this);
     this.browser.removeProgressListener(this.progressFilter);
   }
 
   // WebProgress event handler.
   onLocationChange(aWebProgress, aRequest, aLocationURI, aFlags) {
-    debug `onLocationChange`;
+    debug("onLocationChange");
 
     let fixedURI = aLocationURI;
 
     try {
       fixedURI = Services.uriFixup.createExposableURI(aLocationURI);
     } catch (ex) { }
 
     let message = {
       type: "GeckoView:LocationChange",
       uri: fixedURI.displaySpec,
       canGoBack: this.browser.canGoBack,
       canGoForward: this.browser.canGoForward,
       isTopLevel: aWebProgress.isTopLevel,
     };
 
+    debug("dispatch " + JSON.stringify(message));
+
     this.eventDispatcher.sendRequest(message);
   }
 }
--- a/mobile/android/modules/geckoview/GeckoViewProgress.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewProgress.jsm
@@ -11,16 +11,24 @@ ChromeUtils.import("resource://gre/modul
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "OverrideService",
   "@mozilla.org/security/certoverride;1", "nsICertOverrideService");
 
 XPCOMUtils.defineLazyServiceGetter(this, "IDNService",
   "@mozilla.org/network/idn-service;1", "nsIIDNService");
 
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+    ChromeUtils.import("resource://gre/modules/AndroidLog.jsm",
+                       {}).AndroidLog.d.bind(null, "ViewProgress"));
+
+function debug(aMsg) {
+  // dump(aMsg);
+}
+
 var IdentityHandler = {
   // The definitions below should be kept in sync with those in GeckoView.ProgressListener.SecurityInformation
   // No trusted identity information. No site identity icon is shown.
   IDENTITY_MODE_UNKNOWN: 0,
 
   // Domain-Validation SSL CA-signed domain verification (DV).
   IDENTITY_MODE_IDENTIFIED: 1,
 
@@ -179,56 +187,54 @@ var IdentityHandler = {
 };
 
 class GeckoViewProgress extends GeckoViewModule {
   onInit() {
     this._hostChanged = false;
   }
 
   onEnable() {
-    debug `onEnable`;
+    debug("onEnable");
 
     let flags = Ci.nsIWebProgress.NOTIFY_STATE_NETWORK |
                 Ci.nsIWebProgress.NOTIFY_SECURITY |
                 Ci.nsIWebProgress.NOTIFY_LOCATION;
     this.progressFilter =
       Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
       .createInstance(Ci.nsIWebProgress);
     this.progressFilter.addProgressListener(this, flags);
     this.browser.addProgressListener(this.progressFilter, flags);
   }
 
   onDisable() {
-    debug `onDisable`;
+    debug("onDisable");
 
     if (this.progressFilter) {
       this.progressFilter.removeProgressListener(this);
       this.browser.removeProgressListener(this.progressFilter);
     }
   }
 
   onSettingsUpdate() {
-    const settings = this.settings;
-    debug `onSettingsUpdate: ${settings}`;
+    let settings = this.settings;
+    debug("onSettingsUpdate: " + JSON.stringify(settings));
 
     IdentityHandler.setUseTrackingProtection(!!settings.useTrackingProtection);
     IdentityHandler.setUsePrivateMode(!!settings.usePrivateMode);
   }
 
   onStateChange(aWebProgress, aRequest, aStateFlags, aStatus) {
-    debug `onStateChange: isTopLevel=${ aWebProgress.isTopLevel
-                       }, flags=${ aStateFlags
-                       }, status=${ aStatus }`;
+    debug(`onStateChange() isTopLevel=${aWebProgress.isTopLevel}, stateFlags=${aStateFlags}, state=${aStatus}`);
 
     if (!aWebProgress.isTopLevel) {
       return;
     }
 
     const uriSpec = aRequest.QueryInterface(Ci.nsIChannel).URI.displaySpec;
-    debug `onStateChange: uri=${uriSpec}`;
+    debug(`onStateChange() URI=${uriSpec}`);
 
     if (aStateFlags & Ci.nsIWebProgressListener.STATE_START) {
       const message = {
         type: "GeckoView:PageStart",
         uri: uriSpec,
       };
 
       this.eventDispatcher.sendRequest(message);
@@ -239,17 +245,17 @@ class GeckoViewProgress extends GeckoVie
         success: !aStatus
       };
 
       this.eventDispatcher.sendRequest(message);
     }
   }
 
   onSecurityChange(aWebProgress, aRequest, aState) {
-    debug `onSecurityChange`;
+    debug("onSecurityChange()");
 
     // Don't need to do anything if the data we use to update the UI hasn't changed
     if (this._state === aState && !this._hostChanged) {
       return;
     }
 
     this._state = aState;
     this._hostChanged = false;
@@ -260,18 +266,17 @@ class GeckoViewProgress extends GeckoVie
       type: "GeckoView:SecurityChanged",
       identity: identity
     };
 
     this.eventDispatcher.sendRequest(message);
   }
 
   onLocationChange(aWebProgress, aRequest, aLocationURI, aFlags) {
-    debug `onLocationChange: location=${ aLocationURI.displaySpec
-                          }, flags=${ aFlags }`;
+    debug(`onLocationChange() location=${aLocationURI.displaySpec}, flags=${aFlags}`);
 
     this._hostChanged = true;
     if (aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) {
       // We apparently don't get a STATE_STOP in onStateChange(), so emit PageStop here
       this.eventDispatcher.sendRequest({
         type: "GeckoView:PageStop",
         success: false
       });
--- a/mobile/android/modules/geckoview/GeckoViewRemoteDebugger.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewRemoteDebugger.jsm
@@ -5,22 +5,30 @@
 "use strict";
 
 var EXPORTED_SYMBOLS = ["GeckoViewRemoteDebugger"];
 
 ChromeUtils.import("resource://gre/modules/GeckoViewModule.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+  ChromeUtils.import("resource://gre/modules/AndroidLog.jsm", {})
+    .AndroidLog.d.bind(null, "ViewRemoteDebugger"));
+
 XPCOMUtils.defineLazyGetter(this, "DebuggerServer", () => {
   const { require } = ChromeUtils.import("resource://devtools/shared/Loader.jsm", {});
   const { DebuggerServer } = require("devtools/server/main");
   return DebuggerServer;
 });
 
+function debug(aMsg) {
+  // dump(aMsg);
+}
+
 class GeckoViewRemoteDebugger extends GeckoViewModule {
   onInit() {
     this._isEnabled = false;
     this._usbDebugger = new USBRemoteDebugger();
   }
 
   onSettingsUpdate() {
     let enabled = this.settings.useRemoteDebugger;
@@ -42,17 +50,17 @@ class GeckoViewRemoteDebugger extends Ge
     let windowId = this.window.QueryInterface(Ci.nsIInterfaceRequestor)
                               .getInterface(Ci.nsIDOMWindowUtils)
                               .outerWindowID;
     let env = Cc["@mozilla.org/process/environment;1"]
               .getService(Ci.nsIEnvironment);
     let dataDir = env.get("MOZ_ANDROID_DATA_DIR");
 
     if (!dataDir) {
-      warn `Missing env MOZ_ANDROID_DATA_DIR - aborting debugger server start`;
+      debug("Missing env MOZ_ANDROID_DATA_DIR - aborting debugger server start");
       return;
     }
 
     this._isEnabled = true;
     this._usbDebugger.stop();
 
     let portOrPath = dataDir + "/firefox-debugger-socket-" + windowId;
     this._usbDebugger.start(portOrPath);
@@ -69,32 +77,32 @@ class USBRemoteDebugger {
     try {
       let AuthenticatorType = DebuggerServer.Authenticators.get("PROMPT");
       let authenticator = new AuthenticatorType.Server();
       authenticator.allowConnection = this.allowConnection.bind(this);
       this._listener = DebuggerServer.createListener();
       this._listener.portOrPath = aPortOrPath;
       this._listener.authenticator = authenticator;
       this._listener.open();
-      debug `USB remote debugger - listening on ${aPortOrPath}`;
+      debug(`USB remote debugger - listening on ${aPortOrPath}`);
     } catch (e) {
-      warn `Unable to start USB debugger server: ${e}`;
+      debug("Unable to start USB debugger server: " + e);
     }
   }
 
   stop() {
     if (!this._listener) {
       return;
     }
 
     try {
       this._listener.close();
       this._listener = null;
     } catch (e) {
-      warn `Unable to stop USB debugger server: ${e}`;
+      debug("Unable to stop USB debugger server: " + e);
     }
   }
 
   allowConnection(aSession) {
     if (!this._listener) {
       return DebuggerServer.AuthenticationResult.DENY;
     }
 
--- a/mobile/android/modules/geckoview/GeckoViewScroll.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewScroll.jsm
@@ -4,14 +4,22 @@
 
 "use strict";
 
 var EXPORTED_SYMBOLS = ["GeckoViewScroll"];
 
 ChromeUtils.import("resource://gre/modules/GeckoViewModule.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+    ChromeUtils.import("resource://gre/modules/AndroidLog.jsm",
+                       {}).AndroidLog.d.bind(null, "ViewScroll"));
+
+function debug(aMsg) {
+  // dump(aMsg);
+}
+
 class GeckoViewScroll extends GeckoViewModule {
   onEnable() {
-    debug `onEnable`;
+    debug("onEnable");
     this.registerContent("chrome://geckoview/content/GeckoViewScrollContent.js");
   }
 }
--- a/mobile/android/modules/geckoview/GeckoViewSelectionAction.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewSelectionAction.jsm
@@ -4,15 +4,23 @@
 
 "use strict";
 
 var EXPORTED_SYMBOLS = ["GeckoViewSelectionAction"];
 
 ChromeUtils.import("resource://gre/modules/GeckoViewModule.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+    ChromeUtils.import("resource://gre/modules/AndroidLog.jsm",
+                       {}).AndroidLog.d.bind(null, "ViewSelectionAction"));
+
+function debug(aMsg) {
+  // dump(aMsg);
+}
+
 // Handles inter-op between accessible carets and GeckoSession.
 class GeckoViewSelectionAction extends GeckoViewModule {
   onEnable() {
-    debug `onEnable`;
+    debug("onEnable");
     this.registerContent("chrome://geckoview/content/GeckoViewSelectionActionContent.js");
   }
 }
--- a/mobile/android/modules/geckoview/GeckoViewSettings.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewSettings.jsm
@@ -24,16 +24,24 @@ XPCOMUtils.defineLazyGetter(
   this, "DESKTOP_USER_AGENT",
   function() {
     return Cc["@mozilla.org/network/protocol;1?name=http"]
            .getService(Ci.nsIHttpProtocolHandler).userAgent
            .replace(/Android \d.+?; [a-zA-Z]+/, "X11; Linux x86_64")
            .replace(/Gecko\/[0-9\.]+/, "Gecko/20100101");
   });
 
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+    ChromeUtils.import("resource://gre/modules/AndroidLog.jsm",
+                       {}).AndroidLog.d.bind(null, "ViewSettings"));
+
+function debug(aMsg) {
+  // dump(aMsg);
+}
+
 // Handles GeckoView settings including:
 // * multiprocess
 // * user agent override
 class GeckoViewSettings extends GeckoViewModule {
   onInitBrowser() {
     if (this.settings.useMultiprocess) {
       this.browser.setAttribute("remote", "true");
     }
@@ -43,39 +51,38 @@ class GeckoViewSettings extends GeckoVie
     this._useTrackingProtection = false;
     this._useDesktopMode = false;
 
     this.registerContent(
         "chrome://geckoview/content/GeckoViewContentSettings.js");
   }
 
   onSettingsUpdate() {
-    const settings = this.settings;
-    debug `onSettingsUpdate: ${settings}`;
+    debug("onSettingsUpdate: " + JSON.stringify(this.settings));
 
-    this.displayMode = settings.displayMode;
-    this.useTrackingProtection = !!settings.useTrackingProtection;
-    this.useDesktopMode = !!settings.useDesktopMode;
+    this.displayMode = this.settings.displayMode;
+    this.useTrackingProtection = !!this.settings.useTrackingProtection;
+    this.useDesktopMode = !!this.settings.useDesktopMode;
   }
 
   get useMultiprocess() {
     return this.browser.isRemoteBrowser;
   }
 
   get useTrackingProtection() {
     return this._useTrackingProtection;
   }
 
   set useTrackingProtection(aUse) {
     aUse && SafeBrowsing;
     this._useTrackingProtection = aUse;
   }
 
   onUserAgentRequest(aSubject, aTopic, aData) {
-    debug `onUserAgentRequest`;
+    debug("onUserAgentRequest");
 
     let channel = aSubject.QueryInterface(Ci.nsIHttpChannel);
 
     if (this.browser.outerWindowID !== channel.topLevelOuterContentWindowId) {
       return;
     }
 
     if (this.useDesktopMode) {
--- a/mobile/android/modules/geckoview/GeckoViewTab.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewTab.jsm
@@ -4,16 +4,24 @@
 
 "use strict";
 
 var EXPORTED_SYMBOLS = ["GeckoViewTab"];
 
 ChromeUtils.import("resource://gre/modules/GeckoViewModule.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+    ChromeUtils.import("resource://gre/modules/AndroidLog.jsm",
+                       {}).AndroidLog.d.bind(null, "ViewTab"));
+
+// function debug(aMsg) {
+//   dump(aMsg);
+// }
+
 // Stub BrowserApp implementation for WebExtensions support.
 class GeckoViewTab extends GeckoViewModule {
   onInit() {
     this.browser.tab = { id: 0, browser: this.browser };
 
     this.window.gBrowser = this.window.BrowserApp = {
       selectedBrowser: this.browser,
       tabs: [this.browser.tab],
--- a/mobile/android/modules/geckoview/GeckoViewTrackingProtection.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewTrackingProtection.jsm
@@ -4,30 +4,38 @@
 
 "use strict";
 
 var EXPORTED_SYMBOLS = ["GeckoViewTrackingProtection"];
 
 ChromeUtils.import("resource://gre/modules/GeckoViewModule.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
+XPCOMUtils.defineLazyGetter(this, "dump", () =>
+    ChromeUtils.import("resource://gre/modules/AndroidLog.jsm",
+              {}).AndroidLog.d.bind(null, "ViewTrackingProtection"));
+
+function debug(aMsg) {
+  // dump(aMsg);
+}
+
 class GeckoViewTrackingProtection extends GeckoViewModule {
   onEnable() {
-    debug `onEnable`;
+    debug("onEnable");
 
     const flags = Ci.nsIWebProgress.NOTIFY_SECURITY;
     this.progressFilter =
       Cc["@mozilla.org/appshell/component/browser-status-filter;1"]
       .createInstance(Ci.nsIWebProgress);
     this.progressFilter.addProgressListener(this, flags);
     this.browser.addProgressListener(this.progressFilter, flags);
   }
 
   onSecurityChange(aWebProgress, aRequest, aState) {
-    debug `onSecurityChange`;
+    debug("onSecurityChange");
 
     if (!(aState & Ci.nsIWebProgressListener.STATE_BLOCKED_TRACKING_CONTENT) ||
         !aRequest || !(aRequest instanceof Ci.nsIClassifiedChannel)) {
       return;
     }
 
     let channel = aRequest.QueryInterface(Ci.nsIChannel);
     let uri = channel.URI && channel.URI.spec;
--- a/mobile/android/modules/geckoview/GeckoViewUtils.jsm
+++ b/mobile/android/modules/geckoview/GeckoViewUtils.jsm
@@ -1,19 +1,18 @@
 /* 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/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyModuleGetters(this, {
+  Services: "resource://gre/modules/Services.jsm",
   EventDispatcher: "resource://gre/modules/Messaging.jsm",
-  Log: "resource://gre/modules/Log.jsm",
-  Services: "resource://gre/modules/Services.jsm",
 });
 
 var EXPORTED_SYMBOLS = ["GeckoViewUtils"];
 
 var GeckoViewUtils = {
   /**
    * Define a lazy getter that loads an object from external code, and
    * optionally handles observer and/or message manager notifications for the
@@ -248,96 +247,12 @@ var GeckoViewUtils = {
       dispatcher = this.getDispatcherForWindow(
           iter.getNext().QueryInterface(Ci.nsIDOMWindow));
       if (dispatcher) {
         return dispatcher;
       }
     }
     return null;
   },
-
-  /**
-   * Add logging functions to the specified scope that forward to the given
-   * Log.jsm logger. Currently "debug" and "warn" functions are supported. To
-   * log something, call the function through a template literal:
-   *
-   *   function foo(bar, baz) {
-   *     debug `hello world`;
-   *     debug `foo called with ${bar} as bar`;
-   *     warn `this is a warning for ${baz}`;
-   *   }
-   *
-   * An inline format can also be used for logging:
-   *
-   *   let bar = 42;
-   *   do_something(bar); // No log.
-   *   do_something(debug.foo = bar); // Output "foo = 42" to the log.
-   *
-   * @param tag Name of the Log.jsm logger to forward logs to.
-   * @param scope Scope to add the logging functions to.
-   */
-  initLogging: function(tag, scope) {
-    // Only provide two levels for simplicity.
-    // For "info", use "debug" instead.
-    // For "error", throw an actual JS error instead.
-    for (const level of ["debug", "warn"]) {
-      const log = (strings, ...exprs) =>
-          this._log(log.logger, level, strings, exprs);
-
-      XPCOMUtils.defineLazyGetter(log, "logger", _ => {
-        const logger = Log.repository.getLogger(tag);
-        logger.parent = this.rootLogger;
-        return logger;
-      });
-
-      scope[level] = new Proxy(log, {
-        set: (obj, prop, value) => obj([prop + " = ", ""], value) || true,
-      });
-    }
-    return scope;
-  },
-
-  get rootLogger() {
-    if (!this._rootLogger) {
-      this._rootLogger = Log.repository.getLogger("GeckoView");
-      this._rootLogger.addAppender(new Log.AndroidAppender());
-    }
-    return this._rootLogger;
-  },
-
-  _log: function(logger, level, strings, exprs) {
-    if (!Array.isArray(strings)) {
-      const [, file, line] =
-          (new Error()).stack.match(/.*\n.*\n.*@(.*):(\d+):/);
-      throw Error(`Expecting template literal: ${level} \`foo \${bar}\``,
-                  file, +line);
-    }
-
-    // Do some GeckoView-specific formatting:
-    // 1) Heuristically format flags as hex.
-    // 2) Heuristically format nsresult as string name or hex.
-    for (let i = 0; i < exprs.length; i++) {
-      const expr = exprs[i];
-      switch (typeof expr) {
-        case "number":
-          if (expr > 0 && /\ba?[fF]lags?[\s=:]+$/.test(strings[i])) {
-            // Likely a flag; display in hex.
-            exprs[i] = `0x${expr.toString(0x10)}`;
-          } else if (expr >= 0 && /\b(a?[sS]tatus|rv)[\s=:]+$/.test(strings[i])) {
-            // Likely an nsresult; display in name or hex.
-            exprs[i] = `0x${expr.toString(0x10)}`;
-            for (const name in Cr) {
-              if (expr === Cr[name]) {
-                exprs[i] = name;
-                break;
-              }
-            }
-          }
-          break;
-      }
-    }
-
-    return logger[level](strings, ...exprs);
-  },
 };
 
 XPCOMUtils.defineLazyGetter(GeckoViewUtils, "IS_PARENT_PROCESS", _ =>
     Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_DEFAULT);
--- a/toolkit/modules/Log.jsm
+++ b/toolkit/modules/Log.jsm
@@ -9,22 +9,22 @@ var EXPORTED_SYMBOLS = ["Log"];
 const ONE_BYTE = 1;
 const ONE_KILOBYTE = 1024 * ONE_BYTE;
 const ONE_MEGABYTE = 1024 * ONE_KILOBYTE;
 
 const STREAM_SEGMENT_SIZE = 4096;
 const PR_UINT32_MAX = 0xffffffff;
 
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-XPCOMUtils.defineLazyModuleGetters(this, {
-  AndroidLog: "resource://gre/modules/AndroidLog.jsm", // Only used on Android.
-  OS: "resource://gre/modules/osfile.jsm",
-  Services: "resource://gre/modules/Services.jsm",
-  Task: "resource://gre/modules/Task.jsm",
-});
+ChromeUtils.defineModuleGetter(this, "OS",
+                               "resource://gre/modules/osfile.jsm");
+ChromeUtils.defineModuleGetter(this, "Task",
+                               "resource://gre/modules/Task.jsm");
+ChromeUtils.defineModuleGetter(this, "Services",
+                               "resource://gre/modules/Services.jsm");
 const INTERNAL_FIELDS = new Set(["_level", "_message", "_time", "_namespace"]);
 
 
 /*
  * Dump a message everywhere we can if we have a failure.
  */
 function dumpError(text) {
   dump(text + "\n");
@@ -81,17 +81,16 @@ var Log = {
   BasicFormatter,
   MessageOnlyFormatter,
   StructuredFormatter,
 
   Appender,
   DumpAppender,
   ConsoleAppender,
   StorageStreamAppender,
-  AndroidAppender,
 
   FileAppender,
   BoundedFileAppender,
 
   ParameterFormatter,
   // Logging helper:
   // let logger = Log.repository.getLogger("foo");
   // logger.info(Log.enumerateInterfaces(someObject).join(","));
@@ -413,85 +412,54 @@ Logger.prototype = {
     } else {
       level = this.level;
     }
 
     params.action = action;
     this.log(level, params._message, params);
   },
 
-  _unpackTemplateLiteral(string, params) {
-    if (!Array.isArray(params)) {
-      // Regular log() call.
-      return [string, params];
-    }
-
-    if (!Array.isArray(string)) {
-      // Not using template literal. However params was packed into an array by
-      // the this.[level] call, so we need to unpack it here.
-      return [string, params[0]];
-    }
-
-    // We're using template literal format (logger.warn `foo ${bar}`). Turn the
-    // template strings into one string containing "${0}"..."${n}" tokens, and
-    // feed it to the basic formatter. The formatter will treat the numbers as
-    // indices into the params array, and convert the tokens to the params.
-
-    if (!params.length) {
-      // No params; we need to set params to undefined, so the formatter
-      // doesn't try to output the params array.
-      return [string[0], undefined];
-    }
-
-    let concat = string[0];
-    for (let i = 0; i < params.length; i++) {
-      concat += `\${${i}}${string[i + 1]}`;
-    }
-    return [concat, params];
-  },
-
   log(level, string, params) {
     if (this.level > level)
       return;
 
     // Hold off on creating the message object until we actually have
     // an appender that's responsible.
     let message;
     let appenders = this.appenders;
     for (let appender of appenders) {
       if (appender.level > level) {
         continue;
       }
       if (!message) {
-        [string, params] = this._unpackTemplateLiteral(string, params);
         message = new LogMessage(this._name, level, string, params);
       }
       appender.append(message);
     }
   },
 
-  fatal(string, ...params) {
+  fatal(string, params) {
     this.log(Log.Level.Fatal, string, params);
   },
-  error(string, ...params) {
+  error(string, params) {
     this.log(Log.Level.Error, string, params);
   },
-  warn(string, ...params) {
+  warn(string, params) {
     this.log(Log.Level.Warn, string, params);
   },
-  info(string, ...params) {
+  info(string, params) {
     this.log(Log.Level.Info, string, params);
   },
-  config(string, ...params) {
+  config(string, params) {
     this.log(Log.Level.Config, string, params);
   },
-  debug(string, ...params) {
+  debug(string, params) {
     this.log(Log.Level.Debug, string, params);
   },
-  trace(string, ...params) {
+  trace(string, params) {
     this.log(Log.Level.Trace, string, params);
   }
 };
 
 /*
  * LoggerRepository
  * Implements a hierarchy of Loggers
  */
@@ -574,26 +542,17 @@ LoggerRepository.prototype = {
    *        (string) The Logger to retrieve.
    * @param prefix
    *        (string) The string to prefix each logged message with.
    */
   getLoggerWithMessagePrefix(name, prefix) {
     let log = this.getLogger(name);
 
     let proxy = Object.create(log);
-    proxy.log = (level, string, params) => {
-      if (Array.isArray(string) && Array.isArray(params)) {
-        // Template literal.
-        // We cannot change the original array, so create a new one.
-        string = [prefix + string[0]].concat(string.slice(1));
-      } else {
-        string = prefix + string; // Regular string.
-      }
-      return log.log(level, string, params);
-    };
+    proxy.log = (level, string, params) => log.log(level, prefix + string, params);
     return proxy;
   },
 };
 
 /*
  * Formatters
  * These massage a LogMessage into whatever output is desired.
  * BasicFormatter and StructuredFormatter are implemented here.
@@ -632,17 +591,17 @@ BasicFormatter.prototype = {
     // We could add a special case for NSRESULT values here...
     let pIsObject = (typeof(params) == "object" || typeof(params) == "function");
 
     // if we have params, try and find substitutions.
     if (this.parameterFormatter) {
       // have we successfully substituted any parameters into the message?
       // in the log message
       let subDone = false;
-      let regex = /\$\{(\S*?)\}/g;
+      let regex = /\$\{(\S*)\}/g;
       let textParts = [];
       if (message.message) {
         textParts.push(message.message.replace(regex, (_, sub) => {
           // ${foo} means use the params['foo']
           if (sub) {
             if (pIsObject && sub in message.params) {
               subDone = true;
               return this.parameterFormatter.format(message.params[sub]);
@@ -713,31 +672,16 @@ StructuredFormatter.prototype = {
       output._message = logMessage.message;
     }
 
     return JSON.stringify(output);
   }
 };
 
 /**
- * A formatter that does not prepend time/name/level information to messages,
- * because those fields are logged separately when using the Android logger.
- */
-function AndroidFormatter() {
-  BasicFormatter.call(this);
-}
-AndroidFormatter.prototype = Object.freeze({
-  __proto__: BasicFormatter.prototype,
-
-  format(message) {
-    return this.formatText(message);
-  },
-});
-
-/**
  * Test an object to see if it is a Mozilla JS Error.
  */
 function isError(aObj) {
   return (aObj && typeof(aObj) == "object" && "name" in aObj && "message" in aObj &&
           "fileName" in aObj && "lineNumber" in aObj && "stack" in aObj);
 }
 
 /*
@@ -1058,43 +1002,8 @@ BoundedFileAppender.prototype = {
 
     return fileClosePromise.then(_ => {
       this._size = 0;
       this._file = null;
       return OS.File.remove(this._path);
     });
   }
 };
-
-/*
- * AndroidAppender
- * Logs to Android logcat using AndroidLog.jsm
- */
-function AndroidAppender(aFormatter) {
-  Appender.call(this, aFormatter || new AndroidFormatter());
-  this._name = "AndroidAppender";
-}
-AndroidAppender.prototype = {
-  __proto__: Appender.prototype,
-
-  // Map log level to AndroidLog.foo method.
-  _mapping: {
-    [Log.Level.Fatal]:  "e",
-    [Log.Level.Error]:  "e",
-    [Log.Level.Warn]:   "w",
-    [Log.Level.Info]:   "i",
-    [Log.Level.Config]: "d",
-    [Log.Level.Debug]:  "d",
-    [Log.Level.Trace]:  "v",
-  },
-
-  append(aMessage) {
-    if (!aMessage) {
-      return;
-    }
-
-    // AndroidLog.jsm always prepends "Gecko" to the tag, so we strip any
-    // leading "Gecko" here. Also strip dots to save space.
-    const tag = aMessage.loggerName.replace(/^Gecko|\./g, "");
-    const msg = this._formatter.format(aMessage);
-    AndroidLog[this._mapping[aMessage.level]](tag, msg);
-  },
-};
--- a/toolkit/modules/tests/xpcshell/test_Log.js
+++ b/toolkit/modules/tests/xpcshell/test_Log.js
@@ -69,23 +69,21 @@ add_test(function test_LoggerWithMessage
   let appender = new MockAppender(new Log.MessageOnlyFormatter());
   log.addAppender(appender);
 
   let prefixed = Log.repository.getLoggerWithMessagePrefix(
     "test.logger.prefix", "prefix: ");
 
   log.warn("no prefix");
   prefixed.warn("with prefix");
-  prefixed.warn `with prefix`;
 
-  Assert.equal(appender.messages.length, 3, "3 messages were logged.");
+  Assert.equal(appender.messages.length, 2, "2 messages were logged.");
   Assert.deepEqual(appender.messages, [
     "no prefix",
     "prefix: with prefix",
-    "prefix: with prefix",
   ], "Prefix logger works.");
 
   run_next_test();
 });
 
 /*
  * A utility method for checking object equivalence.
  * Fields with a reqular expression value in expected will be tested
@@ -412,20 +410,16 @@ add_task(async function log_message_with
   Assert.equal(formatMessage("Null ${n} undefined ${u}", {n: null, u: undefined}),
                "Null null undefined undefined");
 
   // Format params with number, bool, and String type.
   Assert.equal(formatMessage("number ${n} boolean ${b} boxed Boolean ${bx} String ${s}",
                              {n: 45, b: false, bx: Boolean(true), s: String("whatevs")}),
                "number 45 boolean false boxed Boolean true String whatevs");
 
-  // Format params with consecutive tokens.
-  Assert.equal(formatMessage("${a}${b}${c}", {a: "foo", b: "bar", c: "baz"}),
-               "foobarbaz");
-
   /*
    * Check that errors get special formatting if they're formatted directly as
    * a named param or they're the only param, but not if they're a field in a
    * larger structure.
    */
   let err = Components.Exception("test exception", Cr.NS_ERROR_FAILURE);
   let str = formatMessage("Exception is ${}", err);
   Assert.ok(str.includes('Exception is [Exception... "test exception"'));
@@ -556,37 +550,16 @@ add_task(async function log_message_with
   Assert.equal(appender.messages.length, 7);
   for (let msg of appender.messages) {
     Assert.ok(msg.params === testParams);
     Assert.ok(msg.message.startsWith("Test "));
   }
 });
 
 /*
- * Test that all the basic logger methods support tagged template literal format.
- */
-add_task(async function log_template_literal_message() {
-  let log = Log.repository.getLogger("error.logger");
-  let appender = new MockAppender(new Log.BasicFormatter());
-  log.addAppender(appender);
-
-  log.fatal `Test ${"foo"} ${42}`;
-  log.error `Test ${"foo"} 42`;
-  log.warn `Test foo 42`;
-  log.info `Test ${"foo " + 42}`;
-  log.config `${"Test"} foo ${42}`;
-  log.debug `Test ${"f"}${"o"}${"o"} 42`;
-  log.trace `${"Test foo 42"}`;
-  Assert.equal(appender.messages.length, 7);
-  for (let msg of appender.messages) {
-    Assert.equal(msg.split("\t")[3], "Test foo 42");
-  }
-});
-
-/*
  * Check that we format JS Errors reasonably.
  * This needs to stay a generator to exercise Task.jsm's stack rewriting.
  */
 add_task(function* format_errors() {
   let pFormat = new Log.ParameterFormatter();
 
   // Test that subclasses of Error are recognized as errors.
   let err = new ReferenceError("Ref Error", "ERROR_FILE", 28);