Bug 1049879 - Remove urgent and rpc message types and replace with message priorities (r=dvander,bent,ehsan)
authorBill McCloskey <wmccloskey@mozilla.com>
Tue, 07 Oct 2014 21:32:45 -0700
changeset 209270 40263f6c0fbc142ed3c1a28ad3d098bc0c0e12b8
parent 209269 405e4dba0359d30ff5bf74f29b43aae4b86939f8
child 209271 4007aeccec79b33a9eae3506f26455ae3e01facc
push id27612
push usercbook@mozilla.com
push dateWed, 08 Oct 2014 13:46:10 +0000
treeherdermozilla-central@3a0d57d665bb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander, bent, ehsan
bugs1049879
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 1049879 - Remove urgent and rpc message types and replace with message priorities (r=dvander,bent,ehsan)
CLOBBER
content/base/src/nsFrameMessageManager.cpp
content/media/webspeech/synth/ipc/PSpeechSynthesis.ipdl
content/media/webspeech/synth/ipc/PSpeechSynthesisRequest.ipdl
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PBrowser.ipdl
dom/ipc/PContent.ipdl
dom/ipc/PContentBridge.ipdl
dom/ipc/PCrashReporter.ipdl
dom/ipc/PScreenManager.ipdl
dom/ipc/ScreenManagerParent.cpp
dom/ipc/ScreenManagerParent.h
dom/ipc/TabChild.cpp
dom/ipc/TabParent.cpp
dom/ipc/TabParent.h
dom/ipc/nsIContentParent.cpp
dom/ipc/nsIContentParent.h
ipc/chromium/src/chrome/common/ipc_message.h
ipc/glue/MessageChannel.cpp
ipc/glue/MessageChannel.h
ipc/ipdl/ipdl/ast.py
ipc/ipdl/ipdl/lower.py
ipc/ipdl/ipdl/parser.py
ipc/ipdl/ipdl/type.py
ipc/ipdl/test/cxx/Makefile.in
ipc/ipdl/test/cxx/PTestHighestPrio.ipdl
ipc/ipdl/test/cxx/PTestRPC.ipdl
ipc/ipdl/test/cxx/PTestUrgency.ipdl
ipc/ipdl/test/cxx/TestHighestPrio.cpp
ipc/ipdl/test/cxx/TestHighestPrio.h
ipc/ipdl/test/cxx/TestRPC.cpp
ipc/ipdl/test/cxx/TestRPC.h
ipc/ipdl/test/cxx/TestUrgency.cpp
ipc/ipdl/test/cxx/TestUrgency.h
ipc/ipdl/test/cxx/moz.build
ipc/testshell/PTestShell.ipdl
js/ipc/JavaScriptBase.h
js/ipc/PJavaScript.ipdl
js/ipc/WrapperAnswer.cpp
js/ipc/WrapperAnswer.h
js/ipc/WrapperOwner.cpp
js/ipc/WrapperOwner.h
widget/windows/nsWindow.cpp
widget/xpwidgets/ScreenProxy.cpp
widget/xpwidgets/nsScreenManagerProxy.cpp
xpcom/threads/nsThread.cpp
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 1069071: IPDL changes require CLOBBER
+Bug 1069071: IPDL changes require CLOBBER (second time around)
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -1730,17 +1730,17 @@ public:
     InfallibleTArray<mozilla::jsipc::CpowEntry> cpows;
     if (aCpows && !cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
       return false;
     }
     if (aIsSync) {
       return cc->SendSyncMessage(PromiseFlatString(aMessage), data, cpows,
                                  IPC::Principal(aPrincipal), aJSONRetVal);
     }
-    return cc->CallRpcMessage(PromiseFlatString(aMessage), data, cpows,
+    return cc->SendRpcMessage(PromiseFlatString(aMessage), data, cpows,
                               IPC::Principal(aPrincipal), aJSONRetVal);
   }
 
   virtual bool DoSendAsyncMessage(JSContext* aCx,
                                   const nsAString& aMessage,
                                   const mozilla::dom::StructuredCloneData& aData,
                                   JS::Handle<JSObject *> aCpows,
                                   nsIPrincipal* aPrincipal) MOZ_OVERRIDE
--- a/content/media/webspeech/synth/ipc/PSpeechSynthesis.ipdl
+++ b/content/media/webspeech/synth/ipc/PSpeechSynthesis.ipdl
@@ -12,17 +12,17 @@ namespace dom {
 
 struct RemoteVoice {
   nsString voiceURI;
   nsString name;
   nsString lang;
   bool localService;
 };
 
-intr protocol PSpeechSynthesis
+sync protocol PSpeechSynthesis
 {
   manager PContent;
   manages PSpeechSynthesisRequest;
 
 child:
 
     VoiceAdded(RemoteVoice aVoice);
 
--- a/content/media/webspeech/synth/ipc/PSpeechSynthesisRequest.ipdl
+++ b/content/media/webspeech/synth/ipc/PSpeechSynthesisRequest.ipdl
@@ -4,17 +4,17 @@
  * 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/. */
 
 include protocol PSpeechSynthesis;
 
 namespace mozilla {
 namespace dom {
 
-intr protocol PSpeechSynthesisRequest
+async protocol PSpeechSynthesisRequest
 {
   manager PSpeechSynthesis;
 
  parent:
 
   Pause();
 
   Resume();
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -3512,24 +3512,24 @@ ContentParent::RecvSyncMessage(const nsS
                                const IPC::Principal& aPrincipal,
                                InfallibleTArray<nsString>* aRetvals)
 {
     return nsIContentParent::RecvSyncMessage(aMsg, aData, aCpows, aPrincipal,
                                              aRetvals);
 }
 
 bool
-ContentParent::AnswerRpcMessage(const nsString& aMsg,
-                                const ClonedMessageData& aData,
-                                const InfallibleTArray<CpowEntry>& aCpows,
-                                const IPC::Principal& aPrincipal,
-                                InfallibleTArray<nsString>* aRetvals)
+ContentParent::RecvRpcMessage(const nsString& aMsg,
+                              const ClonedMessageData& aData,
+                              const InfallibleTArray<CpowEntry>& aCpows,
+                              const IPC::Principal& aPrincipal,
+                              InfallibleTArray<nsString>* aRetvals)
 {
-    return nsIContentParent::AnswerRpcMessage(aMsg, aData, aCpows, aPrincipal,
-                                              aRetvals);
+    return nsIContentParent::RecvRpcMessage(aMsg, aData, aCpows, aPrincipal,
+                                            aRetvals);
 }
 
 bool
 ContentParent::RecvAsyncMessage(const nsString& aMsg,
                                 const ClonedMessageData& aData,
                                 const InfallibleTArray<CpowEntry>& aCpows,
                                 const IPC::Principal& aPrincipal)
 {
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -558,21 +558,21 @@ private:
 
     virtual bool RecvLoadURIExternal(const URIParams& uri) MOZ_OVERRIDE;
 
     virtual bool RecvSyncMessage(const nsString& aMsg,
                                  const ClonedMessageData& aData,
                                  const InfallibleTArray<CpowEntry>& aCpows,
                                  const IPC::Principal& aPrincipal,
                                  InfallibleTArray<nsString>* aRetvals) MOZ_OVERRIDE;
-    virtual bool AnswerRpcMessage(const nsString& aMsg,
-                                  const ClonedMessageData& aData,
-                                  const InfallibleTArray<CpowEntry>& aCpows,
-                                  const IPC::Principal& aPrincipal,
-                                  InfallibleTArray<nsString>* aRetvals) MOZ_OVERRIDE;
+    virtual bool RecvRpcMessage(const nsString& aMsg,
+                                const ClonedMessageData& aData,
+                                const InfallibleTArray<CpowEntry>& aCpows,
+                                const IPC::Principal& aPrincipal,
+                                InfallibleTArray<nsString>* aRetvals) MOZ_OVERRIDE;
     virtual bool RecvAsyncMessage(const nsString& aMsg,
                                   const ClonedMessageData& aData,
                                   const InfallibleTArray<CpowEntry>& aCpows,
                                   const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
 
     virtual bool RecvFilePathUpdateNotify(const nsString& aType,
                                           const nsString& aStorageName,
                                           const nsString& aFilePath,
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -64,17 +64,17 @@ struct NativeKeyBinding
 };
 
 union MaybeNativeKeyBinding
 {
   NativeKeyBinding;
   void_t;
 };
 
-intr protocol PBrowser
+prio(normal upto high) intr protocol PBrowser
 {
     manager PContent or PContentBridge;
 
     manages PColorPicker;
     manages PDocumentRenderer;
     manages PContentPermissionRequest;
     manages PFilePicker;
     manages PIndexedDBPermissionRequest;
@@ -103,18 +103,18 @@ parent:
                       nsString aFeatures,
                       nsString aBaseURI)
       returns (bool windowIsNew, PBrowser window);
 
     sync SyncMessage(nsString aMessage, ClonedMessageData aData,
                      CpowEntry[] aCpows, Principal aPrincipal)
       returns (nsString[] retval);
 
-    rpc RpcMessage(nsString aMessage, ClonedMessageData aData,
-                   CpowEntry[] aCpows, Principal aPrincipal)
+    prio(high) sync RpcMessage(nsString aMessage, ClonedMessageData aData,
+                               CpowEntry[] aCpows, Principal aPrincipal)
       returns (nsString[] retval);
 
     /**
      * The IME sequence number (seqno) parameter is used to make sure
      * that a notification is discarded if it arrives at the chrome process
      * too late. If the notification is late and we accept it, we will have
      * an out-of-date view of the content process, which means events that we
      * dispatch based on this out-of-date view will be wrong also.
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -314,17 +314,17 @@ struct VolumeInfo {
   bool isUnmounting;
 };
 
 union MaybeFileDesc {
     FileDescriptor;
     void_t;
 };
 
-intr protocol PContent
+prio(normal upto high) intr protocol PContent
 {
     parent opens PCompositor;
     parent opens PSharedBufferManager;
     parent opens PImageBridge;
     child opens PBackground;
 
     manages PAsmJSCacheEntry;
     manages PBlob;
@@ -532,17 +532,17 @@ parent:
         returns (bool isSecureURI);
 
     PHal();
 
     PMobileConnection(uint32_t clientId);
 
     PNecko();
 
-    rpc PScreenManager()
+    prio(high) sync PScreenManager()
         returns (uint32_t numberOfScreens,
                  float systemDefaultScale,
                  bool success);
 
     PCellBroadcast();
 
     PSms();
 
@@ -572,18 +572,18 @@ parent:
     sync ReadPrefsArray() returns (PrefSetting[] prefs);
 
     sync ReadFontList() returns (FontListEntry[] retValue);
 
     sync SyncMessage(nsString aMessage, ClonedMessageData aData,
                      CpowEntry[] aCpows, Principal aPrincipal)
       returns (nsString[] retval);
 
-    rpc RpcMessage(nsString aMessage, ClonedMessageData aData,
-                   CpowEntry[] aCpows, Principal aPrincipal)
+    prio(high) sync RpcMessage(nsString aMessage, ClonedMessageData aData,
+                               CpowEntry[] aCpows, Principal aPrincipal)
       returns (nsString[] retval);
 
     ShowAlertNotification(nsString imageUrl,
                           nsString title,
                           nsString text,
                           bool textClickable,
                           nsString cookie,
                           nsString name,
--- a/dom/ipc/PContentBridge.ipdl
+++ b/dom/ipc/PContentBridge.ipdl
@@ -21,17 +21,17 @@ namespace dom {
 /*
  * PContentBridge allows us to represent a parent/child relationship between two
  * child processes.  When a child process wants to open its own child, it asks
  * the root process to create a new process and then bridge them.  The first
  * child will allocate the PContentBridgeParent, and the newly opened child will
  * allocate the PContentBridgeChild.  This protocol allows these processes to
  * share PBrowsers and send messages to each other.
  */
-intr protocol PContentBridge
+prio(normal upto high) intr protocol PContentBridge
 {
     bridges PContent, PContent;
 
     manages PBlob;
     manages PBrowser;
     manages PJavaScript;
 
 parent:
--- a/dom/ipc/PCrashReporter.ipdl
+++ b/dom/ipc/PCrashReporter.ipdl
@@ -14,17 +14,17 @@ namespace dom {
 struct Mapping {
   nsCString library_name;
   nsCString file_id;
   uintptr_t start_address;
   size_t mapping_length;
   size_t file_offset;
 };
 
-intr protocol PCrashReporter {
+async protocol PCrashReporter {
   manager PContent or PPluginModule or PGMP;
 parent:
   AnnotateCrashReport(nsCString key, nsCString data);
   AppendAppNotes(nsCString data);
   __delete__();
 };
 
 }
--- a/dom/ipc/PScreenManager.ipdl
+++ b/dom/ipc/PScreenManager.ipdl
@@ -17,42 +17,42 @@ struct ScreenDetails {
   nsIntRect rectDisplayPix;
   nsIntRect availRect;
   nsIntRect availRectDisplayPix;
   int32_t pixelDepth;
   int32_t colorDepth;
   double contentsScaleFactor;
 };
 
-rpc protocol PScreenManager
+prio(normal upto high) sync protocol PScreenManager
 {
   manager PContent;
 
 parent:
-    rpc Refresh()
+    prio(high) sync Refresh()
       returns (uint32_t numberOfScreens,
                float systemDefaultScale,
                bool success);
 
-    rpc ScreenRefresh(uint32_t aId)
+    prio(high) sync ScreenRefresh(uint32_t aId)
       returns (ScreenDetails screen,
                bool success);
 
-    rpc GetPrimaryScreen()
+    prio(high) sync GetPrimaryScreen()
       returns (ScreenDetails screen,
                bool success);
 
-    rpc ScreenForRect(int32_t aLeft,
+    prio(high) sync ScreenForRect(int32_t aLeft,
                        int32_t aTop,
                        int32_t aWidth,
                        int32_t aHeight)
       returns (ScreenDetails screen,
                bool success);
 
-    rpc ScreenForBrowser(PBrowser aBrowser)
+    prio(high) sync ScreenForBrowser(PBrowser aBrowser)
       returns (ScreenDetails screen,
                bool success);
 
 child:
     __delete__();
 };
 
 } // namespace dom
--- a/dom/ipc/ScreenManagerParent.cpp
+++ b/dom/ipc/ScreenManagerParent.cpp
@@ -19,23 +19,23 @@ ScreenManagerParent::ScreenManagerParent
                                          float* aSystemDefaultScale,
                                          bool* aSuccess)
 {
   mScreenMgr = do_GetService(sScreenManagerContractID);
   if (!mScreenMgr) {
     MOZ_CRASH("Couldn't get nsIScreenManager from ScreenManagerParent.");
   }
 
-  unused << AnswerRefresh(aNumberOfScreens, aSystemDefaultScale, aSuccess);
+  unused << RecvRefresh(aNumberOfScreens, aSystemDefaultScale, aSuccess);
 }
 
 bool
-ScreenManagerParent::AnswerRefresh(uint32_t* aNumberOfScreens,
-                                   float* aSystemDefaultScale,
-                                   bool* aSuccess)
+ScreenManagerParent::RecvRefresh(uint32_t* aNumberOfScreens,
+                                 float* aSystemDefaultScale,
+                                 bool* aSuccess)
 {
   *aSuccess = false;
 
   nsresult rv = mScreenMgr->GetNumberOfScreens(aNumberOfScreens);
   if (NS_FAILED(rv)) {
     return true;
   }
 
@@ -44,19 +44,19 @@ ScreenManagerParent::AnswerRefresh(uint3
     return true;
   }
 
   *aSuccess = true;
   return true;
 }
 
 bool
-ScreenManagerParent::AnswerScreenRefresh(const uint32_t& aId,
-                                         ScreenDetails* aRetVal,
-                                         bool* aSuccess)
+ScreenManagerParent::RecvScreenRefresh(const uint32_t& aId,
+                                       ScreenDetails* aRetVal,
+                                       bool* aSuccess)
 {
   *aSuccess = false;
 
   nsCOMPtr<nsIScreen> screen;
   nsresult rv = mScreenMgr->ScreenForId(aId, getter_AddRefs(screen));
   if (NS_FAILED(rv)) {
     return true;
   }
@@ -65,18 +65,18 @@ ScreenManagerParent::AnswerScreenRefresh
   unused << ExtractScreenDetails(screen, details);
 
   *aRetVal = details;
   *aSuccess = true;
   return true;
 }
 
 bool
-ScreenManagerParent::AnswerGetPrimaryScreen(ScreenDetails* aRetVal,
-                                            bool* aSuccess)
+ScreenManagerParent::RecvGetPrimaryScreen(ScreenDetails* aRetVal,
+                                          bool* aSuccess)
 {
   *aSuccess = false;
 
   nsCOMPtr<nsIScreen> screen;
   nsresult rv = mScreenMgr->GetPrimaryScreen(getter_AddRefs(screen));
 
   NS_ENSURE_SUCCESS(rv, true);
 
@@ -86,22 +86,22 @@ ScreenManagerParent::AnswerGetPrimaryScr
   }
 
   *aRetVal = details;
   *aSuccess = true;
   return true;
 }
 
 bool
-ScreenManagerParent::AnswerScreenForRect(const int32_t& aLeft,
-                                         const int32_t& aTop,
-                                         const int32_t& aWidth,
-                                         const int32_t& aHeight,
-                                         ScreenDetails* aRetVal,
-                                         bool* aSuccess)
+ScreenManagerParent::RecvScreenForRect(const int32_t& aLeft,
+                                       const int32_t& aTop,
+                                       const int32_t& aWidth,
+                                       const int32_t& aHeight,
+                                       ScreenDetails* aRetVal,
+                                       bool* aSuccess)
 {
   *aSuccess = false;
 
   nsCOMPtr<nsIScreen> screen;
   nsresult rv = mScreenMgr->ScreenForRect(aLeft, aTop, aWidth, aHeight, getter_AddRefs(screen));
 
   NS_ENSURE_SUCCESS(rv, true);
 
@@ -111,19 +111,19 @@ ScreenManagerParent::AnswerScreenForRect
   }
 
   *aRetVal = details;
   *aSuccess = true;
   return true;
 }
 
 bool
-ScreenManagerParent::AnswerScreenForBrowser(PBrowserParent* aBrowser,
-                                            ScreenDetails* aRetVal,
-                                            bool* aSuccess)
+ScreenManagerParent::RecvScreenForBrowser(PBrowserParent* aBrowser,
+                                          ScreenDetails* aRetVal,
+                                          bool* aSuccess)
 {
   *aSuccess = false;
 
   // Find the mWidget associated with the tabparent, and then return
   // the nsIScreen it's on.
   TabParent* tabParent = static_cast<TabParent*>(aBrowser);
   nsCOMPtr<nsIWidget> widget = tabParent->GetWidget();
   if (!widget) {
--- a/dom/ipc/ScreenManagerParent.h
+++ b/dom/ipc/ScreenManagerParent.h
@@ -16,39 +16,39 @@ namespace dom {
 class ScreenManagerParent : public PScreenManagerParent
 {
  public:
   ScreenManagerParent(uint32_t* aNumberOfScreens,
                       float* aSystemDefaultScale,
                       bool* aSuccess);
   ~ScreenManagerParent() {};
 
-  virtual bool AnswerRefresh(uint32_t* aNumberOfScreens,
-                             float* aSystemDefaultScale,
-                             bool* aSuccess) MOZ_OVERRIDE;
+  virtual bool RecvRefresh(uint32_t* aNumberOfScreens,
+                           float* aSystemDefaultScale,
+                           bool* aSuccess) MOZ_OVERRIDE;
 
-  virtual bool AnswerScreenRefresh(const uint32_t& aId,
-                                   ScreenDetails* aRetVal,
-                                   bool* aSuccess) MOZ_OVERRIDE;
+  virtual bool RecvScreenRefresh(const uint32_t& aId,
+                                 ScreenDetails* aRetVal,
+                                 bool* aSuccess) MOZ_OVERRIDE;
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 
-  virtual bool AnswerGetPrimaryScreen(ScreenDetails* aRetVal,
-                                      bool* aSuccess) MOZ_OVERRIDE;
+  virtual bool RecvGetPrimaryScreen(ScreenDetails* aRetVal,
+                                    bool* aSuccess) MOZ_OVERRIDE;
 
-  virtual bool AnswerScreenForRect(const int32_t& aLeft,
-                                   const int32_t& aTop,
-                                   const int32_t& aWidth,
-                                   const int32_t& aHeight,
-                                   ScreenDetails* aRetVal,
-                                   bool* aSuccess) MOZ_OVERRIDE;
+  virtual bool RecvScreenForRect(const int32_t& aLeft,
+                                 const int32_t& aTop,
+                                 const int32_t& aWidth,
+                                 const int32_t& aHeight,
+                                 ScreenDetails* aRetVal,
+                                 bool* aSuccess) MOZ_OVERRIDE;
 
-  virtual bool AnswerScreenForBrowser(PBrowserParent* aBrowser,
-                                      ScreenDetails* aRetVal,
-                                      bool* aSuccess);
+  virtual bool RecvScreenForBrowser(PBrowserParent* aBrowser,
+                                    ScreenDetails* aRetVal,
+                                    bool* aSuccess);
 
  private:
   bool ExtractScreenDetails(nsIScreen* aScreen, ScreenDetails &aDetails);
   nsCOMPtr<nsIScreenManager> mScreenMgr;
 };
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -2917,17 +2917,17 @@ TabChild::DoSendBlockingMessage(JSContex
   if (aCpows && !Manager()->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
     return false;
   }
   if (aIsSync) {
     return SendSyncMessage(PromiseFlatString(aMessage), data, cpows,
                            Principal(aPrincipal), aJSONRetVal);
   }
 
-  return CallRpcMessage(PromiseFlatString(aMessage), data, cpows,
+  return SendRpcMessage(PromiseFlatString(aMessage), data, cpows,
                         Principal(aPrincipal), aJSONRetVal);
 }
 
 bool
 TabChild::DoSendAsyncMessage(JSContext* aCx,
                              const nsAString& aMessage,
                              const StructuredCloneData& aData,
                              JS::Handle<JSObject *> aCpows,
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -1123,21 +1123,21 @@ TabParent::RecvSyncMessage(const nsStrin
   }
 
   StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
   CpowIdHolder cpows(Manager(), aCpows);
   return ReceiveMessage(aMessage, true, &cloneData, &cpows, aPrincipal, aJSONRetVal);
 }
 
 bool
-TabParent::AnswerRpcMessage(const nsString& aMessage,
-                            const ClonedMessageData& aData,
-                            const InfallibleTArray<CpowEntry>& aCpows,
-                            const IPC::Principal& aPrincipal,
-                            InfallibleTArray<nsString>* aJSONRetVal)
+TabParent::RecvRpcMessage(const nsString& aMessage,
+                          const ClonedMessageData& aData,
+                          const InfallibleTArray<CpowEntry>& aCpows,
+                          const IPC::Principal& aPrincipal,
+                          InfallibleTArray<nsString>* aJSONRetVal)
 {
   // FIXME Permission check for TabParent in Content process
   nsIPrincipal* principal = aPrincipal;
   if (Manager()->IsContentParent()) {
     ContentParent* parent = Manager()->AsContentParent();
     if (!ContentParent::IgnoreIPCPrincipal() &&
         parent && principal && !AssertAppPrincipal(parent, principal)) {
       return false;
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -142,21 +142,21 @@ public:
                                     const nsString& aBaseURI,
                                     bool* aWindowIsNew,
                                     PBrowserParent** aRetVal) MOZ_OVERRIDE;
     virtual bool RecvSyncMessage(const nsString& aMessage,
                                  const ClonedMessageData& aData,
                                  const InfallibleTArray<CpowEntry>& aCpows,
                                  const IPC::Principal& aPrincipal,
                                  InfallibleTArray<nsString>* aJSONRetVal) MOZ_OVERRIDE;
-    virtual bool AnswerRpcMessage(const nsString& aMessage,
-                                  const ClonedMessageData& aData,
-                                  const InfallibleTArray<CpowEntry>& aCpows,
-                                  const IPC::Principal& aPrincipal,
-                                  InfallibleTArray<nsString>* aJSONRetVal) MOZ_OVERRIDE;
+    virtual bool RecvRpcMessage(const nsString& aMessage,
+                                const ClonedMessageData& aData,
+                                const InfallibleTArray<CpowEntry>& aCpows,
+                                const IPC::Principal& aPrincipal,
+                                InfallibleTArray<nsString>* aJSONRetVal) MOZ_OVERRIDE;
     virtual bool RecvAsyncMessage(const nsString& aMessage,
                                   const ClonedMessageData& aData,
                                   const InfallibleTArray<CpowEntry>& aCpows,
                                   const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
     virtual bool RecvNotifyIMEFocus(const bool& aFocus,
                                     nsIMEUpdatePreference* aPreference,
                                     uint32_t* aSeqno) MOZ_OVERRIDE;
     virtual bool RecvNotifyIMETextChange(const uint32_t& aStart,
--- a/dom/ipc/nsIContentParent.cpp
+++ b/dom/ipc/nsIContentParent.cpp
@@ -188,21 +188,21 @@ nsIContentParent::RecvSyncMessage(const 
     CpowIdHolder cpows(this, aCpows);
     ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
                         aMsg, true, &cloneData, &cpows, aPrincipal, aRetvals);
   }
   return true;
 }
 
 bool
-nsIContentParent::AnswerRpcMessage(const nsString& aMsg,
-                                   const ClonedMessageData& aData,
-                                   const InfallibleTArray<CpowEntry>& aCpows,
-                                   const IPC::Principal& aPrincipal,
-                                   InfallibleTArray<nsString>* aRetvals)
+nsIContentParent::RecvRpcMessage(const nsString& aMsg,
+                                 const ClonedMessageData& aData,
+                                 const InfallibleTArray<CpowEntry>& aCpows,
+                                 const IPC::Principal& aPrincipal,
+                                 InfallibleTArray<nsString>* aRetvals)
 {
   // FIXME Permission check in Content process
   nsIPrincipal* principal = aPrincipal;
   if (IsContentParent()) {
     ContentParent* parent = AsContentParent();
     if (!ContentParent::IgnoreIPCPrincipal() &&
         parent && principal && !AssertAppPrincipal(parent, principal)) {
       return false;
--- a/dom/ipc/nsIContentParent.h
+++ b/dom/ipc/nsIContentParent.h
@@ -86,21 +86,21 @@ protected: // IPDL methods
 
   virtual bool DeallocPBlobParent(PBlobParent* aActor);
 
   virtual bool RecvSyncMessage(const nsString& aMsg,
                                const ClonedMessageData& aData,
                                const InfallibleTArray<jsipc::CpowEntry>& aCpows,
                                const IPC::Principal& aPrincipal,
                                InfallibleTArray<nsString>* aRetvals);
-  virtual bool AnswerRpcMessage(const nsString& aMsg,
-                                const ClonedMessageData& aData,
-                                const InfallibleTArray<jsipc::CpowEntry>& aCpows,
-                                const IPC::Principal& aPrincipal,
-                                InfallibleTArray<nsString>* aRetvals);
+  virtual bool RecvRpcMessage(const nsString& aMsg,
+                              const ClonedMessageData& aData,
+                              const InfallibleTArray<jsipc::CpowEntry>& aCpows,
+                              const IPC::Principal& aPrincipal,
+                              InfallibleTArray<nsString>* aRetvals);
   virtual bool RecvAsyncMessage(const nsString& aMsg,
                                 const ClonedMessageData& aData,
                                 const InfallibleTArray<jsipc::CpowEntry>& aCpows,
                                 const IPC::Principal& aPrincipal);
 
 protected: // members
   nsRefPtr<nsFrameMessageManager> mMessageManager;
 };
--- a/ipc/chromium/src/chrome/common/ipc_message.h
+++ b/ipc/chromium/src/chrome/common/ipc_message.h
@@ -48,19 +48,19 @@ class Message : public Pickle {
     // Sends the given IPC message.  The implementor takes ownership of the
     // given Message regardless of whether or not this method succeeds.  This
     // is done to make this method easier to use.  Returns true on success and
     // false otherwise.
     virtual bool Send(Message* msg) = 0;
   };
 
   enum PriorityValue {
-    PRIORITY_LOW = 1,
-    PRIORITY_NORMAL,
-    PRIORITY_HIGH
+    PRIORITY_NORMAL = 1,
+    PRIORITY_HIGH = 2,
+    PRIORITY_URGENT = 3
   };
 
   enum MessageCompression {
     COMPRESSION_NONE,
     COMPRESSION_ENABLED
   };
 
   virtual ~Message();
@@ -80,36 +80,31 @@ class Message : public Pickle {
 
   Message(const Message& other);
   Message& operator=(const Message& other);
 
   PriorityValue priority() const {
     return static_cast<PriorityValue>(header()->flags & PRIORITY_MASK);
   }
 
+  void set_priority(int prio) {
+    DCHECK((prio & ~PRIORITY_MASK) == 0);
+    header()->flags = (header()->flags & ~PRIORITY_MASK) | prio;
+  }
+
   // True if this is a synchronous message.
   bool is_sync() const {
     return (header()->flags & SYNC_BIT) != 0;
   }
 
   // True if this is a synchronous message.
   bool is_interrupt() const {
     return (header()->flags & INTERRUPT_BIT) != 0;
   }
 
-  // True if this is an urgent message.
-  bool is_urgent() const {
-    return (header()->flags & URGENT_BIT) != 0;
-  }
-
-  // True if this is an RPC message.
-  bool is_rpc() const {
-    return (header()->flags & RPC_BIT) != 0;
-  }
-
   // True if compression is enabled for this message.
   bool compress() const {
     return (header()->flags & COMPRESS_BIT) != 0;
   }
 
   // Set this on a reply to a synchronous message.
   void set_reply() {
     header()->flags |= REPLY_BIT;
@@ -291,41 +286,31 @@ class Message : public Pickle {
   void set_sync() {
     header()->flags |= SYNC_BIT;
   }
 
   void set_interrupt() {
     header()->flags |= INTERRUPT_BIT;
   }
 
-  void set_urgent() {
-    header()->flags |= URGENT_BIT;
-  }
-
-  void set_rpc() {
-    header()->flags |= RPC_BIT;
-  }
-
 #if !defined(OS_MACOSX)
  protected:
 #endif
 
   // flags
   enum {
     PRIORITY_MASK   = 0x0003,
     SYNC_BIT        = 0x0004,
     REPLY_BIT       = 0x0008,
     REPLY_ERROR_BIT = 0x0010,
     UNBLOCK_BIT     = 0x0020,
     PUMPING_MSGS_BIT= 0x0040,
     HAS_SENT_TIME_BIT = 0x0080,
     INTERRUPT_BIT   = 0x0100,
     COMPRESS_BIT    = 0x0200,
-    URGENT_BIT      = 0x0400,
-    RPC_BIT         = 0x0800
   };
 
   struct Header : Pickle::Header {
     int32_t routing;  // ID of the view that this message is destined for
     msgid_t type;   // specifies the user-defined message type
     uint32_t flags;   // specifies control flags for the message
 #if defined(OS_POSIX)
     uint32_t num_fds; // the number of descriptors included with this message
--- a/ipc/glue/MessageChannel.cpp
+++ b/ipc/glue/MessageChannel.cpp
@@ -15,16 +15,72 @@
 #include "nsISupportsImpl.h"
 #include "nsContentUtils.h"
 
 #include "prprf.h"
 
 // Undo the damage done by mozzconf.h
 #undef compress
 
+/*
+ * IPC design:
+ *
+ * There are three kinds of messages: async, sync, and intr. Sync and intr
+ * messages are blocking. Only intr and high-priority sync messages can nest.
+ *
+ * Terminology: To dispatch a message Foo is to run the RecvFoo code for
+ * it. This is also called "handling" the message.
+ *
+ * Sync messages have priorities while async and intr messages always have
+ * normal priority. The three possible priorities are normal, high, and urgent.
+ * The intended uses of these priorities are:
+ *   NORMAL - most messages.
+ *   HIGH   - CPOW-related messages, which can go in either direction.
+ *   URGENT - messages where we don't want to dispatch
+ *            incoming CPOWs while waiting for the response.
+ *
+ * To avoid jank, the parent process is not allowed to send sync messages of
+ * normal priority. The parent also is not allowed to send urgent messages at
+ * all.  When a process is waiting for a response to a sync message M0, it will
+ * dispatch an incoming message M if:
+ *   1. M has a higher priority than M0, or
+ *   2. if M has the same priority as M0 and we're in the child, or
+ *   3. if M has the same priority as M0 and it was sent by the other side
+        while dispatching M0 (nesting).
+ * The idea is that higher priority messages should take precendence, and we
+ * also want to allow nesting. The purpose of rule 2 is to handle a race where
+ * both processes send to each other simultaneously. In this case, we resolve
+ * the race in favor of the parent (so the child dispatches first).
+ *
+ * Sync messages satisfy the following properties:
+ *   A. When waiting for a response to a sync message, we won't dispatch any
+ *      messages of lower priority.
+ *   B. Sync messages of the same priority will be dispatched roughly in the
+ *      order they were sent. The exception is when the parent and child send
+ *      sync messages to each other simulataneously. In this case, the parent's
+ *      message is dispatched first. While it is dispatched, the child may send
+ *      further nested messages, and these messages may be dispatched before the
+ *      child's original message. We can consider ordering to be preserved here
+ *      because we pretend that the child's original message wasn't sent until
+ *      after the parent's message is finished being dispatched.
+ *
+ * Intr messages are blocking but not prioritized. While waiting for an intr
+ * response, all incoming messages are dispatched until a response is
+ * received. Intr messages also can be nested. When two intr messages race with
+ * each other, a similar scheme is used to ensure that one side wins. The
+ * winning side is chosen based on the message type.
+ *
+ * Intr messages differ from sync messages in that, while sending an intr
+ * message, we may dispatch an async message. This causes some additional
+ * complexity. One issue is that replies can be received out of order. It's also
+ * more difficult to determine whether one message is nested inside
+ * another. Consequently, intr handling uses mOutOfTurnReplies and
+ * mRemoteStackDepthGuess, which are not needed for sync messages.
+ */
+
 using namespace mozilla;
 using namespace std;
 
 using mozilla::MonitorAutoLock;
 using mozilla::MonitorAutoUnlock;
 
 template<>
 struct RunnableMethodTraits<mozilla::ipc::MessageChannel>
@@ -34,17 +90,17 @@ struct RunnableMethodTraits<mozilla::ipc
 };
 
 #define IPC_ASSERT(_cond, ...)                                      \
     do {                                                            \
         if (!(_cond))                                               \
             DebugAbort(__FILE__, __LINE__, #_cond,## __VA_ARGS__);  \
     } while (0)
 
-static uintptr_t gDispatchingUrgentMessageCount;
+static bool gParentIsBlocked;
 
 namespace mozilla {
 namespace ipc {
 
 const int32_t MessageChannel::kNoTimeout = INT32_MIN;
 
 // static
 bool MessageChannel::sIsPumpingMessages = false;
@@ -190,19 +246,19 @@ private:
     CxxStackFrame(const CxxStackFrame&) MOZ_DELETE;
     CxxStackFrame& operator=(const CxxStackFrame&) MOZ_DELETE;
 };
 
 namespace {
 
 class MOZ_STACK_CLASS MaybeScriptBlocker {
 public:
-    explicit MaybeScriptBlocker(MessageChannel *aChannel
+    explicit MaybeScriptBlocker(MessageChannel *aChannel, bool aBlock
                                 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
-        : mBlocked(aChannel->ShouldBlockScripts())
+        : mBlocked(aChannel->ShouldBlockScripts() && aBlock)
     {
         MOZ_GUARD_OBJECT_NOTIFIER_INIT;
         if (mBlocked) {
             nsContentUtils::AddScriptBlocker();
         }
     }
     ~MaybeScriptBlocker() {
         if (mBlocked) {
@@ -222,22 +278,21 @@ MessageChannel::MessageChannel(MessageLi
     mSide(UnknownSide),
     mLink(nullptr),
     mWorkerLoop(nullptr),
     mChannelErrorTask(nullptr),
     mWorkerLoopID(-1),
     mTimeoutMs(kNoTimeout),
     mInTimeoutSecondHalf(false),
     mNextSeqno(0),
-    mPendingSyncReplies(0),
-    mPendingUrgentReplies(0),
-    mPendingRPCReplies(0),
-    mCurrentRPCTransaction(0),
+    mAwaitingSyncReply(false),
+    mAwaitingSyncReplyPriority(0),
     mDispatchingSyncMessage(false),
-    mDispatchingUrgentMessageCount(0),
+    mDispatchingSyncMessagePriority(0),
+    mCurrentTransaction(0),
     mRemoteStackDepthGuess(false),
     mSawInterruptOutMsg(false),
     mAbortOnError(false),
     mBlockScripts(false),
     mFlags(REQUIRE_DEFAULT),
     mPeerPidSet(false),
     mPeerPid(-1)
 {
@@ -322,18 +377,17 @@ MessageChannel::Clear()
 
     if (mChannelErrorTask) {
         mChannelErrorTask->Cancel();
         mChannelErrorTask = nullptr;
     }
 
     // Free up any memory used by pending messages.
     mPending.clear();
-    mPendingUrgentRequest = nullptr;
-    mPendingRPCCall = nullptr;
+    mRecvd = nullptr;
     mOutOfTurnReplies.clear();
     while (!mDeferred.empty()) {
         mDeferred.pop();
     }
 }
 
 bool
 MessageChannel::Open(Transport* aTransport, MessageLoop* aIOLoop, Side aSide)
@@ -483,118 +537,117 @@ MessageChannel::MaybeInterceptSpecialIOM
             printf("NOTE: %s process received `Goodbye', closing down\n",
                    (mSide == ChildSide) ? "child" : "parent");
         }
         return true;
     }
     return false;
 }
 
+bool
+MessageChannel::ShouldDeferMessage(const Message& aMsg)
+{
+    // Never defer messages that have the highest priority, even async
+    // ones. This is safe because only the child can send these messages, so
+    // they can never nest.
+    if (aMsg.priority() == IPC::Message::PRIORITY_URGENT) {
+        MOZ_ASSERT(mSide == ParentSide);
+        return false;
+    }
+
+    // Unless they're urgent, we always defer async messages.
+    if (!aMsg.is_sync()) {
+        MOZ_ASSERT(aMsg.priority() == IPC::Message::PRIORITY_NORMAL);
+        return true;
+    }
+
+    int msgPrio = aMsg.priority();
+    int waitingPrio = AwaitingSyncReplyPriority();
+
+    // Always defer if the priority of the incoming message is less than the
+    // priority of the message we're awaiting.
+    if (msgPrio < waitingPrio)
+        return true;
+
+    // Never defer if the message has strictly greater priority.
+    if (msgPrio > waitingPrio)
+        return false;
+
+    // When both sides send sync messages of the same priority, we resolve the
+    // race by dispatching in the child and deferring the incoming message in
+    // the parent. However, the parent still needs to dispatch nested sync
+    // messages.
+    //
+    // Deferring in the parent only sort of breaks message ordering. When the
+    // child's message comes in, we can pretend the child hasn't quite
+    // finished sending it yet. Since the message is sync, we know that the
+    // child hasn't moved on yet.
+    return mSide == ParentSide && aMsg.transaction_id() != mCurrentTransaction;
+}
+
 void
 MessageChannel::OnMessageReceivedFromLink(const Message& aMsg)
 {
     AssertLinkThread();
     mMonitor->AssertCurrentThreadOwns();
 
     if (MaybeInterceptSpecialIOMessage(aMsg))
         return;
 
-    // Regardless of the Interrupt stack, if we're awaiting a sync or urgent reply,
+    // Regardless of the Interrupt stack, if we're awaiting a sync reply,
     // we know that it needs to be immediately handled to unblock us.
-    if ((AwaitingSyncReply() && aMsg.is_sync()) ||
-        (AwaitingUrgentReply() && aMsg.is_urgent()) ||
-        (AwaitingRPCReply() && aMsg.is_rpc()))
-    {
+    if (AwaitingSyncReply() && aMsg.is_sync() && aMsg.is_reply()) {
+        MOZ_ASSERT(!mRecvd);
         mRecvd = new Message(aMsg);
         NotifyWorkerThread();
         return;
     }
 
-    // Urgent messages cannot be compressed.
-    MOZ_ASSERT(!aMsg.compress() || !aMsg.is_urgent());
+    // Prioritized messages cannot be compressed.
+    MOZ_ASSERT(!aMsg.compress() || aMsg.priority() == IPC::Message::PRIORITY_NORMAL);
 
     bool compress = (aMsg.compress() && !mPending.empty() &&
                      mPending.back().type() == aMsg.type() &&
                      mPending.back().routing_id() == aMsg.routing_id());
     if (compress) {
         // This message type has compression enabled, and the back of the
         // queue was the same message type and routed to the same destination.
         // Replace it with the newer message.
         MOZ_ASSERT(mPending.back().compress());
         mPending.pop_back();
     }
 
     bool shouldWakeUp = AwaitingInterruptReply() ||
-                        // Allow incoming RPCs to be processed inside an urgent message.
-                        (AwaitingUrgentReply() && aMsg.is_rpc()) ||
-                        // Always process urgent messages while blocked.
-                        ((AwaitingSyncReply() || AwaitingRPCReply()) && aMsg.is_urgent());
+                        (AwaitingSyncReply() && !ShouldDeferMessage(aMsg));
 
-    // There are four cases we're concerned about, relating to the state of the
+    // There are three cases we're concerned about, relating to the state of the
     // main thread:
     //
-    // (1) We are waiting on a sync|rpc reply - main thread is blocked on the
+    // (1) We are waiting on a sync reply - main thread is blocked on the
     //     IPC monitor.
     //   - If the message is high priority, we wake up the main thread to
-    //     deliver the message. Otherwise, we leave it in the mPending queue,
-    //     posting a task to the main event loop, where it will be processed
-    //     once the synchronous reply has been received.
+    //     deliver the message depending on ShouldDeferMessage. Otherwise, we
+    //     leave it in the mPending queue, posting a task to the main event
+    //     loop, where it will be processed once the synchronous reply has been
+    //     received.
     //
     // (2) We are waiting on an Interrupt reply - main thread is blocked on the
     //     IPC monitor.
     //   - Always notify and wake up the main thread.
     //
     // (3) We are not waiting on a reply.
     //   - We post a task to the main event loop.
     //
     // Note that, we may notify the main thread even though the monitor is not
     // blocked. This is okay, since we always check for pending events before
     // blocking again.
 
-    if (shouldWakeUp && (AwaitingUrgentReply() && aMsg.is_rpc())) {
-        // If we're receiving an RPC message while blocked on an urgent message,
-        // we must defer any messages that were not sent as part of the child
-        // answering the urgent message.
-        //
-        // We must also be sure that we will not accidentally defer any RPC
-        // message that was sent while answering an urgent message. Otherwise,
-        // we will deadlock.
-        //
-        // On the parent side, the current transaction can only transition from 0
-        // to an ID, either by us issuing an urgent request while not blocked, or
-        // by receiving an RPC request while not blocked. When we unblock, the
-        // current transaction is reset to 0.
-        //
-        // When the child side receives an urgent message, any RPC messages sent
-        // before issuing the urgent reply will carry the urgent message's
-        // transaction ID.
-        //
-        // Since AwaitingUrgentReply() implies we are blocked, it also implies
-        // that we are within a transaction that will not change until we are
-        // completely unblocked (i.e, the transaction has completed).
-        if (aMsg.transaction_id() != mCurrentRPCTransaction)
-            shouldWakeUp = false;
-    }
-
-    if (aMsg.is_urgent()) {
-        MOZ_ASSERT(!mPendingUrgentRequest);
-        mPendingUrgentRequest = new Message(aMsg);
-    } else if (aMsg.is_rpc() && shouldWakeUp) {
-        // Only use this slot if we need to wake up for an RPC call. Otherwise
-        // we treat it like a normal async or sync message.
-        MOZ_ASSERT(!mPendingRPCCall);
-        mPendingRPCCall = new Message(aMsg);
-    } else {
-        mPending.push_back(aMsg);
-    }
+    mPending.push_back(aMsg);
 
     if (shouldWakeUp) {
-        // Always wake up Interrupt waiters, sync waiters for urgent messages,
-        // RPC waiters for urgent messages, and urgent waiters for RPCs in the
-        // same transaction.
         NotifyWorkerThread();
     } else {
         // Worker thread is either not blocked on a reply, or this is an
         // incoming Interrupt that raced with outgoing sync, and needs to be
         // deferred to a later event-loop iteration.
         if (!compress) {
             // If we compressed away the previous message, we'll re-use
             // its pending task.
@@ -602,103 +655,64 @@ MessageChannel::OnMessageReceivedFromLin
         }
     }
 }
 
 bool
 MessageChannel::Send(Message* aMsg, Message* aReply)
 {
     // See comment in DispatchUrgentMessage.
-    MaybeScriptBlocker scriptBlocker(this);
+    MaybeScriptBlocker scriptBlocker(this, true);
 
     // Sanity checks.
     AssertWorkerThread();
     mMonitor->AssertNotCurrentThreadOwns();
 
 #ifdef OS_WIN
     SyncStackFrame frame(this, false);
 #endif
 
     CxxStackFrame f(*this, OUT_MESSAGE, aMsg);
 
     MonitorAutoLock lock(*mMonitor);
 
     IPC_ASSERT(aMsg->is_sync(), "can only Send() sync messages here");
-    IPC_ASSERT(!DispatchingSyncMessage(), "violation of sync handler invariant");
-    IPC_ASSERT(!DispatchingUrgentMessage(), "sync messages forbidden while handling urgent message");
-    IPC_ASSERT(!AwaitingSyncReply(), "nested sync messages are not supported");
+    IPC_ASSERT(aMsg->priority() >= DispatchingSyncMessagePriority(),
+               "can't send sync message of a lesser priority than what's being dispatched");
+    IPC_ASSERT(mAwaitingSyncReplyPriority <= aMsg->priority(),
+               "nested sync message sends must be of increasing priority");
 
-    AutoEnterPendingReply replies(mPendingSyncReplies);
+    AutoSetValue<bool> replies(mAwaitingSyncReply, true);
+    AutoSetValue<int> prio(mAwaitingSyncReplyPriority, aMsg->priority());
+    AutoEnterTransaction transact(this);
+    aMsg->set_transaction_id(mCurrentTransaction);
+
     if (!SendAndWait(aMsg, aReply))
         return false;
 
     NS_ABORT_IF_FALSE(aReply->is_sync(), "reply is not sync");
     return true;
 }
 
-bool
-MessageChannel::UrgentCall(Message* aMsg, Message* aReply)
+struct AutoDeferMessages
 {
-    // See comment in DispatchUrgentMessage.
-    MaybeScriptBlocker scriptBlocker(this);
-
-    AssertWorkerThread();
-    mMonitor->AssertNotCurrentThreadOwns();
-    IPC_ASSERT(mSide == ParentSide, "cannot send urgent requests from child");
-
-#ifdef OS_WIN
-    SyncStackFrame frame(this, false);
-#endif
+    typedef IPC::Message Message;
 
-    CxxStackFrame f(*this, OUT_MESSAGE, aMsg);
-
-    MonitorAutoLock lock(*mMonitor);
-
-    IPC_ASSERT(!AwaitingInterruptReply(), "urgent calls cannot be issued within Interrupt calls");
-    IPC_ASSERT(!AwaitingSyncReply(), "urgent calls cannot be issued within sync sends");
-
-    AutoEnterRPCTransaction transact(this);
-    aMsg->set_transaction_id(mCurrentRPCTransaction);
-
-    AutoEnterPendingReply replies(mPendingUrgentReplies);
-    if (!SendAndWait(aMsg, aReply))
-        return false;
+    std::deque<Message>& mQueue;
+    mozilla::Vector<Message> mDeferred;
 
-    NS_ABORT_IF_FALSE(aReply->is_urgent(), "reply is not urgent");
-    return true;
-}
-
-bool
-MessageChannel::RPCCall(Message* aMsg, Message* aReply)
-{
-    // See comment in DispatchUrgentMessage.
-    MaybeScriptBlocker scriptBlocker(this);
-
-    AssertWorkerThread();
-    mMonitor->AssertNotCurrentThreadOwns();
-    IPC_ASSERT(mSide == ChildSide, "cannot send rpc messages from parent");
+    AutoDeferMessages(std::deque<Message>& queue) : mQueue(queue) {}
+    ~AutoDeferMessages() {
+        mQueue.insert(mQueue.begin(), mDeferred.begin(), mDeferred.end());
+    }
 
-#ifdef OS_WIN
-    SyncStackFrame frame(this, false);
-#endif
-
-    CxxStackFrame f(*this, OUT_MESSAGE, aMsg);
-
-    MonitorAutoLock lock(*mMonitor);
-
-    AutoEnterRPCTransaction transact(this);
-    aMsg->set_transaction_id(mCurrentRPCTransaction);
-
-    AutoEnterPendingReply replies(mPendingRPCReplies);
-    if (!SendAndWait(aMsg, aReply))
-        return false;
-
-    NS_ABORT_IF_FALSE(aReply->is_rpc(), "expected rpc reply");
-    return true;
-}
+    void Defer(Message aMsg) {
+        mDeferred.append(aMsg);
+    }
+};
 
 bool
 MessageChannel::SendAndWait(Message* aMsg, Message* aReply)
 {
     mMonitor->AssertCurrentThreadOwns();
 
     nsAutoPtr<Message> msg(aMsg);
 
@@ -709,80 +723,62 @@ MessageChannel::SendAndWait(Message* aMs
 
     msg->set_seqno(NextSeqno());
 
     DebugOnly<int32_t> replySeqno = msg->seqno();
     DebugOnly<msgid_t> replyType = msg->type() + 1;
 
     mLink->SendMessage(msg.forget());
 
-    while (true) {
-        // Wait for an event to occur.
-        while (true) {
-            if (mRecvd || mPendingUrgentRequest || mPendingRPCCall)
-                break;
-
-            bool maybeTimedOut = !WaitForSyncNotify();
+    AutoDeferMessages defer(mPending);
 
-            if (!Connected()) {
-                ReportConnectionError("MessageChannel::SendAndWait");
-                return false;
-            }
-
-            if (maybeTimedOut && !ShouldContinueFromTimeout())
-                return false;
+    while (true) {
+        while (!mPending.empty()) {
+            Message msg = mPending.front();
+            mPending.pop_front();
+            if (ShouldDeferMessage(msg))
+                defer.Defer(msg);
+            else
+                ProcessPendingRequest(msg);
         }
 
-        // We need to make sure that all messages deposited in mPendingRPCCall
-        // and mPendingUrgentRequest are dispatched before we leave this
-        // function. Otherwise, there's nothing to wake us up and force us to
-        // dispatch them.
-        while (mPendingUrgentRequest) {
-            if (!ProcessPendingUrgentRequest())
-                return false;
-        }
-
-        while (mPendingRPCCall) {
-            if (!ProcessPendingRPCCall())
-                return false;
-        }
-
+        // See if we've received a reply.
         if (mRecvd) {
-            NS_ABORT_IF_FALSE(mRecvd->is_reply(), "expected reply");
+            MOZ_ASSERT(mRecvd->is_reply(), "expected reply");
 
             if (mRecvd->is_reply_error()) {
                 mRecvd = nullptr;
                 return false;
             }
 
-            NS_ABORT_IF_FALSE(mRecvd->type() == replyType, "wrong reply type");
-            NS_ABORT_IF_FALSE(mRecvd->seqno() == replySeqno, "wrong sequence number");
+            MOZ_ASSERT(mRecvd->type() == replyType, "wrong reply type");
+            MOZ_ASSERT(mRecvd->seqno() == replySeqno);
 
             *aReply = *mRecvd;
             mRecvd = nullptr;
             return true;
         }
+
+        bool maybeTimedOut = !WaitForSyncNotify();
+
+        if (!Connected()) {
+            ReportConnectionError("MessageChannel::SendAndWait");
+            return false;
+        }
+
+        if (maybeTimedOut && !ShouldContinueFromTimeout())
+            return false;
     }
 
     return true;
 }
 
 bool
 MessageChannel::Call(Message* aMsg, Message* aReply)
 {
-    if (aMsg->is_urgent())
-        return UrgentCall(aMsg, aReply);
-    if (aMsg->is_rpc())
-        return RPCCall(aMsg, aReply);
-    return InterruptCall(aMsg, aReply);
-}
-
-bool
-MessageChannel::InterruptCall(Message* aMsg, Message* aReply)
-{
     AssertWorkerThread();
     mMonitor->AssertNotCurrentThreadOwns();
 
 #ifdef OS_WIN
     SyncStackFrame frame(this, true);
 #endif
 
     // This must come before MonitorAutoLock, as its destructor acquires the
@@ -791,39 +787,38 @@ MessageChannel::InterruptCall(Message* a
 
     MonitorAutoLock lock(*mMonitor);
     if (!Connected()) {
         ReportConnectionError("MessageChannel::Call");
         return false;
     }
 
     // Sanity checks.
-    IPC_ASSERT(!AwaitingSyncReply() && !AwaitingUrgentReply(),
-               "cannot issue Interrupt call whiel blocked on sync or urgent");
-    IPC_ASSERT(!DispatchingSyncMessage() || aMsg->priority() == IPC::Message::PRIORITY_HIGH,
+    IPC_ASSERT(!AwaitingSyncReply(),
+               "cannot issue Interrupt call while blocked on sync request");
+    IPC_ASSERT(!DispatchingSyncMessage(),
                "violation of sync handler invariant");
     IPC_ASSERT(aMsg->is_interrupt(), "can only Call() Interrupt messages here");
 
-
     nsAutoPtr<Message> msg(aMsg);
 
     msg->set_seqno(NextSeqno());
     msg->set_interrupt_remote_stack_depth_guess(mRemoteStackDepthGuess);
     msg->set_interrupt_local_stack_depth(1 + InterruptStackDepth());
     mInterruptStack.push(*msg);
     mLink->SendMessage(msg.forget());
 
     while (true) {
         // if a handler invoked by *Dispatch*() spun a nested event
         // loop, and the connection was broken during that loop, we
         // might have already processed the OnError event. if so,
         // trying another loop iteration will be futile because
         // channel state will have been cleared
         if (!Connected()) {
-            ReportConnectionError("MessageChannel::InterruptCall");
+            ReportConnectionError("MessageChannel::Call");
             return false;
         }
 
         // Now might be the time to process a message deferred because of race
         // resolution.
         MaybeUndeferIncall();
 
         // Wait for an event to occur.
@@ -840,24 +835,18 @@ MessageChannel::InterruptCall(Message* a
 
             if (maybeTimedOut && !ShouldContinueFromTimeout())
                 return false;
         }
 
         Message recvd;
         MessageMap::iterator it;
 
-        if (mPendingUrgentRequest) {
-            recvd = *mPendingUrgentRequest;
-            mPendingUrgentRequest = nullptr;
-        } else if (mPendingRPCCall) {
-            recvd = *mPendingRPCCall;
-            mPendingRPCCall = nullptr;
-        } else if ((it = mOutOfTurnReplies.find(mInterruptStack.top().seqno()))
-                    != mOutOfTurnReplies.end())
+        if ((it = mOutOfTurnReplies.find(mInterruptStack.top().seqno()))
+            != mOutOfTurnReplies.end())
         {
             recvd = it->second;
             mOutOfTurnReplies.erase(it);
         } else if (!mPending.empty()) {
             recvd = mPending.front();
             mPending.pop_front();
         } else {
             // because of subtleties with nested event loops, it's possible
@@ -865,21 +854,18 @@ MessageChannel::InterruptCall(Message* a
             // deferred in-call that needs to be processed.  either way, we
             // won't break the inner while loop again until something new
             // happens.
             continue;
         }
 
         // If the message is not Interrupt, we can dispatch it as normal.
         if (!recvd.is_interrupt()) {
-            // Other side should be blocked.
-            IPC_ASSERT(!recvd.is_sync() || mPending.empty(), "other side should be blocked");
-
             {
-                AutoEnterRPCTransaction transaction(this, &recvd);
+                AutoEnterTransaction transaction(this, &recvd);
                 MonitorAutoUnlock unlock(*mMonitor);
                 CxxStackFrame frame(*this, IN_MESSAGE, &recvd);
                 DispatchMessage(recvd);
             }
             if (!Connected()) {
                 ReportConnectionError("MessageChannel::DispatchMessage");
                 return false;
             }
@@ -950,90 +936,47 @@ bool
 MessageChannel::InterruptEventOccurred()
 {
     AssertWorkerThread();
     mMonitor->AssertCurrentThreadOwns();
     IPC_ASSERT(InterruptStackDepth() > 0, "not in wait loop");
 
     return (!Connected() ||
             !mPending.empty() ||
-            mPendingUrgentRequest ||
-            mPendingRPCCall ||
             (!mOutOfTurnReplies.empty() &&
              mOutOfTurnReplies.find(mInterruptStack.top().seqno()) !=
              mOutOfTurnReplies.end()));
 }
 
 bool
-MessageChannel::ProcessPendingUrgentRequest()
+MessageChannel::ProcessPendingRequest(Message aUrgent)
 {
     AssertWorkerThread();
     mMonitor->AssertCurrentThreadOwns();
 
     // Note that it is possible we could have sent a sync message at
     // the same time the parent process sent an urgent message, and
     // therefore mPendingUrgentRequest is set *and* mRecvd is set as
     // well, because the link thread received both before the worker
     // thread woke up.
     //
     // In this case, we process the urgent message first, but we need
     // to save the reply.
     nsAutoPtr<Message> savedReply(mRecvd.forget());
 
-    // We're the child process. We should not be receiving RPC calls.
-    IPC_ASSERT(!mPendingRPCCall, "unexpected RPC call");
-
-    nsAutoPtr<Message> recvd(mPendingUrgentRequest.forget());
     {
         // In order to send the parent RPC messages and guarantee it will
         // wake up, we must re-use its transaction.
-        AutoEnterRPCTransaction transaction(this, recvd);
+        AutoEnterTransaction transaction(this, &aUrgent);
 
         MonitorAutoUnlock unlock(*mMonitor);
-        DispatchUrgentMessage(*recvd);
+        DispatchMessage(aUrgent);
     }
     if (!Connected()) {
-        ReportConnectionError("MessageChannel::DispatchUrgentMessage");
-        return false;
-    }
-
-    // In between having dispatched our reply to the parent process, and
-    // re-acquiring the monitor, the parent process could have already
-    // processed that reply and sent the reply to our sync message. If so,
-    // our saved reply should be empty.
-    IPC_ASSERT(!mRecvd || !savedReply, "unknown reply");
-    if (!mRecvd)
-        mRecvd = savedReply.forget();
-    return true;
-}
-
-bool
-MessageChannel::ProcessPendingRPCCall()
-{
-    AssertWorkerThread();
-    mMonitor->AssertCurrentThreadOwns();
-
-    // See comment above re: mRecvd replies and incoming calls.
-    nsAutoPtr<Message> savedReply(mRecvd.forget());
-
-    IPC_ASSERT(!mPendingUrgentRequest, "unexpected urgent message");
-
-    nsAutoPtr<Message> recvd(mPendingRPCCall.forget());
-    {
-        // If we are not currently in a transaction, this will begin one,
-        // and the link thread will not wake us up for any RPC messages not
-        // apart of this transaction. If we are already in a transaction,
-        // then this will assert that we're still in the same transaction.
-        AutoEnterRPCTransaction transaction(this, recvd);
-
-        MonitorAutoUnlock unlock(*mMonitor);
-        DispatchRPCMessage(*recvd);
-    }
-    if (!Connected()) {
-        ReportConnectionError("MessageChannel::DispatchRPCMessage");
+        ReportConnectionError("MessageChannel::ProcessPendingRequest");
         return false;
     }
 
     // In between having dispatched our reply to the parent process, and
     // re-acquiring the monitor, the parent process could have already
     // processed that reply and sent the reply to our sync message. If so,
     // our saved reply should be empty.
     IPC_ASSERT(!mRecvd || !savedReply, "unknown reply");
@@ -1048,28 +991,16 @@ MessageChannel::DequeueOne(Message *recv
     AssertWorkerThread();
     mMonitor->AssertCurrentThreadOwns();
 
     if (!Connected()) {
         ReportConnectionError("OnMaybeDequeueOne");
         return false;
     }
 
-    if (mPendingUrgentRequest) {
-        *recvd = *mPendingUrgentRequest;
-        mPendingUrgentRequest = nullptr;
-        return true;
-    }
-
-    if (mPendingRPCCall) {
-        *recvd = *mPendingRPCCall;
-        mPendingRPCCall = nullptr;
-        return true;
-    }
-
     if (!mDeferred.empty())
         MaybeUndeferIncall();
 
     if (mPending.empty())
         return false;
 
     *recvd = mPending.front();
     mPending.pop_front();
@@ -1092,152 +1023,90 @@ MessageChannel::OnMaybeDequeueOne()
         // We probably just received a reply in a nested loop for an
         // Interrupt call sent before entering that loop.
         mOutOfTurnReplies[recvd.seqno()] = recvd;
         return false;
     }
 
     {
         // We should not be in a transaction yet if we're not blocked.
-        MOZ_ASSERT(mCurrentRPCTransaction == 0);
-        AutoEnterRPCTransaction transaction(this, &recvd);
+        MOZ_ASSERT(mCurrentTransaction == 0);
+        AutoEnterTransaction transaction(this, &recvd);
 
         MonitorAutoUnlock unlock(*mMonitor);
 
         CxxStackFrame frame(*this, IN_MESSAGE, &recvd);
         DispatchMessage(recvd);
     }
     return true;
 }
 
 void
 MessageChannel::DispatchMessage(const Message &aMsg)
 {
     if (aMsg.is_sync())
         DispatchSyncMessage(aMsg);
-    else if (aMsg.is_urgent())
-        DispatchUrgentMessage(aMsg);
     else if (aMsg.is_interrupt())
         DispatchInterruptMessage(aMsg, 0);
-    else if (aMsg.is_rpc())
-        DispatchRPCMessage(aMsg);
     else
         DispatchAsyncMessage(aMsg);
 }
 
 void
 MessageChannel::DispatchSyncMessage(const Message& aMsg)
 {
     AssertWorkerThread();
 
     Message *reply = nullptr;
 
-    mDispatchingSyncMessage = true;
-    Result rv = mListener->OnMessageReceived(aMsg, reply);
-    mDispatchingSyncMessage = false;
+    int prio = aMsg.priority();
+
+    // We don't want to run any code that might run a nested event loop here, so
+    // we avoid running event handlers. Once we've sent the response to the
+    // urgent message, it's okay to run event handlers again since the parent is
+    // no longer blocked.
+    MOZ_ASSERT_IF(prio > IPC::Message::PRIORITY_NORMAL, NS_IsMainThread());
+    MaybeScriptBlocker scriptBlocker(this, prio > IPC::Message::PRIORITY_NORMAL);
+
+    IPC_ASSERT(prio >= mDispatchingSyncMessagePriority,
+               "priority inversion while dispatching sync message");
+    IPC_ASSERT(prio >= mAwaitingSyncReplyPriority,
+               "dispatching a message of lower priority while waiting for a response");
+
+    bool dummy;
+    bool& blockingVar = ShouldBlockScripts() ? gParentIsBlocked : dummy;
+
+    Result rv;
+    {
+        AutoSetValue<bool> blocked(blockingVar, true);
+        AutoSetValue<bool> sync(mDispatchingSyncMessage, true);
+        AutoSetValue<int> prioSet(mDispatchingSyncMessagePriority, prio);
+        rv = mListener->OnMessageReceived(aMsg, reply);
+    }
 
     if (!MaybeHandleError(rv, aMsg, "DispatchSyncMessage")) {
         delete reply;
         reply = new Message();
         reply->set_sync();
+        reply->set_priority(aMsg.priority());
         reply->set_reply();
         reply->set_reply_error();
     }
     reply->set_seqno(aMsg.seqno());
 
     MonitorAutoLock lock(*mMonitor);
     if (ChannelConnected == mChannelState)
         mLink->SendMessage(reply);
 }
 
 void
-MessageChannel::DispatchUrgentMessage(const Message& aMsg)
-{
-    AssertWorkerThread();
-    MOZ_ASSERT(aMsg.is_urgent());
-
-    Message *reply = nullptr;
-
-    MOZ_ASSERT(NS_IsMainThread());
-
-    // We don't want to run any code that might run a nested event loop here, so
-    // we avoid running event handlers. Once we've sent the response to the
-    // urgent message, it's okay to run event handlers again since the parent is
-    // no longer blocked.
-    //
-    // We also put script blockers at the start of every synchronous send
-    // call. That way we won't run any scripts while waiting for a response to
-    // another message. Running scripts could cause us to send more sync
-    // messages, and the other side wouldn't know what to do if it received a
-    // sync message while dispatching another sync message. (In practice, the
-    // other side would queue the second sync message, while we would need it to
-    // dispatch that message before sending the reply to the original sync
-    // message. Otherwise the replies would come out of order.)
-    //
-    // We omit the script blocker for InterruptCall since interrupt messages are
-    // designed to handle this sort of re-entry. (For example, if the child
-    // sends an intr message to the parent, the child will process any queued
-    // async messages from the parent while waiting for the intr response. In
-    // doing so, the child could trigger sync messages to be sent to the parent
-    // while the parent is still dispatching the intr message. If the parent
-    // sends an intr reply while the child is waiting for a sync response, the
-    // intr reply will be queued in mPending. Once the sync reply is received,
-    // InterruptCall will find the intr reply in mPending and run it.)  The
-    // situation where we run event handlers while waiting for an intr reply is
-    // no different than the one where we process async messages while waiting
-    // for an intr reply.
-    MaybeScriptBlocker scriptBlocker(this);
-
-    gDispatchingUrgentMessageCount++;
-    mDispatchingUrgentMessageCount++;
-    Result rv = mListener->OnCallReceived(aMsg, reply);
-    mDispatchingUrgentMessageCount--;
-    gDispatchingUrgentMessageCount--;
-
-    if (!MaybeHandleError(rv, aMsg, "DispatchUrgentMessage")) {
-        delete reply;
-        reply = new Message();
-        reply->set_urgent();
-        reply->set_reply();
-        reply->set_reply_error();
-    }
-    reply->set_seqno(aMsg.seqno());
-
-    MonitorAutoLock lock(*mMonitor);
-    if (ChannelConnected == mChannelState)
-        mLink->SendMessage(reply);
-}
-
-void
-MessageChannel::DispatchRPCMessage(const Message& aMsg)
-{
-    AssertWorkerThread();
-    MOZ_ASSERT(aMsg.is_rpc());
-
-    Message *reply = nullptr;
-
-    if (!MaybeHandleError(mListener->OnCallReceived(aMsg, reply), aMsg, "DispatchRPCMessage")) {
-        delete reply;
-        reply = new Message();
-        reply->set_rpc();
-        reply->set_reply();
-        reply->set_reply_error();
-    }
-    reply->set_seqno(aMsg.seqno());
-    
-    MonitorAutoLock lock(*mMonitor);
-    if (ChannelConnected == mChannelState)
-        mLink->SendMessage(reply);
-}
-
-void
 MessageChannel::DispatchAsyncMessage(const Message& aMsg)
 {
     AssertWorkerThread();
-    MOZ_ASSERT(!aMsg.is_interrupt() && !aMsg.is_sync() && !aMsg.is_urgent());
+    MOZ_ASSERT(!aMsg.is_interrupt() && !aMsg.is_sync());
 
     if (aMsg.routing_id() == MSG_ROUTING_NONE) {
         NS_RUNTIMEABORT("unhandled special message!");
     }
 
     MaybeHandleError(mListener->OnMessageReceived(aMsg), aMsg, "DispatchAsyncMessage");
 }
 
@@ -1341,16 +1210,17 @@ MessageChannel::MaybeUndeferIncall()
     // maybe time to process this message
     Message call = mDeferred.top();
     mDeferred.pop();
 
     // fix up fudge factor we added to account for race
     IPC_ASSERT(0 < mRemoteStackDepthGuess, "fatal logic error");
     --mRemoteStackDepthGuess;
 
+    MOZ_ASSERT(call.priority() == IPC::Message::PRIORITY_NORMAL);
     mPending.push_back(call);
 }
 
 void
 MessageChannel::FlushPendingInterruptQueue()
 {
     AssertWorkerThread();
     mMonitor->AssertNotCurrentThreadOwns();
@@ -1613,17 +1483,17 @@ void
 MessageChannel::OnChannelErrorFromLink()
 {
     AssertLinkThread();
     mMonitor->AssertCurrentThreadOwns();
 
     if (InterruptStackDepth() > 0)
         NotifyWorkerThread();
 
-    if (AwaitingSyncReply() || AwaitingRPCReply() || AwaitingUrgentReply())
+    if (AwaitingSyncReply())
         NotifyWorkerThread();
 
     if (ChannelClosing != mChannelState) {
         if (mAbortOnError) {
             NS_RUNTIMEABORT("Aborting on channel error.");
         }
         mChannelState = ChannelError;
         mMonitor->Notify();
@@ -1851,15 +1721,15 @@ MessageChannel::DumpInterruptStack(const
         mCxxStackFrames[i].Describe(&id, &dir, &sems, &name);
 
         printf_stderr("%s[(%u) %s %s %s(actor=%d) ]\n", pfx,
                       i, dir, sems, name, id);
     }
 }
 
 bool
-ProcessingUrgentMessages()
+ParentProcessIsBlocked()
 {
-    return gDispatchingUrgentMessageCount > 0;
+    return gParentIsBlocked;
 }
 
 } // ipc
 } // mozilla
--- a/ipc/glue/MessageChannel.h
+++ b/ipc/glue/MessageChannel.h
@@ -221,24 +221,19 @@ class MessageChannel : HasResultCodes
     // SendAndWait() expects that the worker thread owns the monitor, and that
     // the message has been prepared to be sent over the link. It returns as
     // soon as a reply has been received, or an error has occurred.
     //
     // Note that while the child is blocked waiting for a sync reply, it can wake
     // up to process urgent calls from the parent.
     bool SendAndWait(Message* aMsg, Message* aReply);
 
-    bool RPCCall(Message* aMsg, Message* aReply);
-    bool InterruptCall(Message* aMsg, Message* aReply);
-    bool UrgentCall(Message* aMsg, Message* aReply);
-
     bool InterruptEventOccurred();
 
-    bool ProcessPendingUrgentRequest();
-    bool ProcessPendingRPCCall();
+    bool ProcessPendingRequest(Message aUrgent);
 
     void MaybeUndeferIncall();
     void EnqueuePendingMessages();
 
     // Executed on the worker thread. Dequeues one pending message.
     bool OnMaybeDequeueOne();
     bool DequeueOne(Message *recvd);
 
@@ -322,39 +317,36 @@ class MessageChannel : HasResultCodes
     size_t InterruptStackDepth() const {
         mMonitor->AssertCurrentThreadOwns();
         return mInterruptStack.size();
     }
 
     // Returns true if we're blocking waiting for a reply.
     bool AwaitingSyncReply() const {
         mMonitor->AssertCurrentThreadOwns();
-        return mPendingSyncReplies > 0;
+        return mAwaitingSyncReply;
     }
-    bool AwaitingUrgentReply() const {
+    int AwaitingSyncReplyPriority() const {
         mMonitor->AssertCurrentThreadOwns();
-        return mPendingUrgentReplies > 0;
-    }
-    bool AwaitingRPCReply() const {
-        mMonitor->AssertCurrentThreadOwns();
-        return mPendingRPCReplies > 0;
+        return mAwaitingSyncReplyPriority;
     }
     bool AwaitingInterruptReply() const {
         mMonitor->AssertCurrentThreadOwns();
         return !mInterruptStack.empty();
     }
 
     // Returns true if we're dispatching a sync message's callback.
     bool DispatchingSyncMessage() const {
+        AssertWorkerThread();
         return mDispatchingSyncMessage;
     }
 
-    // Returns true if we're dispatching an urgent message's callback.
-    bool DispatchingUrgentMessage() const {
-        return mDispatchingUrgentMessageCount > 0;
+    int DispatchingSyncMessagePriority() const {
+        AssertWorkerThread();
+        return mDispatchingSyncMessagePriority;
     }
 
     bool Connected() const;
 
   private:
     // Executed on the IO thread.
     void NotifyWorkerThread();
 
@@ -362,16 +354,17 @@ class MessageChannel : HasResultCodes
     // thread, in which case it shouldn't be delivered to the worker.
     bool MaybeInterceptSpecialIOMessage(const Message& aMsg);
 
     void OnChannelConnected(int32_t peer_id);
 
     // Tell the IO thread to close the channel and wait for it to ACK.
     void SynchronouslyClose();
 
+    bool ShouldDeferMessage(const Message& aMsg);
     void OnMessageReceivedFromLink(const Message& aMsg);
     void OnChannelErrorFromLink();
 
   private:
     // Run on the not current thread.
     void NotifyChannelClosed();
     void NotifyMaybeChannelError();
 
@@ -455,105 +448,100 @@ class MessageChannel : HasResultCodes
     bool mInTimeoutSecondHalf;
 
     // Worker-thread only; sequence numbers for messages that require
     // synchronous replies.
     int32_t mNextSeqno;
 
     static bool sIsPumpingMessages;
 
-    class AutoEnterPendingReply {
+    template<class T>
+    class AutoSetValue {
       public:
-        explicit AutoEnterPendingReply(size_t &replyVar)
-          : mReplyVar(replyVar)
+        explicit AutoSetValue(T &var, const T &newValue)
+          : mVar(var), mPrev(var)
         {
-            mReplyVar++;
+            mVar = newValue;
         }
-        ~AutoEnterPendingReply() {
-            mReplyVar--;
+        ~AutoSetValue() {
+            mVar = mPrev;
         }
       private:
-        size_t& mReplyVar;
+        T& mVar;
+        T mPrev;
     };
 
-    // Worker-thread only; type we're expecting for the reply to a sync
-    // out-message. This will never be greater than 1.
-    size_t mPendingSyncReplies;
+    // Worker thread only.
+    bool mAwaitingSyncReply;
+    int mAwaitingSyncReplyPriority;
 
-    // Worker-thread only; Number of urgent and rpc replies we're waiting on.
-    // These are mutually exclusive since one channel cannot have outcalls of
-    // both kinds.
-    size_t mPendingUrgentReplies;
-    size_t mPendingRPCReplies;
+    // Set while we are dispatching a synchronous message. Only for use on the
+    // worker thread.
+    bool mDispatchingSyncMessage;
+    int mDispatchingSyncMessagePriority;
 
     // When we send an urgent request from the parent process, we could race
     // with an RPC message that was issued by the child beforehand. In this
     // case, if the parent were to wake up while waiting for the urgent reply,
     // and process the RPC, it could send an additional urgent message. The
     // child would wake up to process the urgent message (as it always will),
     // then send a reply, which could be received by the parent out-of-order
     // with respect to the first urgent reply.
     //
     // To address this problem, urgent or RPC requests are associated with a
     // "transaction". Whenever one side of the channel wishes to start a
     // chain of RPC/urgent messages, it allocates a new transaction ID. Any
     // messages the parent receives, not apart of this transaction, are
     // deferred. When issuing RPC/urgent requests on top of a started
     // transaction, the initiating transaction ID is used.
-    // 
+    //
     // To ensure IDs are unique, we use sequence numbers for transaction IDs,
     // which grow in opposite directions from child to parent.
 
     // The current transaction ID.
-    int32_t mCurrentRPCTransaction;
+    int32_t mCurrentTransaction;
 
-    class AutoEnterRPCTransaction
+    class AutoEnterTransaction
     {
       public:
-       explicit AutoEnterRPCTransaction(MessageChannel *aChan)
+       explicit AutoEnterTransaction(MessageChannel *aChan)
         : mChan(aChan),
-          mOldTransaction(mChan->mCurrentRPCTransaction)
+          mOldTransaction(mChan->mCurrentTransaction)
        {
            mChan->mMonitor->AssertCurrentThreadOwns();
-           if (mChan->mCurrentRPCTransaction == 0)
-               mChan->mCurrentRPCTransaction = mChan->NextSeqno();
+           if (mChan->mCurrentTransaction == 0)
+               mChan->mCurrentTransaction = mChan->NextSeqno();
        }
-       AutoEnterRPCTransaction(MessageChannel *aChan, Message *message)
+       explicit AutoEnterTransaction(MessageChannel *aChan, Message *message)
         : mChan(aChan),
-          mOldTransaction(mChan->mCurrentRPCTransaction)
+          mOldTransaction(mChan->mCurrentTransaction)
        {
            mChan->mMonitor->AssertCurrentThreadOwns();
 
-           if (!message->is_rpc() && !message->is_urgent())
+           if (!message->is_sync())
                return;
 
-           MOZ_ASSERT_IF(mChan->mSide == ParentSide,
-                         !mOldTransaction || mOldTransaction == message->transaction_id());
-           mChan->mCurrentRPCTransaction = message->transaction_id();
+           MOZ_ASSERT_IF(mChan->mSide == ParentSide && mOldTransaction != message->transaction_id(),
+                         !mOldTransaction || message->priority() > mChan->AwaitingSyncReplyPriority());
+           mChan->mCurrentTransaction = message->transaction_id();
        }
-       ~AutoEnterRPCTransaction() {
+       ~AutoEnterTransaction() {
            mChan->mMonitor->AssertCurrentThreadOwns();
-           mChan->mCurrentRPCTransaction = mOldTransaction;
+           mChan->mCurrentTransaction = mOldTransaction;
        }
 
       private:
        MessageChannel *mChan;
        int32_t mOldTransaction;
     };
 
     // If waiting for the reply to a sync out-message, it will be saved here
     // on the I/O thread and then read and cleared by the worker thread.
     nsAutoPtr<Message> mRecvd;
 
-    // Set while we are dispatching a synchronous message.
-    bool mDispatchingSyncMessage;
-
-    // Count of the recursion depth of dispatching urgent messages.
-    size_t mDispatchingUrgentMessageCount;
-
     // Queue of all incoming messages, except for replies to sync and urgent
     // messages, which are delivered directly to mRecvd, and any pending urgent
     // incall, which is stored in mPendingUrgentRequest.
     //
     // If both this side and the other side are functioning correctly, the queue
     // can only be in certain configurations.  Let
     //
     //   |A<| be an async in-message,
@@ -582,28 +570,16 @@ class MessageChannel : HasResultCodes
     // then other side "finished with us," and went back to its own business.
     // That business might have included sending any number of async message
     // |A<*| until sending a blocking message |(S< | C<)|.  If we had more than
     // one Interrupt call on our stack, the other side *better* not have sent us
     // another blocking message, because it's blocked on a reply from us.
     //
     MessageQueue mPending;
 
-    // Note that these two pointers are mutually exclusive. One channel cannot
-    // send both urgent requests (parent -> child) and RPC calls (child->parent).
-    // Also note that since initiating either requires blocking, they cannot
-    // queue up on the other side. One message slot is enough.
-    //
-    // Normally, all other message types are deferred into into mPending, and
-    // only these two types have special treatment (since they wake up blocked
-    // requests). However, when an RPC in-call races with an urgent out-call,
-    // the RPC message will be put into mPending instead of its slot below.
-    nsAutoPtr<Message> mPendingUrgentRequest;
-    nsAutoPtr<Message> mPendingRPCCall;
-
     // Stack of all the out-calls on which this channel is awaiting responses.
     // Each stack refers to a different protocol and the stacks are mutually
     // exclusive: multiple outcalls of the same kind cannot be initiated while
     // another is active.
     std::stack<Message> mInterruptStack;
 
     // This is what we think the Interrupt stack depth is on the "other side" of this
     // Interrupt channel.  We maintain this variable so that we can detect racy Interrupt
@@ -671,14 +647,14 @@ class MessageChannel : HasResultCodes
     // safely.  This is necessary to be able to cancel notification if we are
     // closed at the same time.
     nsRefPtr<RefCountedTask> mOnChannelConnectedTask;
     DebugOnly<bool> mPeerPidSet;
     int32_t mPeerPid;
 };
 
 bool
-ProcessingUrgentMessages();
+ParentProcessIsBlocked();
 
 } // namespace ipc
 } // namespace mozilla
 
 #endif  // ifndef ipc_glue_MessageChannel_h
--- a/ipc/ipdl/ipdl/ast.py
+++ b/ipc/ipdl/ipdl/ast.py
@@ -1,14 +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/.
 
 import sys
 
+NORMAL_PRIORITY = 1
+HIGH_PRIORITY = 2
+URGENT_PRIORITY = 3
+
 class Visitor:
     def defaultVisit(self, node):
         raise Exception, "INTERNAL ERROR: no visitor for node type `%s'"% (
             node.__class__.__name__)
 
     def visitTranslationUnit(self, tu):
         for cxxInc in tu.cxxIncludes:
             cxxInc.accept(self)
@@ -209,18 +213,16 @@ class PrettyPrinted:
     def __str__(cls):  return cls.pretty
     
 class ASYNC(PrettyPrinted):
     pretty = 'async'
 class INTR(PrettyPrinted):
     pretty = 'intr'
 class SYNC(PrettyPrinted):
     pretty = 'sync'
-class RPC(PrettyPrinted):
-    pretty = 'rpc'
 
 class INOUT(PrettyPrinted):
     pretty = 'inout'
 class IN(PrettyPrinted):
     pretty = 'in'
 class OUT(PrettyPrinted):
     pretty = 'out'
 
@@ -229,16 +231,17 @@ class Namespace(Node):
     def __init__(self, loc, namespace):
         Node.__init__(self, loc)
         self.name = namespace
 
 class Protocol(NamespacedNode):
     def __init__(self, loc):
         NamespacedNode.__init__(self, loc)
         self.sendSemantics = ASYNC
+        self.priority = NORMAL_PRIORITY
         self.spawnsStmts = [ ]
         self.bridgesStmts = [ ]
         self.opensStmts = [ ]
         self.managers = [ ]
         self.managesStmts = [ ]
         self.messageDecls = [ ]
         self.transitionStmts = [ ]
         self.startStates = [ ]
@@ -288,30 +291,28 @@ class ManagesStmt(Node):
         Node.__init__(self, loc)
         self.name = managedName
 
 class MessageDecl(Node):
     def __init__(self, loc):
         Node.__init__(self, loc)
         self.name = None
         self.sendSemantics = ASYNC
+        self.priority = NORMAL_PRIORITY
         self.direction = None
         self.inParams = [ ]
         self.outParams = [ ]
         self.compress = ''
 
     def addInParams(self, inParamsList):
         self.inParams += inParamsList
 
     def addOutParams(self, outParamsList):
         self.outParams += outParamsList
 
-    def hasReply(self):
-        return self.sendSemantics is SYNC or self.sendSemantics is INTR
-
 class Transition(Node):
     def __init__(self, loc, trigger, msg, toStates):
         Node.__init__(self, loc)
         self.trigger = trigger
         self.msg = msg
         self.toStates = toStates
 
     def __cmp__(self, o):
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -272,23 +272,23 @@ def _putInNamespaces(cxxthing, namespace
         newns = Namespace(ns.name)
         innerns.addstmt(newns)
         innerns = newns
     innerns.addstmt(cxxthing)
     return outerns
 
 def _sendPrefix(msgtype):
     """Prefix of the name of the C++ method that sends |msgtype|."""
-    if msgtype.isInterrupt() or msgtype.isRpc():
+    if msgtype.isInterrupt():
         return 'Call'
     return 'Send'
 
 def _recvPrefix(msgtype):
     """Prefix of the name of the C++ method that handles |msgtype|."""
-    if msgtype.isInterrupt() or msgtype.isRpc():
+    if msgtype.isInterrupt():
         return 'Answer'
     return 'Recv'
 
 def _flatTypeName(ipdltype):
     """Return a 'flattened' IPDL type name that can be used as an
 identifier.
 E.g., |Foo[]| --> |ArrayOfFoo|."""
     # NB: this logic depends heavily on what IPDL types are allowed to
@@ -2979,17 +2979,17 @@ class _GenerateProtocolActorCode(ipdl.as
                 Whitespace.NL ])
 
             # Close()
             closemeth = MethodDefn(MethodDecl('Close'))
             closemeth.addstmt(StmtExpr(
                 ExprCall(ExprSelect(p.channelVar(), '.', 'Close'))))
             self.cls.addstmts([ closemeth, Whitespace.NL ])
 
-            if ptype.talksSync() or ptype.talksInterrupt():
+            if ptype.isSync() or ptype.isInterrupt():
                 # SetReplyTimeoutMs()
                 timeoutvar = ExprVar('aTimeoutMs')
                 settimeout = MethodDefn(MethodDecl(
                     'SetReplyTimeoutMs',
                     params=[ Decl(Type.INT32, timeoutvar.name) ]))
                 settimeout.addstmt(StmtExpr(
                     ExprCall(
                         ExprSelect(p.channelVar(), '.', 'SetReplyTimeoutMs'),
@@ -3048,38 +3048,40 @@ class _GenerateProtocolActorCode(ipdl.as
         # for ctor recv cases, we can't read the actor ID into a PFoo*
         # because it doesn't exist on this side yet.  Use a "special"
         # actor handle instead
         handlevar = ExprVar('__handle')
         self.handlevar = handlevar
 
         msgtype = ExprCall(ExprSelect(msgvar, '.', 'type'), [ ])
         self.asyncSwitch = StmtSwitch(msgtype)
-        if toplevel.talksSync():
+        self.syncSwitch = None
+        self.interruptSwitch = None
+        if toplevel.isSync() or toplevel.isInterrupt():
             self.syncSwitch = StmtSwitch(msgtype)
-            if toplevel.talksRpc():
+            if toplevel.isInterrupt():
                 self.interruptSwitch = StmtSwitch(msgtype)
 
         # implement Send*() methods and add dispatcher cases to
         # message switch()es
         for md in p.messageDecls:
             self.visitMessageDecl(md)
 
         # Handlers for the creation of actors when a new channel is
         # opened
         if len(channelOpenedActors):
             self.makeChannelOpenedHandlers(channelOpenedActors)
 
         # add default cases
         default = StmtBlock()
         default.addstmt(StmtReturn(_Result.NotKnown))
         self.asyncSwitch.addcase(DefaultLabel(), default)
-        if toplevel.talksSync():
+        if toplevel.isSync() or toplevel.isInterrupt():
             self.syncSwitch.addcase(DefaultLabel(), default)
-            if toplevel.talksRpc():
+            if toplevel.isInterrupt():
                 self.interruptSwitch.addcase(DefaultLabel(), default)
 
         # FIXME/bug 535053: only manager protocols and non-manager
         # protocols with union types need Lookup().  we'll give it to
         # all for the time being (simpler)
         if 1 or ptype.isManager():
             self.cls.addstmts(self.implementManagerIface())
 
@@ -3146,20 +3148,16 @@ class _GenerateProtocolActorCode(ipdl.as
             return method
 
         dispatches = (ptype.isToplevel() and ptype.isManager())
         self.cls.addstmts([
             makeHandlerMethod('OnMessageReceived', self.asyncSwitch,
                               hasReply=0, dispatches=dispatches),
             Whitespace.NL
         ])
-        if not toplevel.talksRpc():
-          self.interruptSwitch = None
-          if not toplevel.talksSync():
-            self.syncSwitch = None
         self.cls.addstmts([
             makeHandlerMethod('OnMessageReceived', self.syncSwitch,
                               hasReply=1, dispatches=dispatches),
             Whitespace.NL
         ])
         self.cls.addstmts([
             makeHandlerMethod('OnCallReceived', self.interruptSwitch,
                               hasReply=1, dispatches=dispatches),
@@ -3185,17 +3183,17 @@ class _GenerateProtocolActorCode(ipdl.as
 
         # int32_t GetProtocolTypeId() { return PFoo; }
         gettypetag = MethodDefn(
             MethodDecl('GetProtocolTypeId', ret=_actorTypeTagType()))
         gettypetag.addstmt(StmtReturn(_protocolId(ptype)))
         self.cls.addstmts([ gettypetag, Whitespace.NL ])
 
         # OnReplyTimeout()
-        if toplevel.talksSync() or toplevel.talksInterrupt():
+        if toplevel.isSync() or toplevel.isInterrupt():
             ontimeout = MethodDefn(
                 MethodDecl('OnReplyTimeout', ret=Type.BOOL))
 
             if ptype.isToplevel():
                 ontimeout.addstmt(StmtReturn(
                     ExprCall(p.shouldContinueFromTimeoutVar())))
             else:
                 ontimeout.addstmts([
@@ -3273,17 +3271,17 @@ class _GenerateProtocolActorCode(ipdl.as
             onconnected.addstmt(
                 _runtimeAbort("'OnConnected' called on non-toplevel actor"))
 
         self.cls.addstmts([ onconnected, Whitespace.NL ])
 
         # User-facing shmem methods
         self.cls.addstmts(self.makeShmemIface())
 
-        if (ptype.isToplevel() and ptype.talksInterrupt()):
+        if (ptype.isToplevel() and ptype.isInterrupt()):
 
             processnative = MethodDefn(
                 MethodDecl('ProcessNativeEventsInInterruptCall', ret=Type.VOID))
 
             processnative.addstmts([
                     CppDirective('ifdef', 'OS_WIN'),
                     StmtExpr(ExprCall(
                             ExprSelect(p.channelVar(), '.',
@@ -4775,32 +4773,32 @@ class _GenerateProtocolActorCode(ipdl.as
         if this:  read = ExprSelect(this, '->', read.name)
         return self.maybeAddNullabilityArg(
             ipdltype, ExprCall(read, args=[ expr, from_, iterexpr ]))
 
 
     def visitMessageDecl(self, md):
         isctor = md.decl.type.isCtor()
         isdtor = md.decl.type.isDtor()
-        sems = md.decl.type.sendSemantics
+        decltype = md.decl.type
         sendmethod = None
         helpermethod = None
         recvlbl, recvcase = None, None
 
         def addRecvCase(lbl, case):
-            if sems is ipdl.ast.ASYNC:
+            if decltype.isAsync():
                 self.asyncSwitch.addcase(lbl, case)
-            elif sems is ipdl.ast.SYNC:
+            elif decltype.isSync():
                 self.syncSwitch.addcase(lbl, case)
-            elif sems is ipdl.ast.INTR or sems is ipdl.ast.RPC:
+            elif decltype.isInterrupt():
                 self.interruptSwitch.addcase(lbl, case)
             else: assert 0
 
         if self.sendsMessage(md):
-            isasync = (sems is ipdl.ast.ASYNC)
+            isasync = decltype.isAsync()
 
             if isctor:
                 self.cls.addstmts([ self.genHelperCtor(md), Whitespace.NL ])
 
             if isctor and isasync:
                 sendmethod, (recvlbl, recvcase) = self.genAsyncCtor(md)
             elif isctor:
                 sendmethod = self.genBlockingCtorMethod(md)
@@ -5180,31 +5178,24 @@ class _GenerateProtocolActorCode(ipdl.as
 
         stmts = [ StmtExpr(ExprCall(
             ExprSelect(var, '->', 'set_routing_id'),
             args=[ routingId ])) ]
 
         if md.decl.type.isSync():
             stmts.append(StmtExpr(ExprCall(
                 ExprSelect(var, '->', 'set_sync'))))
-        elif md.decl.type.isRpc():
-            # We use urgent messages from the parent to the child and
-            # RPC messages from the child to the parent. However,
-            # replies should always be sent using the same semantics
-            # as the original message, so we need to flip.
-            if (self.side == 'parent') ^ reply:
-                stmts.append(StmtExpr(ExprCall(
-                    ExprSelect(var, '->', 'set_urgent'))))
-            else:
-                stmts.append(StmtExpr(ExprCall(
-                    ExprSelect(var, '->', 'set_rpc'))))
         elif md.decl.type.isInterrupt():
             stmts.append(StmtExpr(ExprCall(
                 ExprSelect(var, '->', 'set_interrupt'))))
 
+        stmts.append(StmtExpr(ExprCall(
+            ExprSelect(var, '->', 'set_priority'),
+            args=[ ExprLiteral.Int(md.decl.type.priority) ])))
+
         if reply:
             stmts.append(StmtExpr(ExprCall(
                 ExprSelect(var, '->', 'set_reply'))))
 
         return stmts + [ Whitespace.NL ]
 
 
     def deserializeMessage(self, md, side, errfn):
--- a/ipc/ipdl/ipdl/parser.py
+++ b/ipc/ipdl/ipdl/parser.py
@@ -122,39 +122,43 @@ reserved = set((
         'call',
         'child',
         'class',
         'compress',
         '__delete__',
         'delete',                       # reserve 'delete' to prevent its use
         'from',
         'goto',
+        'high',
         'include',
         'intr',
         'manager',
         'manages',
         'namespace',
+        'normal',
         'nullable',
         'opens',
         'or',
         'parent',
+        'prio',
         'protocol',
         'recv',
         'returns',
-        'rpc',
         'send',
         'spawns',
         'start',
         'state',
         'struct',
         'sync',
         'union',
+        'upto',
+        'urgent',
         'using'))
 tokens = [
-    'COLONCOLON', 'ID', 'STRING'
+    'COLONCOLON', 'ID', 'STRING',
 ] + [ r.upper() for r in reserved ]
 
 t_COLONCOLON = '::'
 
 literals = '(){}[]<>;:,~'
 t_ignore = ' \f\t\v'
 
 def t_linecomment(t):
@@ -344,21 +348,22 @@ def p_ComponentTypes(p):
                       | Type ';'"""
     if 3 == len(p):
         p[0] = [ p[1] ]
     else:
         p[1].append(p[2])
         p[0] = p[1]
 
 def p_ProtocolDefn(p):
-    """ProtocolDefn : OptionalSendSemanticsQual PROTOCOL ID '{' ProtocolBody '}' ';'"""
+    """ProtocolDefn : OptionalProtocolSendSemanticsQual PROTOCOL ID '{' ProtocolBody '}' ';'"""
     protocol = p[5]
     protocol.loc = locFromTok(p, 2)
     protocol.name = p[3]
-    protocol.sendSemantics = p[1]
+    protocol.priorityRange = p[1][0]
+    protocol.sendSemantics = p[1][1]
     p[0] = protocol
 
     if Parser.current.type == 'header':
         _error(protocol.loc, 'can\'t define a protocol in a header.  Do it in a protocol spec instead.')
 
 
 def p_ProtocolBody(p):
     """ProtocolBody : SpawnsStmtsOpt"""
@@ -490,17 +495,18 @@ def p_MessageDirectionLabel(p):
     elif p[1] == 'both':
         Parser.current.direction = INOUT
     else:
         assert 0
 
 def p_MessageDecl(p):
     """MessageDecl : OptionalSendSemanticsQual MessageBody"""
     msg = p[2]
-    msg.sendSemantics = p[1]
+    msg.priority = p[1][0]
+    msg.sendSemantics = p[1][1]
 
     if Parser.current.direction is None:
         _error(msg.loc, 'missing message direction')
     msg.direction = Parser.current.direction
 
     p[0] = msg
 
 def p_MessageBody(p):
@@ -610,34 +616,77 @@ def p_StateList(p):
         p[0] = p[1]
 
 def p_State(p):
     """State : ID"""
     p[0] = State(locFromTok(p, 1), p[1])
 
 ##--------------------
 ## Minor stuff
+def p_Priority(p):
+    """Priority : NORMAL
+                | HIGH
+                | URGENT"""
+    prios = {'normal': 1,
+             'high': 2,
+             'urgent': 3}
+    p[0] = prios[p[1]]
+
 def p_OptionalSendSemanticsQual(p):
     """OptionalSendSemanticsQual : SendSemanticsQual
                                  | """
     if 2 == len(p): p[0] = p[1]
-    else:           p[0] = ASYNC
+    else:           p[0] = [ NORMAL_PRIORITY, ASYNC ]
 
 def p_SendSemanticsQual(p):
     """SendSemanticsQual : ASYNC
-                         | INTR
-                         | RPC
-                         | SYNC"""
-    s = p[1]
-    if 'async' == s: p[0] =    ASYNC
-    elif 'intr' == s: p[0] =   INTR
-    elif 'sync' == s: p[0] =   SYNC
-    elif 'rpc' == s: p[0] =    RPC
+                         | SYNC
+                         | PRIO '(' Priority ')' ASYNC
+                         | PRIO '(' Priority ')' SYNC
+                         | INTR"""
+    if p[1] == 'prio':
+        mtype = p[5]
+        prio = p[3]
     else:
-        assert 0
+        mtype = p[1]
+        prio = NORMAL_PRIORITY
+
+    if mtype == 'async': mtype = ASYNC
+    elif mtype == 'sync': mtype = SYNC
+    elif mtype == 'intr': mtype = INTR
+    else: assert 0
+
+    p[0] = [ prio, mtype ]
+
+def p_OptionalProtocolSendSemanticsQual(p):
+    """OptionalProtocolSendSemanticsQual : ProtocolSendSemanticsQual
+                                         | """
+    if 2 == len(p): p[0] = p[1]
+    else:           p[0] = [ (NORMAL_PRIORITY, NORMAL_PRIORITY), ASYNC ]
+
+def p_ProtocolSendSemanticsQual(p):
+    """ProtocolSendSemanticsQual : ASYNC
+                                 | SYNC
+                                 | PRIO '(' Priority UPTO Priority ')' ASYNC
+                                 | PRIO '(' Priority UPTO Priority ')' SYNC
+                                 | PRIO '(' Priority UPTO Priority ')' INTR
+                                 | INTR"""
+    if p[1] == 'prio':
+        mtype = p[7]
+        prio = (p[3], p[5])
+    else:
+        mtype = p[1]
+        prio = (NORMAL_PRIORITY, NORMAL_PRIORITY)
+
+    if mtype == 'async': mtype = ASYNC
+    elif mtype == 'sync': mtype = SYNC
+    elif mtype == 'intr': mtype = INTR
+    else: assert 0
+
+    p[0] = [ prio, mtype ]
 
 def p_ParamList(p):
     """ParamList : ParamList ',' Param
                  | Param
                  | """
     if 1 == len(p):
         p[0] = [ ]
     elif 2 == len(p):
--- a/ipc/ipdl/ipdl/type.py
+++ b/ipc/ipdl/ipdl/type.py
@@ -1,18 +1,20 @@
 # vim: set ts=4 sw=4 tw=99 et:
 # 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/.
 
 import os, sys
 
 from ipdl.ast import CxxInclude, Decl, Loc, QualifiedId, State, StructDecl, TransitionStmt
-from ipdl.ast import TypeSpec, UnionDecl, UsingStmt, Visitor, ASYNC, SYNC, INTR
-from ipdl.ast import IN, OUT, INOUT, ANSWER, CALL, RECV, SEND, RPC
+from ipdl.ast import TypeSpec, UnionDecl, UsingStmt, Visitor
+from ipdl.ast import ASYNC, SYNC, INTR
+from ipdl.ast import IN, OUT, INOUT, ANSWER, CALL, RECV, SEND
+from ipdl.ast import NORMAL_PRIORITY, HIGH_PRIORITY, URGENT_PRIORITY
 import ipdl.builtin as builtin
 
 _DELETE_MSG = '__delete__'
 
 
 def _otherside(side):
     if side == 'parent':  return 'child'
     elif side == 'child': return 'parent'
@@ -199,52 +201,59 @@ class IPDLType(Type):
     def isUnion(self): return False
     def isArray(self): return False
     def isAtom(self):  return True
     def isCompound(self): return False
     def isShmem(self): return False
     def isChmod(self): return False
     def isFD(self): return False
 
-    def isAsync(self): return self.sendSemantics is ASYNC
-    def isSync(self): return self.sendSemantics is SYNC
+    def isAsync(self): return self.sendSemantics == ASYNC
+    def isSync(self): return self.sendSemantics == SYNC
     def isInterrupt(self): return self.sendSemantics is INTR
-    def isRpc(self): return self.sendSemantics is RPC
+
+    def hasReply(self):  return (self.isSync() or self.isInterrupt())
 
-    def talksAsync(self): return True
-    def talksSync(self): return self.isSync() or self.isRpc() or self.isInterrupt()
-    def talksRpc(self): return self.isRpc() or self.isInterrupt()
-    def talksInterrupt(self): return self.isInterrupt()
+    @classmethod
+    def convertsTo(cls, lesser, greater):
+        if (lesser.priorityRange[0] < greater.priorityRange[0] or
+            lesser.priorityRange[1] > greater.priorityRange[1]):
+            return False
 
-    def hasReply(self):  return (self.isSync()
-                                 or self.isInterrupt()
-                                 or self.isRpc())
+        if lesser.isAsync():
+            return True
+        elif lesser.isSync() and not greater.isAsync():
+            return True
+        elif greater.isInterrupt():
+            return True
+
+        return False
 
     def needsMoreJuiceThan(self, o):
-        return (o.isAsync() and not self.isAsync()
-                or o.isSync() and self.isRpc()
-                or o.isRpc() and self.isInterrupt())
+        return not IPDLType.convertsTo(self, o)
 
 class StateType(IPDLType):
     def __init__(self, protocol, name, start=False):
         self.protocol = protocol
         self.name = name
         self.start = start
     def isState(self): return True
     def name(self):
         return self.name
     def fullname(self):
         return self.name()
 
 class MessageType(IPDLType):
-    def __init__(self, sendSemantics, direction,
+    def __init__(self, priority, sendSemantics, direction,
                  ctor=False, dtor=False, cdtype=None, compress=False):
         assert not (ctor and dtor)
         assert not (ctor or dtor) or type is not None
 
+        self.priority = priority
+        self.priorityRange = (priority, priority)
         self.sendSemantics = sendSemantics
         self.direction = direction
         self.params = [ ]
         self.returns = [ ]
         self.ctor = ctor
         self.dtor = dtor
         self.cdtype = cdtype
         self.compress = compress
@@ -270,18 +279,19 @@ class Bridge:
     def __cmp__(self, o):
         return cmp(self.parent, o.parent) or cmp(self.child, o.child)
     def __eq__(self, o):
         return self.parent == o.parent and self.child == o.child
     def __hash__(self):
         return hash(self.parent) + hash(self.child)
 
 class ProtocolType(IPDLType):
-    def __init__(self, qname, sendSemantics, stateless=False):
+    def __init__(self, qname, priorityRange, sendSemantics, stateless=False):
         self.qname = qname
+        self.priorityRange = priorityRange
         self.sendSemantics = sendSemantics
         self.spawns = set()             # ProtocolType
         self.opens = set()              # ProtocolType
         self.managers = []           # ProtocolType
         self.manages = [ ]
         self.stateless = stateless
         self.hasDelete = False
         self.hasReentrantDelete = False
@@ -679,17 +689,17 @@ class GatherDecls(TcheckVisitor):
             # types?
             qname = p.qname()
             if 0 == len(qname.quals):
                 fullname = None
             else:
                 fullname = str(qname)
             p.decl = self.declare(
                 loc=p.loc,
-                type=ProtocolType(qname, p.sendSemantics,
+                type=ProtocolType(qname, p.priorityRange, p.sendSemantics,
                                   stateless=(0 == len(p.transitionStmts))),
                 shortname=p.name,
                 fullname=fullname)
 
             # XXX ugh, this sucks.  but we need this information to compute
             # what friend decls we need in generated C++
             p.decl.type._ast = p
 
@@ -1078,17 +1088,17 @@ class GatherDecls(TcheckVisitor):
         if _DELETE_MSG == msgname:
             isdtor = True
             cdtype = self.currentProtocolDecl.type
 
 
         # enter message scope
         self.symtab.enterScope(md)
 
-        msgtype = MessageType(md.sendSemantics, md.direction,
+        msgtype = MessageType(md.priority, md.sendSemantics, md.direction,
                               ctor=isctor, dtor=isdtor, cdtype=cdtype,
                               compress=(md.compress == 'compress'))
 
         # replace inparam Param nodes with proper Decls
         def paramToDecl(param):
             ptname = param.typespec.basename()
             ploc = param.typespec.loc
 
@@ -1452,17 +1462,32 @@ class CheckTypes(TcheckVisitor):
 
 
     def visitMessageDecl(self, md):
         mtype, mname = md.decl.type, md.decl.progname
         ptype, pname = md.protocolDecl.type, md.protocolDecl.shortname
 
         loc = md.decl.loc
 
-        if mtype.isSync() and (mtype.isOut() or mtype.isInout()):
+        if mtype.priority == HIGH_PRIORITY and not mtype.isSync():
+            self.error(
+                loc,
+                "high priority messages must be sync (here, message `%s' in protocol `%s')",
+                mname, pname)
+
+        if mtype.priority == URGENT_PRIORITY and (mtype.isOut() or mtype.isInout()):
+            self.error(
+                loc,
+                "urgent parent-to-child messages are verboten (here, message `%s' in protocol `%s')",
+                mname, pname)
+
+        # We allow high priority sync messages to be sent from the
+        # parent. Normal and urgent sync messages can only come from
+        # the child.
+        if mtype.isSync() and mtype.priority == NORMAL_PRIORITY and (mtype.isOut() or mtype.isInout()):
             self.error(
                 loc,
                 "sync parent-to-child messages are verboten (here, message `%s' in protocol `%s')",
                 mname, pname)
 
         if mtype.needsMoreJuiceThan(ptype):
             self.error(
                 loc,
--- a/ipc/ipdl/test/cxx/Makefile.in
+++ b/ipc/ipdl/test/cxx/Makefile.in
@@ -14,17 +14,17 @@ IPDLTESTHDRS = $(addprefix $(srcdir)/,$(
 TESTER_TEMPLATE := $(srcdir)/IPDLUnitTests.template.cpp
 GENTESTER := $(srcdir)/genIPDLUnitTests.py
 
 include $(topsrcdir)/config/rules.mk
 
 
 IPDLUNITTEST_BIN = $(DEPTH)/dist/bin/ipdlunittest$(BIN_SUFFIX)
 
-IPDLUnitTests.cpp : Makefile.in $(GENTESTER) $(TESTER_TEMPLATE) $(IPDLTESTHDRS)
+IPDLUnitTests.cpp : Makefile.in moz.build $(GENTESTER) $(TESTER_TEMPLATE) $(IPDLTESTHDRS)
 	$(PYTHON) $(GENTESTER) $(TESTER_TEMPLATE) -t $(IPDLTESTS) -e $(EXTRA_PROTOCOLS) > $@
 
 check-proc::
 	@$(EXIT_ON_ERROR)  \
 	for test in $(IPDLTESTS); do  \
 		 $(RUN_TEST_PROGRAM) $(IPDLUNITTEST_BIN) $$test ;  \
 	done
 
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/cxx/PTestHighestPrio.ipdl
@@ -0,0 +1,18 @@
+namespace mozilla {
+namespace _ipdltest {
+
+prio(normal upto urgent) sync protocol PTestHighestPrio
+{
+parent:
+  prio(urgent) async Msg1();
+  sync Msg2();
+  prio(urgent) async Msg3();
+  prio(urgent) sync Msg4();
+
+child:
+  async Start();
+  prio(high) sync StartInner();
+};
+
+}
+}
--- a/ipc/ipdl/test/cxx/PTestRPC.ipdl
+++ b/ipc/ipdl/test/cxx/PTestRPC.ipdl
@@ -1,27 +1,26 @@
 namespace mozilla {
 namespace _ipdltest {
 
-intr protocol PTestRPC
+prio(normal upto high) sync protocol PTestRPC
 {
 parent:
-    rpc Test1_Start() returns (uint32_t result);
-    rpc Test1_InnerEvent() returns (uint32_t result);
+    prio(high) sync Test1_Start() returns (uint32_t result);
+    prio(high) sync Test1_InnerEvent() returns (uint32_t result);
     async Test2_Start();
-    rpc Test2_OutOfOrder();
+    prio(high) sync Test2_Msg2();
+    prio(high) sync Test2_FirstUrgent();
+    prio(high) sync Test2_SecondUrgent();
     sync Test3_Start() returns (uint32_t result);
-    rpc Test3_InnerEvent() returns (uint32_t result);
-    intr Test4_Start() returns (uint32_t result);
-    rpc Test4_Inner() returns (uint32_t result);
+    prio(high) sync Test3_InnerEvent() returns (uint32_t result);
 
 child:
     async Start();
-    rpc Test1_InnerQuery() returns (uint32_t result);
-    rpc Test1_NoReenter() returns (uint32_t result);
-    rpc Test2_FirstUrgent();
-    rpc Test2_SecondUrgent();
-    rpc Test3_WakeUp() returns (uint32_t result);
-    rpc Test4_WakeUp() returns (uint32_t result);
+    prio(high) sync Test1_InnerQuery() returns (uint32_t result);
+    prio(high) sync Test1_NoReenter() returns (uint32_t result);
+    prio(high) sync Test2_Msg1();
+    prio(high) sync Test2_Msg3();
+    prio(high) sync Test3_WakeUp() returns (uint32_t result);
 };
 
 } // namespace _ipdltest
 } // namespace mozilla
--- a/ipc/ipdl/test/cxx/PTestUrgency.ipdl
+++ b/ipc/ipdl/test/cxx/PTestUrgency.ipdl
@@ -1,19 +1,19 @@
 namespace mozilla {
 namespace _ipdltest {
 
-intr protocol PTestUrgency
+prio(normal upto high) sync protocol PTestUrgency
 {
 parent:
     sync Test1() returns (uint32_t result);
     async Test2();
     sync Test3() returns (uint32_t result);
     sync FinalTest_Begin();
 
 child:
     async Start();
-    rpc Reply1() returns (uint32_t result);
-    rpc Reply2() returns (uint32_t result);
+    prio(high) sync Reply1() returns (uint32_t result);
+    prio(high) sync Reply2() returns (uint32_t result);
 };
 
 } // namespace _ipdltest
 } // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/cxx/TestHighestPrio.cpp
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: sw=4 ts=4 et :
+ */
+/* 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/. */
+
+#include "TestHighestPrio.h"
+
+#include "IPDLUnitTests.h"      // fail etc.
+#if defined(OS_POSIX)
+#include <unistd.h>
+#else
+#include <windows.h>
+#endif
+
+namespace mozilla {
+namespace _ipdltest {
+
+//-----------------------------------------------------------------------------
+// parent
+
+TestHighestPrioParent::TestHighestPrioParent()
+  : msg_num_(0)
+{
+    MOZ_COUNT_CTOR(TestHighestPrioParent);
+}
+
+TestHighestPrioParent::~TestHighestPrioParent()
+{
+    MOZ_COUNT_DTOR(TestHighestPrioParent);
+}
+
+void
+TestHighestPrioParent::Main()
+{
+    if (!SendStart())
+        fail("sending Start");
+}
+
+bool
+TestHighestPrioParent::RecvMsg1()
+{
+    MOZ_ASSERT(msg_num_ == 0);
+    msg_num_ = 1;
+    return true;
+}
+
+bool
+TestHighestPrioParent::RecvMsg2()
+{
+
+    MOZ_ASSERT(msg_num_ == 1);
+    msg_num_ = 2;
+
+    if (!SendStartInner())
+        fail("sending StartInner");
+
+    return true;
+}
+
+bool
+TestHighestPrioParent::RecvMsg3()
+{
+    MOZ_ASSERT(msg_num_ == 2);
+    msg_num_ = 3;
+    return true;
+}
+
+bool
+TestHighestPrioParent::RecvMsg4()
+{
+    MOZ_ASSERT(msg_num_ == 3);
+    msg_num_ = 4;
+    return true;
+}
+
+//-----------------------------------------------------------------------------
+// child
+
+
+TestHighestPrioChild::TestHighestPrioChild()
+{
+    MOZ_COUNT_CTOR(TestHighestPrioChild);
+}
+
+TestHighestPrioChild::~TestHighestPrioChild()
+{
+    MOZ_COUNT_DTOR(TestHighestPrioChild);
+}
+
+bool
+TestHighestPrioChild::RecvStart()
+{
+    if (!SendMsg1())
+        fail("sending Msg1");
+
+    if (!SendMsg2())
+        fail("sending Msg2");
+
+    Close();
+    return true;
+}
+
+bool
+TestHighestPrioChild::RecvStartInner()
+{
+    if (!SendMsg3())
+        fail("sending Msg3");
+
+    if (!SendMsg4())
+        fail("sending Msg4");
+
+    return true;
+}
+
+} // namespace _ipdltest
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/test/cxx/TestHighestPrio.h
@@ -0,0 +1,68 @@
+#ifndef mozilla__ipdltest_TestHighestPrio_h
+#define mozilla__ipdltest_TestHighestPrio_h 1
+
+#include "mozilla/_ipdltest/IPDLUnitTests.h"
+
+#include "mozilla/_ipdltest/PTestHighestPrioParent.h"
+#include "mozilla/_ipdltest/PTestHighestPrioChild.h"
+
+namespace mozilla {
+namespace _ipdltest {
+
+
+class TestHighestPrioParent :
+    public PTestHighestPrioParent
+{
+public:
+    TestHighestPrioParent();
+    virtual ~TestHighestPrioParent();
+
+    static bool RunTestInProcesses() { return true; }
+    static bool RunTestInThreads() { return false; }
+
+    void Main();
+
+    bool RecvMsg1() MOZ_OVERRIDE;
+    bool RecvMsg2() MOZ_OVERRIDE;
+    bool RecvMsg3() MOZ_OVERRIDE;
+    bool RecvMsg4() MOZ_OVERRIDE;
+
+    virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
+    {
+        if (NormalShutdown != why)
+            fail("unexpected destruction!");
+        if (msg_num_ != 4)
+            fail("missed IPC call");
+        passed("ok");
+        QuitParent();
+    }
+
+private:
+    int msg_num_;
+};
+
+
+class TestHighestPrioChild :
+    public PTestHighestPrioChild
+{
+public:
+    TestHighestPrioChild();
+    virtual ~TestHighestPrioChild();
+
+    bool RecvStart() MOZ_OVERRIDE;
+    bool RecvStartInner() MOZ_OVERRIDE;
+
+    virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
+    {
+        if (NormalShutdown != why)
+            fail("unexpected destruction!");
+        QuitChild();
+    }
+};
+
+
+} // namespace _ipdltest
+} // namespace mozilla
+
+
+#endif // ifndef mozilla__ipdltest_TestHighestPrio_h
--- a/ipc/ipdl/test/cxx/TestRPC.cpp
+++ b/ipc/ipdl/test/cxx/TestRPC.cpp
@@ -9,18 +9,16 @@
 
 namespace mozilla {
 namespace _ipdltest {
 
 //-----------------------------------------------------------------------------
 // parent
 
 TestRPCParent::TestRPCParent()
- : reentered_(false),
-   resolved_first_cpow_(false)
 {
   MOZ_COUNT_CTOR(TestRPCParent);
 }
 
 TestRPCParent::~TestRPCParent()
 {
   MOZ_COUNT_DTOR(TestRPCParent);
 }
@@ -28,187 +26,177 @@ TestRPCParent::~TestRPCParent()
 void
 TestRPCParent::Main()
 {
   if (!SendStart())
     fail("sending Start");
 }
 
 bool
-TestRPCParent::AnswerTest1_Start(uint32_t* aResult)
+TestRPCParent::RecvTest1_Start(uint32_t* aResult)
 {
   uint32_t result;
-  if (!CallTest1_InnerQuery(&result))
-    fail("CallTest1_InnerQuery");
+  if (!SendTest1_InnerQuery(&result))
+    fail("SendTest1_InnerQuery");
   if (result != 300)
     fail("Wrong result (expected 300)");
 
   *aResult = 100;
   return true;
 }
 
 bool
-TestRPCParent::AnswerTest1_InnerEvent(uint32_t* aResult)
+TestRPCParent::RecvTest1_InnerEvent(uint32_t* aResult)
 {
   uint32_t result;
-  if (!CallTest1_NoReenter(&result))
-    fail("CallTest1_NoReenter");
+  if (!SendTest1_NoReenter(&result))
+    fail("SendTest1_NoReenter");
   if (result != 400)
     fail("Wrong result (expected 400)");
 
   *aResult = 200;
   return true;
 }
 
 bool
 TestRPCParent::RecvTest2_Start()
 {
-  // Send a CPOW. During this time, we must NOT process the RPC message, as
-  // we could start receiving CPOW replies out-of-order.
-  if (!CallTest2_FirstUrgent())
-    fail("CallTest2_FirstUrgent");
+  if (!SendTest2_Msg1())
+    fail("SendTest2_Msg1");
 
-  MOZ_ASSERT(!reentered_);
-  resolved_first_cpow_ = true;
   return true;
 }
 
 bool
-TestRPCParent::AnswerTest2_OutOfOrder()
+TestRPCParent::RecvTest2_Msg2()
 {
-  // Send a CPOW. If this RPC call was initiated while waiting for the first
-  // CPOW to resolve, replies will be processed out of order, and we'll crash.
-  if (!CallTest2_SecondUrgent())
-    fail("CallTest2_SecondUrgent");
+  if (!SendTest2_Msg3())
+    fail("SendTest2_Msg3");
+
+  return true;
+}
 
-  reentered_ = true;
+bool
+TestRPCParent::RecvTest2_FirstUrgent()
+{
+  return true;
+}
+
+bool
+TestRPCParent::RecvTest2_SecondUrgent()
+{
   return true;
 }
 
 bool
 TestRPCParent::RecvTest3_Start(uint32_t* aResult)
 {
-  if (!CallTest3_WakeUp(aResult))
-    fail("CallTest3_WakeUp");
+  if (!SendTest3_WakeUp(aResult))
+    fail("SendTest3_WakeUp");
 
   return true;
 }
 
 bool
-TestRPCParent::AnswerTest3_InnerEvent(uint32_t* aResult)
+TestRPCParent::RecvTest3_InnerEvent(uint32_t* aResult)
 {
   *aResult = 200;
   return true;
 }
 
-bool
-TestRPCParent::AnswerTest4_Start(uint32_t* aResult)
-{
-  if (!CallTest4_WakeUp(aResult))
-    fail("CallTest4_WakeUp");
-
-  return true;
-}
-
-bool
-TestRPCParent::AnswerTest4_Inner(uint32_t* aResult)
-{
-  *aResult = 700;
-  return true;
-}
-
 //-----------------------------------------------------------------------------
 // child
 
 
 TestRPCChild::TestRPCChild()
+ : reentered_(false),
+   resolved_first_cpow_(false)
 {
     MOZ_COUNT_CTOR(TestRPCChild);
 }
 
 TestRPCChild::~TestRPCChild()
 {
     MOZ_COUNT_DTOR(TestRPCChild);
 }
 
 bool
 TestRPCChild::RecvStart()
 {
   uint32_t result;
-  if (!CallTest1_Start(&result))
-    fail("CallTest1_Start");
+  if (!SendTest1_Start(&result))
+    fail("SendTest1_Start");
   if (result != 100)
     fail("Wrong result (expected 100)");
 
   if (!SendTest2_Start())
     fail("SendTest2_Start");
 
-  if (!CallTest2_OutOfOrder())
-    fail("CallTest2_OutOfOrder");
+  if (!SendTest2_Msg2())
+    fail("SendTest2_Msg2");
 
   result = 0;
   if (!SendTest3_Start(&result))
     fail("SendTest3_Start");
   if (result != 200)
     fail("Wrong result (expected 200)");
 
-  // See bug 937216 (RPC calls within interrupts).
-  if (!CallTest4_Start(&result))
-    fail("SendTest4_Start");
-  if (result != 700)
-    fail("Wrong result (expected 700)");
-
   Close();
   return true;
 }
 
 bool
-TestRPCChild::AnswerTest1_InnerQuery(uint32_t* aResult)
+TestRPCChild::RecvTest1_InnerQuery(uint32_t* aResult)
 {
   uint32_t result;
-  if (!CallTest1_InnerEvent(&result))
-    fail("CallTest1_InnerEvent");
+  if (!SendTest1_InnerEvent(&result))
+    fail("SendTest1_InnerEvent");
   if (result != 200)
     fail("Wrong result (expected 200)");
 
   *aResult = 300;
   return true;
 }
 
 bool
-TestRPCChild::AnswerTest1_NoReenter(uint32_t* aResult)
+TestRPCChild::RecvTest1_NoReenter(uint32_t* aResult)
 {
   *aResult = 400;
   return true;
 }
 
-bool
-TestRPCChild::AnswerTest2_FirstUrgent()
+bool TestRPCChild::RecvTest2_Msg1()
 {
-  return true;
-}
+  MOZ_ASSERT(resolved_first_cpow_);
 
-bool
-TestRPCChild::AnswerTest2_SecondUrgent()
-{
+  // Send a CPOW. If this RPC call was initiated while waiting for the first
+  // CPOW to resolve, replies will be processed out of order, and we'll crash.
+  if (!SendTest2_SecondUrgent())
+    fail("SendTest2_SecondUrgent");
+
+  reentered_ = true;
   return true;
 }
 
 bool
-TestRPCChild::AnswerTest3_WakeUp(uint32_t* aResult)
+TestRPCChild::RecvTest2_Msg3()
 {
-  if (!CallTest3_InnerEvent(aResult))
-    fail("CallTest3_InnerEvent");
+  // Send a CPOW. During this time, we must NOT process the RPC message, as
+  // we could start receiving CPOW replies out-of-order.
+  if (!SendTest2_FirstUrgent())
+    fail("SendTest2_FirstUrgent");
 
+  MOZ_ASSERT(!reentered_);
+  resolved_first_cpow_ = true;
   return true;
 }
 
 bool
-TestRPCChild::AnswerTest4_WakeUp(uint32_t* aResult)
+TestRPCChild::RecvTest3_WakeUp(uint32_t* aResult)
 {
-  if (!CallTest4_Inner(aResult))
-    fail("CallTest4_Inner");
+  if (!SendTest3_InnerEvent(aResult))
+    fail("SendTest3_InnerEvent");
 
   return true;
 }
 
 } // namespace _ipdltest
 } // namespace mozilla
--- a/ipc/ipdl/test/cxx/TestRPC.h
+++ b/ipc/ipdl/test/cxx/TestRPC.h
@@ -17,64 +17,59 @@ public:
     TestRPCParent();
     virtual ~TestRPCParent();
 
     static bool RunTestInProcesses() { return true; }
     static bool RunTestInThreads() { return false; }
 
     void Main();
 
-    bool AnswerTest1_Start(uint32_t* aResult) MOZ_OVERRIDE;
-    bool AnswerTest1_InnerEvent(uint32_t* aResult) MOZ_OVERRIDE;
+    bool RecvTest1_Start(uint32_t* aResult) MOZ_OVERRIDE;
+    bool RecvTest1_InnerEvent(uint32_t* aResult) MOZ_OVERRIDE;
     bool RecvTest2_Start() MOZ_OVERRIDE;
-    bool AnswerTest2_OutOfOrder() MOZ_OVERRIDE;
+    bool RecvTest2_Msg2() MOZ_OVERRIDE;
+    bool RecvTest2_FirstUrgent() MOZ_OVERRIDE;
+    bool RecvTest2_SecondUrgent() MOZ_OVERRIDE;
     bool RecvTest3_Start(uint32_t* aResult) MOZ_OVERRIDE;
-    bool AnswerTest3_InnerEvent(uint32_t* aResult) MOZ_OVERRIDE;
-    bool AnswerTest4_Start(uint32_t* aResult) MOZ_OVERRIDE;
-    bool AnswerTest4_Inner(uint32_t* aResult) MOZ_OVERRIDE;
+    bool RecvTest3_InnerEvent(uint32_t* aResult) MOZ_OVERRIDE;
 
     virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
     {
         if (NormalShutdown != why)
             fail("unexpected destruction!");  
-        if (!reentered_)
-            fail("never processed raced RPC call!");
-        if (!resolved_first_cpow_)
-            fail("never resolved first CPOW!");
         passed("ok");
         QuitParent();
     }
-
-private:
-    bool reentered_;
-    bool resolved_first_cpow_;
 };
 
 
 class TestRPCChild :
     public PTestRPCChild
 {
 public:
     TestRPCChild();
     virtual ~TestRPCChild();
 
     bool RecvStart() MOZ_OVERRIDE;
-    bool AnswerTest1_InnerQuery(uint32_t* aResult) MOZ_OVERRIDE;
-    bool AnswerTest1_NoReenter(uint32_t* aResult) MOZ_OVERRIDE;
-    bool AnswerTest2_FirstUrgent() MOZ_OVERRIDE;
-    bool AnswerTest2_SecondUrgent() MOZ_OVERRIDE;
-    bool AnswerTest3_WakeUp(uint32_t* aResult) MOZ_OVERRIDE;
-    bool AnswerTest4_WakeUp(uint32_t* aResult) MOZ_OVERRIDE;
+    bool RecvTest1_InnerQuery(uint32_t* aResult) MOZ_OVERRIDE;
+    bool RecvTest1_NoReenter(uint32_t* aResult) MOZ_OVERRIDE;
+    bool RecvTest2_Msg1() MOZ_OVERRIDE;
+    bool RecvTest2_Msg3() MOZ_OVERRIDE;
+    bool RecvTest3_WakeUp(uint32_t* aResult) MOZ_OVERRIDE;
 
     virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
     {
         if (NormalShutdown != why)
             fail("unexpected destruction!");
         QuitChild();
     }
+
+private:
+    bool reentered_;
+    bool resolved_first_cpow_;
 };
 
 
 } // namespace _ipdltest
 } // namespace mozilla
 
 
 #endif // ifndef mozilla__ipdltest_TestRPC_h
--- a/ipc/ipdl/test/cxx/TestUrgency.cpp
+++ b/ipc/ipdl/test/cxx/TestUrgency.cpp
@@ -43,29 +43,29 @@ TestUrgencyParent::Main()
 {
   if (!SendStart())
     fail("sending Start");
 }
 
 bool
 TestUrgencyParent::RecvTest1(uint32_t *value)
 {
-  if (!CallReply1(value))
+  if (!SendReply1(value))
     fail("sending Reply1");
   if (*value != 99)
     fail("bad value");
   return true;
 }
 
 bool
 TestUrgencyParent::RecvTest2()
 {
   uint32_t value;
   inreply_ = true;
-  if (!CallReply2(&value))
+  if (!SendReply2(&value))
     fail("sending Reply2");
   inreply_ = false;
   if (value != 500)
     fail("bad value");
   return true;
 }
 
 bool
@@ -125,31 +125,31 @@ TestUrgencyChild::RecvStart()
     fail("Final test should have succeeded");
 
   Close();
 
   return true;
 }
 
 bool
-TestUrgencyChild::AnswerReply1(uint32_t *reply)
+TestUrgencyChild::RecvReply1(uint32_t *reply)
 {
   if (test_ != kFirstTestBegin)
-    fail("wrong test # in AnswerReply1");
+    fail("wrong test # in RecvReply1");
 
   *reply = 99;
   test_ = kFirstTestGotReply;
   return true;
 }
 
 bool
-TestUrgencyChild::AnswerReply2(uint32_t *reply)
+TestUrgencyChild::RecvReply2(uint32_t *reply)
 {
   if (test_ != kSecondTestBegin)
-    fail("wrong test # in AnswerReply2");
+    fail("wrong test # in RecvReply2");
 
   // sleep for 5 seconds so the parent process tries to deliver more messages.
   Sleep(5000);
 
   *reply = 500;
   test_ = kSecondTestGotReply;
   return true;
 }
--- a/ipc/ipdl/test/cxx/TestUrgency.h
+++ b/ipc/ipdl/test/cxx/TestUrgency.h
@@ -47,20 +47,18 @@ private:
 class TestUrgencyChild :
     public PTestUrgencyChild
 {
 public:
     TestUrgencyChild();
     virtual ~TestUrgencyChild();
 
     bool RecvStart();
-    bool AnswerReply1(uint32_t *reply);
-    bool AnswerReply2(uint32_t *reply);
-    bool AnswerTest4_Reenter();
-    bool AnswerFinalTest_Hang();
+    bool RecvReply1(uint32_t *reply);
+    bool RecvReply2(uint32_t *reply);
 
     virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE
     {
         QuitChild();
     }
 
 private:
     uint32_t test_;
--- a/ipc/ipdl/test/cxx/moz.build
+++ b/ipc/ipdl/test/cxx/moz.build
@@ -17,16 +17,17 @@ SOURCES += [
     'TestActorPunning.cpp',
     'TestBadActor.cpp',
     'TestBridgeMain.cpp',
     'TestCrashCleanup.cpp',
     'TestDataStructures.cpp',
     'TestDesc.cpp',
     'TestFailedCtor.cpp',
     'TestHangs.cpp',
+    'TestHighestPrio.cpp',
     'TestInterruptErrorCleanup.cpp',
     'TestInterruptRaces.cpp',
     'TestInterruptShutdownRace.cpp',
     'TestJSON.cpp',
     'TestLatency.cpp',
     'TestManyChildAllocs.cpp',
     'TestMultiMgrs.cpp',
     'TestNestedLoops.cpp',
@@ -77,16 +78,17 @@ IPDL_SOURCES += [
     'PTestDesc.ipdl',
     'PTestDescSub.ipdl',
     'PTestDescSubsub.ipdl',
     'PTestFailedCtor.ipdl',
     'PTestFailedCtorSub.ipdl',
     'PTestFailedCtorSubsub.ipdl',
     'PTestHandle.ipdl',
     'PTestHangs.ipdl',
+    'PTestHighestPrio.ipdl',
     'PTestIndirectProtocolParam.ipdlh',
     'PTestIndirectProtocolParamFirst.ipdl',
     'PTestIndirectProtocolParamManage.ipdl',
     'PTestIndirectProtocolParamSecond.ipdl',
     'PTestInterruptErrorCleanup.ipdl',
     'PTestInterruptRaces.ipdl',
     'PTestInterruptShutdownRace.ipdl',
     'PTestJSON.ipdl',
--- a/ipc/testshell/PTestShell.ipdl
+++ b/ipc/testshell/PTestShell.ipdl
@@ -4,17 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include protocol PContent;
 include protocol PTestShellCommand;
 
 namespace mozilla {
 namespace ipc {
 
-intr protocol PTestShell
+async protocol PTestShell
 {
   manager PContent;
 
   manages PTestShellCommand;
 
 child:
   __delete__();
 
--- a/js/ipc/JavaScriptBase.h
+++ b/js/ipc/JavaScriptBase.h
@@ -30,199 +30,199 @@ class JavaScriptBase : public WrapperOwn
     virtual ~JavaScriptBase() {}
 
     virtual void ActorDestroy(WrapperOwner::ActorDestroyReason why) {
         WrapperOwner::ActorDestroy(why);
     }
 
     /*** IPC handlers ***/
 
-    bool AnswerPreventExtensions(const uint64_t &objId, ReturnStatus *rs) {
-        return Answer::AnswerPreventExtensions(ObjectId::deserialize(objId), rs);
+    bool RecvPreventExtensions(const uint64_t &objId, ReturnStatus *rs) {
+        return Answer::RecvPreventExtensions(ObjectId::deserialize(objId), rs);
     }
-    bool AnswerGetPropertyDescriptor(const uint64_t &objId, const JSIDVariant &id,
+    bool RecvGetPropertyDescriptor(const uint64_t &objId, const JSIDVariant &id,
                                      ReturnStatus *rs,
                                      PPropertyDescriptor *out) {
-        return Answer::AnswerGetPropertyDescriptor(ObjectId::deserialize(objId), id, rs, out);
+        return Answer::RecvGetPropertyDescriptor(ObjectId::deserialize(objId), id, rs, out);
     }
-    bool AnswerGetOwnPropertyDescriptor(const uint64_t &objId,
+    bool RecvGetOwnPropertyDescriptor(const uint64_t &objId,
                                         const JSIDVariant &id,
                                         ReturnStatus *rs,
                                         PPropertyDescriptor *out) {
-        return Answer::AnswerGetOwnPropertyDescriptor(ObjectId::deserialize(objId), id, rs, out);
+        return Answer::RecvGetOwnPropertyDescriptor(ObjectId::deserialize(objId), id, rs, out);
     }
-    bool AnswerDefineProperty(const uint64_t &objId, const JSIDVariant &id,
+    bool RecvDefineProperty(const uint64_t &objId, const JSIDVariant &id,
                               const PPropertyDescriptor &flags,
                               ReturnStatus *rs) {
-        return Answer::AnswerDefineProperty(ObjectId::deserialize(objId), id, flags, rs);
+        return Answer::RecvDefineProperty(ObjectId::deserialize(objId), id, flags, rs);
     }
-    bool AnswerDelete(const uint64_t &objId, const JSIDVariant &id,
+    bool RecvDelete(const uint64_t &objId, const JSIDVariant &id,
                       ReturnStatus *rs, bool *success) {
-        return Answer::AnswerDelete(ObjectId::deserialize(objId), id, rs, success);
+        return Answer::RecvDelete(ObjectId::deserialize(objId), id, rs, success);
     }
 
-    bool AnswerHas(const uint64_t &objId, const JSIDVariant &id,
+    bool RecvHas(const uint64_t &objId, const JSIDVariant &id,
                    ReturnStatus *rs, bool *bp) {
-        return Answer::AnswerHas(ObjectId::deserialize(objId), id, rs, bp);
+        return Answer::RecvHas(ObjectId::deserialize(objId), id, rs, bp);
     }
-    bool AnswerHasOwn(const uint64_t &objId, const JSIDVariant &id,
+    bool RecvHasOwn(const uint64_t &objId, const JSIDVariant &id,
                       ReturnStatus *rs, bool *bp) {
-        return Answer::AnswerHasOwn(ObjectId::deserialize(objId), id, rs, bp);
+        return Answer::RecvHasOwn(ObjectId::deserialize(objId), id, rs, bp);
     }
-    bool AnswerGet(const uint64_t &objId, const ObjectVariant &receiverVar,
+    bool RecvGet(const uint64_t &objId, const ObjectVariant &receiverVar,
                    const JSIDVariant &id,
                    ReturnStatus *rs, JSVariant *result) {
-        return Answer::AnswerGet(ObjectId::deserialize(objId), receiverVar, id, rs, result);
+        return Answer::RecvGet(ObjectId::deserialize(objId), receiverVar, id, rs, result);
     }
-    bool AnswerSet(const uint64_t &objId, const ObjectVariant &receiverVar,
+    bool RecvSet(const uint64_t &objId, const ObjectVariant &receiverVar,
                    const JSIDVariant &id, const bool &strict,
                    const JSVariant &value, ReturnStatus *rs, JSVariant *result) {
-        return Answer::AnswerSet(ObjectId::deserialize(objId), receiverVar, id, strict, value, rs, result);
+        return Answer::RecvSet(ObjectId::deserialize(objId), receiverVar, id, strict, value, rs, result);
     }
 
-    bool AnswerIsExtensible(const uint64_t &objId, ReturnStatus *rs,
+    bool RecvIsExtensible(const uint64_t &objId, ReturnStatus *rs,
                             bool *result) {
-        return Answer::AnswerIsExtensible(ObjectId::deserialize(objId), rs, result);
+        return Answer::RecvIsExtensible(ObjectId::deserialize(objId), rs, result);
     }
-    bool AnswerCallOrConstruct(const uint64_t &objId, const nsTArray<JSParam> &argv,
+    bool RecvCallOrConstruct(const uint64_t &objId, const nsTArray<JSParam> &argv,
                                const bool &construct, ReturnStatus *rs, JSVariant *result,
                                nsTArray<JSParam> *outparams) {
-        return Answer::AnswerCallOrConstruct(ObjectId::deserialize(objId), argv, construct, rs, result, outparams);
+        return Answer::RecvCallOrConstruct(ObjectId::deserialize(objId), argv, construct, rs, result, outparams);
     }
-    bool AnswerHasInstance(const uint64_t &objId, const JSVariant &v, ReturnStatus *rs, bool *bp) {
-        return Answer::AnswerHasInstance(ObjectId::deserialize(objId), v, rs, bp);
+    bool RecvHasInstance(const uint64_t &objId, const JSVariant &v, ReturnStatus *rs, bool *bp) {
+        return Answer::RecvHasInstance(ObjectId::deserialize(objId), v, rs, bp);
     }
-    bool AnswerObjectClassIs(const uint64_t &objId, const uint32_t &classValue,
+    bool RecvObjectClassIs(const uint64_t &objId, const uint32_t &classValue,
                              bool *result) {
-        return Answer::AnswerObjectClassIs(ObjectId::deserialize(objId), classValue, result);
+        return Answer::RecvObjectClassIs(ObjectId::deserialize(objId), classValue, result);
     }
-    bool AnswerClassName(const uint64_t &objId, nsString *result) {
-        return Answer::AnswerClassName(ObjectId::deserialize(objId), result);
+    bool RecvClassName(const uint64_t &objId, nsString *result) {
+        return Answer::RecvClassName(ObjectId::deserialize(objId), result);
     }
-    bool AnswerRegExpToShared(const uint64_t &objId, ReturnStatus *rs, nsString *source, uint32_t *flags) {
-        return Answer::AnswerRegExpToShared(ObjectId::deserialize(objId), rs, source, flags);
+    bool RecvRegExpToShared(const uint64_t &objId, ReturnStatus *rs, nsString *source, uint32_t *flags) {
+        return Answer::RecvRegExpToShared(ObjectId::deserialize(objId), rs, source, flags);
     }
 
-    bool AnswerGetPropertyNames(const uint64_t &objId, const uint32_t &flags,
+    bool RecvGetPropertyNames(const uint64_t &objId, const uint32_t &flags,
                                 ReturnStatus *rs, nsTArray<nsString> *names) {
-        return Answer::AnswerGetPropertyNames(ObjectId::deserialize(objId), flags, rs, names);
+        return Answer::RecvGetPropertyNames(ObjectId::deserialize(objId), flags, rs, names);
     }
-    bool AnswerInstanceOf(const uint64_t &objId, const JSIID &iid,
+    bool RecvInstanceOf(const uint64_t &objId, const JSIID &iid,
                           ReturnStatus *rs, bool *instanceof) {
-        return Answer::AnswerInstanceOf(ObjectId::deserialize(objId), iid, rs, instanceof);
+        return Answer::RecvInstanceOf(ObjectId::deserialize(objId), iid, rs, instanceof);
     }
-    bool AnswerDOMInstanceOf(const uint64_t &objId, const int &prototypeID, const int &depth,
+    bool RecvDOMInstanceOf(const uint64_t &objId, const int &prototypeID, const int &depth,
                              ReturnStatus *rs, bool *instanceof) {
-        return Answer::AnswerDOMInstanceOf(ObjectId::deserialize(objId), prototypeID, depth, rs, instanceof);
+        return Answer::RecvDOMInstanceOf(ObjectId::deserialize(objId), prototypeID, depth, rs, instanceof);
     }
 
-    bool AnswerIsCallable(const uint64_t &objId, bool *result) {
-        return Answer::AnswerIsCallable(ObjectId::deserialize(objId), result);
+    bool RecvIsCallable(const uint64_t &objId, bool *result) {
+        return Answer::RecvIsCallable(ObjectId::deserialize(objId), result);
     }
 
-    bool AnswerIsConstructor(const uint64_t &objId, bool *result) {
-        return Answer::AnswerIsConstructor(ObjectId::deserialize(objId), result);
+    bool RecvIsConstructor(const uint64_t &objId, bool *result) {
+        return Answer::RecvIsConstructor(ObjectId::deserialize(objId), result);
     }
 
     bool RecvDropObject(const uint64_t &objId) {
         return Answer::RecvDropObject(ObjectId::deserialize(objId));
     }
 
     /*** Dummy call handlers ***/
 
     bool SendDropObject(const ObjectId &objId) {
         return Base::SendDropObject(objId.serialize());
     }
-    bool CallPreventExtensions(const ObjectId &objId, ReturnStatus *rs) {
-        return Base::CallPreventExtensions(objId.serialize(), rs);
+    bool SendPreventExtensions(const ObjectId &objId, ReturnStatus *rs) {
+        return Base::SendPreventExtensions(objId.serialize(), rs);
     }
-    bool CallGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id,
+    bool SendGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id,
                                      ReturnStatus *rs,
                                      PPropertyDescriptor *out) {
-        return Base::CallGetPropertyDescriptor(objId.serialize(), id, rs, out);
+        return Base::SendGetPropertyDescriptor(objId.serialize(), id, rs, out);
     }
-    bool CallGetOwnPropertyDescriptor(const ObjectId &objId,
+    bool SendGetOwnPropertyDescriptor(const ObjectId &objId,
                                       const JSIDVariant &id,
                                       ReturnStatus *rs,
                                       PPropertyDescriptor *out) {
-        return Base::CallGetOwnPropertyDescriptor(objId.serialize(), id, rs, out);
+        return Base::SendGetOwnPropertyDescriptor(objId.serialize(), id, rs, out);
     }
-    bool CallDefineProperty(const ObjectId &objId, const JSIDVariant &id,
+    bool SendDefineProperty(const ObjectId &objId, const JSIDVariant &id,
                             const PPropertyDescriptor &flags,
                               ReturnStatus *rs) {
-        return Base::CallDefineProperty(objId.serialize(), id, flags, rs);
+        return Base::SendDefineProperty(objId.serialize(), id, flags, rs);
     }
-    bool CallDelete(const ObjectId &objId, const JSIDVariant &id,
+    bool SendDelete(const ObjectId &objId, const JSIDVariant &id,
                     ReturnStatus *rs, bool *success) {
-        return Base::CallDelete(objId.serialize(), id, rs, success);
+        return Base::SendDelete(objId.serialize(), id, rs, success);
     }
 
-    bool CallHas(const ObjectId &objId, const JSIDVariant &id,
+    bool SendHas(const ObjectId &objId, const JSIDVariant &id,
                    ReturnStatus *rs, bool *bp) {
-        return Base::CallHas(objId.serialize(), id, rs, bp);
+        return Base::SendHas(objId.serialize(), id, rs, bp);
     }
-    bool CallHasOwn(const ObjectId &objId, const JSIDVariant &id,
+    bool SendHasOwn(const ObjectId &objId, const JSIDVariant &id,
                     ReturnStatus *rs, bool *bp) {
-        return Base::CallHasOwn(objId.serialize(), id, rs, bp);
+        return Base::SendHasOwn(objId.serialize(), id, rs, bp);
     }
-    bool CallGet(const ObjectId &objId, const ObjectVariant &receiverVar,
+    bool SendGet(const ObjectId &objId, const ObjectVariant &receiverVar,
                  const JSIDVariant &id,
                  ReturnStatus *rs, JSVariant *result) {
-        return Base::CallGet(objId.serialize(), receiverVar, id, rs, result);
+        return Base::SendGet(objId.serialize(), receiverVar, id, rs, result);
     }
-    bool CallSet(const ObjectId &objId, const ObjectVariant &receiverVar,
+    bool SendSet(const ObjectId &objId, const ObjectVariant &receiverVar,
                  const JSIDVariant &id, const bool &strict,
                  const JSVariant &value, ReturnStatus *rs, JSVariant *result) {
-        return Base::CallSet(objId.serialize(), receiverVar, id, strict, value, rs, result);
+        return Base::SendSet(objId.serialize(), receiverVar, id, strict, value, rs, result);
     }
 
-    bool CallIsExtensible(const ObjectId &objId, ReturnStatus *rs,
+    bool SendIsExtensible(const ObjectId &objId, ReturnStatus *rs,
                           bool *result) {
-        return Base::CallIsExtensible(objId.serialize(), rs, result);
+        return Base::SendIsExtensible(objId.serialize(), rs, result);
     }
-    bool CallCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
+    bool SendCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
                              const bool &construct, ReturnStatus *rs, JSVariant *result,
                              nsTArray<JSParam> *outparams) {
-        return Base::CallCallOrConstruct(objId.serialize(), argv, construct, rs, result, outparams);
+        return Base::SendCallOrConstruct(objId.serialize(), argv, construct, rs, result, outparams);
     }
-    bool CallHasInstance(const ObjectId &objId, const JSVariant &v, ReturnStatus *rs, bool *bp) {
-        return Base::CallHasInstance(objId.serialize(), v, rs, bp);
+    bool SendHasInstance(const ObjectId &objId, const JSVariant &v, ReturnStatus *rs, bool *bp) {
+        return Base::SendHasInstance(objId.serialize(), v, rs, bp);
     }
-    bool CallObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
+    bool SendObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
                            bool *result) {
-        return Base::CallObjectClassIs(objId.serialize(), classValue, result);
+        return Base::SendObjectClassIs(objId.serialize(), classValue, result);
     }
-    bool CallClassName(const ObjectId &objId, nsString *result) {
-        return Base::CallClassName(objId.serialize(), result);
+    bool SendClassName(const ObjectId &objId, nsString *result) {
+        return Base::SendClassName(objId.serialize(), result);
     }
 
-    bool CallRegExpToShared(const ObjectId &objId, ReturnStatus *rs,
+    bool SendRegExpToShared(const ObjectId &objId, ReturnStatus *rs,
                             nsString *source, uint32_t *flags) {
-        return Base::CallRegExpToShared(objId.serialize(), rs, source, flags);
+        return Base::SendRegExpToShared(objId.serialize(), rs, source, flags);
     }
 
-    bool CallGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
+    bool SendGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
                               ReturnStatus *rs, nsTArray<nsString> *names) {
-        return Base::CallGetPropertyNames(objId.serialize(), flags, rs, names);
+        return Base::SendGetPropertyNames(objId.serialize(), flags, rs, names);
     }
-    bool CallInstanceOf(const ObjectId &objId, const JSIID &iid,
+    bool SendInstanceOf(const ObjectId &objId, const JSIID &iid,
                         ReturnStatus *rs, bool *instanceof) {
-        return Base::CallInstanceOf(objId.serialize(), iid, rs, instanceof);
+        return Base::SendInstanceOf(objId.serialize(), iid, rs, instanceof);
     }
-    bool CallDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
+    bool SendDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
                            ReturnStatus *rs, bool *instanceof) {
-        return Base::CallDOMInstanceOf(objId.serialize(), prototypeID, depth, rs, instanceof);
+        return Base::SendDOMInstanceOf(objId.serialize(), prototypeID, depth, rs, instanceof);
     }
 
-    bool CallIsCallable(const ObjectId &objId, bool *result) {
-        return Base::CallIsCallable(objId.serialize(), result);
+    bool SendIsCallable(const ObjectId &objId, bool *result) {
+        return Base::SendIsCallable(objId.serialize(), result);
     }
 
-    bool CallIsConstructor(const ObjectId &objId, bool *result) {
-        return Base::CallIsConstructor(objId.serialize(), result);
+    bool SendIsConstructor(const ObjectId &objId, bool *result) {
+        return Base::SendIsConstructor(objId.serialize(), result);
     }
 
     /* The following code is needed to suppress a bogus MSVC warning (C4250). */
 
     virtual bool toObjectVariant(JSContext *cx, JSObject *obj, ObjectVariant *objVarp) {
         return WrapperOwner::toObjectVariant(cx, obj, objVarp);
     }
     virtual JSObject *fromObjectVariant(JSContext *cx, ObjectVariant objVar) {
--- a/js/ipc/PJavaScript.ipdl
+++ b/js/ipc/PJavaScript.ipdl
@@ -10,48 +10,48 @@ include protocol PContentBridge;
 include DOMTypes;
 include JavaScriptTypes;
 
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 
 namespace mozilla {
 namespace jsipc {
 
-intr protocol PJavaScript
+prio(normal upto high) sync protocol PJavaScript
 {
     manager PContent or PContentBridge;
 
 both:
     // Sent when a CPOW has been finalized and table entries can be freed up.
     async DropObject(uint64_t objId);
 
     // These roughly map to the ProxyHandler hooks that CPOWs need.
-    rpc PreventExtensions(uint64_t objId) returns (ReturnStatus rs);
-    rpc GetPropertyDescriptor(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, PPropertyDescriptor result);
-    rpc GetOwnPropertyDescriptor(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, PPropertyDescriptor result);
-    rpc DefineProperty(uint64_t objId, JSIDVariant id, PPropertyDescriptor descriptor) returns (ReturnStatus rs);
-    rpc Delete(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool successful);
+    prio(high) sync PreventExtensions(uint64_t objId) returns (ReturnStatus rs);
+    prio(high) sync GetPropertyDescriptor(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, PPropertyDescriptor result);
+    prio(high) sync GetOwnPropertyDescriptor(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, PPropertyDescriptor result);
+    prio(high) sync DefineProperty(uint64_t objId, JSIDVariant id, PPropertyDescriptor descriptor) returns (ReturnStatus rs);
+    prio(high) sync Delete(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool successful);
 
-    rpc Has(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
-    rpc HasOwn(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
-    rpc Get(uint64_t objId, ObjectVariant receiver, JSIDVariant id) returns (ReturnStatus rs, JSVariant result);
-    rpc Set(uint64_t objId, ObjectVariant receiver, JSIDVariant id, bool strict, JSVariant value) returns (ReturnStatus rs, JSVariant result);
+    prio(high) sync Has(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
+    prio(high) sync HasOwn(uint64_t objId, JSIDVariant id) returns (ReturnStatus rs, bool has);
+    prio(high) sync Get(uint64_t objId, ObjectVariant receiver, JSIDVariant id) returns (ReturnStatus rs, JSVariant result);
+    prio(high) sync Set(uint64_t objId, ObjectVariant receiver, JSIDVariant id, bool strict, JSVariant value) returns (ReturnStatus rs, JSVariant result);
 
-    rpc IsExtensible(uint64_t objId) returns (ReturnStatus rs, bool result);
-    rpc CallOrConstruct(uint64_t objId, JSParam[] argv, bool construct) returns (ReturnStatus rs, JSVariant result, JSParam[] outparams);
-    rpc HasInstance(uint64_t objId, JSVariant v) returns (ReturnStatus rs, bool has);
-    rpc ObjectClassIs(uint64_t objId, uint32_t classValue) returns (bool result);
-    rpc ClassName(uint64_t objId) returns (nsString name);
-    rpc RegExpToShared(uint64_t objId) returns (ReturnStatus rs, nsString source, uint32_t flags);
+    prio(high) sync IsExtensible(uint64_t objId) returns (ReturnStatus rs, bool result);
+    prio(high) sync CallOrConstruct(uint64_t objId, JSParam[] argv, bool construct) returns (ReturnStatus rs, JSVariant result, JSParam[] outparams);
+    prio(high) sync HasInstance(uint64_t objId, JSVariant v) returns (ReturnStatus rs, bool has);
+    prio(high) sync ObjectClassIs(uint64_t objId, uint32_t classValue) returns (bool result);
+    prio(high) sync ClassName(uint64_t objId) returns (nsString name);
+    prio(high) sync RegExpToShared(uint64_t objId) returns (ReturnStatus rs, nsString source, uint32_t flags);
 
-    rpc GetPropertyNames(uint64_t objId, uint32_t flags) returns (ReturnStatus rs, nsString[] names);
-    rpc InstanceOf(uint64_t objId, JSIID iid) returns (ReturnStatus rs, bool instanceof);
-    rpc DOMInstanceOf(uint64_t objId, int prototypeID, int depth) returns (ReturnStatus rs, bool instanceof);
+    prio(high) sync GetPropertyNames(uint64_t objId, uint32_t flags) returns (ReturnStatus rs, nsString[] names);
+    prio(high) sync InstanceOf(uint64_t objId, JSIID iid) returns (ReturnStatus rs, bool instanceof);
+    prio(high) sync DOMInstanceOf(uint64_t objId, int prototypeID, int depth) returns (ReturnStatus rs, bool instanceof);
 
-    rpc IsCallable(uint64_t objId) returns (bool result);
-    rpc IsConstructor(uint64_t objId) returns (bool result);
+    prio(high) sync IsCallable(uint64_t objId) returns (bool result);
+    prio(high) sync IsConstructor(uint64_t objId) returns (bool result);
 
 parent:
     async __delete__();
 };
 
 }
 }
--- a/js/ipc/WrapperAnswer.cpp
+++ b/js/ipc/WrapperAnswer.cpp
@@ -53,17 +53,17 @@ WrapperAnswer::fail(JSContext *cx, Retur
 bool
 WrapperAnswer::ok(ReturnStatus *rs)
 {
     *rs = ReturnStatus(ReturnSuccess());
     return true;
 }
 
 bool
-WrapperAnswer::AnswerPreventExtensions(const ObjectId &objId, ReturnStatus *rs)
+WrapperAnswer::RecvPreventExtensions(const ObjectId &objId, ReturnStatus *rs)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
         return fail(cx, rs);
 
@@ -82,18 +82,18 @@ EmptyDesc(PPropertyDescriptor *desc)
     desc->obj() = LocalObject(0);
     desc->attrs() = 0;
     desc->value() = UndefinedVariant();
     desc->getter() = 0;
     desc->setter() = 0;
 }
 
 bool
-WrapperAnswer::AnswerGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &idVar,
-                                           ReturnStatus *rs, PPropertyDescriptor *out)
+WrapperAnswer::RecvGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &idVar,
+                                         ReturnStatus *rs, PPropertyDescriptor *out)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     EmptyDesc(out);
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
@@ -116,18 +116,18 @@ WrapperAnswer::AnswerGetPropertyDescript
 
     if (!fromDescriptor(cx, desc, out))
         return fail(cx, rs);
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerGetOwnPropertyDescriptor(const ObjectId &objId, const JSIDVariant &idVar,
-                                              ReturnStatus *rs, PPropertyDescriptor *out)
+WrapperAnswer::RecvGetOwnPropertyDescriptor(const ObjectId &objId, const JSIDVariant &idVar,
+                                            ReturnStatus *rs, PPropertyDescriptor *out)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     EmptyDesc(out);
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
@@ -150,18 +150,18 @@ WrapperAnswer::AnswerGetOwnPropertyDescr
 
     if (!fromDescriptor(cx, desc, out))
         return fail(cx, rs);
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerDefineProperty(const ObjectId &objId, const JSIDVariant &idVar,
-                                    const PPropertyDescriptor &descriptor, ReturnStatus *rs)
+WrapperAnswer::RecvDefineProperty(const ObjectId &objId, const JSIDVariant &idVar,
+                                  const PPropertyDescriptor &descriptor, ReturnStatus *rs)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
         return fail(cx, rs);
 
@@ -188,18 +188,18 @@ WrapperAnswer::AnswerDefineProperty(cons
     {
         return fail(cx, rs);
     }
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerDelete(const ObjectId &objId, const JSIDVariant &idVar, ReturnStatus *rs,
-                            bool *success)
+WrapperAnswer::RecvDelete(const ObjectId &objId, const JSIDVariant &idVar, ReturnStatus *rs,
+                          bool *success)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     *success = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
@@ -215,17 +215,17 @@ WrapperAnswer::AnswerDelete(const Object
 
     if (!JS_DeletePropertyById2(cx, obj, id, success))
         return fail(cx, rs);
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerHas(const ObjectId &objId, const JSIDVariant &idVar, ReturnStatus *rs, bool *bp)
+WrapperAnswer::RecvHas(const ObjectId &objId, const JSIDVariant &idVar, ReturnStatus *rs, bool *bp)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     *bp = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
@@ -243,18 +243,18 @@ WrapperAnswer::AnswerHas(const ObjectId 
     if (!JS_HasPropertyById(cx, obj, id, &found))
         return fail(cx, rs);
     *bp = !!found;
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerHasOwn(const ObjectId &objId, const JSIDVariant &idVar, ReturnStatus *rs,
-                            bool *bp)
+WrapperAnswer::RecvHasOwn(const ObjectId &objId, const JSIDVariant &idVar, ReturnStatus *rs,
+                          bool *bp)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     *bp = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
@@ -272,18 +272,18 @@ WrapperAnswer::AnswerHasOwn(const Object
     if (!JS_GetPropertyDescriptorById(cx, obj, id, &desc))
         return fail(cx, rs);
     *bp = (desc.object() == obj);
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerGet(const ObjectId &objId, const ObjectVariant &receiverVar,
-                         const JSIDVariant &idVar, ReturnStatus *rs, JSVariant *result)
+WrapperAnswer::RecvGet(const ObjectId &objId, const ObjectVariant &receiverVar,
+                       const JSIDVariant &idVar, ReturnStatus *rs, JSVariant *result)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     // The outparam will be written to the buffer, so it must be set even if
     // the parent won't read it.
     *result = UndefinedVariant();
 
@@ -309,19 +309,19 @@ WrapperAnswer::AnswerGet(const ObjectId 
         return fail(cx, rs);
 
     LOG("get %s.%s = %s", ReceiverObj(objId), Identifier(idVar), OutVariant(*result));
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerSet(const ObjectId &objId, const ObjectVariant &receiverVar,
-                         const JSIDVariant &idVar, const bool &strict, const JSVariant &value,
-                         ReturnStatus *rs, JSVariant *result)
+WrapperAnswer::RecvSet(const ObjectId &objId, const ObjectVariant &receiverVar,
+                       const JSIDVariant &idVar, const bool &strict, const JSVariant &value,
+                       ReturnStatus *rs, JSVariant *result)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     // The outparam will be written to the buffer, so it must be set even if
     // the parent won't read it.
     *result = UndefinedVariant();
 
@@ -352,17 +352,17 @@ WrapperAnswer::AnswerSet(const ObjectId 
 
     if (!toVariant(cx, val, result))
         return fail(cx, rs);
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerIsExtensible(const ObjectId &objId, ReturnStatus *rs, bool *result)
+WrapperAnswer::RecvIsExtensible(const ObjectId &objId, ReturnStatus *rs, bool *result)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     *result = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
@@ -376,22 +376,22 @@ WrapperAnswer::AnswerIsExtensible(const 
     if (!JS_IsExtensible(cx, obj, &extensible))
         return fail(cx, rs);
 
     *result = !!extensible;
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerCallOrConstruct(const ObjectId &objId,
-                                     const nsTArray<JSParam> &argv,
-                                     const bool &construct,
-                                     ReturnStatus *rs,
-                                     JSVariant *result,
-                                     nsTArray<JSParam> *outparams)
+WrapperAnswer::RecvCallOrConstruct(const ObjectId &objId,
+                                   const nsTArray<JSParam> &argv,
+                                   const bool &construct,
+                                   ReturnStatus *rs,
+                                   JSVariant *result,
+                                   nsTArray<JSParam> *outparams)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     // The outparam will be written to the buffer, so it must be set even if
     // the parent won't read it.
     *result = UndefinedVariant();
 
@@ -483,17 +483,17 @@ WrapperAnswer::AnswerCallOrConstruct(con
     }
 
     LOG("%s.call(%s) = %s", ReceiverObj(objId), argv, OutVariant(*result));
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerHasInstance(const ObjectId &objId, const JSVariant &vVar, ReturnStatus *rs, bool *bp)
+WrapperAnswer::RecvHasInstance(const ObjectId &objId, const JSVariant &vVar, ReturnStatus *rs, bool *bp)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
         return fail(cx, rs);
 
@@ -507,18 +507,18 @@ WrapperAnswer::AnswerHasInstance(const O
 
     if (!JS_HasInstance(cx, obj, val, bp))
         return fail(cx, rs);
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
-                                   bool *result)
+WrapperAnswer::RecvObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
+                                 bool *result)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj) {
         // This is very unfortunate, but we have no choice.
         *result = false;
@@ -529,17 +529,17 @@ WrapperAnswer::AnswerObjectClassIs(const
 
     LOG("%s.objectClassIs()", ReceiverObj(objId));
 
     *result = js_ObjectClassIs(cx, obj, (js::ESClassValue)classValue);
     return true;
 }
 
 bool
-WrapperAnswer::AnswerClassName(const ObjectId &objId, nsString *name)
+WrapperAnswer::RecvClassName(const ObjectId &objId, nsString *name)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj) {
         // This is very unfortunate, but we have no choice.
         return "<dead CPOW>";
@@ -549,18 +549,18 @@ WrapperAnswer::AnswerClassName(const Obj
 
     LOG("%s.className()", ReceiverObj(objId));
 
     *name = NS_ConvertASCIItoUTF16(js_ObjectClassName(cx, obj));
     return true;
 }
 
 bool
-WrapperAnswer::AnswerRegExpToShared(const ObjectId &objId, ReturnStatus *rs,
-                                    nsString *source, uint32_t *flags)
+WrapperAnswer::RecvRegExpToShared(const ObjectId &objId, ReturnStatus *rs,
+                                  nsString *source, uint32_t *flags)
 {
     AutoSafeJSContext cx;
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
         return fail(cx, rs);
 
     JSAutoCompartment ac(cx, obj);
     MOZ_RELEASE_ASSERT(JS_ObjectIsRegExp(cx, obj));
@@ -574,18 +574,18 @@ WrapperAnswer::AnswerRegExpToShared(cons
     source->Assign(sourceStr);
 
     *flags = JS_GetRegExpFlags(cx, obj);
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
-                                      ReturnStatus *rs, nsTArray<nsString> *names)
+WrapperAnswer::RecvGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
+                                    ReturnStatus *rs, nsTArray<nsString> *names)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
         return fail(cx, rs);
 
@@ -604,18 +604,18 @@ WrapperAnswer::AnswerGetPropertyNames(co
 
         names->AppendElement(name);
     }
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerInstanceOf(const ObjectId &objId, const JSIID &iid, ReturnStatus *rs,
-                                bool *instanceof)
+WrapperAnswer::RecvInstanceOf(const ObjectId &objId, const JSIID &iid, ReturnStatus *rs,
+                              bool *instanceof)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     *instanceof = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
@@ -631,18 +631,18 @@ WrapperAnswer::AnswerInstanceOf(const Ob
     nsresult rv = xpc::HasInstance(cx, obj, &nsiid, instanceof);
     if (rv != NS_OK)
         return fail(cx, rs);
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerDOMInstanceOf(const ObjectId &objId, const int &prototypeID,
-                                   const int &depth, ReturnStatus *rs, bool *instanceof)
+WrapperAnswer::RecvDOMInstanceOf(const ObjectId &objId, const int &prototypeID,
+                                 const int &depth, ReturnStatus *rs, bool *instanceof)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     *instanceof = false;
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj)
@@ -656,17 +656,17 @@ WrapperAnswer::AnswerDOMInstanceOf(const
     if (!mozilla::dom::InterfaceHasInstance(cx, prototypeID, depth, obj, &tmp))
         return fail(cx, rs);
     *instanceof = tmp;
 
     return ok(rs);
 }
 
 bool
-WrapperAnswer::AnswerIsCallable(const ObjectId &objId, bool *result)
+WrapperAnswer::RecvIsCallable(const ObjectId &objId, bool *result)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj) {
         // This is very unfortunate, but we have no choice.
         *result = false;
@@ -676,17 +676,17 @@ WrapperAnswer::AnswerIsCallable(const Ob
 
     LOG("%s.isCallable()", ReceiverObj(objId));
 
     *result = JS::IsCallable(obj);
     return true;
 }
 
 bool
-WrapperAnswer::AnswerIsConstructor(const ObjectId &objId, bool *result)
+WrapperAnswer::RecvIsConstructor(const ObjectId &objId, bool *result)
 {
     AutoSafeJSContext cx;
     JSAutoRequest request(cx);
 
     RootedObject obj(cx, findObjectById(cx, objId));
     if (!obj) {
         // This is very unfortunate, but we have no choice.
         *result = false;
--- a/js/ipc/WrapperAnswer.h
+++ b/js/ipc/WrapperAnswer.h
@@ -13,61 +13,61 @@
 namespace mozilla {
 namespace jsipc {
 
 class WrapperAnswer : public virtual JavaScriptShared
 {
   public:
     explicit WrapperAnswer(JSRuntime *rt) : JavaScriptShared(rt) {}
 
-    bool AnswerPreventExtensions(const ObjectId &objId, ReturnStatus *rs);
-    bool AnswerGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id,
-                                     ReturnStatus *rs,
-                                     PPropertyDescriptor *out);
-    bool AnswerGetOwnPropertyDescriptor(const ObjectId &objId,
-                                        const JSIDVariant &id,
-                                        ReturnStatus *rs,
-                                        PPropertyDescriptor *out);
-    bool AnswerDefineProperty(const ObjectId &objId, const JSIDVariant &id,
-                              const PPropertyDescriptor &flags,
-                              ReturnStatus *rs);
-    bool AnswerDelete(const ObjectId &objId, const JSIDVariant &id,
-                      ReturnStatus *rs, bool *success);
+    bool RecvPreventExtensions(const ObjectId &objId, ReturnStatus *rs);
+    bool RecvGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id,
+                                   ReturnStatus *rs,
+                                   PPropertyDescriptor *out);
+    bool RecvGetOwnPropertyDescriptor(const ObjectId &objId,
+                                      const JSIDVariant &id,
+                                      ReturnStatus *rs,
+                                      PPropertyDescriptor *out);
+    bool RecvDefineProperty(const ObjectId &objId, const JSIDVariant &id,
+                            const PPropertyDescriptor &flags,
+                            ReturnStatus *rs);
+    bool RecvDelete(const ObjectId &objId, const JSIDVariant &id,
+                    ReturnStatus *rs, bool *success);
 
-    bool AnswerHas(const ObjectId &objId, const JSIDVariant &id,
-                       ReturnStatus *rs, bool *bp);
-    bool AnswerHasOwn(const ObjectId &objId, const JSIDVariant &id,
-                          ReturnStatus *rs, bool *bp);
-    bool AnswerGet(const ObjectId &objId, const ObjectVariant &receiverVar,
-                       const JSIDVariant &id,
-                       ReturnStatus *rs, JSVariant *result);
-    bool AnswerSet(const ObjectId &objId, const ObjectVariant &receiverVar,
-                   const JSIDVariant &id, const bool &strict,
-                   const JSVariant &value, ReturnStatus *rs, JSVariant *result);
+    bool RecvHas(const ObjectId &objId, const JSIDVariant &id,
+                 ReturnStatus *rs, bool *bp);
+    bool RecvHasOwn(const ObjectId &objId, const JSIDVariant &id,
+                    ReturnStatus *rs, bool *bp);
+    bool RecvGet(const ObjectId &objId, const ObjectVariant &receiverVar,
+                 const JSIDVariant &id,
+                 ReturnStatus *rs, JSVariant *result);
+    bool RecvSet(const ObjectId &objId, const ObjectVariant &receiverVar,
+                 const JSIDVariant &id, const bool &strict,
+                 const JSVariant &value, ReturnStatus *rs, JSVariant *result);
 
-    bool AnswerIsExtensible(const ObjectId &objId, ReturnStatus *rs,
-                            bool *result);
-    bool AnswerCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
-                               const bool &construct, ReturnStatus *rs, JSVariant *result,
-                               nsTArray<JSParam> *outparams);
-    bool AnswerHasInstance(const ObjectId &objId, const JSVariant &v, ReturnStatus *rs, bool *bp);
-    bool AnswerObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
-                             bool *result);
-    bool AnswerClassName(const ObjectId &objId, nsString *result);
-    bool AnswerRegExpToShared(const ObjectId &objId, ReturnStatus *rs, nsString *source, uint32_t *flags);
+    bool RecvIsExtensible(const ObjectId &objId, ReturnStatus *rs,
+                          bool *result);
+    bool RecvCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
+                             const bool &construct, ReturnStatus *rs, JSVariant *result,
+                             nsTArray<JSParam> *outparams);
+    bool RecvHasInstance(const ObjectId &objId, const JSVariant &v, ReturnStatus *rs, bool *bp);
+    bool RecvObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
+                           bool *result);
+    bool RecvClassName(const ObjectId &objId, nsString *result);
+    bool RecvRegExpToShared(const ObjectId &objId, ReturnStatus *rs, nsString *source, uint32_t *flags);
 
-    bool AnswerGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
-                                ReturnStatus *rs, nsTArray<nsString> *names);
-    bool AnswerInstanceOf(const ObjectId &objId, const JSIID &iid,
-                          ReturnStatus *rs, bool *instanceof);
-    bool AnswerDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
-                             ReturnStatus *rs, bool *instanceof);
+    bool RecvGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
+                              ReturnStatus *rs, nsTArray<nsString> *names);
+    bool RecvInstanceOf(const ObjectId &objId, const JSIID &iid,
+                        ReturnStatus *rs, bool *instanceof);
+    bool RecvDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
+                           ReturnStatus *rs, bool *instanceof);
 
-    bool AnswerIsCallable(const ObjectId &objId, bool *result);
-    bool AnswerIsConstructor(const ObjectId &objId, bool *result);
+    bool RecvIsCallable(const ObjectId &objId, bool *result);
+    bool RecvIsConstructor(const ObjectId &objId, bool *result);
 
     bool RecvDropObject(const ObjectId &objId);
 
   private:
     bool fail(JSContext *cx, ReturnStatus *rs);
     bool ok(ReturnStatus *rs);
 };
 
--- a/js/ipc/WrapperOwner.cpp
+++ b/js/ipc/WrapperOwner.cpp
@@ -119,17 +119,17 @@ CPOWProxyHandler::preventExtensions(JSCo
 }
 
 bool
 WrapperOwner::preventExtensions(JSContext *cx, HandleObject proxy)
 {
     ObjectId objId = idOf(proxy);
 
     ReturnStatus status;
-    if (!CallPreventExtensions(objId, &status))
+    if (!SendPreventExtensions(objId, &status))
         return ipcfail(cx);
 
     LOG_STACK();
 
     return ok(cx, status);
 }
 
 bool
@@ -146,17 +146,17 @@ WrapperOwner::getPropertyDescriptor(JSCo
     ObjectId objId = idOf(proxy);
 
     JSIDVariant idVar;
     if (!toJSIDVariant(cx, id, &idVar))
         return false;
 
     ReturnStatus status;
     PPropertyDescriptor result;
-    if (!CallGetPropertyDescriptor(objId, idVar, &status, &result))
+    if (!SendGetPropertyDescriptor(objId, idVar, &status, &result))
         return ipcfail(cx);
 
     LOG_STACK();
 
     if (!ok(cx, status))
         return false;
 
     return toDescriptor(cx, result, desc);
@@ -176,17 +176,17 @@ WrapperOwner::getOwnPropertyDescriptor(J
     ObjectId objId = idOf(proxy);
 
     JSIDVariant idVar;
     if (!toJSIDVariant(cx, id, &idVar))
         return false;
 
     ReturnStatus status;
     PPropertyDescriptor result;
-    if (!CallGetOwnPropertyDescriptor(objId, idVar, &status, &result))
+    if (!SendGetOwnPropertyDescriptor(objId, idVar, &status, &result))
         return ipcfail(cx);
 
     LOG_STACK();
 
     if (!ok(cx, status))
         return false;
 
     return toDescriptor(cx, result, desc);
@@ -209,17 +209,17 @@ WrapperOwner::defineProperty(JSContext *
     if (!toJSIDVariant(cx, id, &idVar))
         return false;
 
     PPropertyDescriptor descriptor;
     if (!fromDescriptor(cx, desc, &descriptor))
         return false;
 
     ReturnStatus status;
-    if (!CallDefineProperty(objId, idVar, descriptor, &status))
+    if (!SendDefineProperty(objId, idVar, descriptor, &status))
         return ipcfail(cx);
 
     LOG_STACK();
 
     return ok(cx, status);
 }
 
 bool
@@ -246,17 +246,17 @@ WrapperOwner::delete_(JSContext *cx, Han
 {
     ObjectId objId = idOf(proxy);
 
     JSIDVariant idVar;
     if (!toJSIDVariant(cx, id, &idVar))
         return false;
 
     ReturnStatus status;
-    if (!CallDelete(objId, idVar, &status, bp))
+    if (!SendDelete(objId, idVar, &status, bp))
         return ipcfail(cx);
 
     LOG_STACK();
 
     return ok(cx, status);
 }
 
 bool
@@ -282,17 +282,17 @@ WrapperOwner::has(JSContext *cx, HandleO
 {
     ObjectId objId = idOf(proxy);
 
     JSIDVariant idVar;
     if (!toJSIDVariant(cx, id, &idVar))
         return false;
 
     ReturnStatus status;
-    if (!CallHas(objId, idVar, &status, bp))
+    if (!SendHas(objId, idVar, &status, bp))
         return ipcfail(cx);
 
     LOG_STACK();
 
     return ok(cx, status);
 }
 
 bool
@@ -306,17 +306,17 @@ WrapperOwner::hasOwn(JSContext *cx, Hand
 {
     ObjectId objId = idOf(proxy);
 
     JSIDVariant idVar;
     if (!toJSIDVariant(cx, id, &idVar))
         return false;
 
     ReturnStatus status;
-    if (!CallHasOwn(objId, idVar, &status, bp))
+    if (!SendHasOwn(objId, idVar, &status, bp))
         return ipcfail(cx);
 
     LOG_STACK();
 
     return !!ok(cx, status);
 }
 
 bool
@@ -391,17 +391,17 @@ WrapperOwner::get(JSContext *cx, HandleO
         return false;
 
     JSIDVariant idVar;
     if (!toJSIDVariant(cx, id, &idVar))
         return false;
 
     JSVariant val;
     ReturnStatus status;
-    if (!CallGet(objId, receiverVar, idVar, &status, &val))
+    if (!SendGet(objId, receiverVar, idVar, &status, &val))
         return ipcfail(cx);
 
     LOG_STACK();
 
     if (!ok(cx, status))
         return false;
 
     if (!fromVariant(cx, val, vp))
@@ -446,17 +446,17 @@ WrapperOwner::set(JSContext *cx, JS::Han
         return false;
 
     JSVariant val;
     if (!toVariant(cx, vp, &val))
         return false;
 
     ReturnStatus status;
     JSVariant result;
-    if (!CallSet(objId, receiverVar, idVar, strict, val, &status, &result))
+    if (!SendSet(objId, receiverVar, idVar, strict, val, &status, &result))
         return ipcfail(cx);
 
     LOG_STACK();
 
     if (!ok(cx, status))
         return false;
 
     return fromVariant(cx, result, vp);
@@ -481,17 +481,17 @@ CPOWProxyHandler::isExtensible(JSContext
 }
 
 bool
 WrapperOwner::isExtensible(JSContext *cx, HandleObject proxy, bool *extensible)
 {
     ObjectId objId = idOf(proxy);
 
     ReturnStatus status;
-    if (!CallIsExtensible(objId, &status, extensible))
+    if (!SendIsExtensible(objId, &status, extensible))
         return ipcfail(cx);
 
     LOG_STACK();
 
     return ok(cx, status);
 }
 
 bool
@@ -545,17 +545,17 @@ WrapperOwner::callOrConstruct(JSContext 
         if (!toVariant(cx, v, &val))
             return false;
         vals.AppendElement(JSParam(val));
     }
 
     JSVariant result;
     ReturnStatus status;
     InfallibleTArray<JSParam> outparams;
-    if (!CallCallOrConstruct(objId, vals, construct, &status, &result, &outparams))
+    if (!SendCallOrConstruct(objId, vals, construct, &status, &result, &outparams))
         return ipcfail(cx);
 
     LOG_STACK();
 
     if (!ok(cx, status))
         return false;
 
     if (outparams.Length() != outobjects.length())
@@ -595,17 +595,17 @@ WrapperOwner::hasInstance(JSContext *cx,
     ObjectId objId = idOf(proxy);
 
     JSVariant vVar;
     if (!toVariant(cx, v, &vVar))
         return false;
 
     ReturnStatus status;
     JSVariant result;
-    if (!CallHasInstance(objId, vVar, &status, bp))
+    if (!SendHasInstance(objId, vVar, &status, bp))
         return ipcfail(cx);
 
     LOG_STACK();
 
     return ok(cx, status);
 }
 
 bool
@@ -617,17 +617,17 @@ CPOWProxyHandler::objectClassIs(HandleOb
 bool
 WrapperOwner::objectClassIs(JSContext *cx, HandleObject proxy, js::ESClassValue classValue)
 {
     ObjectId objId = idOf(proxy);
 
     // This function is assumed infallible, so we just return false if the IPC
     // channel fails.
     bool result;
-    if (!CallObjectClassIs(objId, classValue, &result))
+    if (!SendObjectClassIs(objId, classValue, &result))
         return false;
 
     LOG_STACK();
 
     return result;
 }
 
 const char *
@@ -640,17 +640,17 @@ CPOWProxyHandler::className(JSContext *c
 }
 
 const char *
 WrapperOwner::className(JSContext *cx, HandleObject proxy)
 {
     ObjectId objId = idOf(proxy);
 
     nsString name;
-    if (!CallClassName(objId, &name))
+    if (!SendClassName(objId, &name))
         return "<error>";
 
     LOG_STACK();
 
     return ToNewCString(name);
 }
 
 bool
@@ -662,17 +662,17 @@ CPOWProxyHandler::regexp_toShared(JSCont
 bool
 WrapperOwner::regexp_toShared(JSContext *cx, HandleObject proxy, RegExpGuard *g)
 {
     ObjectId objId = idOf(proxy);
 
     ReturnStatus status;
     nsString source;
     unsigned flags = 0;
-    if (!CallRegExpToShared(objId, &status, &source, &flags))
+    if (!SendRegExpToShared(objId, &status, &source, &flags))
         return ipcfail(cx);
 
     LOG_STACK();
 
     if (!ok(cx, status))
         return false;
 
     RootedObject regexp(cx);
@@ -706,17 +706,17 @@ CPOWProxyHandler::isCallable(JSObject *p
 }
 
 bool
 WrapperOwner::isCallable(JSObject *obj)
 {
     ObjectId objId = idOf(obj);
 
     bool callable = false;
-    if (!CallIsCallable(objId, &callable)) {
+    if (!SendIsCallable(objId, &callable)) {
         NS_WARNING("IPC isCallable() failed");
         return false;
     }
 
     return callable;
 }
 
 bool
@@ -729,17 +729,17 @@ CPOWProxyHandler::isConstructor(JSObject
 }
 
 bool
 WrapperOwner::isConstructor(JSObject *obj)
 {
     ObjectId objId = idOf(obj);
 
     bool constructor = false;
-    if (!CallIsConstructor(objId, &constructor)) {
+    if (!SendIsConstructor(objId, &constructor)) {
         NS_WARNING("IPC isConstructor() failed");
         return false;
     }
 
     return constructor;
 }
 
 void
@@ -772,17 +772,17 @@ WrapperOwner::init()
 
 bool
 WrapperOwner::getPropertyNames(JSContext *cx, HandleObject proxy, uint32_t flags, AutoIdVector &props)
 {
     ObjectId objId = idOf(proxy);
 
     ReturnStatus status;
     InfallibleTArray<nsString> names;
-    if (!CallGetPropertyNames(objId, flags, &status, &names))
+    if (!SendGetPropertyNames(objId, flags, &status, &names))
         return ipcfail(cx);
 
     LOG_STACK();
 
     if (!ok(cx, status))
         return false;
 
     for (size_t i = 0; i < names.Length(); i++) {
@@ -836,32 +836,32 @@ nsresult
 WrapperOwner::instanceOf(JSObject *obj, const nsID *id, bool *bp)
 {
     ObjectId objId = idOf(obj);
 
     JSIID iid;
     ConvertID(*id, &iid);
 
     ReturnStatus status;
-    if (!CallInstanceOf(objId, iid, &status, bp))
+    if (!SendInstanceOf(objId, iid, &status, bp))
         return NS_ERROR_UNEXPECTED;
 
     if (status.type() != ReturnStatus::TReturnSuccess)
         return NS_ERROR_UNEXPECTED;
 
     return NS_OK;
 }
 
 bool
 WrapperOwner::domInstanceOf(JSContext *cx, JSObject *obj, int prototypeID, int depth, bool *bp)
 {
     ObjectId objId = idOf(obj);
 
     ReturnStatus status;
-    if (!CallDOMInstanceOf(objId, prototypeID, depth, &status, bp))
+    if (!SendDOMInstanceOf(objId, prototypeID, depth, &status, bp))
         return ipcfail(cx);
 
     LOG_STACK();
 
     return ok(cx, status);
 }
 
 void
--- a/js/ipc/WrapperOwner.h
+++ b/js/ipc/WrapperOwner.h
@@ -102,63 +102,63 @@ class WrapperOwner : public virtual Java
     // Check whether a return status is okay, and if not, propagate its error.
     bool ok(JSContext *cx, const ReturnStatus &status);
 
     bool inactive_;
 
     /*** Dummy call handlers ***/
   public:
     virtual bool SendDropObject(const ObjectId &objId) = 0;
-    virtual bool CallPreventExtensions(const ObjectId &objId, ReturnStatus *rs) = 0;
-    virtual bool CallGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id,
+    virtual bool SendPreventExtensions(const ObjectId &objId, ReturnStatus *rs) = 0;
+    virtual bool SendGetPropertyDescriptor(const ObjectId &objId, const JSIDVariant &id,
                                            ReturnStatus *rs,
                                            PPropertyDescriptor *out) = 0;
-    virtual bool CallGetOwnPropertyDescriptor(const ObjectId &objId,
+    virtual bool SendGetOwnPropertyDescriptor(const ObjectId &objId,
                                               const JSIDVariant &id,
                                               ReturnStatus *rs,
                                               PPropertyDescriptor *out) = 0;
-    virtual bool CallDefineProperty(const ObjectId &objId, const JSIDVariant &id,
+    virtual bool SendDefineProperty(const ObjectId &objId, const JSIDVariant &id,
                                     const PPropertyDescriptor &flags,
                                     ReturnStatus *rs) = 0;
-    virtual bool CallDelete(const ObjectId &objId, const JSIDVariant &id,
+    virtual bool SendDelete(const ObjectId &objId, const JSIDVariant &id,
                             ReturnStatus *rs, bool *success) = 0;
 
-    virtual bool CallHas(const ObjectId &objId, const JSIDVariant &id,
+    virtual bool SendHas(const ObjectId &objId, const JSIDVariant &id,
                          ReturnStatus *rs, bool *bp) = 0;
-    virtual bool CallHasOwn(const ObjectId &objId, const JSIDVariant &id,
+    virtual bool SendHasOwn(const ObjectId &objId, const JSIDVariant &id,
                             ReturnStatus *rs, bool *bp) = 0;
-    virtual bool CallGet(const ObjectId &objId, const ObjectVariant &receiverVar,
+    virtual bool SendGet(const ObjectId &objId, const ObjectVariant &receiverVar,
                          const JSIDVariant &id,
                          ReturnStatus *rs, JSVariant *result) = 0;
-    virtual bool CallSet(const ObjectId &objId, const ObjectVariant &receiverVar,
+    virtual bool SendSet(const ObjectId &objId, const ObjectVariant &receiverVar,
                          const JSIDVariant &id, const bool &strict,
                          const JSVariant &value, ReturnStatus *rs, JSVariant *result) = 0;
 
-    virtual bool CallIsExtensible(const ObjectId &objId, ReturnStatus *rs,
+    virtual bool SendIsExtensible(const ObjectId &objId, ReturnStatus *rs,
                                   bool *result) = 0;
-    virtual bool CallCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
+    virtual bool SendCallOrConstruct(const ObjectId &objId, const nsTArray<JSParam> &argv,
                                      const bool &construct, ReturnStatus *rs, JSVariant *result,
                                      nsTArray<JSParam> *outparams) = 0;
-    virtual bool CallHasInstance(const ObjectId &objId, const JSVariant &v,
+    virtual bool SendHasInstance(const ObjectId &objId, const JSVariant &v,
                                  ReturnStatus *rs, bool *bp) = 0;
-    virtual bool CallObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
+    virtual bool SendObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
                                    bool *result) = 0;
-    virtual bool CallClassName(const ObjectId &objId, nsString *result) = 0;
-    virtual bool CallRegExpToShared(const ObjectId &objId, ReturnStatus *rs, nsString *source,
+    virtual bool SendClassName(const ObjectId &objId, nsString *result) = 0;
+    virtual bool SendRegExpToShared(const ObjectId &objId, ReturnStatus *rs, nsString *source,
                                     uint32_t *flags) = 0;
 
-    virtual bool CallGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
+    virtual bool SendGetPropertyNames(const ObjectId &objId, const uint32_t &flags,
                                       ReturnStatus *rs, nsTArray<nsString> *names) = 0;
-    virtual bool CallInstanceOf(const ObjectId &objId, const JSIID &iid,
+    virtual bool SendInstanceOf(const ObjectId &objId, const JSIID &iid,
                                 ReturnStatus *rs, bool *instanceof) = 0;
-    virtual bool CallDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
+    virtual bool SendDOMInstanceOf(const ObjectId &objId, const int &prototypeID, const int &depth,
                                    ReturnStatus *rs, bool *instanceof) = 0;
 
-    virtual bool CallIsCallable(const ObjectId &objId, bool *result) = 0;
-    virtual bool CallIsConstructor(const ObjectId &objId, bool *result) = 0;
+    virtual bool SendIsCallable(const ObjectId &objId, bool *result) = 0;
+    virtual bool SendIsConstructor(const ObjectId &objId, bool *result) = 0;
 };
 
 bool
 IsCPOW(JSObject *obj);
 
 bool
 IsWrappedCPOW(JSObject *obj);
 
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -4328,17 +4328,17 @@ inline static mozilla::HangMonitor::Acti
   return mozilla::HangMonitor::kActivityUIAVail;
 }
 
 // The WndProc procedure for all nsWindows in this toolkit. This merely catches
 // exceptions and passes the real work to WindowProcInternal. See bug 587406
 // and http://msdn.microsoft.com/en-us/library/ms633573%28VS.85%29.aspx
 LRESULT CALLBACK nsWindow::WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
-  MOZ_RELEASE_ASSERT(!ipc::ProcessingUrgentMessages());
+  MOZ_RELEASE_ASSERT(!ipc::ParentProcessIsBlocked());
 
   HangMonitor::NotifyActivity(ActivityTypeForMessage(msg));
 
   return mozilla::CallWindowProcCrashProtected(WindowProcInternal, hWnd, msg, wParam, lParam);
 }
 
 LRESULT CALLBACK nsWindow::WindowProcInternal(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
--- a/widget/xpwidgets/ScreenProxy.cpp
+++ b/widget/xpwidgets/ScreenProxy.cpp
@@ -142,17 +142,17 @@ ScreenProxy::EnsureCacheIsValid()
   if (mCacheValid) {
     return true;
   }
 
   bool success = false;
   // Kick off a synchronous IPC call to the parent to get the
   // most up-to-date information.
   ScreenDetails details;
-  unused << mScreenManager->CallScreenRefresh(mId, &details, &success);
+  unused << mScreenManager->SendScreenRefresh(mId, &details, &success);
   if (!success) {
     NS_WARNING("Updating a ScreenProxy in the child process failed on parent side.");
     return false;
   }
 
   PopulateByDetails(details);
   mCacheValid = true;
 
--- a/widget/xpwidgets/nsScreenManagerProxy.cpp
+++ b/widget/xpwidgets/nsScreenManagerProxy.cpp
@@ -23,17 +23,17 @@ NS_IMPL_ISUPPORTS(nsScreenManagerProxy, 
 
 nsScreenManagerProxy::nsScreenManagerProxy()
   : mNumberOfScreens(-1)
   , mSystemDefaultScale(1.0)
   , mCacheValid(true)
   , mCacheWillInvalidate(false)
 {
   bool success = false;
-  unused << ContentChild::GetSingleton()->CallPScreenManagerConstructor(
+  unused << ContentChild::GetSingleton()->SendPScreenManagerConstructor(
                                             this,
                                             &mNumberOfScreens,
                                             &mSystemDefaultScale,
                                             &success);
 
   if (!success) {
     // We're in bad shape. We'll return the default values, but we'll basically
     // be lying.
@@ -59,17 +59,17 @@ nsScreenManagerProxy::nsScreenManagerPro
 NS_IMETHODIMP
 nsScreenManagerProxy::GetPrimaryScreen(nsIScreen** outScreen)
 {
   InvalidateCacheOnNextTick();
 
   if (!mPrimaryScreen) {
     ScreenDetails details;
     bool success = false;
-    unused << CallGetPrimaryScreen(&details, &success);
+    unused << SendGetPrimaryScreen(&details, &success);
     if (!success) {
       return NS_ERROR_FAILURE;
     }
 
     mPrimaryScreen = new ScreenProxy(this, details);
   }
   NS_ADDREF(*outScreen = mPrimaryScreen);
   return NS_OK;
@@ -87,17 +87,17 @@ NS_IMETHODIMP
 nsScreenManagerProxy::ScreenForRect(int32_t inLeft,
                                     int32_t inTop,
                                     int32_t inWidth,
                                     int32_t inHeight,
                                     nsIScreen** outScreen)
 {
   bool success = false;
   ScreenDetails details;
-  unused << CallScreenForRect(inLeft, inTop, inWidth, inHeight, &details, &success);
+  unused << SendScreenForRect(inLeft, inTop, inWidth, inHeight, &details, &success);
   if (!success) {
     return NS_ERROR_FAILURE;
   }
 
   nsRefPtr<ScreenProxy> screen = new ScreenProxy(this, details);
   NS_ADDREF(*outScreen = screen);
 
   return NS_OK;
@@ -121,17 +121,17 @@ nsScreenManagerProxy::ScreenForNativeWid
           return NS_OK;
       }
   }
 
   // Never cached this screen, so we have to ask the parent process
   // for it.
   bool success = false;
   ScreenDetails details;
-  unused << CallScreenForBrowser(tabChild, &details, &success);
+  unused << SendScreenForBrowser(tabChild, &details, &success);
   if (!success) {
     return NS_ERROR_FAILURE;
   }
 
   ScreenCacheEntry newEntry;
   nsRefPtr<ScreenProxy> screen = new ScreenProxy(this, details);
 
   newEntry.mScreenProxy = screen;
@@ -172,17 +172,17 @@ nsScreenManagerProxy::EnsureCacheIsValid
 {
   if (mCacheValid) {
     return true;
   }
 
   bool success = false;
   // Kick off a synchronous IPC call to the parent to get the
   // most up-to-date information.
-  unused << CallRefresh(&mNumberOfScreens, &mSystemDefaultScale, &success);
+  unused << SendRefresh(&mNumberOfScreens, &mSystemDefaultScale, &success);
   if (!success) {
     NS_WARNING("Refreshing nsScreenManagerProxy failed in the parent process.");
     return false;
   }
 
   mCacheValid = true;
 
   InvalidateCacheOnNextTick();
--- a/xpcom/threads/nsThread.cpp
+++ b/xpcom/threads/nsThread.cpp
@@ -722,17 +722,17 @@ void canary_alarm_handler(int signum)
 
 NS_IMETHODIMP
 nsThread::ProcessNextEvent(bool aMayWait, bool* aResult)
 {
   LOG(("THRD(%p) ProcessNextEvent [%u %u]\n", this, aMayWait, mRunningEvent));
 
   // If we're on the main thread, we shouldn't be dispatching CPOWs.
   MOZ_RELEASE_ASSERT(mIsMainThread != MAIN_THREAD ||
-                     !ipc::ProcessingUrgentMessages());
+                     !ipc::ParentProcessIsBlocked());
 
   if (NS_WARN_IF(PR_GetCurrentThread() != mThread)) {
     return NS_ERROR_NOT_SAME_THREAD;
   }
 
   // The toplevel event loop normally blocks waiting for the next event, but
   // if we're trying to shut this thread down, we must exit the event loop when
   // the event queue is empty.