Bug 722428: Fix leaks in mochitest by reworking SpecialPowers and nsDOMWindowUtils. r=mounir,ctalbert
authorKyle Huey <khuey@kylehuey.com>
Sun, 01 Apr 2012 19:23:51 -0700
changeset 94117 3e46009daea3ca4538a1fe4cd49c4ce3ed3546e6
parent 94116 447ede53509a3930d1ba5ecaa891af2b01460bed
child 94118 93251eb39b6e83d366935dd769091e9cc9708525
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmounir, ctalbert
bugs722428
milestone14.0a1
first release with
nightly linux32
3e46009daea3 / 14.0a1 / 20120402031127 / files
nightly linux64
3e46009daea3 / 14.0a1 / 20120402031127 / files
nightly mac
3e46009daea3 / 14.0a1 / 20120402031127 / files
nightly win32
3e46009daea3 / 14.0a1 / 20120402031127 / files
nightly win64
3e46009daea3 / 14.0a1 / 20120402031127 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 722428: Fix leaks in mochitest by reworking SpecialPowers and nsDOMWindowUtils. r=mounir,ctalbert
dom/base/nsDOMWindowUtils.cpp
dom/base/nsDOMWindowUtils.h
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
testing/mochitest/specialpowers/content/specialpowers.js
testing/mochitest/tests/SimpleTest/ChromePowers.js
testing/mochitest/tests/SimpleTest/specialpowersAPI.js
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -102,66 +102,60 @@ static bool IsUniversalXPConnectCapable(
   nsresult rv = nsContentUtils::GetSecurityManager()->
                   IsCapabilityEnabled("UniversalXPConnect", &hasCap);
   NS_ENSURE_SUCCESS(rv, false);
   return hasCap;
 }
 
 DOMCI_DATA(WindowUtils, nsDOMWindowUtils)
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMWindowUtils)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMWindowUtils)
-  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mWindow)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMWindowUtils)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mWindow,
-                                                       nsIScriptGlobalObject)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMWindowUtils)
+NS_INTERFACE_MAP_BEGIN(nsDOMWindowUtils)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMWindowUtils)
   NS_INTERFACE_MAP_ENTRY(nsIDOMWindowUtils)
   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WindowUtils)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMWindowUtils)
-NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMWindowUtils)
+NS_IMPL_ADDREF(nsDOMWindowUtils)
+NS_IMPL_RELEASE(nsDOMWindowUtils)
 
 nsDOMWindowUtils::nsDOMWindowUtils(nsGlobalWindow *aWindow)
-  : mWindow(aWindow)
 {
-  NS_ASSERTION(mWindow->IsOuterWindow(), "How did that happen?");
+  nsCOMPtr<nsISupports> supports = do_QueryObject(aWindow);
+  mWindow = do_GetWeakReference(supports);
+  NS_ASSERTION(aWindow->IsOuterWindow(), "How did that happen?");
 }
 
 nsDOMWindowUtils::~nsDOMWindowUtils()
 {
 }
 
 nsIPresShell*
 nsDOMWindowUtils::GetPresShell()
 {
-  if (!mWindow)
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  if (!window)
     return nsnull;
 
-  nsIDocShell *docShell = mWindow->GetDocShell();
+  nsIDocShell *docShell = window->GetDocShell();
   if (!docShell)
     return nsnull;
 
   nsCOMPtr<nsIPresShell> presShell;
   docShell->GetPresShell(getter_AddRefs(presShell));
   return presShell;
 }
 
 nsPresContext*
 nsDOMWindowUtils::GetPresContext()
 {
-  if (!mWindow)
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  if (!window)
     return nsnull;
-  nsIDocShell *docShell = mWindow->GetDocShell();
+  nsIDocShell *docShell = window->GetDocShell();
   if (!docShell)
     return nsnull;
   nsRefPtr<nsPresContext> presContext;
   docShell->GetPresContext(getter_AddRefs(presContext));
   return presContext;
 }
 
 NS_IMETHODIMP
@@ -192,34 +186,36 @@ NS_IMETHODIMP
 nsDOMWindowUtils::GetDocCharsetIsForced(bool *aIsForced)
 {
   *aIsForced = false;
 
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
-  if (mWindow) {
-    nsCOMPtr<nsIDocument> doc(do_QueryInterface(mWindow->GetExtantDocument()));
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  if (window) {
+    nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
     *aIsForced = doc &&
       doc->GetDocumentCharacterSetSource() >= kCharsetFromParentForced;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetDocumentMetadata(const nsAString& aName,
                                       nsAString& aValue)
 {
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
-  if (mWindow) {
-    nsCOMPtr<nsIDocument> doc(do_QueryInterface(mWindow->GetExtantDocument()));
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  if (window) {
+    nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
     if (doc) {
       nsCOMPtr<nsIAtom> name = do_GetAtom(aName);
       doc->GetHeaderData(name, aValue);
       return NS_OK;
     }
   }
   
   aValue.Truncate();
@@ -805,18 +801,19 @@ nsDOMWindowUtils::ForceUpdateNativeMenuA
     return NS_ERROR_FAILURE;
 
   return widget->ForceUpdateNativeMenuAt(indexString);
 }
 
 nsIWidget*
 nsDOMWindowUtils::GetWidget(nsPoint* aOffset)
 {
-  if (mWindow) {
-    nsIDocShell *docShell = mWindow->GetDocShell();
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  if (window) {
+    nsIDocShell *docShell = window->GetDocShell();
     if (docShell) {
       nsCOMPtr<nsIPresShell> presShell;
       docShell->GetPresShell(getter_AddRefs(presShell));
       if (presShell) {
         nsIFrame* frame = presShell->GetRootFrame();
         if (frame)
           return frame->GetView()->GetNearestWidget(aOffset);
       }
@@ -850,22 +847,23 @@ nsDOMWindowUtils::GetWidgetForElement(ns
 
 NS_IMETHODIMP
 nsDOMWindowUtils::Focus(nsIDOMElement* aElement)
 {
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
+  nsCOMPtr<nsIDOMWindow> window = do_QueryReferent(mWindow);
   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
   if (fm) {
     if (aElement)
       fm->SetFocus(aElement, 0);
     else
-      fm->ClearFocus(mWindow);
+      fm->ClearFocus(window);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GarbageCollect(nsICycleCollectorListener *aListener,
                                  PRInt32 aExtraForgetSkippableCalls)
@@ -963,17 +961,20 @@ nsDOMWindowUtils::SendSimpleGestureEvent
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::ElementFromPoint(float aX, float aY,
                                    bool aIgnoreRootScrollFrame,
                                    bool aFlushLayout,
                                    nsIDOMElement** aReturn)
 {
-  nsCOMPtr<nsIDocument> doc(do_QueryInterface(mWindow->GetExtantDocument()));
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_STATE(window);
+
+  nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
   NS_ENSURE_STATE(doc);
 
   return doc->ElementFromPointHelper(aX, aY, aIgnoreRootScrollFrame, aFlushLayout,
                                      aReturn);
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::NodesFromRect(float aX, float aY,
@@ -982,17 +983,20 @@ nsDOMWindowUtils::NodesFromRect(float aX
                                 bool aIgnoreRootScrollFrame,
                                 bool aFlushLayout,
                                 nsIDOMNodeList** aReturn)
 {
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
-  nsCOMPtr<nsIDocument> doc(do_QueryInterface(mWindow->GetExtantDocument()));
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_STATE(window);
+
+  nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
   NS_ENSURE_STATE(doc);
 
   return doc->NodesFromRectHelper(aX, aY, aTopSize, aRightSize, aBottomSize, aLeftSize, 
                                   aIgnoreRootScrollFrame, aFlushLayout, aReturn);
 }
 
 static already_AddRefed<gfxImageSurface>
 CanvasToImageSurface(nsIDOMHTMLCanvasElement* aCanvas)
@@ -1105,49 +1109,56 @@ nsDOMWindowUtils::ClearMozAfterPaintEven
 
 NS_IMETHODIMP
 nsDOMWindowUtils::DisableNonTestMouseEvents(bool aDisable)
 {
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
-  NS_ENSURE_TRUE(mWindow, NS_ERROR_FAILURE);
-  nsIDocShell *docShell = mWindow->GetDocShell();
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
+  nsIDocShell *docShell = window->GetDocShell();
   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
   nsCOMPtr<nsIPresShell> presShell;
   docShell->GetPresShell(getter_AddRefs(presShell));
   NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
   presShell->DisableNonTestMouseEvents(aDisable);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SuppressEventHandling(bool aSuppress)
 {
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
-  nsCOMPtr<nsIDocument> doc(do_QueryInterface(mWindow->GetExtantDocument()));
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_STATE(window);
+
+  nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
 
   if (aSuppress) {
     doc->SuppressEventHandling();
   } else {
     doc->UnsuppressEventHandlingAndFireEvents(true);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetScrollXY(bool aFlushLayout, PRInt32* aScrollX, PRInt32* aScrollY)
 {
-  nsCOMPtr<nsIDocument> doc(do_QueryInterface(mWindow->GetExtantDocument()));
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_STATE(window);
+
+  nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
   NS_ENSURE_STATE(doc);
 
   if (aFlushLayout) {
     doc->FlushPendingNotifications(Flush_Layout);
   }
 
   nsPoint scrollPos(0,0);
   nsIPresShell *presShell = doc->GetShell();
@@ -1416,19 +1427,20 @@ nsDOMWindowUtils::SendQueryContentEvent(
                                         nsIQueryContentEventResult **aResult)
 {
   *aResult = nsnull;
 
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
-  NS_ENSURE_TRUE(mWindow, NS_ERROR_FAILURE);
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
 
-  nsIDocShell *docShell = mWindow->GetDocShell();
+  nsIDocShell *docShell = window->GetDocShell();
   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIPresShell> presShell;
   docShell->GetPresShell(getter_AddRefs(presShell));
   NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
 
   nsPresContext* presContext = presShell->GetPresContext();
   NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
@@ -1598,62 +1610,80 @@ nsDOMWindowUtils::GetVisitedDependentCom
                     const nsAString& aPropertyName, nsAString& aResult)
 {
   aResult.Truncate();
 
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_STATE(window);
+
   nsCOMPtr<nsIDOMCSSStyleDeclaration> decl;
   nsresult rv =
-    mWindow->GetComputedStyle(aElement, aPseudoElement, getter_AddRefs(decl));
+    window->GetComputedStyle(aElement, aPseudoElement, getter_AddRefs(decl));
   NS_ENSURE_SUCCESS(rv, rv);
 
   static_cast<nsComputedDOMStyle*>(decl.get())->SetExposeVisitedStyle(true);
   rv = decl->GetPropertyValue(aPropertyName, aResult);
   static_cast<nsComputedDOMStyle*>(decl.get())->SetExposeVisitedStyle(false);
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::EnterModalState()
 {
-  mWindow->EnterModalState();
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_STATE(window);
+
+  window->EnterModalState();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::LeaveModalState()
 {
-  mWindow->LeaveModalState(nsnull);
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_STATE(window);
+
+  window->LeaveModalState(nsnull);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::EnterModalStateWithWindow(nsIDOMWindow **aWindow)
 {
-  *aWindow = mWindow->EnterModalState();
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_STATE(window);
+
+  *aWindow = window->EnterModalState();
   NS_IF_ADDREF(*aWindow);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::LeaveModalStateWithWindow(nsIDOMWindow *aWindow)
 {
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_STATE(window);
+
   NS_ENSURE_ARG_POINTER(aWindow);
-  mWindow->LeaveModalState(aWindow);
+  window->LeaveModalState(aWindow);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::IsInModalState(bool *retval)
 {
-  *retval = mWindow->IsInModalState();
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_STATE(window);
+
+  *retval = static_cast<nsGlobalWindow*>(window.get())->IsInModalState();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetParent(const JS::Value& aObject,
                             JSContext* aCx,
                             JS::Value* aParent)
 {
@@ -1678,53 +1708,66 @@ nsDOMWindowUtils::GetParent(const JS::Va
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetOuterWindowID(PRUint64 *aWindowID)
 {
-  NS_ASSERTION(mWindow->IsOuterWindow(), "How did that happen?");
-  *aWindowID = mWindow->WindowID();
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_STATE(window);
+
+  NS_ASSERTION(window->IsOuterWindow(), "How did that happen?");
+  *aWindowID = window->WindowID();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetCurrentInnerWindowID(PRUint64 *aWindowID)
 {
-  NS_ASSERTION(mWindow->IsOuterWindow(), "How did that happen?");
-  nsGlobalWindow* inner = mWindow->GetCurrentInnerWindowInternal();
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_TRUE(window, NS_ERROR_NOT_AVAILABLE);
+
+  NS_ASSERTION(window->IsOuterWindow(), "How did that happen?");
+  nsGlobalWindow* inner =
+    static_cast<nsGlobalWindow*>(window.get())->GetCurrentInnerWindowInternal();
   if (!inner) {
     return NS_ERROR_NOT_AVAILABLE;
   }
   *aWindowID = inner->WindowID();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SuspendTimeouts()
 {
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
-  mWindow->SuspendTimeouts();
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
+
+  window->SuspendTimeouts();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::ResumeTimeouts()
 {
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
-  mWindow->ResumeTimeouts();
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
+
+  window->ResumeTimeouts();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetLayerManagerType(nsAString& aType)
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
@@ -1883,20 +1926,23 @@ nsDOMWindowUtils::ComputeAnimationDistan
 }
 
 nsresult
 nsDOMWindowUtils::RenderDocument(const nsRect& aRect,
                                  PRUint32 aFlags,
                                  nscolor aBackgroundColor,
                                  gfxContext* aThebesContext)
 {
+    nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+    NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
+
     // Get DOM Document
     nsresult rv;
     nsCOMPtr<nsIDOMDocument> ddoc;
-    rv = mWindow->GetDocument(getter_AddRefs(ddoc));
+    rv = window->GetDocument(getter_AddRefs(ddoc));
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Get Document
     nsCOMPtr<nsIDocument> doc = do_QueryInterface(ddoc, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Get Primary Shell
     nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
@@ -1906,18 +1952,21 @@ nsDOMWindowUtils::RenderDocument(const n
     return presShell->RenderDocument(aRect, aFlags, aBackgroundColor, aThebesContext);
 }
 
 NS_IMETHODIMP 
 nsDOMWindowUtils::GetCursorType(PRInt16 *aCursor)
 {
   NS_ENSURE_ARG_POINTER(aCursor);
 
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);  
+
   bool isSameDoc = false;
-  nsCOMPtr<nsIDocument> doc(do_QueryInterface(mWindow->GetExtantDocument()));
+  nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
 
   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
 
   do {
     if (nsEventStateManager::sMouseOverDocument == doc.get()) {
       isSameDoc = true;
       break;
     }
@@ -1938,18 +1987,19 @@ nsDOMWindowUtils::GetCursorType(PRInt16 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GoOnline()
 {
   // This is only allowed from about:neterror, which is unprivileged, so it
   // can't access the io-service itself.
-  NS_ENSURE_TRUE(mWindow, NS_ERROR_FAILURE);
-  nsCOMPtr<nsIDocument> doc(do_QueryInterface(mWindow->GetExtantDocument()));
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
+  nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
   NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
   nsCOMPtr<nsIURI> documentURI;
   documentURI = doc->GetDocumentURI();
 
   nsCAutoString spec;
   documentURI->GetSpec(spec);
   if (!StringBeginsWith(spec,  NS_LITERAL_CSTRING("about:neterror?")))
     return NS_ERROR_DOM_SECURITY_ERR;
@@ -2063,17 +2113,20 @@ nsDOMWindowUtils::LeafLayersPartitionWin
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetMayHaveTouchEventListeners(bool* aResult)
 {
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
-  nsPIDOMWindow* innerWindow = mWindow->GetCurrentInnerWindow();
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
+
+  nsPIDOMWindow* innerWindow = window->GetCurrentInnerWindow();
   *aResult = innerWindow ? innerWindow->HasTouchEventListeners() : false;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::CheckAndClearPaintedState(nsIDOMElement* aElement, bool* aResult)
 {
   if (!aElement) {
@@ -2111,21 +2164,22 @@ nsDOMWindowUtils::GetFileReferences(cons
                                     PRInt64 aId, PRInt32* aRefCnt,
                                     PRInt32* aDBRefCnt, PRInt32* aSliceRefCnt,
                                     bool* aResult)
 {
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
-  NS_ENSURE_TRUE(mWindow, NS_ERROR_FAILURE);
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
 
   nsCString origin;
   nsresult rv = indexedDB::IndexedDatabaseManager::GetASCIIOriginFromWindow(
-    mWindow, origin);
+    window, origin);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsRefPtr<indexedDB::IndexedDatabaseManager> mgr =
     indexedDB::IndexedDatabaseManager::Get();
 
   if (mgr) {
     nsRefPtr<indexedDB::FileManager> fileManager =
       mgr->GetFileManager(origin, aDatabaseName);
@@ -2215,18 +2269,19 @@ nsDOMWindowUtils::GetPCCountScriptConten
 
   result = str;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetPaintingSuppressed(bool *aPaintingSuppressed)
 {
-  NS_ENSURE_TRUE(mWindow, NS_ERROR_FAILURE);
-  nsIDocShell *docShell = mWindow->GetDocShell();
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
+  nsIDocShell *docShell = window->GetDocShell();
   NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
 
   nsCOMPtr<nsIPresShell> presShell;
   docShell->GetPresShell(getter_AddRefs(presShell));
   NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
 
   *aPaintingSuppressed = presShell->IsPaintingSuppressed();
   return NS_OK;
@@ -2234,17 +2289,20 @@ nsDOMWindowUtils::GetPaintingSuppressed(
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetPlugins(JSContext* cx, jsval* aPlugins)
 {
   if (!IsUniversalXPConnectCapable()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
-  nsIDOMDocument* ddoc = mWindow->GetExtantDocument();
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
+  NS_ENSURE_STATE(window);
+
+  nsIDOMDocument* ddoc = window->GetExtantDocument();
 
   nsresult rv;
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(ddoc, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsTArray<nsIObjectLoadingContent*> plugins;
   doc->GetPlugins(plugins);
 
--- a/dom/base/nsDOMWindowUtils.h
+++ b/dom/base/nsDOMWindowUtils.h
@@ -44,23 +44,21 @@ class nsGlobalWindow;
 class nsIPresShell;
 
 class nsDOMWindowUtils : public nsIDOMWindowUtils,
                          public nsSupportsWeakReference
 {
 public:
   nsDOMWindowUtils(nsGlobalWindow *aWindow);
   ~nsDOMWindowUtils();
-  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
-  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsDOMWindowUtils,
-                                           nsIDOMWindowUtils)
+  NS_DECL_ISUPPORTS
   NS_DECL_NSIDOMWINDOWUTILS
 
 protected:
-  nsRefPtr<nsGlobalWindow> mWindow;
+  nsWeakPtr mWindow;
 
   // If aOffset is non-null, it gets filled in with the offset of the root
   // frame of our window to the nearest widget in the app units of our window.
   // Add this offset to any event offset we're given to make it relative to the
   // widget returned by GetWidget.
   nsIWidget* GetWidget(nsPoint* aOffset = nsnull);
   nsIWidget* GetWidgetForElement(nsIDOMElement* aElement);
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1219,16 +1219,17 @@ nsGlobalWindow::CleanUp(bool aIgnoreModa
   mToolbar = nsnull;
   mLocationbar = nsnull;
   mPersonalbar = nsnull;
   mStatusbar = nsnull;
   mScrollbars = nsnull;
   mLocation = nsnull;
   mHistory = nsnull;
   mFrames = nsnull;
+  mWindowUtils = nsnull;
   mApplicationCache = nsnull;
   mIndexedDB = nsnull;
   mPendingStorageEventsObsolete = nsnull;
 
   mPerformance = nsnull;
 
   ClearControllers();
 
@@ -8363,30 +8364,22 @@ nsGlobalWindow::GetInterface(const nsIID
         }
       }
     }
   }
 #endif
   else if (aIID.Equals(NS_GET_IID(nsIDOMWindowUtils))) {
     FORWARD_TO_OUTER(GetInterface, (aIID, aSink), NS_ERROR_NOT_INITIALIZED);
 
-    nsCOMPtr<nsISupports> utils(do_QueryReferent(mWindowUtils));
-    if (utils) {
-      *aSink = utils;
-      NS_ADDREF(((nsISupports *) *aSink));
-    } else {
-      nsDOMWindowUtils *utilObj = new nsDOMWindowUtils(this);
-      nsCOMPtr<nsISupports> utilsIfc =
-                              NS_ISUPPORTS_CAST(nsIDOMWindowUtils *, utilObj);
-      if (utilsIfc) {
-        mWindowUtils = do_GetWeakReference(utilsIfc);
-        *aSink = utilsIfc;
-        NS_ADDREF(((nsISupports *) *aSink));
-      }
-    }
+    if (!mWindowUtils) {
+      mWindowUtils = new nsDOMWindowUtils(this);
+    }
+
+    *aSink = mWindowUtils;
+    NS_ADDREF(((nsISupports *) *aSink));
   }
   else {
     return QueryInterface(aIID, aSink);
   }
 
   return *aSink ? NS_OK : NS_ERROR_NO_INTERFACE;
 }
 
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -131,16 +131,17 @@ class WindowStateHolder;
 class nsGlobalWindowObserver;
 class nsGlobalWindow;
 class nsDummyJavaPluginOwner;
 class PostMessageEvent;
 class nsRunnable;
 class nsDOMEventTargetHelper;
 class nsDOMOfflineResourceList;
 class nsDOMMozURLProperty;
+class nsDOMWindowUtils;
 
 #ifdef MOZ_DISABLE_DOMCRYPTO
 class nsIDOMCrypto;
 #endif
 
 class nsWindowSizes;
 
 namespace mozilla {
@@ -891,17 +892,17 @@ protected:
   nsRefPtr<nsPerformance>       mPerformance;
   nsRefPtr<nsDOMWindowList>     mFrames;
   nsRefPtr<nsBarProp>           mMenubar;
   nsRefPtr<nsBarProp>           mToolbar;
   nsRefPtr<nsBarProp>           mLocationbar;
   nsRefPtr<nsBarProp>           mPersonalbar;
   nsRefPtr<nsBarProp>           mStatusbar;
   nsRefPtr<nsBarProp>           mScrollbars;
-  nsCOMPtr<nsIWeakReference>    mWindowUtils;
+  nsRefPtr<nsDOMWindowUtils>    mWindowUtils;
   nsString                      mStatus;
   nsString                      mDefaultStatus;
   // index 0->language_id 1, so index MAX-1 == language_id MAX
   nsGlobalWindowObserver*       mObserver;
 #ifndef MOZ_DISABLE_DOMCRYPTO
   nsCOMPtr<nsIDOMCrypto>        mCrypto;
 #endif
   nsCOMPtr<nsIDOMStorage>      mLocalStorage;
--- a/testing/mochitest/specialpowers/content/specialpowers.js
+++ b/testing/mochitest/specialpowers/content/specialpowers.js
@@ -34,17 +34,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK *****/
 /* This code is loaded in every child process that is started by mochitest in
  * order to be used as a replacement for UniversalXPConnect
  */
 
 function SpecialPowers(window) {
-  this.window = window;
+  this.window = Components.utils.getWeakReference(window);
   this._encounteredCrashDumpFiles = [];
   this._unexpectedCrashDumpFiles = { };
   this._crashDumpDir = null;
   this.DOMWindowUtils = bindDOMWindowUtils(window);
   this._pongHandlers = [];
   this._messageListener = this._messageReceived.bind(this);
   addMessageListener("SPPingService", this._messageListener);
   this._consoleListeners = [];
--- a/testing/mochitest/tests/SimpleTest/ChromePowers.js
+++ b/testing/mochitest/tests/SimpleTest/ChromePowers.js
@@ -31,23 +31,23 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL. 
  *
  * ***** END LICENSE BLOCK ***** */
 
 function ChromePowers(window) {
-  this.window = window;
+  this.window = Components.utils.getWeakReference(window);
 
   // In the case of browser-chrome tests, we are running as a [ChromeWindow]
   // and we have no window.QueryInterface available, content.window is what we need
   if (typeof(window) == "ChromeWindow" && typeof(content.window) == "Window") {
     this.DOMWindowUtils = bindDOMWindowUtils(content.window);
-    this.window = content.window
+    this.window = Components.utils.getWeakReference(content.window);
   } else {
     this.DOMWindowUtils = bindDOMWindowUtils(window);
   }
 
   this.spObserver = new SpecialPowersObserverAPI();
 }
 
 ChromePowers.prototype = new SpecialPowersAPI();
--- a/testing/mochitest/tests/SimpleTest/specialpowersAPI.js
+++ b/testing/mochitest/tests/SimpleTest/specialpowersAPI.js
@@ -72,17 +72,19 @@ function bindDOMWindowUtils(aWindow) {
   // have to explicitly stub out new methods that appear on
   // nsIDOMWindowUtils.
   var proto = Object.getPrototypeOf(util);
   var target = {};
   function rebind(desc, prop) {
     if (prop in desc && typeof(desc[prop]) == "function") {
       var oldval = desc[prop];
       try {
-        desc[prop] = function() { return oldval.apply(util, arguments); };
+        desc[prop] = function() {
+          return oldval.apply(util, arguments);
+        };
       } catch (ex) {
         dump("WARNING: Special Powers failed to rebind function: " + desc + "::" + prop + "\n");
       }
     }
   }
   for (var i in proto) {
     var desc = Object.getOwnPropertyDescriptor(proto, i);
     rebind(desc, "get");
@@ -382,17 +384,17 @@ SpecialPowersAPI.prototype = {
   wrap: wrapPrivileged,
   unwrap: unwrapPrivileged,
 
   get MockFilePicker() {
     return MockFilePicker
   },
 
   getDOMWindowUtils: function(aWindow) {
-    if (aWindow == this.window && this.DOMWindowUtils != null)
+    if (aWindow == this.window.get() && this.DOMWindowUtils != null)
       return this.DOMWindowUtils;
 
     return bindDOMWindowUtils(aWindow);
   },
 
   removeExpectedCrashDumpFiles: function(aExpectingProcessCrash) {
     var success = true;
     if (aExpectingProcessCrash) {
@@ -769,17 +771,17 @@ SpecialPowersAPI.prototype = {
   },
 
   createSystemXHR: function() {
     return Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
              .createInstance(Ci.nsIXMLHttpRequest);
   },
 
   snapshotWindow: function (win, withCaret) {
-    var el = this.window.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
+    var el = this.window.get().document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
     el.width = win.innerWidth;
     el.height = win.innerHeight;
     var ctx = el.getContext("2d");
     var flags = 0;
 
     ctx.drawWindow(win, win.scrollX, win.scrollY,
                    win.innerWidth, win.innerHeight,
                    "rgb(255,255,255)",
@@ -997,17 +999,17 @@ SpecialPowersAPI.prototype = {
     if (this._cb == null) {
       this._cb = Components.classes["@mozilla.org/widget/clipboard;1"].
                             getService(Components.interfaces.nsIClipboard);
     }
     return this._cb.supportsSelectionClipboard();
   },
 
   snapshotWindow: function (win, withCaret) {
-    var el = this.window.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
+    var el = this.window.get().document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
     el.width = win.innerWidth;
     el.height = win.innerHeight;
     var ctx = el.getContext("2d");
     var flags = 0;
 
     ctx.drawWindow(win, win.scrollX, win.scrollY,
                    win.innerWidth, win.innerHeight,
                    "rgb(255,255,255)",