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 idunknown
push userunknown
push dateunknown
reviewersbzbarsky, blocking-fennec
bugs548904
milestone2.0b7pre
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);
 
 };
 
 }
 }