bug 1097998 - Warn when using CPOWs when content process isn't in a safe state r=billm, bholley
authorBrad Lassey <blassey@mozilla.com>
Fri, 02 Jan 2015 13:50:21 -0500
changeset 248068 d4b0aadb4e445da3f8de277ec5bbd8e92bf074ac
parent 248067 bb746b3a827fa843027f05b02565a1b45e5c34f1
child 248069 a7e5b17a0e4bc3b396008d7f11cda9cef4c8bdb2
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm, bholley
bugs1097998
milestone37.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 1097998 - Warn when using CPOWs when content process isn't in a safe state r=billm, bholley
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
ipc/glue/MessageChannel.cpp
ipc/glue/MessageLink.h
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1602,16 +1602,35 @@ ContentParent::OnChannelError()
 #ifdef MOZ_NUWA_PROCESS
     // Handle app or Nuwa process exit before normal channel error handling.
     PreallocatedProcessManager::MaybeForgetSpare(this);
 #endif
     PContentParent::OnChannelError();
 }
 
 void
+ContentParent::OnBeginSyncTransaction() {
+    if (XRE_GetProcessType() == GeckoProcessType_Default) {
+        nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
+        JSContext *cx = nsContentUtils::GetCurrentJSContext();
+        if (console && cx) {
+            nsAutoString filename;
+            uint32_t lineno = 0;
+            nsJSUtils::GetCallingLocation(cx, filename, &lineno);
+            nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
+            error->Init(NS_LITERAL_STRING("unsafe CPOW usage"), filename, EmptyString(),
+                        lineno, 0, nsIScriptError::warningFlag, "chrome javascript");
+            console->LogMessage(error);
+        } else {
+            NS_WARNING("Unsafe synchronous IPC message");
+        }
+    }
+}
+
+void
 ContentParent::OnChannelConnected(int32_t pid)
 {
     ProcessHandle handle;
     if (!base::OpenPrivilegedProcessHandle(pid, &handle)) {
         NS_WARNING("Can't open handle to child process.");
     }
     else {
         // we need to close the existing handle before setting a new one.
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -248,16 +248,18 @@ public:
      * about this name: It might not be unique, apps can spoof special names,
      * etc.  So please don't use this name to make any decisions about the
      * ContentParent based on the value returned here.
      */
     void FriendlyName(nsAString& aName, bool aAnonymize = false);
 
     virtual void OnChannelError() MOZ_OVERRIDE;
 
+    virtual void OnBeginSyncTransaction() MOZ_OVERRIDE;
+
     virtual PCrashReporterParent*
     AllocPCrashReporterParent(const NativeThreadId& tid,
                               const uint32_t& processType) MOZ_OVERRIDE;
     virtual bool
     RecvPCrashReporterConstructor(PCrashReporterParent* actor,
                                   const NativeThreadId& tid,
                                   const uint32_t& processType) MOZ_OVERRIDE;
 
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -714,16 +714,19 @@ MessageChannel::Send(Message* aMsg, Mess
 {
     // See comment in DispatchSyncMessage.
     MaybeScriptBlocker scriptBlocker(this, true);
 
     // Sanity checks.
     AssertWorkerThread();
     mMonitor->AssertNotCurrentThreadOwns();
 
+    if (mCurrentTransaction == 0)
+        mListener->OnBeginSyncTransaction();
+
 #ifdef OS_WIN
     SyncStackFrame frame(this, false);
 #endif
 
     CxxStackFrame f(*this, OUT_MESSAGE, aMsg);
 
     MonitorAutoLock lock(*mMonitor);
 
--- a/ipc/glue/MessageLink.h
+++ b/ipc/glue/MessageLink.h
@@ -83,16 +83,20 @@ class MessageListener
         NS_RUNTIMEABORT("default impl shouldn't be invoked");
     }
     virtual void OnEnteredCall() {
         NS_RUNTIMEABORT("default impl shouldn't be invoked");
     }
     virtual void OnExitedCall() {
         NS_RUNTIMEABORT("default impl shouldn't be invoked");
     }
+    /* This callback is called when a sync message is sent that begins a new IPC transaction
+       (i.e., when it is not part of an existing sequence of nested messages). */
+    virtual void OnBeginSyncTransaction() {
+    }
     virtual RacyInterruptPolicy MediateInterruptRace(const Message& parent,
                                                      const Message& child)
     {
         return RIPChildWins;
     }
 
     virtual void ProcessRemoteNativeEventsInInterruptCall() {
     }