Bug 548904 - Remote console messages from content to chrome via a listener. r=bzbarsky a=blocking-fennec
authorJosh Matthews <josh@joshmatthews.net>
Thu, 23 Sep 2010 21:39:32 -0400
changeset 54870 5f0370936fc9c5d9b9bae32a5fe72df2007f709f
parent 54869 e3dcde25c792558ef0e17fbcd35aa9f1187fbc5a
child 54871 ba32daebb14a00700e8b5ab2ed7d89dccb95a6fd
push id16048
push userblassey@mozilla.com
push dateFri, 01 Oct 2010 15:12:19 +0000
treeherdermozilla-central@ba32daebb14a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbzbarsky, blocking-fennec
bugs548904
milestone2.0b7pre
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 548904 - Remote console messages from content to chrome via a listener. r=bzbarsky a=blocking-fennec
dom/ipc/ContentChild.cpp
dom/ipc/ContentChild.h
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/ContentProcess.cpp
dom/ipc/Makefile.in
dom/ipc/PContent.ipdl
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -52,16 +52,18 @@
 
 #include "nsIObserverService.h"
 #include "nsTObserverArray.h"
 #include "nsIObserver.h"
 #include "nsIPrefService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsXULAppAPI.h"
 #include "nsWeakReference.h"
+#include "nsIScriptError.h"
+#include "nsIConsoleService.h"
 
 #include "History.h"
 #include "nsDocShellCID.h"
 #include "nsNetUtil.h"
 
 #include "base/message_loop.h"
 #include "base/task.h"
 
@@ -107,16 +109,69 @@ public:
         return true;
     }
 
 private:
     nsCOMPtr<nsIObserver> mObserver;
     nsString mData;
 };
 
+class ConsoleListener : public nsIConsoleListener
+{
+public:
+    ConsoleListener(ContentChild* aChild)
+    : mChild(aChild) {}
+
+    NS_DECL_ISUPPORTS
+    NS_DECL_NSICONSOLELISTENER
+
+private:
+    ContentChild* mChild;
+    friend class ContentChild;
+};
+
+NS_IMPL_ISUPPORTS1(ConsoleListener, nsIConsoleListener)
+
+NS_IMETHODIMP
+ConsoleListener::Observe(nsIConsoleMessage* aMessage)
+{
+    if (!mChild)
+        return NS_OK;
+    
+    nsCOMPtr<nsIScriptError> scriptError = do_QueryInterface(aMessage);
+    if (scriptError) {
+        nsString msg, sourceName, sourceLine;
+        nsXPIDLCString category;
+        PRUint32 lineNum, colNum, flags;
+
+        nsresult rv = scriptError->GetErrorMessage(msg);
+        NS_ENSURE_SUCCESS(rv, rv);
+        rv = scriptError->GetSourceName(sourceName);
+        NS_ENSURE_SUCCESS(rv, rv);
+        rv = scriptError->GetSourceLine(sourceLine);
+        NS_ENSURE_SUCCESS(rv, rv);
+        rv = scriptError->GetCategory(getter_Copies(category));
+        NS_ENSURE_SUCCESS(rv, rv);
+        rv = scriptError->GetLineNumber(&lineNum);
+        NS_ENSURE_SUCCESS(rv, rv);
+        rv = scriptError->GetColumnNumber(&colNum);
+        NS_ENSURE_SUCCESS(rv, rv);
+        rv = scriptError->GetFlags(&flags);
+        NS_ENSURE_SUCCESS(rv, rv);
+        mChild->SendScriptError(msg, sourceName, sourceLine,
+                               lineNum, colNum, flags, category);
+        return NS_OK;
+    }
+
+    nsXPIDLString msg;
+    nsresult rv = aMessage->GetMessageMoz(getter_Copies(msg));
+    NS_ENSURE_SUCCESS(rv, rv);
+    mChild->SendConsoleMessage(msg);
+    return NS_OK;
+}
 
 ContentChild* ContentChild::sSingleton;
 
 ContentChild::ContentChild()
 {
 }
 
 ContentChild::~ContentChild()
@@ -141,16 +196,30 @@ ContentChild::Init(MessageLoop* aIOLoop,
     NS_ASSERTION(!sSingleton, "only one ContentChild per child");
   
     Open(aChannel, aParentHandle, aIOLoop);
     sSingleton = this;
 
     return true;
 }
 
+void
+ContentChild::InitXPCOM()
+{
+    nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
+    if (!svc) {
+        NS_WARNING("Couldn't acquire console service");
+        return;
+    }
+
+    mConsoleListener = new ConsoleListener(this);
+    if (NS_FAILED(svc->RegisterListener(mConsoleListener)))
+        NS_WARNING("Couldn't register console listener for child process");
+}
+
 PBrowserChild*
 ContentChild::AllocPBrowser(const PRUint32& aChromeFlags)
 {
     nsRefPtr<TabChild> iframe = new TabChild(aChromeFlags);
     return NS_SUCCEEDED(iframe->Init()) ? iframe.forget().get() : NULL;
 }
 
 bool
@@ -248,16 +317,23 @@ ContentChild::ActorDestroy(ActorDestroyR
 #ifndef DEBUG
     // In release builds, there's no point in the content process
     // going through the full XPCOM shutdown path, because it doesn't
     // keep persistent state.
     QuickExit();
 #endif
 
     mAlertObservers.Clear();
+    
+    nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
+    if (svc) {
+        svc->UnregisterListener(mConsoleListener);
+        mConsoleListener->mChild = nsnull;
+    }
+
     XRE_ShutdownChildProcess();
 }
 
 void
 ContentChild::ProcessingError(Result what)
 {
     switch (what) {
     case MsgDropped:
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -38,37 +38,40 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef mozilla_dom_ContentChild_h
 #define mozilla_dom_ContentChild_h
 
 #include "mozilla/dom/PContentChild.h"
 
 #include "nsTArray.h"
+#include "nsIConsoleListener.h"
 
 struct ChromePackage;
 class nsIObserver;
 struct ResourceMapping;
 struct OverrideMapping;
 
 namespace mozilla {
 namespace dom {
 
 class AlertObserver;
 class PrefObserver;
+class ConsoleListener;
 
 class ContentChild : public PContentChild
 {
 public:
     ContentChild();
     virtual ~ContentChild();
 
     bool Init(MessageLoop* aIOLoop,
               base::ProcessHandle aParentHandle,
               IPC::Channel* aChannel);
+    void InitXPCOM();
 
     static ContentChild* GetSingleton() {
         NS_ASSERTION(sSingleton, "not initialized");
         return sSingleton;
     }
 
     /* if you remove this, please talk to cjones or dougt */
     virtual bool RecvDummy(Shmem& foo) { return true; }
@@ -119,16 +122,17 @@ private:
     /**
      * Exit *now*.  Do not shut down XPCOM, do not pass Go, do not run
      * static destructors, do not collect $200.
      */
     NS_NORETURN void QuickExit();
 
     nsTArray<nsAutoPtr<AlertObserver> > mAlertObservers;
     nsTArray<nsAutoPtr<PrefObserver> > mPrefObservers;
+    nsRefPtr<ConsoleListener> mConsoleListener;
     bool mDead;
 
     static ContentChild* sSingleton;
 
     DISALLOW_EVIL_CONSTRUCTORS(ContentChild);
 };
 
 } // namespace dom
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -55,16 +55,19 @@
 #include "nsThreadUtils.h"
 #include "nsChromeRegistryChrome.h"
 #include "nsExternalHelperAppService.h"
 #include "nsCExternalHandlerService.h"
 #include "nsFrameMessageManager.h"
 #include "nsIAlertsService.h"
 #include "nsToolkitCompsCID.h"
 #include "nsIDOMGeoGeolocation.h"
+#include "nsIConsoleService.h"
+#include "nsIScriptError.h"
+#include "nsConsoleMessage.h"
 
 #include "mozilla/dom/ExternalHelperAppParent.h"
 
 using namespace mozilla::ipc;
 using namespace mozilla::net;
 using namespace mozilla::places;
 using mozilla::MonitorAutoEnter;
 
@@ -542,10 +545,45 @@ ContentParent::RecvGeolocationStop()
 
 NS_IMETHODIMP
 ContentParent::HandleEvent(nsIDOMGeoPosition* postion)
 {
   SendGeolocationUpdate(GeoPosition(postion));
   return NS_OK;
 }
 
+bool
+ContentParent::RecvConsoleMessage(const nsString& aMessage)
+{
+  nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
+  if (!svc)
+    return true;
+  
+  nsRefPtr<nsConsoleMessage> msg(new nsConsoleMessage(aMessage.get()));
+  svc->LogMessage(msg);
+  return true;
+}
+
+bool
+ContentParent::RecvScriptError(const nsString& aMessage,
+                                      const nsString& aSourceName,
+                                      const nsString& aSourceLine,
+                                      const PRUint32& aLineNumber,
+                                      const PRUint32& aColNumber,
+                                      const PRUint32& aFlags,
+                                      const nsCString& aCategory)
+{
+  nsCOMPtr<nsIConsoleService> svc(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
+  if (!svc)
+      return true;
+
+  nsCOMPtr<nsIScriptError> msg(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
+  nsresult rv = msg->Init(aMessage.get(), aSourceName.get(), aSourceLine.get(),
+                          aLineNumber, aColNumber, aFlags, aCategory.get());
+  if (NS_FAILED(rv))
+    return true;
+
+  svc->LogMessage(msg);
+  return true;
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -152,16 +152,25 @@ private:
 
     virtual bool RecvSyncMessage(const nsString& aMsg, const nsString& aJSON,
                                  nsTArray<nsString>* aRetvals);
     virtual bool RecvAsyncMessage(const nsString& aMsg, const nsString& aJSON);
 
     virtual bool RecvGeolocationStart();
     virtual bool RecvGeolocationStop();
 
+    virtual bool RecvConsoleMessage(const nsString& aMessage);
+    virtual bool RecvScriptError(const nsString& aMessage,
+                                 const nsString& aSourceName,
+                                 const nsString& aSourceLine,
+                                 const PRUint32& aLineNumber,
+                                 const PRUint32& aColNumber,
+                                 const PRUint32& aFlags,
+                                 const nsCString& aCategory);
+
     mozilla::Monitor mMonitor;
 
     GeckoChildProcessHost* mSubprocess;
 
     PRInt32 mGeolocationWatchID;
     int mRunToCompletionDepth;
     bool mShouldCallUnblockChild;
     nsCOMPtr<nsIThreadObserver> mOldObserver;
--- a/dom/ipc/ContentProcess.cpp
+++ b/dom/ipc/ContentProcess.cpp
@@ -48,16 +48,17 @@ namespace dom {
 
 bool
 ContentProcess::Init()
 {
     mContent.Init(IOThreadChild::message_loop(),
                          ParentHandle(),
                          IOThreadChild::channel());
     mXREEmbed.Start();
+    mContent.InitXPCOM();
     
     return true;
 }
 
 void
 ContentProcess::CleanUp()
 {
     mXREEmbed.Stop();
--- a/dom/ipc/Makefile.in
+++ b/dom/ipc/Makefile.in
@@ -75,13 +75,14 @@ include $(topsrcdir)/config/rules.mk
 LOCAL_INCLUDES += \
 		-I$(srcdir)/../../content/base/src \
 		-I$(srcdir)/../../content/events/src \
 		-I$(srcdir)/../../toolkit/components/places/src \
 		-I$(topsrcdir)/chrome/src \
 		-I$(topsrcdir)/uriloader/exthandler \
 		-I$(srcdir)/../../netwerk/base/src \
 		-I$(srcdir)/../src/base \
+		-I$(srcdir)/../../xpcom/base \
 		$(NULL)
 
 DEFINES += -DBIN_SUFFIX='"$(BIN_SUFFIX)"'
 
 CXXFLAGS += $(TK_CFLAGS)
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -110,15 +110,20 @@ parent:
 
     PExternalHelperApp(URI uri, nsCString aMimeContentType,
                        nsCString aContentDisposition, bool aForceSave,
                        PRInt64 aContentLength);
     
     GeolocationStart();
     GeolocationStop();
 
+    ConsoleMessage(nsString message);
+    ScriptError(nsString message, nsString sourceName, nsString sourceLine,
+                PRUint32 lineNumber, PRUint32 colNumber, PRUint32 flags,
+                nsCString category); 
+
 both:
      AsyncMessage(nsString aMessage, nsString aJSON);
 
 };
 
 }
 }