Bug 1049879 - Remove urgent and rpc message types and replace with message priorities (r=dvander,bent,ehsan)
☠☠ backed out by 405e4dba0359 ☠ ☠
authorBill McCloskey <wmccloskey@mozilla.com>
Tue, 07 Oct 2014 21:32:45 -0700
changeset 209263 e56bf4ea89fbe8633f23035e98bbd547ad262b0c
parent 209262 a08cd664c7b10a49e15259927049b7badbf191c5
child 209264 d9d3423d423087cf96b0a43d69879485d5184838
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersdvander, bent, ehsan
bugs1049879
milestone35.0a1
Bug 1049879 - Remove urgent and rpc message types and replace with message priorities (r=dvander,bent,ehsan)
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/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.