Bug 1126042 - Use different window IDs for different processes (r=smaug)
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -53,16 +53,17 @@
#include "mozilla/Likely.h"
#include "mozilla/unused.h"
// Other Classes
#include "mozilla/dom/BarProps.h"
#include "nsContentCID.h"
#include "nsLayoutStatics.h"
#include "nsCCUncollectableMarker.h"
+#include "mozilla/dom/ContentChild.h"
#include "mozilla/dom/workers/Workers.h"
#include "mozilla/dom/MessagePortList.h"
#include "mozilla/dom/ToJSValue.h"
#include "nsJSPrincipals.h"
#include "mozilla/Attributes.h"
#include "mozilla/Debug.h"
#include "mozilla/EventListenerManager.h"
#include "mozilla/EventStates.h"
@@ -557,31 +558,61 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(n
// Return true if this timeout has a refcount of 1. This is used to check
// that dummy_timeout doesn't leak from nsGlobalWindow::RunTimeout.
bool
nsTimeout::HasRefCntOne()
{
return mRefCnt.get() == 1;
}
+// We use only 53 bits for the window ID so that it can be converted to and from
+// a JS value without loss of precision. The upper bits of the window ID hold the
+// process ID. The lower bits identify the window.
+static const uint64_t kWindowIDTotalBits = 53;
+static const uint64_t kWindowIDProcessBits = 22;
+static const uint64_t kWindowIDWindowBits = kWindowIDTotalBits - kWindowIDProcessBits;
+
+// Try to return a window ID that is unique across processes and that will never
+// be recycled.
+static uint64_t
+NextWindowID()
+{
+ uint64_t processID = 0;
+ if (XRE_GetProcessType() == GeckoProcessType_Content) {
+ ContentChild* cc = ContentChild::GetSingleton();
+ processID = cc->GetID();
+ }
+
+ MOZ_RELEASE_ASSERT(processID < (uint64_t(1) << kWindowIDProcessBits));
+ uint64_t processBits = processID & ((uint64_t(1) << kWindowIDProcessBits) - 1);
+
+ // Make sure no actual window ends up with mWindowID == 0.
+ uint64_t windowID = ++gNextWindowID;
+
+ MOZ_RELEASE_ASSERT(windowID < (uint64_t(1) << kWindowIDWindowBits));
+ uint64_t windowBits = windowID & ((uint64_t(1) << kWindowIDWindowBits) - 1);
+
+ return (processBits << kWindowIDWindowBits) | windowBits;
+}
+
nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow *aOuterWindow)
: mFrameElement(nullptr), mDocShell(nullptr), mModalStateDepth(0),
mRunningTimeout(nullptr), mMutationBits(0), mIsDocumentLoaded(false),
mIsHandlingResizeEvent(false), mIsInnerWindow(aOuterWindow != nullptr),
mMayHavePaintEventListener(false), mMayHaveTouchEventListener(false),
mMayHaveTouchCaret(false),
mMayHaveScrollWheelEventListener(false),
mMayHaveMouseEnterLeaveEventListener(false),
mMayHavePointerEnterLeaveEventListener(false),
mIsModalContentWindow(false),
mIsActive(false), mIsBackground(false),
mAudioMuted(false), mAudioVolume(1.0),
mInnerWindow(nullptr), mOuterWindow(aOuterWindow),
// Make sure no actual window ends up with mWindowID == 0
- mWindowID(++gNextWindowID), mHasNotifiedGlobalCreated(false),
+ mWindowID(NextWindowID()), mHasNotifiedGlobalCreated(false),
mMarkedCCGeneration(0), mSendAfterRemotePaint(false)
{}
nsPIDOMWindow::~nsPIDOMWindow() {}
// DialogValueHolder CC goop.
NS_IMPL_CYCLE_COLLECTION(DialogValueHolder, mValue)