Bug 1199131 - Crash when click on a SELECT wich has at least 1 OPTION with background-attachment:fixed and a background. r=mstange, a=lizzard
authorTimothy Nikkel <tnikkel@gmail.com>
Mon, 09 Nov 2015 03:00:00 +0100
changeset 296671 c6d927b2b229
parent 296670 0056c6a320b7
child 296672 b199ea9f265c
child 296677 8dbe32e326fd
child 296680 6735ab09c616
push id5280
push usercbook@mozilla.com
push date2015-11-09 13:40 +0000
treeherdermozilla-beta@c6d927b2b229 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmstange, lizzard
bugs1199131, 1156238
milestone43.0
Bug 1199131 - Crash when click on a SELECT wich has at least 1 OPTION with background-attachment:fixed and a background. r=mstange, a=lizzard Bug 1156238. At minimum always use the root reference frame as the "stop at" ancestor when finding the animated geometry root. * * * Bug 1156238. Skip setting async scroll clips if we aren't painting to the window because they are useless then. r=mstange Displayports only get acted upon when painting to the window, and the async scroll clips only get computed when we use a displayport. In addition we change an assert because if we are painting to the window then our root reference frame is either a root frame, or a popup frame. In either case we should not be able to get to out of flows outside of the frame subtree rooted at the root reference frame by following placeholders.
layout/base/FrameLayerBuilder.cpp
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/generic/nsFrame.cpp
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -1025,18 +1025,19 @@ public:
     mContainerReferenceFrame =
       const_cast<nsIFrame*>(aContainerItem ? aContainerItem->ReferenceFrameForChildren() :
                                              mBuilder->FindReferenceFrameFor(mContainerFrame));
     bool isAtRoot = !aContainerItem || (aContainerItem->Frame() == mBuilder->RootReferenceFrame());
     MOZ_ASSERT_IF(isAtRoot, mContainerReferenceFrame == mBuilder->RootReferenceFrame());
     mContainerAnimatedGeometryRoot = isAtRoot
       ? mContainerReferenceFrame
       : nsLayoutUtils::GetAnimatedGeometryRootFor(aContainerItem, aBuilder, aManager);
-    MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(mBuilder->RootReferenceFrame(),
-                                                      mContainerAnimatedGeometryRoot));
+    MOZ_ASSERT(!mBuilder->IsPaintingToWindow() ||
+      nsLayoutUtils::IsAncestorFrameCrossDoc(mBuilder->RootReferenceFrame(),
+                                             mContainerAnimatedGeometryRoot));
     NS_ASSERTION(!aContainerItem || !aContainerItem->ShouldFixToViewport(aManager),
                  "Container items never return true for ShouldFixToViewport");
     mContainerFixedPosFrame =
         FindFixedPosFrameForLayerData(mContainerAnimatedGeometryRoot, false);
     // When AllowResidualTranslation is false, display items will be drawn
     // scaled with a translation by integer pixels, so we know how the snapping
     // will work.
     mSnappingEnabled = aManager->IsSnappingEffectiveTransforms() &&
@@ -4582,16 +4583,22 @@ void
 ContainerState::SetupScrollingMetadata(NewLayerEntry* aEntry)
 {
   if (mFlattenToSingleLayer) {
     // animated geometry roots are forced to all match, so we can't
     // use them and we don't get async scrolling.
     return;
   }
 
+  if (!mBuilder->IsPaintingToWindow()) {
+    // async scrolling not possible, and async scrolling info not computed
+    // for this paint.
+    return;
+  }
+
   nsAutoTArray<FrameMetrics,2> metricsArray;
   if (aEntry->mBaseFrameMetrics) {
     metricsArray.AppendElement(*aEntry->mBaseFrameMetrics);
 
     // The base FrameMetrics was not computed by the nsIScrollableframe, so it
     // should not have a mask layer.
     MOZ_ASSERT(!aEntry->mBaseFrameMetrics->GetMaskLayerIndex());
   }
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -1072,17 +1072,17 @@ nsDisplayListBuilder::GetCachedAnimatedG
                                                     nsIFrame** aOutResult)
 {
   AnimatedGeometryRootLookup lookup(aFrame, aStopAtAncestor);
   return mAnimatedGeometryRootCache.Get(lookup, aOutResult);
 }
 
 static nsIFrame*
 ComputeAnimatedGeometryRootFor(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
-                               const nsIFrame* aStopAtAncestor = nullptr,
+                               const nsIFrame* aStopAtAncestor,
                                bool aUseCache = false)
 {
   nsIFrame* cursor = aFrame;
   while (cursor != aStopAtAncestor) {
     if (aUseCache) {
       nsIFrame* result;
       if (aBuilder->GetCachedAnimatedGeometryRoot(cursor, aStopAtAncestor, &result)) {
         return result;
@@ -1107,18 +1107,19 @@ nsDisplayListBuilder::FindAnimatedGeomet
   AnimatedGeometryRootLookup lookup(aFrame, aStopAtAncestor);
   mAnimatedGeometryRootCache.Put(lookup, result);
   return result;
 }
 
 void
 nsDisplayListBuilder::RecomputeCurrentAnimatedGeometryRoot()
 {
-  mCurrentAnimatedGeometryRoot = ComputeAnimatedGeometryRootFor(this, const_cast<nsIFrame *>(mCurrentFrame));
-  AnimatedGeometryRootLookup lookup(mCurrentFrame, nullptr);
+  mCurrentAnimatedGeometryRoot =
+    ComputeAnimatedGeometryRootFor(this, const_cast<nsIFrame *>(mCurrentFrame), mReferenceFrame);
+  AnimatedGeometryRootLookup lookup(mCurrentFrame, mReferenceFrame);
   mAnimatedGeometryRootCache.Put(lookup, mCurrentAnimatedGeometryRoot);
 }
 
 void
 nsDisplayListBuilder::AdjustWindowDraggingRegion(nsIFrame* aFrame)
 {
   if (!mWindowDraggingAllowed || !IsForPainting()) {
     return;
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -213,17 +213,17 @@ public:
    * returning the next ancestor to check.
    */
   bool IsAnimatedGeometryRoot(nsIFrame* aFrame, nsIFrame** aParent = nullptr);
 
   /**
    * Returns the nearest ancestor frame to aFrame that is considered to have
    * (or will have) animated geometry. This can return aFrame.
    */
-  nsIFrame* FindAnimatedGeometryRootFor(nsIFrame* aFrame, const nsIFrame* aStopAtAncestor = nullptr);
+  nsIFrame* FindAnimatedGeometryRootFor(nsIFrame* aFrame, const nsIFrame* aStopAtAncestor);
 
   /**
    * @return the root of the display list's frame (sub)tree, whose origin
    * establishes the coordinate system for the display list
    */
   nsIFrame* RootReferenceFrame() 
   {
     return mReferenceFrame;
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1355,22 +1355,27 @@ nsLayoutUtils::GetAfterFrameForContent(n
 /*static*/ nsIFrame*
 nsLayoutUtils::GetAfterFrame(nsIFrame* aFrame)
 {
   return GetAfterFrameForContent(aFrame, aFrame->GetContent());
 }
 
 // static
 nsIFrame*
-nsLayoutUtils::GetClosestFrameOfType(nsIFrame* aFrame, nsIAtom* aFrameType)
+nsLayoutUtils::GetClosestFrameOfType(nsIFrame* aFrame,
+                                     nsIAtom* aFrameType,
+                                     nsIFrame* aStopAt)
 {
   for (nsIFrame* frame = aFrame; frame; frame = frame->GetParent()) {
     if (frame->GetType() == aFrameType) {
       return frame;
     }
+    if (frame == aStopAt) {
+      break;
+    }
   }
   return nullptr;
 }
 
 // static
 nsIFrame*
 nsLayoutUtils::GetStyleFrame(nsIFrame* aFrame)
 {
@@ -1848,20 +1853,21 @@ nsLayoutUtils::GetAnimatedGeometryRootFo
 {
   nsIFrame* f = aItem->Frame();
   if (aItem->ShouldFixToViewport(aManager)) {
     // Make its active scrolled root be the active scrolled root of
     // the enclosing viewport, since it shouldn't be scrolled by scrolled
     // frames in its document. InvalidateFixedBackgroundFramesFromList in
     // nsGfxScrollFrame will not repaint this item when scrolling occurs.
     nsIFrame* viewportFrame =
-      nsLayoutUtils::GetClosestFrameOfType(f, nsGkAtoms::viewportFrame);
-    NS_ASSERTION(viewportFrame, "no viewport???");
-    return GetAnimatedGeometryRootForFrame(aBuilder, viewportFrame,
-        aBuilder->FindReferenceFrameFor(viewportFrame));
+      nsLayoutUtils::GetClosestFrameOfType(f, nsGkAtoms::viewportFrame, aBuilder->RootReferenceFrame());
+    if (viewportFrame) {
+      return GetAnimatedGeometryRootForFrame(aBuilder, viewportFrame,
+          aBuilder->FindReferenceFrameFor(viewportFrame));
+    }
   }
   return GetAnimatedGeometryRootForFrame(aBuilder, f, aItem->ReferenceFrame());
 }
 
 // static
 nsIScrollableFrame*
 nsLayoutUtils::GetNearestScrollableFrameForDirection(nsIFrame* aFrame,
                                                      Direction aDirection)
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -268,20 +268,23 @@ public:
   static nsIFrame* GetAfterFrame(nsIFrame* aFrame);
 
   /**
    * Given a frame, search up the frame tree until we find an
    * ancestor that (or the frame itself) is of type aFrameType, if any.
    *
    * @param aFrame the frame to start at
    * @param aFrameType the frame type to look for
+   * @param aStopAt a frame to stop at after we checked it
    * @return a frame of the given type or nullptr if no
    *         such ancestor exists
    */
-  static nsIFrame* GetClosestFrameOfType(nsIFrame* aFrame, nsIAtom* aFrameType);
+  static nsIFrame* GetClosestFrameOfType(nsIFrame* aFrame,
+                                         nsIAtom* aFrameType,
+                                         nsIFrame* aStopAt = nullptr);
 
   /**
    * Given a frame, search up the frame tree until we find an
    * ancestor that (or the frame itself) is a "Page" frame, if any.
    *
    * @param aFrame the frame to start at
    * @return a frame of type nsGkAtoms::pageFrame or nullptr if no
    *         such ancestor exists
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2539,22 +2539,25 @@ nsIFrame::BuildDisplayListForChild(nsDis
     child->MarkAbsoluteFramesForDisplayList(aBuilder, dirty);
 
     if (!pseudoStackingContext) {
       // THIS IS THE COMMON CASE.
       // Not a pseudo or real stacking context. Do the simple thing and
       // return early.
 
       if (aBuilder->IsBuildingLayerEventRegions()) {
+        const nsIFrame* rootReferenceFrame = aBuilder->RootReferenceFrame();
         MOZ_ASSERT(buildingForChild.GetPrevAnimatedGeometryRoot() ==
-                   aBuilder->FindAnimatedGeometryRootFor(child->GetParent()));
+                   aBuilder->FindAnimatedGeometryRootFor(child->GetParent(),
+                                                         rootReferenceFrame));
 
         // If this frame has a different animated geometry root than its parent,
         // make sure we accumulate event regions for its layer.
-        nsIFrame *animatedGeometryRoot = aBuilder->FindAnimatedGeometryRootFor(child);
+        nsIFrame *animatedGeometryRoot =
+          aBuilder->FindAnimatedGeometryRootFor(child, rootReferenceFrame);
         if (animatedGeometryRoot != buildingForChild.GetPrevAnimatedGeometryRoot()) {
           nsDisplayLayerEventRegions* eventRegions =
             new (aBuilder) nsDisplayLayerEventRegions(aBuilder, child);
           aBuilder->SetLayerEventRegions(eventRegions);
           aLists.BorderBackground()->AppendNewToTop(eventRegions);
         }
       }