Bug 1512990 - Part 2 - implement direct calls in the IPDL compiler; r=froydnj
authorAlex Gaynor <agaynor@mozilla.com>
Wed, 06 Feb 2019 15:57:37 +0000
changeset 457458 cb8d1788b8028e816c8fbfdae6bd70c5c824ad25
parent 457457 d623e8eff5e383b4fb281a90a5502227322a7286
child 457459 09c24f46810fa8c6ebd5879d32db87132e72a06e
push id111729
push userrgurzau@mozilla.com
push dateWed, 06 Feb 2019 22:00:03 +0000
treeherdermozilla-inbound@dacb06f05d5b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1512990
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1512990 - Part 2 - implement direct calls in the IPDL compiler; r=froydnj When calling a Recv/Alloc/Dealloc method on most types, cast `this` to the derived class. There is a heuristic to figure out what the correct derived type is. There is a blacklist of types which we can't do direct calls on for the moment, as well as an override for types that do work with direct calls but which don't match the heuristic. Differential Revision: https://phabricator.services.mozilla.com/D16492
devtools/shared/heapsnapshot/HeapSnapshotTempFileHelperParent.h
dom/cache/CacheChild.h
dom/cache/CacheOpChild.h
dom/cache/CacheParent.h
dom/cache/CacheStorageChild.h
dom/cache/CacheStorageParent.h
dom/cache/CacheStreamControlChild.h
dom/cache/CacheStreamControlParent.h
dom/file/ipc/TemporaryIPCBlobChild.h
dom/file/ipc/TemporaryIPCBlobParent.h
dom/filehandle/ActorsParent.h
dom/filesystem/FileSystemTaskBase.h
dom/gamepad/ipc/GamepadTestChannelChild.h
dom/ipc/ContentBridgeChild.h
dom/ipc/ContentBridgeParent.h
dom/ipc/ContentChild.h
dom/ipc/ContentParent.h
dom/ipc/TabChild.h
dom/ipc/TabParent.h
dom/ipc/WindowGlobalParent.h
dom/media/gmp/ChromiumCDMParent.h
dom/media/gmp/GMPChild.h
dom/media/gmp/GMPContentParent.h
dom/media/gmp/GMPParent.h
dom/media/gmp/GMPStorageChild.h
dom/media/gmp/GMPStorageParent.h
dom/media/gmp/GMPTimerChild.h
dom/media/gmp/GMPTimerParent.h
dom/media/gmp/GMPVideoDecoderChild.h
dom/media/gmp/GMPVideoDecoderParent.h
dom/media/gmp/GMPVideoEncoderChild.h
dom/media/gmp/GMPVideoEncoderParent.h
dom/media/ipc/RemoteDecoderManagerChild.h
dom/media/ipc/RemoteDecoderManagerParent.h
dom/media/ipc/VideoDecoderManagerChild.h
dom/media/ipc/VideoDecoderManagerParent.h
dom/media/systemservices/MediaSystemResourceManagerChild.h
dom/media/systemservices/MediaSystemResourceManagerParent.h
dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h
dom/media/webspeech/synth/ipc/SpeechSynthesisParent.h
dom/messagechannel/MessagePortChild.h
dom/messagechannel/MessagePortParent.h
dom/payments/ipc/PaymentRequestChild.h
dom/payments/ipc/PaymentRequestParent.h
dom/plugins/ipc/PluginInstanceChild.h
dom/plugins/ipc/PluginInstanceParent.h
dom/plugins/ipc/PluginModuleChild.h
dom/plugins/ipc/PluginModuleParent.h
dom/plugins/ipc/StreamNotifyChild.h
dom/plugins/ipc/StreamNotifyParent.h
dom/serviceworkers/ServiceWorkerManagerParent.h
dom/workers/remoteworkers/RemoteWorkerChild.h
dom/workers/remoteworkers/RemoteWorkerParent.h
dom/workers/sharedworkers/SharedWorkerChild.h
gfx/layers/ipc/APZCTreeManagerChild.h
gfx/layers/ipc/CompositorBridgeChild.h
gfx/layers/ipc/CompositorBridgeParent.h
gfx/layers/ipc/LayerTransactionParent.h
gfx/layers/ipc/UiCompositorControllerChild.h
gfx/layers/wr/WebRenderBridgeChild.h
gfx/vr/ipc/VRChild.h
gfx/vr/ipc/VRGPUParent.h
gfx/vr/ipc/VRManagerChild.h
gfx/vr/ipc/VRManagerParent.h
gfx/vr/ipc/VRParent.h
ipc/glue/FileDescriptorSetChild.h
ipc/glue/FileDescriptorSetParent.h
ipc/glue/InProcessChild.h
ipc/glue/InProcessParent.h
ipc/ipdl/ipdl/direct_call.py
ipc/ipdl/ipdl/lower.py
ipc/testshell/TestShellParent.h
js/xpconnect/loader/ScriptCacheActors.h
layout/ipc/VsyncChild.h
layout/ipc/VsyncParent.h
media/mtransport/ipc/StunAddrsRequestChild.h
media/mtransport/ipc/StunAddrsRequestParent.h
netwerk/cookie/CookieServiceChild.h
netwerk/cookie/CookieServiceParent.h
netwerk/dns/DNSRequestChild.h
netwerk/ipc/NeckoChild.h
netwerk/ipc/NeckoParent.h
netwerk/protocol/http/HttpBackgroundChannelChild.h
netwerk/protocol/http/TrackingDummyChannelChild.h
netwerk/protocol/websocket/WebSocketChannelChild.h
netwerk/protocol/websocket/WebSocketChannelParent.h
netwerk/protocol/websocket/WebSocketEventListenerParent.h
netwerk/protocol/wyciwyg/WyciwygChannelParent.h
toolkit/components/extensions/webrequest/StreamFilterChild.h
toolkit/components/extensions/webrequest/StreamFilterParent.h
toolkit/components/printingui/ipc/nsPrintingProxy.h
--- a/devtools/shared/heapsnapshot/HeapSnapshotTempFileHelperParent.h
+++ b/devtools/shared/heapsnapshot/HeapSnapshotTempFileHelperParent.h
@@ -9,16 +9,18 @@
 
 #include "mozilla/devtools/PHeapSnapshotTempFileHelperParent.h"
 
 namespace mozilla {
 namespace devtools {
 
 class HeapSnapshotTempFileHelperParent
     : public PHeapSnapshotTempFileHelperParent {
+  friend class PHeapSnapshotTempFileHelperParent;
+
   explicit HeapSnapshotTempFileHelperParent() {}
   void ActorDestroy(ActorDestroyReason why) override {}
   mozilla::ipc::IPCResult RecvOpenHeapSnapshotTempFile(
       OpenHeapSnapshotTempFileResponse* outResponse) override;
 
  public:
   static inline PHeapSnapshotTempFileHelperParent* Create();
 };
--- a/dom/cache/CacheChild.h
+++ b/dom/cache/CacheChild.h
@@ -19,16 +19,18 @@ namespace dom {
 class Promise;
 
 namespace cache {
 
 class Cache;
 class CacheOpArgs;
 
 class CacheChild final : public PCacheChild, public ActorChild {
+  friend class PCacheChild;
+
  public:
   class MOZ_RAII AutoLock final {
     CacheChild* mActor;
 
    public:
     explicit AutoLock(CacheChild* aActor) : mActor(aActor) {
       MOZ_DIAGNOSTIC_ASSERT(mActor);
       mActor->Lock();
--- a/dom/cache/CacheOpChild.h
+++ b/dom/cache/CacheOpChild.h
@@ -21,16 +21,17 @@ class Promise;
 
 namespace cache {
 
 class CacheOpChild final : public PCacheOpChild,
                            public ActorChild,
                            public TypeUtils {
   friend class CacheChild;
   friend class CacheStorageChild;
+  friend class PCacheOpChild;
 
  private:
   // This class must be constructed by CacheChild or CacheStorageChild using
   // their ExecuteOp() factory method.
   CacheOpChild(CacheWorkerHolder* aWorkerHolder, nsIGlobalObject* aGlobal,
                nsISupports* aParent, Promise* aPromise);
   ~CacheOpChild();
 
--- a/dom/cache/CacheParent.h
+++ b/dom/cache/CacheParent.h
@@ -12,16 +12,18 @@
 
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 class Manager;
 
 class CacheParent final : public PCacheParent {
+  friend class PCacheParent;
+
  public:
   CacheParent(cache::Manager* aManager, CacheId aCacheId);
   virtual ~CacheParent();
 
  private:
   // PCacheParent methods
   virtual void ActorDestroy(ActorDestroyReason aReason) override;
 
--- a/dom/cache/CacheStorageChild.h
+++ b/dom/cache/CacheStorageChild.h
@@ -21,16 +21,18 @@ class Promise;
 namespace cache {
 
 class CacheOpArgs;
 class CacheStorage;
 class CacheWorkerHolder;
 class PCacheChild;
 
 class CacheStorageChild final : public PCacheStorageChild, public ActorChild {
+  friend class PCacheStorageChild;
+
  public:
   CacheStorageChild(CacheStorage* aListener, CacheWorkerHolder* aWorkerHolder);
   ~CacheStorageChild();
 
   // Must be called by the associated CacheStorage listener in its
   // DestroyInternal() method.  Also, CacheStorage must call
   // SendDestroyFromListener() on the actor in its destructor to trigger
   // ActorDestroy() if it has not been called yet.
--- a/dom/cache/CacheStorageParent.h
+++ b/dom/cache/CacheStorageParent.h
@@ -14,16 +14,18 @@
 namespace mozilla {
 namespace dom {
 namespace cache {
 
 class ManagerId;
 
 class CacheStorageParent final : public PCacheStorageParent,
                                  public PrincipalVerifier::Listener {
+  friend class PCacheStorageParent;
+
  public:
   CacheStorageParent(PBackgroundParent* aManagingActor, Namespace aNamespace,
                      const mozilla::ipc::PrincipalInfo& aPrincipalInfo);
   virtual ~CacheStorageParent();
 
  private:
   // PCacheStorageParent methods
   virtual void ActorDestroy(ActorDestroyReason aReason) override;
--- a/dom/cache/CacheStreamControlChild.h
+++ b/dom/cache/CacheStreamControlChild.h
@@ -19,16 +19,18 @@ class AutoIPCStream;
 namespace dom {
 namespace cache {
 
 class ReadStream;
 
 class CacheStreamControlChild final : public PCacheStreamControlChild,
                                       public StreamControl,
                                       public ActorChild {
+  friend class PCacheStreamControlChild;
+
  public:
   CacheStreamControlChild();
   ~CacheStreamControlChild();
 
   // ActorChild methods
   virtual void StartDestroy() override;
 
   // StreamControl methods
--- a/dom/cache/CacheStreamControlParent.h
+++ b/dom/cache/CacheStreamControlParent.h
@@ -20,16 +20,18 @@ namespace dom {
 namespace cache {
 
 class ReadStream;
 class StreamList;
 
 class CacheStreamControlParent final : public PCacheStreamControlParent,
                                        public StreamControl,
                                        Manager::Listener {
+  friend class PCacheStreamControlParent;
+
  public:
   CacheStreamControlParent();
   ~CacheStreamControlParent();
 
   void SetStreamList(StreamList* aStreamList);
   void Close(const nsID& aId);
   void CloseAll();
   void Shutdown();
--- a/dom/file/ipc/TemporaryIPCBlobChild.h
+++ b/dom/file/ipc/TemporaryIPCBlobChild.h
@@ -20,16 +20,18 @@ class TemporaryIPCBlobChildCallback {
   NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
 
   virtual void OperationSucceeded(BlobImpl* aBlobImpl) = 0;
   virtual void OperationFailed(nsresult aRv) = 0;
 };
 
 class TemporaryIPCBlobChild final
     : public mozilla::ipc::PTemporaryIPCBlobChild {
+  friend class mozilla::ipc::PTemporaryIPCBlobChild;
+
  public:
   NS_INLINE_DECL_REFCOUNTING(TemporaryIPCBlobChild)
 
   explicit TemporaryIPCBlobChild(MutableBlobStorage* aMutableBlobStorage);
 
   void AskForBlob(TemporaryIPCBlobChildCallback* aCallback,
                   const nsACString& aContentType, PRFileDesc* aFD);
 
--- a/dom/file/ipc/TemporaryIPCBlobParent.h
+++ b/dom/file/ipc/TemporaryIPCBlobParent.h
@@ -12,16 +12,18 @@
 
 class nsIFile;
 
 namespace mozilla {
 namespace dom {
 
 class TemporaryIPCBlobParent final
     : public mozilla::ipc::PTemporaryIPCBlobParent {
+  friend class mozilla::ipc::PTemporaryIPCBlobParent;
+
  public:
   explicit TemporaryIPCBlobParent();
 
   mozilla::ipc::IPCResult CreateAndShareFile();
 
  private:
   ~TemporaryIPCBlobParent();
 
--- a/dom/filehandle/ActorsParent.h
+++ b/dom/filehandle/ActorsParent.h
@@ -86,16 +86,18 @@ class FileHandleThreadPool final {
   void Cleanup();
 
   void FinishFileHandle(FileHandle* aFileHandle);
 
   bool MaybeFireCallback(StoragesCompleteCallback* aCallback);
 };
 
 class BackgroundMutableFileParentBase : public PBackgroundMutableFileParent {
+  friend PBackgroundMutableFileParent;
+
   nsTHashtable<nsPtrHashKey<FileHandle>> mFileHandles;
   nsCString mDirectoryId;
   nsString mFileName;
   FileHandleStorage mStorage;
   bool mInvalidated;
   bool mActorWasAlive;
   bool mActorDestroyed;
 
--- a/dom/filesystem/FileSystemTaskBase.h
+++ b/dom/filesystem/FileSystemTaskBase.h
@@ -94,16 +94,18 @@ class FileSystemParams;
  *   function -[GetSuccessRequestResult].
  * Child/Parent:
  *   (7) The process receives IPC and calls [SetRequestResult] to get the
  *   task result. Each task needs to implement its specific success result
  *   parsing function [SetSuccessRequestResult] to get the success result.
  *   (8) Call [HandlerCallback] to send the task result to the content page.
  */
 class FileSystemTaskChildBase : public PFileSystemRequestChild {
+  friend class PFileSystemRequestChild;
+
  public:
   NS_INLINE_DECL_REFCOUNTING(FileSystemTaskChildBase)
 
   /*
    * Start the task. It will dispatch all the information to the parent process,
    * PBackground thread. This method must be called from the owning thread.
    */
   void Start();
--- a/dom/gamepad/ipc/GamepadTestChannelChild.h
+++ b/dom/gamepad/ipc/GamepadTestChannelChild.h
@@ -9,16 +9,18 @@
 
 #ifndef mozilla_dom_GamepadTestChannelChild_h_
 #  define mozilla_dom_GamepadTestChannelChild_h_
 
 namespace mozilla {
 namespace dom {
 
 class GamepadTestChannelChild final : public PGamepadTestChannelChild {
+  friend class PGamepadTestChannelChild;
+
  public:
   GamepadTestChannelChild() {}
   ~GamepadTestChannelChild() {}
   void AddPromise(const uint32_t& aID, Promise* aPromise);
 
  private:
   virtual mozilla::ipc::IPCResult RecvReplyGamepadIndex(
       const uint32_t& aID, const uint32_t& aIndex) override;
--- a/dom/ipc/ContentBridgeChild.h
+++ b/dom/ipc/ContentBridgeChild.h
@@ -10,16 +10,18 @@
 #include "mozilla/dom/PContentBridgeChild.h"
 #include "mozilla/dom/nsIContentChild.h"
 
 namespace mozilla {
 namespace dom {
 
 class ContentBridgeChild final : public PContentBridgeChild,
                                  public nsIContentChild {
+  friend class PContentBridgeChild;
+
  public:
   explicit ContentBridgeChild();
 
   NS_DECL_ISUPPORTS
 
   static void Create(Endpoint<PContentBridgeChild>&& aEndpoint);
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
--- a/dom/ipc/ContentBridgeParent.h
+++ b/dom/ipc/ContentBridgeParent.h
@@ -13,16 +13,18 @@
 #include "nsIObserver.h"
 
 namespace mozilla {
 namespace dom {
 
 class ContentBridgeParent : public PContentBridgeParent,
                             public nsIContentParent,
                             public nsIObserver {
+  friend class PContentBridgeParent;
+
  public:
   explicit ContentBridgeParent();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
   void DeferredDestroy();
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -80,16 +80,18 @@ class ContentChild final : public PConte
                            public nsIWindowProvider,
                            public nsIContentChild {
   typedef mozilla::dom::ClonedMessageData ClonedMessageData;
   typedef mozilla::ipc::FileDescriptor FileDescriptor;
   typedef mozilla::ipc::OptionalURIParams OptionalURIParams;
   typedef mozilla::ipc::PFileDescriptorSetChild PFileDescriptorSetChild;
   typedef mozilla::ipc::URIParams URIParams;
 
+  friend class PContentChild;
+
  public:
   NS_DECL_NSIWINDOWPROVIDER
 
   ContentChild();
   virtual ~ContentChild();
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
   NS_IMETHOD_(MozExternalRefCountType) AddRef(void) override { return 1; }
   NS_IMETHOD_(MozExternalRefCountType) Release(void) override { return 1; }
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -119,16 +119,17 @@ class ContentParent final : public PCont
   typedef mozilla::ipc::OptionalURIParams OptionalURIParams;
   typedef mozilla::ipc::PFileDescriptorSetParent PFileDescriptorSetParent;
   typedef mozilla::ipc::TestShellParent TestShellParent;
   typedef mozilla::ipc::URIParams URIParams;
   typedef mozilla::ipc::PrincipalInfo PrincipalInfo;
   typedef mozilla::dom::ClonedMessageData ClonedMessageData;
 
   friend class mozilla::PreallocatedProcessManagerImpl;
+  friend class PContentParent;
 #ifdef FUZZING
   friend class mozilla::ipc::ProtocolFuzzerHelper;
 #endif
 
  public:
   virtual bool IsContentParent() const override { return true; }
 
   using LaunchError = GeckoChildProcessHost::LaunchError;
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -210,16 +210,18 @@ class TabChild final : public TabChildBa
   typedef mozilla::dom::ClonedMessageData ClonedMessageData;
   typedef mozilla::dom::CoalescedMouseData CoalescedMouseData;
   typedef mozilla::dom::CoalescedWheelData CoalescedWheelData;
   typedef mozilla::layers::APZEventState APZEventState;
   typedef mozilla::layers::SetAllowedTouchBehaviorCallback
       SetAllowedTouchBehaviorCallback;
   typedef mozilla::layers::TouchBehaviorFlags TouchBehaviorFlags;
 
+  friend class PBrowserChild;
+
  public:
   /**
    * Find TabChild of aTabId in the same content process of the
    * caller.
    */
   static already_AddRefed<TabChild> FindTabChild(const TabId& aTabId);
 
   // Return a list of all active TabChildren.
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -82,16 +82,18 @@ class TabParent final : public PBrowserP
                         public nsITabParent,
                         public nsIAuthPromptProvider,
                         public nsIKeyEventInPluginCallback,
                         public nsSupportsWeakReference,
                         public TabContext,
                         public LiveResizeListener {
   typedef mozilla::dom::ClonedMessageData ClonedMessageData;
 
+  friend class PBrowserParent;
+
   virtual ~TabParent();
 
  public:
   // Helper class for ContentParent::RecvCreateWindow.
   struct AutoUseNewTab;
 
   // nsITabParent
   NS_DECL_NSITABPARENT
--- a/dom/ipc/WindowGlobalParent.h
+++ b/dom/ipc/WindowGlobalParent.h
@@ -24,16 +24,18 @@ class WindowGlobalChild;
 class JSWindowActorParent;
 
 /**
  * A handle in the parent process to a specific nsGlobalWindowInner object.
  */
 class WindowGlobalParent final : public nsISupports,
                                  public nsWrapperCache,
                                  public PWindowGlobalParent {
+  friend class PWindowGlobalParent;
+
  public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WindowGlobalParent)
 
   static already_AddRefed<WindowGlobalParent> GetByInnerWindowId(
       uint64_t aInnerWindowId);
 
   static already_AddRefed<WindowGlobalParent> GetByInnerWindowId(
--- a/dom/media/gmp/ChromiumCDMParent.h
+++ b/dom/media/gmp/ChromiumCDMParent.h
@@ -26,16 +26,18 @@ class MediaRawData;
 class ChromiumCDMProxy;
 
 namespace gmp {
 
 class GMPContentParent;
 
 class ChromiumCDMParent final : public PChromiumCDMParent,
                                 public GMPCrashHelperHolder {
+  friend class PChromiumCDMParent;
+
  public:
   typedef MozPromise<bool, MediaResult, /* IsExclusive = */ true> InitPromise;
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ChromiumCDMParent)
 
   ChromiumCDMParent(GMPContentParent* aContentParent, uint32_t aPluginId);
 
   uint32_t PluginId() const { return mPluginId; }
--- a/dom/media/gmp/GMPChild.h
+++ b/dom/media/gmp/GMPChild.h
@@ -15,16 +15,18 @@
 #include "prlink.h"
 
 namespace mozilla {
 namespace gmp {
 
 class GMPContentChild;
 
 class GMPChild : public PGMPChild {
+  friend class PGMPChild;
+
  public:
   GMPChild();
   virtual ~GMPChild();
 
   bool Init(const nsAString& aPluginPath, base::ProcessId aParentPid,
             MessageLoop* aIOLoop, IPC::Channel* aChannel);
   MessageLoop* GMPMessageLoop();
 
--- a/dom/media/gmp/GMPContentParent.h
+++ b/dom/media/gmp/GMPContentParent.h
@@ -14,16 +14,18 @@ namespace mozilla {
 namespace gmp {
 
 class GMPParent;
 class GMPVideoDecoderParent;
 class GMPVideoEncoderParent;
 class ChromiumCDMParent;
 
 class GMPContentParent final : public PGMPContentParent, public GMPSharedMem {
+  friend class PGMPContentParent;
+
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPContentParent)
 
   explicit GMPContentParent(GMPParent* aParent = nullptr);
 
   nsresult GetGMPVideoDecoder(GMPVideoDecoderParent** aGMPVD,
                               uint32_t aDecryptorId);
   void VideoDecoderDestroyed(GMPVideoDecoderParent* aDecoder);
--- a/dom/media/gmp/GMPParent.h
+++ b/dom/media/gmp/GMPParent.h
@@ -50,16 +50,18 @@ enum GMPState {
   GMPStateLoaded,
   GMPStateUnloading,
   GMPStateClosing
 };
 
 class GMPContentParent;
 
 class GMPParent final : public PGMPParent {
+  friend class PGMPParent;
+
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPParent)
 
   explicit GMPParent(AbstractThread* aMainThread);
 
   RefPtr<GenericPromise> Init(GeckoMediaPluginServiceParent* aService,
                               nsIFile* aPluginDir);
   nsresult CloneFrom(const GMPParent* aOther);
--- a/dom/media/gmp/GMPStorageChild.h
+++ b/dom/media/gmp/GMPStorageChild.h
@@ -42,16 +42,18 @@ class GMPRecordImpl : public GMPRecord {
  private:
   ~GMPRecordImpl() {}
   const nsCString mName;
   GMPRecordClient* const mClient;
   GMPStorageChild* const mOwner;
 };
 
 class GMPStorageChild : public PGMPStorageChild {
+  friend class PGMPStorageChild;
+
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPStorageChild)
 
   explicit GMPStorageChild(GMPChild* aPlugin);
 
   GMPErr CreateRecord(const nsCString& aRecordName, GMPRecord** aOutRecord,
                       GMPRecordClient* aClient);
 
--- a/dom/media/gmp/GMPStorageParent.h
+++ b/dom/media/gmp/GMPStorageParent.h
@@ -10,16 +10,18 @@
 #include "GMPStorage.h"
 
 namespace mozilla {
 namespace gmp {
 
 class GMPParent;
 
 class GMPStorageParent : public PGMPStorageParent {
+  friend class PGMPStorageParent;
+
  public:
   NS_INLINE_DECL_REFCOUNTING(GMPStorageParent)
   GMPStorageParent(const nsCString& aNodeId, GMPParent* aPlugin);
 
   nsresult Init();
   void Shutdown();
 
  protected:
--- a/dom/media/gmp/GMPTimerChild.h
+++ b/dom/media/gmp/GMPTimerChild.h
@@ -14,16 +14,18 @@
 #include "gmp-platform.h"
 
 namespace mozilla {
 namespace gmp {
 
 class GMPChild;
 
 class GMPTimerChild : public PGMPTimerChild {
+  friend class PGMPTimerChild;
+
  public:
   NS_INLINE_DECL_REFCOUNTING(GMPTimerChild)
 
   explicit GMPTimerChild(GMPChild* aPlugin);
 
   GMPErr SetTimer(GMPTask* aTask, int64_t aTimeoutMS);
 
  protected:
--- a/dom/media/gmp/GMPTimerParent.h
+++ b/dom/media/gmp/GMPTimerParent.h
@@ -13,16 +13,18 @@
 #include "nsHashKeys.h"
 #include "mozilla/Monitor.h"
 #include "nsIThread.h"
 
 namespace mozilla {
 namespace gmp {
 
 class GMPTimerParent : public PGMPTimerParent {
+  friend class PGMPTimerParent;
+
  public:
   NS_INLINE_DECL_REFCOUNTING(GMPTimerParent)
   explicit GMPTimerParent(nsISerialEventTarget* aGMPEventTarget);
 
   void Shutdown();
 
  protected:
   mozilla::ipc::IPCResult RecvSetTimer(const uint32_t& aTimerId,
--- a/dom/media/gmp/GMPVideoDecoderChild.h
+++ b/dom/media/gmp/GMPVideoDecoderChild.h
@@ -16,16 +16,18 @@
 namespace mozilla {
 namespace gmp {
 
 class GMPContentChild;
 
 class GMPVideoDecoderChild : public PGMPVideoDecoderChild,
                              public GMPVideoDecoderCallback,
                              public GMPSharedMemManager {
+  friend class PGMPVideoDecoderChild;
+
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPVideoDecoderChild);
 
   explicit GMPVideoDecoderChild(GMPContentChild* aPlugin);
 
   void Init(GMPVideoDecoder* aDecoder);
   GMPVideoHostImpl& Host();
 
--- a/dom/media/gmp/GMPVideoDecoderParent.h
+++ b/dom/media/gmp/GMPVideoDecoderParent.h
@@ -21,16 +21,18 @@ namespace mozilla {
 namespace gmp {
 
 class GMPContentParent;
 
 class GMPVideoDecoderParent final : public PGMPVideoDecoderParent,
                                     public GMPVideoDecoderProxy,
                                     public GMPSharedMemManager,
                                     public GMPCrashHelperHolder {
+  friend class PGMPVideoDecoderParent;
+
  public:
   NS_INLINE_DECL_REFCOUNTING(GMPVideoDecoderParent)
 
   explicit GMPVideoDecoderParent(GMPContentParent* aPlugin);
 
   GMPVideoHostImpl& Host();
   nsresult Shutdown();
 
--- a/dom/media/gmp/GMPVideoEncoderChild.h
+++ b/dom/media/gmp/GMPVideoEncoderChild.h
@@ -15,16 +15,18 @@
 namespace mozilla {
 namespace gmp {
 
 class GMPContentChild;
 
 class GMPVideoEncoderChild : public PGMPVideoEncoderChild,
                              public GMPVideoEncoderCallback,
                              public GMPSharedMemManager {
+  friend class PGMPVideoEncoderChild;
+
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPVideoEncoderChild);
 
   explicit GMPVideoEncoderChild(GMPContentChild* aPlugin);
 
   void Init(GMPVideoEncoder* aEncoder);
   GMPVideoHostImpl& Host();
 
--- a/dom/media/gmp/GMPVideoEncoderParent.h
+++ b/dom/media/gmp/GMPVideoEncoderParent.h
@@ -20,16 +20,18 @@ namespace mozilla {
 namespace gmp {
 
 class GMPContentParent;
 
 class GMPVideoEncoderParent : public GMPVideoEncoderProxy,
                               public PGMPVideoEncoderParent,
                               public GMPSharedMemManager,
                               public GMPCrashHelperHolder {
+  friend class PGMPVideoEncoderParent;
+
  public:
   NS_INLINE_DECL_REFCOUNTING(GMPVideoEncoderParent)
 
   explicit GMPVideoEncoderParent(GMPContentParent* aPlugin);
 
   GMPVideoHostImpl& Host();
   void Shutdown();
 
--- a/dom/media/ipc/RemoteDecoderManagerChild.h
+++ b/dom/media/ipc/RemoteDecoderManagerChild.h
@@ -5,16 +5,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #ifndef include_dom_media_ipc_RemoteDecoderManagerChild_h
 #define include_dom_media_ipc_RemoteDecoderManagerChild_h
 #include "mozilla/PRemoteDecoderManagerChild.h"
 
 namespace mozilla {
 
 class RemoteDecoderManagerChild final : public PRemoteDecoderManagerChild {
+  friend class PRemoteDecoderManagerChild;
+
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteDecoderManagerChild)
 
   // Can only be called from the manager thread
   static RemoteDecoderManagerChild* GetSingleton();
 
   // Can be called from any thread.
   static nsIThread* GetManagerThread();
--- a/dom/media/ipc/RemoteDecoderManagerParent.h
+++ b/dom/media/ipc/RemoteDecoderManagerParent.h
@@ -7,16 +7,18 @@
 #define include_dom_media_ipc_RemoteDecoderManagerParent_h
 #include "mozilla/PRemoteDecoderManagerParent.h"
 
 namespace mozilla {
 
 class RemoteDecoderManagerThreadHolder;
 
 class RemoteDecoderManagerParent final : public PRemoteDecoderManagerParent {
+  friend class PRemoteDecoderManagerParent;
+
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteDecoderManagerParent)
 
   static bool CreateForContent(
       Endpoint<PRemoteDecoderManagerParent>&& aEndpoint);
 
   static bool StartupThreads();
   static void ShutdownThreads();
--- a/dom/media/ipc/VideoDecoderManagerChild.h
+++ b/dom/media/ipc/VideoDecoderManagerChild.h
@@ -11,16 +11,18 @@
 
 namespace mozilla {
 namespace gfx {
 class SourceSurface;
 }
 
 class VideoDecoderManagerChild final : public PVideoDecoderManagerChild,
                                        public mozilla::ipc::IShmemAllocator {
+  friend class PVideoDecoderManagerChild;
+
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoDecoderManagerChild)
 
   // Can only be called from the manager thread
   static VideoDecoderManagerChild* GetSingleton();
 
   // Can be called from any thread.
   static nsIThread* GetManagerThread();
--- a/dom/media/ipc/VideoDecoderManagerParent.h
+++ b/dom/media/ipc/VideoDecoderManagerParent.h
@@ -8,16 +8,18 @@
 
 #include "mozilla/PVideoDecoderManagerParent.h"
 
 namespace mozilla {
 
 class VideoDecoderManagerThreadHolder;
 
 class VideoDecoderManagerParent final : public PVideoDecoderManagerParent {
+  friend class PVideoDecoderManagerParent;
+
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoDecoderManagerParent)
 
   static bool CreateForContent(
       Endpoint<PVideoDecoderManagerParent>&& aEndpoint);
 
   // Can be called from any thread
   SurfaceDescriptorGPUVideo StoreImage(layers::Image* aImage,
--- a/dom/media/systemservices/MediaSystemResourceManagerChild.h
+++ b/dom/media/systemservices/MediaSystemResourceManagerChild.h
@@ -19,16 +19,18 @@ class BackgroundChildImpl;
 
 namespace media {
 
 /**
  * Handle MediaSystemResourceManager's IPC
  */
 class MediaSystemResourceManagerChild final
     : public PMediaSystemResourceManagerChild {
+  friend class PMediaSystemResourceManagerChild;
+
  public:
   struct ResourceListener {
     /* The resource is reserved and can be granted.
      * The client can allocate the requested resource.
      */
     virtual void resourceReserved() = 0;
     /* The resource is not reserved any more.
      * The client should release the resource as soon as possible if the
--- a/dom/media/systemservices/MediaSystemResourceManagerParent.h
+++ b/dom/media/systemservices/MediaSystemResourceManagerParent.h
@@ -14,16 +14,18 @@
 namespace mozilla {
 namespace media {
 
 /**
  * Handle MediaSystemResourceManager's IPC
  */
 class MediaSystemResourceManagerParent final
     : public PMediaSystemResourceManagerParent {
+  friend class PMediaSystemResourceManagerParent;
+
  public:
   MediaSystemResourceManagerParent();
   virtual ~MediaSystemResourceManagerParent();
 
  protected:
   mozilla::ipc::IPCResult RecvAcquire(
       const uint32_t& aId, const MediaSystemResourceType& aResourceType,
       const bool& aWillWait) override;
--- a/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h
+++ b/dom/media/webspeech/synth/ipc/SpeechSynthesisChild.h
@@ -14,16 +14,17 @@ namespace mozilla {
 namespace dom {
 
 class nsSynthVoiceRegistry;
 class SpeechSynthesisRequestChild;
 class SpeechTaskChild;
 
 class SpeechSynthesisChild : public PSpeechSynthesisChild {
   friend class nsSynthVoiceRegistry;
+  friend class PSpeechSynthesisChild;
 
  public:
   mozilla::ipc::IPCResult RecvInitialVoicesAndState(
       nsTArray<RemoteVoice>&& aVoices, nsTArray<nsString>&& aDefaults,
       const bool& aIsSpeaking) override;
 
   mozilla::ipc::IPCResult RecvVoiceAdded(const RemoteVoice& aVoice) override;
 
--- a/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.h
+++ b/dom/media/webspeech/synth/ipc/SpeechSynthesisParent.h
@@ -14,16 +14,17 @@ namespace dom {
 
 class ContentParent;
 class SpeechTaskParent;
 class SpeechSynthesisRequestParent;
 
 class SpeechSynthesisParent : public PSpeechSynthesisParent {
   friend class ContentParent;
   friend class SpeechSynthesisRequestParent;
+  friend class PSpeechSynthesisParent;
 
  public:
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
   bool SendInit();
 
  protected:
   SpeechSynthesisParent();
--- a/dom/messagechannel/MessagePortChild.h
+++ b/dom/messagechannel/MessagePortChild.h
@@ -12,16 +12,18 @@
 #include "nsISupportsImpl.h"
 
 namespace mozilla {
 namespace dom {
 
 class MessagePort;
 
 class MessagePortChild final : public PMessagePortChild {
+  friend class PMessagePortChild;
+
  public:
   NS_INLINE_DECL_REFCOUNTING(MessagePortChild)
 
   MessagePortChild();
 
   void SetPort(MessagePort* aPort) { mPort = aPort; }
 
  private:
--- a/dom/messagechannel/MessagePortParent.h
+++ b/dom/messagechannel/MessagePortParent.h
@@ -10,16 +10,18 @@
 #include "mozilla/dom/PMessagePortParent.h"
 
 namespace mozilla {
 namespace dom {
 
 class MessagePortService;
 
 class MessagePortParent final : public PMessagePortParent {
+  friend class PMessagePortParent;
+
  public:
   explicit MessagePortParent(const nsID& aUUID);
   ~MessagePortParent();
 
   bool Entangle(const nsID& aDestinationUUID, const uint32_t& aSequenceID);
 
   bool Entangled(const nsTArray<ClonedMessageData>& aMessages);
 
--- a/dom/payments/ipc/PaymentRequestChild.h
+++ b/dom/payments/ipc/PaymentRequestChild.h
@@ -10,16 +10,18 @@
 #include "mozilla/dom/PPaymentRequestChild.h"
 
 namespace mozilla {
 namespace dom {
 
 class PaymentRequest;
 
 class PaymentRequestChild final : public PPaymentRequestChild {
+  friend class PPaymentRequestChild;
+
  public:
   explicit PaymentRequestChild(PaymentRequest* aRequest);
 
   void MaybeDelete(bool aCanBeInManager);
 
   nsresult RequestPayment(const IPCPaymentActionRequest& aAction);
 
  protected:
--- a/dom/payments/ipc/PaymentRequestParent.h
+++ b/dom/payments/ipc/PaymentRequestParent.h
@@ -10,16 +10,18 @@
 #include "mozilla/dom/PPaymentRequestParent.h"
 #include "nsIPaymentAddress.h"
 #include "nsIPaymentActionResponse.h"
 
 namespace mozilla {
 namespace dom {
 
 class PaymentRequestParent final : public PPaymentRequestParent {
+  friend class PPaymentRequestParent;
+
   NS_INLINE_DECL_REFCOUNTING(PaymentRequestParent)
  public:
   PaymentRequestParent();
 
   nsresult RespondPayment(nsIPaymentActionResponse* aResponse);
   nsresult ChangeShippingAddress(const nsAString& aRequestId,
                                  nsIPaymentAddress* aAddress);
   nsresult ChangeShippingOption(const nsAString& aRequestId,
--- a/dom/plugins/ipc/PluginInstanceChild.h
+++ b/dom/plugins/ipc/PluginInstanceChild.h
@@ -47,16 +47,17 @@ class PBrowserStreamChild;
 class BrowserStreamChild;
 class StreamNotifyChild;
 
 class PluginInstanceChild : public PPluginInstanceChild {
   friend class BrowserStreamChild;
   friend class PluginStreamChild;
   friend class StreamNotifyChild;
   friend class PluginScriptableObjectChild;
+  friend class PPluginInstanceChild;
 
 #ifdef OS_WIN
   friend LRESULT CALLBACK PluginWindowProc(HWND hWnd, UINT message,
                                            WPARAM wParam, LPARAM lParam);
   static LRESULT CALLBACK PluginWindowProcInternal(HWND hWnd, UINT message,
                                                    WPARAM wParam,
                                                    LPARAM lParam);
 #endif
--- a/dom/plugins/ipc/PluginInstanceParent.h
+++ b/dom/plugins/ipc/PluginInstanceParent.h
@@ -40,16 +40,17 @@ namespace plugins {
 class PBrowserStreamParent;
 class PluginModuleParent;
 class D3D11SurfaceHolder;
 
 class PluginInstanceParent : public PPluginInstanceParent {
   friend class PluginModuleParent;
   friend class BrowserStreamParent;
   friend class StreamNotifyParent;
+  friend class PPluginInstanceParent;
 
 #if defined(XP_WIN)
  public:
   /**
    * Helper method for looking up instances based on a supplied id.
    */
   static PluginInstanceParent* LookupPluginInstanceByID(uintptr_t aId);
 #endif  // defined(XP_WIN)
--- a/dom/plugins/ipc/PluginModuleChild.h
+++ b/dom/plugins/ipc/PluginModuleChild.h
@@ -36,16 +36,18 @@ namespace mozilla {
 
 class ChildProfilerController;
 
 namespace plugins {
 
 class PluginInstanceChild;
 
 class PluginModuleChild : public PPluginModuleChild {
+  friend class PPluginModuleChild;
+
  protected:
   virtual mozilla::ipc::RacyInterruptPolicy MediateInterruptRace(
       const MessageInfo& parent, const MessageInfo& child) override {
     return MediateRace(parent, child);
   }
 
   virtual bool ShouldContinueFromReplyTimeout() override;
 
--- a/dom/plugins/ipc/PluginModuleParent.h
+++ b/dom/plugins/ipc/PluginModuleParent.h
@@ -72,16 +72,18 @@ class FinishInjectorInitTask;
  */
 class PluginModuleParent : public PPluginModuleParent,
                            public PluginLibrary
 #ifdef MOZ_CRASHREPORTER_INJECTOR
     ,
                            public CrashReporter::InjectorCrashCallback
 #endif
 {
+  friend class PPluginModuleParent;
+
  protected:
   typedef mozilla::PluginLibrary PluginLibrary;
 
   PPluginInstanceParent* AllocPPluginInstanceParent(
       const nsCString& aMimeType, const InfallibleTArray<nsCString>& aNames,
       const InfallibleTArray<nsCString>& aValues) override;
 
   virtual bool DeallocPPluginInstanceParent(
--- a/dom/plugins/ipc/StreamNotifyChild.h
+++ b/dom/plugins/ipc/StreamNotifyChild.h
@@ -12,16 +12,17 @@
 namespace mozilla {
 namespace plugins {
 
 class BrowserStreamChild;
 
 class StreamNotifyChild : public PStreamNotifyChild {
   friend class PluginInstanceChild;
   friend class BrowserStreamChild;
+  friend class PStreamNotifyChild;
 
  public:
   explicit StreamNotifyChild(const nsCString& aURL)
       : mURL(aURL), mClosure(nullptr), mBrowserStream(nullptr) {}
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
   void SetValid(void* aClosure) { mClosure = aClosure; }
--- a/dom/plugins/ipc/StreamNotifyParent.h
+++ b/dom/plugins/ipc/StreamNotifyParent.h
@@ -9,16 +9,17 @@
 
 #include "mozilla/plugins/PStreamNotifyParent.h"
 
 namespace mozilla {
 namespace plugins {
 
 class StreamNotifyParent : public PStreamNotifyParent {
   friend class PluginInstanceParent;
+  friend class PStreamNotifyParent;
 
   StreamNotifyParent() : mDestructionFlag(nullptr) {}
   ~StreamNotifyParent() {
     if (mDestructionFlag) *mDestructionFlag = true;
   }
 
  public:
   // If we are destroyed within the call to NPN_GetURLNotify, notify the caller
--- a/dom/serviceworkers/ServiceWorkerManagerParent.h
+++ b/dom/serviceworkers/ServiceWorkerManagerParent.h
@@ -18,16 +18,17 @@ class BackgroundParentImpl;
 }  // namespace ipc
 
 namespace dom {
 
 class ServiceWorkerManagerService;
 
 class ServiceWorkerManagerParent final : public PServiceWorkerManagerParent {
   friend class mozilla::ipc::BackgroundParentImpl;
+  friend class PServiceWorkerManagerParent;
 
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ServiceWorkerManagerParent)
 
   uint64_t ID() const { return mID; }
 
  private:
   ServiceWorkerManagerParent();
--- a/dom/workers/remoteworkers/RemoteWorkerChild.h
+++ b/dom/workers/remoteworkers/RemoteWorkerChild.h
@@ -18,16 +18,18 @@ namespace dom {
 
 class RemoteWorkerData;
 class WeakWorkerRef;
 class WorkerErrorReport;
 class WorkerPrivate;
 class OptionalMessagePortIdentifier;
 
 class RemoteWorkerChild final : public PRemoteWorkerChild {
+  friend class PRemoteWorkerChild;
+
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RemoteWorkerChild)
 
   RemoteWorkerChild();
 
   void ExecWorker(const RemoteWorkerData& aData);
 
   void InitializeOnWorker(WorkerPrivate* aWorkerPrivate);
--- a/dom/workers/remoteworkers/RemoteWorkerParent.h
+++ b/dom/workers/remoteworkers/RemoteWorkerParent.h
@@ -10,16 +10,18 @@
 #include "mozilla/dom/PRemoteWorkerParent.h"
 
 namespace mozilla {
 namespace dom {
 
 class RemoteWorkerController;
 
 class RemoteWorkerParent final : public PRemoteWorkerParent {
+  friend class PRemoteWorkerParent;
+
  public:
   NS_INLINE_DECL_REFCOUNTING(RemoteWorkerParent)
 
   RemoteWorkerParent();
 
   void Initialize();
 
   void SetController(RemoteWorkerController* aController);
--- a/dom/workers/sharedworkers/SharedWorkerChild.h
+++ b/dom/workers/sharedworkers/SharedWorkerChild.h
@@ -11,16 +11,18 @@
 #include "nsISupportsImpl.h"
 
 namespace mozilla {
 namespace dom {
 
 class SharedWorker;
 
 class SharedWorkerChild final : public mozilla::dom::PSharedWorkerChild {
+  friend class PSharedWorkerChild;
+
  public:
   NS_INLINE_DECL_REFCOUNTING(SharedWorkerChild)
 
   SharedWorkerChild();
 
   void SetParent(SharedWorker* aSharedWorker) { mParent = aSharedWorker; }
 
   void SendClose();
--- a/gfx/layers/ipc/APZCTreeManagerChild.h
+++ b/gfx/layers/ipc/APZCTreeManagerChild.h
@@ -14,16 +14,18 @@
 namespace mozilla {
 namespace layers {
 
 class APZInputBridgeChild;
 class RemoteCompositorSession;
 
 class APZCTreeManagerChild : public IAPZCTreeManager,
                              public PAPZCTreeManagerChild {
+  friend class PAPZCTreeManagerChild;
+
  public:
   APZCTreeManagerChild();
 
   void SetCompositorSession(RemoteCompositorSession* aSession);
   void SetInputBridge(APZInputBridgeChild* aInputBridge);
   void Destroy();
 
   void SetKeyboardMap(const KeyboardMap& aKeyboardMap) override;
--- a/gfx/layers/ipc/CompositorBridgeChild.h
+++ b/gfx/layers/ipc/CompositorBridgeChild.h
@@ -48,16 +48,18 @@ class CompositorOptions;
 class TextureClient;
 class TextureClientPool;
 struct FrameMetrics;
 
 class CompositorBridgeChild final : public PCompositorBridgeChild,
                                     public TextureForwarder {
   typedef InfallibleTArray<AsyncParentMessageData> AsyncParentMessageArray;
 
+  friend class PCompositorBridgeChild;
+
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorBridgeChild, override);
 
   explicit CompositorBridgeChild(CompositorManagerChild* aManager);
 
   /**
    * Initialize the singleton compositor bridge for a content process.
    */
--- a/gfx/layers/ipc/CompositorBridgeParent.h
+++ b/gfx/layers/ipc/CompositorBridgeParent.h
@@ -208,16 +208,17 @@ MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(
 
 class CompositorBridgeParent final : public CompositorBridgeParentBase,
                                      public CompositorController,
                                      public CompositorVsyncSchedulerOwner {
   friend class CompositorThreadHolder;
   friend class InProcessCompositorSession;
   friend class gfx::GPUProcessManager;
   friend class gfx::GPUParent;
+  friend class PCompositorBridgeParent;
 #ifdef FUZZING
   friend class mozilla::ipc::ProtocolFuzzerHelper;
 #endif
 
  public:
   NS_IMETHOD_(MozExternalRefCountType) AddRef() override {
     return CompositorBridgeParentBase::AddRef();
   }
--- a/gfx/layers/ipc/LayerTransactionParent.h
+++ b/gfx/layers/ipc/LayerTransactionParent.h
@@ -33,16 +33,18 @@ class CompositorBridgeParentBase;
 
 class LayerTransactionParent final : public PLayerTransactionParent,
                                      public CompositableParentManager,
                                      public ShmemAllocator {
   typedef InfallibleTArray<Edit> EditArray;
   typedef InfallibleTArray<OpDestroy> OpDestroyArray;
   typedef InfallibleTArray<PluginWindowData> PluginsArray;
 
+  friend class PLayerTransactionParent;
+
  public:
   LayerTransactionParent(HostLayerManager* aManager,
                          CompositorBridgeParentBase* aBridge,
                          CompositorAnimationStorage* aAnimStorage, LayersId aId,
                          TimeDuration aVsyncRate);
 
  protected:
   ~LayerTransactionParent();
--- a/gfx/layers/ipc/UiCompositorControllerChild.h
+++ b/gfx/layers/ipc/UiCompositorControllerChild.h
@@ -17,16 +17,18 @@
 
 class nsBaseWidget;
 
 namespace mozilla {
 namespace layers {
 
 class UiCompositorControllerChild final
     : protected PUiCompositorControllerChild {
+  friend class PUiCompositorControllerChild;
+
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(UiCompositorControllerChild)
 
   static RefPtr<UiCompositorControllerChild> CreateForSameProcess(
       const LayersId& aRootLayerTreeId);
   static RefPtr<UiCompositorControllerChild> CreateForGPUProcess(
       const uint64_t& aProcessToken,
       Endpoint<PUiCompositorControllerChild>&& aEndpoint);
--- a/gfx/layers/wr/WebRenderBridgeChild.h
+++ b/gfx/layers/wr/WebRenderBridgeChild.h
@@ -54,16 +54,18 @@ class ThreadSafeWeakPtrHashKey : public 
 
 typedef ThreadSafeWeakPtrHashKey<gfx::UnscaledFont> UnscaledFontHashKey;
 typedef ThreadSafeWeakPtrHashKey<gfx::ScaledFont> ScaledFontHashKey;
 
 class WebRenderBridgeChild final : public PWebRenderBridgeChild,
                                    public CompositableForwarder {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderBridgeChild, override)
 
+  friend class PWebRenderBridgeChild;
+
  public:
   explicit WebRenderBridgeChild(const wr::PipelineId& aPipelineId);
 
   void AddWebRenderParentCommand(const WebRenderParentCommand& aCmd);
 
   void UpdateResources(wr::IpcResourceUpdateQueue& aResources);
   void BeginTransaction();
   void EndTransaction(const wr::LayoutSize& aContentSize,
--- a/gfx/vr/ipc/VRChild.h
+++ b/gfx/vr/ipc/VRChild.h
@@ -17,16 +17,18 @@ namespace ipc {
 class CrashReporterHost;
 }  // namespace ipc
 namespace gfx {
 
 class VRProcessParent;
 class VRChild;
 
 class VRChild final : public PVRChild, public gfxVarReceiver {
+  friend class PVRChild;
+
  public:
   explicit VRChild(VRProcessParent* aHost);
   ~VRChild() = default;
 
   static void Destroy(UniquePtr<VRChild>&& aChild);
   void Init();
   virtual void OnVarChanged(const GfxVarUpdate& aVar) override;
 
@@ -42,9 +44,9 @@ class VRChild final : public PVRChild, p
  private:
   VRProcessParent* mHost;
   UniquePtr<ipc::CrashReporterHost> mCrashReporter;
 };
 
 }  // namespace gfx
 }  // namespace mozilla
 
-#endif  // GFX_VR_CHILD_H
\ No newline at end of file
+#endif  // GFX_VR_CHILD_H
--- a/gfx/vr/ipc/VRGPUParent.h
+++ b/gfx/vr/ipc/VRGPUParent.h
@@ -11,16 +11,18 @@
 #include "VRService.h"
 
 namespace mozilla {
 namespace gfx {
 
 class VRGPUParent final : public PVRGPUParent {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRGPUParent)
 
+  friend class PVRGPUParent;
+
  public:
   static RefPtr<VRGPUParent> CreateForGPU(Endpoint<PVRGPUParent>&& aEndpoint);
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
   bool IsClosed();
 
  protected:
   void Bind(Endpoint<PVRGPUParent>&& aEndpoint);
   virtual mozilla::ipc::IPCResult RecvStartVRService() override;
--- a/gfx/vr/ipc/VRManagerChild.h
+++ b/gfx/vr/ipc/VRManagerChild.h
@@ -27,16 +27,18 @@ class VRMockDisplay;
 namespace layers {
 class SyncObjectClient;
 }
 namespace gfx {
 class VRLayerChild;
 class VRDisplayClient;
 
 class VRManagerChild : public PVRManagerChild {
+  friend class PVRManagerChild;
+
  public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRManagerChild);
 
   static VRManagerChild* Get();
 
   // Indicate that an observer wants to receive VR events.
   void AddListener(dom::VREventObserver* aObserver);
   // Indicate that an observer should no longer receive VR events.
--- a/gfx/vr/ipc/VRManagerParent.h
+++ b/gfx/vr/ipc/VRManagerParent.h
@@ -24,16 +24,18 @@ class VRManager;
 namespace impl {
 class VRDisplayPuppet;
 class VRControllerPuppet;
 }  // namespace impl
 
 class VRManagerParent final : public PVRManagerParent {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRManagerParent);
 
+  friend class PVRManagerParent;
+
  public:
   explicit VRManagerParent(ProcessId aChildProcessId, bool aIsContentChild);
 
   static VRManagerParent* CreateSameProcess();
   static bool CreateForGPUProcess(Endpoint<PVRManagerParent>&& aEndpoint);
   static bool CreateForContent(Endpoint<PVRManagerParent>&& aEndpoint);
 
   bool IsSameProcess() const;
--- a/gfx/vr/ipc/VRParent.h
+++ b/gfx/vr/ipc/VRParent.h
@@ -14,16 +14,18 @@ namespace mozilla {
 namespace gfx {
 
 class VRService;
 class VRSystemManagerExternal;
 
 class VRParent final : public PVRParent {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VRParent);
 
+  friend class PVRParent;
+
  public:
   explicit VRParent();
 
   bool Init(base::ProcessId aParentPid, const char* aParentBuildID,
             MessageLoop* aIOLoop, IPC::Channel* aChannel);
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
   bool GetOpenVRControllerActionPath(nsCString* aPath);
   bool GetOpenVRControllerManifestPath(OpenVRControllerType aType,
@@ -53,9 +55,9 @@ class VRParent final : public PVRParent 
   nsDataHashtable<nsUint32HashKey, nsCString> mOpenVRControllerManifest;
   RefPtr<VRGPUParent> mVRGPUParent;
   DISALLOW_COPY_AND_ASSIGN(VRParent);
 };
 
 }  // namespace gfx
 }  // namespace mozilla
 
-#endif  // GFX_VR_PARENT_H
\ No newline at end of file
+#endif  // GFX_VR_PARENT_H
--- a/ipc/glue/FileDescriptorSetChild.h
+++ b/ipc/glue/FileDescriptorSetChild.h
@@ -23,16 +23,17 @@ class nsIContentChild;
 namespace ipc {
 
 class BackgroundChildImpl;
 class FileDescriptor;
 
 class FileDescriptorSetChild final : public PFileDescriptorSetChild {
   friend class BackgroundChildImpl;
   friend class mozilla::dom::nsIContentChild;
+  friend class PFileDescriptorSetChild;
 
   nsTArray<FileDescriptor> mFileDescriptors;
 
  public:
   void ForgetFileDescriptors(nsTArray<FileDescriptor>& aFileDescriptors);
 
  private:
   explicit FileDescriptorSetChild(const FileDescriptor& aFileDescriptor);
--- a/ipc/glue/FileDescriptorSetParent.h
+++ b/ipc/glue/FileDescriptorSetParent.h
@@ -23,16 +23,17 @@ class nsIContentParent;
 namespace ipc {
 
 class BackgroundParentImpl;
 class FileDescriptor;
 
 class FileDescriptorSetParent final : public PFileDescriptorSetParent {
   friend class BackgroundParentImpl;
   friend class mozilla::dom::nsIContentParent;
+  friend class PFileDescriptorSetParent;
 
   nsTArray<FileDescriptor> mFileDescriptors;
 
  public:
   void ForgetFileDescriptors(nsTArray<FileDescriptor>& aFileDescriptors);
 
  private:
   explicit FileDescriptorSetParent(const FileDescriptor& aFileDescriptor);
--- a/ipc/glue/InProcessChild.h
+++ b/ipc/glue/InProcessChild.h
@@ -26,16 +26,17 @@ class InProcessParent;
  *
  * The `PInProcess` actor should be used as an alternate manager to `PContent`
  * for async actors which want to communicate uniformly between Content->Chrome
  * and Chrome->Chrome situations.
  */
 class InProcessChild : public PInProcessChild {
  public:
   friend class InProcessParent;
+  friend class PInProcessChild;
 
   NS_INLINE_DECL_REFCOUNTING(InProcessChild)
 
   // Get the singleton instance of this actor.
   static InProcessChild* Singleton();
 
   // Get the parent side of the in-process child actor |aActor|. If |aActor| is
   // not an in-process actor, or is not connected, this method will return
--- a/ipc/glue/InProcessParent.h
+++ b/ipc/glue/InProcessParent.h
@@ -26,16 +26,17 @@ class InProcessChild;
  *
  * The `PInProcess` actor should be used as an alternate manager to `PContent`
  * for async actors which want to communicate uniformly between Content->Chrome
  * and Chrome->Chrome situations.
  */
 class InProcessParent : public nsIObserver, public PInProcessParent {
  public:
   friend class InProcessChild;
+  friend class PInProcessParent;
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
   // Get the singleton instance of this actor.
   static InProcessParent* Singleton();
 
   // Get the child side of the in-process child actor |aActor|. If |aActor| is
new file mode 100644
--- /dev/null
+++ b/ipc/ipdl/ipdl/direct_call.py
@@ -0,0 +1,329 @@
+# 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/.
+
+
+# Our long term goal is to burn this list down, so new entries should be added
+# extremely sparingly and only with a very good reason! You must have an IPC
+# peer's r+ to add something new!
+
+# {(Protocol, side): (Class, HeaderFile)}
+DIRECT_CALL_OVERRIDES = {
+    ("PAPZ", "parent"): (
+        "RemoteContentController", "mozilla/layers/RemoteContentController.h"
+    ),
+
+    ("PBackgroundMutableFile", "parent"): (
+        "BackgroundMutableFileParentBase", "mozilla/dom/filehandle/ActorsParent.h"
+    ),
+
+    ("PBrowser", "parent"): ("TabParent", "mozilla/dom/TabParent.h"),
+
+    ("PChromiumCDM", "parent"): ("ChromiumCDMParent", "ChromiumCDMParent.h"),
+
+    ("PCompositorBridge", "parent"): (
+        "CompositorBridgeParentBase", "mozilla/layers/CompositorBridgeParent.h"
+    ),
+
+    ("PContentPermissionRequest", "child"): (
+        "RemotePermissionRequest", "nsContentPermissionHelper.h"
+    ),
+
+    ("PFileSystemRequest", "child"): (
+        "FileSystemTaskChildBase", "mozilla/dom/FileSystemTaskBase.h"
+    ),
+
+    ("PGMP", "child"): ("GMPChild", "GMPChild.h"),
+    ("PGMP", "parent"): ("GMPParent", "GMPParent.h"),
+    ("PGMPContent", "child"): ("GMPContentChild", "GMPContentChild.h"),
+    ("PGMPStorage", "child"): ("GMPStorageChild", "GMPStorageChild.h"),
+    ("PGMPTimer", "child"): ("GMPTimerChild", "GMPTimerChild.h"),
+    ("PGMPTimer", "parent"): ("GMPTimerParent", "GMPTimerParent.h"),
+    ("PGMPVideoEncoder", "child"): ("GMPVideoEncoderChild", "GMPVideoEncoderChild.h"),
+    ("PGMPVideoDecoder", "child"): ("GMPVideoDecoderChild", "GMPVideoDecoderChild.h"),
+
+    ("PIPCBlobInputStream", "child"): (
+        "mozilla::dom::IPCBlobInputStreamChild", "mozilla/dom/ipc/IPCBlobInputStreamChild.h"
+    ),
+    ("PIPCBlobInputStream", "parent"): (
+        "mozilla::dom::IPCBlobInputStreamParent", "mozilla/dom/ipc/IPCBlobInputStreamParent.h"
+    ),
+
+    ("PLoginReputation", "parent"): ("LoginReputationParent", "mozilla/LoginReputationIPC.h"),
+
+    ("PMedia", "child"): ("Child", "mozilla/media/MediaChild.h"),
+
+    ("PPendingIPCBlob", "child"): ("PendingIPCBlobChild", "mozilla/dom/ipc/PendingIPCBlobChild.h"),
+    ("PPendingIPCBlob", "parent"): (
+        "mozilla::dom::PendingIPCBlobParent", "mozilla/dom/ipc/PendingIPCBlobParent.h"
+    ),
+
+    ("PPresentationRequest", "child"): (
+        "PresentationRequestChild", "mozilla/dom/PresentationChild.h"
+    ),
+    ("PPresentationRequest", "parent"): (
+        "PresentationRequestParent", "mozilla/dom/PresentationParent.h"
+    ),
+
+    ("PPrinting", "child"): ("nsPrintingProxy", "nsPrintingProxy.h"),
+    ("PPrinting", "parent"): ("PrintingParent", "mozilla/embedding/printingui/PrintingParent.h"),
+
+    ("PPSMContentDownloader", "child"): (
+        "PSMContentDownloaderChild", "mozilla/psm/PSMContentListener.h"
+    ),
+    ("PPSMContentDownloader", "parent"): (
+        "PSMContentDownloaderParent", "mozilla/psm/PSMContentListener.h"
+    ),
+
+    ("PRemoteSpellcheckEngine", "child"): (
+        "RemoteSpellcheckEngineChild", "mozilla/RemoteSpellCheckEngineChild.h"
+    ),
+    ("PRemoteSpellcheckEngine", "parent"): (
+        "RemoteSpellcheckEngineParent", "mozilla/RemoteSpellCheckEngineParent.h"
+    ),
+
+    ("PScriptCache", "child"): ("ScriptCacheChild", "mozilla/loader/ScriptCacheActors.h"),
+    ("PScriptCache", "parent"): ("ScriptCacheParent", "mozilla/loader/ScriptCacheActors.h"),
+
+    ("PTCPServerSocket", "child"): (
+        "mozilla::dom::TCPServerSocketChild", "mozilla/dom/network/TCPServerSocketChild.h"
+    ),
+    ("PTCPServerSocket", "parent"): (
+        "mozilla::dom::TCPServerSocketParent", "mozilla/dom/network/TCPServerSocketParent.h"
+    ),
+    ("PTCPSocket", "child"): (
+        "mozilla::dom::TCPSocketChild", "mozilla/dom/network/TCPSocketChild.h"
+    ),
+    ("PTCPSocket", "parent"): (
+        "mozilla::dom::TCPSocketParent", "mozilla/dom/network/TCPSocketParent.h"
+    ),
+
+    ("PTemporaryIPCBlob", "child"): (
+        "mozilla::dom::TemporaryIPCBlobChild", "mozilla/dom/ipc/TemporaryIPCBlobChild.h"
+    ),
+    ("PTemporaryIPCBlob", "parent"): (
+        "mozilla::dom::TemporaryIPCBlobParent", "mozilla/dom/ipc/TemporaryIPCBlobParent.h"
+    ),
+
+    ("PTestShellCommand", "parent"): ("TestShellCommandParent", "mozilla/ipc/TestShellParent.h"),
+
+    ("PTransportProvider", "child"): (
+        "TransportProviderChild", "mozilla/net/IPCTransportProvider.h"
+    ),
+    ("PTransportProvider", "parent"): (
+        "TransportProviderParent", "mozilla/net/IPCTransportProvider.h"
+    ),
+
+    ("PUDPSocket", "child"): (
+        "mozilla::dom::UDPSocketChild", "mozilla/dom/network/UDPSocketChild.h"
+    ),
+    ("PUDPSocket", "parent"): (
+        "mozilla::dom::UDPSocketParent", "mozilla/dom/network/UDPSocketParent.h"
+    ),
+
+    ("PURLClassifierLocal", "child"): (
+        "URLClassifierLocalChild", "mozilla/dom/URLClassifierChild.h"
+    ),
+    ("PURLClassifierLocal", "parent"): (
+        "URLClassifierLocalParent", "mozilla/dom/URLClassifierParent.h"
+    ),
+
+    ("PVR", "child"): ("VRChild", "VRChild.h"),
+    ("PVR", "parent"): ("VRParent", "VRParent.h"),
+    ("PVRGPU", "child"): ("VRGPUChild", "VRGPUChild.h"),
+    ("PVRGPU", "parent"): ("VRGPUParent", "VRGPUParent.h"),
+    ("PVRLayer", "child"): ("VRLayerChild", "VRLayerChild.h"),
+    ("PVRManager", "child"): ("VRManagerChild", "VRManagerChild.h"),
+    ("PVRManager", "parent"): ("VRManagerParent", "VRManagerParent.h"),
+
+    ("PWebSocket", "child"): ("WebSocketChannelChild", "mozilla/net/WebSocketChannelChild.h"),
+    ("PWebSocket", "parent"): ("WebSocketChannelParent", "mozilla/net/WebSocketChannelParent.h"),
+}
+
+# Our long term goal is to burn this list down, so new entries should be added
+# extremely sparingly and only with a very good reason! You must have an IPC
+# peer's r+ to add something new!
+
+# set() of (Protocol, side)
+VIRTUAL_CALL_CLASSES = set([
+    # Defined as a strange template
+    ("PJavaScript", "child"),
+    ("PJavaScript", "parent"),
+    ("PMedia", "parent"),
+    ("PTexture", "parent"),
+
+    # Defined in a .cpp
+    ("PAsmJSCacheEntry", "child"),
+    ("PAsmJSCacheEntry", "parent"),
+    ("PBackgroundFileHandle", "parent"),
+    ("PBackgroundFileRequest", "parent"),
+    ("PBackgroundIDBCursor", "parent"),
+    ("PBackgroundIDBDatabase", "parent"),
+    ("PBackgroundIDBDatabaseFile", "child"),
+    ("PBackgroundIDBDatabaseFile", "parent"),
+    ("PBackgroundIDBDatabaseRequest", "parent"),
+    ("PBackgroundIDBFactory", "parent"),
+    ("PBackgroundIDBFactoryRequest", "parent"),
+    ("PBackgroundIDBRequest", "parent"),
+    ("PBackgroundIDBTransaction", "parent"),
+    ("PBackgroundIDBVersionChangeTransaction", "parent"),
+    ("PBackgroundIndexedDBUtils", "parent"),
+    ("PBackgroundLSDatabase", "parent"),
+    ("PBackgroundLSObserver", "parent"),
+    ("PBackgroundLSRequest", "parent"),
+    ("PBackgroundLSSimpleRequest", "parent"),
+    ("PBackgroundLSSnapshot", "parent"),
+    ("PBackgroundSDBConnection", "parent"),
+    ("PBackgroundSDBRequest", "parent"),
+    ("PBackgroundTest", "child"),
+    ("PBackgroundTest", "parent"),
+    ("PChildToParentStream", "child"),
+    ("PChildToParentStream", "parent"),
+    ("PContentPermissionRequest", "parent"),
+    ("PCycleCollectWithLogs", "child"),
+    ("PCycleCollectWithLogs", "parent"),
+    ("PHal", "child"),
+    ("PHal", "parent"),
+    ("PIndexedDBPermissionRequest", "parent"),
+    ("PParentToChildStream", "child"),
+    ("PParentToChildStream", "parent"),
+    ("PProcessHangMonitor", "child"),
+    ("PProcessHangMonitor", "parent"),
+    ("PQuota", "parent"),
+    ("PQuotaRequest", "parent"),
+    ("PQuotaUsageRequest", "parent"),
+    ("PSimpleChannel", "child"),
+    ("PTexture", "child"),
+
+    # .h is not exported
+    ("PBackground", "child"),
+    ("PBackground", "parent"),
+    ("PBackgroundFileHandle", "child"),
+    ("PBackgroundFileRequest", "child"),
+    ("PBackgroundIDBCursor", "child"),
+    ("PBackgroundIDBDatabase", "child"),
+    ("PBackgroundIDBDatabaseRequest", "child"),
+    ("PBackgroundIDBFactory", "child"),
+    ("PBackgroundIDBFactoryRequest", "child"),
+    ("PBackgroundIDBRequest", "child"),
+    ("PBackgroundIDBTransaction", "child"),
+    ("PBackgroundIDBVersionChangeTransaction", "child"),
+    ("PBackgroundIndexedDBUtils", "child"),
+    ("PBackgroundLSDatabase", "child"),
+    ("PBackgroundLSObserver", "child"),
+    ("PBackgroundLSRequest", "child"),
+    ("PBackgroundLSSimpleRequest", "child"),
+    ("PBackgroundLSSnapshot", "child"),
+    ("PBackgroundMutableFile", "child"),
+    ("PBackgroundSDBConnection", "child"),
+    ("PBackgroundSDBRequest", "child"),
+    ("PBroadcastChannel", "child"),
+    ("PBroadcastChannel", "parent"),
+    ("PChromiumCDM", "child"),
+    ("PClientHandle", "child"),
+    ("PClientHandle", "parent"),
+    ("PClientHandleOp", "child"),
+    ("PClientHandleOp", "parent"),
+    ("PClientManager", "child"),
+    ("PClientManager", "parent"),
+    ("PClientManagerOp", "child"),
+    ("PClientManagerOp", "parent"),
+    ("PClientNavigateOp", "child"),
+    ("PClientNavigateOp", "parent"),
+    ("PClientOpenWindowOp", "child"),
+    ("PClientOpenWindowOp", "parent"),
+    ("PClientSource", "child"),
+    ("PClientSource", "parent"),
+    ("PClientSourceOp", "child"),
+    ("PClientSourceOp", "parent"),
+    ("PColorPicker", "child"),
+    ("PColorPicker", "parent"),
+    ("PDataChannel", "child"),
+    ("PFileChannel", "child"),
+    ("PFilePicker", "child"),
+    ("PFunctionBroker", "child"),
+    ("PFunctionBroker", "parent"),
+    ("PHandlerService", "child"),
+    ("PHandlerService", "parent"),
+    ("PPluginBackgroundDestroyer", "child"),
+    ("PPluginBackgroundDestroyer", "parent"),
+    ("PPrintProgressDialog", "child"),
+    ("PPrintProgressDialog", "parent"),
+    ("PPrintSettingsDialog", "child"),
+    ("PPrintSettingsDialog", "parent"),
+    ("PQuota", "child"),
+    ("PQuotaRequest", "child"),
+    ("PQuotaUsageRequest", "child"),
+    ("PRemoteVideoDecoder", "child"),
+    ("PRemoteVideoDecoder", "parent"),
+    ("PServiceWorker", "child"),
+    ("PServiceWorker", "parent"),
+    ("PServiceWorkerContainer", "child"),
+    ("PServiceWorkerContainer", "parent"),
+    ("PServiceWorkerRegistration", "child"),
+    ("PServiceWorkerRegistration", "parent"),
+    ("PServiceWorkerUpdater", "child"),
+    ("PServiceWorkerUpdater", "parent"),
+    ("PVideoDecoder", "child"),
+    ("PVideoDecoder", "parent"),
+    ("PVRLayer", "parent"),
+    ("PWebBrowserPersistResources", "child"),
+    ("PWebBrowserPersistResources", "parent"),
+    ("PWebBrowserPersistSerialize", "child"),
+    ("PWebBrowserPersistSerialize", "parent"),
+    ("PWebrtcGlobal", "child"),
+    ("PWebrtcGlobal", "parent"),
+
+    # .h is only exported on some platforms/configs
+    ("PCameras", "child"),
+    ("PCameras", "parent"),
+    ("PCompositorWidget", "child"),
+    ("PCompositorWidget", "parent"),
+    ("PDocAccessible", "child"),
+    ("PDocAccessible", "parent"),
+    ("PPluginSurface", "parent"),
+    ("PPluginWidget", "child"),
+    ("PPluginWidget", "parent"),
+    ("PProfiler", "child"),
+    ("PProfiler", "parent"),
+    ("PSpeechSynthesisRequest", "child"),
+    ("PSpeechSynthesisRequest", "parent"),
+    ("PStunAddrsRequest", "child"),
+    ("PStunAddrsRequest", "parent"),
+    ("PWebrtcProxyChannel", "child"),
+    ("PWebrtcProxyChannel", "parent"),
+
+    # .h includes something that's a LOCAL_INCLUDE
+    ("PBackgroundLocalStorageCache", "child"),
+    ("PBackgroundLocalStorageCache", "parent"),
+    ("PBackgroundStorage", "child"),
+    ("PBackgroundStorage", "parent"),
+    ("PBrowserStream", "parent"),
+    ("PExternalHelperApp", "parent"),
+    ("PFTPChannel", "child"),
+    ("PFTPChannel", "parent"),
+    ("PHttpChannel", "child"),
+    ("PHttpChannel", "parent"),
+    ("PWyciwygChannel", "child"),
+
+    # bug 1513911
+    ("PIndexedDBPermissionRequest", "child"),
+
+    # Recv* methods are MOZ_CAN_RUN_SCRIPT and OnMessageReceived is not, so
+    # it's not allowed to call them.
+    ("PBrowser", "child"),
+
+    # can't be included safely for compilation error reasons
+    ("PGMPContent", "parent"),
+    ("PGMPService", "child"),
+    ("PGMPService", "parent"),
+    ("PGMPStorage", "parent"),
+    ("PGMPVideoDecoder", "parent"),
+    ("PGMPVideoEncoder", "parent"),
+    ("PWebRenderBridge", "parent"),
+
+    # Not actually subclassed
+    ("PLoginReputation", "child"),
+    ("PPluginSurface", "child"),
+    ("PTestShellCommand", "child"),
+])
--- a/ipc/ipdl/ipdl/lower.py
+++ b/ipc/ipdl/ipdl/lower.py
@@ -4,18 +4,20 @@
 
 import re
 from copy import deepcopy
 from collections import OrderedDict
 
 import ipdl.ast
 import ipdl.builtin
 from ipdl.cxx.ast import *
+from ipdl.direct_call import VIRTUAL_CALL_CLASSES, DIRECT_CALL_OVERRIDES
 from ipdl.type import ActorType, UnionType, TypeVisitor, builtinHeaderIncludes
 
+
 # -----------------------------------------------------------------------------
 # "Public" interface to lowering
 ##
 
 
 class LowerToCxx:
     def lower(self, tu, segmentcapacitydict):
         '''returns |[ header: File ], [ cpp : File ]| representing the
@@ -2946,16 +2948,28 @@ class _GenerateProtocolActorCode(ipdl.as
         actortype = ActorType(tu.protocol.decl.type)
         traitsdecl, traitsdefn = _ParamTraits.actorPickling(actortype, self.side)
 
         self.hdrfile.addthings(
             [traitsdecl, Whitespace.NL] + _includeGuardEnd(hf)
         )
 
         # make the .cpp file
+        if (self.protocol.name, self.side) not in VIRTUAL_CALL_CLASSES:
+            if (self.protocol.name, self.side) in DIRECT_CALL_OVERRIDES:
+                (_, header_file) = DIRECT_CALL_OVERRIDES[self.protocol.name, self.side]
+            else:
+                assert self.protocol.name.startswith("P")
+                header_file = "{}/{}{}.h".format(
+                    "/".join(n.name for n in self.protocol.namespaces),
+                    self.protocol.name[1:],
+                    self.side.capitalize(),
+                )
+            self.externalIncludes.add(header_file)
+
         cf.addthings([
             _DISCLAIMER,
             Whitespace.NL,
             CppDirective(
                 'include',
                 '"' + _protocolHeaderName(self.protocol, self.side) + '.h"')]
             + setToIncludes(self.externalIncludes))
 
@@ -3729,17 +3743,34 @@ class _GenerateProtocolActorCode(ipdl.as
     # -------------------------------------------------------------------------
     # The next few functions are the crux of the IPDL code generator.
     # They generate code for all the nasty work of message
     # serialization/deserialization and dispatching handlers for
     # received messages.
     ##
 
     def thisCall(self, function, args):
-        return ExprCall(ExprVar(function), args=args)
+        # If we're a direct call type, we cast `this` to the derived class
+        # before performing the call. Otherwise just emit the virtual call.
+        if (self.protocol.name, self.side) in VIRTUAL_CALL_CLASSES:
+            return ExprCall(ExprVar(function), args=args)
+
+        if (self.protocol.name, self.side) in DIRECT_CALL_OVERRIDES:
+            (class_name, _) = DIRECT_CALL_OVERRIDES[self.protocol.name, self.side]
+        else:
+            assert self.protocol.name.startswith("P")
+            class_name = "{}{}".format(self.protocol.name[1:], self.side.capitalize())
+        return ExprCall(
+            ExprSelect(
+                ExprCast(ExprVar("this"), Type(class_name, ptr=True), static=True),
+                "->",
+                ExprVar(function)
+            ),
+            args=args
+        )
 
     def visitMessageDecl(self, md):
         isctor = md.decl.type.isCtor()
         isdtor = md.decl.type.isDtor()
         decltype = md.decl.type
         sendmethod = None
         movesendmethod = None
         promisesendmethod = None
--- a/ipc/testshell/TestShellParent.h
+++ b/ipc/testshell/TestShellParent.h
@@ -17,28 +17,32 @@
 
 namespace mozilla {
 
 namespace ipc {
 
 class TestShellCommandParent;
 
 class TestShellParent : public PTestShellParent {
+  friend class PTestShellParent;
+
  public:
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   PTestShellCommandParent* AllocPTestShellCommandParent(
       const nsString& aCommand) override;
 
   bool DeallocPTestShellCommandParent(PTestShellCommandParent* aActor) override;
 
   bool CommandDone(TestShellCommandParent* aActor, const nsString& aResponse);
 };
 
 class TestShellCommandParent : public PTestShellCommandParent {
+  friend class PTestShellCommandParent;
+
  public:
   TestShellCommandParent() {}
 
   bool SetCallback(JSContext* aCx, const JS::Value& aCallback);
 
   bool RunCallback(const nsString& aResponse);
 
   void ReleaseCallback();
--- a/js/xpconnect/loader/ScriptCacheActors.h
+++ b/js/xpconnect/loader/ScriptCacheActors.h
@@ -16,16 +16,18 @@ class FileDescriptor;
 }
 
 namespace loader {
 
 using mozilla::ipc::FileDescriptor;
 using mozilla::ipc::IPCResult;
 
 class ScriptCacheParent final : public PScriptCacheParent {
+  friend class PScriptCacheParent;
+
  public:
   explicit ScriptCacheParent(bool wantCacheData)
       : mWantCacheData(wantCacheData) {}
 
  protected:
   virtual IPCResult Recv__delete__(nsTArray<ScriptData>&& scripts) override;
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
--- a/layout/ipc/VsyncChild.h
+++ b/layout/ipc/VsyncChild.h
@@ -24,16 +24,17 @@ namespace layout {
 // The PVsyncChild actor receives a vsync event from the main process and
 // delivers it to the child process. Currently this is restricted to the main
 // thread only. The actor will stay alive until the process dies or its
 // PVsyncParent actor dies.
 class VsyncChild final : public PVsyncChild {
   NS_INLINE_DECL_REFCOUNTING(VsyncChild)
 
   friend class mozilla::ipc::BackgroundChildImpl;
+  friend class PVsyncChild;
 
  public:
   // Hide the SendObserve/SendUnobserve in PVsyncChild. We add an flag
   // mObservingVsync to handle the race problem of unobserving vsync event.
   bool SendObserve();
   bool SendUnobserve();
 
   // Bind a VsyncObserver into VsyncChild after ipc channel connected.
--- a/layout/ipc/VsyncParent.h
+++ b/layout/ipc/VsyncParent.h
@@ -22,16 +22,17 @@ class BackgroundParentImpl;
 
 namespace layout {
 
 // Use PBackground thread in the main process to send vsync notifications to
 // content process. This actor will be released when its parent protocol calls
 // DeallocPVsyncParent().
 class VsyncParent final : public PVsyncParent, public VsyncObserver {
   friend class mozilla::ipc::BackgroundParentImpl;
+  friend class PVsyncParent;
 
  private:
   static already_AddRefed<VsyncParent> Create();
 
   VsyncParent();
   virtual ~VsyncParent();
 
   virtual bool NotifyVsync(const VsyncEvent& aVsync) override;
--- a/media/mtransport/ipc/StunAddrsRequestChild.h
+++ b/media/mtransport/ipc/StunAddrsRequestChild.h
@@ -22,16 +22,18 @@ class StunAddrsListener {
  protected:
   virtual ~StunAddrsListener() {}
 
   ThreadSafeAutoRefCnt mRefCnt;
   NS_DECL_OWNINGTHREAD
 };
 
 class StunAddrsRequestChild final : public PStunAddrsRequestChild {
+  friend class PStunAddrsRequestChild;
+
  public:
   explicit StunAddrsRequestChild(StunAddrsListener* listener,
                                  nsIEventTarget* mainThreadEventTarget);
 
   NS_IMETHOD_(MozExternalRefCountType) AddRef();
   NS_IMETHOD_(MozExternalRefCountType) Release();
 
   // Not sure why AddIPDLReference & ReleaseIPDLReference don't come
--- a/media/mtransport/ipc/StunAddrsRequestParent.h
+++ b/media/mtransport/ipc/StunAddrsRequestParent.h
@@ -6,16 +6,18 @@
 #define mozilla_net_StunAddrsRequestParent_h
 
 #include "mozilla/net/PStunAddrsRequestParent.h"
 
 namespace mozilla {
 namespace net {
 
 class StunAddrsRequestParent : public PStunAddrsRequestParent {
+  friend class PStunAddrsRequestParent;
+
  public:
   StunAddrsRequestParent();
 
   NS_IMETHOD_(MozExternalRefCountType) AddRef();
   NS_IMETHOD_(MozExternalRefCountType) Release();
 
   mozilla::ipc::IPCResult Recv__delete__() override;
 
--- a/netwerk/cookie/CookieServiceChild.h
+++ b/netwerk/cookie/CookieServiceChild.h
@@ -26,16 +26,18 @@ namespace mozilla {
 namespace net {
 class CookieStruct;
 
 class CookieServiceChild : public PCookieServiceChild,
                            public nsICookieService,
                            public nsIObserver,
                            public nsITimerCallback,
                            public nsSupportsWeakReference {
+  friend class PCookieServiceChild;
+
  public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSICOOKIESERVICE
   NS_DECL_NSIOBSERVER
   NS_DECL_NSITIMERCALLBACK
 
   typedef nsTArray<RefPtr<nsCookie>> CookiesList;
   typedef nsClassHashtable<nsCookieKey, CookiesList> CookiesMap;
--- a/netwerk/cookie/CookieServiceParent.h
+++ b/netwerk/cookie/CookieServiceParent.h
@@ -14,16 +14,18 @@ class nsCookieService;
 namespace mozilla {
 class OriginAttributes;
 }
 
 namespace mozilla {
 namespace net {
 
 class CookieServiceParent : public PCookieServiceParent {
+  friend class PCookieServiceParent;
+
  public:
   CookieServiceParent();
   virtual ~CookieServiceParent() = default;
 
   void TrackCookieLoad(nsIChannel *aChannel);
 
   void RemoveBatchDeletedCookies(nsIArray *aCookieList);
 
--- a/netwerk/dns/DNSRequestChild.h
+++ b/netwerk/dns/DNSRequestChild.h
@@ -13,16 +13,18 @@
 #include "nsIDNSListener.h"
 #include "nsIDNSByTypeRecord.h"
 #include "nsIEventTarget.h"
 
 namespace mozilla {
 namespace net {
 
 class DNSRequestChild final : public PDNSRequestChild, public nsICancelable {
+  friend class PDNSRequestChild;
+
  public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSICANCELABLE
 
   DNSRequestChild(const nsACString& aHost, const uint16_t& aType,
                   const OriginAttributes& aOriginAttributes,
                   const uint32_t& aFlags, nsIDNSListener* aListener,
                   nsIEventTarget* target);
--- a/netwerk/ipc/NeckoChild.h
+++ b/netwerk/ipc/NeckoChild.h
@@ -11,16 +11,18 @@
 #include "mozilla/net/PNeckoChild.h"
 #include "mozilla/net/NeckoCommon.h"
 
 namespace mozilla {
 namespace net {
 
 // Header file contents
 class NeckoChild : public PNeckoChild {
+  friend class PNeckoChild;
+
  public:
   NeckoChild() = default;
   virtual ~NeckoChild();
 
   static void InitNeckoChild();
 
  protected:
   virtual PHttpChannelChild* AllocPHttpChannelChild(
--- a/netwerk/ipc/NeckoParent.h
+++ b/netwerk/ipc/NeckoParent.h
@@ -22,16 +22,18 @@ namespace net {
 enum PBOverrideStatus {
   kPBOverride_Unset = 0,
   kPBOverride_Private,
   kPBOverride_NotPrivate
 };
 
 // Header file contents
 class NeckoParent : public PNeckoParent {
+  friend class PNeckoParent;
+
  public:
   NeckoParent();
   virtual ~NeckoParent() = default;
 
   MOZ_MUST_USE
   static const char* GetValidatedOriginAttributes(
       const SerializedLoadContext& aSerialized, PContentParent* aBrowser,
       nsIPrincipal* aRequestingPrincipal, mozilla::OriginAttributes& aAttrs);
--- a/netwerk/protocol/http/HttpBackgroundChannelChild.h
+++ b/netwerk/protocol/http/HttpBackgroundChannelChild.h
@@ -17,16 +17,17 @@ using mozilla::ipc::IPCResult;
 
 namespace mozilla {
 namespace net {
 
 class HttpChannelChild;
 
 class HttpBackgroundChannelChild final : public PHttpBackgroundChannelChild {
   friend class BackgroundChannelCreateCallback;
+  friend class PHttpBackgroundChannelChild;
 
  public:
   explicit HttpBackgroundChannelChild();
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(HttpBackgroundChannelChild)
 
   // Associate this background channel with a HttpChannelChild and
   // initiate the createion of the PBackground IPC channel.
--- a/netwerk/protocol/http/TrackingDummyChannelChild.h
+++ b/netwerk/protocol/http/TrackingDummyChannelChild.h
@@ -14,16 +14,18 @@
 
 class nsIHttpChannel;
 class nsIURI;
 
 namespace mozilla {
 namespace net {
 
 class TrackingDummyChannelChild final : public PTrackingDummyChannelChild {
+  friend class PTrackingDummyChannelChild;
+
  public:
   static bool Create(nsIHttpChannel* aChannel, nsIURI* aURI,
                      const std::function<void(bool)>& aCallback);
 
   // Used by PNeckoChild only!
   TrackingDummyChannelChild();
   ~TrackingDummyChannelChild();
 
--- a/netwerk/protocol/websocket/WebSocketChannelChild.h
+++ b/netwerk/protocol/websocket/WebSocketChannelChild.h
@@ -17,16 +17,18 @@ namespace mozilla {
 namespace net {
 
 class ChannelEvent;
 class ChannelEventQueue;
 
 class WebSocketChannelChild final : public BaseWebSocketChannel,
                                     public PWebSocketChild,
                                     public NeckoTargetHolder {
+  friend class PWebSocketChild;
+
  public:
   explicit WebSocketChannelChild(bool aSecure);
 
   NS_DECL_THREADSAFE_ISUPPORTS
 
   // nsIWebSocketChannel methods BaseWebSocketChannel didn't implement for us
   //
   NS_IMETHOD AsyncOpen(nsIURI* aURI, const nsACString& aOrigin,
--- a/netwerk/protocol/websocket/WebSocketChannelParent.h
+++ b/netwerk/protocol/websocket/WebSocketChannelParent.h
@@ -19,16 +19,18 @@
 class nsIAuthPromptProvider;
 
 namespace mozilla {
 namespace net {
 
 class WebSocketChannelParent : public PWebSocketParent,
                                public nsIWebSocketListener,
                                public nsIInterfaceRequestor {
+  friend class PWebSocketParent;
+
   ~WebSocketChannelParent() = default;
 
  public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIWEBSOCKETLISTENER
   NS_DECL_NSIINTERFACEREQUESTOR
 
   WebSocketChannelParent(nsIAuthPromptProvider* aAuthProvider,
--- a/netwerk/protocol/websocket/WebSocketEventListenerParent.h
+++ b/netwerk/protocol/websocket/WebSocketEventListenerParent.h
@@ -12,16 +12,18 @@
 
 namespace mozilla {
 namespace net {
 
 class WebSocketEventService;
 
 class WebSocketEventListenerParent final : public PWebSocketEventListenerParent,
                                            public nsIWebSocketEventListener {
+  friend class PWebSocketEventListenerParent;
+
  public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIWEBSOCKETEVENTLISTENER
 
   explicit WebSocketEventListenerParent(uint64_t aInnerWindowID);
 
  private:
   ~WebSocketEventListenerParent();
--- a/netwerk/protocol/wyciwyg/WyciwygChannelParent.h
+++ b/netwerk/protocol/wyciwyg/WyciwygChannelParent.h
@@ -18,16 +18,18 @@ namespace dom {
 class PBrowserParent;
 }  // namespace dom
 
 namespace net {
 
 class WyciwygChannelParent : public PWyciwygChannelParent,
                              public nsIStreamListener,
                              public nsIInterfaceRequestor {
+  friend class PWyciwygChannelParent;
+
  public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSIINTERFACEREQUESTOR
 
   WyciwygChannelParent();
 
--- a/toolkit/components/extensions/webrequest/StreamFilterChild.h
+++ b/toolkit/components/extensions/webrequest/StreamFilterChild.h
@@ -22,16 +22,17 @@ namespace extensions {
 using mozilla::dom::StreamFilterStatus;
 using mozilla::ipc::IPCResult;
 
 class StreamFilter;
 
 class StreamFilterChild final : public PStreamFilterChild,
                                 public StreamFilterBase {
   friend class StreamFilter;
+  friend class PStreamFilterChild;
 
  public:
   NS_INLINE_DECL_REFCOUNTING(StreamFilterChild)
 
   StreamFilterChild() : mState(State::Uninitialized), mReceivedOnStop(false) {}
 
   enum class State {
     // Uninitialized, waiting for constructor response from parent.
--- a/toolkit/components/extensions/webrequest/StreamFilterParent.h
+++ b/toolkit/components/extensions/webrequest/StreamFilterParent.h
@@ -39,16 +39,18 @@ namespace extensions {
 using namespace mozilla::dom;
 using mozilla::ipc::IPCResult;
 
 class StreamFilterParent final : public PStreamFilterParent,
                                  public nsIStreamListener,
                                  public nsIThreadRetargetableStreamListener,
                                  public nsIRequest,
                                  public StreamFilterBase {
+  friend class PStreamFilterParent;
+
  public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSISTREAMLISTENER
   NS_DECL_NSIREQUEST
   NS_DECL_NSIREQUESTOBSERVER
   NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER
 
   StreamFilterParent();
--- a/toolkit/components/printingui/ipc/nsPrintingProxy.h
+++ b/toolkit/components/printingui/ipc/nsPrintingProxy.h
@@ -12,16 +12,18 @@
 namespace mozilla {
 namespace layout {
 class PRemotePrintJobChild;
 }
 }  // namespace mozilla
 
 class nsPrintingProxy final : public nsIPrintingPromptService,
                               public mozilla::embedding::PPrintingChild {
+  friend class mozilla::embedding::PPrintingChild;
+
  public:
   static already_AddRefed<nsPrintingProxy> GetInstance();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPRINTINGPROMPTSERVICE
 
   /**
    * Used to proxy nsIPrintSettings.savePrintSettingsToPrefs calls to the