Bug 1067576 - Make console.log work in frame scripts (r=Mossop)
authorBill McCloskey <wmccloskey@mozilla.com>
Tue, 07 Oct 2014 11:46:25 -0700
changeset 232447 c5e310d17e58610b6f1b1b13779a98a1ccc1acb4
parent 232446 e5c5d33293aa89bcae840849adba3438d57810c5
child 232448 09bd9d93d3e2574abdc5db3f608737a309eb8d59
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMossop
bugs1067576
milestone35.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1067576 - Make console.log work in frame scripts (r=Mossop)
browser/installer/package-manifest.in
toolkit/components/moz.build
toolkit/components/processsingleton/ContentProcessSingleton.js
toolkit/components/processsingleton/MainProcessSingleton.js
toolkit/components/processsingleton/ProcessSingleton.manifest
toolkit/components/processsingleton/moz.build
toolkit/content/browser-content.js
toolkit/content/widgets/browser.xml
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -439,16 +439,19 @@
 @BINPATH@/components/nsUpdateService.js
 @BINPATH@/components/nsUpdateServiceStub.js
 #endif
 @BINPATH@/components/nsUpdateTimerManager.manifest
 @BINPATH@/components/nsUpdateTimerManager.js
 @BINPATH@/components/addoncompat.manifest
 @BINPATH@/components/multiprocessShims.js
 @BINPATH@/components/pluginGlue.manifest
+@BINPATH@/components/ProcessSingleton.manifest
+@BINPATH@/components/MainProcessSingleton.js
+@BINPATH@/components/ContentProcessSingleton.js
 @BINPATH@/browser/components/nsSessionStore.manifest
 @BINPATH@/browser/components/nsSessionStartup.js
 @BINPATH@/browser/components/nsSessionStore.js
 @BINPATH@/components/nsURLFormatter.manifest
 @BINPATH@/components/nsURLFormatter.js
 @BINPATH@/browser/components/@DLL_PREFIX@browsercomps@DLL_SUFFIX@
 @BINPATH@/components/txEXSLTRegExFunctions.manifest
 @BINPATH@/components/txEXSLTRegExFunctions.js
--- a/toolkit/components/moz.build
+++ b/toolkit/components/moz.build
@@ -31,16 +31,17 @@ DIRS += [
     'jsdownloads',
     'mediasniffer',
     'microformats',
     'osfile',
     'parentalcontrols',
     'passwordmgr',
     'perf',
     'places',
+    'processsingleton',
     'promiseworker',
     'prompts',
     'protobuf',
     'reflect',
     'sqlite',
     'startup',
     'statusfilter',
     'telemetry',
new file mode 100644
--- /dev/null
+++ b/toolkit/components/processsingleton/ContentProcessSingleton.js
@@ -0,0 +1,64 @@
+/* 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";
+
+const Cu = Components.utils;
+const Ci = Components.interfaces;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
+                                   "@mozilla.org/childprocessmessagemanager;1",
+                                   "nsIMessageSender");
+
+function ContentProcessSingleton() {}
+ContentProcessSingleton.prototype = {
+  classID: Components.ID("{ca2a8470-45c7-11e4-916c-0800200c9a66}"),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
+                                         Ci.nsISupportsWeakReference]),
+
+  observe: function(subject, topic, data) {
+    switch (topic) {
+    case "app-startup": {
+      Services.obs.addObserver(this, "console-api-log-event", false);
+      Services.obs.addObserver(this, "xpcom-shutdown", false);
+      break;
+    }
+    case "console-api-log-event": {
+      let consoleMsg = subject.wrappedJSObject;
+
+      let msgData = {
+        level: consoleMsg.level,
+        filename: consoleMsg.filename,
+        lineNumber: consoleMsg.lineNumber,
+        functionName: consoleMsg.functionName,
+        timeStamp: consoleMsg.timeStamp,
+        arguments: [],
+      };
+
+      // We can't send objects over the message manager, so we sanitize
+      // them out.
+      for (let arg of consoleMsg.arguments) {
+        if ((typeof arg == "object" || typeof arg == "function") && arg !== null) {
+          msgData.arguments.push("<unavailable>");
+        } else {
+          msgData.arguments.push(arg);
+        }
+      }
+
+      cpmm.sendAsyncMessage("Console:Log", msgData);
+      break;
+    }
+
+    case "xpcom-shutdown":
+      Services.obs.removeObserver(this, "console-api-log-event");
+      Services.obs.removeObserver(this, "xpcom-shutdown");
+      break;
+    }
+  },
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([ContentProcessSingleton]);
new file mode 100644
--- /dev/null
+++ b/toolkit/components/processsingleton/MainProcessSingleton.js
@@ -0,0 +1,53 @@
+/* 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";
+
+const Cu = Components.utils;
+const Ci = Components.interfaces;
+const Cc = Components.classes;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
+                                   "@mozilla.org/parentprocessmessagemanager;1",
+                                   "nsIMessageListenerManager");
+
+XPCOMUtils.defineLazyServiceGetter(this, "globalmm",
+                                   "@mozilla.org/globalmessagemanager;1",
+                                   "nsIMessageBroadcaster");
+
+function MainProcessSingleton() {}
+MainProcessSingleton.prototype = {
+  classID: Components.ID("{0636a680-45cb-11e4-916c-0800200c9a66}"),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
+                                         Ci.nsISupportsWeakReference]),
+
+  receiveMessage: function(message) {
+    let logMsg = message.data;
+    logMsg.wrappedJSObject = logMsg;
+    Services.obs.notifyObservers(logMsg, "console-api-log-event", null);
+  },
+
+  observe: function(subject, topic, data) {
+    switch (topic) {
+    case "app-startup": {
+      Services.obs.addObserver(this, "xpcom-shutdown", false);
+
+      // Load this script early so that console.* is initialized
+      // before other frame scripts.
+      globalmm.loadFrameScript("chrome://global/content/browser-content.js", true);
+      ppmm.addMessageListener("Console:Log", this);
+      break;
+    }
+
+    case "xpcom-shutdown":
+      ppmm.removeMessageListener("Console:Log", this);
+      break;
+    }
+  },
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([MainProcessSingleton]);
new file mode 100644
--- /dev/null
+++ b/toolkit/components/processsingleton/ProcessSingleton.manifest
@@ -0,0 +1,7 @@
+component {0636a680-45cb-11e4-916c-0800200c9a66} MainProcessSingleton.js process=main
+contract @mozilla.org/main-process-singleton;1 {0636a680-45cb-11e4-916c-0800200c9a66} process=main
+category app-startup MainProcessSingleton service,@mozilla.org/main-process-singleton;1 process=main
+
+component {ca2a8470-45c7-11e4-916c-0800200c9a66} ContentProcessSingleton.js process=content
+contract @mozilla.org/content-process-singleton;1 {ca2a8470-45c7-11e4-916c-0800200c9a66} process=content
+category app-startup ContentProcessSingleton service,@mozilla.org/content-process-singleton;1 process=content
new file mode 100644
--- /dev/null
+++ b/toolkit/components/processsingleton/moz.build
@@ -0,0 +1,11 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+EXTRA_COMPONENTS += [
+    'ContentProcessSingleton.js',
+    'MainProcessSingleton.js',
+    'ProcessSingleton.manifest',
+]
--- a/toolkit/content/browser-content.js
+++ b/toolkit/content/browser-content.js
@@ -343,9 +343,13 @@ let PopupBlocking = {
     }
   },
 
   updateBlockedPopups: function(freshPopup) {
     sendAsyncMessage("PopupBlocking:UpdateBlockedPopups",
                      {blockedPopups: this.popupData, freshPopup: freshPopup});
   },
 };
-PopupBlocking.init();
\ No newline at end of file
+PopupBlocking.init();
+
+// Set up console.* for frame scripts.
+let Console = Components.utils.import("resource://gre/modules/devtools/Console.jsm", {});
+this.console = new Console.ConsoleAPI();
--- a/toolkit/content/widgets/browser.xml
+++ b/toolkit/content/widgets/browser.xml
@@ -785,17 +785,16 @@
             this.addEventListener("pageshow", this.onPageShow, true);
             this.addEventListener("pagehide", this.onPageHide, true);
           }
 
           if (this.messageManager) {
             this.messageManager.addMessageListener("PopupBlocking:UpdateBlockedPopups", this);
             this.messageManager.addMessageListener("Autoscroll:Start", this);
             this.messageManager.addMessageListener("Autoscroll:Cancel", this);
-            this.messageManager.loadFrameScript("chrome://global/content/browser-content.js", true);
           }
         ]]>
       </constructor>
 
       <destructor>
         <![CDATA[
           this.destroy();
         ]]>