diff --git a/dom/ipc/ContentChild.cpp b/dom/ipc/ContentChild.cpp index 315a5df59f9..bee0f04e08e 100644 --- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -92,6 +92,10 @@ #define getpid _getpid #endif +#ifdef MOZ_X11 +#include "mozilla/X11Util.h" +#endif + #ifdef ACCESSIBILITY #include "nsIAccessibilityService.h" #endif @@ -352,6 +356,13 @@ ContentChild::Init(MessageLoop* aIOLoop, Open(aChannel, aParentHandle, aIOLoop); sSingleton = this; +#ifdef MOZ_X11 + // Send the parent our X socket to act as a proxy reference for our X + // resources. + int xSocketFd = ConnectionNumber(DefaultXDisplay()); + SendBackUpXResources(FileDescriptor(xSocketFd)); +#endif + #ifdef MOZ_CRASHREPORTER SendPCrashReporterConstructor(CrashReporter::CurrentThreadId(), XRE_GetProcessType()); diff --git a/dom/ipc/ContentParent.cpp b/dom/ipc/ContentParent.cpp index 3dbe4da4bc5..34b37f70b2f 100644 --- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -3258,6 +3258,22 @@ ContentParent::RecvRemoveIdleObserver(const uint64_t& aObserver, const uint32_t& return true; } +bool +ContentParent::RecvBackUpXResources(const FileDescriptor& aXSocketFd) +{ +#ifndef MOZ_X11 + NS_RUNTIMEABORT("This message only makes sense on X11 platforms"); +#else + NS_ABORT_IF_FALSE(0 > mChildXSocketFdDup.get(), + "Already backed up X resources??"); + mChildXSocketFdDup.forget(); + if (aXSocketFd.IsValid()) { + mChildXSocketFdDup.reset(aXSocketFd.PlatformHandle()); + } +#endif + return true; +} + } // namespace dom } // namespace mozilla diff --git a/dom/ipc/ContentParent.h b/dom/ipc/ContentParent.h index e8fd718caaa..521f107dc6d 100644 --- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -11,6 +11,7 @@ #include "mozilla/ipc/GeckoChildProcessHost.h" #include "mozilla/dom/ipc/Blob.h" #include "mozilla/Attributes.h" +#include "mozilla/FileUtils.h" #include "mozilla/HalTypes.h" #include "mozilla/LinkedList.h" #include "mozilla/StaticPtr.h" @@ -534,6 +535,9 @@ private: virtual bool RecvRemoveIdleObserver(const uint64_t& observerId, const uint32_t& aIdleTimeInS) MOZ_OVERRIDE; + virtual bool + RecvBackUpXResources(const FileDescriptor& aXSocketFd) MOZ_OVERRIDE; + // If you add strong pointers to cycle collected objects here, be sure to // release these objects in ShutDownProcess. See the comment there for more // details. @@ -586,6 +590,12 @@ private: nsConsoleService* GetConsoleService(); nsDataHashtable > mIdleListeners; + +#ifdef MOZ_X11 + // Dup of child's X socket, used to scope its resources to this + // object instead of the child process's lifetime. + ScopedClose mChildXSocketFdDup; +#endif }; } // namespace dom diff --git a/dom/ipc/PContent.ipdl b/dom/ipc/PContent.ipdl index a64e9a39eb7..92459c6ed15 100644 --- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -519,6 +519,20 @@ parent: AddIdleObserver(uint64_t observerId, uint32_t idleTimeInS); RemoveIdleObserver(uint64_t observerId, uint32_t idleTimeInS); + + /** + * This message is only used on X11 platforms. + * + * Send a dup of the plugin process's X socket to the parent + * process. In theory, this scheme keeps the plugin's X resources + * around until after both the plugin process shuts down *and* the + * parent process closes the dup fd. This is used to prevent the + * parent process from crashing on X errors if, e.g., the plugin + * crashes *just before* a repaint and the parent process tries to + * use the newly-invalid surface. + */ + BackUpXResources(FileDescriptor aXSocketFd); + both: AsyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows, Principal aPrincipal);