From 0ed88b02bfb0e8f2ffc435a79f214592fad7f037 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Wed, 7 Mar 2018 15:40:42 +1300 Subject: [PATCH 01/23] Bug 1438990 - Remove common clip count code from FrameLayerBuilder, as it's no longer necessary now that we have ASRs. r=mstange --- layout/painting/DisplayItemClip.cpp | 48 +++------- layout/painting/DisplayItemClip.h | 19 +--- layout/painting/FrameLayerBuilder.cpp | 127 +++++--------------------- layout/painting/FrameLayerBuilder.h | 3 +- 4 files changed, 40 insertions(+), 157 deletions(-) diff --git a/layout/painting/DisplayItemClip.cpp b/layout/painting/DisplayItemClip.cpp index 0f16c7850fff..f553802d298b 100644 --- a/layout/painting/DisplayItemClip.cpp +++ b/layout/painting/DisplayItemClip.cpp @@ -91,11 +91,10 @@ DisplayItemClip::IntersectWith(const DisplayItemClip& aOther) void DisplayItemClip::ApplyTo(gfxContext* aContext, - int32_t A2D, - uint32_t aBegin, uint32_t aEnd) + int32_t A2D) { ApplyRectTo(aContext, A2D); - ApplyRoundedRectClipsTo(aContext, A2D, aBegin, aEnd); + ApplyRoundedRectClipsTo(aContext, A2D, 0, mRoundedClipRects.Length()); } void @@ -126,30 +125,27 @@ DisplayItemClip::ApplyRoundedRectClipsTo(gfxContext* aContext, void DisplayItemClip::FillIntersectionOfRoundedRectClips(gfxContext* aContext, const Color& aColor, - int32_t aAppUnitsPerDevPixel, - uint32_t aBegin, - uint32_t aEnd) const + int32_t aAppUnitsPerDevPixel) const { DrawTarget& aDrawTarget = *aContext->GetDrawTarget(); - aEnd = std::min(aEnd, mRoundedClipRects.Length()); - - if (aBegin >= aEnd) { + uint32_t end = mRoundedClipRects.Length(); + if (!end) { return; } // Push clips for any rects that come BEFORE the rect at |aEnd - 1|, if any: - ApplyRoundedRectClipsTo(aContext, aAppUnitsPerDevPixel, aBegin, aEnd - 1); + ApplyRoundedRectClipsTo(aContext, aAppUnitsPerDevPixel, 0, end - 1); // Now fill the rect at |aEnd - 1|: RefPtr roundedRect = MakeRoundedRectPath(aDrawTarget, aAppUnitsPerDevPixel, - mRoundedClipRects[aEnd - 1]); + mRoundedClipRects[end - 1]); ColorPattern color(ToDeviceColor(aColor)); aDrawTarget.Fill(roundedRect, color); // Finally, pop any clips that we may have pushed: - for (uint32_t i = aBegin; i < aEnd - 1; ++i) { + for (uint32_t i = 0; i < end - 1; ++i) { aContext->PopClip(); } } @@ -358,16 +354,13 @@ AccumulateRectDifference(const nsRect& aR1, const nsRect& aR2, const nsRect& aBo } void -DisplayItemClip::AddOffsetAndComputeDifference(uint32_t aStart, - const nsPoint& aOffset, +DisplayItemClip::AddOffsetAndComputeDifference(const nsPoint& aOffset, const nsRect& aBounds, const DisplayItemClip& aOther, - uint32_t aOtherStart, const nsRect& aOtherBounds, nsRegion* aDifference) { if (mHaveClipRect != aOther.mHaveClipRect || - aStart != aOtherStart || mRoundedClipRects.Length() != aOther.mRoundedClipRects.Length()) { aDifference->Or(*aDifference, aBounds); aDifference->Or(*aDifference, aOtherBounds); @@ -378,7 +371,7 @@ DisplayItemClip::AddOffsetAndComputeDifference(uint32_t aStart, aBounds.Union(aOtherBounds), aDifference); } - for (uint32_t i = aStart; i < mRoundedClipRects.Length(); ++i) { + for (uint32_t i = 0; i < mRoundedClipRects.Length(); ++i) { if (mRoundedClipRects[i] + aOffset != aOther.mRoundedClipRects[i]) { // The corners make it tricky so we'll just add both rects here. aDifference->Or(*aDifference, mRoundedClipRects[i].mRect.Intersect(aBounds)); @@ -387,27 +380,10 @@ DisplayItemClip::AddOffsetAndComputeDifference(uint32_t aStart, } } -uint32_t -DisplayItemClip::GetCommonRoundedRectCount(const DisplayItemClip& aOther, - uint32_t aMax) const -{ - uint32_t end = std::min(std::min(mRoundedClipRects.Length(), size_t(aMax)), - aOther.mRoundedClipRects.Length()); - uint32_t clipCount = 0; - for (; clipCount < end; ++clipCount) { - if (mRoundedClipRects[clipCount] != - aOther.mRoundedClipRects[clipCount]) { - return clipCount; - } - } - return clipCount; -} - void -DisplayItemClip::AppendRoundedRects(nsTArray* aArray, uint32_t aCount) const +DisplayItemClip::AppendRoundedRects(nsTArray* aArray) const { - size_t count = std::min(mRoundedClipRects.Length(), size_t(aCount)); - aArray->AppendElements(mRoundedClipRects.Elements(), count); + aArray->AppendElements(mRoundedClipRects.Elements(), mRoundedClipRects.Length()); } bool diff --git a/layout/painting/DisplayItemClip.h b/layout/painting/DisplayItemClip.h index 1ef0601f193a..60a34a9b43bb 100644 --- a/layout/painting/DisplayItemClip.h +++ b/layout/painting/DisplayItemClip.h @@ -81,8 +81,7 @@ public: // Apply this |DisplayItemClip| to the given gfxContext. Any saving of state // or clearing of other clips must be done by the caller. // See aBegin/aEnd note on ApplyRoundedRectsTo. - void ApplyTo(gfxContext* aContext, int32_t A2D, - uint32_t aBegin = 0, uint32_t aEnd = UINT32_MAX); + void ApplyTo(gfxContext* aContext, int32_t A2D); void ApplyRectTo(gfxContext* aContext, int32_t A2D) const; // Applies the rounded rects in this Clip to aContext @@ -94,9 +93,7 @@ public: // Draw (fill) the rounded rects in this clip to aContext void FillIntersectionOfRoundedRectClips(gfxContext* aContext, const Color& aColor, - int32_t aAppUnitsPerDevPixel, - uint32_t aBegin, - uint32_t aEnd) const; + int32_t aAppUnitsPerDevPixel) const; // 'Draw' (create as a path, does not stroke or fill) aRoundRect to aContext already_AddRefed MakeRoundedRectPath(DrawTarget& aDrawTarget, int32_t A2D, @@ -148,8 +145,8 @@ public: // Adds the difference between Intersect(*this + aPoint, aBounds) and // Intersect(aOther, aOtherBounds) to aDifference (or a bounding-box thereof). - void AddOffsetAndComputeDifference(uint32_t aStart, const nsPoint& aPoint, const nsRect& aBounds, - const DisplayItemClip& aOther, uint32_t aOtherStart, const nsRect& aOtherBounds, + void AddOffsetAndComputeDifference(const nsPoint& aPoint, const nsRect& aBounds, + const DisplayItemClip& aOther, const nsRect& aOtherBounds, nsRegion* aDifference); bool operator==(const DisplayItemClip& aOther) const { @@ -172,14 +169,8 @@ public: nsCString ToString() const; - /** - * Find the largest N such that the first N rounded rects in 'this' are - * equal to the first N rounded rects in aOther, and N <= aMax. - */ - uint32_t GetCommonRoundedRectCount(const DisplayItemClip& aOther, - uint32_t aMax) const; uint32_t GetRoundedRectCount() const { return mRoundedClipRects.Length(); } - void AppendRoundedRects(nsTArray* aArray, uint32_t aCount) const; + void AppendRoundedRects(nsTArray* aArray) const; void ToComplexClipRegions(int32_t aAppUnitsPerDevPixel, const layers::StackingContextHelper& aSc, diff --git a/layout/painting/FrameLayerBuilder.cpp b/layout/painting/FrameLayerBuilder.cpp index 4cbd4c7f9de5..8056b96f53a0 100644 --- a/layout/painting/FrameLayerBuilder.cpp +++ b/layout/painting/FrameLayerBuilder.cpp @@ -449,7 +449,6 @@ public: mShouldPaintOnContentSide(false), mDTCRequiresTargetConfirmation(false), mImage(nullptr), - mCommonClipCount(-1), mNewChildLayersIndex(-1) {} @@ -661,24 +660,10 @@ public: * no part at all. */ DisplayItemClip mItemClip; - /** - * The first mCommonClipCount rounded rectangle clips are identical for - * all items in the layer. - * -1 if there are no items in the layer; must be >=0 by the time that this - * data is popped from the stack. - */ - int32_t mCommonClipCount; /** * Index of this layer in mNewChildLayers. */ int32_t mNewChildLayersIndex; - /* - * Updates mCommonClipCount by checking for rounded rect clips in common - * between the clip on a new item (aCurrentClip) and the common clips - * on items already in the layer (the first mCommonClipCount rounded rects - * in mItemClip). - */ - void UpdateCommonClipCount(const DisplayItemClip& aCurrentClip); /** * The region of visible content above the layer and below the * next PaintedLayerData currently in the stack, if any. @@ -1385,12 +1370,8 @@ protected: * aLayer is the layer to be clipped. * relative to the container reference frame * aRoundedRectClipCount is used when building mask layers for PaintedLayers, - * SetupMaskLayer will build a mask layer for only the first - * aRoundedRectClipCount rounded rects in aClip - * Returns the number of rounded rects included in the mask layer. */ - uint32_t SetupMaskLayer(Layer *aLayer, const DisplayItemClip& aClip, - uint32_t aRoundedRectClipCount = UINT32_MAX); + void SetupMaskLayer(Layer *aLayer, const DisplayItemClip& aClip); /** * If |aClip| has rounded corners, create a mask layer for them, and @@ -1410,8 +1391,7 @@ protected: already_AddRefed CreateMaskLayer( Layer *aLayer, const DisplayItemClip& aClip, - const Maybe& aForAncestorMaskLayer, - uint32_t aRoundedRectClipCount = UINT32_MAX); + const Maybe& aForAncestorMaskLayer); /** * Get the display port for an AGR. @@ -1498,8 +1478,6 @@ class PaintedDisplayItemLayerUserData : public LayerUserData { public: PaintedDisplayItemLayerUserData() : - mMaskClipCount(0), - mLastCommonClipCount(0), mForcedBackgroundColor(NS_RGBA(0,0,0,0)), mXScale(1.f), mYScale(1.f), mAppUnitsPerDevPixel(0), @@ -1511,19 +1489,6 @@ public: NS_INLINE_DECL_REFCOUNTING(PaintedDisplayItemLayerUserData); - /** - * Record the number of clips in the PaintedLayer's mask layer. - * Should not be reset when the layer is recycled since it is used to track - * changes in the use of mask layers. - */ - uint32_t mMaskClipCount; - - /** - * Records the number of clips in the PaintedLayer's mask layer during - * the previous paint. Used for invalidation. - */ - uint32_t mLastCommonClipCount; - /** * A color that should be painted over the bounds of the layer's visible * region before any other content is painted. @@ -1640,7 +1605,6 @@ struct MaskLayerUserData : public LayerUserData , mAppUnitsPerDevPixel(-1) { } MaskLayerUserData(const DisplayItemClip& aClip, - uint32_t aRoundedRectClipCount, int32_t aAppUnitsPerDevPixel, const ContainerLayerParameters& aParams) : mScaleX(aParams.mXScale) @@ -1648,7 +1612,7 @@ struct MaskLayerUserData : public LayerUserData , mOffset(aParams.mOffset) , mAppUnitsPerDevPixel(aAppUnitsPerDevPixel) { - aClip.AppendRoundedRects(&mRoundedClipRects, aRoundedRectClipCount); + aClip.AppendRoundedRects(&mRoundedClipRects); } void operator=(MaskLayerUserData&& aOther) @@ -2500,7 +2464,6 @@ ContainerState::PreparePaintedLayerForUse(PaintedLayer* aLayer, aData->mLastPaintOffset = GetTranslationForPaintedLayer(aLayer); aData->mHasExplicitLastPaintOffset = true; - aData->mLastCommonClipCount = aData->mMaskClipCount; // Set up transform so that 0,0 in the PaintedLayer corresponds to the // (pixel-snapped) top-left of the aAnimatedGeometryRoot. @@ -2763,18 +2726,6 @@ PaintedLayerDataNode::FindOpaqueBackgroundColorInParentNode() const return mTree.UniformBackgroundColor(); } -void -PaintedLayerData::UpdateCommonClipCount( - const DisplayItemClip& aCurrentClip) -{ - if (mCommonClipCount >= 0) { - mCommonClipCount = mItemClip.GetCommonRoundedRectCount(aCurrentClip, mCommonClipCount); - } else { - // first item in the layer - mCommonClipCount = aCurrentClip.GetRoundedRectCount(); - } -} - bool PaintedLayerData::CanOptimizeToImageLayer(nsDisplayListBuilder* aBuilder) { @@ -3361,22 +3312,7 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB data->mLayer->InvalidateWholeLayer(); } userData->mForcedBackgroundColor = backgroundColor; - - // use a mask layer for rounded rect clipping. - // data->mCommonClipCount may be -1 if we haven't put any actual - // drawable items in this layer (i.e. it's only catching events). - uint32_t commonClipCount; - commonClipCount = std::max(0, data->mCommonClipCount); - - // if the number of clips we are going to mask has decreased, then aLayer might have - // cached graphics which assume the existence of a soon-to-be non-existent mask layer - // in that case, invalidate the whole layer. - if (commonClipCount < userData->mMaskClipCount) { - PaintedLayer* painted = layer->AsPaintedLayer(); - painted->InvalidateWholeLayer(); - } - - userData->mMaskClipCount = SetupMaskLayer(layer, data->mItemClip, commonClipCount); + SetupMaskLayer(layer, data->mItemClip); } else { // mask layer for image and color layers SetupMaskLayer(layer, data->mItemClip); @@ -4019,8 +3955,7 @@ ContainerState::SetupMaskLayerForScrolledClip(Layer* aLayer, { if (aClip.GetRoundedRectCount() > 0) { Maybe maskLayerIndex = Some(aLayer->GetAncestorMaskLayerCount()); - if (RefPtr maskLayer = CreateMaskLayer(aLayer, aClip, maskLayerIndex, - aClip.GetRoundedRectCount())) { + if (RefPtr maskLayer = CreateMaskLayer(aLayer, aClip, maskLayerIndex)) { aLayer->AddAncestorMaskLayer(maskLayer); return maskLayerIndex; } @@ -4687,11 +4622,6 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList) static_cast(item); paintedLayerData->AccumulateHitTestInfo(this, hitTestInfo); } else { - // check to see if the new item has rounded rect clips in common with - // other items in the layer - if (mManager->IsWidgetLayerManager()) { - paintedLayerData->UpdateCommonClipCount(itemClip); - } paintedLayerData->Accumulate(this, item, itemVisibleRect, itemClip, layerState, aList); if (!paintedLayerData->mLayer) { @@ -4820,11 +4750,9 @@ FrameLayerBuilder::ComputeGeometryChangeForItem(DisplayItemData* aData) if (!combined.IsEmpty() || aData->mLayerState == LAYER_INACTIVE) { geometry = item->AllocateGeometry(mDisplayListBuilder); } - aData->mClip.AddOffsetAndComputeDifference(layerData->mMaskClipCount, - shift, aData->mGeometry->ComputeInvalidationRegion(), - clip, layerData->mLastCommonClipCount, - geometry ? geometry->ComputeInvalidationRegion() : - aData->mGeometry->ComputeInvalidationRegion(), + aData->mClip.AddOffsetAndComputeDifference(shift, aData->mGeometry->ComputeInvalidationRegion(), + clip, geometry ? geometry->ComputeInvalidationRegion() : + aData->mGeometry->ComputeInvalidationRegion(), &combined); // Add in any rect that the frame specified @@ -5308,7 +5236,7 @@ ContainerState::SetupScrollingMetadata(NewLayerEntry* aEntry) // layer as an additional, separate clip. Maybe nextIndex = Some(maskLayers.Length()); RefPtr maskLayer = - CreateMaskLayer(aEntry->mLayer, *clip, nextIndex, clip->GetRoundedRectCount()); + CreateMaskLayer(aEntry->mLayer, *clip, nextIndex); if (maskLayer) { MOZ_ASSERT(metadata->HasScrollClip()); metadata->ScrollClip().SetMaskLayerIndex(nextIndex); @@ -6034,8 +5962,7 @@ FrameLayerBuilder::PaintItems(nsTArray& aItems, nsDisplayListBuilder* aBuilder, nsPresContext* aPresContext, const nsIntPoint& aOffset, - float aXScale, float aYScale, - int32_t aCommonClipCount) + float aXScale, float aYScale) { DrawTarget& aDrawTarget = *aContext->GetDrawTarget(); @@ -6084,9 +6011,7 @@ FrameLayerBuilder::PaintItems(nsTArray& aItems, if (currentClipIsSetInContext) { currentClip = *clip; aContext->Save(); - NS_ASSERTION(aCommonClipCount < 100, - "Maybe you really do have more than a hundred clipping rounded rects, or maybe something has gone wrong."); - currentClip.ApplyTo(aContext, aPresContext->AppUnitsPerDevPixel(), aCommonClipCount); + currentClip.ApplyTo(aContext, aPresContext->AppUnitsPerDevPixel()); aContext->NewPath(); } } @@ -6249,8 +6174,7 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer, layerBuilder->PaintItems(userData->mItems, iterRect, aContext, builder, presContext, - offset, userData->mXScale, userData->mYScale, - userData->mMaskClipCount); + offset, userData->mXScale, userData->mYScale); if (gfxPrefs::GfxLoggingPaintedPixelCountEnabled()) { aLayer->Manager()->AddPaintedPixelCount(iterRect.Area()); } @@ -6265,8 +6189,7 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer, layerBuilder->PaintItems(userData->mItems, aRegionToDraw.GetBounds(), aContext, builder, presContext, - offset, userData->mXScale, userData->mYScale, - userData->mMaskClipCount); + offset, userData->mXScale, userData->mYScale); if (gfxPrefs::GfxLoggingPaintedPixelCountEnabled()) { aLayer->Manager()->AddPaintedPixelCount( aRegionToDraw.GetBounds().Area()); @@ -6343,26 +6266,23 @@ CalculateBounds(const nsTArray& aRects, int32_t aA return gfx::Rect(bounds.ToNearestPixels(aAppUnitsPerDevPixel)); } -uint32_t +void ContainerState::SetupMaskLayer(Layer *aLayer, - const DisplayItemClip& aClip, - uint32_t aRoundedRectClipCount) + const DisplayItemClip& aClip) { // don't build an unnecessary mask - if (aClip.GetRoundedRectCount() == 0 || - aRoundedRectClipCount == 0) { - return 0; + if (aClip.GetRoundedRectCount() == 0) { + return; } RefPtr maskLayer = - CreateMaskLayer(aLayer, aClip, Nothing(), aRoundedRectClipCount); + CreateMaskLayer(aLayer, aClip, Nothing()); if (!maskLayer) { - return 0; + return; } aLayer->SetMaskLayer(maskLayer); - return aRoundedRectClipCount; } static MaskLayerUserData* @@ -6387,8 +6307,7 @@ SetMaskLayerUserData(Layer* aMaskLayer) already_AddRefed ContainerState::CreateMaskLayer(Layer *aLayer, const DisplayItemClip& aClip, - const Maybe& aForAncestorMaskLayer, - uint32_t aRoundedRectClipCount) + const Maybe& aForAncestorMaskLayer) { // aLayer will never be the container layer created by an nsDisplayMask // because nsDisplayMask propagates the DisplayItemClip to its contents @@ -6405,7 +6324,7 @@ ContainerState::CreateMaskLayer(Layer *aLayer, MaskLayerUserData* userData = GetMaskLayerUserData(maskLayer.get()); int32_t A2D = mContainerFrame->PresContext()->AppUnitsPerDevPixel(); - MaskLayerUserData newData(aClip, aRoundedRectClipCount, A2D, mParameters); + MaskLayerUserData newData(aClip, A2D, mParameters); if (*userData == newData) { return maskLayer.forget(); } @@ -6485,9 +6404,7 @@ ContainerState::CreateMaskLayer(Layer *aLayer, // paint the clipping rects with alpha to create the mask aClip.FillIntersectionOfRoundedRectClips(context, Color(1.f, 1.f, 1.f, 1.f), - newData.mAppUnitsPerDevPixel, - 0, - aRoundedRectClipCount); + newData.mAppUnitsPerDevPixel); // build the image and container MOZ_ASSERT(aLayer->Manager() == mManager); diff --git a/layout/painting/FrameLayerBuilder.h b/layout/painting/FrameLayerBuilder.h index de4b7cc46485..6e0108daff8c 100644 --- a/layout/painting/FrameLayerBuilder.h +++ b/layout/painting/FrameLayerBuilder.h @@ -674,8 +674,7 @@ protected: nsDisplayListBuilder* aBuilder, nsPresContext* aPresContext, const nsIntPoint& aOffset, - float aXScale, float aYScale, - int32_t aCommonClipCount); + float aXScale, float aYScale); /** * We accumulate ClippedDisplayItem elements in a hashtable during From e415dc84fdd156ad306aea5a02070a30c623052e Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Wed, 7 Mar 2018 15:42:43 +1300 Subject: [PATCH 02/23] Bug 1440966 - Store optimized Layer in DisplayItemData as part of AddPaintedLayerFor. r=jnicol --- layout/painting/FrameLayerBuilder.cpp | 47 ++++++++++----------------- layout/painting/FrameLayerBuilder.h | 12 ++----- 2 files changed, 19 insertions(+), 40 deletions(-) diff --git a/layout/painting/FrameLayerBuilder.cpp b/layout/painting/FrameLayerBuilder.cpp index 8056b96f53a0..a16b9df53ce1 100644 --- a/layout/painting/FrameLayerBuilder.cpp +++ b/layout/painting/FrameLayerBuilder.cpp @@ -2011,19 +2011,6 @@ FrameLayerBuilder::DidBeginRetainedLayerTransaction(LayerManager* aManager) } } -void -FrameLayerBuilder::StoreOptimizedLayerForFrame(nsDisplayItem* aItem, Layer* aLayer) -{ - if (!mRetainingManager) { - return; - } - - DisplayItemData* data = GetDisplayItemDataForManager(aItem, aLayer->Manager()); - NS_ASSERTION(data, "Must have already stored data for this item!"); - data->mOptLayer = aLayer; - data->mItem = nullptr; -} - void FrameLayerBuilder::DidEndTransaction() { @@ -3192,16 +3179,6 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB mNewChildLayers[data->mNewChildLayersIndex].mLayer = paintedLayer.forget(); } - for (auto& item : data->mAssignedDisplayItems) { - MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_LAYER_EVENT_REGIONS); - MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO); - - InvalidateForLayerChange(item.mItem, data->mLayer, item.mDisplayItemData); - mLayerBuilder->AddPaintedDisplayItem(data, item, *this, - data->mAnimatedGeometryRootOffset); - item.mDisplayItemData = nullptr; - } - PaintedDisplayItemLayerUserData* userData = GetPaintedDisplayItemLayerUserData(data->mLayer); NS_ASSERTION(userData, "where did our user data go?"); userData->mLastItemCount = data->mAssignedDisplayItems.Length(); @@ -3246,10 +3223,6 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB data->mLayer->SetVisibleRegion(LayerIntRegion()); data->mLayer->InvalidateWholeLayer(); data->mLayer->SetEventRegions(EventRegions()); - - for (auto& item : data->mAssignedDisplayItems) { - mLayerBuilder->StoreOptimizedLayerForFrame(item.mItem, layer); - } } } @@ -3260,6 +3233,15 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB FLB_LOG_PAINTED_LAYER_DECISION(data, " Selected painted layer=%p\n", layer.get()); } + for (auto& item : data->mAssignedDisplayItems) { + MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_LAYER_EVENT_REGIONS); + MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO); + + InvalidateForLayerChange(item.mItem, data->mLayer, item.mDisplayItemData); + mLayerBuilder->AddPaintedDisplayItem(data, item, *this, layer); + item.mDisplayItemData = nullptr; + } + if (mLayerBuilder->IsBuildingRetainedLayers()) { newLayerEntry->mVisibleRegion = data->mVisibleRegion; newLayerEntry->mOpaqueRegion = data->mOpaqueRegion; @@ -4784,8 +4766,7 @@ FrameLayerBuilder::ComputeGeometryChangeForItem(DisplayItemData* aData) void FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, AssignedDisplayItem& aItem, - ContainerState& aContainerState, - const nsPoint& aTopLeft) + ContainerState& aContainerState) { PaintedLayer* layer = aLayerData->mLayer; PaintedDisplayItemLayerUserData* paintedData = @@ -4801,7 +4782,7 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, // We need to grab these before updating the DisplayItemData because it will overwrite them. nsRegion clip; if (aItem.mClip.ComputeRegionInClips(&aItem.mDisplayItemData->GetClip(), - aTopLeft - paintedData->mLastAnimatedGeometryRootOrigin, + aLayerData->mAnimatedGeometryRootOffset - paintedData->mLastAnimatedGeometryRootOrigin, &clip)) { intClip = clip.GetBounds().ScaleToOutsidePixels(paintedData->mXScale, paintedData->mYScale, @@ -4823,6 +4804,12 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, data = StoreDataForFrame(aItem.mItem, layer, aItem.mLayerState, nullptr); } data->mInactiveManager = tempManager; + // We optimized this PaintedLayer into a ColorLayer/ImageLayer. Store the optimized + // layer here. + if (aLayer != layer) { + data->mOptLayer = aLayer; + data->mItem = nullptr; + } } if (tempManager) { diff --git a/layout/painting/FrameLayerBuilder.h b/layout/painting/FrameLayerBuilder.h index 6e0108daff8c..7f70d75122c2 100644 --- a/layout/painting/FrameLayerBuilder.h +++ b/layout/painting/FrameLayerBuilder.h @@ -510,10 +510,10 @@ public: * aItem must have an underlying frame. * @param aTopLeft offset from active scrolled root to reference frame */ - void AddPaintedDisplayItem(PaintedLayerData* aLayer, + void AddPaintedDisplayItem(PaintedLayerData* aLayerData, AssignedDisplayItem& aAssignedDisplayItem, ContainerState& aContainerState, - const nsPoint& aTopLeft); + Layer* aLayer); /** * Calls GetOldLayerForFrame on the underlying frame of the display item, @@ -590,14 +590,6 @@ public: */ static gfxSize GetPaintedLayerScaleForFrame(nsIFrame* aFrame); - /** - * Stores a Layer as the dedicated layer in the DisplayItemData for a given frame/key pair. - * - * Used when we optimize a PaintedLayer into an ImageLayer and want to retroactively update the - * DisplayItemData so we can retrieve the layer from within layout. - */ - void StoreOptimizedLayerForFrame(nsDisplayItem* aItem, Layer* aLayer); - static void RemoveFrameFromLayerManager(const nsIFrame* aFrame, SmallPointerArray& aArray); From 74fea66ce5e1e248701e3b589f1270865a716444 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 5 Mar 2018 15:18:34 +1100 Subject: [PATCH 03/23] Bug 440908 - Remove gIsAnyPrefLocked. r=glandium It optimizes Preferences::IsLocked(), but that function is called fewer than 200 times while starting the browser and opening a range of tabs. MozReview-Commit-ID: 5q0zS8TSwdu --HG-- extra : rebase_source : 015c5ebbe28097ef3f02b1062e650df67721f1c3 --- modules/libpref/Preferences.cpp | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp index 920797e11cda..1bbc07eab893 100644 --- a/modules/libpref/Preferences.cpp +++ b/modules/libpref/Preferences.cpp @@ -820,8 +820,6 @@ static PLDHashTable* gHashTable; static CallbackNode* gFirstCallback = nullptr; static CallbackNode* gLastPriorityNode = nullptr; -static bool gIsAnyPrefLocked = false; - // These are only used during the call to NotifyCallbacks(). static bool gCallbacksInProgress = false; static bool gShouldCleanupDeadNodes = false; @@ -4185,7 +4183,6 @@ Preferences::LockInAnyProcess(const char* aPrefName) if (!pref->IsLocked()) { pref->SetIsLocked(true); - gIsAnyPrefLocked = true; NotifyCallbacks(aPrefName); } @@ -4223,14 +4220,8 @@ Preferences::IsLocked(const char* aPrefName) { NS_ENSURE_TRUE(InitStaticMembers(), false); - if (gIsAnyPrefLocked) { - Pref* pref = pref_HashTableLookup(aPrefName); - if (pref && pref->IsLocked()) { - return true; - } - } - - return false; + Pref* pref = pref_HashTableLookup(aPrefName); + return pref && pref->IsLocked(); } /* static */ nsresult From 038a72de3b1ecfdae2a5a106974e4a9b9eb0f491 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 2 Mar 2018 15:31:40 +1100 Subject: [PATCH 04/23] Bug 440908 - Add support for `sticky` and `locked` attributes to default prefs. r=glandium Sticky prefs are already specifiable with `sticky_pref`, but this is a more general attribute mechanism. The ability to specify a locked pref in the data file is new. The patch also adds nsIPrefService.readDefaultPrefsFromFile, to match the existing nsIPrefService.readUserPrefsFromFile method, and converts a number of the existing tests to use it. MozReview-Commit-ID: 9LLMBJVZfg7 --HG-- extra : rebase_source : fa25bad87c4d9fcba6dc13cd2cc04ea6a2354f51 --- modules/libpref/Preferences.cpp | 110 +++++++++----- modules/libpref/nsIPrefService.idl | 12 +- modules/libpref/parser/src/lib.rs | 92 +++++++++--- modules/libpref/test/gtest/Parser.cpp | 135 +++++++++++------- modules/libpref/test/unit/data/testParser.js | 9 +- .../libpref/test/unit/data/testPrefLocked.js | 2 + .../test/unit/data/testPrefLockedUser.js | 3 + .../test/unit/test_locked_file_prefs.js | 45 ++++++ modules/libpref/test/unit/test_parser.js | 7 +- modules/libpref/test/unit/test_stickyprefs.js | 31 ++-- modules/libpref/test/unit/xpcshell.ini | 2 + services/sync/tests/unit/test_prefs_store.js | 2 +- 12 files changed, 323 insertions(+), 127 deletions(-) create mode 100644 modules/libpref/test/unit/data/testPrefLocked.js create mode 100644 modules/libpref/test/unit/data/testPrefLockedUser.js create mode 100644 modules/libpref/test/unit/test_locked_file_prefs.js diff --git a/modules/libpref/Preferences.cpp b/modules/libpref/Preferences.cpp index 1bbc07eab893..330ed4a09b54 100644 --- a/modules/libpref/Preferences.cpp +++ b/modules/libpref/Preferences.cpp @@ -596,8 +596,9 @@ public: nsresult SetDefaultValue(PrefType aType, PrefValue aValue, - bool aFromFile, bool aIsSticky, + bool aIsLocked, + bool aFromFile, bool* aValueChanged) { // Types must always match when setting the default value. @@ -607,20 +608,25 @@ public: // Should we set the default value? Only if the pref is not locked, and // doing so would change the default value. - if (!IsLocked() && !ValueMatches(PrefValueKind::Default, aType, aValue)) { - mDefaultValue.Replace(Type(), aType, aValue); - mHasDefaultValue = true; - if (!aFromFile) { - mHasChangedSinceInit = true; + if (!IsLocked()) { + if (aIsLocked) { + SetIsLocked(true); } - if (aIsSticky) { - mIsSticky = true; + if (!ValueMatches(PrefValueKind::Default, aType, aValue)) { + mDefaultValue.Replace(Type(), aType, aValue); + mHasDefaultValue = true; + if (!aFromFile) { + mHasChangedSinceInit = true; + } + if (aIsSticky) { + mIsSticky = true; + } + if (!mHasUserValue) { + *aValueChanged = true; + } + // What if we change the default to be the same as the user value? + // Should we clear the user value? Currently we don't. } - if (!mHasUserValue) { - *aValueChanged = true; - } - // What if we change the default to be the same as the user value? - // Should we clear the user value? Currently we don't. } return NS_OK; } @@ -944,6 +950,7 @@ pref_SetPref(const char* aPrefName, PrefValueKind aKind, PrefValue aValue, bool aIsSticky, + bool aIsLocked, bool aFromFile) { MOZ_ASSERT(NS_IsMainThread()); @@ -966,9 +973,10 @@ pref_SetPref(const char* aPrefName, bool valueChanged = false; nsresult rv; if (aKind == PrefValueKind::Default) { - rv = - pref->SetDefaultValue(aType, aValue, aFromFile, aIsSticky, &valueChanged); + rv = pref->SetDefaultValue( + aType, aValue, aIsSticky, aIsLocked, aFromFile, &valueChanged); } else { + MOZ_ASSERT(!aIsLocked); // `locked` is disallowed in user pref files rv = pref->SetUserValue(aType, aValue, aFromFile, &valueChanged); } if (NS_FAILED(rv)) { @@ -1076,7 +1084,8 @@ typedef void (*PrefsParserPrefFn)(const char* aPrefName, PrefType aType, PrefValueKind aKind, PrefValue aValue, - bool aIsSticky); + bool aIsSticky, + bool aIsLocked); // Keep this in sync with ErrorFn in prefs_parser/src/lib.rs. // @@ -1087,6 +1096,7 @@ typedef void (*PrefsParserErrorFn)(const char* aMsg); // Keep this in sync with prefs_parser_parse() in prefs_parser/src/lib.rs. bool prefs_parser_parse(const char* aPath, + PrefValueKind aKind, const char* aBuf, size_t aLen, PrefsParserPrefFn aPrefFn, @@ -1100,13 +1110,14 @@ public: ~Parser() = default; bool Parse(const nsCString& aName, + PrefValueKind aKind, const char* aPath, const TimeStamp& aStartTime, const nsCString& aBuf) { sNumPrefs = 0; bool ok = prefs_parser_parse( - aPath, aBuf.get(), aBuf.Length(), HandlePref, HandleError); + aPath, aKind, aBuf.get(), aBuf.Length(), HandlePref, HandleError); if (!ok) { return false; } @@ -1128,11 +1139,17 @@ private: PrefType aType, PrefValueKind aKind, PrefValue aValue, - bool aIsSticky) + bool aIsSticky, + bool aIsLocked) { sNumPrefs++; - pref_SetPref( - aPrefName, aType, aKind, aValue, aIsSticky, /* fromFile */ true); + pref_SetPref(aPrefName, + aType, + aKind, + aValue, + aIsSticky, + aIsLocked, + /* fromFile */ true); } static void HandleError(const char* aMsg) @@ -1164,7 +1181,8 @@ TestParseErrorHandlePref(const char* aPrefName, PrefType aType, PrefValueKind aKind, PrefValue aValue, - bool aIsSticky) + bool aIsSticky, + bool aIsLocked) { } @@ -1179,9 +1197,10 @@ TestParseErrorHandleError(const char* aMsg) // Keep this in sync with the declaration in test/gtest/Parser.cpp. void -TestParseError(const char* aText, nsCString& aErrorMsg) +TestParseError(PrefValueKind aKind, const char* aText, nsCString& aErrorMsg) { prefs_parser_parse("test", + aKind, aText, strlen(aText), TestParseErrorHandlePref, @@ -2449,7 +2468,7 @@ Preferences::HandleDirty() } static nsresult -openPrefFile(nsIFile* aFile); +openPrefFile(nsIFile* aFile, PrefValueKind aKind); static const char kTelemetryPref[] = "toolkit.telemetry.enabled"; static const char kChannelPref[] = "app.update.channel"; @@ -3156,6 +3175,19 @@ Preferences::Observe(nsISupports* aSubject, return rv; } +NS_IMETHODIMP +Preferences::ReadDefaultPrefsFromFile(nsIFile* aFile) +{ + ENSURE_PARENT_PROCESS("Preferences::ReadDefaultPrefsFromFile", "all prefs"); + + if (!aFile) { + NS_ERROR("ReadDefaultPrefsFromFile requires a parameter"); + return NS_ERROR_INVALID_ARG; + } + + return openPrefFile(aFile, PrefValueKind::Default); +} + NS_IMETHODIMP Preferences::ReadUserPrefsFromFile(nsIFile* aFile) { @@ -3166,7 +3198,7 @@ Preferences::ReadUserPrefsFromFile(nsIFile* aFile) return NS_ERROR_INVALID_ARG; } - return openPrefFile(aFile); + return openPrefFile(aFile, PrefValueKind::User); } NS_IMETHODIMP @@ -3413,7 +3445,7 @@ Preferences::ReadSavedPrefs() return nullptr; } - rv = openPrefFile(file); + rv = openPrefFile(file, PrefValueKind::User); if (rv == NS_ERROR_FILE_NOT_FOUND) { // This is a normal case for new users. Telemetry::ScalarSet( @@ -3442,7 +3474,7 @@ Preferences::ReadUserOverridePrefs() } aFile->AppendNative(NS_LITERAL_CSTRING("user.js")); - rv = openPrefFile(aFile); + rv = openPrefFile(aFile, PrefValueKind::User); if (rv != NS_ERROR_FILE_NOT_FOUND) { // If the file exists and was at least partially read, record that in // telemetry as it may be a sign of pref injection. @@ -3584,7 +3616,7 @@ Preferences::WritePrefFile(nsIFile* aFile, SaveMethod aSaveMethod) } static nsresult -openPrefFile(nsIFile* aFile) +openPrefFile(nsIFile* aFile, PrefValueKind aKind) { TimeStamp startTime = TimeStamp::Now(); @@ -3600,7 +3632,7 @@ openPrefFile(nsIFile* aFile) Parser parser; if (!parser.Parse( - filename, NS_ConvertUTF16toUTF8(path).get(), startTime, data)) { + filename, aKind, NS_ConvertUTF16toUTF8(path).get(), startTime, data)) { return NS_ERROR_FILE_CORRUPTED; } @@ -3701,7 +3733,7 @@ pref_LoadPrefsInDir(nsIFile* aDir, uint32_t arrayCount = prefFiles.Count(); uint32_t i; for (i = 0; i < arrayCount; ++i) { - rv2 = openPrefFile(prefFiles[i]); + rv2 = openPrefFile(prefFiles[i], PrefValueKind::Default); if (NS_FAILED(rv2)) { NS_ERROR("Default pref file not parsed successfully."); rv = rv2; @@ -3713,7 +3745,7 @@ pref_LoadPrefsInDir(nsIFile* aDir, // This may be a sparse array; test before parsing. nsIFile* file = specialFiles[i]; if (file) { - rv2 = openPrefFile(file); + rv2 = openPrefFile(file, PrefValueKind::Default); if (NS_FAILED(rv2)) { NS_ERROR("Special default pref file not parsed successfully."); rv = rv2; @@ -3734,7 +3766,11 @@ pref_ReadPrefFromJar(nsZipArchive* aJarReader, const char* aName) URLPreloader::ReadZip(aJarReader, nsDependentCString(aName))); Parser parser; - if (!parser.Parse(nsDependentCString(aName), aName, startTime, manifest)) { + if (!parser.Parse(nsDependentCString(aName), + PrefValueKind::Default, + aName, + startTime, + manifest)) { return NS_ERROR_FILE_CORRUPTED; } @@ -3814,7 +3850,7 @@ Preferences::InitInitialObjects() rv = greprefsFile->AppendNative(NS_LITERAL_CSTRING("greprefs.js")); NS_ENSURE_SUCCESS(rv, Err("greprefsFile->AppendNative() failed")); - rv = openPrefFile(greprefsFile); + rv = openPrefFile(greprefsFile, PrefValueKind::Default); if (NS_FAILED(rv)) { NS_WARNING("Error parsing GRE default preferences. Is this an old-style " "embedding app?"); @@ -3943,15 +3979,14 @@ Preferences::InitInitialObjects() bool releaseCandidateOnBeta = false; if (!strcmp(NS_STRINGIFY(MOZ_UPDATE_CHANNEL), "release")) { nsAutoCString updateChannelPrefValue; - Preferences::GetCString(kChannelPref, updateChannelPrefValue, - PrefValueKind::Default); + Preferences::GetCString( + kChannelPref, updateChannelPrefValue, PrefValueKind::Default); releaseCandidateOnBeta = updateChannelPrefValue.EqualsLiteral("beta"); } if (!strcmp(NS_STRINGIFY(MOZ_UPDATE_CHANNEL), "nightly") || !strcmp(NS_STRINGIFY(MOZ_UPDATE_CHANNEL), "aurora") || - !strcmp(NS_STRINGIFY(MOZ_UPDATE_CHANNEL), "beta") || - developerBuild || + !strcmp(NS_STRINGIFY(MOZ_UPDATE_CHANNEL), "beta") || developerBuild || releaseCandidateOnBeta) { Preferences::SetBoolInAnyProcess( kTelemetryPref, true, PrefValueKind::Default); @@ -4101,6 +4136,7 @@ Preferences::SetCStringInAnyProcess(const char* aPrefName, aKind, prefValue, /* isSticky */ false, + /* isLocked */ false, /* fromFile */ false); } @@ -4127,6 +4163,7 @@ Preferences::SetBoolInAnyProcess(const char* aPrefName, aKind, prefValue, /* isSticky */ false, + /* isLocked */ false, /* fromFile */ false); } @@ -4151,6 +4188,7 @@ Preferences::SetIntInAnyProcess(const char* aPrefName, aKind, prefValue, /* isSticky */ false, + /* isLocked */ false, /* fromFile */ false); } diff --git a/modules/libpref/nsIPrefService.idl b/modules/libpref/nsIPrefService.idl index 237ea1884168..e9ea1675f313 100644 --- a/modules/libpref/nsIPrefService.idl +++ b/modules/libpref/nsIPrefService.idl @@ -45,7 +45,7 @@ interface nsIPrefService : nsISupports * * @throws Error File failed to write. * - * @see readUserPrefs + * @see readUserPrefsFromFile * @see nsIFile */ void savePrefFile(in nsIFile aFile); @@ -102,14 +102,20 @@ interface nsIPrefService : nsISupports readonly attribute boolean dirty; /** - * Read in the preferences specified in a user preference file. This method - * does not clear user preferences that were already set. + * Read in the preferences specified in a default preference file. This + * method does not clear preferences that were already set, but it may + * overwrite existing preferences. * * @param aFile The file to be read. * * @throws Error File failed to read or contained invalid data. * @note This method is intended for internal unit testing only! */ + void readDefaultPrefsFromFile(in nsIFile aFile); + + /** + * Like readDefaultPrefsFromFile, but for a user prefs file. + */ void readUserPrefsFromFile(in nsIFile aFile); }; diff --git a/modules/libpref/parser/src/lib.rs b/modules/libpref/parser/src/lib.rs index 29ce0f549138..8d8b9a6125e4 100644 --- a/modules/libpref/parser/src/lib.rs +++ b/modules/libpref/parser/src/lib.rs @@ -4,10 +4,12 @@ //! This crate implements a prefs file parser. //! -//! Pref files have the following grammar. +//! Pref files have the following grammar. Note that there are slight +//! differences between the grammar for a default prefs files and a user prefs +//! file. //! //! = * -//! = "(" "," ")" ";" +//! = "(" "," ")" ";" //! = "user_pref" | "pref" | "sticky_pref" //! = //! = | "true" | "false" | @@ -21,6 +23,9 @@ //! gives a UTF-16 code unit that is converted to UTF-8 before being copied //! into an 8-bit string value. \x00 and \u0000 are disallowed because they //! would cause C++ code handling such strings to misbehave. +//! = ("," )* // in default pref files +//! = // in user pref files +//! = "sticky" | "locked" // default pref files only //! //! Comments can take three forms: //! - # Python-style comments @@ -94,7 +99,7 @@ pub enum PrefType { } /// Keep this in sync with PrefValueKind in Preferences.h. -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Copy, Debug, PartialEq)] #[repr(u8)] pub enum PrefValueKind { Default, @@ -112,7 +117,7 @@ pub union PrefValue { /// Keep this in sync with PrefsParserPrefFn in Preferences.cpp. type PrefFn = unsafe extern "C" fn(pref_name: *const c_char, pref_type: PrefType, pref_value_kind: PrefValueKind, pref_value: PrefValue, - is_sticky: bool); + is_sticky: bool, is_locked: bool); /// Keep this in sync with PrefsParserErrorFn in Preferences.cpp. type ErrorFn = unsafe extern "C" fn(msg: *const c_char); @@ -129,8 +134,8 @@ type ErrorFn = unsafe extern "C" fn(msg: *const c_char); /// Keep this in sync with the prefs_parser_parse() declaration in /// Preferences.cpp. #[no_mangle] -pub extern "C" fn prefs_parser_parse(path: *const c_char, buf: *const c_char, len: usize, - pref_fn: PrefFn, error_fn: ErrorFn) -> bool { +pub extern "C" fn prefs_parser_parse(path: *const c_char, kind: PrefValueKind, buf: *const c_char, + len: usize, pref_fn: PrefFn, error_fn: ErrorFn) -> bool { let path = unsafe { std::ffi::CStr::from_ptr(path).to_string_lossy().into_owned() }; // Make sure `buf` ends in a '\0', and include that in the length, because @@ -138,7 +143,7 @@ pub extern "C" fn prefs_parser_parse(path: *const c_char, buf: *const c_char, le let buf = unsafe { std::slice::from_raw_parts(buf as *const c_uchar, len + 1) }; assert!(buf.last() == Some(&EOF)); - let mut parser = Parser::new(&path, &buf, pref_fn, error_fn); + let mut parser = Parser::new(&path, kind, &buf, pref_fn, error_fn); parser.parse() } @@ -157,6 +162,8 @@ enum Token { UserPref, // user_pref True, // true False, // false + Sticky, // sticky + Locked, // locked // String literal, e.g. '"string"'. The value is stored elsewhere. String, @@ -272,36 +279,41 @@ struct KeywordInfo { token: Token, } -const KEYWORD_INFOS: &[KeywordInfo; 5] = &[ +const KEYWORD_INFOS: [KeywordInfo; 7] = [ // These are ordered by frequency. KeywordInfo { string: b"pref", token: Token::Pref }, KeywordInfo { string: b"true", token: Token::True }, KeywordInfo { string: b"false", token: Token::False }, KeywordInfo { string: b"user_pref", token: Token::UserPref }, + KeywordInfo { string: b"sticky", token: Token::Sticky }, + KeywordInfo { string: b"locked", token: Token::Locked }, KeywordInfo { string: b"sticky_pref", token: Token::StickyPref }, ]; struct Parser<'t> { - path: &'t str, // Path to the file being parsed. Used in error messages. - buf: &'t [u8], // Text being parsed. - i: usize, // Index of next char to be read. - line_num: u32, // Current line number within the text. - pref_fn: PrefFn, // Callback for processing each pref. - error_fn: ErrorFn, // Callback for parse errors. - has_errors: bool, // Have we encountered errors? + path: &'t str, // Path to the file being parsed. Used in error messages. + kind: PrefValueKind, // Default prefs file or user prefs file? + buf: &'t [u8], // Text being parsed. + i: usize, // Index of next char to be read. + line_num: u32, // Current line number within the text. + pref_fn: PrefFn, // Callback for processing each pref. + error_fn: ErrorFn, // Callback for parse errors. + has_errors: bool, // Have we encountered errors? } // As described above, we use 0 to represent EOF. const EOF: u8 = b'\0'; impl<'t> Parser<'t> { - fn new(path: &'t str, buf: &'t [u8], pref_fn: PrefFn, error_fn: ErrorFn) -> Parser<'t> { + fn new(path: &'t str, kind: PrefValueKind, buf: &'t [u8], pref_fn: PrefFn, error_fn: ErrorFn) + -> Parser<'t> { // Make sure these tables take up 1 byte per entry. assert!(std::mem::size_of_val(&CHAR_KINDS) == 256); assert!(std::mem::size_of_val(&SPECIAL_STRING_CHARS) == 256); Parser { path: path, + kind: kind, buf: buf, i: 0, line_num: 1, @@ -323,7 +335,7 @@ impl<'t> Parser<'t> { // this will be either the first token of a new pref, or EOF. loop { // - let (pref_value_kind, is_sticky) = match token { + let (pref_value_kind, mut is_sticky) = match token { Token::Pref => (PrefValueKind::Default, false), Token::StickyPref => (PrefValueKind::Default, true), Token::UserPref => (PrefValueKind::User, false), @@ -370,7 +382,6 @@ impl<'t> Parser<'t> { Token::String => { (PrefType::String, PrefValue { string_val: value_str.as_ptr() as *const c_char }) - } Token::Int(u) => { // Accept u <= 2147483647; anything larger will overflow i32. @@ -425,10 +436,49 @@ impl<'t> Parser<'t> { } }; + // ("," )* // default pref files only + let mut is_locked = false; + let mut has_attrs = false; + if self.kind == PrefValueKind::Default { + let ok = loop { + // "," + token = self.get_token(&mut none_str); + if token != Token::SingleChar(b',') { + break true; + } + + // + token = self.get_token(&mut none_str); + match token { + Token::Sticky => is_sticky = true, + Token::Locked => is_locked = true, + _ => { + token = + self.error_and_recover(token, "expected pref attribute after ','"); + break false; + } + } + has_attrs = true; + }; + if !ok { + continue; + } + } else { + token = self.get_token(&mut none_str); + } + // ")" - token = self.get_token(&mut none_str); if token != Token::SingleChar(b')') { - token = self.error_and_recover(token, "expected ')' after pref value"); + let expected_msg = if self.kind == PrefValueKind::Default { + if has_attrs { + "expected ',' or ')' after pref attribute" + } else { + "expected ',' or ')' after pref value" + } + } else { + "expected ')' after pref value" + }; + token = self.error_and_recover(token, expected_msg); continue; } @@ -440,7 +490,7 @@ impl<'t> Parser<'t> { } unsafe { (self.pref_fn)(pref_name.as_ptr() as *const c_char, pref_type, pref_value_kind, - pref_value, is_sticky) }; + pref_value, is_sticky, is_locked) }; token = self.get_token(&mut none_str); } diff --git a/modules/libpref/test/gtest/Parser.cpp b/modules/libpref/test/gtest/Parser.cpp index acf352b1c15b..d5469dd38007 100644 --- a/modules/libpref/test/gtest/Parser.cpp +++ b/modules/libpref/test/gtest/Parser.cpp @@ -6,12 +6,15 @@ #include "gtest/gtest.h" #include "mozilla/ArrayUtils.h" +#include "Preferences.h" + +using namespace mozilla; // Keep this in sync with the declaration in Preferences.cpp. // // It's declared here to avoid polluting Preferences.h with test-only stuff. void -TestParseError(const char* aText, nsCString& aErrorMsg); +TestParseError(PrefValueKind aKind, const char* aText, nsCString& aErrorMsg); TEST(PrefsParser, Errors) { @@ -19,12 +22,18 @@ TEST(PrefsParser, Errors) // Use a macro rather than a function so that the line number reported by // gtest on failure is useful. -#define P(text_, expectedErrorMsg_) \ +#define P(kind_, text_, expectedErrorMsg_) \ do { \ - TestParseError(text_, actualErrorMsg); \ + TestParseError(kind_, text_, actualErrorMsg); \ ASSERT_STREQ(expectedErrorMsg_, actualErrorMsg.get()); \ } while (0) +#define DEFAULT(text_, expectedErrorMsg_) \ + P(PrefValueKind::Default, text_, expectedErrorMsg_) + +#define USER(text_, expectedErrorMsg_) \ + P(PrefValueKind::User, text_, expectedErrorMsg_) + // clang-format off //------------------------------------------------------------------------- @@ -33,7 +42,7 @@ TEST(PrefsParser, Errors) //------------------------------------------------------------------------- // Normal prefs. - P(R"( + DEFAULT(R"( pref("bool", true); sticky_pref("int", 123); user_pref("string", "value"); @@ -42,12 +51,12 @@ user_pref("string", "value"); ); // Totally empty input. - P("", + DEFAULT("", "" ); // Whitespace-only input. - P(R"( + DEFAULT(R"( )" "\v \t \v \f", "" @@ -60,7 +69,7 @@ user_pref("string", "value"); //------------------------------------------------------------------------- // Integer overflow errors. - P(R"( + DEFAULT(R"( pref("int.ok", 2147483647); pref("int.overflow", 2147483648); pref("int.ok", +2147483647); @@ -84,7 +93,7 @@ pref("int.overflow", 1234567890987654321); ); // Other integer errors. - P(R"( + DEFAULT(R"( pref("int.unexpected", 100foo); pref("int.ok", 0); )", @@ -92,7 +101,7 @@ pref("int.ok", 0); ); // \x00 is not allowed. - P(R"( + DEFAULT(R"( pref("string.bad-x-escape", "foo\x00bar"); pref("int.ok", 0); )", @@ -101,7 +110,7 @@ pref("int.ok", 0); // Various bad things after \x: end of string, punctuation, space, newline, // EOF. - P(R"( + DEFAULT(R"( pref("string.bad-x-escape", "foo\x"); pref("string.bad-x-escape", "foo\x,bar"); pref("string.bad-x-escape", "foo\x 12"); @@ -116,7 +125,7 @@ pref("string.bad-x-escape", "foo\x)", ); // Not enough hex digits. - P(R"( + DEFAULT(R"( pref("string.bad-x-escape", "foo\x1"); pref("int.ok", 0); )", @@ -124,7 +133,7 @@ pref("int.ok", 0); ); // Invalid hex digit. - P(R"( + DEFAULT(R"( pref("string.bad-x-escape", "foo\x1G"); pref("int.ok", 0); )", @@ -134,7 +143,7 @@ pref("int.ok", 0); // \u0000 is not allowed. // (The string literal is broken in two so that MSVC doesn't complain about // an invalid universal-character-name.) - P(R"( + DEFAULT(R"( pref("string.bad-u-escape", "foo\)" R"(u0000 bar"); pref("int.ok", 0); )", @@ -143,7 +152,7 @@ pref("int.ok", 0); // Various bad things after \u: end of string, punctuation, space, newline, // EOF. - P(R"( + DEFAULT(R"( pref("string.bad-u-escape", "foo\u"); pref("string.bad-u-escape", "foo\u,bar"); pref("string.bad-u-escape", "foo\u 1234"); @@ -158,7 +167,7 @@ pref("string.bad-u-escape", "foo\u)", ); // Not enough hex digits. - P(R"( + DEFAULT(R"( pref("string.bad-u-escape", "foo\u1"); pref("string.bad-u-escape", "foo\u12"); pref("string.bad-u-escape", "foo\u123"); @@ -170,7 +179,7 @@ pref("int.ok", 0); ); // Invalid hex digit. - P(R"( + DEFAULT(R"( pref("string.bad-u-escape", "foo\u1G34"); pref("int.ok", 0); )", @@ -180,7 +189,7 @@ pref("int.ok", 0); // High surrogate not followed by low surrogate. // (The string literal is broken in two so that MSVC doesn't complain about // an invalid universal-character-name.) - P(R"( + DEFAULT(R"( pref("string.bad-u-surrogate", "foo\)" R"(ud83c,blah"); pref("int.ok", 0); )", @@ -190,7 +199,7 @@ pref("int.ok", 0); // High surrogate followed by invalid low surrogate value. // (The string literal is broken in two so that MSVC doesn't complain about // an invalid universal-character-name.) - P(R"( + DEFAULT(R"( pref("string.bad-u-surrogate", "foo\)" R"(ud83c\u1234"); pref("int.ok", 0); )", @@ -198,7 +207,7 @@ pref("int.ok", 0); ); // Unlike in JavaScript, \b, \f, \t, \v aren't allowed. - P(R"( + DEFAULT(R"( pref("string.bad-escape", "foo\b"); pref("string.bad-escape", "foo\f"); pref("string.bad-escape", "foo\t"); @@ -213,7 +222,7 @@ pref("int.ok", 0); // Various bad things after \: non-special letter, number, punctuation, // space, newline, EOF. - P(R"( + DEFAULT(R"( pref("string.bad-escape", "foo\Q"); pref("string.bad-escape", "foo\1"); pref("string.bad-escape", "foo\,"); @@ -232,7 +241,7 @@ pref("string.bad-escape", "foo\)", // Unterminated string literals. // Simple case. - P(R"( + DEFAULT(R"( pref("string.unterminated-string", "foo )", "test:3: prefs parse error: unterminated string literal\n" @@ -241,7 +250,7 @@ pref("string.unterminated-string", "foo // Alternative case; `int` comes after the string and is seen as a keyword. // The parser then skips to the ';', so no error about the unterminated // string is issued. - P(R"( + DEFAULT(R"( pref("string.unterminated-string", "foo); pref("int.ok", 0); )", @@ -249,21 +258,21 @@ pref("int.ok", 0); ); // Mismatched quotes (1). - P(R"( + DEFAULT(R"( pref("string.unterminated-string", "foo'); )", "test:3: prefs parse error: unterminated string literal\n" ); // Mismatched quotes (2). - P(R"( + DEFAULT(R"( pref("string.unterminated-string", 'foo"); )", "test:3: prefs parse error: unterminated string literal\n" ); // Unknown keywords. - P(R"( + DEFAULT(R"( foo; preff("string.bad-keyword", true); ticky_pref("string.bad-keyword", true); @@ -278,33 +287,33 @@ pref("string.bad-keyword", TRUE); ); // Unterminated C-style comment. - P(R"( + DEFAULT(R"( /* comment )", "test:3: prefs parse error: unterminated /* comment\n" ); // Malformed comment. - P(R"( + DEFAULT(R"( / comment )", "test:2: prefs parse error: expected '/' or '*' after '/'\n" ); // C++-style comment ending in EOF (1). - P(R"( + DEFAULT(R"( // comment)", "" ); // C++-style comment ending in EOF (2). - P(R"( + DEFAULT(R"( //)", "" ); // Various unexpected characters. - P(R"( + DEFAULT(R"( pref("unexpected.chars", &true); pref("unexpected.chars" : true); @pref("unexpected.chars", true); @@ -320,7 +329,7 @@ pref["unexpected.chars": true]; // All the parsing errors. //------------------------------------------------------------------------- - P(R"( + DEFAULT(R"( "pref"("parse.error": true); pref1("parse.error": true); pref(123: true); @@ -328,7 +337,9 @@ pref("parse.error" true); pref("parse.error", pref); pref("parse.error", -true); pref("parse.error", +"value"); +pref("parse.error", true,); pref("parse.error", true; +pref("parse.error", true, sticky, locked; pref("parse.error", true) pref("int.ok", 1); pref("parse.error", true))", @@ -339,59 +350,83 @@ pref("parse.error", true))", "test:6: prefs parse error: expected pref value after ','\n" "test:7: prefs parse error: expected integer literal after '-'\n" "test:8: prefs parse error: expected integer literal after '+'\n" - "test:9: prefs parse error: expected ')' after pref value\n" - "test:11: prefs parse error: expected ';' after ')'\n" - "test:12: prefs parse error: expected ';' after ')'\n" + "test:9: prefs parse error: expected pref attribute after ','\n" + "test:10: prefs parse error: expected ',' or ')' after pref value\n" + "test:11: prefs parse error: expected ',' or ')' after pref attribute\n" + "test:13: prefs parse error: expected ';' after ')'\n" + "test:14: prefs parse error: expected ';' after ')'\n" + ); + + USER(R"( +pref("parse.error", true; +pref("int.ok", 1); + )", + "test:2: prefs parse error: expected ')' after pref value\n" ); // Parse errors involving unexpected EOF. - P(R"( + DEFAULT(R"( pref)", "test:2: prefs parse error: expected '(' after pref specifier\n" ); - P(R"( + DEFAULT(R"( pref()", "test:2: prefs parse error: expected pref name after '('\n" ); - P(R"( + DEFAULT(R"( pref("parse.error")", "test:2: prefs parse error: expected ',' after pref name\n" ); - P(R"( + DEFAULT(R"( pref("parse.error",)", "test:2: prefs parse error: expected pref value after ','\n" ); - P(R"( + DEFAULT(R"( pref("parse.error", -)", "test:2: prefs parse error: expected integer literal after '-'\n" ); - P(R"( + DEFAULT(R"( pref("parse.error", +)", "test:2: prefs parse error: expected integer literal after '+'\n" ); - P(R"( + DEFAULT(R"( +pref("parse.error", true)", + "test:2: prefs parse error: expected ',' or ')' after pref value\n" + ); + + USER(R"( pref("parse.error", true)", "test:2: prefs parse error: expected ')' after pref value\n" ); - P(R"( + DEFAULT(R"( +pref("parse.error", true,)", + "test:2: prefs parse error: expected pref attribute after ','\n" + ); + + DEFAULT(R"( +pref("parse.error", true, sticky)", + "test:2: prefs parse error: expected ',' or ')' after pref attribute\n" + ); + + DEFAULT(R"( pref("parse.error", true))", "test:2: prefs parse error: expected ';' after ')'\n" ); // This is something we saw in practice with the old parser, which allowed // repeated semicolons. - P(R"( + DEFAULT(R"( pref("parse.error", true);; -pref("parse.error", true);;; -pref("parse.error", true);;;; +pref("parse.error", true, locked);;; +pref("parse.error", true, sticky, locked);;;; pref("int.ok", 0); )", "test:2: prefs parse error: expected pref specifier at start of pref definition\n" @@ -411,24 +446,24 @@ pref("int.ok", 0); // the error is on line 4. (Note: these ones don't use raw string literals // because MSVC somehow swallows any \r that appears in them.) - P("\n \r \r\n bad", + DEFAULT("\n \r \r\n bad", "test:4: prefs parse error: unknown keyword\n" ); - P("#\n#\r#\r\n bad", + DEFAULT("#\n#\r#\r\n bad", "test:4: prefs parse error: unknown keyword\n" ); - P("//\n//\r//\r\n bad", + DEFAULT("//\n//\r//\r\n bad", "test:4: prefs parse error: unknown keyword\n" ); - P("/*\n \r \r\n*/ bad", + DEFAULT("/*\n \r \r\n*/ bad", "test:4: prefs parse error: unknown keyword\n" ); // Note: the escape sequences do *not* affect the line number. - P("pref(\"foo\\n\n foo\\r\r foo\\r\\n\r\n foo\", bad);", + DEFAULT("pref(\"foo\\n\n foo\\r\r foo\\r\\n\r\n foo\", bad);", "test:4: prefs parse error: unknown keyword\n" ); diff --git a/modules/libpref/test/unit/data/testParser.js b/modules/libpref/test/unit/data/testParser.js index 932e195e7cdf..f59567c0334c 100644 --- a/modules/libpref/test/unit/data/testParser.js +++ b/modules/libpref/test/unit/data/testParser.js @@ -1,5 +1,6 @@ -// Note: this file tests only valid syntax. See -// modules/libpref/test/gtest/Parser.cpp for tests if invalid syntax. +// Note: this file tests only valid syntax (of user pref files, not default +// pref files). See modules/libpref/test/gtest/Parser.cpp for tests if invalid +// syntax. # # comment @@ -50,6 +51,10 @@ pref pref("pref", true); sticky_pref("sticky_pref", true); user_pref("user_pref", true); +pref("sticky_pref2", true, sticky); +pref("locked_pref", true, locked); +pref("locked_sticky_pref", true, locked, sticky,sticky, + locked, locked, locked); pref("bool.true", true); pref("bool.false", false); diff --git a/modules/libpref/test/unit/data/testPrefLocked.js b/modules/libpref/test/unit/data/testPrefLocked.js new file mode 100644 index 000000000000..001b65122b11 --- /dev/null +++ b/modules/libpref/test/unit/data/testPrefLocked.js @@ -0,0 +1,2 @@ +pref("testPref.unlocked.int", 333); +pref("testPref.locked.int", 444, locked); diff --git a/modules/libpref/test/unit/data/testPrefLockedUser.js b/modules/libpref/test/unit/data/testPrefLockedUser.js new file mode 100644 index 000000000000..4da40b7abc8b --- /dev/null +++ b/modules/libpref/test/unit/data/testPrefLockedUser.js @@ -0,0 +1,3 @@ +// testPrefLocked.js defined this pref as a locked pref. +// Changing a locked pref has no effect. +user_pref("testPref.locked.int", 555); diff --git a/modules/libpref/test/unit/test_locked_file_prefs.js b/modules/libpref/test/unit/test_locked_file_prefs.js new file mode 100644 index 000000000000..042c8b05f3de --- /dev/null +++ b/modules/libpref/test/unit/test_locked_file_prefs.js @@ -0,0 +1,45 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// This file tests the `locked` attribute in default pref files. + +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); +Components.utils.import("resource://gre/modules/Services.jsm"); + +const ps = Services.prefs; + +add_test(function notChangedFromAPI() { + ps.resetPrefs(); + ps.readDefaultPrefsFromFile(do_get_file("data/testPrefLocked.js")); + Assert.strictEqual(ps.getIntPref("testPref.unlocked.int"), 333); + Assert.strictEqual(ps.getIntPref("testPref.locked.int"), 444); + + // Unlocked pref: can set the user value, which is used upon reading. + ps.setIntPref("testPref.unlocked.int", 334); + Assert.ok(ps.prefHasUserValue("testPref.unlocked.int"), "has a user value"); + Assert.strictEqual(ps.getIntPref("testPref.unlocked.int"), 334); + + // Locked pref: can set the user value, but the default value is used upon + // reading. + ps.setIntPref("testPref.locked.int", 445); + Assert.ok(ps.prefHasUserValue("testPref.locked.int"), "has a user value"); + Assert.strictEqual(ps.getIntPref("testPref.locked.int"), 444); + + // After unlocking, the user value is used. + ps.unlockPref("testPref.locked.int"); + Assert.ok(ps.prefHasUserValue("testPref.locked.int"), "has a user value"); + Assert.strictEqual(ps.getIntPref("testPref.locked.int"), 445); + + run_next_test(); +}); + +add_test(function notChangedFromUserPrefs() { + ps.resetPrefs(); + ps.readDefaultPrefsFromFile(do_get_file("data/testPrefLocked.js")); + ps.readUserPrefsFromFile(do_get_file("data/testPrefLockedUser.js")); + + Assert.strictEqual(ps.getIntPref("testPref.unlocked.int"), 333); + Assert.strictEqual(ps.getIntPref("testPref.locked.int"), 444); + + run_next_test(); +}); diff --git a/modules/libpref/test/unit/test_parser.js b/modules/libpref/test/unit/test_parser.js index c17b0b26616a..5bbc2ab38095 100644 --- a/modules/libpref/test/unit/test_parser.js +++ b/modules/libpref/test/unit/test_parser.js @@ -10,7 +10,7 @@ function run_test() { var prefs = ps.getBranch(null); ps.resetPrefs(); - ps.readUserPrefsFromFile(do_get_file('data/testParser.js')); + ps.readDefaultPrefsFromFile(do_get_file('data/testParser.js')); Assert.equal(ps.getBoolPref("comment1"), true); Assert.equal(ps.getBoolPref("comment2"), true); @@ -19,6 +19,11 @@ function run_test() { Assert.equal(ps.getBoolPref("pref"), true); Assert.equal(ps.getBoolPref("sticky_pref"), true); Assert.equal(ps.getBoolPref("user_pref"), true); + Assert.equal(ps.getBoolPref("sticky_pref2"), true); + Assert.equal(ps.getBoolPref("locked_pref"), true); + Assert.equal(ps.getBoolPref("locked_sticky_pref"), true); + Assert.equal(ps.prefIsLocked("locked_pref"), true); + Assert.equal(ps.prefIsLocked("locked_sticky_pref"), true); Assert.equal(ps.getBoolPref("bool.true"), true); Assert.equal(ps.getBoolPref("bool.false"), false); diff --git a/modules/libpref/test/unit/test_stickyprefs.js b/modules/libpref/test/unit/test_stickyprefs.js index 09dbe22ccaec..f7d87a90d1b7 100644 --- a/modules/libpref/test/unit/test_stickyprefs.js +++ b/modules/libpref/test/unit/test_stickyprefs.js @@ -6,12 +6,17 @@ ChromeUtils.import("resource://gre/modules/Services.jsm"); const ps = Services.prefs; -// A little helper to reset the service and load some pref files -function resetAndLoad(filenames) { +// A little helper to reset the service and load one pref file. +function resetAndLoadDefaults() { ps.resetPrefs(); - for (let filename of filenames) { - ps.readUserPrefsFromFile(do_get_file(filename)); - } + ps.readDefaultPrefsFromFile(do_get_file("data/testPrefSticky.js")); +} + +// A little helper to reset the service and load two pref files. +function resetAndLoadAll() { + ps.resetPrefs(); + ps.readDefaultPrefsFromFile(do_get_file("data/testPrefSticky.js")); + ps.readUserPrefsFromFile(do_get_file("data/testPrefStickyUser.js")); } // A little helper that saves the current state to a file in the profile @@ -39,7 +44,7 @@ function run_test() { // A sticky pref should not be written if the value is unchanged. add_test(function notWrittenWhenUnchanged() { - resetAndLoad(["data/testPrefSticky.js"]); + resetAndLoadDefaults(); Assert.strictEqual(ps.getBoolPref("testPref.unsticky.bool"), true); Assert.strictEqual(ps.getBoolPref("testPref.sticky.bool"), false); @@ -61,7 +66,7 @@ add_test(function writtenOnceLoadedWithoutChange() { // Load the same pref file *as well as* a pref file that has a user_pref for // our sticky with the default value. It should be re-written without us // touching it. - resetAndLoad(["data/testPrefSticky.js", "data/testPrefStickyUser.js"]); + resetAndLoadAll(); // reset and re-read what we just wrote - it should be written. saveAndReload(); Assert.strictEqual(ps.getBoolPref("testPref.sticky.bool"), false, @@ -73,7 +78,7 @@ add_test(function writtenOnceLoadedWithoutChange() { add_test(function writtenOnceLoadedWithChangeNonDefault() { // Load the same pref file *as well as* a pref file that has a user_pref for // our sticky - then change the pref. It should be written. - resetAndLoad(["data/testPrefSticky.js", "data/testPrefStickyUser.js"]); + resetAndLoadAll(); // Set a new val and check we wrote it. ps.setBoolPref("testPref.sticky.bool", false); saveAndReload(); @@ -86,7 +91,7 @@ add_test(function writtenOnceLoadedWithChangeNonDefault() { add_test(function writtenOnceLoadedWithChangeNonDefault() { // Load the same pref file *as well as* a pref file that has a user_pref for // our sticky - then change the pref. It should be written. - resetAndLoad(["data/testPrefSticky.js", "data/testPrefStickyUser.js"]); + resetAndLoadAll(); // Set a new val and check we wrote it. ps.setBoolPref("testPref.sticky.bool", true); saveAndReload(); @@ -102,7 +107,7 @@ add_test(function writtenOnceLoadedWithChangeNonDefault() { // the pref had never changed.) add_test(function hasUserValue() { // sticky pref without user value. - resetAndLoad(["data/testPrefSticky.js"]); + resetAndLoadDefaults(); Assert.strictEqual(ps.getBoolPref("testPref.sticky.bool"), false); Assert.ok(!ps.prefHasUserValue("testPref.sticky.bool"), "should not initially reflect a user value"); @@ -121,7 +126,7 @@ add_test(function hasUserValue() { ps.setBoolPref("testPref.sticky.bool", false, "expected default"); // And make sure the pref immediately reflects a user value after load. - resetAndLoad(["data/testPrefSticky.js", "data/testPrefStickyUser.js"]); + resetAndLoadAll(); Assert.strictEqual(ps.getBoolPref("testPref.sticky.bool"), false); Assert.ok(ps.prefHasUserValue("testPref.sticky.bool"), "should have a user value when loaded value is the default"); @@ -132,7 +137,7 @@ add_test(function hasUserValue() { add_test(function clearUserPref() { // load things such that we have a sticky value which is the same as the // default. - resetAndLoad(["data/testPrefSticky.js", "data/testPrefStickyUser.js"]); + resetAndLoadAll(); ps.clearUserPref("testPref.sticky.bool"); // Once we save prefs the sticky pref should no longer be written. @@ -153,7 +158,7 @@ add_test(function clearUserPref() { // even if the value has not) add_test(function observerFires() { // load things so there's no sticky value. - resetAndLoad(["data/testPrefSticky.js"]); + resetAndLoadDefaults(); function observe(subject, topic, data) { Assert.equal(data, "testPref.sticky.bool"); diff --git a/modules/libpref/test/unit/xpcshell.ini b/modules/libpref/test/unit/xpcshell.ini index 6318da1771eb..30d4ad035758 100644 --- a/modules/libpref/test/unit/xpcshell.ini +++ b/modules/libpref/test/unit/xpcshell.ini @@ -11,6 +11,8 @@ support-files = [test_bug790374.js] [test_stickyprefs.js] support-files = data/testPrefSticky.js data/testPrefStickyUser.js +[test_locked_file_prefs.js] +support-files = data/testPrefLocked.js data/testPrefLockedUser.js [test_changeType.js] [test_defaultValues.js] [test_dirtyPrefs.js] diff --git a/services/sync/tests/unit/test_prefs_store.js b/services/sync/tests/unit/test_prefs_store.js index 878f8d342d35..5dda71f275fa 100644 --- a/services/sync/tests/unit/test_prefs_store.js +++ b/services/sync/tests/unit/test_prefs_store.js @@ -25,7 +25,7 @@ function makePersona(id) { add_task(async function run_test() { _("Test fixtures."); // read our custom prefs file before doing anything. - Services.prefs.readUserPrefsFromFile(do_get_file("prefs_test_prefs_store.js")); + Services.prefs.readDefaultPrefsFromFile(do_get_file("prefs_test_prefs_store.js")); let engine = Service.engineManager.get("prefs"); let store = engine._store; From cb93c8b8f0508ed4d09a03529a098fac12b26741 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 7 Mar 2018 09:34:06 +1100 Subject: [PATCH 05/23] Bug 440908 - Convert sticky prefs in default pref files to the new syntax. r=glandium MozReview-Commit-ID: GgkNSsdGhBV --HG-- extra : rebase_source : efaf5f79ab7b608975ee960057d8be380061fdc0 --- browser/app/profile/firefox.js | 7 ++++--- devtools/shim/devtools-startup-prefs.js | 6 +++--- modules/libpref/init/all.js | 16 ++++++++-------- modules/libpref/test/unit/data/testPrefSticky.js | 2 +- .../libpref/test/unit/data/testPrefStickyUser.js | 2 +- modules/libpref/test/unit/test_stickyprefs.js | 2 +- 6 files changed, 18 insertions(+), 17 deletions(-) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index dd403311ed21..ce05ffc0e022 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1242,9 +1242,10 @@ pref("services.sync.syncedTabs.showRemoteIcons", true); // Developer edition preferences #ifdef MOZ_DEV_EDITION -sticky_pref("lightweightThemes.selectedThemeID", "firefox-compact-dark@mozilla.org"); +pref("lightweightThemes.selectedThemeID", "firefox-compact-dark@mozilla.org", + sticky); #else -sticky_pref("lightweightThemes.selectedThemeID", ""); +pref("lightweightThemes.selectedThemeID", "", sticky); #endif // Whether the character encoding menu is under the main Firefox button. This @@ -1266,7 +1267,7 @@ pref("browser.newtabpage.introShown", false); pref("browser.newtabpage.enabled", true); // Toggles the directory tiles content of 'about:newtab'. -sticky_pref("browser.newtabpage.enhanced", true); +pref("browser.newtabpage.enhanced", true, sticky); // enables Activity Stream inspired layout pref("browser.newtabpage.compact", false); diff --git a/devtools/shim/devtools-startup-prefs.js b/devtools/shim/devtools-startup-prefs.js index 70148f7b83d3..8321d93baebd 100644 --- a/devtools/shim/devtools-startup-prefs.js +++ b/devtools/shim/devtools-startup-prefs.js @@ -13,9 +13,9 @@ pref("devtools.jsonview.enabled", true); // Default theme ("dark" or "light") #ifdef MOZ_DEV_EDITION -sticky_pref("devtools.theme", "dark"); +pref("devtools.theme", "dark", sticky); #else -sticky_pref("devtools.theme", "light"); +pref("devtools.theme", "light", sticky); #endif // Should the devtools toolbar be opened on startup @@ -38,4 +38,4 @@ pref("devtools.onboarding.telemetry.logged", false); // Completely disable DevTools entry points, as well as all DevTools command line // arguments This should be merged with devtools.enabled, see Bug 1440675. -pref("devtools.policy.disabled", false); \ No newline at end of file +pref("devtools.policy.disabled", false); diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index a45961dc6292..451236eb47ad 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1089,23 +1089,23 @@ pref("devtools.errorconsole.deprecation_warnings", true); #ifdef NIGHTLY_BUILD // Don't show the Browser Toolbox prompt on local builds / nightly -sticky_pref("devtools.debugger.prompt-connection", false); +pref("devtools.debugger.prompt-connection", false, sticky); #else -sticky_pref("devtools.debugger.prompt-connection", true); +pref("devtools.debugger.prompt-connection", true, sticky); #endif #ifdef MOZILLA_OFFICIAL // Disable debugging chrome -sticky_pref("devtools.chrome.enabled", false); +pref("devtools.chrome.enabled", false, sticky); // Disable remote debugging connections -sticky_pref("devtools.debugger.remote-enabled", false); +pref("devtools.debugger.remote-enabled", false, sticky); // enable JS dump() function. -sticky_pref("browser.dom.window.dump.enabled", false); +pref("browser.dom.window.dump.enabled", false, sticky); #else // In local builds, enable the browser toolbox by default -sticky_pref("devtools.chrome.enabled", true); -sticky_pref("devtools.debugger.remote-enabled", true); -sticky_pref("browser.dom.window.dump.enabled", true); +pref("devtools.chrome.enabled", true, sticky); +pref("devtools.debugger.remote-enabled", true, sticky); +pref("browser.dom.window.dump.enabled", true, sticky); #endif diff --git a/modules/libpref/test/unit/data/testPrefSticky.js b/modules/libpref/test/unit/data/testPrefSticky.js index 69b3165fb48b..ef1a02adfd49 100644 --- a/modules/libpref/test/unit/data/testPrefSticky.js +++ b/modules/libpref/test/unit/data/testPrefSticky.js @@ -1,2 +1,2 @@ pref("testPref.unsticky.bool", true); -sticky_pref("testPref.sticky.bool", false); +pref("testPref.sticky.bool", false, sticky); diff --git a/modules/libpref/test/unit/data/testPrefStickyUser.js b/modules/libpref/test/unit/data/testPrefStickyUser.js index 0ea0906813e3..d929c670ad74 100644 --- a/modules/libpref/test/unit/data/testPrefStickyUser.js +++ b/modules/libpref/test/unit/data/testPrefStickyUser.js @@ -1,4 +1,4 @@ -// testPrefSticky.js defined this pref as a sticky_pref(). Once a sticky +// testPrefSticky.js defined this pref as sticky. Once a sticky // pref has been changed, it's written as a user_pref(). // So this test file reflects that scenario. // Note the default in testPrefSticky.js is also false. diff --git a/modules/libpref/test/unit/test_stickyprefs.js b/modules/libpref/test/unit/test_stickyprefs.js index f7d87a90d1b7..78526c0c0e68 100644 --- a/modules/libpref/test/unit/test_stickyprefs.js +++ b/modules/libpref/test/unit/test_stickyprefs.js @@ -60,7 +60,7 @@ add_test(function notWrittenWhenUnchanged() { run_next_test(); }); -// Loading a sticky_pref then a user_pref for the same pref means it should +// Loading a sticky `pref` then a `user_pref` for the same pref means it should // always be written. add_test(function writtenOnceLoadedWithoutChange() { // Load the same pref file *as well as* a pref file that has a user_pref for From 486cc97c49ad476f8cf598943f5f2ce65f8cf0bd Mon Sep 17 00:00:00 2001 From: Dorel Luca Date: Wed, 7 Mar 2018 05:26:02 +0200 Subject: [PATCH 06/23] Backed out changeset b3cf1b5c14cc (bug 1440966) for build bustages on a CLOSED TREE --HG-- extra : histedit_source : f4408776ade25fc873da470bd5aa9d200a42163e --- layout/painting/FrameLayerBuilder.cpp | 47 +++++++++++++++++---------- layout/painting/FrameLayerBuilder.h | 12 +++++-- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/layout/painting/FrameLayerBuilder.cpp b/layout/painting/FrameLayerBuilder.cpp index a16b9df53ce1..8056b96f53a0 100644 --- a/layout/painting/FrameLayerBuilder.cpp +++ b/layout/painting/FrameLayerBuilder.cpp @@ -2011,6 +2011,19 @@ FrameLayerBuilder::DidBeginRetainedLayerTransaction(LayerManager* aManager) } } +void +FrameLayerBuilder::StoreOptimizedLayerForFrame(nsDisplayItem* aItem, Layer* aLayer) +{ + if (!mRetainingManager) { + return; + } + + DisplayItemData* data = GetDisplayItemDataForManager(aItem, aLayer->Manager()); + NS_ASSERTION(data, "Must have already stored data for this item!"); + data->mOptLayer = aLayer; + data->mItem = nullptr; +} + void FrameLayerBuilder::DidEndTransaction() { @@ -3179,6 +3192,16 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB mNewChildLayers[data->mNewChildLayersIndex].mLayer = paintedLayer.forget(); } + for (auto& item : data->mAssignedDisplayItems) { + MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_LAYER_EVENT_REGIONS); + MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO); + + InvalidateForLayerChange(item.mItem, data->mLayer, item.mDisplayItemData); + mLayerBuilder->AddPaintedDisplayItem(data, item, *this, + data->mAnimatedGeometryRootOffset); + item.mDisplayItemData = nullptr; + } + PaintedDisplayItemLayerUserData* userData = GetPaintedDisplayItemLayerUserData(data->mLayer); NS_ASSERTION(userData, "where did our user data go?"); userData->mLastItemCount = data->mAssignedDisplayItems.Length(); @@ -3223,6 +3246,10 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB data->mLayer->SetVisibleRegion(LayerIntRegion()); data->mLayer->InvalidateWholeLayer(); data->mLayer->SetEventRegions(EventRegions()); + + for (auto& item : data->mAssignedDisplayItems) { + mLayerBuilder->StoreOptimizedLayerForFrame(item.mItem, layer); + } } } @@ -3233,15 +3260,6 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB FLB_LOG_PAINTED_LAYER_DECISION(data, " Selected painted layer=%p\n", layer.get()); } - for (auto& item : data->mAssignedDisplayItems) { - MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_LAYER_EVENT_REGIONS); - MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO); - - InvalidateForLayerChange(item.mItem, data->mLayer, item.mDisplayItemData); - mLayerBuilder->AddPaintedDisplayItem(data, item, *this, layer); - item.mDisplayItemData = nullptr; - } - if (mLayerBuilder->IsBuildingRetainedLayers()) { newLayerEntry->mVisibleRegion = data->mVisibleRegion; newLayerEntry->mOpaqueRegion = data->mOpaqueRegion; @@ -4766,7 +4784,8 @@ FrameLayerBuilder::ComputeGeometryChangeForItem(DisplayItemData* aData) void FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, AssignedDisplayItem& aItem, - ContainerState& aContainerState) + ContainerState& aContainerState, + const nsPoint& aTopLeft) { PaintedLayer* layer = aLayerData->mLayer; PaintedDisplayItemLayerUserData* paintedData = @@ -4782,7 +4801,7 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, // We need to grab these before updating the DisplayItemData because it will overwrite them. nsRegion clip; if (aItem.mClip.ComputeRegionInClips(&aItem.mDisplayItemData->GetClip(), - aLayerData->mAnimatedGeometryRootOffset - paintedData->mLastAnimatedGeometryRootOrigin, + aTopLeft - paintedData->mLastAnimatedGeometryRootOrigin, &clip)) { intClip = clip.GetBounds().ScaleToOutsidePixels(paintedData->mXScale, paintedData->mYScale, @@ -4804,12 +4823,6 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, data = StoreDataForFrame(aItem.mItem, layer, aItem.mLayerState, nullptr); } data->mInactiveManager = tempManager; - // We optimized this PaintedLayer into a ColorLayer/ImageLayer. Store the optimized - // layer here. - if (aLayer != layer) { - data->mOptLayer = aLayer; - data->mItem = nullptr; - } } if (tempManager) { diff --git a/layout/painting/FrameLayerBuilder.h b/layout/painting/FrameLayerBuilder.h index 7f70d75122c2..6e0108daff8c 100644 --- a/layout/painting/FrameLayerBuilder.h +++ b/layout/painting/FrameLayerBuilder.h @@ -510,10 +510,10 @@ public: * aItem must have an underlying frame. * @param aTopLeft offset from active scrolled root to reference frame */ - void AddPaintedDisplayItem(PaintedLayerData* aLayerData, + void AddPaintedDisplayItem(PaintedLayerData* aLayer, AssignedDisplayItem& aAssignedDisplayItem, ContainerState& aContainerState, - Layer* aLayer); + const nsPoint& aTopLeft); /** * Calls GetOldLayerForFrame on the underlying frame of the display item, @@ -590,6 +590,14 @@ public: */ static gfxSize GetPaintedLayerScaleForFrame(nsIFrame* aFrame); + /** + * Stores a Layer as the dedicated layer in the DisplayItemData for a given frame/key pair. + * + * Used when we optimize a PaintedLayer into an ImageLayer and want to retroactively update the + * DisplayItemData so we can retrieve the layer from within layout. + */ + void StoreOptimizedLayerForFrame(nsDisplayItem* aItem, Layer* aLayer); + static void RemoveFrameFromLayerManager(const nsIFrame* aFrame, SmallPointerArray& aArray); From 9f7ee3a7b0537361235d6a27c8eb7c8c0fa222f7 Mon Sep 17 00:00:00 2001 From: Dorel Luca Date: Wed, 7 Mar 2018 05:26:20 +0200 Subject: [PATCH 07/23] Backed out changeset 1c81ecf47268 (bug 1438990) for build bustages on a CLOSED TREE --HG-- extra : histedit_source : 05ea7bf920dc027871f99d8f4ac631d0ebf690f5 --- layout/painting/DisplayItemClip.cpp | 50 +++++++--- layout/painting/DisplayItemClip.h | 19 +++- layout/painting/FrameLayerBuilder.cpp | 127 +++++++++++++++++++++----- layout/painting/FrameLayerBuilder.h | 3 +- 4 files changed, 158 insertions(+), 41 deletions(-) diff --git a/layout/painting/DisplayItemClip.cpp b/layout/painting/DisplayItemClip.cpp index f553802d298b..0f16c7850fff 100644 --- a/layout/painting/DisplayItemClip.cpp +++ b/layout/painting/DisplayItemClip.cpp @@ -91,10 +91,11 @@ DisplayItemClip::IntersectWith(const DisplayItemClip& aOther) void DisplayItemClip::ApplyTo(gfxContext* aContext, - int32_t A2D) + int32_t A2D, + uint32_t aBegin, uint32_t aEnd) { ApplyRectTo(aContext, A2D); - ApplyRoundedRectClipsTo(aContext, A2D, 0, mRoundedClipRects.Length()); + ApplyRoundedRectClipsTo(aContext, A2D, aBegin, aEnd); } void @@ -125,27 +126,30 @@ DisplayItemClip::ApplyRoundedRectClipsTo(gfxContext* aContext, void DisplayItemClip::FillIntersectionOfRoundedRectClips(gfxContext* aContext, const Color& aColor, - int32_t aAppUnitsPerDevPixel) const + int32_t aAppUnitsPerDevPixel, + uint32_t aBegin, + uint32_t aEnd) const { DrawTarget& aDrawTarget = *aContext->GetDrawTarget(); - uint32_t end = mRoundedClipRects.Length(); - if (!end) { + aEnd = std::min(aEnd, mRoundedClipRects.Length()); + + if (aBegin >= aEnd) { return; } // Push clips for any rects that come BEFORE the rect at |aEnd - 1|, if any: - ApplyRoundedRectClipsTo(aContext, aAppUnitsPerDevPixel, 0, end - 1); + ApplyRoundedRectClipsTo(aContext, aAppUnitsPerDevPixel, aBegin, aEnd - 1); // Now fill the rect at |aEnd - 1|: RefPtr roundedRect = MakeRoundedRectPath(aDrawTarget, aAppUnitsPerDevPixel, - mRoundedClipRects[end - 1]); + mRoundedClipRects[aEnd - 1]); ColorPattern color(ToDeviceColor(aColor)); aDrawTarget.Fill(roundedRect, color); // Finally, pop any clips that we may have pushed: - for (uint32_t i = 0; i < end - 1; ++i) { + for (uint32_t i = aBegin; i < aEnd - 1; ++i) { aContext->PopClip(); } } @@ -354,13 +358,16 @@ AccumulateRectDifference(const nsRect& aR1, const nsRect& aR2, const nsRect& aBo } void -DisplayItemClip::AddOffsetAndComputeDifference(const nsPoint& aOffset, +DisplayItemClip::AddOffsetAndComputeDifference(uint32_t aStart, + const nsPoint& aOffset, const nsRect& aBounds, const DisplayItemClip& aOther, + uint32_t aOtherStart, const nsRect& aOtherBounds, nsRegion* aDifference) { if (mHaveClipRect != aOther.mHaveClipRect || + aStart != aOtherStart || mRoundedClipRects.Length() != aOther.mRoundedClipRects.Length()) { aDifference->Or(*aDifference, aBounds); aDifference->Or(*aDifference, aOtherBounds); @@ -371,7 +378,7 @@ DisplayItemClip::AddOffsetAndComputeDifference(const nsPoint& aOffset, aBounds.Union(aOtherBounds), aDifference); } - for (uint32_t i = 0; i < mRoundedClipRects.Length(); ++i) { + for (uint32_t i = aStart; i < mRoundedClipRects.Length(); ++i) { if (mRoundedClipRects[i] + aOffset != aOther.mRoundedClipRects[i]) { // The corners make it tricky so we'll just add both rects here. aDifference->Or(*aDifference, mRoundedClipRects[i].mRect.Intersect(aBounds)); @@ -380,10 +387,27 @@ DisplayItemClip::AddOffsetAndComputeDifference(const nsPoint& aOffset, } } -void -DisplayItemClip::AppendRoundedRects(nsTArray* aArray) const +uint32_t +DisplayItemClip::GetCommonRoundedRectCount(const DisplayItemClip& aOther, + uint32_t aMax) const { - aArray->AppendElements(mRoundedClipRects.Elements(), mRoundedClipRects.Length()); + uint32_t end = std::min(std::min(mRoundedClipRects.Length(), size_t(aMax)), + aOther.mRoundedClipRects.Length()); + uint32_t clipCount = 0; + for (; clipCount < end; ++clipCount) { + if (mRoundedClipRects[clipCount] != + aOther.mRoundedClipRects[clipCount]) { + return clipCount; + } + } + return clipCount; +} + +void +DisplayItemClip::AppendRoundedRects(nsTArray* aArray, uint32_t aCount) const +{ + size_t count = std::min(mRoundedClipRects.Length(), size_t(aCount)); + aArray->AppendElements(mRoundedClipRects.Elements(), count); } bool diff --git a/layout/painting/DisplayItemClip.h b/layout/painting/DisplayItemClip.h index 60a34a9b43bb..1ef0601f193a 100644 --- a/layout/painting/DisplayItemClip.h +++ b/layout/painting/DisplayItemClip.h @@ -81,7 +81,8 @@ public: // Apply this |DisplayItemClip| to the given gfxContext. Any saving of state // or clearing of other clips must be done by the caller. // See aBegin/aEnd note on ApplyRoundedRectsTo. - void ApplyTo(gfxContext* aContext, int32_t A2D); + void ApplyTo(gfxContext* aContext, int32_t A2D, + uint32_t aBegin = 0, uint32_t aEnd = UINT32_MAX); void ApplyRectTo(gfxContext* aContext, int32_t A2D) const; // Applies the rounded rects in this Clip to aContext @@ -93,7 +94,9 @@ public: // Draw (fill) the rounded rects in this clip to aContext void FillIntersectionOfRoundedRectClips(gfxContext* aContext, const Color& aColor, - int32_t aAppUnitsPerDevPixel) const; + int32_t aAppUnitsPerDevPixel, + uint32_t aBegin, + uint32_t aEnd) const; // 'Draw' (create as a path, does not stroke or fill) aRoundRect to aContext already_AddRefed MakeRoundedRectPath(DrawTarget& aDrawTarget, int32_t A2D, @@ -145,8 +148,8 @@ public: // Adds the difference between Intersect(*this + aPoint, aBounds) and // Intersect(aOther, aOtherBounds) to aDifference (or a bounding-box thereof). - void AddOffsetAndComputeDifference(const nsPoint& aPoint, const nsRect& aBounds, - const DisplayItemClip& aOther, const nsRect& aOtherBounds, + void AddOffsetAndComputeDifference(uint32_t aStart, const nsPoint& aPoint, const nsRect& aBounds, + const DisplayItemClip& aOther, uint32_t aOtherStart, const nsRect& aOtherBounds, nsRegion* aDifference); bool operator==(const DisplayItemClip& aOther) const { @@ -169,8 +172,14 @@ public: nsCString ToString() const; + /** + * Find the largest N such that the first N rounded rects in 'this' are + * equal to the first N rounded rects in aOther, and N <= aMax. + */ + uint32_t GetCommonRoundedRectCount(const DisplayItemClip& aOther, + uint32_t aMax) const; uint32_t GetRoundedRectCount() const { return mRoundedClipRects.Length(); } - void AppendRoundedRects(nsTArray* aArray) const; + void AppendRoundedRects(nsTArray* aArray, uint32_t aCount) const; void ToComplexClipRegions(int32_t aAppUnitsPerDevPixel, const layers::StackingContextHelper& aSc, diff --git a/layout/painting/FrameLayerBuilder.cpp b/layout/painting/FrameLayerBuilder.cpp index 8056b96f53a0..4cbd4c7f9de5 100644 --- a/layout/painting/FrameLayerBuilder.cpp +++ b/layout/painting/FrameLayerBuilder.cpp @@ -449,6 +449,7 @@ public: mShouldPaintOnContentSide(false), mDTCRequiresTargetConfirmation(false), mImage(nullptr), + mCommonClipCount(-1), mNewChildLayersIndex(-1) {} @@ -660,10 +661,24 @@ public: * no part at all. */ DisplayItemClip mItemClip; + /** + * The first mCommonClipCount rounded rectangle clips are identical for + * all items in the layer. + * -1 if there are no items in the layer; must be >=0 by the time that this + * data is popped from the stack. + */ + int32_t mCommonClipCount; /** * Index of this layer in mNewChildLayers. */ int32_t mNewChildLayersIndex; + /* + * Updates mCommonClipCount by checking for rounded rect clips in common + * between the clip on a new item (aCurrentClip) and the common clips + * on items already in the layer (the first mCommonClipCount rounded rects + * in mItemClip). + */ + void UpdateCommonClipCount(const DisplayItemClip& aCurrentClip); /** * The region of visible content above the layer and below the * next PaintedLayerData currently in the stack, if any. @@ -1370,8 +1385,12 @@ protected: * aLayer is the layer to be clipped. * relative to the container reference frame * aRoundedRectClipCount is used when building mask layers for PaintedLayers, + * SetupMaskLayer will build a mask layer for only the first + * aRoundedRectClipCount rounded rects in aClip + * Returns the number of rounded rects included in the mask layer. */ - void SetupMaskLayer(Layer *aLayer, const DisplayItemClip& aClip); + uint32_t SetupMaskLayer(Layer *aLayer, const DisplayItemClip& aClip, + uint32_t aRoundedRectClipCount = UINT32_MAX); /** * If |aClip| has rounded corners, create a mask layer for them, and @@ -1391,7 +1410,8 @@ protected: already_AddRefed CreateMaskLayer( Layer *aLayer, const DisplayItemClip& aClip, - const Maybe& aForAncestorMaskLayer); + const Maybe& aForAncestorMaskLayer, + uint32_t aRoundedRectClipCount = UINT32_MAX); /** * Get the display port for an AGR. @@ -1478,6 +1498,8 @@ class PaintedDisplayItemLayerUserData : public LayerUserData { public: PaintedDisplayItemLayerUserData() : + mMaskClipCount(0), + mLastCommonClipCount(0), mForcedBackgroundColor(NS_RGBA(0,0,0,0)), mXScale(1.f), mYScale(1.f), mAppUnitsPerDevPixel(0), @@ -1489,6 +1511,19 @@ public: NS_INLINE_DECL_REFCOUNTING(PaintedDisplayItemLayerUserData); + /** + * Record the number of clips in the PaintedLayer's mask layer. + * Should not be reset when the layer is recycled since it is used to track + * changes in the use of mask layers. + */ + uint32_t mMaskClipCount; + + /** + * Records the number of clips in the PaintedLayer's mask layer during + * the previous paint. Used for invalidation. + */ + uint32_t mLastCommonClipCount; + /** * A color that should be painted over the bounds of the layer's visible * region before any other content is painted. @@ -1605,6 +1640,7 @@ struct MaskLayerUserData : public LayerUserData , mAppUnitsPerDevPixel(-1) { } MaskLayerUserData(const DisplayItemClip& aClip, + uint32_t aRoundedRectClipCount, int32_t aAppUnitsPerDevPixel, const ContainerLayerParameters& aParams) : mScaleX(aParams.mXScale) @@ -1612,7 +1648,7 @@ struct MaskLayerUserData : public LayerUserData , mOffset(aParams.mOffset) , mAppUnitsPerDevPixel(aAppUnitsPerDevPixel) { - aClip.AppendRoundedRects(&mRoundedClipRects); + aClip.AppendRoundedRects(&mRoundedClipRects, aRoundedRectClipCount); } void operator=(MaskLayerUserData&& aOther) @@ -2464,6 +2500,7 @@ ContainerState::PreparePaintedLayerForUse(PaintedLayer* aLayer, aData->mLastPaintOffset = GetTranslationForPaintedLayer(aLayer); aData->mHasExplicitLastPaintOffset = true; + aData->mLastCommonClipCount = aData->mMaskClipCount; // Set up transform so that 0,0 in the PaintedLayer corresponds to the // (pixel-snapped) top-left of the aAnimatedGeometryRoot. @@ -2726,6 +2763,18 @@ PaintedLayerDataNode::FindOpaqueBackgroundColorInParentNode() const return mTree.UniformBackgroundColor(); } +void +PaintedLayerData::UpdateCommonClipCount( + const DisplayItemClip& aCurrentClip) +{ + if (mCommonClipCount >= 0) { + mCommonClipCount = mItemClip.GetCommonRoundedRectCount(aCurrentClip, mCommonClipCount); + } else { + // first item in the layer + mCommonClipCount = aCurrentClip.GetRoundedRectCount(); + } +} + bool PaintedLayerData::CanOptimizeToImageLayer(nsDisplayListBuilder* aBuilder) { @@ -3312,7 +3361,22 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB data->mLayer->InvalidateWholeLayer(); } userData->mForcedBackgroundColor = backgroundColor; - SetupMaskLayer(layer, data->mItemClip); + + // use a mask layer for rounded rect clipping. + // data->mCommonClipCount may be -1 if we haven't put any actual + // drawable items in this layer (i.e. it's only catching events). + uint32_t commonClipCount; + commonClipCount = std::max(0, data->mCommonClipCount); + + // if the number of clips we are going to mask has decreased, then aLayer might have + // cached graphics which assume the existence of a soon-to-be non-existent mask layer + // in that case, invalidate the whole layer. + if (commonClipCount < userData->mMaskClipCount) { + PaintedLayer* painted = layer->AsPaintedLayer(); + painted->InvalidateWholeLayer(); + } + + userData->mMaskClipCount = SetupMaskLayer(layer, data->mItemClip, commonClipCount); } else { // mask layer for image and color layers SetupMaskLayer(layer, data->mItemClip); @@ -3955,7 +4019,8 @@ ContainerState::SetupMaskLayerForScrolledClip(Layer* aLayer, { if (aClip.GetRoundedRectCount() > 0) { Maybe maskLayerIndex = Some(aLayer->GetAncestorMaskLayerCount()); - if (RefPtr maskLayer = CreateMaskLayer(aLayer, aClip, maskLayerIndex)) { + if (RefPtr maskLayer = CreateMaskLayer(aLayer, aClip, maskLayerIndex, + aClip.GetRoundedRectCount())) { aLayer->AddAncestorMaskLayer(maskLayer); return maskLayerIndex; } @@ -4622,6 +4687,11 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList) static_cast(item); paintedLayerData->AccumulateHitTestInfo(this, hitTestInfo); } else { + // check to see if the new item has rounded rect clips in common with + // other items in the layer + if (mManager->IsWidgetLayerManager()) { + paintedLayerData->UpdateCommonClipCount(itemClip); + } paintedLayerData->Accumulate(this, item, itemVisibleRect, itemClip, layerState, aList); if (!paintedLayerData->mLayer) { @@ -4750,9 +4820,11 @@ FrameLayerBuilder::ComputeGeometryChangeForItem(DisplayItemData* aData) if (!combined.IsEmpty() || aData->mLayerState == LAYER_INACTIVE) { geometry = item->AllocateGeometry(mDisplayListBuilder); } - aData->mClip.AddOffsetAndComputeDifference(shift, aData->mGeometry->ComputeInvalidationRegion(), - clip, geometry ? geometry->ComputeInvalidationRegion() : - aData->mGeometry->ComputeInvalidationRegion(), + aData->mClip.AddOffsetAndComputeDifference(layerData->mMaskClipCount, + shift, aData->mGeometry->ComputeInvalidationRegion(), + clip, layerData->mLastCommonClipCount, + geometry ? geometry->ComputeInvalidationRegion() : + aData->mGeometry->ComputeInvalidationRegion(), &combined); // Add in any rect that the frame specified @@ -5236,7 +5308,7 @@ ContainerState::SetupScrollingMetadata(NewLayerEntry* aEntry) // layer as an additional, separate clip. Maybe nextIndex = Some(maskLayers.Length()); RefPtr maskLayer = - CreateMaskLayer(aEntry->mLayer, *clip, nextIndex); + CreateMaskLayer(aEntry->mLayer, *clip, nextIndex, clip->GetRoundedRectCount()); if (maskLayer) { MOZ_ASSERT(metadata->HasScrollClip()); metadata->ScrollClip().SetMaskLayerIndex(nextIndex); @@ -5962,7 +6034,8 @@ FrameLayerBuilder::PaintItems(nsTArray& aItems, nsDisplayListBuilder* aBuilder, nsPresContext* aPresContext, const nsIntPoint& aOffset, - float aXScale, float aYScale) + float aXScale, float aYScale, + int32_t aCommonClipCount) { DrawTarget& aDrawTarget = *aContext->GetDrawTarget(); @@ -6011,7 +6084,9 @@ FrameLayerBuilder::PaintItems(nsTArray& aItems, if (currentClipIsSetInContext) { currentClip = *clip; aContext->Save(); - currentClip.ApplyTo(aContext, aPresContext->AppUnitsPerDevPixel()); + NS_ASSERTION(aCommonClipCount < 100, + "Maybe you really do have more than a hundred clipping rounded rects, or maybe something has gone wrong."); + currentClip.ApplyTo(aContext, aPresContext->AppUnitsPerDevPixel(), aCommonClipCount); aContext->NewPath(); } } @@ -6174,7 +6249,8 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer, layerBuilder->PaintItems(userData->mItems, iterRect, aContext, builder, presContext, - offset, userData->mXScale, userData->mYScale); + offset, userData->mXScale, userData->mYScale, + userData->mMaskClipCount); if (gfxPrefs::GfxLoggingPaintedPixelCountEnabled()) { aLayer->Manager()->AddPaintedPixelCount(iterRect.Area()); } @@ -6189,7 +6265,8 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer, layerBuilder->PaintItems(userData->mItems, aRegionToDraw.GetBounds(), aContext, builder, presContext, - offset, userData->mXScale, userData->mYScale); + offset, userData->mXScale, userData->mYScale, + userData->mMaskClipCount); if (gfxPrefs::GfxLoggingPaintedPixelCountEnabled()) { aLayer->Manager()->AddPaintedPixelCount( aRegionToDraw.GetBounds().Area()); @@ -6266,23 +6343,26 @@ CalculateBounds(const nsTArray& aRects, int32_t aA return gfx::Rect(bounds.ToNearestPixels(aAppUnitsPerDevPixel)); } -void +uint32_t ContainerState::SetupMaskLayer(Layer *aLayer, - const DisplayItemClip& aClip) + const DisplayItemClip& aClip, + uint32_t aRoundedRectClipCount) { // don't build an unnecessary mask - if (aClip.GetRoundedRectCount() == 0) { - return; + if (aClip.GetRoundedRectCount() == 0 || + aRoundedRectClipCount == 0) { + return 0; } RefPtr maskLayer = - CreateMaskLayer(aLayer, aClip, Nothing()); + CreateMaskLayer(aLayer, aClip, Nothing(), aRoundedRectClipCount); if (!maskLayer) { - return; + return 0; } aLayer->SetMaskLayer(maskLayer); + return aRoundedRectClipCount; } static MaskLayerUserData* @@ -6307,7 +6387,8 @@ SetMaskLayerUserData(Layer* aMaskLayer) already_AddRefed ContainerState::CreateMaskLayer(Layer *aLayer, const DisplayItemClip& aClip, - const Maybe& aForAncestorMaskLayer) + const Maybe& aForAncestorMaskLayer, + uint32_t aRoundedRectClipCount) { // aLayer will never be the container layer created by an nsDisplayMask // because nsDisplayMask propagates the DisplayItemClip to its contents @@ -6324,7 +6405,7 @@ ContainerState::CreateMaskLayer(Layer *aLayer, MaskLayerUserData* userData = GetMaskLayerUserData(maskLayer.get()); int32_t A2D = mContainerFrame->PresContext()->AppUnitsPerDevPixel(); - MaskLayerUserData newData(aClip, A2D, mParameters); + MaskLayerUserData newData(aClip, aRoundedRectClipCount, A2D, mParameters); if (*userData == newData) { return maskLayer.forget(); } @@ -6404,7 +6485,9 @@ ContainerState::CreateMaskLayer(Layer *aLayer, // paint the clipping rects with alpha to create the mask aClip.FillIntersectionOfRoundedRectClips(context, Color(1.f, 1.f, 1.f, 1.f), - newData.mAppUnitsPerDevPixel); + newData.mAppUnitsPerDevPixel, + 0, + aRoundedRectClipCount); // build the image and container MOZ_ASSERT(aLayer->Manager() == mManager); diff --git a/layout/painting/FrameLayerBuilder.h b/layout/painting/FrameLayerBuilder.h index 6e0108daff8c..de4b7cc46485 100644 --- a/layout/painting/FrameLayerBuilder.h +++ b/layout/painting/FrameLayerBuilder.h @@ -674,7 +674,8 @@ protected: nsDisplayListBuilder* aBuilder, nsPresContext* aPresContext, const nsIntPoint& aOffset, - float aXScale, float aYScale); + float aXScale, float aYScale, + int32_t aCommonClipCount); /** * We accumulate ClippedDisplayItem elements in a hashtable during From d047164a17a7771a4b4687c726a9d1307d5f7ebe Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Mon, 5 Mar 2018 14:21:38 -0800 Subject: [PATCH 08/23] Bug 1442931: Part 1 - Forbid web-visible interfaces outside of WebIDL root. r=mystor Web-visible WebIDL interfaces require DOM peer review with every change, which is enforced by a commit hook. ChromeOnly interfaces are not exposed to the web, and therefore don't require the same strictures. The current commit hook enforces the review requirement for changes to any (non-Servo) WebIDL file, and is not smart enough to determine if the change is web-visible. In order to loosen that restriction, we need the build system to enforce the requirement that only WebIDL files in certain locations may contain web-visible interfaces, so that the commit hook can restrict itself to checking only those directories. This change restricts the location of web-visible WebIDL interfaces to the dom/webidl/ and dom/bindings/ roots (along with the corresponding objdir root for generated interfaces). A follow-up will change the commit hook to only enforce review requirements on these directories. MozReview-Commit-ID: CiDxXxN4oO4 --HG-- extra : rebase_source : f61b33ae4c973b1c9ec1423bb9baca59725e44b1 --- dom/bindings/Configuration.py | 20 +++++++++++++++++- dom/bindings/mozwebidlcodegen/__init__.py | 25 +++++++++++++++++++++-- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/dom/bindings/Configuration.py b/dom/bindings/Configuration.py index 8b57c1e52a3c..c2c6515cadb9 100644 --- a/dom/bindings/Configuration.py +++ b/dom/bindings/Configuration.py @@ -18,12 +18,16 @@ class DescriptorProvider: pass +def isChildPath(path, basePath): + return os.path.commonprefix((path, basePath)) == basePath + + class Configuration(DescriptorProvider): """ Represents global configuration state based on IDL parse data and the configuration file. """ - def __init__(self, filename, parseData, generatedEvents=[]): + def __init__(self, filename, webRoots, parseData, generatedEvents=[]): DescriptorProvider.__init__(self) # Read the configuration file. @@ -31,6 +35,9 @@ class Configuration(DescriptorProvider): execfile(filename, glbl) config = glbl['DOMInterfaces'] + def isInWebIDLRoot(path): + return any(isChildPath(path, root) for root in webRoots) + # Build descriptors for all the interfaces we have in the parse data. # This allows callers to specify a subset of interfaces by filtering # |parseData|. @@ -94,6 +101,17 @@ class Configuration(DescriptorProvider): "%s\n" "%s" % (partialIface.location, iface.location)) + if not (iface.getExtendedAttribute("ChromeOnly") or + not (iface.hasInterfaceObject() or + iface.isNavigatorProperty()) or + isInWebIDLRoot(iface.filename())): + raise TypeError( + "Interfaces which are exposed to the web may only be " + "defined in a DOM WebIDL root %r. Consider marking " + "the interface [ChromeOnly] if you do not want it " + "exposed to the web.\n" + "%s" % + (webRoots, iface.location)) self.interfaces[iface.identifier.name] = iface if iface.identifier.name not in config: # Completely skip consequential interfaces with no descriptor diff --git a/dom/bindings/mozwebidlcodegen/__init__.py b/dom/bindings/mozwebidlcodegen/__init__.py index b6e351e52f75..57722a5bd6c9 100644 --- a/dom/bindings/mozwebidlcodegen/__init__.py +++ b/dom/bindings/mozwebidlcodegen/__init__.py @@ -150,7 +150,7 @@ class WebIDLCodegenManager(LoggingMixin): 'PrototypeList.cpp', } - def __init__(self, config_path, inputs, exported_header_dir, + def __init__(self, config_path, webidl_root, inputs, exported_header_dir, codegen_dir, state_path, cache_dir=None, make_deps_path=None, make_deps_target=None): """Create an instance that manages WebIDLs in the build system. @@ -176,6 +176,7 @@ class WebIDLCodegenManager(LoggingMixin): input_paths, exported_stems, generated_events_stems, example_interfaces = inputs self._config_path = config_path + self._webidl_root = webidl_root self._input_paths = set(input_paths) self._exported_stems = set(exported_stems) self._generated_events_stems = set(generated_events_stems) @@ -332,8 +333,26 @@ class WebIDLCodegenManager(LoggingMixin): hashes[path] = hashlib.sha1(data).hexdigest() parser.parse(data, path) + # Only these directories may contain WebIDL files with interfaces + # which are exposed to the web. WebIDL files in these roots may not + # be changed without DOM peer review. + # + # Other directories may contain WebIDL files as long as they only + # contain ChromeOnly interfaces. These are not subject to mandatory + # DOM peer review. + web_roots = ( + # The main WebIDL root. + self._webidl_root, + # The binding config root, which contains some test-only + # interfaces. + os.path.dirname(self._config_path), + # The objdir sub-directory which contains generated WebIDL files. + self._codegen_dir, + ) + self._parser_results = parser.finish() - self._config = Configuration(self._config_path, self._parser_results, + self._config = Configuration(self._config_path, web_roots, + self._parser_results, self._generated_events_stems_as_array) self._input_hashes = hashes @@ -546,6 +565,7 @@ def create_build_system_manager(topsrcdir, topobjdir, dist_dir): """Create a WebIDLCodegenManager for use by the build system.""" src_dir = os.path.join(topsrcdir, 'dom', 'bindings') obj_dir = os.path.join(topobjdir, 'dom', 'bindings') + webidl_root = os.path.join(topsrcdir, 'dom', 'webidl') with open(os.path.join(obj_dir, 'file-lists.json'), 'rb') as fh: files = json.load(fh) @@ -562,6 +582,7 @@ def create_build_system_manager(topsrcdir, topobjdir, dist_dir): return WebIDLCodegenManager( os.path.join(src_dir, 'Bindings.conf'), + webidl_root, inputs, os.path.join(dist_dir, 'include', 'mozilla', 'dom'), obj_dir, From 1306e251c04abb1a9aa8e3d3c54b89c214742c8b Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sun, 4 Mar 2018 16:37:10 -0800 Subject: [PATCH 09/23] Bug 1442931: Part 2 - Move internal WebIDL interfaces to separate directory. r=mystor DONTBUILD This change moves several chrome-only WebIDL files to a separate chrome-only directory. There are several other chrome-only interfaces which are heavily tied to DOM code. Since those should probably still require DOM peer review for changes, I left them where they were. MozReview-Commit-ID: K3NsNtfntV6 --HG-- rename : dom/webidl/ChannelWrapper.webidl => dom/chrome-webidl/ChannelWrapper.webidl rename : dom/webidl/ChromeUtils.webidl => dom/chrome-webidl/ChromeUtils.webidl rename : dom/webidl/DominatorTree.webidl => dom/chrome-webidl/DominatorTree.webidl rename : dom/webidl/HeapSnapshot.webidl => dom/chrome-webidl/HeapSnapshot.webidl rename : dom/webidl/InspectorUtils.webidl => dom/chrome-webidl/InspectorUtils.webidl rename : dom/webidl/MatchGlob.webidl => dom/chrome-webidl/MatchGlob.webidl rename : dom/webidl/MatchPattern.webidl => dom/chrome-webidl/MatchPattern.webidl rename : dom/webidl/MozStorageAsyncStatementParams.webidl => dom/chrome-webidl/MozStorageAsyncStatementParams.webidl rename : dom/webidl/MozStorageStatementParams.webidl => dom/chrome-webidl/MozStorageStatementParams.webidl rename : dom/webidl/MozStorageStatementRow.webidl => dom/chrome-webidl/MozStorageStatementRow.webidl rename : dom/webidl/PrecompiledScript.webidl => dom/chrome-webidl/PrecompiledScript.webidl rename : dom/webidl/PromiseDebugging.webidl => dom/chrome-webidl/PromiseDebugging.webidl rename : dom/webidl/StructuredCloneHolder.webidl => dom/chrome-webidl/StructuredCloneHolder.webidl rename : dom/webidl/WebExtensionContentScript.webidl => dom/chrome-webidl/WebExtensionContentScript.webidl rename : dom/webidl/WebExtensionPolicy.webidl => dom/chrome-webidl/WebExtensionPolicy.webidl rename : dom/webidl/moz.build => dom/chrome-webidl/moz.build extra : rebase_source : be95383471d1abadb742bbce683adc69b317028e extra : amend_source : ccb7840f3cdc5f7bd9871631e22d26d89a4dc156 --- .../ChannelWrapper.webidl | 0 .../ChromeUtils.webidl | 0 .../DominatorTree.webidl | 0 .../HeapSnapshot.webidl | 0 .../InspectorUtils.webidl | 0 .../MatchGlob.webidl | 0 .../MatchPattern.webidl | 0 .../MozStorageAsyncStatementParams.webidl | 0 .../MozStorageStatementParams.webidl | 0 .../MozStorageStatementRow.webidl | 0 .../PrecompiledScript.webidl | 0 .../PromiseDebugging.webidl | 0 .../StructuredCloneHolder.webidl | 0 .../WebExtensionContentScript.webidl | 0 .../WebExtensionPolicy.webidl | 0 dom/chrome-webidl/moz.build | 47 +++++++++++++++++++ dom/moz.build | 1 + dom/webidl/moz.build | 21 --------- 18 files changed, 48 insertions(+), 21 deletions(-) rename dom/{webidl => chrome-webidl}/ChannelWrapper.webidl (100%) rename dom/{webidl => chrome-webidl}/ChromeUtils.webidl (100%) rename dom/{webidl => chrome-webidl}/DominatorTree.webidl (100%) rename dom/{webidl => chrome-webidl}/HeapSnapshot.webidl (100%) rename dom/{webidl => chrome-webidl}/InspectorUtils.webidl (100%) rename dom/{webidl => chrome-webidl}/MatchGlob.webidl (100%) rename dom/{webidl => chrome-webidl}/MatchPattern.webidl (100%) rename dom/{webidl => chrome-webidl}/MozStorageAsyncStatementParams.webidl (100%) rename dom/{webidl => chrome-webidl}/MozStorageStatementParams.webidl (100%) rename dom/{webidl => chrome-webidl}/MozStorageStatementRow.webidl (100%) rename dom/{webidl => chrome-webidl}/PrecompiledScript.webidl (100%) rename dom/{webidl => chrome-webidl}/PromiseDebugging.webidl (100%) rename dom/{webidl => chrome-webidl}/StructuredCloneHolder.webidl (100%) rename dom/{webidl => chrome-webidl}/WebExtensionContentScript.webidl (100%) rename dom/{webidl => chrome-webidl}/WebExtensionPolicy.webidl (100%) create mode 100644 dom/chrome-webidl/moz.build diff --git a/dom/webidl/ChannelWrapper.webidl b/dom/chrome-webidl/ChannelWrapper.webidl similarity index 100% rename from dom/webidl/ChannelWrapper.webidl rename to dom/chrome-webidl/ChannelWrapper.webidl diff --git a/dom/webidl/ChromeUtils.webidl b/dom/chrome-webidl/ChromeUtils.webidl similarity index 100% rename from dom/webidl/ChromeUtils.webidl rename to dom/chrome-webidl/ChromeUtils.webidl diff --git a/dom/webidl/DominatorTree.webidl b/dom/chrome-webidl/DominatorTree.webidl similarity index 100% rename from dom/webidl/DominatorTree.webidl rename to dom/chrome-webidl/DominatorTree.webidl diff --git a/dom/webidl/HeapSnapshot.webidl b/dom/chrome-webidl/HeapSnapshot.webidl similarity index 100% rename from dom/webidl/HeapSnapshot.webidl rename to dom/chrome-webidl/HeapSnapshot.webidl diff --git a/dom/webidl/InspectorUtils.webidl b/dom/chrome-webidl/InspectorUtils.webidl similarity index 100% rename from dom/webidl/InspectorUtils.webidl rename to dom/chrome-webidl/InspectorUtils.webidl diff --git a/dom/webidl/MatchGlob.webidl b/dom/chrome-webidl/MatchGlob.webidl similarity index 100% rename from dom/webidl/MatchGlob.webidl rename to dom/chrome-webidl/MatchGlob.webidl diff --git a/dom/webidl/MatchPattern.webidl b/dom/chrome-webidl/MatchPattern.webidl similarity index 100% rename from dom/webidl/MatchPattern.webidl rename to dom/chrome-webidl/MatchPattern.webidl diff --git a/dom/webidl/MozStorageAsyncStatementParams.webidl b/dom/chrome-webidl/MozStorageAsyncStatementParams.webidl similarity index 100% rename from dom/webidl/MozStorageAsyncStatementParams.webidl rename to dom/chrome-webidl/MozStorageAsyncStatementParams.webidl diff --git a/dom/webidl/MozStorageStatementParams.webidl b/dom/chrome-webidl/MozStorageStatementParams.webidl similarity index 100% rename from dom/webidl/MozStorageStatementParams.webidl rename to dom/chrome-webidl/MozStorageStatementParams.webidl diff --git a/dom/webidl/MozStorageStatementRow.webidl b/dom/chrome-webidl/MozStorageStatementRow.webidl similarity index 100% rename from dom/webidl/MozStorageStatementRow.webidl rename to dom/chrome-webidl/MozStorageStatementRow.webidl diff --git a/dom/webidl/PrecompiledScript.webidl b/dom/chrome-webidl/PrecompiledScript.webidl similarity index 100% rename from dom/webidl/PrecompiledScript.webidl rename to dom/chrome-webidl/PrecompiledScript.webidl diff --git a/dom/webidl/PromiseDebugging.webidl b/dom/chrome-webidl/PromiseDebugging.webidl similarity index 100% rename from dom/webidl/PromiseDebugging.webidl rename to dom/chrome-webidl/PromiseDebugging.webidl diff --git a/dom/webidl/StructuredCloneHolder.webidl b/dom/chrome-webidl/StructuredCloneHolder.webidl similarity index 100% rename from dom/webidl/StructuredCloneHolder.webidl rename to dom/chrome-webidl/StructuredCloneHolder.webidl diff --git a/dom/webidl/WebExtensionContentScript.webidl b/dom/chrome-webidl/WebExtensionContentScript.webidl similarity index 100% rename from dom/webidl/WebExtensionContentScript.webidl rename to dom/chrome-webidl/WebExtensionContentScript.webidl diff --git a/dom/webidl/WebExtensionPolicy.webidl b/dom/chrome-webidl/WebExtensionPolicy.webidl similarity index 100% rename from dom/webidl/WebExtensionPolicy.webidl rename to dom/chrome-webidl/WebExtensionPolicy.webidl diff --git a/dom/chrome-webidl/moz.build b/dom/chrome-webidl/moz.build new file mode 100644 index 000000000000..71168e3846d9 --- /dev/null +++ b/dom/chrome-webidl/moz.build @@ -0,0 +1,47 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +with Files("**"): + BUG_COMPONENT = ("Core", "DOM") + +with Files("ChannelWrapper.webidl"): + BUG_COMPONENT = ("Toolkit", "WebExtensions: Request Handling") + +with Files("HeapSnapshot.webidl"): + BUG_COMPONENT = ("Firefox", "Developer Tools: Memory") + +with Files("InspectorUtils.webidl"): + BUG_COMPONENT = ("Firefox", "Developer Tools: Inspector") + +with Files("MatchGlob.webidl"): + BUG_COMPONENT = ("Toolkit", "WebExtensions: General") + +with Files("MatchPattern.webidl"): + BUG_COMPONENT = ("Toolkit", "WebExtensions: General") + +with Files("WebExtension*.webidl"): + BUG_COMPONENT = ("Toolkit", "WebExtensions: General") + +PREPROCESSED_WEBIDL_FILES = [ + 'ChromeUtils.webidl', +] + +WEBIDL_FILES = [ + 'ChannelWrapper.webidl', + 'DominatorTree.webidl', + 'HeapSnapshot.webidl', + 'InspectorUtils.webidl', + 'MatchGlob.webidl', + 'MatchPattern.webidl', + 'MozStorageAsyncStatementParams.webidl', + 'MozStorageStatementParams.webidl', + 'MozStorageStatementRow.webidl', + 'PrecompiledScript.webidl', + 'PromiseDebugging.webidl', + 'StructuredCloneHolder.webidl', + 'WebExtensionContentScript.webidl', + 'WebExtensionPolicy.webidl', +] diff --git a/dom/moz.build b/dom/moz.build index 0adab75f5e1a..17ad358df944 100644 --- a/dom/moz.build +++ b/dom/moz.build @@ -41,6 +41,7 @@ DIRS += [ 'browser-element', 'cache', 'canvas', + 'chrome-webidl', 'clients', 'commandhandler', 'credentialmanagement', diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index 8501b4c86e09..afe307c9cd64 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -139,9 +139,6 @@ with Files("HTML*"): with Files("HashChangeEvent.webidl"): BUG_COMPONENT = ("Core", "DOM: Events") -with Files("HeapSnapshot.webidl"): - BUG_COMPONENT = ("Firefox", "Developer Tools: Memory") - with Files("HiddenPluginEvent.webidl"): BUG_COMPONENT = ("Core", "Plug-ins") @@ -163,9 +160,6 @@ with Files("InputEvent.webidl"): with Files("InstallTrigger.webidl"): BUG_COMPONENT = ("Toolkit", "Add-ons Manager") -with Files("InspectorUtils.webidl"): - BUG_COMPONENT = ("Firefox", "Developer Tools: Inspector") - with Files("KeyAlgorithm.webidl"): BUG_COMPONENT = ("Core", "DOM: Security") @@ -360,7 +354,6 @@ GENERATED_WEBIDL_FILES = [ ] PREPROCESSED_WEBIDL_FILES = [ - 'ChromeUtils.webidl', 'Node.webidl', 'Window.webidl', ] @@ -418,7 +411,6 @@ WEBIDL_FILES = [ 'CDATASection.webidl', 'ChannelMergerNode.webidl', 'ChannelSplitterNode.webidl', - 'ChannelWrapper.webidl', 'CharacterData.webidl', 'CheckerboardReportService.webidl', 'ChildNode.webidl', @@ -483,7 +475,6 @@ WEBIDL_FILES = [ 'DOMError.webidl', 'DOMException.webidl', 'DOMImplementation.webidl', - 'DominatorTree.webidl', 'DOMMatrix.webidl', 'DOMParser.webidl', 'DOMPoint.webidl', @@ -536,7 +527,6 @@ WEBIDL_FILES = [ 'GetUserMediaRequest.webidl', 'Grid.webidl', 'Headers.webidl', - 'HeapSnapshot.webidl', 'History.webidl', 'HTMLAllCollection.webidl', 'HTMLAnchorElement.webidl', @@ -635,7 +625,6 @@ WEBIDL_FILES = [ 'ImageData.webidl', 'ImageDocument.webidl', 'InputEvent.webidl', - 'InspectorUtils.webidl', 'IntersectionObserver.webidl', 'IntlUtils.webidl', 'IterableIterator.webidl', @@ -651,8 +640,6 @@ WEBIDL_FILES = [ 'ListBoxObject.webidl', 'LocalMediaStream.webidl', 'Location.webidl', - 'MatchGlob.webidl', - 'MatchPattern.webidl', 'MediaDeviceInfo.webidl', 'MediaDevices.webidl', 'MediaElementAudioSourceNode.webidl', @@ -693,9 +680,6 @@ WEBIDL_FILES = [ 'MimeTypeArray.webidl', 'MouseEvent.webidl', 'MouseScrollEvent.webidl', - 'MozStorageAsyncStatementParams.webidl', - 'MozStorageStatementParams.webidl', - 'MozStorageStatementRow.webidl', 'MutationEvent.webidl', 'MutationObserver.webidl', 'NamedNodeMap.webidl', @@ -742,7 +726,6 @@ WEBIDL_FILES = [ 'PopupBoxObject.webidl', 'Position.webidl', 'PositionError.webidl', - 'PrecompiledScript.webidl', 'Presentation.webidl', 'PresentationAvailability.webidl', 'PresentationConnection.webidl', @@ -752,7 +735,6 @@ WEBIDL_FILES = [ 'ProcessingInstruction.webidl', 'ProfileTimelineMarker.webidl', 'Promise.webidl', - 'PromiseDebugging.webidl', 'PushEvent.webidl', 'PushManager.webidl', 'PushManager.webidl', @@ -790,7 +772,6 @@ WEBIDL_FILES = [ 'StorageType.webidl', 'StreamFilter.webidl', 'StreamFilterDataEvent.webidl', - 'StructuredCloneHolder.webidl', 'StyleSheet.webidl', 'StyleSheetList.webidl', 'SubtleCrypto.webidl', @@ -945,8 +926,6 @@ WEBIDL_FILES = [ 'WaveShaperNode.webidl', 'WebAuthentication.webidl', 'WebComponents.webidl', - 'WebExtensionContentScript.webidl', - 'WebExtensionPolicy.webidl', 'WebGL2RenderingContext.webidl', 'WebGLRenderingContext.webidl', 'WebKitCSSMatrix.webidl', From aa19ca17094eb22e90359c940660fcf6354a3c6d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 5 Mar 2018 13:54:06 +1100 Subject: [PATCH 10/23] Bug 1442433 - Remove the refcount from static atoms. r=froydnj The refcount is only used for dynamic atoms. On 64-bit, this reduces sizeof(nsStaticAtom) from 24 bytes to 16 bytes, and the on-heap size from 32 bytes to 16 bytes. This saves 42 KiB per process. On 32-bit, this reduces sizeof(nsStaticAtom) from 16 bytes to 12 bytes, but the on-heap size stays at 16 bytes, so memory usage is unchanged. MozReview-Commit-ID: 7d9H7MRHN9a --HG-- extra : rebase_source : d3eafb3aaf44a592afd6c89cd0519d043056e65a --- xpcom/ds/nsAtom.h | 8 ++-- xpcom/ds/nsAtomTable.cpp | 81 +++++++++++++++++++++++++++------------- 2 files changed, 59 insertions(+), 30 deletions(-) diff --git a/xpcom/ds/nsAtom.h b/xpcom/ds/nsAtom.h index cf043198687d..5178776f1765 100644 --- a/xpcom/ds/nsAtom.h +++ b/xpcom/ds/nsAtom.h @@ -88,15 +88,15 @@ private: friend class nsAtomSubTable; friend class nsHtml5AtomEntry; - // Dynamic atom construction is done by |friend|s. +protected: + // Used by nsDynamicAtom and directly (by nsHtml5AtomEntry) for HTML5 atoms. nsAtom(AtomKind aKind, const nsAString& aString, uint32_t aHash); -protected: + // Used by nsStaticAtom. nsAtom(const char16_t* aString, uint32_t aLength, uint32_t aHash); ~nsAtom(); - mozilla::ThreadSafeAutoRefCnt mRefCnt; uint32_t mLength: 30; uint32_t mKind: 2; // nsAtom::AtomKind uint32_t mHash; @@ -118,7 +118,7 @@ class nsStaticAtom : public nsAtom { public: // These are deleted so it's impossible to RefPtr. Raw - // nsStaticAtom atoms should be used instead. + // nsStaticAtom pointers should be used instead. MozExternalRefCountType AddRef() = delete; MozExternalRefCountType Release() = delete; diff --git a/xpcom/ds/nsAtomTable.cpp b/xpcom/ds/nsAtomTable.cpp index 4cca81b680f6..33e0062f0a73 100644 --- a/xpcom/ds/nsAtomTable.cpp +++ b/xpcom/ds/nsAtomTable.cpp @@ -64,10 +64,37 @@ enum class GCKind { // See nsAtom::AddRef() and nsAtom::Release(). static Atomic gUnusedAtomCount(0); +// Dynamic atoms need a ref count; this class adds that to nsAtom. +class nsDynamicAtom : public nsAtom +{ +public: + // We can't use NS_INLINE_DECL_THREADSAFE_REFCOUNTING because the refcounting + // of this type is special. + MozExternalRefCountType AddRef(); + MozExternalRefCountType Release(); + + static nsDynamicAtom* As(nsAtom* aAtom) + { + MOZ_ASSERT(aAtom->IsDynamicAtom()); + return static_cast(aAtom); + } + +private: + friend class nsAtomTable; + friend class nsAtomSubTable; + + // Construction is done by |friend|s. + nsDynamicAtom(const nsAString& aString, uint32_t aHash) + : nsAtom(AtomKind::DynamicAtom, aString, aHash) + , mRefCnt(1) + {} + + mozilla::ThreadSafeAutoRefCnt mRefCnt; +}; + // This constructor is for dynamic atoms and HTML5 atoms. nsAtom::nsAtom(AtomKind aKind, const nsAString& aString, uint32_t aHash) - : mRefCnt(1) - , mLength(aString.Length()) + : mLength(aString.Length()) , mKind(static_cast(aKind)) , mHash(aHash) { @@ -88,7 +115,7 @@ nsAtom::nsAtom(AtomKind aKind, const nsAString& aString, uint32_t aHash) mString[mLength] = char16_t(0); } - MOZ_ASSERT_IF(IsDynamicAtom(), mHash == HashString(mString, mLength)); + MOZ_ASSERT_IF(!IsHTML5Atom(), mHash == HashString(mString, mLength)); MOZ_ASSERT(mString[mLength] == char16_t(0), "null terminated"); MOZ_ASSERT(buf && buf->StorageSize() >= (mLength + 1) * sizeof(char16_t), @@ -474,7 +501,8 @@ nsAtomSubTable::GCLocked(GCKind aKind) } nsAtom* atom = entry->mAtom; - if (atom->mRefCnt == 0) { + MOZ_ASSERT(!atom->IsHTML5Atom()); + if (atom->IsDynamicAtom() && nsDynamicAtom::As(atom)->mRefCnt == 0) { i.Remove(); delete atom; ++removedCount; @@ -516,15 +544,9 @@ GCAtomTable() } } -MozExternalRefCountType -nsAtom::AddRef() +MOZ_ALWAYS_INLINE MozExternalRefCountType +nsDynamicAtom::AddRef() { - MOZ_ASSERT(!IsHTML5Atom(), "Attempt to AddRef an HTML5 atom"); - if (!IsDynamicAtom()) { - MOZ_ASSERT(IsStaticAtom()); - return 2; - } - MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); nsrefcnt count = ++mRefCnt; if (count == 1) { @@ -533,15 +555,9 @@ nsAtom::AddRef() return count; } -MozExternalRefCountType -nsAtom::Release() +MOZ_ALWAYS_INLINE MozExternalRefCountType +nsDynamicAtom::Release() { - MOZ_ASSERT(!IsHTML5Atom(), "Attempt to Release an HTML5 atom"); - if (!IsDynamicAtom()) { - MOZ_ASSERT(IsStaticAtom()); - return 1; - } - #ifdef DEBUG // We set a lower GC threshold for atoms in debug builds so that we exercise // the GC machinery more often. @@ -561,6 +577,22 @@ nsAtom::Release() return count; } +MozExternalRefCountType +nsAtom::AddRef() +{ + MOZ_ASSERT(!IsHTML5Atom(), "Attempt to AddRef an HTML5 atom"); + + return IsStaticAtom() ? 2 : nsDynamicAtom::As(this)->AddRef(); +} + +MozExternalRefCountType +nsAtom::Release() +{ + MOZ_ASSERT(!IsHTML5Atom(), "Attempt to Release an HTML5 atom"); + + return IsStaticAtom() ? 1 : nsDynamicAtom::As(this)->Release(); +} + //---------------------------------------------------------------------- // Have the static atoms been inserted into the table? @@ -706,8 +738,7 @@ nsAtomTable::Atomize(const nsACString& aUTF8String) // Actually, now there is, sort of: ForgetSharedBuffer. nsString str; CopyUTF8toUTF16(aUTF8String, str); - RefPtr atom = - dont_AddRef(new nsAtom(nsAtom::AtomKind::DynamicAtom, str, hash)); + RefPtr atom = dont_AddRef(new nsDynamicAtom(str, hash)); he->mAtom = atom; @@ -743,8 +774,7 @@ nsAtomTable::Atomize(const nsAString& aUTF16String) return atom.forget(); } - RefPtr atom = - dont_AddRef(new nsAtom(nsAtom::AtomKind::DynamicAtom, aUTF16String, hash)); + RefPtr atom = dont_AddRef(new nsDynamicAtom(aUTF16String, hash)); he->mAtom = atom; return atom.forget(); @@ -783,8 +813,7 @@ nsAtomTable::AtomizeMainThread(const nsAString& aUTF16String) if (he->mAtom) { retVal = he->mAtom; } else { - RefPtr newAtom = dont_AddRef( - new nsAtom(nsAtom::AtomKind::DynamicAtom, aUTF16String, hash)); + RefPtr newAtom = dont_AddRef(new nsDynamicAtom(aUTF16String, hash)); he->mAtom = newAtom; retVal = newAtom.forget(); } From f39f6d122812437faffebc532eff0601b2d4ec50 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 5 Mar 2018 13:54:06 +1100 Subject: [PATCH 11/23] Bug 1442433 - Make some nsAtom fields `const`. r=froydnj Also remove the unused SetKind() method. MozReview-Commit-ID: CIh6BmN7OLI --HG-- extra : rebase_source : 149b9e9ef1180e074b13fd5812ea8dbf2f907bb4 --- xpcom/ds/nsAtom.h | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/xpcom/ds/nsAtom.h b/xpcom/ds/nsAtom.h index 5178776f1765..191af8dcd96a 100644 --- a/xpcom/ds/nsAtom.h +++ b/xpcom/ds/nsAtom.h @@ -38,12 +38,6 @@ public: return Equals(aString.BeginReading(), aString.Length()); } - void SetKind(AtomKind aKind) - { - mKind = static_cast(aKind); - MOZ_ASSERT(Kind() == aKind); - } - AtomKind Kind() const { return static_cast(mKind); } bool IsDynamicAtom() const { return Kind() == AtomKind::DynamicAtom; } @@ -97,9 +91,9 @@ protected: ~nsAtom(); - uint32_t mLength: 30; - uint32_t mKind: 2; // nsAtom::AtomKind - uint32_t mHash; + const uint32_t mLength:30; + const uint32_t mKind:2; // nsAtom::AtomKind + const uint32_t mHash; // WARNING! For static atoms, this is a pointer to a static char buffer. For // non-static atoms it points to the chars in an nsStringBuffer. This means // that nsStringBuffer::FromData(mString) calls are only valid for non-static From 9bc7f17b9e4cf346454c564103b7255302f8d4b8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 7 Mar 2018 11:57:54 +1100 Subject: [PATCH 12/23] Bug 1442433 - Make nsAtom::mString more const. r=froydnj The patch also uses GetStringBuffer() in a couple of appropriate places. MozReview-Commit-ID: JufCUgmO8JL --HG-- extra : rebase_source : ecd3f17b5560b19622c86759d605fa122d70e48a --- xpcom/ds/nsAtom.h | 7 ++--- xpcom/ds/nsAtomTable.cpp | 56 +++++++++++++++++++++++----------------- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/xpcom/ds/nsAtom.h b/xpcom/ds/nsAtom.h index 191af8dcd96a..a8ca3ae01b1d 100644 --- a/xpcom/ds/nsAtom.h +++ b/xpcom/ds/nsAtom.h @@ -51,11 +51,12 @@ public: void ToString(nsAString& aString) const; void ToUTF8String(nsACString& aString) const; - // This is only valid for dynamic atoms. + // This is not valid for static atoms. The caller must *not* mutate the + // string buffer, otherwise all hell will break loose. nsStringBuffer* GetStringBuffer() const { // See the comment on |mString|'s declaration. - MOZ_ASSERT(IsDynamicAtom()); + MOZ_ASSERT(IsDynamicAtom() || IsHTML5Atom()); return nsStringBuffer::FromData(mString); } @@ -98,7 +99,7 @@ protected: // non-static atoms it points to the chars in an nsStringBuffer. This means // that nsStringBuffer::FromData(mString) calls are only valid for non-static // atoms. - char16_t* mString; + char16_t* const mString; }; // A trivial subclass of nsAtom that can be used for known static atoms. The diff --git a/xpcom/ds/nsAtomTable.cpp b/xpcom/ds/nsAtomTable.cpp index 33e0062f0a73..a174ea9c4720 100644 --- a/xpcom/ds/nsAtomTable.cpp +++ b/xpcom/ds/nsAtomTable.cpp @@ -92,38 +92,47 @@ private: mozilla::ThreadSafeAutoRefCnt mRefCnt; }; +static char16_t* +FromStringBuffer(const nsAString& aString) +{ + char16_t* str; + size_t length = aString.Length(); + RefPtr buf = nsStringBuffer::FromString(aString); + if (buf) { + str = static_cast(buf->Data()); + } else { + const size_t size = (length + 1) * sizeof(char16_t); + buf = nsStringBuffer::Alloc(size); + if (MOZ_UNLIKELY(!buf)) { + NS_ABORT_OOM(size); // OOM because atom allocations should be small. + } + str = static_cast(buf->Data()); + CopyUnicodeTo(aString, 0, str, length); + str[length] = char16_t(0); + } + + MOZ_ASSERT(buf && buf->StorageSize() >= (length + 1) * sizeof(char16_t), + "enough storage"); + + // Take ownership of the string buffer. + mozilla::Unused << buf.forget(); + + return str; +} + // This constructor is for dynamic atoms and HTML5 atoms. nsAtom::nsAtom(AtomKind aKind, const nsAString& aString, uint32_t aHash) : mLength(aString.Length()) , mKind(static_cast(aKind)) , mHash(aHash) + , mString(FromStringBuffer(aString)) { MOZ_ASSERT(aKind == AtomKind::DynamicAtom || aKind == AtomKind::HTML5Atom); - RefPtr buf = nsStringBuffer::FromString(aString); - if (buf) { - mString = static_cast(buf->Data()); - } else { - const size_t size = (mLength + 1) * sizeof(char16_t); - buf = nsStringBuffer::Alloc(size); - if (MOZ_UNLIKELY(!buf)) { - // We OOM because atom allocations should be small and it's hard to - // handle them more gracefully in a constructor. - NS_ABORT_OOM(size); - } - mString = static_cast(buf->Data()); - CopyUnicodeTo(aString, 0, mString, mLength); - mString[mLength] = char16_t(0); - } MOZ_ASSERT_IF(!IsHTML5Atom(), mHash == HashString(mString, mLength)); MOZ_ASSERT(mString[mLength] == char16_t(0), "null terminated"); - MOZ_ASSERT(buf && buf->StorageSize() >= (mLength + 1) * sizeof(char16_t), - "enough storage"); MOZ_ASSERT(Equals(aString), "correct data"); - - // Take ownership of buffer - mozilla::Unused << buf.forget(); } // This constructor is for static atoms. @@ -143,7 +152,7 @@ nsAtom::~nsAtom() { if (!IsStaticAtom()) { MOZ_ASSERT(IsDynamicAtom() || IsHTML5Atom()); - nsStringBuffer::FromData(mString)->Release(); + GetStringBuffer()->Release(); } } @@ -157,7 +166,7 @@ nsAtom::ToString(nsAString& aString) const // which is what's important. aString.AssignLiteral(mString, mLength); } else { - nsStringBuffer::FromData(mString)->ToString(mLength, aString); + GetStringBuffer()->ToString(mLength, aString); } } @@ -182,8 +191,7 @@ nsAtom::AddSizeOfIncludingThis(MallocSizeOf aMallocSizeOf, AtomsSizes& aSizes) } else { aSizes.mDynamicAtomObjects += thisSize; aSizes.mDynamicUnsharedBuffers += - nsStringBuffer::FromData(mString)->SizeOfIncludingThisIfUnshared( - aMallocSizeOf); + GetStringBuffer()->SizeOfIncludingThisIfUnshared(aMallocSizeOf); } } From ba2ac04f54fec7f5f4d789c58860cf153181504b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 7 Mar 2018 11:59:01 +1100 Subject: [PATCH 13/23] Bug 1442433 - Make nsAtom::mString even more const. r=froydnj MozReview-Commit-ID: ANm2nrnO4Lb --HG-- extra : rebase_source : 444f72316f047004cddfc2eef947b122db1cb87d --- xpcom/ds/nsAtom.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xpcom/ds/nsAtom.h b/xpcom/ds/nsAtom.h index a8ca3ae01b1d..d450b89d5a61 100644 --- a/xpcom/ds/nsAtom.h +++ b/xpcom/ds/nsAtom.h @@ -57,7 +57,7 @@ public: { // See the comment on |mString|'s declaration. MOZ_ASSERT(IsDynamicAtom() || IsHTML5Atom()); - return nsStringBuffer::FromData(mString); + return nsStringBuffer::FromData(const_cast(mString)); } // A hashcode that is better distributed than the actual atom pointer, for @@ -99,7 +99,7 @@ protected: // non-static atoms it points to the chars in an nsStringBuffer. This means // that nsStringBuffer::FromData(mString) calls are only valid for non-static // atoms. - char16_t* const mString; + const char16_t* const mString; }; // A trivial subclass of nsAtom that can be used for known static atoms. The From 897ea8c31489e06882ec974f9c12936940e91413 Mon Sep 17 00:00:00 2001 From: Makoto Kato Date: Wed, 7 Mar 2018 11:01:30 +0900 Subject: [PATCH 14/23] Bug 1438955 - Remove ImmReleaseContext hook. r=masayuki --HG-- extra : rebase_source : 78eeb24aa1b89c634cb9da089b43c01bdd390906 --- dom/plugins/ipc/PluginInstanceChild.cpp | 20 +++----------------- dom/plugins/ipc/PluginInstanceChild.h | 1 - toolkit/xre/test/win/TestDllInterceptor.cpp | 1 - 3 files changed, 3 insertions(+), 19 deletions(-) diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginInstanceChild.cpp index e5b2382ca8aa..7547db7d5f55 100644 --- a/dom/plugins/ipc/PluginInstanceChild.cpp +++ b/dom/plugins/ipc/PluginInstanceChild.cpp @@ -76,7 +76,6 @@ static HWND sWinlessPopupSurrogateHWND = nullptr; static User32TrackPopupMenu sUser32TrackPopupMenuStub = nullptr; typedef HIMC (WINAPI *Imm32ImmGetContext)(HWND hWND); -typedef BOOL (WINAPI *Imm32ImmReleaseContext)(HWND hWND, HIMC hIMC); typedef LONG (WINAPI *Imm32ImmGetCompositionString)(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, @@ -87,7 +86,6 @@ typedef BOOL (WINAPI *Imm32ImmNotifyIME)(HIMC hIMC, DWORD dwAction, DWORD dwIndex, DWORD dwValue); static WindowsDllInterceptor sImm32Intercept; static Imm32ImmGetContext sImm32ImmGetContextStub = nullptr; -static Imm32ImmReleaseContext sImm32ImmReleaseContextStub = nullptr; static Imm32ImmGetCompositionString sImm32ImmGetCompositionStringStub = nullptr; static Imm32ImmSetCandidateWindow sImm32ImmSetCandidateWindowStub = nullptr; static Imm32ImmNotifyIME sImm32ImmNotifyIME = nullptr; @@ -2035,17 +2033,6 @@ PluginInstanceChild::ImmGetContextProc(HWND aWND) return sHookIMC; } -// static -BOOL -PluginInstanceChild::ImmReleaseContextProc(HWND aWND, HIMC aIMC) -{ - if (aIMC == sHookIMC) { - return TRUE; - } - - return sImm32ImmReleaseContextStub(aWND, aIMC); -} - // static LONG PluginInstanceChild::ImmGetCompositionStringProc(HIMC aIMC, DWORD aIndex, @@ -2130,16 +2117,15 @@ PluginInstanceChild::InitImm32Hook() } // When using windowless plugin, IMM API won't work due ot OOP. + // + // ImmReleaseContext on Windows 7+ just returns TRUE only, so we don't + // need to hook this. sImm32Intercept.Init("imm32.dll"); sImm32Intercept.AddHook( "ImmGetContext", reinterpret_cast(ImmGetContextProc), (void**)&sImm32ImmGetContextStub); - sImm32Intercept.AddHook( - "ImmReleaseContext", - reinterpret_cast(ImmReleaseContextProc), - (void**)&sImm32ImmReleaseContextStub); sImm32Intercept.AddHook( "ImmGetCompositionStringW", reinterpret_cast(ImmGetCompositionStringProc), diff --git a/dom/plugins/ipc/PluginInstanceChild.h b/dom/plugins/ipc/PluginInstanceChild.h index 86c94cd1a851..ed223d26b18c 100644 --- a/dom/plugins/ipc/PluginInstanceChild.h +++ b/dom/plugins/ipc/PluginInstanceChild.h @@ -335,7 +335,6 @@ private: #endif static HIMC WINAPI ImmGetContextProc(HWND aWND); - static BOOL WINAPI ImmReleaseContextProc(HWND aWND, HIMC aIMC); static LONG WINAPI ImmGetCompositionStringProc(HIMC aIMC, DWORD aIndex, LPVOID aBuf, DWORD aLen); static BOOL WINAPI ImmSetCandidateWindowProc(HIMC hIMC, diff --git a/toolkit/xre/test/win/TestDllInterceptor.cpp b/toolkit/xre/test/win/TestDllInterceptor.cpp index 64f75b344eb8..8c642e86b171 100644 --- a/toolkit/xre/test/win/TestDllInterceptor.cpp +++ b/toolkit/xre/test/win/TestDllInterceptor.cpp @@ -675,7 +675,6 @@ int main() TestDetour("user32.dll", "CreateWindowExW") && TestHook(TestInSendMessageEx, "user32.dll", "InSendMessageEx") && TestHook(TestImmGetContext, "imm32.dll", "ImmGetContext") && - // TestHook("imm32.dll", "ImmReleaseContext") && // see Bug 1316415 TestHook(TestImmGetCompositionStringW, "imm32.dll", "ImmGetCompositionStringW") && TestHook(TestImmSetCandidateWindow, "imm32.dll", "ImmSetCandidateWindow") && TestHook(TestImmNotifyIME, "imm32.dll", "ImmNotifyIME") && From 1684805047f4fa5eb0b0cd982c7c29c50566ccee Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Mon, 5 Mar 2018 17:10:05 -0600 Subject: [PATCH 15/23] Bug 1443147 - Fix PosixNSPR build after bug 1441454. r=sfink --HG-- extra : rebase_source : 8187dec35e6d7c398f31c2438cd903edb52fe6b4 --- js/src/shell/js.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 8b55e2203b8d..598ee5cf5b91 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -136,12 +136,25 @@ using mozilla::TimeStamp; // Avoid an unnecessary NSPR dependency on Linux and OS X just for the shell. #ifdef JS_POSIX_NSPR + +enum PRLibSpecType { PR_LibSpec_Pathname }; + +struct PRLibSpec { + PRLibSpecType type; + union { + const char *pathname; + } value; +}; + typedef void PRLibrary; -static PRLibrary* -PR_LoadLibrary(const char* path) +#define PR_LD_NOW RTLD_NOW +#define PR_LD_GLOBAL RTLD_GLOBAL + +static PRLibrary * +PR_LoadLibraryWithFlags(PRLibSpec libSpec, int flags) { - return dlopen(path, RTLD_LAZY | RTLD_GLOBAL); + return dlopen(libSpec.value.pathname, flags); } static void From 27f4fb5abd0f746be034e2c690364f9fb2c16a26 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Tue, 6 Mar 2018 20:47:41 -0800 Subject: [PATCH 16/23] Backed out two changesets (bug 1442931) for Windows build bustage MozReview-Commit-ID: EAP1dIdvd8g --HG-- extra : histedit_source : 0848dcd64f0e1cccaf9ce2c5faa08509990cfade%2Cd100c0c3dfca8b92f9cd1fda1b126a0d2f8a47cd --- dom/bindings/Configuration.py | 20 +------- dom/bindings/mozwebidlcodegen/__init__.py | 25 +--------- dom/chrome-webidl/moz.build | 47 ------------------- dom/moz.build | 1 - .../ChannelWrapper.webidl | 0 .../ChromeUtils.webidl | 0 .../DominatorTree.webidl | 0 .../HeapSnapshot.webidl | 0 .../InspectorUtils.webidl | 0 .../MatchGlob.webidl | 0 .../MatchPattern.webidl | 0 .../MozStorageAsyncStatementParams.webidl | 0 .../MozStorageStatementParams.webidl | 0 .../MozStorageStatementRow.webidl | 0 .../PrecompiledScript.webidl | 0 .../PromiseDebugging.webidl | 0 .../StructuredCloneHolder.webidl | 0 .../WebExtensionContentScript.webidl | 0 .../WebExtensionPolicy.webidl | 0 dom/webidl/moz.build | 21 +++++++++ 20 files changed, 24 insertions(+), 90 deletions(-) delete mode 100644 dom/chrome-webidl/moz.build rename dom/{chrome-webidl => webidl}/ChannelWrapper.webidl (100%) rename dom/{chrome-webidl => webidl}/ChromeUtils.webidl (100%) rename dom/{chrome-webidl => webidl}/DominatorTree.webidl (100%) rename dom/{chrome-webidl => webidl}/HeapSnapshot.webidl (100%) rename dom/{chrome-webidl => webidl}/InspectorUtils.webidl (100%) rename dom/{chrome-webidl => webidl}/MatchGlob.webidl (100%) rename dom/{chrome-webidl => webidl}/MatchPattern.webidl (100%) rename dom/{chrome-webidl => webidl}/MozStorageAsyncStatementParams.webidl (100%) rename dom/{chrome-webidl => webidl}/MozStorageStatementParams.webidl (100%) rename dom/{chrome-webidl => webidl}/MozStorageStatementRow.webidl (100%) rename dom/{chrome-webidl => webidl}/PrecompiledScript.webidl (100%) rename dom/{chrome-webidl => webidl}/PromiseDebugging.webidl (100%) rename dom/{chrome-webidl => webidl}/StructuredCloneHolder.webidl (100%) rename dom/{chrome-webidl => webidl}/WebExtensionContentScript.webidl (100%) rename dom/{chrome-webidl => webidl}/WebExtensionPolicy.webidl (100%) diff --git a/dom/bindings/Configuration.py b/dom/bindings/Configuration.py index c2c6515cadb9..8b57c1e52a3c 100644 --- a/dom/bindings/Configuration.py +++ b/dom/bindings/Configuration.py @@ -18,16 +18,12 @@ class DescriptorProvider: pass -def isChildPath(path, basePath): - return os.path.commonprefix((path, basePath)) == basePath - - class Configuration(DescriptorProvider): """ Represents global configuration state based on IDL parse data and the configuration file. """ - def __init__(self, filename, webRoots, parseData, generatedEvents=[]): + def __init__(self, filename, parseData, generatedEvents=[]): DescriptorProvider.__init__(self) # Read the configuration file. @@ -35,9 +31,6 @@ class Configuration(DescriptorProvider): execfile(filename, glbl) config = glbl['DOMInterfaces'] - def isInWebIDLRoot(path): - return any(isChildPath(path, root) for root in webRoots) - # Build descriptors for all the interfaces we have in the parse data. # This allows callers to specify a subset of interfaces by filtering # |parseData|. @@ -101,17 +94,6 @@ class Configuration(DescriptorProvider): "%s\n" "%s" % (partialIface.location, iface.location)) - if not (iface.getExtendedAttribute("ChromeOnly") or - not (iface.hasInterfaceObject() or - iface.isNavigatorProperty()) or - isInWebIDLRoot(iface.filename())): - raise TypeError( - "Interfaces which are exposed to the web may only be " - "defined in a DOM WebIDL root %r. Consider marking " - "the interface [ChromeOnly] if you do not want it " - "exposed to the web.\n" - "%s" % - (webRoots, iface.location)) self.interfaces[iface.identifier.name] = iface if iface.identifier.name not in config: # Completely skip consequential interfaces with no descriptor diff --git a/dom/bindings/mozwebidlcodegen/__init__.py b/dom/bindings/mozwebidlcodegen/__init__.py index 57722a5bd6c9..b6e351e52f75 100644 --- a/dom/bindings/mozwebidlcodegen/__init__.py +++ b/dom/bindings/mozwebidlcodegen/__init__.py @@ -150,7 +150,7 @@ class WebIDLCodegenManager(LoggingMixin): 'PrototypeList.cpp', } - def __init__(self, config_path, webidl_root, inputs, exported_header_dir, + def __init__(self, config_path, inputs, exported_header_dir, codegen_dir, state_path, cache_dir=None, make_deps_path=None, make_deps_target=None): """Create an instance that manages WebIDLs in the build system. @@ -176,7 +176,6 @@ class WebIDLCodegenManager(LoggingMixin): input_paths, exported_stems, generated_events_stems, example_interfaces = inputs self._config_path = config_path - self._webidl_root = webidl_root self._input_paths = set(input_paths) self._exported_stems = set(exported_stems) self._generated_events_stems = set(generated_events_stems) @@ -333,26 +332,8 @@ class WebIDLCodegenManager(LoggingMixin): hashes[path] = hashlib.sha1(data).hexdigest() parser.parse(data, path) - # Only these directories may contain WebIDL files with interfaces - # which are exposed to the web. WebIDL files in these roots may not - # be changed without DOM peer review. - # - # Other directories may contain WebIDL files as long as they only - # contain ChromeOnly interfaces. These are not subject to mandatory - # DOM peer review. - web_roots = ( - # The main WebIDL root. - self._webidl_root, - # The binding config root, which contains some test-only - # interfaces. - os.path.dirname(self._config_path), - # The objdir sub-directory which contains generated WebIDL files. - self._codegen_dir, - ) - self._parser_results = parser.finish() - self._config = Configuration(self._config_path, web_roots, - self._parser_results, + self._config = Configuration(self._config_path, self._parser_results, self._generated_events_stems_as_array) self._input_hashes = hashes @@ -565,7 +546,6 @@ def create_build_system_manager(topsrcdir, topobjdir, dist_dir): """Create a WebIDLCodegenManager for use by the build system.""" src_dir = os.path.join(topsrcdir, 'dom', 'bindings') obj_dir = os.path.join(topobjdir, 'dom', 'bindings') - webidl_root = os.path.join(topsrcdir, 'dom', 'webidl') with open(os.path.join(obj_dir, 'file-lists.json'), 'rb') as fh: files = json.load(fh) @@ -582,7 +562,6 @@ def create_build_system_manager(topsrcdir, topobjdir, dist_dir): return WebIDLCodegenManager( os.path.join(src_dir, 'Bindings.conf'), - webidl_root, inputs, os.path.join(dist_dir, 'include', 'mozilla', 'dom'), obj_dir, diff --git a/dom/chrome-webidl/moz.build b/dom/chrome-webidl/moz.build deleted file mode 100644 index 71168e3846d9..000000000000 --- a/dom/chrome-webidl/moz.build +++ /dev/null @@ -1,47 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -with Files("**"): - BUG_COMPONENT = ("Core", "DOM") - -with Files("ChannelWrapper.webidl"): - BUG_COMPONENT = ("Toolkit", "WebExtensions: Request Handling") - -with Files("HeapSnapshot.webidl"): - BUG_COMPONENT = ("Firefox", "Developer Tools: Memory") - -with Files("InspectorUtils.webidl"): - BUG_COMPONENT = ("Firefox", "Developer Tools: Inspector") - -with Files("MatchGlob.webidl"): - BUG_COMPONENT = ("Toolkit", "WebExtensions: General") - -with Files("MatchPattern.webidl"): - BUG_COMPONENT = ("Toolkit", "WebExtensions: General") - -with Files("WebExtension*.webidl"): - BUG_COMPONENT = ("Toolkit", "WebExtensions: General") - -PREPROCESSED_WEBIDL_FILES = [ - 'ChromeUtils.webidl', -] - -WEBIDL_FILES = [ - 'ChannelWrapper.webidl', - 'DominatorTree.webidl', - 'HeapSnapshot.webidl', - 'InspectorUtils.webidl', - 'MatchGlob.webidl', - 'MatchPattern.webidl', - 'MozStorageAsyncStatementParams.webidl', - 'MozStorageStatementParams.webidl', - 'MozStorageStatementRow.webidl', - 'PrecompiledScript.webidl', - 'PromiseDebugging.webidl', - 'StructuredCloneHolder.webidl', - 'WebExtensionContentScript.webidl', - 'WebExtensionPolicy.webidl', -] diff --git a/dom/moz.build b/dom/moz.build index 17ad358df944..0adab75f5e1a 100644 --- a/dom/moz.build +++ b/dom/moz.build @@ -41,7 +41,6 @@ DIRS += [ 'browser-element', 'cache', 'canvas', - 'chrome-webidl', 'clients', 'commandhandler', 'credentialmanagement', diff --git a/dom/chrome-webidl/ChannelWrapper.webidl b/dom/webidl/ChannelWrapper.webidl similarity index 100% rename from dom/chrome-webidl/ChannelWrapper.webidl rename to dom/webidl/ChannelWrapper.webidl diff --git a/dom/chrome-webidl/ChromeUtils.webidl b/dom/webidl/ChromeUtils.webidl similarity index 100% rename from dom/chrome-webidl/ChromeUtils.webidl rename to dom/webidl/ChromeUtils.webidl diff --git a/dom/chrome-webidl/DominatorTree.webidl b/dom/webidl/DominatorTree.webidl similarity index 100% rename from dom/chrome-webidl/DominatorTree.webidl rename to dom/webidl/DominatorTree.webidl diff --git a/dom/chrome-webidl/HeapSnapshot.webidl b/dom/webidl/HeapSnapshot.webidl similarity index 100% rename from dom/chrome-webidl/HeapSnapshot.webidl rename to dom/webidl/HeapSnapshot.webidl diff --git a/dom/chrome-webidl/InspectorUtils.webidl b/dom/webidl/InspectorUtils.webidl similarity index 100% rename from dom/chrome-webidl/InspectorUtils.webidl rename to dom/webidl/InspectorUtils.webidl diff --git a/dom/chrome-webidl/MatchGlob.webidl b/dom/webidl/MatchGlob.webidl similarity index 100% rename from dom/chrome-webidl/MatchGlob.webidl rename to dom/webidl/MatchGlob.webidl diff --git a/dom/chrome-webidl/MatchPattern.webidl b/dom/webidl/MatchPattern.webidl similarity index 100% rename from dom/chrome-webidl/MatchPattern.webidl rename to dom/webidl/MatchPattern.webidl diff --git a/dom/chrome-webidl/MozStorageAsyncStatementParams.webidl b/dom/webidl/MozStorageAsyncStatementParams.webidl similarity index 100% rename from dom/chrome-webidl/MozStorageAsyncStatementParams.webidl rename to dom/webidl/MozStorageAsyncStatementParams.webidl diff --git a/dom/chrome-webidl/MozStorageStatementParams.webidl b/dom/webidl/MozStorageStatementParams.webidl similarity index 100% rename from dom/chrome-webidl/MozStorageStatementParams.webidl rename to dom/webidl/MozStorageStatementParams.webidl diff --git a/dom/chrome-webidl/MozStorageStatementRow.webidl b/dom/webidl/MozStorageStatementRow.webidl similarity index 100% rename from dom/chrome-webidl/MozStorageStatementRow.webidl rename to dom/webidl/MozStorageStatementRow.webidl diff --git a/dom/chrome-webidl/PrecompiledScript.webidl b/dom/webidl/PrecompiledScript.webidl similarity index 100% rename from dom/chrome-webidl/PrecompiledScript.webidl rename to dom/webidl/PrecompiledScript.webidl diff --git a/dom/chrome-webidl/PromiseDebugging.webidl b/dom/webidl/PromiseDebugging.webidl similarity index 100% rename from dom/chrome-webidl/PromiseDebugging.webidl rename to dom/webidl/PromiseDebugging.webidl diff --git a/dom/chrome-webidl/StructuredCloneHolder.webidl b/dom/webidl/StructuredCloneHolder.webidl similarity index 100% rename from dom/chrome-webidl/StructuredCloneHolder.webidl rename to dom/webidl/StructuredCloneHolder.webidl diff --git a/dom/chrome-webidl/WebExtensionContentScript.webidl b/dom/webidl/WebExtensionContentScript.webidl similarity index 100% rename from dom/chrome-webidl/WebExtensionContentScript.webidl rename to dom/webidl/WebExtensionContentScript.webidl diff --git a/dom/chrome-webidl/WebExtensionPolicy.webidl b/dom/webidl/WebExtensionPolicy.webidl similarity index 100% rename from dom/chrome-webidl/WebExtensionPolicy.webidl rename to dom/webidl/WebExtensionPolicy.webidl diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index afe307c9cd64..8501b4c86e09 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -139,6 +139,9 @@ with Files("HTML*"): with Files("HashChangeEvent.webidl"): BUG_COMPONENT = ("Core", "DOM: Events") +with Files("HeapSnapshot.webidl"): + BUG_COMPONENT = ("Firefox", "Developer Tools: Memory") + with Files("HiddenPluginEvent.webidl"): BUG_COMPONENT = ("Core", "Plug-ins") @@ -160,6 +163,9 @@ with Files("InputEvent.webidl"): with Files("InstallTrigger.webidl"): BUG_COMPONENT = ("Toolkit", "Add-ons Manager") +with Files("InspectorUtils.webidl"): + BUG_COMPONENT = ("Firefox", "Developer Tools: Inspector") + with Files("KeyAlgorithm.webidl"): BUG_COMPONENT = ("Core", "DOM: Security") @@ -354,6 +360,7 @@ GENERATED_WEBIDL_FILES = [ ] PREPROCESSED_WEBIDL_FILES = [ + 'ChromeUtils.webidl', 'Node.webidl', 'Window.webidl', ] @@ -411,6 +418,7 @@ WEBIDL_FILES = [ 'CDATASection.webidl', 'ChannelMergerNode.webidl', 'ChannelSplitterNode.webidl', + 'ChannelWrapper.webidl', 'CharacterData.webidl', 'CheckerboardReportService.webidl', 'ChildNode.webidl', @@ -475,6 +483,7 @@ WEBIDL_FILES = [ 'DOMError.webidl', 'DOMException.webidl', 'DOMImplementation.webidl', + 'DominatorTree.webidl', 'DOMMatrix.webidl', 'DOMParser.webidl', 'DOMPoint.webidl', @@ -527,6 +536,7 @@ WEBIDL_FILES = [ 'GetUserMediaRequest.webidl', 'Grid.webidl', 'Headers.webidl', + 'HeapSnapshot.webidl', 'History.webidl', 'HTMLAllCollection.webidl', 'HTMLAnchorElement.webidl', @@ -625,6 +635,7 @@ WEBIDL_FILES = [ 'ImageData.webidl', 'ImageDocument.webidl', 'InputEvent.webidl', + 'InspectorUtils.webidl', 'IntersectionObserver.webidl', 'IntlUtils.webidl', 'IterableIterator.webidl', @@ -640,6 +651,8 @@ WEBIDL_FILES = [ 'ListBoxObject.webidl', 'LocalMediaStream.webidl', 'Location.webidl', + 'MatchGlob.webidl', + 'MatchPattern.webidl', 'MediaDeviceInfo.webidl', 'MediaDevices.webidl', 'MediaElementAudioSourceNode.webidl', @@ -680,6 +693,9 @@ WEBIDL_FILES = [ 'MimeTypeArray.webidl', 'MouseEvent.webidl', 'MouseScrollEvent.webidl', + 'MozStorageAsyncStatementParams.webidl', + 'MozStorageStatementParams.webidl', + 'MozStorageStatementRow.webidl', 'MutationEvent.webidl', 'MutationObserver.webidl', 'NamedNodeMap.webidl', @@ -726,6 +742,7 @@ WEBIDL_FILES = [ 'PopupBoxObject.webidl', 'Position.webidl', 'PositionError.webidl', + 'PrecompiledScript.webidl', 'Presentation.webidl', 'PresentationAvailability.webidl', 'PresentationConnection.webidl', @@ -735,6 +752,7 @@ WEBIDL_FILES = [ 'ProcessingInstruction.webidl', 'ProfileTimelineMarker.webidl', 'Promise.webidl', + 'PromiseDebugging.webidl', 'PushEvent.webidl', 'PushManager.webidl', 'PushManager.webidl', @@ -772,6 +790,7 @@ WEBIDL_FILES = [ 'StorageType.webidl', 'StreamFilter.webidl', 'StreamFilterDataEvent.webidl', + 'StructuredCloneHolder.webidl', 'StyleSheet.webidl', 'StyleSheetList.webidl', 'SubtleCrypto.webidl', @@ -926,6 +945,8 @@ WEBIDL_FILES = [ 'WaveShaperNode.webidl', 'WebAuthentication.webidl', 'WebComponents.webidl', + 'WebExtensionContentScript.webidl', + 'WebExtensionPolicy.webidl', 'WebGL2RenderingContext.webidl', 'WebGLRenderingContext.webidl', 'WebKitCSSMatrix.webidl', From c8a6abe11df973ad884ddeaeb6460233b69d8be7 Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Mon, 5 Mar 2018 14:21:38 -0800 Subject: [PATCH 17/23] Bug 1442931: Part 1 - Forbid web-visible interfaces outside of WebIDL root. r=mystor Web-visible WebIDL interfaces require DOM peer review with every change, which is enforced by a commit hook. ChromeOnly interfaces are not exposed to the web, and therefore don't require the same strictures. The current commit hook enforces the review requirement for changes to any (non-Servo) WebIDL file, and is not smart enough to determine if the change is web-visible. In order to loosen that restriction, we need the build system to enforce the requirement that only WebIDL files in certain locations may contain web-visible interfaces, so that the commit hook can restrict itself to checking only those directories. This change restricts the location of web-visible WebIDL interfaces to the dom/webidl/ and dom/bindings/ roots (along with the corresponding objdir root for generated interfaces). A follow-up will change the commit hook to only enforce review requirements on these directories. MozReview-Commit-ID: CiDxXxN4oO4 --HG-- extra : source : 6cb20ada1a0aa1f6d621ba3c85ce9946a6f9841f extra : histedit_source : 1f02888264a936db3e77134c0a7203e911707312%2C6ea38c077b8a7dfaf358bc819d150a20db9bd6b7 --- dom/bindings/Configuration.py | 22 +++++++++++++++- dom/bindings/mozwebidlcodegen/__init__.py | 25 +++++++++++++++++-- .../test/test_mozwebidlcodegen.py | 1 + 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/dom/bindings/Configuration.py b/dom/bindings/Configuration.py index 8b57c1e52a3c..52b378b31ee2 100644 --- a/dom/bindings/Configuration.py +++ b/dom/bindings/Configuration.py @@ -18,12 +18,17 @@ class DescriptorProvider: pass +def isChildPath(path, basePath): + path = os.path.normpath(path) + return os.path.commonprefix((path, basePath)) == basePath + + class Configuration(DescriptorProvider): """ Represents global configuration state based on IDL parse data and the configuration file. """ - def __init__(self, filename, parseData, generatedEvents=[]): + def __init__(self, filename, webRoots, parseData, generatedEvents=[]): DescriptorProvider.__init__(self) # Read the configuration file. @@ -31,6 +36,10 @@ class Configuration(DescriptorProvider): execfile(filename, glbl) config = glbl['DOMInterfaces'] + webRoots = tuple(map(os.path.normpath, webRoots)) + def isInWebIDLRoot(path): + return any(isChildPath(path, root) for root in webRoots) + # Build descriptors for all the interfaces we have in the parse data. # This allows callers to specify a subset of interfaces by filtering # |parseData|. @@ -94,6 +103,17 @@ class Configuration(DescriptorProvider): "%s\n" "%s" % (partialIface.location, iface.location)) + if not (iface.getExtendedAttribute("ChromeOnly") or + not (iface.hasInterfaceObject() or + iface.isNavigatorProperty()) or + isInWebIDLRoot(iface.filename())): + raise TypeError( + "Interfaces which are exposed to the web may only be " + "defined in a DOM WebIDL root %r. Consider marking " + "the interface [ChromeOnly] if you do not want it " + "exposed to the web.\n" + "%s" % + (webRoots, iface.location)) self.interfaces[iface.identifier.name] = iface if iface.identifier.name not in config: # Completely skip consequential interfaces with no descriptor diff --git a/dom/bindings/mozwebidlcodegen/__init__.py b/dom/bindings/mozwebidlcodegen/__init__.py index b6e351e52f75..57722a5bd6c9 100644 --- a/dom/bindings/mozwebidlcodegen/__init__.py +++ b/dom/bindings/mozwebidlcodegen/__init__.py @@ -150,7 +150,7 @@ class WebIDLCodegenManager(LoggingMixin): 'PrototypeList.cpp', } - def __init__(self, config_path, inputs, exported_header_dir, + def __init__(self, config_path, webidl_root, inputs, exported_header_dir, codegen_dir, state_path, cache_dir=None, make_deps_path=None, make_deps_target=None): """Create an instance that manages WebIDLs in the build system. @@ -176,6 +176,7 @@ class WebIDLCodegenManager(LoggingMixin): input_paths, exported_stems, generated_events_stems, example_interfaces = inputs self._config_path = config_path + self._webidl_root = webidl_root self._input_paths = set(input_paths) self._exported_stems = set(exported_stems) self._generated_events_stems = set(generated_events_stems) @@ -332,8 +333,26 @@ class WebIDLCodegenManager(LoggingMixin): hashes[path] = hashlib.sha1(data).hexdigest() parser.parse(data, path) + # Only these directories may contain WebIDL files with interfaces + # which are exposed to the web. WebIDL files in these roots may not + # be changed without DOM peer review. + # + # Other directories may contain WebIDL files as long as they only + # contain ChromeOnly interfaces. These are not subject to mandatory + # DOM peer review. + web_roots = ( + # The main WebIDL root. + self._webidl_root, + # The binding config root, which contains some test-only + # interfaces. + os.path.dirname(self._config_path), + # The objdir sub-directory which contains generated WebIDL files. + self._codegen_dir, + ) + self._parser_results = parser.finish() - self._config = Configuration(self._config_path, self._parser_results, + self._config = Configuration(self._config_path, web_roots, + self._parser_results, self._generated_events_stems_as_array) self._input_hashes = hashes @@ -546,6 +565,7 @@ def create_build_system_manager(topsrcdir, topobjdir, dist_dir): """Create a WebIDLCodegenManager for use by the build system.""" src_dir = os.path.join(topsrcdir, 'dom', 'bindings') obj_dir = os.path.join(topobjdir, 'dom', 'bindings') + webidl_root = os.path.join(topsrcdir, 'dom', 'webidl') with open(os.path.join(obj_dir, 'file-lists.json'), 'rb') as fh: files = json.load(fh) @@ -562,6 +582,7 @@ def create_build_system_manager(topsrcdir, topobjdir, dist_dir): return WebIDLCodegenManager( os.path.join(src_dir, 'Bindings.conf'), + webidl_root, inputs, os.path.join(dist_dir, 'include', 'mozilla', 'dom'), obj_dir, diff --git a/dom/bindings/mozwebidlcodegen/test/test_mozwebidlcodegen.py b/dom/bindings/mozwebidlcodegen/test/test_mozwebidlcodegen.py index ce3315e887ed..03b43e35d152 100644 --- a/dom/bindings/mozwebidlcodegen/test/test_mozwebidlcodegen.py +++ b/dom/bindings/mozwebidlcodegen/test/test_mozwebidlcodegen.py @@ -71,6 +71,7 @@ class TestWebIDLCodegenManager(unittest.TestCase): return dict( config_path=self._config_path, + webidl_root='/', inputs=inputs, exported_header_dir=mozpath.join(tmp, 'exports'), codegen_dir=mozpath.join(tmp, 'codegen'), From d9ca1fc1122cbf13d54062dcca68c6e7c2c2bb1d Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Sun, 4 Mar 2018 16:37:10 -0800 Subject: [PATCH 18/23] Bug 1442931: Part 2 - Move internal WebIDL interfaces to separate directory. r=mystor This change moves several chrome-only WebIDL files to a separate chrome-only directory. There are several other chrome-only interfaces which are heavily tied to DOM code. Since those should probably still require DOM peer review for changes, I left them where they were. MozReview-Commit-ID: K3NsNtfntV6 --HG-- rename : dom/webidl/ChannelWrapper.webidl => dom/chrome-webidl/ChannelWrapper.webidl rename : dom/webidl/ChromeUtils.webidl => dom/chrome-webidl/ChromeUtils.webidl rename : dom/webidl/DominatorTree.webidl => dom/chrome-webidl/DominatorTree.webidl rename : dom/webidl/HeapSnapshot.webidl => dom/chrome-webidl/HeapSnapshot.webidl rename : dom/webidl/InspectorUtils.webidl => dom/chrome-webidl/InspectorUtils.webidl rename : dom/webidl/MatchGlob.webidl => dom/chrome-webidl/MatchGlob.webidl rename : dom/webidl/MatchPattern.webidl => dom/chrome-webidl/MatchPattern.webidl rename : dom/webidl/MozStorageAsyncStatementParams.webidl => dom/chrome-webidl/MozStorageAsyncStatementParams.webidl rename : dom/webidl/MozStorageStatementParams.webidl => dom/chrome-webidl/MozStorageStatementParams.webidl rename : dom/webidl/MozStorageStatementRow.webidl => dom/chrome-webidl/MozStorageStatementRow.webidl rename : dom/webidl/PrecompiledScript.webidl => dom/chrome-webidl/PrecompiledScript.webidl rename : dom/webidl/PromiseDebugging.webidl => dom/chrome-webidl/PromiseDebugging.webidl rename : dom/webidl/StructuredCloneHolder.webidl => dom/chrome-webidl/StructuredCloneHolder.webidl rename : dom/webidl/WebExtensionContentScript.webidl => dom/chrome-webidl/WebExtensionContentScript.webidl rename : dom/webidl/WebExtensionPolicy.webidl => dom/chrome-webidl/WebExtensionPolicy.webidl rename : dom/webidl/moz.build => dom/chrome-webidl/moz.build extra : source : 195cbf3d34334978e5a9d101d4b79f899598159c extra : amend_source : 9ef85f3436706de0049f6c5619407ef4bba4d539 extra : histedit_source : aa0ba8a35662566ad77ad3bb6adbd8cb062f0498 --- .../ChannelWrapper.webidl | 0 .../ChromeUtils.webidl | 0 .../DominatorTree.webidl | 0 .../HeapSnapshot.webidl | 0 .../InspectorUtils.webidl | 0 .../MatchGlob.webidl | 0 .../MatchPattern.webidl | 0 .../MozStorageAsyncStatementParams.webidl | 0 .../MozStorageStatementParams.webidl | 0 .../MozStorageStatementRow.webidl | 0 .../PrecompiledScript.webidl | 0 .../PromiseDebugging.webidl | 0 .../StructuredCloneHolder.webidl | 0 .../WebExtensionContentScript.webidl | 0 .../WebExtensionPolicy.webidl | 0 dom/chrome-webidl/moz.build | 47 +++++++++++++++++++ dom/moz.build | 1 + dom/webidl/moz.build | 21 --------- 18 files changed, 48 insertions(+), 21 deletions(-) rename dom/{webidl => chrome-webidl}/ChannelWrapper.webidl (100%) rename dom/{webidl => chrome-webidl}/ChromeUtils.webidl (100%) rename dom/{webidl => chrome-webidl}/DominatorTree.webidl (100%) rename dom/{webidl => chrome-webidl}/HeapSnapshot.webidl (100%) rename dom/{webidl => chrome-webidl}/InspectorUtils.webidl (100%) rename dom/{webidl => chrome-webidl}/MatchGlob.webidl (100%) rename dom/{webidl => chrome-webidl}/MatchPattern.webidl (100%) rename dom/{webidl => chrome-webidl}/MozStorageAsyncStatementParams.webidl (100%) rename dom/{webidl => chrome-webidl}/MozStorageStatementParams.webidl (100%) rename dom/{webidl => chrome-webidl}/MozStorageStatementRow.webidl (100%) rename dom/{webidl => chrome-webidl}/PrecompiledScript.webidl (100%) rename dom/{webidl => chrome-webidl}/PromiseDebugging.webidl (100%) rename dom/{webidl => chrome-webidl}/StructuredCloneHolder.webidl (100%) rename dom/{webidl => chrome-webidl}/WebExtensionContentScript.webidl (100%) rename dom/{webidl => chrome-webidl}/WebExtensionPolicy.webidl (100%) create mode 100644 dom/chrome-webidl/moz.build diff --git a/dom/webidl/ChannelWrapper.webidl b/dom/chrome-webidl/ChannelWrapper.webidl similarity index 100% rename from dom/webidl/ChannelWrapper.webidl rename to dom/chrome-webidl/ChannelWrapper.webidl diff --git a/dom/webidl/ChromeUtils.webidl b/dom/chrome-webidl/ChromeUtils.webidl similarity index 100% rename from dom/webidl/ChromeUtils.webidl rename to dom/chrome-webidl/ChromeUtils.webidl diff --git a/dom/webidl/DominatorTree.webidl b/dom/chrome-webidl/DominatorTree.webidl similarity index 100% rename from dom/webidl/DominatorTree.webidl rename to dom/chrome-webidl/DominatorTree.webidl diff --git a/dom/webidl/HeapSnapshot.webidl b/dom/chrome-webidl/HeapSnapshot.webidl similarity index 100% rename from dom/webidl/HeapSnapshot.webidl rename to dom/chrome-webidl/HeapSnapshot.webidl diff --git a/dom/webidl/InspectorUtils.webidl b/dom/chrome-webidl/InspectorUtils.webidl similarity index 100% rename from dom/webidl/InspectorUtils.webidl rename to dom/chrome-webidl/InspectorUtils.webidl diff --git a/dom/webidl/MatchGlob.webidl b/dom/chrome-webidl/MatchGlob.webidl similarity index 100% rename from dom/webidl/MatchGlob.webidl rename to dom/chrome-webidl/MatchGlob.webidl diff --git a/dom/webidl/MatchPattern.webidl b/dom/chrome-webidl/MatchPattern.webidl similarity index 100% rename from dom/webidl/MatchPattern.webidl rename to dom/chrome-webidl/MatchPattern.webidl diff --git a/dom/webidl/MozStorageAsyncStatementParams.webidl b/dom/chrome-webidl/MozStorageAsyncStatementParams.webidl similarity index 100% rename from dom/webidl/MozStorageAsyncStatementParams.webidl rename to dom/chrome-webidl/MozStorageAsyncStatementParams.webidl diff --git a/dom/webidl/MozStorageStatementParams.webidl b/dom/chrome-webidl/MozStorageStatementParams.webidl similarity index 100% rename from dom/webidl/MozStorageStatementParams.webidl rename to dom/chrome-webidl/MozStorageStatementParams.webidl diff --git a/dom/webidl/MozStorageStatementRow.webidl b/dom/chrome-webidl/MozStorageStatementRow.webidl similarity index 100% rename from dom/webidl/MozStorageStatementRow.webidl rename to dom/chrome-webidl/MozStorageStatementRow.webidl diff --git a/dom/webidl/PrecompiledScript.webidl b/dom/chrome-webidl/PrecompiledScript.webidl similarity index 100% rename from dom/webidl/PrecompiledScript.webidl rename to dom/chrome-webidl/PrecompiledScript.webidl diff --git a/dom/webidl/PromiseDebugging.webidl b/dom/chrome-webidl/PromiseDebugging.webidl similarity index 100% rename from dom/webidl/PromiseDebugging.webidl rename to dom/chrome-webidl/PromiseDebugging.webidl diff --git a/dom/webidl/StructuredCloneHolder.webidl b/dom/chrome-webidl/StructuredCloneHolder.webidl similarity index 100% rename from dom/webidl/StructuredCloneHolder.webidl rename to dom/chrome-webidl/StructuredCloneHolder.webidl diff --git a/dom/webidl/WebExtensionContentScript.webidl b/dom/chrome-webidl/WebExtensionContentScript.webidl similarity index 100% rename from dom/webidl/WebExtensionContentScript.webidl rename to dom/chrome-webidl/WebExtensionContentScript.webidl diff --git a/dom/webidl/WebExtensionPolicy.webidl b/dom/chrome-webidl/WebExtensionPolicy.webidl similarity index 100% rename from dom/webidl/WebExtensionPolicy.webidl rename to dom/chrome-webidl/WebExtensionPolicy.webidl diff --git a/dom/chrome-webidl/moz.build b/dom/chrome-webidl/moz.build new file mode 100644 index 000000000000..71168e3846d9 --- /dev/null +++ b/dom/chrome-webidl/moz.build @@ -0,0 +1,47 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# 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/. + +with Files("**"): + BUG_COMPONENT = ("Core", "DOM") + +with Files("ChannelWrapper.webidl"): + BUG_COMPONENT = ("Toolkit", "WebExtensions: Request Handling") + +with Files("HeapSnapshot.webidl"): + BUG_COMPONENT = ("Firefox", "Developer Tools: Memory") + +with Files("InspectorUtils.webidl"): + BUG_COMPONENT = ("Firefox", "Developer Tools: Inspector") + +with Files("MatchGlob.webidl"): + BUG_COMPONENT = ("Toolkit", "WebExtensions: General") + +with Files("MatchPattern.webidl"): + BUG_COMPONENT = ("Toolkit", "WebExtensions: General") + +with Files("WebExtension*.webidl"): + BUG_COMPONENT = ("Toolkit", "WebExtensions: General") + +PREPROCESSED_WEBIDL_FILES = [ + 'ChromeUtils.webidl', +] + +WEBIDL_FILES = [ + 'ChannelWrapper.webidl', + 'DominatorTree.webidl', + 'HeapSnapshot.webidl', + 'InspectorUtils.webidl', + 'MatchGlob.webidl', + 'MatchPattern.webidl', + 'MozStorageAsyncStatementParams.webidl', + 'MozStorageStatementParams.webidl', + 'MozStorageStatementRow.webidl', + 'PrecompiledScript.webidl', + 'PromiseDebugging.webidl', + 'StructuredCloneHolder.webidl', + 'WebExtensionContentScript.webidl', + 'WebExtensionPolicy.webidl', +] diff --git a/dom/moz.build b/dom/moz.build index 0adab75f5e1a..17ad358df944 100644 --- a/dom/moz.build +++ b/dom/moz.build @@ -41,6 +41,7 @@ DIRS += [ 'browser-element', 'cache', 'canvas', + 'chrome-webidl', 'clients', 'commandhandler', 'credentialmanagement', diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index 8501b4c86e09..afe307c9cd64 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -139,9 +139,6 @@ with Files("HTML*"): with Files("HashChangeEvent.webidl"): BUG_COMPONENT = ("Core", "DOM: Events") -with Files("HeapSnapshot.webidl"): - BUG_COMPONENT = ("Firefox", "Developer Tools: Memory") - with Files("HiddenPluginEvent.webidl"): BUG_COMPONENT = ("Core", "Plug-ins") @@ -163,9 +160,6 @@ with Files("InputEvent.webidl"): with Files("InstallTrigger.webidl"): BUG_COMPONENT = ("Toolkit", "Add-ons Manager") -with Files("InspectorUtils.webidl"): - BUG_COMPONENT = ("Firefox", "Developer Tools: Inspector") - with Files("KeyAlgorithm.webidl"): BUG_COMPONENT = ("Core", "DOM: Security") @@ -360,7 +354,6 @@ GENERATED_WEBIDL_FILES = [ ] PREPROCESSED_WEBIDL_FILES = [ - 'ChromeUtils.webidl', 'Node.webidl', 'Window.webidl', ] @@ -418,7 +411,6 @@ WEBIDL_FILES = [ 'CDATASection.webidl', 'ChannelMergerNode.webidl', 'ChannelSplitterNode.webidl', - 'ChannelWrapper.webidl', 'CharacterData.webidl', 'CheckerboardReportService.webidl', 'ChildNode.webidl', @@ -483,7 +475,6 @@ WEBIDL_FILES = [ 'DOMError.webidl', 'DOMException.webidl', 'DOMImplementation.webidl', - 'DominatorTree.webidl', 'DOMMatrix.webidl', 'DOMParser.webidl', 'DOMPoint.webidl', @@ -536,7 +527,6 @@ WEBIDL_FILES = [ 'GetUserMediaRequest.webidl', 'Grid.webidl', 'Headers.webidl', - 'HeapSnapshot.webidl', 'History.webidl', 'HTMLAllCollection.webidl', 'HTMLAnchorElement.webidl', @@ -635,7 +625,6 @@ WEBIDL_FILES = [ 'ImageData.webidl', 'ImageDocument.webidl', 'InputEvent.webidl', - 'InspectorUtils.webidl', 'IntersectionObserver.webidl', 'IntlUtils.webidl', 'IterableIterator.webidl', @@ -651,8 +640,6 @@ WEBIDL_FILES = [ 'ListBoxObject.webidl', 'LocalMediaStream.webidl', 'Location.webidl', - 'MatchGlob.webidl', - 'MatchPattern.webidl', 'MediaDeviceInfo.webidl', 'MediaDevices.webidl', 'MediaElementAudioSourceNode.webidl', @@ -693,9 +680,6 @@ WEBIDL_FILES = [ 'MimeTypeArray.webidl', 'MouseEvent.webidl', 'MouseScrollEvent.webidl', - 'MozStorageAsyncStatementParams.webidl', - 'MozStorageStatementParams.webidl', - 'MozStorageStatementRow.webidl', 'MutationEvent.webidl', 'MutationObserver.webidl', 'NamedNodeMap.webidl', @@ -742,7 +726,6 @@ WEBIDL_FILES = [ 'PopupBoxObject.webidl', 'Position.webidl', 'PositionError.webidl', - 'PrecompiledScript.webidl', 'Presentation.webidl', 'PresentationAvailability.webidl', 'PresentationConnection.webidl', @@ -752,7 +735,6 @@ WEBIDL_FILES = [ 'ProcessingInstruction.webidl', 'ProfileTimelineMarker.webidl', 'Promise.webidl', - 'PromiseDebugging.webidl', 'PushEvent.webidl', 'PushManager.webidl', 'PushManager.webidl', @@ -790,7 +772,6 @@ WEBIDL_FILES = [ 'StorageType.webidl', 'StreamFilter.webidl', 'StreamFilterDataEvent.webidl', - 'StructuredCloneHolder.webidl', 'StyleSheet.webidl', 'StyleSheetList.webidl', 'SubtleCrypto.webidl', @@ -945,8 +926,6 @@ WEBIDL_FILES = [ 'WaveShaperNode.webidl', 'WebAuthentication.webidl', 'WebComponents.webidl', - 'WebExtensionContentScript.webidl', - 'WebExtensionPolicy.webidl', 'WebGL2RenderingContext.webidl', 'WebGLRenderingContext.webidl', 'WebKitCSSMatrix.webidl', From 5f62077516bfc1a84b26e63cb9acbfac21e92c92 Mon Sep 17 00:00:00 2001 From: Philipp Kewisch Date: Wed, 7 Mar 2018 01:24:07 +0100 Subject: [PATCH 19/23] Bug 1443682 - Hide the use of OptionalExtensions behind an ifdef. r=mhowell MozReview-Commit-ID: 8jBeNuMlaYj --HG-- extra : transplant_source : Eb%C74%0D%AC%DDpb%EBK%83%8F9W%B7%80%87%97%E0 --- toolkit/mozapps/installer/windows/nsis/common.nsh | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/toolkit/mozapps/installer/windows/nsis/common.nsh b/toolkit/mozapps/installer/windows/nsis/common.nsh index f4ac5d7b1da7..f319907bb8bd 100755 --- a/toolkit/mozapps/installer/windows/nsis/common.nsh +++ b/toolkit/mozapps/installer/windows/nsis/common.nsh @@ -5099,12 +5099,14 @@ ${ElevateUAC} ${EndIf} - ReadINIStr $R8 $R7 "Install" "OptionalExtensions" - ${If} $R8 == "false" - StrCpy $InstallOptionalExtensions "0" - ${Else} - StrCpy $InstallOptionalExtensions "1" - ${EndIf} + !ifdef MOZ_OPTIONAL_EXTENSIONS + ReadINIStr $R8 $R7 "Install" "OptionalExtensions" + ${If} $R8 == "false" + StrCpy $InstallOptionalExtensions "0" + ${Else} + StrCpy $InstallOptionalExtensions "1" + ${EndIf} + !endif !ifndef NO_STARTMENU_DIR ReadINIStr $R8 $R7 "Install" "StartMenuDirectoryName" From 01d4e4cfa4ec1a3bfc491c455bf12b1f0f4b67cc Mon Sep 17 00:00:00 2001 From: Andreea Pavel Date: Wed, 7 Mar 2018 08:53:06 +0200 Subject: [PATCH 20/23] Backed out 2 changesets (bug 1442931) for build bustages at ..\dom\bindings\mozwebidlcodegen\test\test_mozwebidlcodegen.py::TestWebIDLCodegenManager::test_copy_input on a CLOSED TREE Backed out changeset 9f46e7d52b9b (bug 1442931) Backed out changeset 608e21fcd167 (bug 1442931) --HG-- rename : dom/chrome-webidl/ChannelWrapper.webidl => dom/webidl/ChannelWrapper.webidl rename : dom/chrome-webidl/ChromeUtils.webidl => dom/webidl/ChromeUtils.webidl rename : dom/chrome-webidl/DominatorTree.webidl => dom/webidl/DominatorTree.webidl rename : dom/chrome-webidl/HeapSnapshot.webidl => dom/webidl/HeapSnapshot.webidl rename : dom/chrome-webidl/InspectorUtils.webidl => dom/webidl/InspectorUtils.webidl rename : dom/chrome-webidl/MatchGlob.webidl => dom/webidl/MatchGlob.webidl rename : dom/chrome-webidl/MatchPattern.webidl => dom/webidl/MatchPattern.webidl rename : dom/chrome-webidl/MozStorageAsyncStatementParams.webidl => dom/webidl/MozStorageAsyncStatementParams.webidl rename : dom/chrome-webidl/MozStorageStatementParams.webidl => dom/webidl/MozStorageStatementParams.webidl rename : dom/chrome-webidl/MozStorageStatementRow.webidl => dom/webidl/MozStorageStatementRow.webidl rename : dom/chrome-webidl/PrecompiledScript.webidl => dom/webidl/PrecompiledScript.webidl rename : dom/chrome-webidl/PromiseDebugging.webidl => dom/webidl/PromiseDebugging.webidl rename : dom/chrome-webidl/StructuredCloneHolder.webidl => dom/webidl/StructuredCloneHolder.webidl rename : dom/chrome-webidl/WebExtensionContentScript.webidl => dom/webidl/WebExtensionContentScript.webidl rename : dom/chrome-webidl/WebExtensionPolicy.webidl => dom/webidl/WebExtensionPolicy.webidl --- dom/bindings/Configuration.py | 22 +-------- dom/bindings/mozwebidlcodegen/__init__.py | 25 +--------- .../test/test_mozwebidlcodegen.py | 1 - dom/chrome-webidl/moz.build | 47 ------------------- dom/moz.build | 1 - .../ChannelWrapper.webidl | 0 .../ChromeUtils.webidl | 0 .../DominatorTree.webidl | 0 .../HeapSnapshot.webidl | 0 .../InspectorUtils.webidl | 0 .../MatchGlob.webidl | 0 .../MatchPattern.webidl | 0 .../MozStorageAsyncStatementParams.webidl | 0 .../MozStorageStatementParams.webidl | 0 .../MozStorageStatementRow.webidl | 0 .../PrecompiledScript.webidl | 0 .../PromiseDebugging.webidl | 0 .../StructuredCloneHolder.webidl | 0 .../WebExtensionContentScript.webidl | 0 .../WebExtensionPolicy.webidl | 0 dom/webidl/moz.build | 21 +++++++++ 21 files changed, 24 insertions(+), 93 deletions(-) delete mode 100644 dom/chrome-webidl/moz.build rename dom/{chrome-webidl => webidl}/ChannelWrapper.webidl (100%) rename dom/{chrome-webidl => webidl}/ChromeUtils.webidl (100%) rename dom/{chrome-webidl => webidl}/DominatorTree.webidl (100%) rename dom/{chrome-webidl => webidl}/HeapSnapshot.webidl (100%) rename dom/{chrome-webidl => webidl}/InspectorUtils.webidl (100%) rename dom/{chrome-webidl => webidl}/MatchGlob.webidl (100%) rename dom/{chrome-webidl => webidl}/MatchPattern.webidl (100%) rename dom/{chrome-webidl => webidl}/MozStorageAsyncStatementParams.webidl (100%) rename dom/{chrome-webidl => webidl}/MozStorageStatementParams.webidl (100%) rename dom/{chrome-webidl => webidl}/MozStorageStatementRow.webidl (100%) rename dom/{chrome-webidl => webidl}/PrecompiledScript.webidl (100%) rename dom/{chrome-webidl => webidl}/PromiseDebugging.webidl (100%) rename dom/{chrome-webidl => webidl}/StructuredCloneHolder.webidl (100%) rename dom/{chrome-webidl => webidl}/WebExtensionContentScript.webidl (100%) rename dom/{chrome-webidl => webidl}/WebExtensionPolicy.webidl (100%) diff --git a/dom/bindings/Configuration.py b/dom/bindings/Configuration.py index 52b378b31ee2..8b57c1e52a3c 100644 --- a/dom/bindings/Configuration.py +++ b/dom/bindings/Configuration.py @@ -18,17 +18,12 @@ class DescriptorProvider: pass -def isChildPath(path, basePath): - path = os.path.normpath(path) - return os.path.commonprefix((path, basePath)) == basePath - - class Configuration(DescriptorProvider): """ Represents global configuration state based on IDL parse data and the configuration file. """ - def __init__(self, filename, webRoots, parseData, generatedEvents=[]): + def __init__(self, filename, parseData, generatedEvents=[]): DescriptorProvider.__init__(self) # Read the configuration file. @@ -36,10 +31,6 @@ class Configuration(DescriptorProvider): execfile(filename, glbl) config = glbl['DOMInterfaces'] - webRoots = tuple(map(os.path.normpath, webRoots)) - def isInWebIDLRoot(path): - return any(isChildPath(path, root) for root in webRoots) - # Build descriptors for all the interfaces we have in the parse data. # This allows callers to specify a subset of interfaces by filtering # |parseData|. @@ -103,17 +94,6 @@ class Configuration(DescriptorProvider): "%s\n" "%s" % (partialIface.location, iface.location)) - if not (iface.getExtendedAttribute("ChromeOnly") or - not (iface.hasInterfaceObject() or - iface.isNavigatorProperty()) or - isInWebIDLRoot(iface.filename())): - raise TypeError( - "Interfaces which are exposed to the web may only be " - "defined in a DOM WebIDL root %r. Consider marking " - "the interface [ChromeOnly] if you do not want it " - "exposed to the web.\n" - "%s" % - (webRoots, iface.location)) self.interfaces[iface.identifier.name] = iface if iface.identifier.name not in config: # Completely skip consequential interfaces with no descriptor diff --git a/dom/bindings/mozwebidlcodegen/__init__.py b/dom/bindings/mozwebidlcodegen/__init__.py index 57722a5bd6c9..b6e351e52f75 100644 --- a/dom/bindings/mozwebidlcodegen/__init__.py +++ b/dom/bindings/mozwebidlcodegen/__init__.py @@ -150,7 +150,7 @@ class WebIDLCodegenManager(LoggingMixin): 'PrototypeList.cpp', } - def __init__(self, config_path, webidl_root, inputs, exported_header_dir, + def __init__(self, config_path, inputs, exported_header_dir, codegen_dir, state_path, cache_dir=None, make_deps_path=None, make_deps_target=None): """Create an instance that manages WebIDLs in the build system. @@ -176,7 +176,6 @@ class WebIDLCodegenManager(LoggingMixin): input_paths, exported_stems, generated_events_stems, example_interfaces = inputs self._config_path = config_path - self._webidl_root = webidl_root self._input_paths = set(input_paths) self._exported_stems = set(exported_stems) self._generated_events_stems = set(generated_events_stems) @@ -333,26 +332,8 @@ class WebIDLCodegenManager(LoggingMixin): hashes[path] = hashlib.sha1(data).hexdigest() parser.parse(data, path) - # Only these directories may contain WebIDL files with interfaces - # which are exposed to the web. WebIDL files in these roots may not - # be changed without DOM peer review. - # - # Other directories may contain WebIDL files as long as they only - # contain ChromeOnly interfaces. These are not subject to mandatory - # DOM peer review. - web_roots = ( - # The main WebIDL root. - self._webidl_root, - # The binding config root, which contains some test-only - # interfaces. - os.path.dirname(self._config_path), - # The objdir sub-directory which contains generated WebIDL files. - self._codegen_dir, - ) - self._parser_results = parser.finish() - self._config = Configuration(self._config_path, web_roots, - self._parser_results, + self._config = Configuration(self._config_path, self._parser_results, self._generated_events_stems_as_array) self._input_hashes = hashes @@ -565,7 +546,6 @@ def create_build_system_manager(topsrcdir, topobjdir, dist_dir): """Create a WebIDLCodegenManager for use by the build system.""" src_dir = os.path.join(topsrcdir, 'dom', 'bindings') obj_dir = os.path.join(topobjdir, 'dom', 'bindings') - webidl_root = os.path.join(topsrcdir, 'dom', 'webidl') with open(os.path.join(obj_dir, 'file-lists.json'), 'rb') as fh: files = json.load(fh) @@ -582,7 +562,6 @@ def create_build_system_manager(topsrcdir, topobjdir, dist_dir): return WebIDLCodegenManager( os.path.join(src_dir, 'Bindings.conf'), - webidl_root, inputs, os.path.join(dist_dir, 'include', 'mozilla', 'dom'), obj_dir, diff --git a/dom/bindings/mozwebidlcodegen/test/test_mozwebidlcodegen.py b/dom/bindings/mozwebidlcodegen/test/test_mozwebidlcodegen.py index 03b43e35d152..ce3315e887ed 100644 --- a/dom/bindings/mozwebidlcodegen/test/test_mozwebidlcodegen.py +++ b/dom/bindings/mozwebidlcodegen/test/test_mozwebidlcodegen.py @@ -71,7 +71,6 @@ class TestWebIDLCodegenManager(unittest.TestCase): return dict( config_path=self._config_path, - webidl_root='/', inputs=inputs, exported_header_dir=mozpath.join(tmp, 'exports'), codegen_dir=mozpath.join(tmp, 'codegen'), diff --git a/dom/chrome-webidl/moz.build b/dom/chrome-webidl/moz.build deleted file mode 100644 index 71168e3846d9..000000000000 --- a/dom/chrome-webidl/moz.build +++ /dev/null @@ -1,47 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -with Files("**"): - BUG_COMPONENT = ("Core", "DOM") - -with Files("ChannelWrapper.webidl"): - BUG_COMPONENT = ("Toolkit", "WebExtensions: Request Handling") - -with Files("HeapSnapshot.webidl"): - BUG_COMPONENT = ("Firefox", "Developer Tools: Memory") - -with Files("InspectorUtils.webidl"): - BUG_COMPONENT = ("Firefox", "Developer Tools: Inspector") - -with Files("MatchGlob.webidl"): - BUG_COMPONENT = ("Toolkit", "WebExtensions: General") - -with Files("MatchPattern.webidl"): - BUG_COMPONENT = ("Toolkit", "WebExtensions: General") - -with Files("WebExtension*.webidl"): - BUG_COMPONENT = ("Toolkit", "WebExtensions: General") - -PREPROCESSED_WEBIDL_FILES = [ - 'ChromeUtils.webidl', -] - -WEBIDL_FILES = [ - 'ChannelWrapper.webidl', - 'DominatorTree.webidl', - 'HeapSnapshot.webidl', - 'InspectorUtils.webidl', - 'MatchGlob.webidl', - 'MatchPattern.webidl', - 'MozStorageAsyncStatementParams.webidl', - 'MozStorageStatementParams.webidl', - 'MozStorageStatementRow.webidl', - 'PrecompiledScript.webidl', - 'PromiseDebugging.webidl', - 'StructuredCloneHolder.webidl', - 'WebExtensionContentScript.webidl', - 'WebExtensionPolicy.webidl', -] diff --git a/dom/moz.build b/dom/moz.build index 17ad358df944..0adab75f5e1a 100644 --- a/dom/moz.build +++ b/dom/moz.build @@ -41,7 +41,6 @@ DIRS += [ 'browser-element', 'cache', 'canvas', - 'chrome-webidl', 'clients', 'commandhandler', 'credentialmanagement', diff --git a/dom/chrome-webidl/ChannelWrapper.webidl b/dom/webidl/ChannelWrapper.webidl similarity index 100% rename from dom/chrome-webidl/ChannelWrapper.webidl rename to dom/webidl/ChannelWrapper.webidl diff --git a/dom/chrome-webidl/ChromeUtils.webidl b/dom/webidl/ChromeUtils.webidl similarity index 100% rename from dom/chrome-webidl/ChromeUtils.webidl rename to dom/webidl/ChromeUtils.webidl diff --git a/dom/chrome-webidl/DominatorTree.webidl b/dom/webidl/DominatorTree.webidl similarity index 100% rename from dom/chrome-webidl/DominatorTree.webidl rename to dom/webidl/DominatorTree.webidl diff --git a/dom/chrome-webidl/HeapSnapshot.webidl b/dom/webidl/HeapSnapshot.webidl similarity index 100% rename from dom/chrome-webidl/HeapSnapshot.webidl rename to dom/webidl/HeapSnapshot.webidl diff --git a/dom/chrome-webidl/InspectorUtils.webidl b/dom/webidl/InspectorUtils.webidl similarity index 100% rename from dom/chrome-webidl/InspectorUtils.webidl rename to dom/webidl/InspectorUtils.webidl diff --git a/dom/chrome-webidl/MatchGlob.webidl b/dom/webidl/MatchGlob.webidl similarity index 100% rename from dom/chrome-webidl/MatchGlob.webidl rename to dom/webidl/MatchGlob.webidl diff --git a/dom/chrome-webidl/MatchPattern.webidl b/dom/webidl/MatchPattern.webidl similarity index 100% rename from dom/chrome-webidl/MatchPattern.webidl rename to dom/webidl/MatchPattern.webidl diff --git a/dom/chrome-webidl/MozStorageAsyncStatementParams.webidl b/dom/webidl/MozStorageAsyncStatementParams.webidl similarity index 100% rename from dom/chrome-webidl/MozStorageAsyncStatementParams.webidl rename to dom/webidl/MozStorageAsyncStatementParams.webidl diff --git a/dom/chrome-webidl/MozStorageStatementParams.webidl b/dom/webidl/MozStorageStatementParams.webidl similarity index 100% rename from dom/chrome-webidl/MozStorageStatementParams.webidl rename to dom/webidl/MozStorageStatementParams.webidl diff --git a/dom/chrome-webidl/MozStorageStatementRow.webidl b/dom/webidl/MozStorageStatementRow.webidl similarity index 100% rename from dom/chrome-webidl/MozStorageStatementRow.webidl rename to dom/webidl/MozStorageStatementRow.webidl diff --git a/dom/chrome-webidl/PrecompiledScript.webidl b/dom/webidl/PrecompiledScript.webidl similarity index 100% rename from dom/chrome-webidl/PrecompiledScript.webidl rename to dom/webidl/PrecompiledScript.webidl diff --git a/dom/chrome-webidl/PromiseDebugging.webidl b/dom/webidl/PromiseDebugging.webidl similarity index 100% rename from dom/chrome-webidl/PromiseDebugging.webidl rename to dom/webidl/PromiseDebugging.webidl diff --git a/dom/chrome-webidl/StructuredCloneHolder.webidl b/dom/webidl/StructuredCloneHolder.webidl similarity index 100% rename from dom/chrome-webidl/StructuredCloneHolder.webidl rename to dom/webidl/StructuredCloneHolder.webidl diff --git a/dom/chrome-webidl/WebExtensionContentScript.webidl b/dom/webidl/WebExtensionContentScript.webidl similarity index 100% rename from dom/chrome-webidl/WebExtensionContentScript.webidl rename to dom/webidl/WebExtensionContentScript.webidl diff --git a/dom/chrome-webidl/WebExtensionPolicy.webidl b/dom/webidl/WebExtensionPolicy.webidl similarity index 100% rename from dom/chrome-webidl/WebExtensionPolicy.webidl rename to dom/webidl/WebExtensionPolicy.webidl diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index afe307c9cd64..8501b4c86e09 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -139,6 +139,9 @@ with Files("HTML*"): with Files("HashChangeEvent.webidl"): BUG_COMPONENT = ("Core", "DOM: Events") +with Files("HeapSnapshot.webidl"): + BUG_COMPONENT = ("Firefox", "Developer Tools: Memory") + with Files("HiddenPluginEvent.webidl"): BUG_COMPONENT = ("Core", "Plug-ins") @@ -160,6 +163,9 @@ with Files("InputEvent.webidl"): with Files("InstallTrigger.webidl"): BUG_COMPONENT = ("Toolkit", "Add-ons Manager") +with Files("InspectorUtils.webidl"): + BUG_COMPONENT = ("Firefox", "Developer Tools: Inspector") + with Files("KeyAlgorithm.webidl"): BUG_COMPONENT = ("Core", "DOM: Security") @@ -354,6 +360,7 @@ GENERATED_WEBIDL_FILES = [ ] PREPROCESSED_WEBIDL_FILES = [ + 'ChromeUtils.webidl', 'Node.webidl', 'Window.webidl', ] @@ -411,6 +418,7 @@ WEBIDL_FILES = [ 'CDATASection.webidl', 'ChannelMergerNode.webidl', 'ChannelSplitterNode.webidl', + 'ChannelWrapper.webidl', 'CharacterData.webidl', 'CheckerboardReportService.webidl', 'ChildNode.webidl', @@ -475,6 +483,7 @@ WEBIDL_FILES = [ 'DOMError.webidl', 'DOMException.webidl', 'DOMImplementation.webidl', + 'DominatorTree.webidl', 'DOMMatrix.webidl', 'DOMParser.webidl', 'DOMPoint.webidl', @@ -527,6 +536,7 @@ WEBIDL_FILES = [ 'GetUserMediaRequest.webidl', 'Grid.webidl', 'Headers.webidl', + 'HeapSnapshot.webidl', 'History.webidl', 'HTMLAllCollection.webidl', 'HTMLAnchorElement.webidl', @@ -625,6 +635,7 @@ WEBIDL_FILES = [ 'ImageData.webidl', 'ImageDocument.webidl', 'InputEvent.webidl', + 'InspectorUtils.webidl', 'IntersectionObserver.webidl', 'IntlUtils.webidl', 'IterableIterator.webidl', @@ -640,6 +651,8 @@ WEBIDL_FILES = [ 'ListBoxObject.webidl', 'LocalMediaStream.webidl', 'Location.webidl', + 'MatchGlob.webidl', + 'MatchPattern.webidl', 'MediaDeviceInfo.webidl', 'MediaDevices.webidl', 'MediaElementAudioSourceNode.webidl', @@ -680,6 +693,9 @@ WEBIDL_FILES = [ 'MimeTypeArray.webidl', 'MouseEvent.webidl', 'MouseScrollEvent.webidl', + 'MozStorageAsyncStatementParams.webidl', + 'MozStorageStatementParams.webidl', + 'MozStorageStatementRow.webidl', 'MutationEvent.webidl', 'MutationObserver.webidl', 'NamedNodeMap.webidl', @@ -726,6 +742,7 @@ WEBIDL_FILES = [ 'PopupBoxObject.webidl', 'Position.webidl', 'PositionError.webidl', + 'PrecompiledScript.webidl', 'Presentation.webidl', 'PresentationAvailability.webidl', 'PresentationConnection.webidl', @@ -735,6 +752,7 @@ WEBIDL_FILES = [ 'ProcessingInstruction.webidl', 'ProfileTimelineMarker.webidl', 'Promise.webidl', + 'PromiseDebugging.webidl', 'PushEvent.webidl', 'PushManager.webidl', 'PushManager.webidl', @@ -772,6 +790,7 @@ WEBIDL_FILES = [ 'StorageType.webidl', 'StreamFilter.webidl', 'StreamFilterDataEvent.webidl', + 'StructuredCloneHolder.webidl', 'StyleSheet.webidl', 'StyleSheetList.webidl', 'SubtleCrypto.webidl', @@ -926,6 +945,8 @@ WEBIDL_FILES = [ 'WaveShaperNode.webidl', 'WebAuthentication.webidl', 'WebComponents.webidl', + 'WebExtensionContentScript.webidl', + 'WebExtensionPolicy.webidl', 'WebGL2RenderingContext.webidl', 'WebGLRenderingContext.webidl', 'WebKitCSSMatrix.webidl', From 31fcead536985f0eec411b1bed96b5415babd856 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Wed, 7 Mar 2018 15:40:42 +1300 Subject: [PATCH 21/23] Bug 1438990 - Remove common clip count code from FrameLayerBuilder, as it's no longer necessary now that we have ASRs. r=mstange --HG-- extra : rebase_source : 8e7c65df6227df6144a8ef3f7c8b996999ce1c30 --- layout/painting/DisplayItemClip.cpp | 48 +++------- layout/painting/DisplayItemClip.h | 19 +--- layout/painting/FrameLayerBuilder.cpp | 127 +++++--------------------- layout/painting/FrameLayerBuilder.h | 3 +- 4 files changed, 40 insertions(+), 157 deletions(-) diff --git a/layout/painting/DisplayItemClip.cpp b/layout/painting/DisplayItemClip.cpp index 0f16c7850fff..f553802d298b 100644 --- a/layout/painting/DisplayItemClip.cpp +++ b/layout/painting/DisplayItemClip.cpp @@ -91,11 +91,10 @@ DisplayItemClip::IntersectWith(const DisplayItemClip& aOther) void DisplayItemClip::ApplyTo(gfxContext* aContext, - int32_t A2D, - uint32_t aBegin, uint32_t aEnd) + int32_t A2D) { ApplyRectTo(aContext, A2D); - ApplyRoundedRectClipsTo(aContext, A2D, aBegin, aEnd); + ApplyRoundedRectClipsTo(aContext, A2D, 0, mRoundedClipRects.Length()); } void @@ -126,30 +125,27 @@ DisplayItemClip::ApplyRoundedRectClipsTo(gfxContext* aContext, void DisplayItemClip::FillIntersectionOfRoundedRectClips(gfxContext* aContext, const Color& aColor, - int32_t aAppUnitsPerDevPixel, - uint32_t aBegin, - uint32_t aEnd) const + int32_t aAppUnitsPerDevPixel) const { DrawTarget& aDrawTarget = *aContext->GetDrawTarget(); - aEnd = std::min(aEnd, mRoundedClipRects.Length()); - - if (aBegin >= aEnd) { + uint32_t end = mRoundedClipRects.Length(); + if (!end) { return; } // Push clips for any rects that come BEFORE the rect at |aEnd - 1|, if any: - ApplyRoundedRectClipsTo(aContext, aAppUnitsPerDevPixel, aBegin, aEnd - 1); + ApplyRoundedRectClipsTo(aContext, aAppUnitsPerDevPixel, 0, end - 1); // Now fill the rect at |aEnd - 1|: RefPtr roundedRect = MakeRoundedRectPath(aDrawTarget, aAppUnitsPerDevPixel, - mRoundedClipRects[aEnd - 1]); + mRoundedClipRects[end - 1]); ColorPattern color(ToDeviceColor(aColor)); aDrawTarget.Fill(roundedRect, color); // Finally, pop any clips that we may have pushed: - for (uint32_t i = aBegin; i < aEnd - 1; ++i) { + for (uint32_t i = 0; i < end - 1; ++i) { aContext->PopClip(); } } @@ -358,16 +354,13 @@ AccumulateRectDifference(const nsRect& aR1, const nsRect& aR2, const nsRect& aBo } void -DisplayItemClip::AddOffsetAndComputeDifference(uint32_t aStart, - const nsPoint& aOffset, +DisplayItemClip::AddOffsetAndComputeDifference(const nsPoint& aOffset, const nsRect& aBounds, const DisplayItemClip& aOther, - uint32_t aOtherStart, const nsRect& aOtherBounds, nsRegion* aDifference) { if (mHaveClipRect != aOther.mHaveClipRect || - aStart != aOtherStart || mRoundedClipRects.Length() != aOther.mRoundedClipRects.Length()) { aDifference->Or(*aDifference, aBounds); aDifference->Or(*aDifference, aOtherBounds); @@ -378,7 +371,7 @@ DisplayItemClip::AddOffsetAndComputeDifference(uint32_t aStart, aBounds.Union(aOtherBounds), aDifference); } - for (uint32_t i = aStart; i < mRoundedClipRects.Length(); ++i) { + for (uint32_t i = 0; i < mRoundedClipRects.Length(); ++i) { if (mRoundedClipRects[i] + aOffset != aOther.mRoundedClipRects[i]) { // The corners make it tricky so we'll just add both rects here. aDifference->Or(*aDifference, mRoundedClipRects[i].mRect.Intersect(aBounds)); @@ -387,27 +380,10 @@ DisplayItemClip::AddOffsetAndComputeDifference(uint32_t aStart, } } -uint32_t -DisplayItemClip::GetCommonRoundedRectCount(const DisplayItemClip& aOther, - uint32_t aMax) const -{ - uint32_t end = std::min(std::min(mRoundedClipRects.Length(), size_t(aMax)), - aOther.mRoundedClipRects.Length()); - uint32_t clipCount = 0; - for (; clipCount < end; ++clipCount) { - if (mRoundedClipRects[clipCount] != - aOther.mRoundedClipRects[clipCount]) { - return clipCount; - } - } - return clipCount; -} - void -DisplayItemClip::AppendRoundedRects(nsTArray* aArray, uint32_t aCount) const +DisplayItemClip::AppendRoundedRects(nsTArray* aArray) const { - size_t count = std::min(mRoundedClipRects.Length(), size_t(aCount)); - aArray->AppendElements(mRoundedClipRects.Elements(), count); + aArray->AppendElements(mRoundedClipRects.Elements(), mRoundedClipRects.Length()); } bool diff --git a/layout/painting/DisplayItemClip.h b/layout/painting/DisplayItemClip.h index 1ef0601f193a..60a34a9b43bb 100644 --- a/layout/painting/DisplayItemClip.h +++ b/layout/painting/DisplayItemClip.h @@ -81,8 +81,7 @@ public: // Apply this |DisplayItemClip| to the given gfxContext. Any saving of state // or clearing of other clips must be done by the caller. // See aBegin/aEnd note on ApplyRoundedRectsTo. - void ApplyTo(gfxContext* aContext, int32_t A2D, - uint32_t aBegin = 0, uint32_t aEnd = UINT32_MAX); + void ApplyTo(gfxContext* aContext, int32_t A2D); void ApplyRectTo(gfxContext* aContext, int32_t A2D) const; // Applies the rounded rects in this Clip to aContext @@ -94,9 +93,7 @@ public: // Draw (fill) the rounded rects in this clip to aContext void FillIntersectionOfRoundedRectClips(gfxContext* aContext, const Color& aColor, - int32_t aAppUnitsPerDevPixel, - uint32_t aBegin, - uint32_t aEnd) const; + int32_t aAppUnitsPerDevPixel) const; // 'Draw' (create as a path, does not stroke or fill) aRoundRect to aContext already_AddRefed MakeRoundedRectPath(DrawTarget& aDrawTarget, int32_t A2D, @@ -148,8 +145,8 @@ public: // Adds the difference between Intersect(*this + aPoint, aBounds) and // Intersect(aOther, aOtherBounds) to aDifference (or a bounding-box thereof). - void AddOffsetAndComputeDifference(uint32_t aStart, const nsPoint& aPoint, const nsRect& aBounds, - const DisplayItemClip& aOther, uint32_t aOtherStart, const nsRect& aOtherBounds, + void AddOffsetAndComputeDifference(const nsPoint& aPoint, const nsRect& aBounds, + const DisplayItemClip& aOther, const nsRect& aOtherBounds, nsRegion* aDifference); bool operator==(const DisplayItemClip& aOther) const { @@ -172,14 +169,8 @@ public: nsCString ToString() const; - /** - * Find the largest N such that the first N rounded rects in 'this' are - * equal to the first N rounded rects in aOther, and N <= aMax. - */ - uint32_t GetCommonRoundedRectCount(const DisplayItemClip& aOther, - uint32_t aMax) const; uint32_t GetRoundedRectCount() const { return mRoundedClipRects.Length(); } - void AppendRoundedRects(nsTArray* aArray, uint32_t aCount) const; + void AppendRoundedRects(nsTArray* aArray) const; void ToComplexClipRegions(int32_t aAppUnitsPerDevPixel, const layers::StackingContextHelper& aSc, diff --git a/layout/painting/FrameLayerBuilder.cpp b/layout/painting/FrameLayerBuilder.cpp index 4cbd4c7f9de5..8056b96f53a0 100644 --- a/layout/painting/FrameLayerBuilder.cpp +++ b/layout/painting/FrameLayerBuilder.cpp @@ -449,7 +449,6 @@ public: mShouldPaintOnContentSide(false), mDTCRequiresTargetConfirmation(false), mImage(nullptr), - mCommonClipCount(-1), mNewChildLayersIndex(-1) {} @@ -661,24 +660,10 @@ public: * no part at all. */ DisplayItemClip mItemClip; - /** - * The first mCommonClipCount rounded rectangle clips are identical for - * all items in the layer. - * -1 if there are no items in the layer; must be >=0 by the time that this - * data is popped from the stack. - */ - int32_t mCommonClipCount; /** * Index of this layer in mNewChildLayers. */ int32_t mNewChildLayersIndex; - /* - * Updates mCommonClipCount by checking for rounded rect clips in common - * between the clip on a new item (aCurrentClip) and the common clips - * on items already in the layer (the first mCommonClipCount rounded rects - * in mItemClip). - */ - void UpdateCommonClipCount(const DisplayItemClip& aCurrentClip); /** * The region of visible content above the layer and below the * next PaintedLayerData currently in the stack, if any. @@ -1385,12 +1370,8 @@ protected: * aLayer is the layer to be clipped. * relative to the container reference frame * aRoundedRectClipCount is used when building mask layers for PaintedLayers, - * SetupMaskLayer will build a mask layer for only the first - * aRoundedRectClipCount rounded rects in aClip - * Returns the number of rounded rects included in the mask layer. */ - uint32_t SetupMaskLayer(Layer *aLayer, const DisplayItemClip& aClip, - uint32_t aRoundedRectClipCount = UINT32_MAX); + void SetupMaskLayer(Layer *aLayer, const DisplayItemClip& aClip); /** * If |aClip| has rounded corners, create a mask layer for them, and @@ -1410,8 +1391,7 @@ protected: already_AddRefed CreateMaskLayer( Layer *aLayer, const DisplayItemClip& aClip, - const Maybe& aForAncestorMaskLayer, - uint32_t aRoundedRectClipCount = UINT32_MAX); + const Maybe& aForAncestorMaskLayer); /** * Get the display port for an AGR. @@ -1498,8 +1478,6 @@ class PaintedDisplayItemLayerUserData : public LayerUserData { public: PaintedDisplayItemLayerUserData() : - mMaskClipCount(0), - mLastCommonClipCount(0), mForcedBackgroundColor(NS_RGBA(0,0,0,0)), mXScale(1.f), mYScale(1.f), mAppUnitsPerDevPixel(0), @@ -1511,19 +1489,6 @@ public: NS_INLINE_DECL_REFCOUNTING(PaintedDisplayItemLayerUserData); - /** - * Record the number of clips in the PaintedLayer's mask layer. - * Should not be reset when the layer is recycled since it is used to track - * changes in the use of mask layers. - */ - uint32_t mMaskClipCount; - - /** - * Records the number of clips in the PaintedLayer's mask layer during - * the previous paint. Used for invalidation. - */ - uint32_t mLastCommonClipCount; - /** * A color that should be painted over the bounds of the layer's visible * region before any other content is painted. @@ -1640,7 +1605,6 @@ struct MaskLayerUserData : public LayerUserData , mAppUnitsPerDevPixel(-1) { } MaskLayerUserData(const DisplayItemClip& aClip, - uint32_t aRoundedRectClipCount, int32_t aAppUnitsPerDevPixel, const ContainerLayerParameters& aParams) : mScaleX(aParams.mXScale) @@ -1648,7 +1612,7 @@ struct MaskLayerUserData : public LayerUserData , mOffset(aParams.mOffset) , mAppUnitsPerDevPixel(aAppUnitsPerDevPixel) { - aClip.AppendRoundedRects(&mRoundedClipRects, aRoundedRectClipCount); + aClip.AppendRoundedRects(&mRoundedClipRects); } void operator=(MaskLayerUserData&& aOther) @@ -2500,7 +2464,6 @@ ContainerState::PreparePaintedLayerForUse(PaintedLayer* aLayer, aData->mLastPaintOffset = GetTranslationForPaintedLayer(aLayer); aData->mHasExplicitLastPaintOffset = true; - aData->mLastCommonClipCount = aData->mMaskClipCount; // Set up transform so that 0,0 in the PaintedLayer corresponds to the // (pixel-snapped) top-left of the aAnimatedGeometryRoot. @@ -2763,18 +2726,6 @@ PaintedLayerDataNode::FindOpaqueBackgroundColorInParentNode() const return mTree.UniformBackgroundColor(); } -void -PaintedLayerData::UpdateCommonClipCount( - const DisplayItemClip& aCurrentClip) -{ - if (mCommonClipCount >= 0) { - mCommonClipCount = mItemClip.GetCommonRoundedRectCount(aCurrentClip, mCommonClipCount); - } else { - // first item in the layer - mCommonClipCount = aCurrentClip.GetRoundedRectCount(); - } -} - bool PaintedLayerData::CanOptimizeToImageLayer(nsDisplayListBuilder* aBuilder) { @@ -3361,22 +3312,7 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB data->mLayer->InvalidateWholeLayer(); } userData->mForcedBackgroundColor = backgroundColor; - - // use a mask layer for rounded rect clipping. - // data->mCommonClipCount may be -1 if we haven't put any actual - // drawable items in this layer (i.e. it's only catching events). - uint32_t commonClipCount; - commonClipCount = std::max(0, data->mCommonClipCount); - - // if the number of clips we are going to mask has decreased, then aLayer might have - // cached graphics which assume the existence of a soon-to-be non-existent mask layer - // in that case, invalidate the whole layer. - if (commonClipCount < userData->mMaskClipCount) { - PaintedLayer* painted = layer->AsPaintedLayer(); - painted->InvalidateWholeLayer(); - } - - userData->mMaskClipCount = SetupMaskLayer(layer, data->mItemClip, commonClipCount); + SetupMaskLayer(layer, data->mItemClip); } else { // mask layer for image and color layers SetupMaskLayer(layer, data->mItemClip); @@ -4019,8 +3955,7 @@ ContainerState::SetupMaskLayerForScrolledClip(Layer* aLayer, { if (aClip.GetRoundedRectCount() > 0) { Maybe maskLayerIndex = Some(aLayer->GetAncestorMaskLayerCount()); - if (RefPtr maskLayer = CreateMaskLayer(aLayer, aClip, maskLayerIndex, - aClip.GetRoundedRectCount())) { + if (RefPtr maskLayer = CreateMaskLayer(aLayer, aClip, maskLayerIndex)) { aLayer->AddAncestorMaskLayer(maskLayer); return maskLayerIndex; } @@ -4687,11 +4622,6 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList) static_cast(item); paintedLayerData->AccumulateHitTestInfo(this, hitTestInfo); } else { - // check to see if the new item has rounded rect clips in common with - // other items in the layer - if (mManager->IsWidgetLayerManager()) { - paintedLayerData->UpdateCommonClipCount(itemClip); - } paintedLayerData->Accumulate(this, item, itemVisibleRect, itemClip, layerState, aList); if (!paintedLayerData->mLayer) { @@ -4820,11 +4750,9 @@ FrameLayerBuilder::ComputeGeometryChangeForItem(DisplayItemData* aData) if (!combined.IsEmpty() || aData->mLayerState == LAYER_INACTIVE) { geometry = item->AllocateGeometry(mDisplayListBuilder); } - aData->mClip.AddOffsetAndComputeDifference(layerData->mMaskClipCount, - shift, aData->mGeometry->ComputeInvalidationRegion(), - clip, layerData->mLastCommonClipCount, - geometry ? geometry->ComputeInvalidationRegion() : - aData->mGeometry->ComputeInvalidationRegion(), + aData->mClip.AddOffsetAndComputeDifference(shift, aData->mGeometry->ComputeInvalidationRegion(), + clip, geometry ? geometry->ComputeInvalidationRegion() : + aData->mGeometry->ComputeInvalidationRegion(), &combined); // Add in any rect that the frame specified @@ -5308,7 +5236,7 @@ ContainerState::SetupScrollingMetadata(NewLayerEntry* aEntry) // layer as an additional, separate clip. Maybe nextIndex = Some(maskLayers.Length()); RefPtr maskLayer = - CreateMaskLayer(aEntry->mLayer, *clip, nextIndex, clip->GetRoundedRectCount()); + CreateMaskLayer(aEntry->mLayer, *clip, nextIndex); if (maskLayer) { MOZ_ASSERT(metadata->HasScrollClip()); metadata->ScrollClip().SetMaskLayerIndex(nextIndex); @@ -6034,8 +5962,7 @@ FrameLayerBuilder::PaintItems(nsTArray& aItems, nsDisplayListBuilder* aBuilder, nsPresContext* aPresContext, const nsIntPoint& aOffset, - float aXScale, float aYScale, - int32_t aCommonClipCount) + float aXScale, float aYScale) { DrawTarget& aDrawTarget = *aContext->GetDrawTarget(); @@ -6084,9 +6011,7 @@ FrameLayerBuilder::PaintItems(nsTArray& aItems, if (currentClipIsSetInContext) { currentClip = *clip; aContext->Save(); - NS_ASSERTION(aCommonClipCount < 100, - "Maybe you really do have more than a hundred clipping rounded rects, or maybe something has gone wrong."); - currentClip.ApplyTo(aContext, aPresContext->AppUnitsPerDevPixel(), aCommonClipCount); + currentClip.ApplyTo(aContext, aPresContext->AppUnitsPerDevPixel()); aContext->NewPath(); } } @@ -6249,8 +6174,7 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer, layerBuilder->PaintItems(userData->mItems, iterRect, aContext, builder, presContext, - offset, userData->mXScale, userData->mYScale, - userData->mMaskClipCount); + offset, userData->mXScale, userData->mYScale); if (gfxPrefs::GfxLoggingPaintedPixelCountEnabled()) { aLayer->Manager()->AddPaintedPixelCount(iterRect.Area()); } @@ -6265,8 +6189,7 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer, layerBuilder->PaintItems(userData->mItems, aRegionToDraw.GetBounds(), aContext, builder, presContext, - offset, userData->mXScale, userData->mYScale, - userData->mMaskClipCount); + offset, userData->mXScale, userData->mYScale); if (gfxPrefs::GfxLoggingPaintedPixelCountEnabled()) { aLayer->Manager()->AddPaintedPixelCount( aRegionToDraw.GetBounds().Area()); @@ -6343,26 +6266,23 @@ CalculateBounds(const nsTArray& aRects, int32_t aA return gfx::Rect(bounds.ToNearestPixels(aAppUnitsPerDevPixel)); } -uint32_t +void ContainerState::SetupMaskLayer(Layer *aLayer, - const DisplayItemClip& aClip, - uint32_t aRoundedRectClipCount) + const DisplayItemClip& aClip) { // don't build an unnecessary mask - if (aClip.GetRoundedRectCount() == 0 || - aRoundedRectClipCount == 0) { - return 0; + if (aClip.GetRoundedRectCount() == 0) { + return; } RefPtr maskLayer = - CreateMaskLayer(aLayer, aClip, Nothing(), aRoundedRectClipCount); + CreateMaskLayer(aLayer, aClip, Nothing()); if (!maskLayer) { - return 0; + return; } aLayer->SetMaskLayer(maskLayer); - return aRoundedRectClipCount; } static MaskLayerUserData* @@ -6387,8 +6307,7 @@ SetMaskLayerUserData(Layer* aMaskLayer) already_AddRefed ContainerState::CreateMaskLayer(Layer *aLayer, const DisplayItemClip& aClip, - const Maybe& aForAncestorMaskLayer, - uint32_t aRoundedRectClipCount) + const Maybe& aForAncestorMaskLayer) { // aLayer will never be the container layer created by an nsDisplayMask // because nsDisplayMask propagates the DisplayItemClip to its contents @@ -6405,7 +6324,7 @@ ContainerState::CreateMaskLayer(Layer *aLayer, MaskLayerUserData* userData = GetMaskLayerUserData(maskLayer.get()); int32_t A2D = mContainerFrame->PresContext()->AppUnitsPerDevPixel(); - MaskLayerUserData newData(aClip, aRoundedRectClipCount, A2D, mParameters); + MaskLayerUserData newData(aClip, A2D, mParameters); if (*userData == newData) { return maskLayer.forget(); } @@ -6485,9 +6404,7 @@ ContainerState::CreateMaskLayer(Layer *aLayer, // paint the clipping rects with alpha to create the mask aClip.FillIntersectionOfRoundedRectClips(context, Color(1.f, 1.f, 1.f, 1.f), - newData.mAppUnitsPerDevPixel, - 0, - aRoundedRectClipCount); + newData.mAppUnitsPerDevPixel); // build the image and container MOZ_ASSERT(aLayer->Manager() == mManager); diff --git a/layout/painting/FrameLayerBuilder.h b/layout/painting/FrameLayerBuilder.h index de4b7cc46485..6e0108daff8c 100644 --- a/layout/painting/FrameLayerBuilder.h +++ b/layout/painting/FrameLayerBuilder.h @@ -674,8 +674,7 @@ protected: nsDisplayListBuilder* aBuilder, nsPresContext* aPresContext, const nsIntPoint& aOffset, - float aXScale, float aYScale, - int32_t aCommonClipCount); + float aXScale, float aYScale); /** * We accumulate ClippedDisplayItem elements in a hashtable during From d72dbac57c40b6d868d9a9264c493b6b1a8b12ea Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Wed, 7 Mar 2018 15:42:43 +1300 Subject: [PATCH 22/23] Bug 1440966 - Store optimized Layer in DisplayItemData as part of AddPaintedLayerFor. r=jnicol --HG-- extra : rebase_source : e9bfc50ca8e3a4d7ea3161e71bc4fa4c4e6f7fb5 --- layout/painting/FrameLayerBuilder.cpp | 46 ++++++++++----------------- layout/painting/FrameLayerBuilder.h | 12 ++----- 2 files changed, 19 insertions(+), 39 deletions(-) diff --git a/layout/painting/FrameLayerBuilder.cpp b/layout/painting/FrameLayerBuilder.cpp index 8056b96f53a0..09fe86319d44 100644 --- a/layout/painting/FrameLayerBuilder.cpp +++ b/layout/painting/FrameLayerBuilder.cpp @@ -2011,19 +2011,6 @@ FrameLayerBuilder::DidBeginRetainedLayerTransaction(LayerManager* aManager) } } -void -FrameLayerBuilder::StoreOptimizedLayerForFrame(nsDisplayItem* aItem, Layer* aLayer) -{ - if (!mRetainingManager) { - return; - } - - DisplayItemData* data = GetDisplayItemDataForManager(aItem, aLayer->Manager()); - NS_ASSERTION(data, "Must have already stored data for this item!"); - data->mOptLayer = aLayer; - data->mItem = nullptr; -} - void FrameLayerBuilder::DidEndTransaction() { @@ -3192,16 +3179,6 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB mNewChildLayers[data->mNewChildLayersIndex].mLayer = paintedLayer.forget(); } - for (auto& item : data->mAssignedDisplayItems) { - MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_LAYER_EVENT_REGIONS); - MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO); - - InvalidateForLayerChange(item.mItem, data->mLayer, item.mDisplayItemData); - mLayerBuilder->AddPaintedDisplayItem(data, item, *this, - data->mAnimatedGeometryRootOffset); - item.mDisplayItemData = nullptr; - } - PaintedDisplayItemLayerUserData* userData = GetPaintedDisplayItemLayerUserData(data->mLayer); NS_ASSERTION(userData, "where did our user data go?"); userData->mLastItemCount = data->mAssignedDisplayItems.Length(); @@ -3246,10 +3223,6 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB data->mLayer->SetVisibleRegion(LayerIntRegion()); data->mLayer->InvalidateWholeLayer(); data->mLayer->SetEventRegions(EventRegions()); - - for (auto& item : data->mAssignedDisplayItems) { - mLayerBuilder->StoreOptimizedLayerForFrame(item.mItem, layer); - } } } @@ -3260,6 +3233,15 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB FLB_LOG_PAINTED_LAYER_DECISION(data, " Selected painted layer=%p\n", layer.get()); } + for (auto& item : data->mAssignedDisplayItems) { + MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_LAYER_EVENT_REGIONS); + MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO); + + InvalidateForLayerChange(item.mItem, data->mLayer, item.mDisplayItemData); + mLayerBuilder->AddPaintedDisplayItem(data, item, *this, layer); + item.mDisplayItemData = nullptr; + } + if (mLayerBuilder->IsBuildingRetainedLayers()) { newLayerEntry->mVisibleRegion = data->mVisibleRegion; newLayerEntry->mOpaqueRegion = data->mOpaqueRegion; @@ -4785,7 +4767,7 @@ void FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, AssignedDisplayItem& aItem, ContainerState& aContainerState, - const nsPoint& aTopLeft) + Layer* aLayer) { PaintedLayer* layer = aLayerData->mLayer; PaintedDisplayItemLayerUserData* paintedData = @@ -4801,7 +4783,7 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, // We need to grab these before updating the DisplayItemData because it will overwrite them. nsRegion clip; if (aItem.mClip.ComputeRegionInClips(&aItem.mDisplayItemData->GetClip(), - aTopLeft - paintedData->mLastAnimatedGeometryRootOrigin, + aLayerData->mAnimatedGeometryRootOffset - paintedData->mLastAnimatedGeometryRootOrigin, &clip)) { intClip = clip.GetBounds().ScaleToOutsidePixels(paintedData->mXScale, paintedData->mYScale, @@ -4823,6 +4805,12 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, data = StoreDataForFrame(aItem.mItem, layer, aItem.mLayerState, nullptr); } data->mInactiveManager = tempManager; + // We optimized this PaintedLayer into a ColorLayer/ImageLayer. Store the optimized + // layer here. + if (aLayer != layer) { + data->mOptLayer = aLayer; + data->mItem = nullptr; + } } if (tempManager) { diff --git a/layout/painting/FrameLayerBuilder.h b/layout/painting/FrameLayerBuilder.h index 6e0108daff8c..7f70d75122c2 100644 --- a/layout/painting/FrameLayerBuilder.h +++ b/layout/painting/FrameLayerBuilder.h @@ -510,10 +510,10 @@ public: * aItem must have an underlying frame. * @param aTopLeft offset from active scrolled root to reference frame */ - void AddPaintedDisplayItem(PaintedLayerData* aLayer, + void AddPaintedDisplayItem(PaintedLayerData* aLayerData, AssignedDisplayItem& aAssignedDisplayItem, ContainerState& aContainerState, - const nsPoint& aTopLeft); + Layer* aLayer); /** * Calls GetOldLayerForFrame on the underlying frame of the display item, @@ -590,14 +590,6 @@ public: */ static gfxSize GetPaintedLayerScaleForFrame(nsIFrame* aFrame); - /** - * Stores a Layer as the dedicated layer in the DisplayItemData for a given frame/key pair. - * - * Used when we optimize a PaintedLayer into an ImageLayer and want to retroactively update the - * DisplayItemData so we can retrieve the layer from within layout. - */ - void StoreOptimizedLayerForFrame(nsDisplayItem* aItem, Layer* aLayer); - static void RemoveFrameFromLayerManager(const nsIFrame* aFrame, SmallPointerArray& aArray); From 32c3cc16add30142789a7c555478d67acd7731ac Mon Sep 17 00:00:00 2001 From: Andreea Pavel Date: Wed, 7 Mar 2018 11:01:05 +0200 Subject: [PATCH 23/23] Backed out 2 changesets (bug 1440966, bug 1438990) for reftest failures e.g. async-scrolling/bg-fixed-child-mask.html==async-scrolling/bg-fixed-child-mask-ref.html on a CLOSED TREE Backed out changeset 1a8e77cb2c21 (bug 1440966) Backed out changeset 44b5d524c061 (bug 1438990) --- layout/painting/DisplayItemClip.cpp | 50 ++++++-- layout/painting/DisplayItemClip.h | 19 ++- layout/painting/FrameLayerBuilder.cpp | 173 ++++++++++++++++++++------ layout/painting/FrameLayerBuilder.h | 15 ++- 4 files changed, 197 insertions(+), 60 deletions(-) diff --git a/layout/painting/DisplayItemClip.cpp b/layout/painting/DisplayItemClip.cpp index f553802d298b..0f16c7850fff 100644 --- a/layout/painting/DisplayItemClip.cpp +++ b/layout/painting/DisplayItemClip.cpp @@ -91,10 +91,11 @@ DisplayItemClip::IntersectWith(const DisplayItemClip& aOther) void DisplayItemClip::ApplyTo(gfxContext* aContext, - int32_t A2D) + int32_t A2D, + uint32_t aBegin, uint32_t aEnd) { ApplyRectTo(aContext, A2D); - ApplyRoundedRectClipsTo(aContext, A2D, 0, mRoundedClipRects.Length()); + ApplyRoundedRectClipsTo(aContext, A2D, aBegin, aEnd); } void @@ -125,27 +126,30 @@ DisplayItemClip::ApplyRoundedRectClipsTo(gfxContext* aContext, void DisplayItemClip::FillIntersectionOfRoundedRectClips(gfxContext* aContext, const Color& aColor, - int32_t aAppUnitsPerDevPixel) const + int32_t aAppUnitsPerDevPixel, + uint32_t aBegin, + uint32_t aEnd) const { DrawTarget& aDrawTarget = *aContext->GetDrawTarget(); - uint32_t end = mRoundedClipRects.Length(); - if (!end) { + aEnd = std::min(aEnd, mRoundedClipRects.Length()); + + if (aBegin >= aEnd) { return; } // Push clips for any rects that come BEFORE the rect at |aEnd - 1|, if any: - ApplyRoundedRectClipsTo(aContext, aAppUnitsPerDevPixel, 0, end - 1); + ApplyRoundedRectClipsTo(aContext, aAppUnitsPerDevPixel, aBegin, aEnd - 1); // Now fill the rect at |aEnd - 1|: RefPtr roundedRect = MakeRoundedRectPath(aDrawTarget, aAppUnitsPerDevPixel, - mRoundedClipRects[end - 1]); + mRoundedClipRects[aEnd - 1]); ColorPattern color(ToDeviceColor(aColor)); aDrawTarget.Fill(roundedRect, color); // Finally, pop any clips that we may have pushed: - for (uint32_t i = 0; i < end - 1; ++i) { + for (uint32_t i = aBegin; i < aEnd - 1; ++i) { aContext->PopClip(); } } @@ -354,13 +358,16 @@ AccumulateRectDifference(const nsRect& aR1, const nsRect& aR2, const nsRect& aBo } void -DisplayItemClip::AddOffsetAndComputeDifference(const nsPoint& aOffset, +DisplayItemClip::AddOffsetAndComputeDifference(uint32_t aStart, + const nsPoint& aOffset, const nsRect& aBounds, const DisplayItemClip& aOther, + uint32_t aOtherStart, const nsRect& aOtherBounds, nsRegion* aDifference) { if (mHaveClipRect != aOther.mHaveClipRect || + aStart != aOtherStart || mRoundedClipRects.Length() != aOther.mRoundedClipRects.Length()) { aDifference->Or(*aDifference, aBounds); aDifference->Or(*aDifference, aOtherBounds); @@ -371,7 +378,7 @@ DisplayItemClip::AddOffsetAndComputeDifference(const nsPoint& aOffset, aBounds.Union(aOtherBounds), aDifference); } - for (uint32_t i = 0; i < mRoundedClipRects.Length(); ++i) { + for (uint32_t i = aStart; i < mRoundedClipRects.Length(); ++i) { if (mRoundedClipRects[i] + aOffset != aOther.mRoundedClipRects[i]) { // The corners make it tricky so we'll just add both rects here. aDifference->Or(*aDifference, mRoundedClipRects[i].mRect.Intersect(aBounds)); @@ -380,10 +387,27 @@ DisplayItemClip::AddOffsetAndComputeDifference(const nsPoint& aOffset, } } -void -DisplayItemClip::AppendRoundedRects(nsTArray* aArray) const +uint32_t +DisplayItemClip::GetCommonRoundedRectCount(const DisplayItemClip& aOther, + uint32_t aMax) const { - aArray->AppendElements(mRoundedClipRects.Elements(), mRoundedClipRects.Length()); + uint32_t end = std::min(std::min(mRoundedClipRects.Length(), size_t(aMax)), + aOther.mRoundedClipRects.Length()); + uint32_t clipCount = 0; + for (; clipCount < end; ++clipCount) { + if (mRoundedClipRects[clipCount] != + aOther.mRoundedClipRects[clipCount]) { + return clipCount; + } + } + return clipCount; +} + +void +DisplayItemClip::AppendRoundedRects(nsTArray* aArray, uint32_t aCount) const +{ + size_t count = std::min(mRoundedClipRects.Length(), size_t(aCount)); + aArray->AppendElements(mRoundedClipRects.Elements(), count); } bool diff --git a/layout/painting/DisplayItemClip.h b/layout/painting/DisplayItemClip.h index 60a34a9b43bb..1ef0601f193a 100644 --- a/layout/painting/DisplayItemClip.h +++ b/layout/painting/DisplayItemClip.h @@ -81,7 +81,8 @@ public: // Apply this |DisplayItemClip| to the given gfxContext. Any saving of state // or clearing of other clips must be done by the caller. // See aBegin/aEnd note on ApplyRoundedRectsTo. - void ApplyTo(gfxContext* aContext, int32_t A2D); + void ApplyTo(gfxContext* aContext, int32_t A2D, + uint32_t aBegin = 0, uint32_t aEnd = UINT32_MAX); void ApplyRectTo(gfxContext* aContext, int32_t A2D) const; // Applies the rounded rects in this Clip to aContext @@ -93,7 +94,9 @@ public: // Draw (fill) the rounded rects in this clip to aContext void FillIntersectionOfRoundedRectClips(gfxContext* aContext, const Color& aColor, - int32_t aAppUnitsPerDevPixel) const; + int32_t aAppUnitsPerDevPixel, + uint32_t aBegin, + uint32_t aEnd) const; // 'Draw' (create as a path, does not stroke or fill) aRoundRect to aContext already_AddRefed MakeRoundedRectPath(DrawTarget& aDrawTarget, int32_t A2D, @@ -145,8 +148,8 @@ public: // Adds the difference between Intersect(*this + aPoint, aBounds) and // Intersect(aOther, aOtherBounds) to aDifference (or a bounding-box thereof). - void AddOffsetAndComputeDifference(const nsPoint& aPoint, const nsRect& aBounds, - const DisplayItemClip& aOther, const nsRect& aOtherBounds, + void AddOffsetAndComputeDifference(uint32_t aStart, const nsPoint& aPoint, const nsRect& aBounds, + const DisplayItemClip& aOther, uint32_t aOtherStart, const nsRect& aOtherBounds, nsRegion* aDifference); bool operator==(const DisplayItemClip& aOther) const { @@ -169,8 +172,14 @@ public: nsCString ToString() const; + /** + * Find the largest N such that the first N rounded rects in 'this' are + * equal to the first N rounded rects in aOther, and N <= aMax. + */ + uint32_t GetCommonRoundedRectCount(const DisplayItemClip& aOther, + uint32_t aMax) const; uint32_t GetRoundedRectCount() const { return mRoundedClipRects.Length(); } - void AppendRoundedRects(nsTArray* aArray) const; + void AppendRoundedRects(nsTArray* aArray, uint32_t aCount) const; void ToComplexClipRegions(int32_t aAppUnitsPerDevPixel, const layers::StackingContextHelper& aSc, diff --git a/layout/painting/FrameLayerBuilder.cpp b/layout/painting/FrameLayerBuilder.cpp index 09fe86319d44..4cbd4c7f9de5 100644 --- a/layout/painting/FrameLayerBuilder.cpp +++ b/layout/painting/FrameLayerBuilder.cpp @@ -449,6 +449,7 @@ public: mShouldPaintOnContentSide(false), mDTCRequiresTargetConfirmation(false), mImage(nullptr), + mCommonClipCount(-1), mNewChildLayersIndex(-1) {} @@ -660,10 +661,24 @@ public: * no part at all. */ DisplayItemClip mItemClip; + /** + * The first mCommonClipCount rounded rectangle clips are identical for + * all items in the layer. + * -1 if there are no items in the layer; must be >=0 by the time that this + * data is popped from the stack. + */ + int32_t mCommonClipCount; /** * Index of this layer in mNewChildLayers. */ int32_t mNewChildLayersIndex; + /* + * Updates mCommonClipCount by checking for rounded rect clips in common + * between the clip on a new item (aCurrentClip) and the common clips + * on items already in the layer (the first mCommonClipCount rounded rects + * in mItemClip). + */ + void UpdateCommonClipCount(const DisplayItemClip& aCurrentClip); /** * The region of visible content above the layer and below the * next PaintedLayerData currently in the stack, if any. @@ -1370,8 +1385,12 @@ protected: * aLayer is the layer to be clipped. * relative to the container reference frame * aRoundedRectClipCount is used when building mask layers for PaintedLayers, + * SetupMaskLayer will build a mask layer for only the first + * aRoundedRectClipCount rounded rects in aClip + * Returns the number of rounded rects included in the mask layer. */ - void SetupMaskLayer(Layer *aLayer, const DisplayItemClip& aClip); + uint32_t SetupMaskLayer(Layer *aLayer, const DisplayItemClip& aClip, + uint32_t aRoundedRectClipCount = UINT32_MAX); /** * If |aClip| has rounded corners, create a mask layer for them, and @@ -1391,7 +1410,8 @@ protected: already_AddRefed CreateMaskLayer( Layer *aLayer, const DisplayItemClip& aClip, - const Maybe& aForAncestorMaskLayer); + const Maybe& aForAncestorMaskLayer, + uint32_t aRoundedRectClipCount = UINT32_MAX); /** * Get the display port for an AGR. @@ -1478,6 +1498,8 @@ class PaintedDisplayItemLayerUserData : public LayerUserData { public: PaintedDisplayItemLayerUserData() : + mMaskClipCount(0), + mLastCommonClipCount(0), mForcedBackgroundColor(NS_RGBA(0,0,0,0)), mXScale(1.f), mYScale(1.f), mAppUnitsPerDevPixel(0), @@ -1489,6 +1511,19 @@ public: NS_INLINE_DECL_REFCOUNTING(PaintedDisplayItemLayerUserData); + /** + * Record the number of clips in the PaintedLayer's mask layer. + * Should not be reset when the layer is recycled since it is used to track + * changes in the use of mask layers. + */ + uint32_t mMaskClipCount; + + /** + * Records the number of clips in the PaintedLayer's mask layer during + * the previous paint. Used for invalidation. + */ + uint32_t mLastCommonClipCount; + /** * A color that should be painted over the bounds of the layer's visible * region before any other content is painted. @@ -1605,6 +1640,7 @@ struct MaskLayerUserData : public LayerUserData , mAppUnitsPerDevPixel(-1) { } MaskLayerUserData(const DisplayItemClip& aClip, + uint32_t aRoundedRectClipCount, int32_t aAppUnitsPerDevPixel, const ContainerLayerParameters& aParams) : mScaleX(aParams.mXScale) @@ -1612,7 +1648,7 @@ struct MaskLayerUserData : public LayerUserData , mOffset(aParams.mOffset) , mAppUnitsPerDevPixel(aAppUnitsPerDevPixel) { - aClip.AppendRoundedRects(&mRoundedClipRects); + aClip.AppendRoundedRects(&mRoundedClipRects, aRoundedRectClipCount); } void operator=(MaskLayerUserData&& aOther) @@ -2011,6 +2047,19 @@ FrameLayerBuilder::DidBeginRetainedLayerTransaction(LayerManager* aManager) } } +void +FrameLayerBuilder::StoreOptimizedLayerForFrame(nsDisplayItem* aItem, Layer* aLayer) +{ + if (!mRetainingManager) { + return; + } + + DisplayItemData* data = GetDisplayItemDataForManager(aItem, aLayer->Manager()); + NS_ASSERTION(data, "Must have already stored data for this item!"); + data->mOptLayer = aLayer; + data->mItem = nullptr; +} + void FrameLayerBuilder::DidEndTransaction() { @@ -2451,6 +2500,7 @@ ContainerState::PreparePaintedLayerForUse(PaintedLayer* aLayer, aData->mLastPaintOffset = GetTranslationForPaintedLayer(aLayer); aData->mHasExplicitLastPaintOffset = true; + aData->mLastCommonClipCount = aData->mMaskClipCount; // Set up transform so that 0,0 in the PaintedLayer corresponds to the // (pixel-snapped) top-left of the aAnimatedGeometryRoot. @@ -2713,6 +2763,18 @@ PaintedLayerDataNode::FindOpaqueBackgroundColorInParentNode() const return mTree.UniformBackgroundColor(); } +void +PaintedLayerData::UpdateCommonClipCount( + const DisplayItemClip& aCurrentClip) +{ + if (mCommonClipCount >= 0) { + mCommonClipCount = mItemClip.GetCommonRoundedRectCount(aCurrentClip, mCommonClipCount); + } else { + // first item in the layer + mCommonClipCount = aCurrentClip.GetRoundedRectCount(); + } +} + bool PaintedLayerData::CanOptimizeToImageLayer(nsDisplayListBuilder* aBuilder) { @@ -3179,6 +3241,16 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB mNewChildLayers[data->mNewChildLayersIndex].mLayer = paintedLayer.forget(); } + for (auto& item : data->mAssignedDisplayItems) { + MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_LAYER_EVENT_REGIONS); + MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO); + + InvalidateForLayerChange(item.mItem, data->mLayer, item.mDisplayItemData); + mLayerBuilder->AddPaintedDisplayItem(data, item, *this, + data->mAnimatedGeometryRootOffset); + item.mDisplayItemData = nullptr; + } + PaintedDisplayItemLayerUserData* userData = GetPaintedDisplayItemLayerUserData(data->mLayer); NS_ASSERTION(userData, "where did our user data go?"); userData->mLastItemCount = data->mAssignedDisplayItems.Length(); @@ -3223,6 +3295,10 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB data->mLayer->SetVisibleRegion(LayerIntRegion()); data->mLayer->InvalidateWholeLayer(); data->mLayer->SetEventRegions(EventRegions()); + + for (auto& item : data->mAssignedDisplayItems) { + mLayerBuilder->StoreOptimizedLayerForFrame(item.mItem, layer); + } } } @@ -3233,15 +3309,6 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB FLB_LOG_PAINTED_LAYER_DECISION(data, " Selected painted layer=%p\n", layer.get()); } - for (auto& item : data->mAssignedDisplayItems) { - MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_LAYER_EVENT_REGIONS); - MOZ_ASSERT(item.mItem->GetType() != DisplayItemType::TYPE_COMPOSITOR_HITTEST_INFO); - - InvalidateForLayerChange(item.mItem, data->mLayer, item.mDisplayItemData); - mLayerBuilder->AddPaintedDisplayItem(data, item, *this, layer); - item.mDisplayItemData = nullptr; - } - if (mLayerBuilder->IsBuildingRetainedLayers()) { newLayerEntry->mVisibleRegion = data->mVisibleRegion; newLayerEntry->mOpaqueRegion = data->mOpaqueRegion; @@ -3294,7 +3361,22 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB data->mLayer->InvalidateWholeLayer(); } userData->mForcedBackgroundColor = backgroundColor; - SetupMaskLayer(layer, data->mItemClip); + + // use a mask layer for rounded rect clipping. + // data->mCommonClipCount may be -1 if we haven't put any actual + // drawable items in this layer (i.e. it's only catching events). + uint32_t commonClipCount; + commonClipCount = std::max(0, data->mCommonClipCount); + + // if the number of clips we are going to mask has decreased, then aLayer might have + // cached graphics which assume the existence of a soon-to-be non-existent mask layer + // in that case, invalidate the whole layer. + if (commonClipCount < userData->mMaskClipCount) { + PaintedLayer* painted = layer->AsPaintedLayer(); + painted->InvalidateWholeLayer(); + } + + userData->mMaskClipCount = SetupMaskLayer(layer, data->mItemClip, commonClipCount); } else { // mask layer for image and color layers SetupMaskLayer(layer, data->mItemClip); @@ -3937,7 +4019,8 @@ ContainerState::SetupMaskLayerForScrolledClip(Layer* aLayer, { if (aClip.GetRoundedRectCount() > 0) { Maybe maskLayerIndex = Some(aLayer->GetAncestorMaskLayerCount()); - if (RefPtr maskLayer = CreateMaskLayer(aLayer, aClip, maskLayerIndex)) { + if (RefPtr maskLayer = CreateMaskLayer(aLayer, aClip, maskLayerIndex, + aClip.GetRoundedRectCount())) { aLayer->AddAncestorMaskLayer(maskLayer); return maskLayerIndex; } @@ -4604,6 +4687,11 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList) static_cast(item); paintedLayerData->AccumulateHitTestInfo(this, hitTestInfo); } else { + // check to see if the new item has rounded rect clips in common with + // other items in the layer + if (mManager->IsWidgetLayerManager()) { + paintedLayerData->UpdateCommonClipCount(itemClip); + } paintedLayerData->Accumulate(this, item, itemVisibleRect, itemClip, layerState, aList); if (!paintedLayerData->mLayer) { @@ -4732,9 +4820,11 @@ FrameLayerBuilder::ComputeGeometryChangeForItem(DisplayItemData* aData) if (!combined.IsEmpty() || aData->mLayerState == LAYER_INACTIVE) { geometry = item->AllocateGeometry(mDisplayListBuilder); } - aData->mClip.AddOffsetAndComputeDifference(shift, aData->mGeometry->ComputeInvalidationRegion(), - clip, geometry ? geometry->ComputeInvalidationRegion() : - aData->mGeometry->ComputeInvalidationRegion(), + aData->mClip.AddOffsetAndComputeDifference(layerData->mMaskClipCount, + shift, aData->mGeometry->ComputeInvalidationRegion(), + clip, layerData->mLastCommonClipCount, + geometry ? geometry->ComputeInvalidationRegion() : + aData->mGeometry->ComputeInvalidationRegion(), &combined); // Add in any rect that the frame specified @@ -4767,7 +4857,7 @@ void FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, AssignedDisplayItem& aItem, ContainerState& aContainerState, - Layer* aLayer) + const nsPoint& aTopLeft) { PaintedLayer* layer = aLayerData->mLayer; PaintedDisplayItemLayerUserData* paintedData = @@ -4783,7 +4873,7 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, // We need to grab these before updating the DisplayItemData because it will overwrite them. nsRegion clip; if (aItem.mClip.ComputeRegionInClips(&aItem.mDisplayItemData->GetClip(), - aLayerData->mAnimatedGeometryRootOffset - paintedData->mLastAnimatedGeometryRootOrigin, + aTopLeft - paintedData->mLastAnimatedGeometryRootOrigin, &clip)) { intClip = clip.GetBounds().ScaleToOutsidePixels(paintedData->mXScale, paintedData->mYScale, @@ -4805,12 +4895,6 @@ FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData, data = StoreDataForFrame(aItem.mItem, layer, aItem.mLayerState, nullptr); } data->mInactiveManager = tempManager; - // We optimized this PaintedLayer into a ColorLayer/ImageLayer. Store the optimized - // layer here. - if (aLayer != layer) { - data->mOptLayer = aLayer; - data->mItem = nullptr; - } } if (tempManager) { @@ -5224,7 +5308,7 @@ ContainerState::SetupScrollingMetadata(NewLayerEntry* aEntry) // layer as an additional, separate clip. Maybe nextIndex = Some(maskLayers.Length()); RefPtr maskLayer = - CreateMaskLayer(aEntry->mLayer, *clip, nextIndex); + CreateMaskLayer(aEntry->mLayer, *clip, nextIndex, clip->GetRoundedRectCount()); if (maskLayer) { MOZ_ASSERT(metadata->HasScrollClip()); metadata->ScrollClip().SetMaskLayerIndex(nextIndex); @@ -5950,7 +6034,8 @@ FrameLayerBuilder::PaintItems(nsTArray& aItems, nsDisplayListBuilder* aBuilder, nsPresContext* aPresContext, const nsIntPoint& aOffset, - float aXScale, float aYScale) + float aXScale, float aYScale, + int32_t aCommonClipCount) { DrawTarget& aDrawTarget = *aContext->GetDrawTarget(); @@ -5999,7 +6084,9 @@ FrameLayerBuilder::PaintItems(nsTArray& aItems, if (currentClipIsSetInContext) { currentClip = *clip; aContext->Save(); - currentClip.ApplyTo(aContext, aPresContext->AppUnitsPerDevPixel()); + NS_ASSERTION(aCommonClipCount < 100, + "Maybe you really do have more than a hundred clipping rounded rects, or maybe something has gone wrong."); + currentClip.ApplyTo(aContext, aPresContext->AppUnitsPerDevPixel(), aCommonClipCount); aContext->NewPath(); } } @@ -6162,7 +6249,8 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer, layerBuilder->PaintItems(userData->mItems, iterRect, aContext, builder, presContext, - offset, userData->mXScale, userData->mYScale); + offset, userData->mXScale, userData->mYScale, + userData->mMaskClipCount); if (gfxPrefs::GfxLoggingPaintedPixelCountEnabled()) { aLayer->Manager()->AddPaintedPixelCount(iterRect.Area()); } @@ -6177,7 +6265,8 @@ FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer, layerBuilder->PaintItems(userData->mItems, aRegionToDraw.GetBounds(), aContext, builder, presContext, - offset, userData->mXScale, userData->mYScale); + offset, userData->mXScale, userData->mYScale, + userData->mMaskClipCount); if (gfxPrefs::GfxLoggingPaintedPixelCountEnabled()) { aLayer->Manager()->AddPaintedPixelCount( aRegionToDraw.GetBounds().Area()); @@ -6254,23 +6343,26 @@ CalculateBounds(const nsTArray& aRects, int32_t aA return gfx::Rect(bounds.ToNearestPixels(aAppUnitsPerDevPixel)); } -void +uint32_t ContainerState::SetupMaskLayer(Layer *aLayer, - const DisplayItemClip& aClip) + const DisplayItemClip& aClip, + uint32_t aRoundedRectClipCount) { // don't build an unnecessary mask - if (aClip.GetRoundedRectCount() == 0) { - return; + if (aClip.GetRoundedRectCount() == 0 || + aRoundedRectClipCount == 0) { + return 0; } RefPtr maskLayer = - CreateMaskLayer(aLayer, aClip, Nothing()); + CreateMaskLayer(aLayer, aClip, Nothing(), aRoundedRectClipCount); if (!maskLayer) { - return; + return 0; } aLayer->SetMaskLayer(maskLayer); + return aRoundedRectClipCount; } static MaskLayerUserData* @@ -6295,7 +6387,8 @@ SetMaskLayerUserData(Layer* aMaskLayer) already_AddRefed ContainerState::CreateMaskLayer(Layer *aLayer, const DisplayItemClip& aClip, - const Maybe& aForAncestorMaskLayer) + const Maybe& aForAncestorMaskLayer, + uint32_t aRoundedRectClipCount) { // aLayer will never be the container layer created by an nsDisplayMask // because nsDisplayMask propagates the DisplayItemClip to its contents @@ -6312,7 +6405,7 @@ ContainerState::CreateMaskLayer(Layer *aLayer, MaskLayerUserData* userData = GetMaskLayerUserData(maskLayer.get()); int32_t A2D = mContainerFrame->PresContext()->AppUnitsPerDevPixel(); - MaskLayerUserData newData(aClip, A2D, mParameters); + MaskLayerUserData newData(aClip, aRoundedRectClipCount, A2D, mParameters); if (*userData == newData) { return maskLayer.forget(); } @@ -6392,7 +6485,9 @@ ContainerState::CreateMaskLayer(Layer *aLayer, // paint the clipping rects with alpha to create the mask aClip.FillIntersectionOfRoundedRectClips(context, Color(1.f, 1.f, 1.f, 1.f), - newData.mAppUnitsPerDevPixel); + newData.mAppUnitsPerDevPixel, + 0, + aRoundedRectClipCount); // build the image and container MOZ_ASSERT(aLayer->Manager() == mManager); diff --git a/layout/painting/FrameLayerBuilder.h b/layout/painting/FrameLayerBuilder.h index 7f70d75122c2..de4b7cc46485 100644 --- a/layout/painting/FrameLayerBuilder.h +++ b/layout/painting/FrameLayerBuilder.h @@ -510,10 +510,10 @@ public: * aItem must have an underlying frame. * @param aTopLeft offset from active scrolled root to reference frame */ - void AddPaintedDisplayItem(PaintedLayerData* aLayerData, + void AddPaintedDisplayItem(PaintedLayerData* aLayer, AssignedDisplayItem& aAssignedDisplayItem, ContainerState& aContainerState, - Layer* aLayer); + const nsPoint& aTopLeft); /** * Calls GetOldLayerForFrame on the underlying frame of the display item, @@ -590,6 +590,14 @@ public: */ static gfxSize GetPaintedLayerScaleForFrame(nsIFrame* aFrame); + /** + * Stores a Layer as the dedicated layer in the DisplayItemData for a given frame/key pair. + * + * Used when we optimize a PaintedLayer into an ImageLayer and want to retroactively update the + * DisplayItemData so we can retrieve the layer from within layout. + */ + void StoreOptimizedLayerForFrame(nsDisplayItem* aItem, Layer* aLayer); + static void RemoveFrameFromLayerManager(const nsIFrame* aFrame, SmallPointerArray& aArray); @@ -666,7 +674,8 @@ protected: nsDisplayListBuilder* aBuilder, nsPresContext* aPresContext, const nsIntPoint& aOffset, - float aXScale, float aYScale); + float aXScale, float aYScale, + int32_t aCommonClipCount); /** * We accumulate ClippedDisplayItem elements in a hashtable during