Backed out changeset cb3fd4a4b7c5 (bug 771043) for Android mochitest-8 failures.
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 03 Oct 2014 15:26:06 -0400
changeset 231994 40aa7a47fceda8d99607ca93247279463a9443f3
parent 231993 f4ebce0c90d09899637f840eb8febe516b3b54bc
child 231995 09e3b826cf7d546939bc9e5ba9ad5d0e8ca17e6f
push id1
push usersledru@mozilla.com
push dateThu, 04 Dec 2014 17:57:20 +0000
bugs771043
milestone35.0a1
backs outcb3fd4a4b7c55208b7f657f5e5bd55bc975292bc
Backed out changeset cb3fd4a4b7c5 (bug 771043) for Android mochitest-8 failures. CLOSED TREE
content/base/public/nsIDocument.h
content/base/src/nsDocument.cpp
dom/base/nsGlobalWindow.cpp
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/style/MediaQueryList.cpp
layout/style/MediaQueryList.h
layout/style/test/mochitest.ini
layout/style/test/test_bug771043.html
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -20,17 +20,16 @@
 #include "nsPropertyTable.h"             // for member
 #include "nsTHashtable.h"                // for member
 #include "nsWeakReference.h"
 #include "mozilla/dom/DocumentBinding.h"
 #include "mozilla/WeakPtr.h"
 #include "Units.h"
 #include "nsExpirationTracker.h"
 #include "nsClassHashtable.h"
-#include "prclist.h"
 
 class imgIRequest;
 class nsAString;
 class nsBindingManager;
 class nsIDocShell;
 class nsDocShell;
 class nsDOMNavigationTiming;
 class nsFrameLoader;
@@ -109,17 +108,16 @@ class Event;
 class EventTarget;
 class FontFaceSet;
 class FrameRequestCallback;
 class ImportManager;
 class OverfillCallback;
 class HTMLBodyElement;
 struct LifecycleCallbackArgs;
 class Link;
-class MediaQueryList;
 class GlobalObject;
 class NodeFilter;
 class NodeIterator;
 class ProcessingInstruction;
 class StyleSheetList;
 class SVGDocument;
 class Touch;
 class TouchList;
@@ -1502,27 +1500,16 @@ public:
    * Get the box object for an element. This is not exposed through a
    * scriptable interface except for XUL documents.
    */
   virtual already_AddRefed<nsIBoxObject>
     GetBoxObjectFor(mozilla::dom::Element* aElement,
                     mozilla::ErrorResult& aRv) = 0;
 
   /**
-   * Support for window.matchMedia()
-   */
-
-  already_AddRefed<mozilla::dom::MediaQueryList>
-    MatchMedia(const nsAString& aMediaQueryList);
-
-  const PRCList* MediaQueryLists() const {
-    return &mDOMMediaQueryLists;
-  }
-
-  /**
    * Get the compatibility mode for this document
    */
   nsCompatibility GetCompatibilityMode() const {
     return mCompatMode;
   }
   
   /**
    * Check whether we've ever fired a DOMTitleChanged event for this
@@ -2746,19 +2733,16 @@ protected:
   nsCOMPtr<nsIVariant> mStateObjectCached;
 
   uint32_t mInSyncOperationCount;
 
   nsRefPtr<mozilla::dom::XPathEvaluator> mXPathEvaluator;
 
   uint32_t mBlockDOMContentLoaded;
   bool mDidFireDOMContentLoaded:1;
-
-  // Our live MediaQueryLists
-  PRCList mDOMMediaQueryLists;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID)
 
 /**
  * mozAutoSubtreeModified batches DOM mutations so that a DOMSubtreeModified
  * event is dispatched, if necessary, when the outermost mozAutoSubtreeModified
  * object is deleted.
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -188,17 +188,16 @@
 #include "nsSandboxFlags.h"
 #include "nsIAppsService.h"
 #include "mozilla/dom/AnimationTimeline.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/DocumentFragment.h"
 #include "mozilla/dom/Event.h"
 #include "mozilla/dom/HTMLBodyElement.h"
 #include "mozilla/dom/HTMLInputElement.h"
-#include "mozilla/dom/MediaQueryList.h"
 #include "mozilla/dom/NodeFilterBinding.h"
 #include "mozilla/dom/OwningNonNull.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/UndoManager.h"
 #include "mozilla/dom/WebComponentsBinding.h"
 #include "nsFrame.h"
 #include "nsDOMCaretPosition.h"
 #include "nsIDOMHTMLTextAreaElement.h"
@@ -1556,18 +1555,16 @@ nsIDocument::nsIDocument()
     // &&-ed in, this is safe.
     mAllowDNSPrefetch(true),
     mIsBeingUsedAsImage(false),
     mHasLinksToUpdate(false),
     mPartID(0),
     mDidFireDOMContentLoaded(true)
 {
   SetInDocument();
-
-  PR_INIT_CLIST(&mDOMMediaQueryLists);  
 }
 
 // NOTE! nsDocument::operator new() zeroes out all members, so don't
 // bother initializing members to 0.
 
 nsDocument::nsDocument(const char* aContentType)
   : nsIDocument()
   , mAnimatingImages(true)
@@ -1603,19 +1600,16 @@ ClearAllBoxObjects(nsIContent* aKey, nsP
   if (aBoxObject) {
     aBoxObject->Clear();
   }
   return PL_DHASH_NEXT;
 }
 
 nsIDocument::~nsIDocument()
 {
-  NS_ABORT_IF_FALSE(PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists),
-                    "must not have media query lists left");
-
   if (mNodeInfoManager) {
     mNodeInfoManager->DropDocumentReference();
   }
 }
 
 
 nsDocument::~nsDocument()
 {
@@ -2020,28 +2014,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
     PL_DHashTableEnumerate(tmp->mSubDocuments, SubDocTraverser, &cb);
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCSSLoader)
 
   for (uint32_t i = 0; i < tmp->mHostObjectURIs.Length(); ++i) {
     nsHostObjectProtocolHandler::Traverse(tmp->mHostObjectURIs[i], cb);
   }
-
-  // We own only the items in mDOMMediaQueryLists that have listeners;
-  // this reference is managed by their AddListener and RemoveListener
-  // methods.
-  for (PRCList *l = PR_LIST_HEAD(&tmp->mDOMMediaQueryLists);
-       l != &tmp->mDOMMediaQueryLists; l = PR_NEXT_LINK(l)) {
-    MediaQueryList *mql = static_cast<MediaQueryList*>(l);
-    if (mql->HasListeners()) {
-      NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mDOMMediaQueryLists item");
-      cb.NoteXPCOMChild(mql);
-    }
-  }
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsDocument)
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDocument)
   if (tmp->PreservingWrapper()) {
     NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mExpandoAndGeneration.expando);
   }
@@ -2134,27 +2116,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
     tmp->mCSSLoader->DropDocumentReference();
     NS_IMPL_CYCLE_COLLECTION_UNLINK(mCSSLoader)
   }
 
   for (uint32_t i = 0; i < tmp->mHostObjectURIs.Length(); ++i) {
     nsHostObjectProtocolHandler::RemoveDataEntry(tmp->mHostObjectURIs[i]);
   }
 
-  // We own only the items in mDOMMediaQueryLists that have listeners;
-  // this reference is managed by their AddListener and RemoveListener
-  // methods.
-  for (PRCList *l = PR_LIST_HEAD(&tmp->mDOMMediaQueryLists);
-       l != &tmp->mDOMMediaQueryLists; ) {
-    PRCList *next = PR_NEXT_LINK(l);
-    MediaQueryList *mql = static_cast<MediaQueryList*>(l);
-    mql->RemoveAllListeners();
-    l = next;
-  }
-
   tmp->mInUnlinkOrDeletion = false;
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 static bool sPrefsInitialized = false;
 static uint32_t sOnloadDecodeLimit = 0;
 
 nsresult
 nsDocument::Init()
@@ -7011,27 +6982,16 @@ nsDocument::ClearBoxObjectFor(nsIContent
     nsPIBoxObject *boxObject = mBoxObjectTable->GetWeak(aContent);
     if (boxObject) {
       boxObject->Clear();
       mBoxObjectTable->Remove(aContent);
     }
   }
 }
 
-already_AddRefed<MediaQueryList>
-nsIDocument::MatchMedia(const nsAString& aMediaQueryList)
-{
-  nsRefPtr<MediaQueryList> result = new MediaQueryList(this, aMediaQueryList);
-
-  // Insert the new item at the end of the linked list.
-  PR_INSERT_BEFORE(result, &mDOMMediaQueryLists);
-
-  return result.forget();
-}
-
 void
 nsDocument::FlushSkinBindings()
 {
   BindingManager()->FlushSkinBindings();
 }
 
 nsresult
 nsDocument::InitializeFrameLoader(nsFrameLoader* aLoader)
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -5337,21 +5337,36 @@ nsGlobalWindow::MatchMedia(const nsAStri
 {
   // FIXME: This whole forward-to-outer and then get a pres
   // shell/context off the docshell dance is sort of silly; it'd make
   // more sense to forward to the inner, but it's what everyone else
   // (GetSelection, GetScrollXY, etc.) does around here.
   FORWARD_TO_OUTER_OR_THROW(MatchMedia, (aMediaQueryList, aError), aError,
                             nullptr);
 
-  if (!mDoc) {
+  // We need this now to ensure that we have a non-null |presContext|
+  // when we ought to.
+  // This is similar to EnsureSizeUpToDate, but only flushes frames.
+  nsGlobalWindow *parent = static_cast<nsGlobalWindow*>(GetPrivateParent());
+  if (parent) {
+    parent->FlushPendingNotifications(Flush_Frames);
+  }
+
+  if (!mDocShell) {
     return nullptr;
   }
 
-  return mDoc->MatchMedia(aMediaQueryList);
+  nsRefPtr<nsPresContext> presContext;
+  mDocShell->GetPresContext(getter_AddRefs(presContext));
+
+  if (!presContext) {
+    return nullptr;
+  }
+
+  return presContext->MatchMedia(aMediaQueryList);
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::MatchMedia(const nsAString& aMediaQueryList,
                            nsISupports** aResult)
 {
   ErrorResult rv;
   nsRefPtr<MediaQueryList> mediaQueryList = MatchMedia(aMediaQueryList, rv);
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -241,23 +241,28 @@ nsPresContext::nsPresContext(nsIDocument
 
   mCounterStylesDirty = true;
 
   // if text perf logging enabled, init stats struct
   PRLogModuleInfo *log = gfxPlatform::GetLog(eGfxLog_textperf);
   if (log && log->level >= PR_LOG_WARNING) {
     mTextPerf = new gfxTextPerfMetrics();
   }
+
+  PR_INIT_CLIST(&mDOMMediaQueryLists);
 }
 
 nsPresContext::~nsPresContext()
 {
   NS_PRECONDITION(!mShell, "Presshell forgot to clear our mShell pointer");
   SetShell(nullptr);
 
+  NS_ABORT_IF_FALSE(PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists),
+                    "must not have media query lists left");
+
   // Disconnect the refresh driver *after* the transition manager, which
   // needs it.
   if (mRefreshDriver && mRefreshDriver->PresContext() == this) {
     mRefreshDriver->Disconnect();
   }
 
   if (mEventManager) {
     // unclear if these are needed, but can't hurt
@@ -335,32 +340,55 @@ nsPresContext::LastRelease()
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsPresContext)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsPresContext)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument);
   // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mDeviceContext); // not xpcom
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEventManager);
   // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mLanguage); // an atom
 
+  // We own only the items in mDOMMediaQueryLists that have listeners;
+  // this reference is managed by their AddListener and RemoveListener
+  // methods.
+  for (PRCList *l = PR_LIST_HEAD(&tmp->mDOMMediaQueryLists);
+       l != &tmp->mDOMMediaQueryLists; l = PR_NEXT_LINK(l)) {
+    MediaQueryList *mql = static_cast<MediaQueryList*>(l);
+    if (mql->HasListeners()) {
+      NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mDOMMediaQueryLists item");
+      cb.NoteXPCOMChild(mql);
+    }
+  }
+
   // NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTheme); // a service
   // NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mLangService); // a service
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrintSettings);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPrefChangedTimer);
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsPresContext)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument);
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDeviceContext); // worth bothering?
   if (tmp->mEventManager) {
     // unclear if these are needed, but can't hurt
     tmp->mEventManager->NotifyDestroyPresContext(tmp);
     tmp->mEventManager->SetPresContext(nullptr);
     tmp->mEventManager = nullptr;
   }
 
+  // We own only the items in mDOMMediaQueryLists that have listeners;
+  // this reference is managed by their AddListener and RemoveListener
+  // methods.
+  for (PRCList *l = PR_LIST_HEAD(&tmp->mDOMMediaQueryLists);
+       l != &tmp->mDOMMediaQueryLists; ) {
+    PRCList *next = PR_NEXT_LINK(l);
+    MediaQueryList *mql = static_cast<MediaQueryList*>(l);
+    mql->RemoveAllListeners();
+    l = next;
+  }
+
   // NS_RELEASE(tmp->mLanguage); // an atom
 
   // NS_IMPL_CYCLE_COLLECTION_UNLINK(mTheme); // a service
   // NS_IMPL_CYCLE_COLLECTION_UNLINK(mLangService); // a service
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPrintSettings);
   if (tmp->mPrefChangedTimer)
   {
     tmp->mPrefChangedTimer->Cancel();
@@ -1866,45 +1894,45 @@ nsPresContext::MediaFeatureValuesChanged
       mediaFeaturesDidChange ||
       (mUsesViewportUnits && mPendingViewportChange)) {
     RebuildAllStyleData(aChangeHint);
   }
 
   mPendingViewportChange = false;
 
   if (mDocument->IsBeingUsedAsImage()) {
-    MOZ_ASSERT(PR_CLIST_IS_EMPTY(mDocument->MediaQueryLists()));
+    MOZ_ASSERT(PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists));
     return;
   }
 
   MOZ_ASSERT(nsContentUtils::IsSafeToRunScript());
 
   // Media query list listeners should be notified from a queued task
   // (in HTML5 terms), although we also want to notify them on certain
   // flushes.  (We're already running off an event.)
   //
   // Note that we do this after the new style from media queries in
   // style sheets has been computed.
 
-  if (!PR_CLIST_IS_EMPTY(mDocument->MediaQueryLists())) {
+  if (!PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists)) {
     // We build a list of all the notifications we're going to send
     // before we send any of them.  (The spec says the notifications
     // should be a queued task, so any removals that happen during the
     // notifications shouldn't affect what gets notified.)  Furthermore,
     // we hold strong pointers to everything we're going to make
     // notification calls to, since each notification involves calling
     // arbitrary script that might otherwise destroy these objects, or,
     // for that matter, |this|.
     //
     // Note that we intentionally send the notifications to media query
     // list in the order they were created and, for each list, to the
     // listeners in the order added.
     MediaQueryList::NotifyList notifyList;
-    for (PRCList *l = PR_LIST_HEAD(mDocument->MediaQueryLists());
-         l != mDocument->MediaQueryLists(); l = PR_NEXT_LINK(l)) {
+    for (PRCList *l = PR_LIST_HEAD(&mDOMMediaQueryLists);
+         l != &mDOMMediaQueryLists; l = PR_NEXT_LINK(l)) {
       MediaQueryList *mql = static_cast<MediaQueryList*>(l);
       mql->MediumFeaturesChanged(notifyList);
     }
 
     if (!notifyList.IsEmpty()) {
       for (uint32_t i = 0, i_end = notifyList.Length(); i != i_end; ++i) {
         nsAutoMicroTask mt;
         MediaQueryList::HandleChangeData &d = notifyList[i];
@@ -1938,16 +1966,27 @@ nsPresContext::HandleMediaFeatureValuesC
 {
   // Null-check mShell in case the shell has been destroyed (and the
   // event is the only thing holding the pres context alive).
   if (mPendingMediaFeatureValuesChanged && mShell) {
     MediaFeatureValuesChanged(eRebuildStyleIfNeeded);
   }
 }
 
+already_AddRefed<MediaQueryList>
+nsPresContext::MatchMedia(const nsAString& aMediaQueryList)
+{
+  nsRefPtr<MediaQueryList> result = new MediaQueryList(this, aMediaQueryList);
+
+  // Insert the new item at the end of the linked list.
+  PR_INSERT_BEFORE(result, &mDOMMediaQueryLists);
+
+  return result.forget();
+}
+
 nsCompatibility
 nsPresContext::CompatibilityMode() const
 {
   return Document()->GetCompatibilityMode();
 }
 
 void
 nsPresContext::SetPaginatedScrolling(bool aPaginated)
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -67,16 +67,17 @@ class nsIWidget;
 class nsDeviceContext;
 
 namespace mozilla {
 class EventStateManager;
 class RestyleManager;
 class CounterStyleManager;
 namespace dom {
 class FontFaceSet;
+class MediaQueryList;
 }
 namespace layers {
 class ContainerLayer;
 }
 }
 
 // supported values for cached bool types
 enum nsPresContext_CachedBoolPrefType {
@@ -267,16 +268,22 @@ public:
   void PostMediaFeatureValuesChangedEvent();
   void HandleMediaFeatureValuesChangedEvent();
   void FlushPendingMediaFeatureValuesChanged() {
     if (mPendingMediaFeatureValuesChanged)
       MediaFeatureValuesChanged(eRebuildStyleIfNeeded);
   }
 
   /**
+   * Support for window.matchMedia()
+   */
+  already_AddRefed<mozilla::dom::MediaQueryList>
+    MatchMedia(const nsAString& aMediaQueryList);
+
+  /**
    * Access compatibility mode for this context.  This is the same as
    * our document's compatibility mode.
    */
   nsCompatibility CompatibilityMode() const;
 
   /**
    * Notify the context that the document's compatibility mode has changed
    */
@@ -1205,16 +1212,18 @@ public:
   // Should we disable font size inflation because we're inside of
   // shrink-wrapping calculations on an inflation container?
   bool                  mInflationDisabledForShrinkWrap;
 
 protected:
 
   mozilla::WeakPtr<nsDocShell>             mContainer;
 
+  PRCList               mDOMMediaQueryLists;
+
   // Base minimum font size, independent of the language-specific global preference. Defaults to 0
   int32_t               mBaseMinFontSize;
   float                 mTextZoom;      // Text zoom, defaults to 1.0
   float                 mFullZoom;      // Page zoom, defaults to 1.0
 
   float                 mLastFontInflationScreenWidth;
 
   int32_t               mCurAppUnitsPerDevPixel;
--- a/layout/style/MediaQueryList.cpp
+++ b/layout/style/MediaQueryList.cpp
@@ -1,58 +1,57 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
 /* 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/. */
 
 /* implements DOM interface for querying and observing media queries */
 
 #include "mozilla/dom/MediaQueryList.h"
 #include "nsPresContext.h"
 #include "nsIMediaList.h"
 #include "nsCSSParser.h"
 #include "nsIDocument.h"
 
 namespace mozilla {
 namespace dom {
 
-MediaQueryList::MediaQueryList(nsIDocument *aDocument,
+MediaQueryList::MediaQueryList(nsPresContext *aPresContext,
                                const nsAString &aMediaQueryList)
-  : mDocument(aDocument),
+  : mPresContext(aPresContext),
     mMediaList(new nsMediaList),
     mMatchesValid(false)
 {
   PR_INIT_CLIST(this);
 
   SetIsDOMBinding();
 
   nsCSSParser parser;
   parser.ParseMediaList(aMediaQueryList, nullptr, 0, mMediaList, false);
 }
 
 MediaQueryList::~MediaQueryList()
 {
-  if (mDocument) {
+  if (mPresContext) {
     PR_REMOVE_LINK(this);
   }
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(MediaQueryList)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(MediaQueryList)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPresContext)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallbacks)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(MediaQueryList)
-  if (tmp->mDocument) {
+  if (tmp->mPresContext) {
     PR_REMOVE_LINK(tmp);
-    NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument)
+    NS_IMPL_CYCLE_COLLECTION_UNLINK(mPresContext)
   }
   tmp->RemoveAllListeners();
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(MediaQueryList)
 
 NS_INTERFACE_MAP_BEGIN(MediaQueryList)
@@ -136,43 +135,21 @@ MediaQueryList::RemoveAllListeners()
     // See NS_ADDREF_THIS() in AddListener.
     NS_RELEASE_THIS();
   }
 }
 
 void
 MediaQueryList::RecomputeMatches()
 {
-  if (!mDocument) {
+  if (!mPresContext) {
     return;
   }
 
-  if (mDocument->GetParentDocument()) {
-    // Flush frames on the parent so our prescontext will get
-    // recreated as needed.
-    mDocument->GetParentDocument()->FlushPendingNotifications(Flush_Frames);
-    // That might have killed our document, so recheck that.
-    if (!mDocument) {
-      return;
-    }
-  }
-
-  nsIPresShell* shell = mDocument->GetShell();
-  if (!shell) {
-    // XXXbz What's the right behavior here?  Spec doesn't say.
-    return;
-  }
-
-  nsPresContext* presContext = shell->GetPresContext();
-  if (!presContext) {
-    // XXXbz What's the right behavior here?  Spec doesn't say.
-    return;
-  }
-
-  mMatches = mMediaList->Matches(presContext, nullptr);
+  mMatches = mMediaList->Matches(mPresContext, nullptr);
   mMatchesValid = true;
 }
 
 void
 MediaQueryList::MediumFeaturesChanged(NotifyList &aListenersToNotify)
 {
   mMatchesValid = false;
 
@@ -189,17 +166,20 @@ MediaQueryList::MediumFeaturesChanged(No
       }
     }
   }
 }
 
 nsISupports*
 MediaQueryList::GetParentObject() const
 {
-  return mDocument;
+  if (!mPresContext) {
+    return nullptr;
+  }
+  return mPresContext->Document();
 }
 
 JSObject*
 MediaQueryList::WrapObject(JSContext* aCx)
 {
   return MediaQueryListBinding::Wrap(aCx, this);
 }
 
--- a/layout/style/MediaQueryList.h
+++ b/layout/style/MediaQueryList.h
@@ -1,43 +1,41 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
 /* 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/. */
 
 /* implements DOM interface for querying and observing media queries */
 
 #ifndef mozilla_dom_MediaQueryList_h
 #define mozilla_dom_MediaQueryList_h
 
 #include "nsISupports.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsAutoPtr.h"
-#include "nsCOMPtr.h"
 #include "nsTArray.h"
 #include "prclist.h"
 #include "mozilla/Attributes.h"
 #include "nsWrapperCache.h"
 #include "mozilla/dom/MediaQueryListBinding.h"
 
-class nsIDocument;
+class nsPresContext;
 class nsMediaList;
 
 namespace mozilla {
 namespace dom {
 
 class MediaQueryList MOZ_FINAL : public nsISupports,
                                  public nsWrapperCache,
                                  public PRCList
 {
 public:
   // The caller who constructs is responsible for calling Evaluate
   // before calling any other methods.
-  MediaQueryList(nsIDocument *aDocument,
+  MediaQueryList(nsPresContext *aPresContext,
                  const nsAString &aMediaQueryList);
 private:
   ~MediaQueryList();
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaQueryList)
 
@@ -64,31 +62,31 @@ public:
   void GetMedia(nsAString& aMedia);
   bool Matches();
   void AddListener(mozilla::dom::MediaQueryListListener& aListener);
   void RemoveListener(mozilla::dom::MediaQueryListListener& aListener);
 
 private:
   void RecomputeMatches();
 
-  // We only need a pointer to the document to support lazy
+  // We only need a pointer to the pres context to support lazy
   // reevaluation following dynamic changes.  However, this lazy
   // reevaluation is perhaps somewhat important, since some usage
   // patterns may involve the creation of large numbers of
   // MediaQueryList objects which almost immediately become garbage
   // (after a single call to the .matches getter).
   //
   // This pointer does make us a little more dependent on cycle
   // collection.
   //
-  // We have a non-null mDocument for our entire lifetime except
-  // after cycle collection unlinking.  Having a non-null mDocument
-  // is equivalent to being in that document's mDOMMediaQueryLists
+  // We have a non-null mPresContext for our entire lifetime except
+  // after cycle collection unlinking.  Having a non-null mPresContext
+  // is equivalent to being in that pres context's mDOMMediaQueryLists
   // linked list.
-  nsCOMPtr<nsIDocument> mDocument;
+  nsRefPtr<nsPresContext> mPresContext;
 
   nsRefPtr<nsMediaList> mMediaList;
   bool mMatches;
   bool mMatchesValid;
   CallbackList mCallbacks;
 };
 
 } // namespace dom
--- a/layout/style/test/mochitest.ini
+++ b/layout/style/test/mochitest.ini
@@ -90,17 +90,16 @@ support-files = bug517224.sjs
 [test_bug652486.html]
 [test_bug657143.html]
 [test_bug664955.html]
 [test_bug667520.html]
 [test_bug645998.html]
 support-files = file_bug645998-1.css file_bug645998-2.css
 [test_bug716226.html]
 [test_bug765590.html]
-[test_bug771043.html]
 [test_bug798567.html]
 [test_bug798843_pref.html]
 [test_bug829816.html]
 [test_bug874919.html]
 support-files = file_bug829816.css
 [test_bug887741_at-rules_in_declaration_lists.html]
 [test_bug892929.html]
 [test_cascade.html]
deleted file mode 100644
--- a/layout/style/test/test_bug771043.html
+++ /dev/null
@@ -1,67 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=771043
--->
-<head>
-  <meta charset="utf-8">
-  <title>Test for Bug 771043</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-  <script type="application/javascript">
-
-  /** Test for Bug 771043 **/
-  var expectedValue;
-  var callCount = 0;
-  var storedHeight;
-  function callback(arg) {
-    ++callCount;
-    is(arg.matches, expectedValue,
-       "Should have the right value on call #" + callCount + " to the callback");
-  }
-
-  function flushLayout() {
-    storedHeight = document.querySelector("iframe").offsetHeight;
-  }
-
-  function setHeight(height, reason) {
-    var oldCount = callCount;
-    var ifr = document.querySelector("iframe");
-    ifr.style.height = height + "px";
-    flushLayout();
-    is(callCount, oldCount+1, "Should have called our callback when " + reason);
-  }
-
-  SimpleTest.waitForExplicitFinish();
-  addLoadEvent(function() {
-    var mql = frames[0].matchMedia("(orientation: landscape)");
-    mql.addListener(callback);
-    expectedValue = true;
-    setHeight(50, "going landscape");
-    expectedValue = false;
-    setHeight(200, "going portrait");
-
-    var ifr = document.querySelector("iframe");
-    ifr.style.display = "none";
-    flushLayout();
-    ifr.style.display = "";
-    expectedValue = true;
-    setHeight(50, "going landscape from display:none");
-
-    expectedValue = false;
-    setHeight(200, "going portrait after display:none");
-    SimpleTest.finish();
-  });
-  </script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=771043">Mozilla Bug 771043</a>
-<!-- Important: the iframe needs to be displayed -->
-<p id="display"><iframe style="width: 100px; height: 200px"</p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-</pre>
-</body>
-</html>