From 98ab37c97e5852e1c2bc4d2faf60273071d86338 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Mon, 24 Feb 2014 11:42:54 +0100 Subject: [PATCH 01/48] Bug 974841 - Fix TextureClientX11::Lock. r=jrmuizel --- gfx/layers/basic/TextureClientX11.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gfx/layers/basic/TextureClientX11.cpp b/gfx/layers/basic/TextureClientX11.cpp index 86ea930dcc22..d21f2ef4fd8f 100644 --- a/gfx/layers/basic/TextureClientX11.cpp +++ b/gfx/layers/basic/TextureClientX11.cpp @@ -41,8 +41,8 @@ TextureClientX11::Lock(OpenMode aMode) { // XXX - Turn this into a fatal assertion as soon as Bug 952507 is fixed NS_WARN_IF_FALSE(!mLocked, "The TextureClient is already Locked!"); - mLocked = true; - return IsValid() && IsAllocated(); + mLocked = IsValid() && IsAllocated(); + return mLocked; } void From e1b60f2947ef761aa755d452d43573a64f354635 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Mon, 24 Feb 2014 08:23:37 -0500 Subject: [PATCH 02/48] Bug 935778 - Part 0.6: Add support for MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME and use it in moz2d X-Git-Commit-ID: bc256ac44cbba52b04f8f0390965632ec4507608 --- gfx/2d/2D.h | 18 ++++++++++-------- gfx/2d/DataSourceSurfaceWrapper.h | 1 + gfx/2d/DrawEventRecorder.h | 2 ++ gfx/2d/DrawTargetCG.cpp | 1 + gfx/2d/DrawTargetCG.h | 1 + gfx/2d/DrawTargetCairo.h | 2 ++ gfx/2d/DrawTargetD2D.h | 1 + gfx/2d/DrawTargetD2D1.h | 1 + gfx/2d/DrawTargetDual.h | 1 + gfx/2d/DrawTargetRecording.cpp | 3 +++ gfx/2d/DrawTargetRecording.h | 1 + gfx/2d/DrawTargetSkia.cpp | 1 + gfx/2d/DrawTargetSkia.h | 1 + gfx/2d/FilterNodeD2D1.h | 3 +++ gfx/2d/FilterNodeSoftware.h | 25 +++++++++++++++++++++++++ gfx/2d/Filters.h | 2 +- gfx/2d/GradientStopsD2D.h | 1 + gfx/2d/MacIOSurface.h | 5 +++-- gfx/2d/PathAnalysis.h | 1 + gfx/2d/PathCG.h | 2 ++ gfx/2d/PathCairo.h | 2 ++ gfx/2d/PathD2D.h | 2 ++ gfx/2d/PathRecording.h | 2 ++ gfx/2d/PathSkia.h | 2 ++ gfx/2d/ScaledFontBase.h | 1 + gfx/2d/ScaledFontCairo.h | 2 ++ gfx/2d/ScaledFontDWrite.h | 2 ++ gfx/2d/ScaledFontMac.h | 1 + gfx/2d/ScaledFontWin.h | 1 + gfx/2d/SourceSurfaceCG.h | 5 +++++ gfx/2d/SourceSurfaceCairo.h | 2 ++ gfx/2d/SourceSurfaceD2D.h | 2 ++ gfx/2d/SourceSurfaceD2D1.h | 2 ++ gfx/2d/SourceSurfaceD2DTarget.h | 2 ++ gfx/2d/SourceSurfaceDual.h | 1 + gfx/2d/SourceSurfaceRawData.h | 2 ++ gfx/2d/SourceSurfaceSkia.h | 1 + mfbt/RefPtr.h | 3 +++ 38 files changed, 97 insertions(+), 11 deletions(-) diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index ef782cfff4b1..5a161f223aad 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -164,7 +164,7 @@ struct DrawSurfaceOptions { class GradientStops : public RefCounted { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(GradientStops) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStops) virtual ~GradientStops() {} virtual BackendType GetBackendType() const = 0; @@ -317,7 +317,7 @@ public: class SourceSurface : public RefCounted { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(SourceSurface) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurface) virtual ~SourceSurface() {} virtual SurfaceType GetType() const = 0; @@ -341,6 +341,7 @@ public: class DataSourceSurface : public SourceSurface { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurface) DataSourceSurface() : mIsMapped(false) { @@ -398,7 +399,7 @@ public: class PathSink : public RefCounted { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(PathSink) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathSink) virtual ~PathSink() {} /* Move the current point in the path, any figure currently being drawn will @@ -437,7 +438,7 @@ class FlattenedPath; class Path : public RefCounted { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(Path) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(Path) virtual ~Path(); virtual BackendType GetBackendType() const = 0; @@ -506,6 +507,7 @@ protected: class PathBuilder : public PathSink { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathBuilder) /* Finish writing to the path and return a Path object that can be used for * drawing. Future use of the builder results in a crash! */ @@ -537,7 +539,7 @@ struct GlyphBuffer class ScaledFont : public RefCounted { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(ScaledFont) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFont) virtual ~ScaledFont() {} typedef void (*FontFileDataOutput)(const uint8_t *aData, uint32_t aLength, uint32_t aIndex, Float aGlyphSize, void *aBaton); @@ -596,7 +598,7 @@ struct FontOptions class GlyphRenderingOptions : public RefCounted { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(GlyphRenderingOptions) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GlyphRenderingOptions) virtual ~GlyphRenderingOptions() {} virtual FontType GetType() const = 0; @@ -613,7 +615,7 @@ protected: class DrawTarget : public RefCounted { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(DrawTarget) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTarget) DrawTarget() : mTransformDirty(false), mPermitSubpixelAA(false) {} virtual ~DrawTarget() {} @@ -996,7 +998,7 @@ protected: class DrawEventRecorder : public RefCounted { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(DrawEventRecorder) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorder) virtual ~DrawEventRecorder() { } }; diff --git a/gfx/2d/DataSourceSurfaceWrapper.h b/gfx/2d/DataSourceSurfaceWrapper.h index 7c2a6c9fac2e..2a3375f2fca9 100644 --- a/gfx/2d/DataSourceSurfaceWrapper.h +++ b/gfx/2d/DataSourceSurfaceWrapper.h @@ -16,6 +16,7 @@ namespace gfx { class DataSourceSurfaceWrapper : public DataSourceSurface { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceWrapper) DataSourceSurfaceWrapper(DataSourceSurface *aSurface) : mSurface(aSurface) {} diff --git a/gfx/2d/DrawEventRecorder.h b/gfx/2d/DrawEventRecorder.h index 3652996e70f3..292c871babb1 100644 --- a/gfx/2d/DrawEventRecorder.h +++ b/gfx/2d/DrawEventRecorder.h @@ -25,6 +25,7 @@ class PathRecording; class DrawEventRecorderPrivate : public DrawEventRecorder { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderPrivate) DrawEventRecorderPrivate(std::ostream *aStream); virtual ~DrawEventRecorderPrivate() { } @@ -64,6 +65,7 @@ protected: class DrawEventRecorderFile : public DrawEventRecorderPrivate { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawEventRecorderFile) DrawEventRecorderFile(const char *aFilename); ~DrawEventRecorderFile(); diff --git a/gfx/2d/DrawTargetCG.cpp b/gfx/2d/DrawTargetCG.cpp index 2ea7d01ba848..14ff533e08a9 100644 --- a/gfx/2d/DrawTargetCG.cpp +++ b/gfx/2d/DrawTargetCG.cpp @@ -351,6 +351,7 @@ static CGColorRef ColorToCGColor(CGColorSpaceRef aColorSpace, const Color& aColo class GradientStopsCG : public GradientStops { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsCG) //XXX: The skia backend uses a vector and passes in aNumStops. It should do better GradientStopsCG(GradientStop* aStops, uint32_t aNumStops, ExtendMode aExtendMode) { diff --git a/gfx/2d/DrawTargetCG.h b/gfx/2d/DrawTargetCG.h index d7cf4f88c70e..fc94465e53f6 100644 --- a/gfx/2d/DrawTargetCG.h +++ b/gfx/2d/DrawTargetCG.h @@ -95,6 +95,7 @@ SetStrokeOptions(CGContextRef cg, const StrokeOptions &aStrokeOptions) class DrawTargetCG : public DrawTarget { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetCG) friend class BorrowedCGContext; DrawTargetCG(); virtual ~DrawTargetCG(); diff --git a/gfx/2d/DrawTargetCairo.h b/gfx/2d/DrawTargetCairo.h index 23773f0338a0..a5b67fc29405 100644 --- a/gfx/2d/DrawTargetCairo.h +++ b/gfx/2d/DrawTargetCairo.h @@ -20,6 +20,7 @@ class SourceSurfaceCairo; class GradientStopsCairo : public GradientStops { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsCairo) GradientStopsCairo(GradientStop* aStops, uint32_t aNumStops, ExtendMode aExtendMode) : mExtendMode(aExtendMode) @@ -51,6 +52,7 @@ class GradientStopsCairo : public GradientStops class DrawTargetCairo : public DrawTarget { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetCairo) friend class BorrowedCairoContext; DrawTargetCairo(); diff --git a/gfx/2d/DrawTargetD2D.h b/gfx/2d/DrawTargetD2D.h index c25812844f57..ef08cbda5fe3 100644 --- a/gfx/2d/DrawTargetD2D.h +++ b/gfx/2d/DrawTargetD2D.h @@ -43,6 +43,7 @@ struct PrivateD3D10DataD2D class DrawTargetD2D : public DrawTarget { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetD2D) DrawTargetD2D(); virtual ~DrawTargetD2D(); diff --git a/gfx/2d/DrawTargetD2D1.h b/gfx/2d/DrawTargetD2D1.h index 2c40918f8aee..c2105054e1e1 100644 --- a/gfx/2d/DrawTargetD2D1.h +++ b/gfx/2d/DrawTargetD2D1.h @@ -35,6 +35,7 @@ const int32_t kLayerCacheSize1 = 5; class DrawTargetD2D1 : public DrawTarget { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetD2D1) DrawTargetD2D1(); virtual ~DrawTargetD2D1(); diff --git a/gfx/2d/DrawTargetDual.h b/gfx/2d/DrawTargetDual.h index 549a40966a45..6093c9e231a0 100644 --- a/gfx/2d/DrawTargetDual.h +++ b/gfx/2d/DrawTargetDual.h @@ -35,6 +35,7 @@ namespace gfx { class DrawTargetDual : public DrawTarget { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetDual) DrawTargetDual(DrawTarget *aA, DrawTarget *aB) : mA(aA) , mB(aB) diff --git a/gfx/2d/DrawTargetRecording.cpp b/gfx/2d/DrawTargetRecording.cpp index 865a4e62ec27..4add98dd519a 100644 --- a/gfx/2d/DrawTargetRecording.cpp +++ b/gfx/2d/DrawTargetRecording.cpp @@ -17,6 +17,7 @@ namespace gfx { class SourceSurfaceRecording : public SourceSurface { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceRecording) SourceSurfaceRecording(SourceSurface *aFinalSurface, DrawEventRecorderPrivate *aRecorder) : mFinalSurface(aFinalSurface), mRecorder(aRecorder) { @@ -39,6 +40,7 @@ public: class GradientStopsRecording : public GradientStops { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsRecording) GradientStopsRecording(GradientStops *aFinalGradientStops, DrawEventRecorderPrivate *aRecorder) : mFinalGradientStops(aFinalGradientStops), mRecorder(aRecorder) { @@ -78,6 +80,7 @@ GetGradientStops(GradientStops *aStops) class FilterNodeRecording : public FilterNode { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeRecording) using FilterNode::SetAttribute; FilterNodeRecording(FilterNode *aFinalFilterNode, DrawEventRecorderPrivate *aRecorder) diff --git a/gfx/2d/DrawTargetRecording.h b/gfx/2d/DrawTargetRecording.h index db223c8b34b2..c05d775f02da 100644 --- a/gfx/2d/DrawTargetRecording.h +++ b/gfx/2d/DrawTargetRecording.h @@ -15,6 +15,7 @@ namespace gfx { class DrawTargetRecording : public DrawTarget { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetRecording) DrawTargetRecording(DrawEventRecorder *aRecorder, DrawTarget *aDT, bool aHasData = false); ~DrawTargetRecording(); diff --git a/gfx/2d/DrawTargetSkia.cpp b/gfx/2d/DrawTargetSkia.cpp index 4ab6a14ccc2d..2edec2f6ad99 100644 --- a/gfx/2d/DrawTargetSkia.cpp +++ b/gfx/2d/DrawTargetSkia.cpp @@ -36,6 +36,7 @@ namespace gfx { class GradientStopsSkia : public GradientStops { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsSkia) GradientStopsSkia(const std::vector& aStops, uint32_t aNumStops, ExtendMode aExtendMode) : mCount(aNumStops) , mExtendMode(aExtendMode) diff --git a/gfx/2d/DrawTargetSkia.h b/gfx/2d/DrawTargetSkia.h index 0b9548f04df1..4970048d5134 100644 --- a/gfx/2d/DrawTargetSkia.h +++ b/gfx/2d/DrawTargetSkia.h @@ -26,6 +26,7 @@ class SourceSurfaceSkia; class DrawTargetSkia : public DrawTarget { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DrawTargetSkia) DrawTargetSkia(); virtual ~DrawTargetSkia(); diff --git a/gfx/2d/FilterNodeD2D1.h b/gfx/2d/FilterNodeD2D1.h index 4e7a9f8a43f8..c225f51263a5 100644 --- a/gfx/2d/FilterNodeD2D1.h +++ b/gfx/2d/FilterNodeD2D1.h @@ -17,6 +17,7 @@ namespace gfx { class FilterNodeD2D1 : public FilterNode { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeD2D1) static TemporaryRef Create(DrawTarget* aDT, ID2D1DeviceContext *aDC, FilterType aType); FilterNodeD2D1(DrawTarget* aDT, ID2D1Effect *aEffect, FilterType aType) @@ -65,6 +66,7 @@ protected: class FilterNodeConvolveD2D1 : public FilterNodeD2D1 { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeConvolveD2D1) FilterNodeConvolveD2D1(DrawTarget *aDT, ID2D1DeviceContext *aDC); virtual void SetInput(uint32_t aIndex, SourceSurface *aSurface); @@ -95,6 +97,7 @@ private: class FilterNodeComponentTransferD2D1 : public FilterNodeD2D1 { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeComponentTransferD2D1) FilterNodeComponentTransferD2D1(DrawTarget *aDT, ID2D1DeviceContext *aDC, ID2D1Effect *aEffect, FilterType aType); protected: diff --git a/gfx/2d/FilterNodeSoftware.h b/gfx/2d/FilterNodeSoftware.h index 16f6053c9580..dfb0d51ec438 100644 --- a/gfx/2d/FilterNodeSoftware.h +++ b/gfx/2d/FilterNodeSoftware.h @@ -38,6 +38,7 @@ class FilterNodeSoftware : public FilterNode, public FilterInvalidationListener { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeSoftware) virtual ~FilterNodeSoftware(); // Factory method, intended to be called from DrawTarget*::CreateFilter. @@ -217,6 +218,7 @@ protected: class FilterNodeTransformSoftware : public FilterNodeSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeTransformSoftware) FilterNodeTransformSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "Transform"; } using FilterNodeSoftware::SetAttribute; @@ -238,6 +240,7 @@ private: class FilterNodeBlendSoftware : public FilterNodeSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeBlendSoftware) FilterNodeBlendSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "Blend"; } using FilterNodeSoftware::SetAttribute; @@ -256,6 +259,7 @@ private: class FilterNodeMorphologySoftware : public FilterNodeSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeMorphologySoftware) FilterNodeMorphologySoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "Morphology"; } using FilterNodeSoftware::SetAttribute; @@ -276,6 +280,7 @@ private: class FilterNodeColorMatrixSoftware : public FilterNodeSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeColorMatrixSoftware) virtual const char* GetName() MOZ_OVERRIDE { return "ColorMatrix"; } using FilterNodeSoftware::SetAttribute; virtual void SetAttribute(uint32_t aIndex, const Matrix5x4 &aMatrix) MOZ_OVERRIDE; @@ -295,6 +300,7 @@ private: class FilterNodeFloodSoftware : public FilterNodeSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeFloodSoftware) virtual const char* GetName() MOZ_OVERRIDE { return "Flood"; } using FilterNodeSoftware::SetAttribute; virtual void SetAttribute(uint32_t aIndex, const Color &aColor) MOZ_OVERRIDE; @@ -311,6 +317,7 @@ private: class FilterNodeTileSoftware : public FilterNodeSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeTileSoftware) virtual const char* GetName() MOZ_OVERRIDE { return "Tile"; } using FilterNodeSoftware::SetAttribute; virtual void SetAttribute(uint32_t aIndex, const IntRect &aSourceRect) MOZ_OVERRIDE; @@ -331,6 +338,7 @@ private: class FilterNodeComponentTransferSoftware : public FilterNodeSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeComponentTransferSoftware) FilterNodeComponentTransferSoftware(); using FilterNodeSoftware::SetAttribute; @@ -354,6 +362,7 @@ protected: class FilterNodeTableTransferSoftware : public FilterNodeComponentTransferSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeTableTransferSoftware) virtual const char* GetName() MOZ_OVERRIDE { return "TableTransfer"; } using FilterNodeComponentTransferSoftware::SetAttribute; virtual void SetAttribute(uint32_t aIndex, const Float* aFloat, uint32_t aSize) MOZ_OVERRIDE; @@ -373,6 +382,7 @@ private: class FilterNodeDiscreteTransferSoftware : public FilterNodeComponentTransferSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeDiscreteTransferSoftware) virtual const char* GetName() MOZ_OVERRIDE { return "DiscreteTransfer"; } using FilterNodeComponentTransferSoftware::SetAttribute; virtual void SetAttribute(uint32_t aIndex, const Float* aFloat, uint32_t aSize) MOZ_OVERRIDE; @@ -392,6 +402,7 @@ private: class FilterNodeLinearTransferSoftware : public FilterNodeComponentTransferSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeLinearTransformSoftware) FilterNodeLinearTransferSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "LinearTransfer"; } using FilterNodeComponentTransferSoftware::SetAttribute; @@ -416,6 +427,7 @@ private: class FilterNodeGammaTransferSoftware : public FilterNodeComponentTransferSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeGammaTransferSoftware) FilterNodeGammaTransferSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "GammaTransfer"; } using FilterNodeComponentTransferSoftware::SetAttribute; @@ -444,6 +456,7 @@ private: class FilterNodeConvolveMatrixSoftware : public FilterNodeSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeConvolveMatrixSoftware) FilterNodeConvolveMatrixSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "ConvolveMatrix"; } using FilterNodeSoftware::SetAttribute; @@ -485,6 +498,7 @@ private: class FilterNodeDisplacementMapSoftware : public FilterNodeSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeDisplacementMapSoftware) FilterNodeDisplacementMapSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "DisplacementMap"; } using FilterNodeSoftware::SetAttribute; @@ -508,6 +522,7 @@ private: class FilterNodeTurbulenceSoftware : public FilterNodeSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeTurbulenceSoftware) FilterNodeTurbulenceSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "Turbulence"; } using FilterNodeSoftware::SetAttribute; @@ -533,6 +548,7 @@ private: class FilterNodeArithmeticCombineSoftware : public FilterNodeSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeArithmeticCombineSoftware) FilterNodeArithmeticCombineSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "ArithmeticCombine"; } using FilterNodeSoftware::SetAttribute; @@ -554,6 +570,7 @@ private: class FilterNodeCompositeSoftware : public FilterNodeSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeCompositeSoftware) FilterNodeCompositeSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "Composite"; } using FilterNodeSoftware::SetAttribute; @@ -573,6 +590,8 @@ private: // FilterNodeDirectionalBlurSoftware. class FilterNodeBlurXYSoftware : public FilterNodeSoftware { +public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeBlurXYSoftware) protected: virtual TemporaryRef Render(const IntRect& aRect) MOZ_OVERRIDE; virtual IntRect GetOutputRectInRect(const IntRect& aRect) MOZ_OVERRIDE; @@ -587,6 +606,7 @@ protected: class FilterNodeGaussianBlurSoftware : public FilterNodeBlurXYSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeGaussianBlurSoftware) FilterNodeGaussianBlurSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "GaussianBlur"; } using FilterNodeSoftware::SetAttribute; @@ -602,6 +622,7 @@ private: class FilterNodeDirectionalBlurSoftware : public FilterNodeBlurXYSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeDirectionalBlurSoftware) FilterNodeDirectionalBlurSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "DirectionalBlur"; } using FilterNodeSoftware::SetAttribute; @@ -619,6 +640,7 @@ private: class FilterNodeCropSoftware : public FilterNodeSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeCropSoftware) virtual const char* GetName() MOZ_OVERRIDE { return "Crop"; } using FilterNodeSoftware::SetAttribute; virtual void SetAttribute(uint32_t aIndex, const Rect &aSourceRect) MOZ_OVERRIDE; @@ -636,6 +658,7 @@ private: class FilterNodePremultiplySoftware : public FilterNodeSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodePremultiplySoftware) virtual const char* GetName() MOZ_OVERRIDE { return "Premultiply"; } protected: virtual TemporaryRef Render(const IntRect& aRect) MOZ_OVERRIDE; @@ -647,6 +670,7 @@ protected: class FilterNodeUnpremultiplySoftware : public FilterNodeSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeUnpremultiplySoftware) virtual const char* GetName() MOZ_OVERRIDE { return "Unpremultiply"; } protected: virtual TemporaryRef Render(const IntRect& aRect) MOZ_OVERRIDE; @@ -659,6 +683,7 @@ template class FilterNodeLightingSoftware : public FilterNodeSoftware { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNodeLightingSoftware) FilterNodeLightingSoftware(); virtual const char* GetName() MOZ_OVERRIDE { return "Lighting"; } using FilterNodeSoftware::SetAttribute; diff --git a/gfx/2d/Filters.h b/gfx/2d/Filters.h index a0803d72e080..80062350bdba 100644 --- a/gfx/2d/Filters.h +++ b/gfx/2d/Filters.h @@ -466,7 +466,7 @@ enum UnpremultiplyInputs class FilterNode : public RefCounted { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(FilterMode) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FilterNode) virtual ~FilterNode() {} virtual FilterBackend GetBackendType() = 0; diff --git a/gfx/2d/GradientStopsD2D.h b/gfx/2d/GradientStopsD2D.h index 9e6f351bc54d..e06bfa05e17b 100644 --- a/gfx/2d/GradientStopsD2D.h +++ b/gfx/2d/GradientStopsD2D.h @@ -16,6 +16,7 @@ namespace gfx { class GradientStopsD2D : public GradientStops { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GradientStopsD2D) GradientStopsD2D(ID2D1GradientStopCollection *aStopCollection) : mStopCollection(aStopCollection) {} diff --git a/gfx/2d/MacIOSurface.h b/gfx/2d/MacIOSurface.h index e4df5dc75c76..c5ee347f7cef 100644 --- a/gfx/2d/MacIOSurface.h +++ b/gfx/2d/MacIOSurface.h @@ -62,7 +62,7 @@ CGContextType GetContextType(CGContextRef ref); class MacIOSurface : public mozilla::RefCounted { public: - MOZ_DECLARE_REFCOUNTED_TYPENAME(MacIOSurface) + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(MacIOSurface) typedef mozilla::gfx::SourceSurface SourceSurface; static mozilla::TemporaryRef CreateIOSurface(int aWidth, int aHeight, @@ -75,7 +75,7 @@ public: MacIOSurface(const void *aIOSurfacePtr, double aContentsScaleFactor = 1.0, bool aHasAlpha = true) : mIOSurfacePtr(aIOSurfacePtr), mContentsScaleFactor(aContentsScaleFactor), mHasAlpha(aHasAlpha) {} - ~MacIOSurface(); + virtual ~MacIOSurface(); IOSurfaceID GetIOSurfaceID(); void *GetBaseAddress(); // GetWidth() and GetHeight() return values in "display pixels". A @@ -112,6 +112,7 @@ private: class MacIOSurfaceLib: public MacIOSurface { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(MacIOSurfaceLib) static void *sIOSurfaceFramework; static void *sOpenGLFramework; static void *sCoreGraphicsFramework; diff --git a/gfx/2d/PathAnalysis.h b/gfx/2d/PathAnalysis.h index fc6b1a214f9a..6b9b33f89007 100644 --- a/gfx/2d/PathAnalysis.h +++ b/gfx/2d/PathAnalysis.h @@ -23,6 +23,7 @@ struct FlatPathOp class FlattenedPath : public PathSink { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(FlattenedPath) FlattenedPath() : mCachedLength(0) , mCalculatedLength(false) { diff --git a/gfx/2d/PathCG.h b/gfx/2d/PathCG.h index 131f2efce922..45d13d66ed1b 100644 --- a/gfx/2d/PathCG.h +++ b/gfx/2d/PathCG.h @@ -17,6 +17,7 @@ class PathCG; class PathBuilderCG : public PathBuilder { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathBuilderCG) // absorbs a reference of aPath PathBuilderCG(CGMutablePathRef aPath, FillRule aFillRule) : mFillRule(aFillRule) @@ -61,6 +62,7 @@ private: class PathCG : public Path { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathCG) PathCG(CGMutablePathRef aPath, FillRule aFillRule) : mPath(aPath) , mFillRule(aFillRule) diff --git a/gfx/2d/PathCairo.h b/gfx/2d/PathCairo.h index 5aa1ecfbca2c..784306a72324 100644 --- a/gfx/2d/PathCairo.h +++ b/gfx/2d/PathCairo.h @@ -19,6 +19,7 @@ class PathCairo; class PathBuilderCairo : public PathBuilder { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathBuilderCairo) PathBuilderCairo(FillRule aFillRule); virtual void MoveTo(const Point &aPoint); @@ -48,6 +49,7 @@ private: // data class PathCairo : public Path { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathCairo) PathCairo(FillRule aFillRule, std::vector &aPathData, const Point &aCurrentPoint); PathCairo(cairo_t *aContext); ~PathCairo(); diff --git a/gfx/2d/PathD2D.h b/gfx/2d/PathD2D.h index 7f42a9c88de6..d27f1746f49c 100644 --- a/gfx/2d/PathD2D.h +++ b/gfx/2d/PathD2D.h @@ -18,6 +18,7 @@ class PathD2D; class PathBuilderD2D : public PathBuilder { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathBuilderD2D) PathBuilderD2D(ID2D1GeometrySink *aSink, ID2D1PathGeometry *aGeom, FillRule aFillRule) : mSink(aSink) , mGeometry(aGeom) @@ -60,6 +61,7 @@ private: class PathD2D : public Path { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathD2D) PathD2D(ID2D1PathGeometry *aGeometry, bool aEndedActive, const Point &aEndPoint, FillRule aFillRule) : mGeometry(aGeometry) diff --git a/gfx/2d/PathRecording.h b/gfx/2d/PathRecording.h index a3bf5072eaaf..97faa403c726 100644 --- a/gfx/2d/PathRecording.h +++ b/gfx/2d/PathRecording.h @@ -37,6 +37,7 @@ class DrawEventRecorderPrivate; class PathBuilderRecording : public PathBuilder { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathBuilderRecording) PathBuilderRecording(PathBuilder *aBuilder, FillRule aFillRule) : mPathBuilder(aBuilder), mFillRule(aFillRule) { @@ -82,6 +83,7 @@ private: class PathRecording : public Path { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathRecording) PathRecording(Path *aPath, const std::vector aOps, FillRule aFillRule) : mPath(aPath), mPathOps(aOps), mFillRule(aFillRule) { diff --git a/gfx/2d/PathSkia.h b/gfx/2d/PathSkia.h index 8b7777c64dfe..3a1ea808f8ab 100644 --- a/gfx/2d/PathSkia.h +++ b/gfx/2d/PathSkia.h @@ -17,6 +17,7 @@ class PathSkia; class PathBuilderSkia : public PathBuilder { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathBuilderSkia) PathBuilderSkia(const Matrix& aTransform, const SkPath& aPath, FillRule aFillRule); PathBuilderSkia(FillRule aFillRule); @@ -46,6 +47,7 @@ private: class PathSkia : public Path { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(PathSkia) PathSkia(SkPath& aPath, FillRule aFillRule) : mFillRule(aFillRule) { diff --git a/gfx/2d/ScaledFontBase.h b/gfx/2d/ScaledFontBase.h index 92b912f5c840..8ee4808a3274 100644 --- a/gfx/2d/ScaledFontBase.h +++ b/gfx/2d/ScaledFontBase.h @@ -29,6 +29,7 @@ namespace gfx { class ScaledFontBase : public ScaledFont { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontBase) ScaledFontBase(Float aSize); virtual ~ScaledFontBase(); diff --git a/gfx/2d/ScaledFontCairo.h b/gfx/2d/ScaledFontCairo.h index 30bec86c08eb..9f4d227aed0c 100644 --- a/gfx/2d/ScaledFontCairo.h +++ b/gfx/2d/ScaledFontCairo.h @@ -16,6 +16,7 @@ namespace gfx { class ScaledFontCairo : public ScaledFontBase { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontCairo) ScaledFontCairo(cairo_scaled_font_t* aScaledFont, Float aSize); @@ -32,6 +33,7 @@ public: class GlyphRenderingOptionsCairo : public GlyphRenderingOptions { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GlyphRenderingOptionsCairo) GlyphRenderingOptionsCairo() : mHinting(FontHinting::NORMAL) , mAutoHinting(false) diff --git a/gfx/2d/ScaledFontDWrite.h b/gfx/2d/ScaledFontDWrite.h index 65d73ebc8cee..69f9e0df1831 100644 --- a/gfx/2d/ScaledFontDWrite.h +++ b/gfx/2d/ScaledFontDWrite.h @@ -17,6 +17,7 @@ namespace gfx { class ScaledFontDWrite MOZ_FINAL : public ScaledFontBase { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontDwrite) ScaledFontDWrite(IDWriteFontFace *aFont, Float aSize) : mFontFace(aFont) , ScaledFontBase(aSize) @@ -48,6 +49,7 @@ public: class GlyphRenderingOptionsDWrite : public GlyphRenderingOptions { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GlyphRenderingOptionsDWrite) GlyphRenderingOptionsDWrite(IDWriteRenderingParams *aParams) : mParams(aParams) { diff --git a/gfx/2d/ScaledFontMac.h b/gfx/2d/ScaledFontMac.h index e09a1175b212..03c68add6635 100644 --- a/gfx/2d/ScaledFontMac.h +++ b/gfx/2d/ScaledFontMac.h @@ -17,6 +17,7 @@ namespace gfx { class ScaledFontMac : public ScaledFontBase { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontMac) ScaledFontMac(CGFontRef aFont, Float aSize); virtual ~ScaledFontMac(); diff --git a/gfx/2d/ScaledFontWin.h b/gfx/2d/ScaledFontWin.h index 4edbe5cc4c3a..20c95ed3db0a 100644 --- a/gfx/2d/ScaledFontWin.h +++ b/gfx/2d/ScaledFontWin.h @@ -15,6 +15,7 @@ namespace gfx { class ScaledFontWin : public ScaledFontBase { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(ScaledFontWin) ScaledFontWin(LOGFONT* aFont, Float aSize); virtual FontType GetType() const { return FontType::GDI; } diff --git a/gfx/2d/SourceSurfaceCG.h b/gfx/2d/SourceSurfaceCG.h index 10d7fbcd4526..d908346c7370 100644 --- a/gfx/2d/SourceSurfaceCG.h +++ b/gfx/2d/SourceSurfaceCG.h @@ -26,6 +26,7 @@ class DrawTargetCG; class SourceSurfaceCG : public SourceSurface { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceCG) SourceSurfaceCG() {} SourceSurfaceCG(CGImageRef aImage) : mImage(aImage) {} ~SourceSurfaceCG(); @@ -54,6 +55,7 @@ private: class DataSourceSurfaceCG : public DataSourceSurface { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceCG) DataSourceSurfaceCG() {} DataSourceSurfaceCG(CGImageRef aImage); ~DataSourceSurfaceCG(); @@ -88,6 +90,7 @@ private: class SourceSurfaceCGContext : public DataSourceSurface { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceCGContext) virtual void DrawTargetWillChange() = 0; virtual CGImageRef GetImage() = 0; }; @@ -95,6 +98,7 @@ public: class SourceSurfaceCGBitmapContext : public SourceSurfaceCGContext { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceCGBitmapContext) SourceSurfaceCGBitmapContext(DrawTargetCG *); ~SourceSurfaceCGBitmapContext(); @@ -150,6 +154,7 @@ private: class SourceSurfaceCGIOSurfaceContext : public SourceSurfaceCGContext { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceCGIOSurfaceContext) SourceSurfaceCGIOSurfaceContext(DrawTargetCG *); ~SourceSurfaceCGIOSurfaceContext(); diff --git a/gfx/2d/SourceSurfaceCairo.h b/gfx/2d/SourceSurfaceCairo.h index bb730d9105a2..093b666cb3f6 100644 --- a/gfx/2d/SourceSurfaceCairo.h +++ b/gfx/2d/SourceSurfaceCairo.h @@ -16,6 +16,7 @@ class DrawTargetCairo; class SourceSurfaceCairo : public SourceSurface { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceCairo) // Create a SourceSurfaceCairo. The surface will not be copied, but simply // referenced. // If aDrawTarget is non-nullptr, it is assumed that this is a snapshot source @@ -47,6 +48,7 @@ private: // data class DataSourceSurfaceCairo : public DataSourceSurface { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceCairo) DataSourceSurfaceCairo(cairo_surface_t* imageSurf); virtual ~DataSourceSurfaceCairo(); virtual unsigned char *GetData(); diff --git a/gfx/2d/SourceSurfaceD2D.h b/gfx/2d/SourceSurfaceD2D.h index 49f26a39d8a0..c2622d76c3a6 100644 --- a/gfx/2d/SourceSurfaceD2D.h +++ b/gfx/2d/SourceSurfaceD2D.h @@ -18,6 +18,7 @@ class DataSourceSurfaceD2D; class SourceSurfaceD2D : public SourceSurface { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceD2D) SourceSurfaceD2D(); ~SourceSurfaceD2D(); @@ -55,6 +56,7 @@ private: class DataSourceSurfaceD2D : public DataSourceSurface { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceD2D) DataSourceSurfaceD2D(SourceSurfaceD2D* aSourceSurface); virtual ~DataSourceSurfaceD2D(); diff --git a/gfx/2d/SourceSurfaceD2D1.h b/gfx/2d/SourceSurfaceD2D1.h index 7e6155a53ba4..d0b0090341ff 100644 --- a/gfx/2d/SourceSurfaceD2D1.h +++ b/gfx/2d/SourceSurfaceD2D1.h @@ -20,6 +20,7 @@ class DrawTargetD2D1; class SourceSurfaceD2D1 : public SourceSurface { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceD2D1) SourceSurfaceD2D1(ID2D1Image* aImage, ID2D1DeviceContext *aDC, SurfaceFormat aFormat, const IntSize &aSize, DrawTargetD2D1 *aDT = nullptr); @@ -62,6 +63,7 @@ private: class DataSourceSurfaceD2D1 : public DataSourceSurface { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceD2D1) DataSourceSurfaceD2D1(ID2D1Bitmap1 *aMappableBitmap, SurfaceFormat aFormat); ~DataSourceSurfaceD2D1(); diff --git a/gfx/2d/SourceSurfaceD2DTarget.h b/gfx/2d/SourceSurfaceD2DTarget.h index 27f51b2155ba..d48900e6678e 100644 --- a/gfx/2d/SourceSurfaceD2DTarget.h +++ b/gfx/2d/SourceSurfaceD2DTarget.h @@ -19,6 +19,7 @@ class DrawTargetD2D; class SourceSurfaceD2DTarget : public SourceSurface { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceD2DTarget) SourceSurfaceD2DTarget(DrawTargetD2D* aDrawTarget, ID3D10Texture2D* aTexture, SurfaceFormat aFormat); ~SourceSurfaceD2DTarget(); @@ -60,6 +61,7 @@ private: class DataSourceSurfaceD2DTarget : public DataSourceSurface { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceD2DTarget) DataSourceSurfaceD2DTarget(SurfaceFormat aFormat); ~DataSourceSurfaceD2DTarget(); diff --git a/gfx/2d/SourceSurfaceDual.h b/gfx/2d/SourceSurfaceDual.h index 04eb9d29a951..aaa85dcc8682 100644 --- a/gfx/2d/SourceSurfaceDual.h +++ b/gfx/2d/SourceSurfaceDual.h @@ -17,6 +17,7 @@ class DualPattern; class SourceSurfaceDual : public SourceSurface { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SourceSurfaceDual) SourceSurfaceDual(DrawTarget *aDTA, DrawTarget *aDTB) : mA(aDTA->Snapshot()) , mB(aDTB->Snapshot()) diff --git a/gfx/2d/SourceSurfaceRawData.h b/gfx/2d/SourceSurfaceRawData.h index ab41368a08ad..9d1e7d6e0363 100644 --- a/gfx/2d/SourceSurfaceRawData.h +++ b/gfx/2d/SourceSurfaceRawData.h @@ -15,6 +15,7 @@ namespace gfx { class SourceSurfaceRawData : public DataSourceSurface { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceRawData) SourceSurfaceRawData() {} ~SourceSurfaceRawData() { if(mOwnData) delete [] mRawData; } @@ -42,6 +43,7 @@ private: class SourceSurfaceAlignedRawData : public DataSourceSurface { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceAlignedRawData) SourceSurfaceAlignedRawData() {} virtual uint8_t *GetData() { return mArray; } diff --git a/gfx/2d/SourceSurfaceSkia.h b/gfx/2d/SourceSurfaceSkia.h index 42d1cdc886ac..74fc279c8fb9 100644 --- a/gfx/2d/SourceSurfaceSkia.h +++ b/gfx/2d/SourceSurfaceSkia.h @@ -19,6 +19,7 @@ class DrawTargetSkia; class SourceSurfaceSkia : public DataSourceSurface { public: + MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(DataSourceSurfaceSkia) SourceSurfaceSkia(); ~SourceSurfaceSkia(); diff --git a/mfbt/RefPtr.h b/mfbt/RefPtr.h index eaf8b49aa837..912623ebee70 100644 --- a/mfbt/RefPtr.h +++ b/mfbt/RefPtr.h @@ -104,6 +104,9 @@ class RefCounted #define MOZ_DECLARE_REFCOUNTED_TYPENAME(T) \ const char* typeName() const { return #T; } +#define MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(T) \ + virtual const char* typeName() const { return #T; } + } template From 39fc9361f6c18089db58238052a4368107609640 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Mon, 24 Feb 2014 08:30:25 -0500 Subject: [PATCH 03/48] Bug 975740 - Port WIN32_EXE_LDFLAGS to moz.build; r=mshal --- b2g/app/Makefile.in | 6 ------ b2g/app/moz.build | 4 ++++ browser/app/Makefile.in | 6 ------ browser/app/moz.build | 5 +++++ dom/plugins/ipc/hangui/Makefile.in | 4 ---- dom/plugins/ipc/hangui/moz.build | 3 +++ ipc/app/Makefile.in | 6 ------ ipc/app/moz.build | 5 +++++ ipc/ipdl/test/cxx/app/Makefile.in | 4 ---- ipc/ipdl/test/cxx/app/moz.build | 2 ++ js/xpconnect/shell/Makefile.in | 6 ------ js/xpconnect/shell/moz.build | 4 ++++ python/mozbuild/mozbuild/frontend/emitter.py | 1 + python/mozbuild/mozbuild/frontend/sandbox_symbols.py | 11 +++++++++++ .../test/backend/data/variable_passthru/moz.build | 1 + .../mozbuild/test/backend/test_recursivemake.py | 5 ++++- .../test/frontend/data/variable-passthru/moz.build | 1 + .../mozbuild/mozbuild/test/frontend/test_emitter.py | 1 + testing/tools/screenshot/Makefile.in | 4 ---- testing/tools/screenshot/moz.build | 2 ++ toolkit/components/maintenanceservice/Makefile.in | 4 ---- toolkit/components/maintenanceservice/moz.build | 4 +++- toolkit/mozapps/update/updater/Makefile.in | 4 ---- toolkit/mozapps/update/updater/moz.build | 4 +++- webapprt/win/Makefile.in | 6 ------ webapprt/win/moz.build | 5 +++++ xulrunner/app/Makefile.in | 6 ------ xulrunner/app/moz.build | 4 ++++ xulrunner/stub/Makefile.in | 4 ---- xulrunner/stub/moz.build | 3 +++ xulrunner/tools/redit/Makefile.in | 4 ---- xulrunner/tools/redit/moz.build | 2 ++ 32 files changed, 64 insertions(+), 67 deletions(-) diff --git a/b2g/app/Makefile.in b/b2g/app/Makefile.in index 6e13ef1d7c64..65fc7db3cafd 100644 --- a/b2g/app/Makefile.in +++ b/b2g/app/Makefile.in @@ -47,12 +47,6 @@ endif ifeq ($(OS_ARCH),WINNT) OS_LIBS += $(call EXPAND_LIBNAME,version) endif - -ifdef _MSC_VER -# Always enter a Windows program through wmain, whether or not we're -# a console application. -WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup -endif endif #LIBXUL_SDK UA_UPDATE_FILE = ua-update.json diff --git a/b2g/app/moz.build b/b2g/app/moz.build index c3587e98bea7..2d73d527552c 100644 --- a/b2g/app/moz.build +++ b/b2g/app/moz.build @@ -12,6 +12,10 @@ if not CONFIG['LIBXUL_SDK']: SOURCES += [ 'nsBrowserApp.cpp', ] + if CONFIG['_MSC_VER']: + # Always enter a Windows program through wmain, whether or not we're + # a console application. + WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] if CONFIG['ENABLE_MARIONETTE']: DEFINES['ENABLE_MARIONETTE'] = 1 diff --git a/browser/app/Makefile.in b/browser/app/Makefile.in index 6ae9bf496749..30953382ba37 100644 --- a/browser/app/Makefile.in +++ b/browser/app/Makefile.in @@ -54,12 +54,6 @@ NSDISTMODE = copy include $(topsrcdir)/config/config.mk -ifdef _MSC_VER -# Always enter a Windows program through wmain, whether or not we're -# a console application. -WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup -endif - ifeq ($(OS_ARCH),WINNT) RCINCLUDE = splash.rc # Rebuild firefox.exe if the manifest changes - it's included by splash.rc. diff --git a/browser/app/moz.build b/browser/app/moz.build index c19b905aa3a9..f4d2a047e691 100644 --- a/browser/app/moz.build +++ b/browser/app/moz.build @@ -32,3 +32,8 @@ LOCAL_INCLUDES += [ '/xpcom/base', '/xpcom/build', ] + +if CONFIG['_MSC_VER']: + # Always enter a Windows program through wmain, whether or not we're + # a console application. + WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] diff --git a/dom/plugins/ipc/hangui/Makefile.in b/dom/plugins/ipc/hangui/Makefile.in index 101c8a710db4..b4631dc739d8 100644 --- a/dom/plugins/ipc/hangui/Makefile.in +++ b/dom/plugins/ipc/hangui/Makefile.in @@ -13,7 +13,3 @@ STL_FLAGS = \ MOZ_GLUE_LDFLAGS = include $(topsrcdir)/config/rules.mk - -ifdef GNU_CC -WIN32_EXE_LDFLAGS = -municode -endif diff --git a/dom/plugins/ipc/hangui/moz.build b/dom/plugins/ipc/hangui/moz.build index 8197adf59dfe..90b72b762433 100644 --- a/dom/plugins/ipc/hangui/moz.build +++ b/dom/plugins/ipc/hangui/moz.build @@ -15,3 +15,6 @@ UNIFIED_SOURCES += [ include('/ipc/chromium/chromium-config.mozbuild') DEFINES['NS_NO_XPCOM'] = True + +if CONFIG['GNU_CC']: + WIN32_EXE_LDFLAGS += ['-municode'] diff --git a/ipc/app/Makefile.in b/ipc/app/Makefile.in index e3612f77c18f..74a177650098 100644 --- a/ipc/app/Makefile.in +++ b/ipc/app/Makefile.in @@ -36,12 +36,6 @@ NSDISTMODE = copy include $(topsrcdir)/config/config.mk -ifdef _MSC_VER -# Always enter a Windows program through wmain, whether or not we're -# a console application. -WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup -endif - include $(topsrcdir)/config/rules.mk LDFLAGS += $(MOZ_ALLOW_HEAP_EXECUTE_FLAGS) diff --git a/ipc/app/moz.build b/ipc/app/moz.build index 89ae81fdb62f..f8db2eb1f466 100644 --- a/ipc/app/moz.build +++ b/ipc/app/moz.build @@ -29,3 +29,8 @@ if CONFIG['MOZ_CONTENT_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT': '/security/sandbox', '/security/sandbox/chromium', ] + +if CONFIG['_MSC_VER']: + # Always enter a Windows program through wmain, whether or not we're + # a console application. + WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] diff --git a/ipc/ipdl/test/cxx/app/Makefile.in b/ipc/ipdl/test/cxx/app/Makefile.in index 61fbfe4a3c13..5b3c4d1c7e25 100644 --- a/ipc/ipdl/test/cxx/app/Makefile.in +++ b/ipc/ipdl/test/cxx/app/Makefile.in @@ -12,8 +12,4 @@ LIBS = \ include $(topsrcdir)/config/config.mk -ifdef _MSC_VER -WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup -endif - include $(topsrcdir)/config/rules.mk diff --git a/ipc/ipdl/test/cxx/app/moz.build b/ipc/ipdl/test/cxx/app/moz.build index 2b0de8cc535c..08d00a9943d8 100644 --- a/ipc/ipdl/test/cxx/app/moz.build +++ b/ipc/ipdl/test/cxx/app/moz.build @@ -16,3 +16,5 @@ LOCAL_INCLUDES += [ '/xpcom/base', ] +if CONFIG['_MSC_VER']: + WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] diff --git a/js/xpconnect/shell/Makefile.in b/js/xpconnect/shell/Makefile.in index 6bdf31634ea3..6cf727d5a232 100644 --- a/js/xpconnect/shell/Makefile.in +++ b/js/xpconnect/shell/Makefile.in @@ -21,12 +21,6 @@ endif include $(topsrcdir)/config/rules.mk -ifdef _MSC_VER -# Always enter a Windows program through wmain, whether or not we're -# a console application. -WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup -endif - ifdef MOZ_VTUNE CXXFLAGS += -IC:/Program\ Files/Intel/VTune/Analyzer/Include LIBS += C:/Program\ Files/Intel/VTune/Analyzer/Lib/VtuneApi.lib diff --git a/js/xpconnect/shell/moz.build b/js/xpconnect/shell/moz.build index 3eed79f00f6c..117f03db3705 100644 --- a/js/xpconnect/shell/moz.build +++ b/js/xpconnect/shell/moz.build @@ -32,3 +32,7 @@ LOCAL_INCLUDES += [ '/toolkit/xre', ] +if CONFIG['_MSC_VER']: + # Always enter a Windows program through wmain, whether or not we're + # a console application. + WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] diff --git a/python/mozbuild/mozbuild/frontend/emitter.py b/python/mozbuild/mozbuild/frontend/emitter.py index 3243ce02ea98..d87466054f8c 100644 --- a/python/mozbuild/mozbuild/frontend/emitter.py +++ b/python/mozbuild/mozbuild/frontend/emitter.py @@ -245,6 +245,7 @@ class TreeMetadataEmitter(LoggingMixin): 'CFLAGS', 'CXXFLAGS', 'LDFLAGS', + 'WIN32_EXE_LDFLAGS', ] for v in varlist: if v in sandbox and sandbox[v]: diff --git a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py index cc7b3a435393..0b6059fc2182 100644 --- a/python/mozbuild/mozbuild/frontend/sandbox_symbols.py +++ b/python/mozbuild/mozbuild/frontend/sandbox_symbols.py @@ -710,6 +710,17 @@ VARIABLES = { added to the linker's command line in the same order as they appear in the moz.build file. """, 'libs'), + + 'WIN32_EXE_LDFLAGS': (list, list, + """Flags passed to the linker when linking a Windows .exe executable + declared in this directory. + + Note that the ordering of flags matter here, these flags will be + added to the linker's command line in the same order as they + appear in the moz.build file. + + This variable only has an effect on Windows. + """, 'libs'), } # The set of functions exposed to the sandbox. diff --git a/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build b/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build index 959f8c96bb77..8b0b99bbc7df 100644 --- a/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build +++ b/python/mozbuild/mozbuild/test/backend/data/variable_passthru/moz.build @@ -45,3 +45,4 @@ USE_STATIC_LIBS = True CFLAGS += ['-fno-exceptions', '-w'] CXXFLAGS += ['-fcxx-exceptions', '-include foo.h'] LDFLAGS += ['-framework Foo', '-x'] +WIN32_EXE_LDFLAGS += ['-subsystem:console'] diff --git a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py index 837cc666ae6d..86519dbd7938 100644 --- a/python/mozbuild/mozbuild/test/backend/test_recursivemake.py +++ b/python/mozbuild/mozbuild/test/backend/test_recursivemake.py @@ -351,7 +351,10 @@ class TestRecursiveMakeBackend(BackendTester): 'LDFLAGS': [ 'LDFLAGS += -framework Foo', 'LDFLAGS += -x', - ] + ], + 'WIN32_EXE_LDFLAGS': [ + 'WIN32_EXE_LDFLAGS += -subsystem:console', + ], } for var, val in expected.items(): diff --git a/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build b/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build index c1f24eb31a6e..19df3d11418f 100644 --- a/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build +++ b/python/mozbuild/mozbuild/test/frontend/data/variable-passthru/moz.build @@ -51,3 +51,4 @@ USE_STATIC_LIBS = True CFLAGS += ['-fno-exceptions', '-w'] CXXFLAGS += ['-fcxx-exceptions', '-include foo.h'] LDFLAGS += ['-framework Foo', '-x'] +WIN32_EXE_LDFLAGS += ['-subsystem:console'] diff --git a/python/mozbuild/mozbuild/test/frontend/test_emitter.py b/python/mozbuild/mozbuild/test/frontend/test_emitter.py index 7f39fe20d690..730dea7a31a4 100644 --- a/python/mozbuild/mozbuild/test/frontend/test_emitter.py +++ b/python/mozbuild/mozbuild/test/frontend/test_emitter.py @@ -179,6 +179,7 @@ class TestEmitterBasic(unittest.TestCase): CFLAGS=['-fno-exceptions', '-w'], CXXFLAGS=['-fcxx-exceptions', '-include foo.h'], LDFLAGS=['-framework Foo', '-x'], + WIN32_EXE_LDFLAGS=['-subsystem:console'], ) variables = objs[0].variables diff --git a/testing/tools/screenshot/Makefile.in b/testing/tools/screenshot/Makefile.in index 29a8e6080d04..eee57a1d8e49 100644 --- a/testing/tools/screenshot/Makefile.in +++ b/testing/tools/screenshot/Makefile.in @@ -16,8 +16,4 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),windows) OS_LIBS += $(call EXPAND_LIBNAME,gdiplus) MOZ_GLUE_PROGRAM_LDFLAGS = -ifdef GNU_CC -WIN32_EXE_LDFLAGS = -municode -endif - endif # windows diff --git a/testing/tools/screenshot/moz.build b/testing/tools/screenshot/moz.build index fd11bb7f64ed..def2dafdd166 100644 --- a/testing/tools/screenshot/moz.build +++ b/testing/tools/screenshot/moz.build @@ -15,3 +15,5 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': 'win32-screenshot.cpp', ] USE_STATIC_LIBS = True + if CONFIG['GNU_CC']: + WIN32_EXE_FLAGS += ['-municode'] diff --git a/toolkit/components/maintenanceservice/Makefile.in b/toolkit/components/maintenanceservice/Makefile.in index 79a9d21b5ff2..46af5fbc8684 100644 --- a/toolkit/components/maintenanceservice/Makefile.in +++ b/toolkit/components/maintenanceservice/Makefile.in @@ -34,7 +34,3 @@ endif endif include $(topsrcdir)/config/rules.mk - -ifdef _MSC_VER -WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup -endif diff --git a/toolkit/components/maintenanceservice/moz.build b/toolkit/components/maintenanceservice/moz.build index 7fb2c7a70068..fa62779a7b9a 100644 --- a/toolkit/components/maintenanceservice/moz.build +++ b/toolkit/components/maintenanceservice/moz.build @@ -28,5 +28,7 @@ LOCAL_INCLUDES += [ '/toolkit/xre', ] - USE_STATIC_LIBS = True + +if CONFIG['_MSC_VER']: + WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] diff --git a/toolkit/mozapps/update/updater/Makefile.in b/toolkit/mozapps/update/updater/Makefile.in index 893f2fda477b..9a3eba91bcb0 100644 --- a/toolkit/mozapps/update/updater/Makefile.in +++ b/toolkit/mozapps/update/updater/Makefile.in @@ -56,10 +56,6 @@ endif include $(topsrcdir)/config/rules.mk -ifdef _MSC_VER -WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup -endif - ifdef MOZ_WIDGET_GTK libs:: updater.png $(NSINSTALL) -D $(DIST)/bin/icons diff --git a/toolkit/mozapps/update/updater/moz.build b/toolkit/mozapps/update/updater/moz.build index 70167074d443..031fb6a80878 100644 --- a/toolkit/mozapps/update/updater/moz.build +++ b/toolkit/mozapps/update/updater/moz.build @@ -64,9 +64,11 @@ LOCAL_INCLUDES += [ '/xpcom/glue', ] - DELAYLOAD_DLLS += [ 'crypt32.dll', 'userenv.dll', 'wsock32.dll', ] + +if CONFIG['_MSC_VER']: + WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] diff --git a/webapprt/win/Makefile.in b/webapprt/win/Makefile.in index de023f395f17..20cbae9a0cb4 100644 --- a/webapprt/win/Makefile.in +++ b/webapprt/win/Makefile.in @@ -28,12 +28,6 @@ SFX_MODULE = $(topsrcdir)/other-licenses/7zstub/firefox/7zSD.sfx APP_VERSION := $(shell cat $(topsrcdir)/browser/config/version.txt) DEFINES += -DAPP_VERSION=$(APP_VERSION) -ifdef _MSC_VER -# Always enter a Windows program through wmain, whether or not we're -# a console application. -WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup -endif - OS_LIBS += $(call EXPAND_LIBNAME,shell32) RCINCLUDE = webapprt.rc diff --git a/webapprt/win/moz.build b/webapprt/win/moz.build index f8654f993ad4..e9e6d53c0420 100644 --- a/webapprt/win/moz.build +++ b/webapprt/win/moz.build @@ -21,3 +21,8 @@ LOCAL_INCLUDES += [ '/xpcom/base', '/xpcom/build', ] + +if CONFIG['_MSC_VER']: + # Always enter a Windows program through wmain, whether or not we're + # a console application. + WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] diff --git a/xulrunner/app/Makefile.in b/xulrunner/app/Makefile.in index 3fb485eee466..a048a9b57a44 100644 --- a/xulrunner/app/Makefile.in +++ b/xulrunner/app/Makefile.in @@ -32,12 +32,6 @@ NSDISTMODE = copy include $(topsrcdir)/config/config.mk -ifdef _MSC_VER -# Always enter a Windows program through wmain, whether or not we're -# a console application. -WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup -endif - ifeq ($(OS_ARCH),WINNT) OS_LIBS += $(call EXPAND_LIBNAME,comctl32 comdlg32 uuid shell32 ole32 oleaut32 version winspool) RCINCLUDE = splash.rc diff --git a/xulrunner/app/moz.build b/xulrunner/app/moz.build index 3592f3b80c1f..15b8db98b08f 100644 --- a/xulrunner/app/moz.build +++ b/xulrunner/app/moz.build @@ -25,3 +25,7 @@ LOCAL_INCLUDES += [ '/xpcom/build', ] +if CONFIG['_MSC_VER']: + # Always enter a Windows program through wmain, whether or not we're + # a console application. + WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] diff --git a/xulrunner/stub/Makefile.in b/xulrunner/stub/Makefile.in index c02c8eb0b3e3..7387c44c9530 100644 --- a/xulrunner/stub/Makefile.in +++ b/xulrunner/stub/Makefile.in @@ -37,10 +37,6 @@ endif include $(topsrcdir)/config/config.mk -ifdef _MSC_VER -WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup -endif - include $(topsrcdir)/config/rules.mk ifeq ($(OS_ARCH),WINNT) diff --git a/xulrunner/stub/moz.build b/xulrunner/stub/moz.build index 699361171d44..23d98b090bf4 100644 --- a/xulrunner/stub/moz.build +++ b/xulrunner/stub/moz.build @@ -30,3 +30,6 @@ USE_STATIC_LIBS = True if CONFIG['OS_ARCH'] == 'WINNT': LOCAL_INCLUDES += ['/toolkit/xre'] + +if CONFIG['_MSC_VER']: + WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup'] diff --git a/xulrunner/tools/redit/Makefile.in b/xulrunner/tools/redit/Makefile.in index 54c99dcbb084..fd7b5a8fbd44 100644 --- a/xulrunner/tools/redit/Makefile.in +++ b/xulrunner/tools/redit/Makefile.in @@ -12,8 +12,4 @@ LIBS = \ $(XPCOM_STANDALONE_GLUE_LDOPTS) \ $(NULL) -ifdef GNU_CC -WIN32_EXE_LDFLAGS = -municode -endif - endif diff --git a/xulrunner/tools/redit/moz.build b/xulrunner/tools/redit/moz.build index 0eb0c94a938f..4b1ad889a07e 100644 --- a/xulrunner/tools/redit/moz.build +++ b/xulrunner/tools/redit/moz.build @@ -11,3 +11,5 @@ if CONFIG['OS_ARCH'] == 'WINNT': ] for var in ('WIN32_LEAN_AND_MEAN', 'UNICODE', '_UNICODE', 'XPCOM_GLUE'): DEFINES[var] = True + if CONFIG['GNU_CC']: + WIN32_EXE_LDFLAGS += ['-municode'] From 5971f5f9a42fb5f5cd3a79ecddc85b6db2b53e56 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Mon, 24 Feb 2014 08:31:58 -0500 Subject: [PATCH 04/48] Bug 976030 - Fix a typo in my patch for bug 898563. r=me and DONTBUILD because trivial Thanks to Maks Naumov's eagle eyes for spotting it. --- gfx/layers/ipc/AsyncPanZoomController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 462c786a74d4..59d0c33f2c72 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -1978,7 +1978,7 @@ void AsyncPanZoomController::TimeoutContentResponse() { void AsyncPanZoomController::UpdateZoomConstraints(const ZoomConstraints& aConstraints) { APZC_LOG("%p updating zoom constraints to %d %f %f\n", this, aConstraints.mAllowZoom, aConstraints.mMinZoom.scale, aConstraints.mMaxZoom.scale); - if (IsFloatNaN(aConstraints.mMinZoom.scale) || IsFloatNaN(aConstraints.mMinZoom.scale)) { + if (IsFloatNaN(aConstraints.mMinZoom.scale) || IsFloatNaN(aConstraints.mMaxZoom.scale)) { NS_WARNING("APZC received zoom constraints with NaN values; dropping...\n"); return; } From dbd09c5457f7a5fd1457ba874c3dd15572bcb02b Mon Sep 17 00:00:00 2001 From: Dan Minor Date: Mon, 24 Feb 2014 08:01:31 -0500 Subject: [PATCH 05/48] Bug 975403 - Support chunking in jit-test harness; r=terrence --- js/src/jit-test/jit_test.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/js/src/jit-test/jit_test.py b/js/src/jit-test/jit_test.py index 7d42cfeff763..c45e67e4af58 100755 --- a/js/src/jit-test/jit_test.py +++ b/js/src/jit-test/jit_test.py @@ -3,7 +3,7 @@ # 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/. -import os, posixpath, shlex, shutil, subprocess, sys, traceback +import math, os, posixpath, shlex, shutil, subprocess, sys, traceback def add_libdir_to_path(): from os.path import dirname, exists, join, realpath @@ -97,6 +97,10 @@ def main(argv): help='The location of libraries to push -- preferably stripped') op.add_option('--repeat', type=int, default=1, help='Repeat tests the given number of times.') + op.add_option('--this-chunk', type=int, default=1, + help='The test chunk to run.') + op.add_option('--total-chunks', type=int, default=1, + help='The total number of test chunks.') options, args = op.parse_args(argv) if len(args) < 1: @@ -160,6 +164,15 @@ def main(argv): if not options.run_slow: test_list = [ _ for _ in test_list if not _.slow ] + # If chunking is enabled, determine which tests are part of this chunk. + # This code was adapted from testing/mochitest/runtestsremote.py. + if options.total_chunks > 1: + total_tests = len(test_list) + tests_per_chunk = math.ceil(total_tests / float(options.total_chunks)) + start = int(round((options.this_chunk - 1) * tests_per_chunk)) + end = int(round(options.this_chunk * tests_per_chunk)) + test_list = test_list[start:end] + # The full test list is ready. Now create copies for each JIT configuration. job_list = [] if options.tbpl: From 520a4edf624cd35f2e3fd47f16d1f6e3d99cf6ba Mon Sep 17 00:00:00 2001 From: Rick Eyre Date: Fri, 21 Feb 2014 22:11:06 -0500 Subject: [PATCH 06/48] Bug 865407 - Part 8: Update vtt.js to latest version. r=rillian This completes the initial implementation of the processing algorithm. The algorithm doesn't support vertical text yet, but that's not a big issue since Firefox doesn't support it. --- content/media/webvtt/WebVTTParserWrapper.js | 2 +- content/media/webvtt/vtt.jsm | 546 +++++++++++++------- 2 files changed, 368 insertions(+), 180 deletions(-) diff --git a/content/media/webvtt/WebVTTParserWrapper.js b/content/media/webvtt/WebVTTParserWrapper.js index 3fa84abd1005..308efab78e46 100644 --- a/content/media/webvtt/WebVTTParserWrapper.js +++ b/content/media/webvtt/WebVTTParserWrapper.js @@ -52,7 +52,7 @@ WebVTTParserWrapper.prototype = processCues: function(window, cues, overlay) { - WebVTTParser.processCues(window, cues, null, overlay); + WebVTTParser.processCues(window, cues, overlay); }, classDescription: "Wrapper for the JS WebVTTParser (vtt.js)", diff --git a/content/media/webvtt/vtt.jsm b/content/media/webvtt/vtt.jsm index 37c621482d27..beb4b8e4b982 100644 --- a/content/media/webvtt/vtt.jsm +++ b/content/media/webvtt/vtt.jsm @@ -8,7 +8,7 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]; * Code below is vtt.js the JS WebVTTParser. * Current source code can be found at http://github.com/andreasgal/vtt.js * - * Code taken from commit d819872e198d051dfcebcfb7ecf260462c9a9c6f + * Code taken from commit b812cd783d4284de1bc6b0349b7bda151052a1df */ /** * Copyright 2013 vtt.js Contributors @@ -101,20 +101,18 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]; // Accept a setting if its a valid (signed) integer. integer: function(k, v) { if (/^-?\d+$/.test(v)) { // integer - this.set(k, parseInt(v, 10)); + // Only take values in the range of -1000 ~ 1000 + this.set(k, Math.min(Math.max(parseInt(v, 10), -1000), 1000)); } }, // Accept a setting if its a valid percentage. - percent: function(k, v, frac) { + percent: function(k, v) { var m; if ((m = v.match(/^([\d]{1,3})(\.[\d]*)?%$/))) { - v = v.replace("%", ""); - if (!m[2] || (m[2] && frac)) { - v = parseFloat(v); - if (v >= 0 && v <= 100) { - this.set(k, v); - return true; - } + v = parseFloat(v); + if (v >= 0 && v <= 100) { + this.set(k, v); + return true; } } return false; @@ -664,25 +662,59 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]; return ++count * -1; } - function BoundingBox() { + function StyleBox() { } - BoundingBox.prototype.applyStyles = function(styles) { - var div = this.div; + // Apply styles to a div. If there is no div passed then it defaults to the + // div on 'this'. + StyleBox.prototype.applyStyles = function(styles, div) { + div = div || this.div; Object.keys(styles).forEach(function(style) { div.style[style] = styles[style]; }); }; - BoundingBox.prototype.formatStyle = function(val, unit) { + StyleBox.prototype.formatStyle = function(val, unit) { return val === 0 ? 0 : val + unit; }; - function BasicBoundingBox(window, cue) { - BoundingBox.call(this); + // Constructs the computed display state of the cue (a div). Places the div + // into the overlay which should be a block level element (usually a div). + function CueStyleBox(window, cue, styleOptions) { + StyleBox.call(this); + this.cue = cue; - // Parse our cue's text into a DOM tree rooted at 'div'. - this.div = parseContent(window, cue.text); + // Parse our cue's text into a DOM tree rooted at 'cueDiv'. This div will + // have inline positioning and will function as the cue background box. + this.cueDiv = parseContent(window, cue.text); + this.applyStyles({ + color: "rgba(255, 255, 255, 1)", + backgroundColor: "rgba(0, 0, 0, 0.8)", + position: "relative", + left: 0, + right: 0, + top: 0, + bottom: 0, + display: "inline" + }, this.cueDiv); + + // Create an absolutely positioned div that will be used to position the cue + // div. Note, all WebVTT cue-setting alignments are equivalent to the CSS + // mirrors of them except "middle" which is "center" in CSS. + this.div = window.document.createElement("div"); + this.applyStyles({ + textAlign: cue.align === "middle" ? "center" : cue.align, + direction: determineBidi(this.cueDiv), + writingMode: cue.vertical === "" ? "horizontal-tb" + : cue.vertical === "lr" ? "vertical-lr" + : "vertical-rl", + unicodeBidi: "plaintext", + font: styleOptions.font, + whiteSpace: "pre-line", + position: "absolute" + }); + + this.div.appendChild(this.cueDiv); // Calculate the distance from the reference edge of the viewport to the text // position of the cue box. The reference edge will be resolved later when @@ -718,149 +750,277 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]; }); } - // All WebVTT cue-setting alignments are equivalent to the CSS mirrors of - // them except "middle" which is "center" in CSS. - this.applyStyles({ - "textAlign": cue.align === "middle" ? "center" : cue.align - }); - } - BasicBoundingBox.prototype = Object.create(BoundingBox.prototype); - BasicBoundingBox.prototype.constructor = BasicBoundingBox; - - const CUE_FONT_SIZE = 2.5; - const SCROLL_DURATION = 0.433; - const LINE_HEIGHT = 0.0533; - const REGION_FONT_SIZE = 1.3; - - // Constructs the computed display state of the cue (a div). Places the div - // into the overlay which should be a block level element (usually a div). - function CueBoundingBox(window, cue, overlay) { - BasicBoundingBox.call(this, window, cue); - this.applyStyles({ - direction: determineBidi(this.div), - writingMode: cue.vertical === "" ? "horizontal-tb" - : cue.vertical === "lr" ? "vertical-lr" - : "vertical-rl", - position: "absolute", - unicodeBidi: "plaintext", - fontSize: CUE_FONT_SIZE + "vh", - fontFamily: "sans-serif", - color: "rgba(255, 255, 255, 1)", - backgroundColor: "rgba(0, 0, 0, 0.8)", - whiteSpace: "pre-line" - }); - - // Append the div to the overlay so we can get the computed styles of the - // element in order to position for overlap avoidance. - overlay.appendChild(this.div); - - // Calculate the distance from the reference edge of the viewport to the line - // position of the cue box. The reference edge will be resolved later when - // the box orientation styles are applied. Default if snapToLines is not set - // is 85. - var linePos = 85; - if (!cue.snapToLines) { - var computedLinePos = computeLinePos(cue), - boxComputedStyle = window.getComputedStyle(this.div), - size = cue.vertical === "" ? boxComputedStyle.getPropertyValue("height") : - boxComputedStyle.getPropertyValue("width"), - // Get the percentage value of the computed height as getPropertyValue - // returns pixels. - overlayHeight = window.getComputedStyle(overlay).getPropertyValue("height"), - calculatedPercentage = (size.replace("px", "") / overlayHeight.replace("px", "")) * 100; - - switch (cue.lineAlign) { - case "start": - linePos = computedLinePos; - break; - case "middle": - linePos = computedLinePos - (calculatedPercentage / 2); - break; - case "end": - linePos = computedLinePos - calculatedPercentage; - break; - } - } - - switch (cue.vertical) { - case "": + this.move = function(box) { this.applyStyles({ - top: this.formatStyle(linePos, "%") + top: this.formatStyle(box.top, "px"), + bottom: this.formatStyle(box.bottom, "px"), + left: this.formatStyle(box.left, "px"), + right: this.formatStyle(box.right, "px"), + height: this.formatStyle(box.height, "px"), + width: this.formatStyle(box.width, "px"), }); - break; - case "rl": - this.applyStyles({ - left: this.formatStyle(linePos, "%") - }); - break; - case "lr": - this.applyStyles({ - right: this.formatStyle(linePos, "%") - }); - break; - } - - cue.displayState = this.div; - } - CueBoundingBox.prototype = Object.create(BasicBoundingBox.prototype); - CueBoundingBox.prototype.constuctor = CueBoundingBox; - - function RegionBoundingBox(window, region) { - BoundingBox.call(this); - this.div = window.document.createElement("div"); - - var left = region.viewportAnchorX - - region.regionAnchorX * region.width / 100, - top = region.viewportAnchorY - - region.regionAnchorY * region.lines * LINE_HEIGHT / 100; - - this.applyStyles({ - position: "absolute", - writingMode: "horizontal-tb", - backgroundColor: "rgba(0, 0, 0, 0.8)", - wordWrap: "break-word", - overflowWrap: "break-word", - font: REGION_FONT_SIZE + "vh/" + LINE_HEIGHT + "vh sans-serif", - lineHeight: LINE_HEIGHT + "vh", - color: "rgba(255, 255, 255, 1)", - overflow: "hidden", - width: this.formatStyle(region.width, "%"), - minHeight: "0", - // TODO: This value is undefined in the spec, but I am assuming that they - // refer to lines * line height to get the max height See issue #107. - maxHeight: this.formatStyle(region.lines * LINE_HEIGHT, "px"), - left: this.formatStyle(left, "%"), - top: this.formatStyle(top, "%"), - display: "inline-flex", - flexFlow: "column", - justifyContent: "flex-end" - }); - - this.maybeAddCue = function(cue) { - if (region.id !== cue.regionId) { - return false; - } - - var basicBox = new BasicBoundingBox(window, cue); - basicBox.applyStyles({ - position: "relative", - unicodeBidi: "plaintext", - width: "auto" - }); - - if (this.div.childNodes.length === 1 && region.scroll === "up") { - this.applyStyles({ - transitionProperty: "top", - transitionDuration: SCROLL_DURATION + "s" - }); - } - - this.div.appendChild(basicBox.div); - return true; }; } - RegionBoundingBox.prototype = Object.create(BoundingBox.prototype); - RegionBoundingBox.prototype.constructor = RegionBoundingBox; + CueStyleBox.prototype = Object.create(StyleBox.prototype); + CueStyleBox.prototype.constructor = CueStyleBox; + + // Represents the co-ordinates of an Element in a way that we can easily + // compute things with such as if it overlaps or intersects with another Element. + // Can initialize it with either a StyleBox or another BoxPosition. + function BoxPosition(obj) { + var self = this; + + // Either a BoxPosition was passed in and we need to copy it, or a StyleBox + // was passed in and we need to copy the results of 'getBoundingClientRect' + // as the object returned is readonly. All co-ordinate values are in reference + // to the viewport origin (top left). + var lh; + if (obj.div) { + var rects = (rects = obj.div.childNodes) && (rects = rects[0]) && + rects.getClientRects && rects.getClientRects(); + obj = obj.div.getBoundingClientRect(); + // In certain cases the outter div will be slightly larger then the sum of + // the inner div's lines. This could be due to bold text, etc, on some platforms. + // In this case we should get the average line height and use that. This will + // result in the desired behaviour. + lh = rects ? Math.max((rects[0] && rects[0].height) || 0, obj.height / rects.length) + : 0; + } + this.left = obj.left; + this.right = obj.right; + this.top = obj.top; + this.height = obj.height; + this.bottom = obj.bottom; + this.width = obj.width; + this.lineHeight = lh !== undefined ? lh : obj.lineHeight; + } + + // Move the box along a particular axis. If no amount to move is passed, via + // the val parameter, then the default amount is the line height of the box. + BoxPosition.prototype.move = function(axis, val) { + val = val !== undefined ? val : this.lineHeight; + switch (axis) { + case "+x": + this.left += val; + this.right += val; + break; + case "-x": + this.left -= val; + this.right -= val; + break; + case "+y": + this.top += val; + this.bottom += val; + break; + case "-y": + this.top -= val; + this.bottom -= val; + break; + } + }; + + // Check if this box overlaps another box, b2. + BoxPosition.prototype.overlaps = function(b2) { + return this.left < b2.right && + this.right > b2.left && + this.top < b2.bottom && + this.bottom > b2.top; + }; + + // Check if this box overlaps any other boxes in boxes. + BoxPosition.prototype.overlapsAny = function(boxes) { + for (var i = 0; i < boxes.length; i++) { + if (this.overlaps(boxes[i])) { + return true; + } + } + return false; + }; + + // Check if this box is within another box. + BoxPosition.prototype.within = function(container) { + return this.top >= container.top && + this.bottom <= container.bottom && + this.left >= container.left && + this.right <= container.right; + }; + + // Check if this box is entirely within the container or it is overlapping + // on the edge opposite of the axis direction passed. For example, if "+x" is + // passed and the box is overlapping on the left edge of the container, then + // return true. + BoxPosition.prototype.overlapsOppositeAxis = function(container, axis) { + switch (axis) { + case "+x": + return this.left < container.left; + case "-x": + return this.right > container.right; + case "+y": + return this.top < container.top; + case "-y": + return this.bottom > container.bottom; + } + }; + + // Find the percentage of the area that this box is overlapping with another + // box. + BoxPosition.prototype.intersectPercentage = function(b2) { + var x = Math.max(0, Math.min(this.right, b2.right) - Math.max(this.left, b2.left)), + y = Math.max(0, Math.min(this.bottom, b2.bottom) - Math.max(this.top, b2.top)), + intersectArea = x * y; + return intersectArea / (this.height * this.width); + }; + + // Convert the positions from this box to CSS compatible positions using + // the reference container's positions. This has to be done because this + // box's positions are in reference to the viewport origin, whereas, CSS + // values are in referecne to their respective edges. + BoxPosition.prototype.toCSSCompatValues = function(reference) { + return { + top: this.top - reference.top, + bottom: reference.bottom - this.bottom, + left: this.left - reference.left, + right: reference.right - this.right, + height: this.height, + width: this.width + }; + }; + + // Get an object that represents the box's position without anything extra. + // Can pass a StyleBox, HTMLElement, or another BoxPositon. + BoxPosition.getSimpleBoxPosition = function(obj) { + obj = obj.div ? obj.div.getBoundingClientRect() : + obj.tagName ? obj.getBoundingClientRect() : obj; + return { + left: obj.left, + right: obj.right, + top: obj.top, + height: obj.height, + bottom: obj.bottom, + width: obj.width + }; + }; + + // Move a StyleBox to its specified, or next best, position. The containerBox + // is the box that contains the StyleBox, such as a div. boxPositions are + // a list of other boxes that the styleBox can't overlap with. + function moveBoxToLinePosition(window, styleBox, containerBox, boxPositions) { + + // Find the best position for a cue box, b, on the video. The axis parameter + // is a list of axis, the order of which, it will move the box along. For example: + // Passing ["+x", "-x"] will move the box first along the x axis in the positive + // direction. If it doesn't find a good position for it there it will then move + // it along the x axis in the negative direction. + function findBestPosition(b, axis) { + var bestPosition, + specifiedPosition = new BoxPosition(b), + percentage = 1; // Highest possible so the first thing we get is better. + + for (var i = 0; i < axis.length; i++) { + while (b.overlapsOppositeAxis(containerBox, axis[i]) || + (b.within(containerBox) && b.overlapsAny(boxPositions))) { + b.move(axis[i]); + } + // We found a spot where we aren't overlapping anything. This is our + // best position. + if (b.within(containerBox)) { + return b; + } + var p = b.intersectPercentage(containerBox); + // If we're outside the container box less then we were on our last try + // then remember this position as the best position. + if (percentage > p) { + bestPosition = new BoxPosition(b); + percentage = p; + } + // Reset the box position to the specified position. + b = new BoxPosition(specifiedPosition); + } + return bestPosition || specifiedPosition; + } + + function reverseAxis(axis) { + return axis.map(function(a) { + return a.indexOf("+") !== -1 ? a.replace("+", "-") : a.replace("-", "+"); + }); + } + + var boxPosition = new BoxPosition(styleBox), + cue = styleBox.cue, + linePos = computeLinePos(cue), + axis = []; + + // If we have a line number to align the cue to. + if (cue.snapToLines) { + switch (cue.vertical) { + case "": + axis = [ "+y", "-y" ]; + break; + case "rl": + axis = [ "+x", "-x" ]; + break; + case "lr": + axis = [ "-x", "+x" ]; + break; + } + + // If computed line position returns negative then line numbers are + // relative to the bottom of the video instead of the top. Therefore, we + // need to increase our initial position by the length or width of the + // video, depending on the writing direction, and reverse our axis directions. + var initialPosition = boxPosition.lineHeight * Math.floor(linePos + 0.5), + initialAxis = axis[0]; + if (linePos < 0) { + initialPosition += cue.vertical === "" ? containerBox.height : containerBox.width; + axis = reverseAxis(axis); + } + + // Move the box to the specified position. This may not be its best + // position. + boxPosition.move(initialAxis, initialPosition); + + } else { + // If we have a percentage line value for the cue. + var calculatedPercentage = (boxPosition.lineHeight / containerBox.height) * 100; + + switch (cue.lineAlign) { + case "middle": + linePos -= (calculatedPercentage / 2); + break; + case "end": + linePos -= calculatedPercentage; + break; + } + + // Apply initial line position to the cue box. + switch (cue.vertical) { + case "": + styleBox.applyStyles({ + top: styleBox.formatStyle(linePos, "%") + }); + break; + case "rl": + styleBox.applyStyles({ + left: styleBox.formatStyle(linePos, "%") + }); + break; + case "lr": + styleBox.applyStyles({ + right: styleBox.formatStyle(linePos, "%") + }); + break; + } + + axis = [ "+y", "-x", "+x", "-y" ]; + + // Get the box position again after we've applied the specified positioning + // to it. + boxPosition = new BoxPosition(styleBox); + } + + var bestPosition = findBestPosition(boxPosition, axis); + styleBox.move(bestPosition.toCSSCompatValues(containerBox)); + } function WebVTTParser(window, decoder) { this.window = window; @@ -891,10 +1051,14 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]; return parseContent(window, cuetext); }; + const FONT_SIZE_PERCENT = 0.05; + const FONT_STYLE = "sans-serif"; + const CUE_BACKGROUND_PADDING = "1.5%"; + // Runs the processing model over the cues and regions passed to it. // @param overlay A block level element (usually a div) that the computed cues // and regions will be placed into. - WebVTTParser.processCues = function(window, cues, regions, overlay) { + WebVTTParser.processCues = function(window, cues, overlay) { if (!window || !cues || !overlay) { return null; } @@ -904,32 +1068,56 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]; overlay.removeChild(overlay.firstChild); } - var regionBoxes = regions ? regions.map(function(region) { - return new RegionBoundingBox(window, region); - }) : null; + var paddedOverlay = window.document.createElement("div"); + paddedOverlay.style.position = "absolute"; + paddedOverlay.style.left = "0"; + paddedOverlay.style.right = "0"; + paddedOverlay.style.top = "0"; + paddedOverlay.style.bottom = "0"; + paddedOverlay.style.margin = CUE_BACKGROUND_PADDING; + overlay.appendChild(paddedOverlay); - function mapCueToRegion(cue) { - for (var i = 0; i < regionBoxes.length; i++) { - if (regionBoxes[i].maybeAddCue(cue)) { + // Determine if we need to compute the display states of the cues. This could + // be the case if a cue's state has been changed since the last computation or + // if it has not been computed yet. + function shouldCompute(cues) { + for (var i = 0; i < cues.length; i++) { + if (cues[i].hasBeenReset || !cues[i].displayState) { return true; } } return false; } - for (var i = 0; i < cues.length; i++) { - // Check to see if this cue is contained within a VTTRegion. - if (regionBoxes && mapCueToRegion(cues[i])) { - continue; - } - // Check to see if we can just reuse the last computed styles of the cue. - if (cues[i].hasBeenReset !== true && cues[i].displayState) { - overlay.appendChild(cues[i].displayState); - continue; - } - // Compute the position of the cue box on the cue overlay. - var cueBox = new CueBoundingBox(window, cues[i], overlay); + // We don't need to recompute the cues' display states. Just reuse them. + if (!shouldCompute(cues)) { + cues.forEach(function(cue) { + paddedOverlay.appendChild(cue.displayState); + }); + return; } + + var boxPositions = [], + containerBox = BoxPosition.getSimpleBoxPosition(paddedOverlay), + fontSize = Math.round(containerBox.height * FONT_SIZE_PERCENT * 100) / 100; + var styleOptions = { + font: fontSize + "px " + FONT_STYLE + }; + + cues.forEach(function(cue) { + // Compute the intial position and styles of the cue div. + var styleBox = new CueStyleBox(window, cue, styleOptions); + paddedOverlay.appendChild(styleBox.div); + + // Move the cue div to it's correct line position. + moveBoxToLinePosition(window, styleBox, containerBox, boxPositions); + + // Remember the computed div so that we don't have to recompute it later + // if we don't have too. + cue.displayState = styleBox.div; + + boxPositions.push(BoxPosition.getSimpleBoxPosition(styleBox)); + }); }; WebVTTParser.prototype = { @@ -972,7 +1160,7 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]; settings.set(k, v); break; case "width": - settings.percent(k, v, true); + settings.percent(k, v); break; case "lines": settings.integer(k, v); @@ -986,8 +1174,8 @@ this.EXPORTED_SYMBOLS = ["WebVTTParser"]; // We have to make sure both x and y parse, so use a temporary // settings object here. var anchor = new Settings(); - anchor.percent("x", xy[0], true); - anchor.percent("y", xy[1], true); + anchor.percent("x", xy[0]); + anchor.percent("y", xy[1]); if (!anchor.has("x") || !anchor.has("y")) { break; } From 5d199d31427af4152ca0bf6815f0597eb9cf03d7 Mon Sep 17 00:00:00 2001 From: Rick Eyre Date: Fri, 21 Feb 2014 22:14:22 -0500 Subject: [PATCH 07/48] Bug 865407 - Part 9: Remove border-box and padding CSS on the caption overlay. r=rillian This wasn't working correctly. Vtt.js now takes care of applying padding to the video overlay. --- layout/style/html.css | 2 -- 1 file changed, 2 deletions(-) diff --git a/layout/style/html.css b/layout/style/html.css index f09794488e83..9e83101a82df 100644 --- a/layout/style/html.css +++ b/layout/style/html.css @@ -729,8 +729,6 @@ audio:not([controls]) { video > .caption-box { position: relative; overflow: hidden; - padding: 1.5%; - box-sizing: border-box; } /* emulation of non-standard HTML tag */ From b59464a8663effb78358cbd09990f300c51ffcf4 Mon Sep 17 00:00:00 2001 From: Simone Carletti Date: Mon, 24 Feb 2014 09:41:55 -0500 Subject: [PATCH 08/48] Bug 969087 - Add GitHubUserContent.com to PSL. r=gerv --- netwerk/dns/effective_tld_names.dat | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/netwerk/dns/effective_tld_names.dat b/netwerk/dns/effective_tld_names.dat index 376409ee8200..d63a56e0eab9 100644 --- a/netwerk/dns/effective_tld_names.dat +++ b/netwerk/dns/effective_tld_names.dat @@ -7719,8 +7719,9 @@ a.prod.fastly.net global.prod.fastly.net // GitHub, Inc. -// Submitted by Ben Toews 2013-04-18 +// Submitted by Ben Toews 2014-02-06 github.io +githubusercontent.com // GlobeHosting, Inc. // Submitted by Zoltan Egresi 2013-07-12 From 46c4d5f8340ae768541ba561d5268084090fde50 Mon Sep 17 00:00:00 2001 From: "Raymond Etornam Agbeame(:retornam)" Date: Mon, 24 Feb 2014 09:41:55 -0500 Subject: [PATCH 09/48] Bug 970614 - Remove code wrapped in #if 0 ... #endif blocks in PSM. r=keeler --- .../manager/ssl/src/nsCMSSecureMessage.cpp | 4 -- .../manager/ssl/src/nsNSSCertificateDB.cpp | 19 +----- security/manager/ssl/src/nsPKCS12Blob.cpp | 60 ------------------- security/manager/ssl/src/nsPKCS12Blob.h | 4 -- 4 files changed, 1 insertion(+), 86 deletions(-) diff --git a/security/manager/ssl/src/nsCMSSecureMessage.cpp b/security/manager/ssl/src/nsCMSSecureMessage.cpp index 71830149aba1..1155ca79140f 100644 --- a/security/manager/ssl/src/nsCMSSecureMessage.cpp +++ b/security/manager/ssl/src/nsCMSSecureMessage.cpp @@ -167,10 +167,6 @@ SendMessage(const char *msg, const char *base64Cert, char ** _retval) goto done; } -#if 0 - cert->dbhandle = CERT_GetDefaultCertDB(); /* work-around */ -#endif - /* Step 2. Get a signature cert */ /* Step 3. Build inner (signature) content */ diff --git a/security/manager/ssl/src/nsNSSCertificateDB.cpp b/security/manager/ssl/src/nsNSSCertificateDB.cpp index d7a3c92e6ce8..0623e22eb3fe 100644 --- a/security/manager/ssl/src/nsNSSCertificateDB.cpp +++ b/security/manager/ssl/src/nsNSSCertificateDB.cpp @@ -93,14 +93,6 @@ nsNSSCertificateDB::FindCertByNickname(nsISupports *aToken, NS_ConvertUTF16toUTF8 aUtf8Nickname(nickname); asciiname = const_cast(aUtf8Nickname.get()); PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Getting \"%s\"\n", asciiname)); -#if 0 - // what it should be, but for now... - if (aToken) { - cert = PK11_FindCertFromNickname(asciiname, nullptr); - } else { - cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), asciiname); - } -#endif cert = PK11_FindCertFromNickname(asciiname, nullptr); if (!cert) { cert = CERT_FindCertByNickname(CERT_GetDefaultCertDB(), asciiname); @@ -187,16 +179,7 @@ nsNSSCertificateDB::FindCertNicknames(nsISupports *aToken, * obtain the cert list from NSS */ insanity::pkix::ScopedCERTCertList certList; - PK11CertListType pk11type; -#if 0 - // this would seem right, but it didn't work... - // oh, I know why - bonks out on internal slot certs - if (aType == nsIX509Cert::USER_CERT) - pk11type = PK11CertListUser; - else -#endif - pk11type = PK11CertListUnique; - certList = PK11_ListCerts(pk11type, nullptr); + certList = PK11_ListCerts(PK11CertListUnique, nullptr); if (!certList) goto cleanup; /* diff --git a/security/manager/ssl/src/nsPKCS12Blob.cpp b/security/manager/ssl/src/nsPKCS12Blob.cpp index ed8bbe6bf0c4..6898d8ac50aa 100644 --- a/security/manager/ssl/src/nsPKCS12Blob.cpp +++ b/security/manager/ssl/src/nsPKCS12Blob.cpp @@ -237,46 +237,6 @@ finish: return NS_OK; } -#if 0 -// nsPKCS12Blob::LoadCerts -// -// Given an array of certificate nicknames, load the corresponding -// certificates into a local array. -nsresult -nsPKCS12Blob::LoadCerts(const char16_t **certNames, int numCerts) -{ - nsresult rv; - char namecpy[256]; - /* Create the local array if needed */ - if (!mCertArray) { - rv = NS_NewISupportsArray(getter_AddRefs(mCertArray)); - if (NS_FAILED(rv)) { - if (!handleError()) - return NS_ERROR_OUT_OF_MEMORY; - } - } - /* Add the certs */ - for (int i=0; i cert = nsNSSCertificate::Create(nssCert); - CERT_DestroyCertificate(nssCert); - if (!cert) { - if (!handleError()) - return NS_ERROR_OUT_OF_MEMORY; - } else { - mCertArray->AppendElement(cert); - } - } - return NS_OK; -} -#endif - static bool isExtractable(SECKEYPrivateKey *privKey) { @@ -344,18 +304,7 @@ nsPKCS12Blob::ExportToFile(nsIFile *file, // add password integrity srv = SEC_PKCS12AddPasswordIntegrity(ecx, &unicodePw, SEC_OID_SHA1); if (srv) goto finish; -#if 0 - // count the number of certs to export - nrv = mCertArray->Count(&numCerts); - if (NS_FAILED(nrv)) goto finish; - // loop over the certs for (i=0; i cert; - nrv = mCertArray->GetElementAt(i, getter_AddRefs(cert)); - if (NS_FAILED(nrv)) goto finish; -#endif - for (i=0; i(certs[i]); nsNSSCertificate *cert = (nsNSSCertificate *)certs[i]; // get it as a CERTCertificate XXX insanity::pkix::ScopedCERTCertificate nssCert(cert->GetCert()); @@ -802,15 +751,6 @@ nsPKCS12Blob::handleError(int myerr) /* ask to keep going? what happens if one collision but others ok? */ // The following errors cannot be "handled", notify the user (via an alert) // that the operation failed. -#if 0 - // XXX a boy can dream... - // but the PKCS12 lib never throws this error - // but then again, how would it? anyway, convey the info below - case SEC_ERROR_PKCS12_PRIVACY_PASSWORD_INCORRECT: - msgID = "PKCS12PasswordInvalid"; - break; -#endif - case SEC_ERROR_BAD_PASSWORD: msgID = "PK11BadPassword"; break; case SEC_ERROR_BAD_DER: diff --git a/security/manager/ssl/src/nsPKCS12Blob.h b/security/manager/ssl/src/nsPKCS12Blob.h index 027ad63464ab..9aadd27c8199 100644 --- a/security/manager/ssl/src/nsPKCS12Blob.h +++ b/security/manager/ssl/src/nsPKCS12Blob.h @@ -39,10 +39,6 @@ public: nsresult ImportFromFile(nsIFile *file); // PKCS#12 Export -#if 0 - //nsresult LoadCerts(const char16_t **certNames, int numCerts); - nsresult LoadCerts(nsIX509Cert **certs, int numCerts); -#endif nsresult ExportToFile(nsIFile *file, nsIX509Cert **certs, int numCerts); private: From cd767c8acc22eb63c0faf94f893fd670a22916e9 Mon Sep 17 00:00:00 2001 From: Chris Lewis Date: Mon, 24 Feb 2014 09:41:55 -0500 Subject: [PATCH 10/48] Bug 974097 - AppendChild operation in LayersMessages.idplh should be called PrependChild. r=gal --- gfx/layers/ipc/LayerTransactionParent.cpp | 10 +++++----- gfx/layers/ipc/LayersMessages.ipdlh | 4 ++-- gfx/layers/ipc/ShadowLayers.cpp | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/gfx/layers/ipc/LayerTransactionParent.cpp b/gfx/layers/ipc/LayerTransactionParent.cpp index e4fdc4b0caf9..0633a503064c 100644 --- a/gfx/layers/ipc/LayerTransactionParent.cpp +++ b/gfx/layers/ipc/LayerTransactionParent.cpp @@ -97,12 +97,12 @@ ShadowAfter(const OpInsertAfter& op) } static ShadowLayerParent* -ShadowContainer(const OpAppendChild& op) +ShadowContainer(const OpPrependChild& op) { return cast(op.containerParent()); } static ShadowLayerParent* -ShadowChild(const OpAppendChild& op) +ShadowChild(const OpPrependChild& op) { return cast(op.childLayerParent()); } @@ -416,10 +416,10 @@ LayerTransactionParent::RecvUpdate(const InfallibleTArray& cset, } break; } - case Edit::TOpAppendChild: { - MOZ_LAYERS_LOG(("[ParentSide] AppendChild")); + case Edit::TOpPrependChild: { + MOZ_LAYERS_LOG(("[ParentSide] PrependChild")); - const OpAppendChild& oac = edit.get_OpAppendChild(); + const OpPrependChild& oac = edit.get_OpPrependChild(); Layer* child = ShadowChild(oac)->AsLayer(); if (!child) { return false; diff --git a/gfx/layers/ipc/LayersMessages.ipdlh b/gfx/layers/ipc/LayersMessages.ipdlh index 69ad0f86074c..13f087f502e9 100644 --- a/gfx/layers/ipc/LayersMessages.ipdlh +++ b/gfx/layers/ipc/LayersMessages.ipdlh @@ -247,7 +247,7 @@ struct OpSetLayerAttributes { // Monkey with the tree structure struct OpSetRoot { PLayer root; }; struct OpInsertAfter { PLayer container; PLayer childLayer; PLayer after; }; -struct OpAppendChild { PLayer container; PLayer childLayer; }; +struct OpPrependChild { PLayer container; PLayer childLayer; }; struct OpRemoveChild { PLayer container; PLayer childLayer; }; struct OpRepositionChild { PLayer container; PLayer childLayer; PLayer after; }; struct OpRaiseToTopChild { PLayer container; PLayer childLayer; }; @@ -371,7 +371,7 @@ union Edit { OpSetRoot; OpInsertAfter; - OpAppendChild; + OpPrependChild; OpRemoveChild; OpRepositionChild; OpRaiseToTopChild; diff --git a/gfx/layers/ipc/ShadowLayers.cpp b/gfx/layers/ipc/ShadowLayers.cpp index 1cdad1465a64..d7167f448975 100644 --- a/gfx/layers/ipc/ShadowLayers.cpp +++ b/gfx/layers/ipc/ShadowLayers.cpp @@ -276,8 +276,8 @@ ShadowLayerForwarder::InsertAfter(ShadowableLayer* aContainer, nullptr, Shadow(aChild), nullptr, Shadow(aAfter))); else - mTxn->AddEdit(OpAppendChild(nullptr, Shadow(aContainer), - nullptr, Shadow(aChild))); + mTxn->AddEdit(OpPrependChild(nullptr, Shadow(aContainer), + nullptr, Shadow(aChild))); } void ShadowLayerForwarder::RemoveChild(ShadowableLayer* aContainer, From 40d90dfa2313d38a6c691e57315707dbb57070f8 Mon Sep 17 00:00:00 2001 From: Jan Beich Date: Mon, 24 Feb 2014 09:41:55 -0500 Subject: [PATCH 11/48] Bug 974272 - Unbreak skia/qt on tier3 as well. r=gw280 --- gfx/skia/moz.build | 1 - 1 file changed, 1 deletion(-) diff --git a/gfx/skia/moz.build b/gfx/skia/moz.build index 779fe106fd81..8f9753357a50 100644 --- a/gfx/skia/moz.build +++ b/gfx/skia/moz.build @@ -744,7 +744,6 @@ if CONFIG['MOZ_WIDGET_QT']: 'trunk/src/ports/SkTime_Unix.cpp', 'trunk/src/ports/SkTLS_pthread.cpp', 'trunk/src/utils/SkThreadUtils_pthread.cpp', - 'trunk/src/utils/SkThreadUtils_pthread_linux.cpp', ] if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows': SOURCES += [ From a127266e74d54e08d1958de11679e4ecb8f47226 Mon Sep 17 00:00:00 2001 From: Arnaud Sourioux Date: Mon, 24 Feb 2014 09:41:56 -0500 Subject: [PATCH 12/48] Bug 974687 - Part 1: Add about 300 MOZ_OVERRIDE in layout/. r=dholbert --- layout/base/nsBidiPresUtils.cpp | 6 ++--- layout/base/nsDisplayList.h | 18 ++++++------- layout/base/nsDocumentViewer.cpp | 2 +- layout/base/nsFrameTraversal.cpp | 20 +++++++-------- layout/base/nsLayoutDebugger.cpp | 14 +++++------ layout/base/nsLayoutUtils.cpp | 2 +- layout/base/nsPresContext.cpp | 2 +- layout/base/nsPresShell.cpp | 4 +-- layout/forms/nsButtonFrameRenderer.cpp | 12 ++++----- layout/forms/nsComboboxControlFrame.cpp | 14 +++++------ layout/forms/nsComboboxControlFrame.h | 6 ++--- layout/forms/nsFieldSetFrame.cpp | 4 +-- layout/forms/nsFieldSetFrame.h | 23 +++++++++-------- layout/forms/nsFileControlFrame.h | 4 +-- layout/forms/nsNumberControlFrame.h | 3 ++- layout/generic/TextOverflow.cpp | 6 ++--- layout/generic/nsBRFrame.cpp | 24 +++++++++--------- layout/generic/nsBulletFrame.cpp | 12 ++++----- layout/generic/nsCanvasFrame.cpp | 4 +-- layout/generic/nsFrame.cpp | 2 +- layout/generic/nsFrameSetFrame.cpp | 26 +++++++++---------- layout/generic/nsGfxScrollFrame.cpp | 6 ++--- layout/generic/nsGfxScrollFrame.h | 4 +-- layout/generic/nsHTMLCanvasFrame.cpp | 8 +++--- layout/generic/nsImageFrame.cpp | 4 +-- layout/generic/nsImageMap.cpp | 30 +++++++++++----------- layout/generic/nsObjectFrame.cpp | 16 ++++++------ layout/generic/nsSelection.cpp | 2 +- layout/generic/nsSplittableFrame.h | 2 +- layout/generic/nsTextFrame.cpp | 32 ++++++++++++------------ layout/generic/nsVideoFrame.cpp | 8 +++--- layout/mathml/nsMathMLContainerFrame.cpp | 6 ++--- layout/mathml/nsMathMLFrame.cpp | 4 +-- layout/mathml/nsMathMLmencloseFrame.cpp | 2 +- layout/mathml/nsMathMLmfracFrame.cpp | 2 +- layout/mathml/nsMathMLmtableFrame.h | 6 ++--- layout/printing/nsPrintEngine.cpp | 2 +- layout/style/StyleRule.cpp | 12 ++++----- layout/style/nsDOMCSSAttrDeclaration.h | 2 +- layout/style/nsFontFaceLoader.h | 11 ++++---- layout/svg/SVGFEContainerFrame.cpp | 10 ++++---- layout/svg/SVGFEImageFrame.cpp | 12 ++++----- layout/svg/SVGFELeafFrame.cpp | 10 ++++---- layout/svg/SVGFEUnstyledLeafFrame.cpp | 10 ++++---- layout/svg/SVGTextFrame.cpp | 26 +++++++++---------- layout/svg/SVGViewFrame.cpp | 10 ++++---- layout/svg/nsSVGAFrame.cpp | 8 +++--- layout/svg/nsSVGImageFrame.cpp | 12 ++++----- layout/svg/nsSVGIntegrationUtils.cpp | 6 ++--- layout/svg/nsSVGOuterSVGFrame.cpp | 6 ++--- layout/svg/nsSVGPathGeometryFrame.h | 2 +- layout/svg/nsSVGStopFrame.cpp | 8 +++--- layout/svg/nsSVGSwitchFrame.cpp | 12 ++++----- layout/svg/nsSVGUseFrame.cpp | 18 ++++++------- layout/svg/nsSVGUtils.cpp | 2 +- layout/tables/nsTableCellFrame.cpp | 6 ++--- layout/tables/nsTableFrame.cpp | 4 +-- layout/tables/nsTableOuterFrame.h | 4 +-- layout/tables/nsTableRowFrame.cpp | 2 +- layout/tables/nsTableRowGroupFrame.cpp | 2 +- layout/xul/nsBoxFrame.cpp | 6 ++--- layout/xul/nsDocElementBoxFrame.cpp | 10 ++++---- layout/xul/nsImageBoxFrame.cpp | 2 +- layout/xul/nsListBoxObject.cpp | 6 ++--- layout/xul/nsMenuBarFrame.cpp | 2 +- layout/xul/nsMenuFrame.cpp | 8 +++--- layout/xul/nsMenuPopupFrame.cpp | 2 +- layout/xul/nsProgressMeterFrame.cpp | 4 +-- layout/xul/nsRootBoxFrame.cpp | 28 ++++++++++----------- layout/xul/nsScrollBoxFrame.cpp | 10 ++++---- layout/xul/nsTextBoxFrame.cpp | 12 ++++----- layout/xul/tree/nsTreeBodyFrame.cpp | 2 +- layout/xul/tree/nsTreeColFrame.cpp | 2 +- 73 files changed, 317 insertions(+), 314 deletions(-) diff --git a/layout/base/nsBidiPresUtils.cpp b/layout/base/nsBidiPresUtils.cpp index 5aea83cac1db..94dc090c1f4b 100644 --- a/layout/base/nsBidiPresUtils.cpp +++ b/layout/base/nsBidiPresUtils.cpp @@ -2031,20 +2031,20 @@ public: virtual void SetText(const char16_t* aText, int32_t aLength, - nsBidiDirection aDirection) + nsBidiDirection aDirection) MOZ_OVERRIDE { mTextRunConstructionContext->SetTextRunRTL(aDirection==NSBIDI_RTL); mText = aText; mLength = aLength; } - virtual nscoord GetWidth() + virtual nscoord GetWidth() MOZ_OVERRIDE { return mTextRunConstructionContext->GetWidth(mText, mLength); } virtual void DrawText(nscoord aXOffset, - nscoord) + nscoord) MOZ_OVERRIDE { mCtx->FontMetrics()->DrawString(mText, mLength, mPt.x + aXOffset, mPt.y, mCtx, mTextRunConstructionContext); diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 3a84d06c169f..bcac696cc47b 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -1736,7 +1736,7 @@ public: } NS_DISPLAY_DECL_NAME(mName, mType) - virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) { + virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE { if (mType == nsDisplayItem::TYPE_HEADER_FOOTER) { bool snap; return GetBounds(aBuilder, &snap); @@ -1908,7 +1908,7 @@ public: const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("Border", TYPE_BORDER) - virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder); + virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, const nsDisplayItemGeometry* aGeometry, @@ -2227,9 +2227,9 @@ public: virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, const nsDisplayItemGeometry* aGeometry, - nsRegion* aInvalidRegion); + nsRegion* aInvalidRegion) MOZ_OVERRIDE; - virtual bool ApplyOpacity(float aOpacity) + virtual bool ApplyOpacity(float aOpacity) MOZ_OVERRIDE { mOpacity = aOpacity; return true; @@ -2264,7 +2264,7 @@ public: const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("BoxShadowInner", TYPE_BOX_SHADOW_INNER) - virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) + virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE { return new nsDisplayBoxShadowInnerGeometry(this, aBuilder); } @@ -2465,7 +2465,7 @@ public: } NS_DISPLAY_DECL_NAME("WrapList", TYPE_WRAP_LIST) - virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder); + virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; virtual nsDisplayList* GetSameCoordinateSystemChildren() MOZ_OVERRIDE { @@ -2596,7 +2596,7 @@ public: virtual ~nsDisplayMixBlendMode(); #endif - nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap); + nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; virtual already_AddRefed BuildLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager, @@ -2936,7 +2936,7 @@ public: virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters); + const ContainerLayerParameters& aParameters) MOZ_OVERRIDE; virtual already_AddRefed BuildLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager, @@ -3004,7 +3004,7 @@ public: NS_DISPLAY_DECL_NAME("nsDisplayTransform", TYPE_TRANSFORM) - virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) + virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE { if (mStoredList.GetComponentAlphaBounds(aBuilder).IsEmpty()) return nsRect(); diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp index 45f85f5a4e63..58584934763d 100644 --- a/layout/base/nsDocumentViewer.cpp +++ b/layout/base/nsDocumentViewer.cpp @@ -447,7 +447,7 @@ public: nsDocumentShownDispatcher(nsCOMPtr aDocument) : mDocument(aDocument) {} - NS_IMETHOD Run(); + NS_IMETHOD Run() MOZ_OVERRIDE; private: nsCOMPtr mDocument; diff --git a/layout/base/nsFrameTraversal.cpp b/layout/base/nsFrameTraversal.cpp index d61e3939c37a..837329eae678 100644 --- a/layout/base/nsFrameTraversal.cpp +++ b/layout/base/nsFrameTraversal.cpp @@ -19,13 +19,13 @@ public: virtual ~nsFrameIterator() {} - virtual void First(); - virtual void Next(); - virtual nsIFrame* CurrentItem(); - virtual bool IsDone(); + virtual void First() MOZ_OVERRIDE; + virtual void Next() MOZ_OVERRIDE; + virtual nsIFrame* CurrentItem() MOZ_OVERRIDE; + virtual bool IsDone() MOZ_OVERRIDE; - virtual void Last(); - virtual void Prev(); + virtual void Last() MOZ_OVERRIDE; + virtual void Prev() MOZ_OVERRIDE; nsFrameIterator(nsPresContext* aPresContext, nsIFrame *aStart, nsIteratorType aType, bool aLockScroll, bool aFollowOOFs); @@ -106,11 +106,11 @@ public: nsFrameIterator(aPresContext, aStart, aType, aLockScroll, aFollowOOFs) {} protected: - nsIFrame* GetFirstChildInner(nsIFrame* aFrame); - nsIFrame* GetLastChildInner(nsIFrame* aFrame); + nsIFrame* GetFirstChildInner(nsIFrame* aFrame) MOZ_OVERRIDE; + nsIFrame* GetLastChildInner(nsIFrame* aFrame) MOZ_OVERRIDE; - nsIFrame* GetNextSiblingInner(nsIFrame* aFrame); - nsIFrame* GetPrevSiblingInner(nsIFrame* aFrame); + nsIFrame* GetNextSiblingInner(nsIFrame* aFrame) MOZ_OVERRIDE; + nsIFrame* GetPrevSiblingInner(nsIFrame* aFrame) MOZ_OVERRIDE; }; /************IMPLEMENTATIONS**************/ diff --git a/layout/base/nsLayoutDebugger.cpp b/layout/base/nsLayoutDebugger.cpp index 831b567f1215..49745b7aeeb0 100644 --- a/layout/base/nsLayoutDebugger.cpp +++ b/layout/base/nsLayoutDebugger.cpp @@ -27,22 +27,22 @@ public: NS_DECL_ISUPPORTS - NS_IMETHOD SetShowFrameBorders(bool aEnable); + NS_IMETHOD SetShowFrameBorders(bool aEnable) MOZ_OVERRIDE; - NS_IMETHOD GetShowFrameBorders(bool* aResult); + NS_IMETHOD GetShowFrameBorders(bool* aResult) MOZ_OVERRIDE; - NS_IMETHOD SetShowEventTargetFrameBorder(bool aEnable); + NS_IMETHOD SetShowEventTargetFrameBorder(bool aEnable) MOZ_OVERRIDE; - NS_IMETHOD GetShowEventTargetFrameBorder(bool* aResult); + NS_IMETHOD GetShowEventTargetFrameBorder(bool* aResult) MOZ_OVERRIDE; NS_IMETHOD GetContentSize(nsIDocument* aDocument, - int32_t* aSizeInBytesResult); + int32_t* aSizeInBytesResult) MOZ_OVERRIDE; NS_IMETHOD GetFrameSize(nsIPresShell* aPresentation, - int32_t* aSizeInBytesResult); + int32_t* aSizeInBytesResult) MOZ_OVERRIDE; NS_IMETHOD GetStyleSize(nsIPresShell* aPresentation, - int32_t* aSizeInBytesResult); + int32_t* aSizeInBytesResult) MOZ_OVERRIDE; }; diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 1d72ad2ee61a..06e60f1f1bca 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -2562,7 +2562,7 @@ struct BoxToRect : public nsLayoutUtils::BoxCallback { uint32_t aFlags) : mRelativeTo(aRelativeTo), mCallback(aCallback), mFlags(aFlags) {} - virtual void AddBox(nsIFrame* aFrame) { + virtual void AddBox(nsIFrame* aFrame) MOZ_OVERRIDE { nsRect r; nsIFrame* outer = nsSVGUtils::GetOuterSVGFrameAndCoveredRegion(aFrame, &r); if (!outer) { diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp index 332059fac59a..de1d0fda0ff0 100644 --- a/layout/base/nsPresContext.cpp +++ b/layout/base/nsPresContext.cpp @@ -2462,7 +2462,7 @@ public: "DOMPaintEvent requested for a detached pres context"); mList.TakeFrom(aList); } - NS_IMETHOD Run() + NS_IMETHOD Run() MOZ_OVERRIDE { // The pres context might have been detached during the delay - // that's fine, just don't fire the event. diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index ca43e1cc6793..f2854e6ccba1 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -448,7 +448,7 @@ class MOZ_STACK_CLASS nsPresShellEventCB : public nsDispatchingCallback public: nsPresShellEventCB(PresShell* aPresShell) : mPresShell(aPresShell) {} - virtual void HandleEvent(nsEventChainPostVisitor& aVisitor) + virtual void HandleEvent(nsEventChainPostVisitor& aVisitor) MOZ_OVERRIDE { if (aVisitor.mPresContext && aVisitor.mEvent->eventStructType != NS_EVENT) { if (aVisitor.mEvent->message == NS_MOUSE_BUTTON_DOWN || @@ -501,7 +501,7 @@ public: // Fires the "before-first-paint" event so that interested parties (right now, the // mobile browser) are aware of it. - NS_IMETHOD Run() + NS_IMETHOD Run() MOZ_OVERRIDE { nsCOMPtr observerService = mozilla::services::GetObserverService(); diff --git a/layout/forms/nsButtonFrameRenderer.cpp b/layout/forms/nsButtonFrameRenderer.cpp index 11fabd2bfc22..2d823a3a2880 100644 --- a/layout/forms/nsButtonFrameRenderer.cpp +++ b/layout/forms/nsButtonFrameRenderer.cpp @@ -73,8 +73,8 @@ public: #endif virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap); + nsRenderingContext* aCtx) MOZ_OVERRIDE; + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("ButtonBoxShadowOuter", TYPE_BUTTON_BOX_SHADOW_OUTER) private: nsButtonFrameRenderer* mBFR; @@ -112,12 +112,12 @@ public: #endif virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames) { + HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE { aOutFrames->AppendElement(mFrame); } virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap); + nsRenderingContext* aCtx) MOZ_OVERRIDE; + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, const nsDisplayItemGeometry* aGeometry, nsRegion *aInvalidRegion) MOZ_OVERRIDE; @@ -147,7 +147,7 @@ public: #endif virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("ButtonForeground", TYPE_BUTTON_FOREGROUND) private: nsButtonFrameRenderer* mBFR; diff --git a/layout/forms/nsComboboxControlFrame.cpp b/layout/forms/nsComboboxControlFrame.cpp index 9ab1608853be..1542f6ebe591 100644 --- a/layout/forms/nsComboboxControlFrame.cpp +++ b/layout/forms/nsComboboxControlFrame.cpp @@ -75,7 +75,7 @@ class nsComboButtonListener : public nsIDOMEventListener public: NS_DECL_ISUPPORTS - NS_IMETHOD HandleEvent(nsIDOMEvent*) + NS_IMETHOD HandleEvent(nsIDOMEvent*) MOZ_OVERRIDE { mComboBox->ShowDropDown(!mComboBox->IsDroppedDown()); return NS_OK; @@ -371,14 +371,14 @@ public: MOZ_COUNT_DTOR(nsResizeDropdownAtFinalPosition); } - virtual bool ReflowFinished() + virtual bool ReflowFinished() MOZ_OVERRIDE { Run(); NS_RELEASE_THIS(); return false; } - virtual void ReflowCallbackCanceled() + virtual void ReflowCallbackCanceled() MOZ_OVERRIDE { NS_RELEASE_THIS(); } @@ -1218,9 +1218,9 @@ public: // Need this so that line layout knows that this block's width // depends on the available width. - virtual nsIAtom* GetType() const; + virtual nsIAtom* GetType() const MOZ_OVERRIDE; - virtual bool IsFrameOfType(uint32_t aFlags) const + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE { return nsBlockFrame::IsFrameOfType(aFlags & ~(nsIFrame::eReplacedContainsBlock)); @@ -1229,7 +1229,7 @@ public: virtual nsresult Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); + nsReflowStatus& aStatus) MOZ_OVERRIDE; virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, @@ -1449,7 +1449,7 @@ public: #endif virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("ComboboxFocus", TYPE_COMBOBOX_FOCUS) }; diff --git a/layout/forms/nsComboboxControlFrame.h b/layout/forms/nsComboboxControlFrame.h index 18303f685d85..2196606c1beb 100644 --- a/layout/forms/nsComboboxControlFrame.h +++ b/layout/forms/nsComboboxControlFrame.h @@ -76,7 +76,7 @@ public: virtual nsresult HandleEvent(nsPresContext* aPresContext, mozilla::WidgetGUIEvent* aEvent, - nsEventStatus* aEventStatus); + nsEventStatus* aEventStatus) MOZ_OVERRIDE; virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, @@ -95,7 +95,7 @@ public: ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock)); } - virtual nsIScrollableFrame* GetScrollTargetFrame() { + virtual nsIScrollableFrame* GetScrollTargetFrame() MOZ_OVERRIDE { return do_QueryFrame(mDropdownFrame); } @@ -108,7 +108,7 @@ public: virtual const nsFrameList& GetChildList(ChildListID aListID) const MOZ_OVERRIDE; virtual void GetChildLists(nsTArray* aLists) const MOZ_OVERRIDE; - virtual nsIFrame* GetContentInsertionFrame(); + virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE; // nsIFormControlFrame virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue) MOZ_OVERRIDE; diff --git a/layout/forms/nsFieldSetFrame.cpp b/layout/forms/nsFieldSetFrame.cpp index c2e0b3c0a010..93afd484f285 100644 --- a/layout/forms/nsFieldSetFrame.cpp +++ b/layout/forms/nsFieldSetFrame.cpp @@ -106,9 +106,9 @@ public: #endif virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames); + HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE; virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, const nsDisplayItemGeometry* aGeometry, nsRegion *aInvalidRegion) MOZ_OVERRIDE; diff --git a/layout/forms/nsFieldSetFrame.h b/layout/forms/nsFieldSetFrame.h index 98d245ccfea6..3ae9974742ef 100644 --- a/layout/forms/nsFieldSetFrame.h +++ b/layout/forms/nsFieldSetFrame.h @@ -6,6 +6,7 @@ #ifndef nsFieldSetFrame_h___ #define nsFieldSetFrame_h___ +#include "mozilla/Attributes.h" #include "nsContainerFrame.h" class nsFieldSetFrame MOZ_FINAL : public nsContainerFrame @@ -18,13 +19,13 @@ public: NS_HIDDEN_(nscoord) GetIntrinsicWidth(nsRenderingContext* aRenderingContext, nsLayoutUtils::IntrinsicWidthType); - virtual nscoord GetMinWidth(nsRenderingContext* aRenderingContext); - virtual nscoord GetPrefWidth(nsRenderingContext* aRenderingContext); + virtual nscoord GetMinWidth(nsRenderingContext* aRenderingContext) MOZ_OVERRIDE; + virtual nscoord GetPrefWidth(nsRenderingContext* aRenderingContext) MOZ_OVERRIDE; virtual nsSize ComputeSize(nsRenderingContext *aRenderingContext, nsSize aCBSize, nscoord aAvailableWidth, nsSize aMargin, nsSize aBorder, nsSize aPadding, uint32_t aFlags) MOZ_OVERRIDE; - virtual nscoord GetBaseline() const; + virtual nscoord GetBaseline() const MOZ_OVERRIDE; /** * The area to paint box-shadows around. It's the border rect except @@ -35,7 +36,7 @@ public: virtual nsresult Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); + nsReflowStatus& aStatus) MOZ_OVERRIDE; virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, @@ -45,15 +46,15 @@ public: nsPoint aPt, const nsRect& aDirtyRect, uint32_t aBGFlags); virtual nsresult AppendFrames(ChildListID aListID, - nsFrameList& aFrameList); + nsFrameList& aFrameList) MOZ_OVERRIDE; virtual nsresult InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame, - nsFrameList& aFrameList); + nsFrameList& aFrameList) MOZ_OVERRIDE; virtual nsresult RemoveFrame(ChildListID aListID, - nsIFrame* aOldFrame); + nsIFrame* aOldFrame) MOZ_OVERRIDE; - virtual nsIAtom* GetType() const; - virtual bool IsFrameOfType(uint32_t aFlags) const + virtual nsIAtom* GetType() const MOZ_OVERRIDE; + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE { return nsContainerFrame::IsFrameOfType(aFlags & ~nsIFrame::eCanContainOverflowContainers); @@ -69,11 +70,11 @@ public: #ifdef DEBUG virtual nsresult SetInitialChildList(ChildListID aListID, - nsFrameList& aChildList); + nsFrameList& aChildList) MOZ_OVERRIDE; #endif #ifdef DEBUG_FRAME_DUMP - virtual nsresult GetFrameName(nsAString& aResult) const { + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE { return MakeFrameName(NS_LITERAL_STRING("FieldSet"), aResult); } #endif diff --git a/layout/forms/nsFileControlFrame.h b/layout/forms/nsFileControlFrame.h index 0916d3a46485..6f4cfd010be1 100644 --- a/layout/forms/nsFileControlFrame.h +++ b/layout/forms/nsFileControlFrame.h @@ -49,8 +49,8 @@ public: virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, int32_t aModType) MOZ_OVERRIDE; - virtual void ContentStatesChanged(nsEventStates aStates); - virtual bool IsLeaf() const + virtual void ContentStatesChanged(nsEventStates aStates) MOZ_OVERRIDE; + virtual bool IsLeaf() const MOZ_OVERRIDE { return true; } diff --git a/layout/forms/nsNumberControlFrame.h b/layout/forms/nsNumberControlFrame.h index 828e95b2086d..76da938d7c3c 100644 --- a/layout/forms/nsNumberControlFrame.h +++ b/layout/forms/nsNumberControlFrame.h @@ -6,6 +6,7 @@ #ifndef nsNumberControlFrame_h__ #define nsNumberControlFrame_h__ +#include "mozilla/Attributes.h" #include "nsContainerFrame.h" #include "nsIFormControlFrame.h" #include "nsIAnonymousContentCreator.h" @@ -43,7 +44,7 @@ public: NS_DECL_FRAMEARENA_HELPERS virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; - virtual void ContentStatesChanged(nsEventStates aStates); + virtual void ContentStatesChanged(nsEventStates aStates) MOZ_OVERRIDE; virtual bool IsLeaf() const MOZ_OVERRIDE { return true; } #ifdef ACCESSIBILITY diff --git a/layout/generic/TextOverflow.cpp b/layout/generic/TextOverflow.cpp index db1eae28bf9e..d62468125e2c 100644 --- a/layout/generic/TextOverflow.cpp +++ b/layout/generic/TextOverflow.cpp @@ -167,16 +167,16 @@ public: MOZ_COUNT_DTOR(nsDisplayTextOverflowMarker); } #endif - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) { + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE { *aSnap = false; nsRect shadowRect = nsLayoutUtils::GetTextShadowRectsUnion(mRect, mFrame); return mRect.Union(shadowRect); } virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; - virtual uint32_t GetPerFrameKey() { + virtual uint32_t GetPerFrameKey() MOZ_OVERRIDE { return (mIndex << nsDisplayItem::TYPE_BITS) | nsDisplayItem::GetPerFrameKey(); } void PaintTextToContext(nsRenderingContext* aCtx, diff --git a/layout/generic/nsBRFrame.cpp b/layout/generic/nsBRFrame.cpp index 108cf210424a..7a9ed768da53 100644 --- a/layout/generic/nsBRFrame.cpp +++ b/layout/generic/nsBRFrame.cpp @@ -26,28 +26,28 @@ public: friend nsIFrame* NS_NewBRFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); - virtual ContentOffsets CalcContentOffsetsFromFramePoint(nsPoint aPoint); + virtual ContentOffsets CalcContentOffsetsFromFramePoint(nsPoint aPoint) MOZ_OVERRIDE; - virtual bool PeekOffsetNoAmount(bool aForward, int32_t* aOffset); + virtual bool PeekOffsetNoAmount(bool aForward, int32_t* aOffset) MOZ_OVERRIDE; virtual bool PeekOffsetCharacter(bool aForward, int32_t* aOffset, - bool aRespectClusters = true); + bool aRespectClusters = true) MOZ_OVERRIDE; virtual bool PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect, - int32_t* aOffset, PeekWordState* aState); + int32_t* aOffset, PeekWordState* aState) MOZ_OVERRIDE; virtual nsresult Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); + nsReflowStatus& aStatus) MOZ_OVERRIDE; virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext, - InlineMinWidthData *aData); + InlineMinWidthData *aData) MOZ_OVERRIDE; virtual void AddInlinePrefWidth(nsRenderingContext *aRenderingContext, - InlinePrefWidthData *aData); - virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext); - virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext); - virtual nsIAtom* GetType() const; - virtual nscoord GetBaseline() const; + InlinePrefWidthData *aData) MOZ_OVERRIDE; + virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; + virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; + virtual nsIAtom* GetType() const MOZ_OVERRIDE; + virtual nscoord GetBaseline() const MOZ_OVERRIDE; - virtual bool IsFrameOfType(uint32_t aFlags) const + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE { return nsFrame::IsFrameOfType(aFlags & ~(nsIFrame::eReplaced | nsIFrame::eLineParticipant)); diff --git a/layout/generic/nsBulletFrame.cpp b/layout/generic/nsBulletFrame.cpp index fb76fb37c4ad..fdc8595b37dc 100644 --- a/layout/generic/nsBulletFrame.cpp +++ b/layout/generic/nsBulletFrame.cpp @@ -206,33 +206,33 @@ public: } #endif - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE { *aSnap = false; return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame(); } virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames) { + HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE { aOutFrames->AppendElement(mFrame); } virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("Bullet", TYPE_BULLET) - virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) + virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE { bool snap; return GetBounds(aBuilder, &snap); } - virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) + virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE { return new nsDisplayBulletGeometry(this, aBuilder); } virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, const nsDisplayItemGeometry* aGeometry, - nsRegion *aInvalidRegion) + nsRegion *aInvalidRegion) MOZ_OVERRIDE { const nsDisplayBulletGeometry* geometry = static_cast(aGeometry); nsBulletFrame* f = static_cast(mFrame); diff --git a/layout/generic/nsCanvasFrame.cpp b/layout/generic/nsCanvasFrame.cpp index 46d109444525..0ecb58952472 100644 --- a/layout/generic/nsCanvasFrame.cpp +++ b/layout/generic/nsCanvasFrame.cpp @@ -301,7 +301,7 @@ public: MOZ_COUNT_DTOR(nsDisplayCanvasFocus); } - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE { *aSnap = false; // This is an overestimate, but that's not a problem. @@ -310,7 +310,7 @@ public: } virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx) + nsRenderingContext* aCtx) MOZ_OVERRIDE { nsCanvasFrame* frame = static_cast(mFrame); frame->PaintFocus(*aCtx, ToReferenceFrame()); diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 03e26e8a2462..89059e38b513 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1351,7 +1351,7 @@ public: #endif virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("SelectionOverlay", TYPE_SELECTION_OVERLAY) private: int16_t mSelectionValue; diff --git a/layout/generic/nsFrameSetFrame.cpp b/layout/generic/nsFrameSetFrame.cpp index 7d9b9c01993d..ea6010f1bbfe 100644 --- a/layout/generic/nsFrameSetFrame.cpp +++ b/layout/generic/nsFrameSetFrame.cpp @@ -83,15 +83,15 @@ public: NS_DECL_FRAMEARENA_HELPERS #ifdef DEBUG_FRAME_DUMP - virtual nsresult GetFrameName(nsAString& aResult) const; + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; #endif virtual nsresult HandleEvent(nsPresContext* aPresContext, WidgetGUIEvent* aEvent, - nsEventStatus* aEventStatus); + nsEventStatus* aEventStatus) MOZ_OVERRIDE; virtual nsresult GetCursor(const nsPoint& aPoint, - nsIFrame::Cursor& aCursor); + nsIFrame::Cursor& aCursor) MOZ_OVERRIDE; virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, @@ -100,7 +100,7 @@ public: virtual nsresult Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); + nsReflowStatus& aStatus) MOZ_OVERRIDE; bool GetVisibility() { return mVisibility || mVisibilityOverride; } void SetVisibility(bool aVisibility); @@ -111,8 +111,8 @@ public: protected: nsHTMLFramesetBorderFrame(nsStyleContext* aContext, int32_t aWidth, bool aVertical, bool aVisible); virtual ~nsHTMLFramesetBorderFrame(); - virtual nscoord GetIntrinsicWidth(); - virtual nscoord GetIntrinsicHeight(); + virtual nscoord GetIntrinsicWidth() MOZ_OVERRIDE; + virtual nscoord GetIntrinsicHeight() MOZ_OVERRIDE; // the prev and next neighbors are indexes into the row (for a horizontal border) or col (for // a vertical border) of nsHTMLFramesetFrames or nsHTMLFrames @@ -137,7 +137,7 @@ public: NS_DECL_FRAMEARENA_HELPERS #ifdef DEBUG_FRAME_DUMP - virtual nsresult GetFrameName(nsAString& aResult) const + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE { return MakeFrameName(NS_LITERAL_STRING("FramesetBlank"), aResult); } @@ -150,13 +150,13 @@ public: virtual nsresult Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); + nsReflowStatus& aStatus) MOZ_OVERRIDE; protected: nsHTMLFramesetBlankFrame(nsStyleContext* aContext) : nsLeafFrame(aContext) {} virtual ~nsHTMLFramesetBlankFrame(); - virtual nscoord GetIntrinsicWidth(); - virtual nscoord GetIntrinsicHeight(); + virtual nscoord GetIntrinsicWidth() MOZ_OVERRIDE; + virtual nscoord GetIntrinsicHeight() MOZ_OVERRIDE; friend class nsHTMLFramesetFrame; friend class nsHTMLFrameset; @@ -1470,11 +1470,11 @@ public: // REVIEW: see old GetFrameForPoint // Receives events in its bounds virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames) { + HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE { aOutFrames->AppendElement(mFrame); } virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("FramesetBorder", TYPE_FRAMESET_BORDER) }; @@ -1673,7 +1673,7 @@ public: } #endif - virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx); + virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("FramesetBlank", TYPE_FRAMESET_BLANK) }; diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 5b7fb24a6344..83e6660fb7ef 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -1335,7 +1335,7 @@ public: return true; } - virtual void WillRefresh(mozilla::TimeStamp aTime) { + virtual void WillRefresh(mozilla::TimeStamp aTime) MOZ_OVERRIDE { // The callback may release "this". // We don't access members after returning, so no need for KungFuDeathGrip. ScrollFrameHelper::AsyncScrollCallback(mCallee, aTime); @@ -2196,13 +2196,13 @@ public: virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, - nsDisplayList* aList) { + nsDisplayList* aList) MOZ_OVERRIDE { SetCount(++mCount); return new (aBuilder) nsDisplayScrollLayer(aBuilder, aList, mScrolledFrame, mScrolledFrame, mScrollFrame); } virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder, - nsDisplayItem* aItem) { + nsDisplayItem* aItem) MOZ_OVERRIDE { SetCount(++mCount); return new (aBuilder) nsDisplayScrollLayer(aBuilder, aItem, aItem->Frame(), mScrolledFrame, mScrollFrame); diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index db9d8f9cb205..73c230478c21 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -536,7 +536,7 @@ public: virtual nsIFrame* GetScrolledFrame() const MOZ_OVERRIDE { return mHelper.GetScrolledFrame(); } - virtual mozilla::ScrollbarStyles GetScrollbarStyles() const { + virtual mozilla::ScrollbarStyles GetScrollbarStyles() const MOZ_OVERRIDE { return mHelper.GetScrollbarStylesFromFrame(); } virtual uint32_t GetScrollbarVisibility() const MOZ_OVERRIDE { @@ -843,7 +843,7 @@ public: virtual nsIFrame* GetScrolledFrame() const MOZ_OVERRIDE { return mHelper.GetScrolledFrame(); } - virtual mozilla::ScrollbarStyles GetScrollbarStyles() const { + virtual mozilla::ScrollbarStyles GetScrollbarStyles() const MOZ_OVERRIDE { return mHelper.GetScrollbarStylesFromFrame(); } virtual uint32_t GetScrollbarVisibility() const MOZ_OVERRIDE { diff --git a/layout/generic/nsHTMLCanvasFrame.cpp b/layout/generic/nsHTMLCanvasFrame.cpp index ab0e3eb3f8b2..fa75894c0751 100644 --- a/layout/generic/nsHTMLCanvasFrame.cpp +++ b/layout/generic/nsHTMLCanvasFrame.cpp @@ -36,7 +36,7 @@ public: NS_DISPLAY_DECL_NAME("nsDisplayCanvas", TYPE_CANVAS) virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, - bool* aSnap) { + bool* aSnap) MOZ_OVERRIDE { *aSnap = false; nsIFrame* f = Frame(); HTMLCanvasElement *canvas = @@ -48,7 +48,7 @@ public: return result; } - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) { + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE { *aSnap = true; nsHTMLCanvasFrame* f = static_cast(Frame()); return f->GetInnerArea() + ToReferenceFrame(); @@ -56,14 +56,14 @@ public: virtual already_AddRefed BuildLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) + const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE { return static_cast(mFrame)-> BuildLayer(aBuilder, aManager, this, aContainerParameters); } virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) + const ContainerLayerParameters& aParameters) MOZ_OVERRIDE { if (HTMLCanvasElement::FromContent(mFrame->GetContent())->ShouldForceInactiveLayer(aManager)) return LAYER_INACTIVE; diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index ae6b5945401f..4e1daed2ece9 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -1072,13 +1072,13 @@ public: nsDisplayAltFeedback(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) : nsDisplayItem(aBuilder, aFrame) {} - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE { *aSnap = false; return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame(); } - virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) + virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE { nsImageFrame* f = static_cast(mFrame); nsEventStates state = f->GetContent()->AsElement()->State(); diff --git a/layout/generic/nsImageMap.cpp b/layout/generic/nsImageMap.cpp index c99b530bd430..d837af07ebbd 100644 --- a/layout/generic/nsImageMap.cpp +++ b/layout/generic/nsImageMap.cpp @@ -266,9 +266,9 @@ class DefaultArea : public Area { public: DefaultArea(nsIContent* aArea); - virtual bool IsInside(nscoord x, nscoord y) const; - virtual void Draw(nsIFrame* aFrame, nsRenderingContext& aRC); - virtual void GetRect(nsIFrame* aFrame, nsRect& aRect); + virtual bool IsInside(nscoord x, nscoord y) const MOZ_OVERRIDE; + virtual void Draw(nsIFrame* aFrame, nsRenderingContext& aRC) MOZ_OVERRIDE; + virtual void GetRect(nsIFrame* aFrame, nsRect& aRect) MOZ_OVERRIDE; }; DefaultArea::DefaultArea(nsIContent* aArea) @@ -311,10 +311,10 @@ class RectArea : public Area { public: RectArea(nsIContent* aArea); - virtual void ParseCoords(const nsAString& aSpec); - virtual bool IsInside(nscoord x, nscoord y) const; - virtual void Draw(nsIFrame* aFrame, nsRenderingContext& aRC); - virtual void GetRect(nsIFrame* aFrame, nsRect& aRect); + virtual void ParseCoords(const nsAString& aSpec) MOZ_OVERRIDE; + virtual bool IsInside(nscoord x, nscoord y) const MOZ_OVERRIDE; + virtual void Draw(nsIFrame* aFrame, nsRenderingContext& aRC) MOZ_OVERRIDE; + virtual void GetRect(nsIFrame* aFrame, nsRect& aRect) MOZ_OVERRIDE; }; RectArea::RectArea(nsIContent* aArea) @@ -413,10 +413,10 @@ class PolyArea : public Area { public: PolyArea(nsIContent* aArea); - virtual void ParseCoords(const nsAString& aSpec); - virtual bool IsInside(nscoord x, nscoord y) const; - virtual void Draw(nsIFrame* aFrame, nsRenderingContext& aRC); - virtual void GetRect(nsIFrame* aFrame, nsRect& aRect); + virtual void ParseCoords(const nsAString& aSpec) MOZ_OVERRIDE; + virtual bool IsInside(nscoord x, nscoord y) const MOZ_OVERRIDE; + virtual void Draw(nsIFrame* aFrame, nsRenderingContext& aRC) MOZ_OVERRIDE; + virtual void GetRect(nsIFrame* aFrame, nsRect& aRect) MOZ_OVERRIDE; }; PolyArea::PolyArea(nsIContent* aArea) @@ -553,10 +553,10 @@ class CircleArea : public Area { public: CircleArea(nsIContent* aArea); - virtual void ParseCoords(const nsAString& aSpec); - virtual bool IsInside(nscoord x, nscoord y) const; - virtual void Draw(nsIFrame* aFrame, nsRenderingContext& aRC); - virtual void GetRect(nsIFrame* aFrame, nsRect& aRect); + virtual void ParseCoords(const nsAString& aSpec) MOZ_OVERRIDE; + virtual bool IsInside(nscoord x, nscoord y) const MOZ_OVERRIDE; + virtual void Draw(nsIFrame* aFrame, nsRenderingContext& aRC) MOZ_OVERRIDE; + virtual void GetRect(nsIFrame* aFrame, nsRect& aRect) MOZ_OVERRIDE; }; CircleArea::CircleArea(nsIContent* aArea) diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp index 722a575692d4..8d2c513625f1 100644 --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -855,23 +855,23 @@ public: } #endif - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap); + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion, - const nsRect& aAllowVisibleRegionExpansion); + const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("PluginReadback", TYPE_PLUGIN_READBACK) virtual already_AddRefed BuildLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) + const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE { return static_cast(mFrame)->BuildLayer(aBuilder, aManager, this, aContainerParameters); } virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) + const ContainerLayerParameters& aParameters) MOZ_OVERRIDE { return LAYER_ACTIVE; } @@ -925,23 +925,23 @@ public: } #endif - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap); + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion, - const nsRect& aAllowVisibleRegionExpansion); + const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("PluginVideo", TYPE_PLUGIN_VIDEO) virtual already_AddRefed BuildLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) + const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE { return static_cast(mFrame)->BuildLayer(aBuilder, aManager, this, aContainerParameters); } virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) + const ContainerLayerParameters& aParameters) MOZ_OVERRIDE { return LAYER_ACTIVE; } diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index 0bed7a3b4b00..230afc766f21 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -200,7 +200,7 @@ public: return NS_OK; } - NS_IMETHOD Notify(nsITimer *timer) + NS_IMETHOD Notify(nsITimer *timer) MOZ_OVERRIDE { if (mSelection && mPresContext) { diff --git a/layout/generic/nsSplittableFrame.h b/layout/generic/nsSplittableFrame.h index 11e51227503b..35a5eededd03 100644 --- a/layout/generic/nsSplittableFrame.h +++ b/layout/generic/nsSplittableFrame.h @@ -96,7 +96,7 @@ protected: * @see nsIFrame::GetSkipSides() * @see nsIFrame::ApplySkipSides() */ - virtual int GetSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const; + virtual int GetSkipSides(const nsHTMLReflowState* aReflowState = nullptr) const MOZ_OVERRIDE; #ifdef DEBUG virtual void DumpBaseRegressionData(nsPresContext* aPresContext, FILE* out, int32_t aIndent) MOZ_OVERRIDE; diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index c778e2eb7853..0ec392493296 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -977,7 +977,7 @@ public: mChangedBreaks(false), mExistingTextRun(aExistingTextRun) {} virtual void SetBreaks(uint32_t aOffset, uint32_t aLength, - uint8_t* aBreakBefore) { + uint8_t* aBreakBefore) MOZ_OVERRIDE { if (mTextRun->SetPotentialLineBreaks(aOffset + mOffsetIntoTextRun, aLength, aBreakBefore, mContext)) { mChangedBreaks = true; @@ -987,7 +987,7 @@ public: } virtual void SetCapitalization(uint32_t aOffset, uint32_t aLength, - bool* aCapitalize) { + bool* aCapitalize) MOZ_OVERRIDE { NS_ASSERTION(mTextRun->GetFlags() & nsTextFrameUtils::TEXT_IS_TRANSFORMED, "Text run should be transformed!"); nsTransformedTextRun* transformedTextRun = @@ -3925,12 +3925,12 @@ public: nsIFrame* aParent, nsIFrame* aPrevInFlow) MOZ_OVERRIDE; - virtual void DestroyFrom(nsIFrame* aDestructRoot); + virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; - virtual nsIFrame* GetPrevContinuation() const { + virtual nsIFrame* GetPrevContinuation() const MOZ_OVERRIDE { return mPrevContinuation; } - virtual void SetPrevContinuation(nsIFrame* aPrevContinuation) { + virtual void SetPrevContinuation(nsIFrame* aPrevContinuation) MOZ_OVERRIDE { NS_ASSERTION (!aPrevContinuation || GetType() == aPrevContinuation->GetType(), "setting a prev continuation with incorrect type!"); NS_ASSERTION (!nsSplittableFrame::IsInPrevContinuationChain(aPrevContinuation, this), @@ -3938,7 +3938,7 @@ public: mPrevContinuation = aPrevContinuation; RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION); } - virtual nsIFrame* GetPrevInFlowVirtual() const { return GetPrevInFlow(); } + virtual nsIFrame* GetPrevInFlowVirtual() const MOZ_OVERRIDE { return GetPrevInFlow(); } nsIFrame* GetPrevInFlow() const { return (GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION) ? mPrevContinuation : nullptr; } @@ -3954,15 +3954,15 @@ public: virtual nsIFrame* FirstContinuation() const MOZ_OVERRIDE; virtual void AddInlineMinWidth(nsRenderingContext *aRenderingContext, - InlineMinWidthData *aData); + InlineMinWidthData *aData) MOZ_OVERRIDE; virtual void AddInlinePrefWidth(nsRenderingContext *aRenderingContext, - InlinePrefWidthData *aData); + InlinePrefWidthData *aData) MOZ_OVERRIDE; virtual nsresult GetRenderedText(nsAString* aString = nullptr, gfxSkipChars* aSkipChars = nullptr, gfxSkipCharsIterator* aSkipIter = nullptr, uint32_t aSkippedStartOffset = 0, - uint32_t aSkippedMaxLength = UINT32_MAX) + uint32_t aSkippedMaxLength = UINT32_MAX) MOZ_OVERRIDE { return NS_ERROR_NOT_IMPLEMENTED; } // Call on a primary text frame only protected: @@ -4478,7 +4478,7 @@ public: } #endif - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) { + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE { *aSnap = false; nsRect temp = mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame(); // Bug 748228 @@ -4486,29 +4486,29 @@ public: return temp; } virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames) { + HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE { if (nsRect(ToReferenceFrame(), mFrame->GetSize()).Intersects(aRect)) { aOutFrames->AppendElement(mFrame); } } virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("Text", TYPE_TEXT) - virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) + virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE { bool snap; return GetBounds(aBuilder, &snap); } - virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) + virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE { return new nsDisplayTextGeometry(this, aBuilder); } virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, const nsDisplayItemGeometry* aGeometry, - nsRegion *aInvalidRegion) + nsRegion *aInvalidRegion) MOZ_OVERRIDE { const nsDisplayTextGeometry* geometry = static_cast(aGeometry); nsTextFrame* f = static_cast(mFrame); @@ -4526,7 +4526,7 @@ public: } } - virtual void DisableComponentAlpha() { mDisableSubpixelAA = true; } + virtual void DisableComponentAlpha() MOZ_OVERRIDE { mDisableSubpixelAA = true; } bool mDisableSubpixelAA; }; diff --git a/layout/generic/nsVideoFrame.cpp b/layout/generic/nsVideoFrame.cpp index ce1dac7e82d4..c75a05062ab3 100644 --- a/layout/generic/nsVideoFrame.cpp +++ b/layout/generic/nsVideoFrame.cpp @@ -230,7 +230,7 @@ class DispatchResizeToControls : public nsRunnable public: DispatchResizeToControls(nsIContent* aContent) : mContent(aContent) {} - NS_IMETHOD Run() { + NS_IMETHOD Run() MOZ_OVERRIDE { nsContentUtils::DispatchTrustedEvent(mContent->OwnerDoc(), mContent, NS_LITERAL_STRING("resizevideocontrols"), false, false); @@ -383,7 +383,7 @@ public: // away completely (e.g. because of a decoder error). The problem would // be especially acute if we have off-main-thread rendering. - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE { *aSnap = true; nsIFrame* f = Frame(); @@ -392,14 +392,14 @@ public: virtual already_AddRefed BuildLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aContainerParameters) + const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE { return static_cast(mFrame)->BuildLayer(aBuilder, aManager, this, aContainerParameters); } virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, LayerManager* aManager, - const ContainerLayerParameters& aParameters) + const ContainerLayerParameters& aParameters) MOZ_OVERRIDE { if (aManager->IsCompositingCheap()) { // Since ImageLayers don't require additional memory of the diff --git a/layout/mathml/nsMathMLContainerFrame.cpp b/layout/mathml/nsMathMLContainerFrame.cpp index ceac7382e726..730d0817e427 100644 --- a/layout/mathml/nsMathMLContainerFrame.cpp +++ b/layout/mathml/nsMathMLContainerFrame.cpp @@ -80,7 +80,7 @@ public: #endif virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("MathMLError", TYPE_MATHML_ERROR) }; @@ -1319,10 +1319,10 @@ nsMathMLContainerFrame::PositionRowChildFrames(nscoord aOffsetX, class ForceReflow : public nsIReflowCallback { public: - virtual bool ReflowFinished() { + virtual bool ReflowFinished() MOZ_OVERRIDE { return true; } - virtual void ReflowCallbackCanceled() {} + virtual void ReflowCallbackCanceled() MOZ_OVERRIDE {} }; // We only need one of these so we just make it a static global, no need diff --git a/layout/mathml/nsMathMLFrame.cpp b/layout/mathml/nsMathMLFrame.cpp index 2925faf95716..df214aa4bf3d 100644 --- a/layout/mathml/nsMathMLFrame.cpp +++ b/layout/mathml/nsMathMLFrame.cpp @@ -284,7 +284,7 @@ public: #endif virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("MathMLBoundingMetrics", TYPE_MATHML_BOUNDING_METRICS) private: nsRect mRect; @@ -329,7 +329,7 @@ public: #endif virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("MathMLBar", TYPE_MATHML_BAR) private: nsRect mRect; diff --git a/layout/mathml/nsMathMLmencloseFrame.cpp b/layout/mathml/nsMathMLmencloseFrame.cpp index 387753423869..81adb423abb7 100644 --- a/layout/mathml/nsMathMLmencloseFrame.cpp +++ b/layout/mathml/nsMathMLmencloseFrame.cpp @@ -724,7 +724,7 @@ public: #endif virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("MathMLMencloseNotation", TYPE_MATHML_MENCLOSE_NOTATION) private: diff --git a/layout/mathml/nsMathMLmfracFrame.cpp b/layout/mathml/nsMathMLmfracFrame.cpp index 20318c39bca1..e23a39bbd660 100644 --- a/layout/mathml/nsMathMLmfracFrame.cpp +++ b/layout/mathml/nsMathMLmfracFrame.cpp @@ -519,7 +519,7 @@ public: } #endif - virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx); + virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("MathMLSlash", TYPE_MATHML_SLASH) private: diff --git a/layout/mathml/nsMathMLmtableFrame.h b/layout/mathml/nsMathMLmtableFrame.h index 0fdcbb457588..2f7fc8d89fdc 100644 --- a/layout/mathml/nsMathMLmtableFrame.h +++ b/layout/mathml/nsMathMLmtableFrame.h @@ -194,10 +194,10 @@ public: nsIAtom* aAttribute, int32_t aModType) MOZ_OVERRIDE; - virtual uint8_t GetVerticalAlign() const; + virtual uint8_t GetVerticalAlign() const MOZ_OVERRIDE; virtual nsresult ProcessBorders(nsTableFrame* aFrame, nsDisplayListBuilder* aBuilder, - const nsDisplayListSet& aLists); + const nsDisplayListSet& aLists) MOZ_OVERRIDE; virtual int32_t GetRowSpan() MOZ_OVERRIDE; virtual int32_t GetColSpan() MOZ_OVERRIDE; @@ -246,7 +246,7 @@ public: ~(nsIFrame::eMathML | nsIFrame::eExcludesIgnorableWhitespace)); } - virtual const nsStyleText* StyleTextForLineLayout(); + virtual const nsStyleText* StyleTextForLineLayout() MOZ_OVERRIDE; virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) MOZ_OVERRIDE; protected: diff --git a/layout/printing/nsPrintEngine.cpp b/layout/printing/nsPrintEngine.cpp index 6395636e621a..fe58dd2565b9 100644 --- a/layout/printing/nsPrintEngine.cpp +++ b/layout/printing/nsPrintEngine.cpp @@ -3605,7 +3605,7 @@ public: NS_ASSERTION(mDocViewerPrint, "mDocViewerPrint is null."); } - NS_IMETHOD Run() { + NS_IMETHOD Run() MOZ_OVERRIDE { if (mDocViewerPrint) mDocViewerPrint->OnDonePrinting(); return NS_OK; diff --git a/layout/style/StyleRule.cpp b/layout/style/StyleRule.cpp index 683a9e5fc28d..4e00639e60a3 100644 --- a/layout/style/StyleRule.cpp +++ b/layout/style/StyleRule.cpp @@ -970,19 +970,19 @@ public: DOMCSSDeclarationImpl(css::StyleRule *aRule); virtual ~DOMCSSDeclarationImpl(void); - NS_IMETHOD GetParentRule(nsIDOMCSSRule **aParent); + NS_IMETHOD GetParentRule(nsIDOMCSSRule **aParent) MOZ_OVERRIDE; void DropReference(void); - virtual css::Declaration* GetCSSDeclaration(bool aAllocate); - virtual nsresult SetCSSDeclaration(css::Declaration* aDecl); - virtual void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv); - virtual nsIDocument* DocToUpdate(); + virtual css::Declaration* GetCSSDeclaration(bool aAllocate) MOZ_OVERRIDE; + virtual nsresult SetCSSDeclaration(css::Declaration* aDecl) MOZ_OVERRIDE; + virtual void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) MOZ_OVERRIDE; + virtual nsIDocument* DocToUpdate() MOZ_OVERRIDE; // Override |AddRef| and |Release| for being a member of // |DOMCSSStyleRule|. Also, we need to forward QI for cycle // collection things to DOMCSSStyleRule. NS_DECL_ISUPPORTS_INHERITED - virtual nsINode *GetParentObject() + virtual nsINode *GetParentObject() MOZ_OVERRIDE { return mRule ? mRule->GetDocument() : nullptr; } diff --git a/layout/style/nsDOMCSSAttrDeclaration.h b/layout/style/nsDOMCSSAttrDeclaration.h index 5191376154be..7bca0ceae038 100644 --- a/layout/style/nsDOMCSSAttrDeclaration.h +++ b/layout/style/nsDOMCSSAttrDeclaration.h @@ -39,7 +39,7 @@ public: virtual nsINode* GetParentObject() MOZ_OVERRIDE; NS_IMETHOD SetPropertyValue(const nsCSSProperty aPropID, - const nsAString& aValue); + const nsAString& aValue) MOZ_OVERRIDE; protected: virtual nsresult SetCSSDeclaration(mozilla::css::Declaration* aDecl) MOZ_OVERRIDE; diff --git a/layout/style/nsFontFaceLoader.h b/layout/style/nsFontFaceLoader.h index 198f1d47a97a..0a6f0686edfc 100644 --- a/layout/style/nsFontFaceLoader.h +++ b/layout/style/nsFontFaceLoader.h @@ -9,6 +9,7 @@ #ifndef nsFontFaceLoader_h_ #define nsFontFaceLoader_h_ +#include "mozilla/Attributes.h" #include "nsCOMPtr.h" #include "nsIStreamLoader.h" #include "nsIChannel.h" @@ -36,7 +37,7 @@ public: // returns whether load process successfully started or not nsresult StartLoad(gfxMixedFontFamily* aFamily, gfxProxyFontEntry* aFontToLoad, - const gfxFontFaceSrc* aFontFaceSrc); + const gfxFontFaceSrc* aFontFaceSrc) MOZ_OVERRIDE; // Called by nsFontFaceLoader when the loader has completed normally. // It's removed from the mLoaders set. @@ -48,7 +49,7 @@ public: virtual void ReplaceFontEntry(gfxMixedFontFamily* aFamily, gfxProxyFontEntry* aProxy, - gfxFontEntry* aFontEntry); + gfxFontEntry* aFontEntry) MOZ_OVERRIDE; nsCSSFontFaceRule* FindRuleForEntry(gfxFontEntry* aFontEntry); @@ -70,16 +71,16 @@ protected: gfxProxyFontEntry* aProxy, const char* aMessage, uint32_t aFlags = nsIScriptError::errorFlag, - nsresult aStatus = NS_OK); + nsresult aStatus = NS_OK) MOZ_OVERRIDE; virtual nsresult CheckFontLoad(const gfxFontFaceSrc* aFontFaceSrc, nsIPrincipal** aPrincipal, - bool* aBypassCache); + bool* aBypassCache) MOZ_OVERRIDE; virtual nsresult SyncLoadFontData(gfxProxyFontEntry* aFontToLoad, const gfxFontFaceSrc* aFontFaceSrc, uint8_t*& aBuffer, - uint32_t& aBufferLength); + uint32_t& aBufferLength) MOZ_OVERRIDE; virtual bool GetPrivateBrowsing() MOZ_OVERRIDE; diff --git a/layout/svg/SVGFEContainerFrame.cpp b/layout/svg/SVGFEContainerFrame.cpp index 62705fc81e64..0c31647ced5b 100644 --- a/layout/svg/SVGFEContainerFrame.cpp +++ b/layout/svg/SVGFEContainerFrame.cpp @@ -31,14 +31,14 @@ protected: public: NS_DECL_FRAMEARENA_HELPERS - virtual bool IsFrameOfType(uint32_t aFlags) const + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE { return SVGFEContainerFrameBase::IsFrameOfType( aFlags & ~(nsIFrame::eSVG | nsIFrame::eSVGContainer)); } #ifdef DEBUG_FRAME_DUMP - virtual nsresult GetFrameName(nsAString& aResult) const + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE { return MakeFrameName(NS_LITERAL_STRING("SVGFEContainer"), aResult); } @@ -54,13 +54,13 @@ public: * * @see nsGkAtoms::svgFEContainerFrame */ - virtual nsIAtom* GetType() const; + virtual nsIAtom* GetType() const MOZ_OVERRIDE; virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, - int32_t aModType); + int32_t aModType) MOZ_OVERRIDE; - virtual bool UpdateOverflow() { + virtual bool UpdateOverflow() MOZ_OVERRIDE { // We don't maintain a visual overflow rect return false; } diff --git a/layout/svg/SVGFEImageFrame.cpp b/layout/svg/SVGFEImageFrame.cpp index a481ecebfe82..efa5d9f92ab3 100644 --- a/layout/svg/SVGFEImageFrame.cpp +++ b/layout/svg/SVGFEImageFrame.cpp @@ -34,15 +34,15 @@ public: virtual void Init(nsIContent* aContent, nsIFrame* aParent, nsIFrame* aPrevInFlow) MOZ_OVERRIDE; - virtual void DestroyFrom(nsIFrame* aDestructRoot); + virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; - virtual bool IsFrameOfType(uint32_t aFlags) const + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE { return SVGFEImageFrameBase::IsFrameOfType(aFlags & ~(nsIFrame::eSVG)); } #ifdef DEBUG_FRAME_DUMP - virtual nsresult GetFrameName(nsAString& aResult) const + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE { return MakeFrameName(NS_LITERAL_STRING("SVGFEImage"), aResult); } @@ -53,13 +53,13 @@ public: * * @see nsGkAtoms::svgFEImageFrame */ - virtual nsIAtom* GetType() const; + virtual nsIAtom* GetType() const MOZ_OVERRIDE; virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, - int32_t aModType); + int32_t aModType) MOZ_OVERRIDE; - virtual bool UpdateOverflow() { + virtual bool UpdateOverflow() MOZ_OVERRIDE { // We don't maintain a visual overflow rect return false; } diff --git a/layout/svg/SVGFELeafFrame.cpp b/layout/svg/SVGFELeafFrame.cpp index 3d8abc542fbc..a7b04fc30822 100644 --- a/layout/svg/SVGFELeafFrame.cpp +++ b/layout/svg/SVGFELeafFrame.cpp @@ -35,13 +35,13 @@ public: nsIFrame* aPrevInFlow) MOZ_OVERRIDE; #endif - virtual bool IsFrameOfType(uint32_t aFlags) const + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE { return SVGFELeafFrameBase::IsFrameOfType(aFlags & ~(nsIFrame::eSVG)); } #ifdef DEBUG_FRAME_DUMP - virtual nsresult GetFrameName(nsAString& aResult) const + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE { return MakeFrameName(NS_LITERAL_STRING("SVGFELeaf"), aResult); } @@ -52,13 +52,13 @@ public: * * @see nsGkAtoms::svgFELeafFrame */ - virtual nsIAtom* GetType() const; + virtual nsIAtom* GetType() const MOZ_OVERRIDE; virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, - int32_t aModType); + int32_t aModType) MOZ_OVERRIDE; - virtual bool UpdateOverflow() { + virtual bool UpdateOverflow() MOZ_OVERRIDE { // We don't maintain a visual overflow rect return false; } diff --git a/layout/svg/SVGFEUnstyledLeafFrame.cpp b/layout/svg/SVGFEUnstyledLeafFrame.cpp index 99d6ca1f005d..e02ea9c00a5d 100644 --- a/layout/svg/SVGFEUnstyledLeafFrame.cpp +++ b/layout/svg/SVGFEUnstyledLeafFrame.cpp @@ -29,13 +29,13 @@ public: const nsRect& aDirtyRect, const nsDisplayListSet& aLists) MOZ_OVERRIDE {} - virtual bool IsFrameOfType(uint32_t aFlags) const + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE { return SVGFEUnstyledLeafFrameBase::IsFrameOfType(aFlags & ~(nsIFrame::eSVG)); } #ifdef DEBUG_FRAME_DUMP - virtual nsresult GetFrameName(nsAString& aResult) const + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE { return MakeFrameName(NS_LITERAL_STRING("SVGFEUnstyledLeaf"), aResult); } @@ -46,13 +46,13 @@ public: * * @see nsGkAtoms::svgFEUnstyledLeafFrame */ - virtual nsIAtom* GetType() const; + virtual nsIAtom* GetType() const MOZ_OVERRIDE; virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, - int32_t aModType); + int32_t aModType) MOZ_OVERRIDE; - virtual bool UpdateOverflow() { + virtual bool UpdateOverflow() MOZ_OVERRIDE { // We don't maintain a visual overflow rect return false; } diff --git a/layout/svg/SVGTextFrame.cpp b/layout/svg/SVGTextFrame.cpp index 087fe16edc83..9a0913ad4f16 100644 --- a/layout/svg/SVGTextFrame.cpp +++ b/layout/svg/SVGTextFrame.cpp @@ -2707,17 +2707,17 @@ public: { } - void NotifyBeforeText(nscolor aColor); - void NotifyGlyphPathEmitted(); - void NotifyBeforeSVGGlyphPainted(); - void NotifyAfterSVGGlyphPainted(); - void NotifyAfterText(); - void NotifyBeforeSelectionBackground(nscolor aColor); - void NotifySelectionBackgroundPathEmitted(); - void NotifyBeforeDecorationLine(nscolor aColor); - void NotifyDecorationLinePathEmitted(); - void NotifyBeforeSelectionDecorationLine(nscolor aColor); - void NotifySelectionDecorationLinePathEmitted(); + void NotifyBeforeText(nscolor aColor) MOZ_OVERRIDE; + void NotifyGlyphPathEmitted() MOZ_OVERRIDE; + void NotifyBeforeSVGGlyphPainted() MOZ_OVERRIDE; + void NotifyAfterSVGGlyphPainted() MOZ_OVERRIDE; + void NotifyAfterText() MOZ_OVERRIDE; + void NotifyBeforeSelectionBackground(nscolor aColor) MOZ_OVERRIDE; + void NotifySelectionBackgroundPathEmitted() MOZ_OVERRIDE; + void NotifyBeforeDecorationLine(nscolor aColor) MOZ_OVERRIDE; + void NotifyDecorationLinePathEmitted() MOZ_OVERRIDE; + void NotifyBeforeSelectionDecorationLine(nscolor aColor) MOZ_OVERRIDE; + void NotifySelectionDecorationLinePathEmitted() MOZ_OVERRIDE; private: void FillWithOpacity(); @@ -3086,9 +3086,9 @@ public: mDisableSubpixelAA = true; } virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames); + HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE; virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; private: bool mDisableSubpixelAA; }; diff --git a/layout/svg/SVGViewFrame.cpp b/layout/svg/SVGViewFrame.cpp index 218f92600d99..d841a4b60414 100644 --- a/layout/svg/SVGViewFrame.cpp +++ b/layout/svg/SVGViewFrame.cpp @@ -40,13 +40,13 @@ public: nsIFrame* aPrevInFlow) MOZ_OVERRIDE; #endif - virtual bool IsFrameOfType(uint32_t aFlags) const + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE { return SVGViewFrameBase::IsFrameOfType(aFlags & ~(nsIFrame::eSVG)); } #ifdef DEBUG_FRAME_DUMP - virtual nsresult GetFrameName(nsAString& aResult) const + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE { return MakeFrameName(NS_LITERAL_STRING("SVGView"), aResult); } @@ -57,13 +57,13 @@ public: * * @see nsGkAtoms::svgFELeafFrame */ - virtual nsIAtom* GetType() const; + virtual nsIAtom* GetType() const MOZ_OVERRIDE; virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, - int32_t aModType); + int32_t aModType) MOZ_OVERRIDE; - virtual bool UpdateOverflow() { + virtual bool UpdateOverflow() MOZ_OVERRIDE { // We don't maintain a visual overflow rect return false; } diff --git a/layout/svg/nsSVGAFrame.cpp b/layout/svg/nsSVGAFrame.cpp index 38e975dacc63..b75e9a1e7aa7 100644 --- a/layout/svg/nsSVGAFrame.cpp +++ b/layout/svg/nsSVGAFrame.cpp @@ -35,23 +35,23 @@ public: // nsIFrame: virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, - int32_t aModType); + int32_t aModType) MOZ_OVERRIDE; /** * Get the "type" of the frame * * @see nsGkAtoms::svgAFrame */ - virtual nsIAtom* GetType() const; + virtual nsIAtom* GetType() const MOZ_OVERRIDE; #ifdef DEBUG_FRAME_DUMP - virtual nsresult GetFrameName(nsAString& aResult) const + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE { return MakeFrameName(NS_LITERAL_STRING("SVGA"), aResult); } #endif // nsISVGChildFrame interface: - virtual void NotifySVGChanged(uint32_t aFlags); + virtual void NotifySVGChanged(uint32_t aFlags) MOZ_OVERRIDE; // nsSVGContainerFrame methods: virtual gfxMatrix GetCanvasTM(uint32_t aFor, diff --git a/layout/svg/nsSVGImageFrame.cpp b/layout/svg/nsSVGImageFrame.cpp index b32ac09832b7..5cf036a221fa 100644 --- a/layout/svg/nsSVGImageFrame.cpp +++ b/layout/svg/nsSVGImageFrame.cpp @@ -60,8 +60,8 @@ public: virtual nsresult PaintSVG(nsRenderingContext *aContext, const nsIntRect *aDirtyRect, nsIFrame* aTransformRoot) MOZ_OVERRIDE; - virtual nsIFrame* GetFrameForPoint(const nsPoint &aPoint); - virtual void ReflowSVG(); + virtual nsIFrame* GetFrameForPoint(const nsPoint &aPoint) MOZ_OVERRIDE; + virtual void ReflowSVG() MOZ_OVERRIDE; // nsSVGPathGeometryFrame methods: virtual uint16_t GetHitTestFlags() MOZ_OVERRIDE; @@ -69,21 +69,21 @@ public: // nsIFrame interface: virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, - int32_t aModType); + int32_t aModType) MOZ_OVERRIDE; virtual void Init(nsIContent* aContent, nsIFrame* aParent, nsIFrame* aPrevInFlow) MOZ_OVERRIDE; - virtual void DestroyFrom(nsIFrame* aDestructRoot); + virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; /** * Get the "type" of the frame * * @see nsGkAtoms::svgImageFrame */ - virtual nsIAtom* GetType() const; + virtual nsIAtom* GetType() const MOZ_OVERRIDE; #ifdef DEBUG_FRAME_DUMP - virtual nsresult GetFrameName(nsAString& aResult) const + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE { return MakeFrameName(NS_LITERAL_STRING("SVGImage"), aResult); } diff --git a/layout/svg/nsSVGIntegrationUtils.cpp b/layout/svg/nsSVGIntegrationUtils.cpp index 2091b7e1a748..bdce385e75e5 100644 --- a/layout/svg/nsSVGIntegrationUtils.cpp +++ b/layout/svg/nsSVGIntegrationUtils.cpp @@ -58,7 +58,7 @@ public: "We want the first continuation here"); } - virtual void AddBox(nsIFrame* aFrame) { + virtual void AddBox(nsIFrame* aFrame) MOZ_OVERRIDE { nsRect overflow = (aFrame == mCurrentFrame) ? mCurrentFrameOverflowArea : GetPreEffectsVisualOverflowRect(aFrame); mResult.UnionRect(mResult, overflow + aFrame->GetOffsetTo(mFirstContinuation)); @@ -384,7 +384,7 @@ public: mOffset(aOffset) {} virtual void Paint(nsRenderingContext *aContext, nsIFrame *aTarget, - const nsIntRect* aDirtyRect, nsIFrame* aTransformRoot) + const nsIntRect* aDirtyRect, nsIFrame* aTransformRoot) MOZ_OVERRIDE { BasicLayerManager* basic = static_cast(mLayerManager); basic->SetTarget(aContext->ThebesContext()); @@ -595,7 +595,7 @@ public: virtual bool operator()(gfxContext* aContext, const gfxRect& aFillRect, const GraphicsFilter& aFilter, - const gfxMatrix& aTransform); + const gfxMatrix& aTransform) MOZ_OVERRIDE; private: nsIFrame* mFrame; nsSize mPaintServerSize; diff --git a/layout/svg/nsSVGOuterSVGFrame.cpp b/layout/svg/nsSVGOuterSVGFrame.cpp index 5bc5a425452f..9158bfc7d067 100644 --- a/layout/svg/nsSVGOuterSVGFrame.cpp +++ b/layout/svg/nsSVGOuterSVGFrame.cpp @@ -507,13 +507,13 @@ public: #endif virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames); + HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE; virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, const nsDisplayItemGeometry* aGeometry, - nsRegion* aInvalidRegion); + nsRegion* aInvalidRegion) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("SVGOuterSVG", TYPE_SVG_OUTER_SVG) }; diff --git a/layout/svg/nsSVGPathGeometryFrame.h b/layout/svg/nsSVGPathGeometryFrame.h index b8d51c0bd092..38ae06f0000d 100644 --- a/layout/svg/nsSVGPathGeometryFrame.h +++ b/layout/svg/nsSVGPathGeometryFrame.h @@ -65,7 +65,7 @@ public: nsIAtom* aAttribute, int32_t aModType) MOZ_OVERRIDE; - virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext); + virtual void DidSetStyleContext(nsStyleContext* aOldStyleContext) MOZ_OVERRIDE; /** * Get the "type" of the frame diff --git a/layout/svg/nsSVGStopFrame.cpp b/layout/svg/nsSVGStopFrame.cpp index 334eff241519..c20c8c236c4c 100644 --- a/layout/svg/nsSVGStopFrame.cpp +++ b/layout/svg/nsSVGStopFrame.cpp @@ -42,22 +42,22 @@ public: virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, - int32_t aModType); + int32_t aModType) MOZ_OVERRIDE; /** * Get the "type" of the frame * * @see nsGkAtoms::svgStopFrame */ - virtual nsIAtom* GetType() const; + virtual nsIAtom* GetType() const MOZ_OVERRIDE; - virtual bool IsFrameOfType(uint32_t aFlags) const + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE { return nsSVGStopFrameBase::IsFrameOfType(aFlags & ~(nsIFrame::eSVG)); } #ifdef DEBUG_FRAME_DUMP - virtual nsresult GetFrameName(nsAString& aResult) const + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE { return MakeFrameName(NS_LITERAL_STRING("SVGStop"), aResult); } diff --git a/layout/svg/nsSVGSwitchFrame.cpp b/layout/svg/nsSVGSwitchFrame.cpp index aabd2c5e1f34..1af185510f30 100644 --- a/layout/svg/nsSVGSwitchFrame.cpp +++ b/layout/svg/nsSVGSwitchFrame.cpp @@ -38,10 +38,10 @@ public: * * @see nsGkAtoms::svgSwitchFrame */ - virtual nsIAtom* GetType() const; + virtual nsIAtom* GetType() const MOZ_OVERRIDE; #ifdef DEBUG_FRAME_DUMP - virtual nsresult GetFrameName(nsAString& aResult) const + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE { return MakeFrameName(NS_LITERAL_STRING("SVGSwitch"), aResult); } @@ -55,11 +55,11 @@ public: virtual nsresult PaintSVG(nsRenderingContext* aContext, const nsIntRect *aDirtyRect, nsIFrame* aTransformRoot) MOZ_OVERRIDE; - nsIFrame* GetFrameForPoint(const nsPoint &aPoint); - nsRect GetCoveredRegion(); - virtual void ReflowSVG(); + nsIFrame* GetFrameForPoint(const nsPoint &aPoint) MOZ_OVERRIDE; + nsRect GetCoveredRegion() MOZ_OVERRIDE; + virtual void ReflowSVG() MOZ_OVERRIDE; virtual SVGBBox GetBBoxContribution(const Matrix &aToBBoxUserspace, - uint32_t aFlags); + uint32_t aFlags) MOZ_OVERRIDE; private: nsIFrame *GetActiveChildFrame(); diff --git a/layout/svg/nsSVGUseFrame.cpp b/layout/svg/nsSVGUseFrame.cpp index 575688f4f1fb..c9a22107c2b3 100644 --- a/layout/svg/nsSVGUseFrame.cpp +++ b/layout/svg/nsSVGUseFrame.cpp @@ -38,34 +38,34 @@ public: virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, - int32_t aModType); + int32_t aModType) MOZ_OVERRIDE; - virtual void DestroyFrom(nsIFrame* aDestructRoot); + virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; /** * Get the "type" of the frame * * @see nsGkAtoms::svgUseFrame */ - virtual nsIAtom* GetType() const; + virtual nsIAtom* GetType() const MOZ_OVERRIDE; - virtual bool IsLeaf() const; + virtual bool IsLeaf() const MOZ_OVERRIDE; #ifdef DEBUG_FRAME_DUMP - virtual nsresult GetFrameName(nsAString& aResult) const + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE { return MakeFrameName(NS_LITERAL_STRING("SVGUse"), aResult); } #endif // nsISVGChildFrame interface: - virtual void ReflowSVG(); - virtual void NotifySVGChanged(uint32_t aFlags); + virtual void ReflowSVG() MOZ_OVERRIDE; + virtual void NotifySVGChanged(uint32_t aFlags) MOZ_OVERRIDE; // nsIAnonymousContentCreator - virtual nsresult CreateAnonymousContent(nsTArray& aElements); + virtual nsresult CreateAnonymousContent(nsTArray& aElements) MOZ_OVERRIDE; virtual void AppendAnonymousContentTo(nsBaseContentList& aElements, - uint32_t aFilter); + uint32_t aFilter) MOZ_OVERRIDE; private: bool mHasValidDimensions; diff --git a/layout/svg/nsSVGUtils.cpp b/layout/svg/nsSVGUtils.cpp index b480a557d321..35845299cb0a 100644 --- a/layout/svg/nsSVGUtils.cpp +++ b/layout/svg/nsSVGUtils.cpp @@ -438,7 +438,7 @@ class SVGPaintCallback : public nsSVGFilterPaintCallback { public: virtual void Paint(nsRenderingContext *aContext, nsIFrame *aTarget, - const nsIntRect* aDirtyRect, nsIFrame* aTransformRoot) + const nsIntRect* aDirtyRect, nsIFrame* aTransformRoot) MOZ_OVERRIDE { nsISVGChildFrame *svgChildFrame = do_QueryFrame(aTarget); NS_ASSERTION(svgChildFrame, "Expected SVG frame here"); diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp index b3800b55d9cc..7ce0132b8f90 100644 --- a/layout/tables/nsTableCellFrame.cpp +++ b/layout/tables/nsTableCellFrame.cpp @@ -385,12 +385,12 @@ public: #endif virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames) { + HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE { aOutFrames->AppendElement(mFrame); } virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap); + nsRenderingContext* aCtx) MOZ_OVERRIDE; + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, const nsDisplayItemGeometry* aGeometry, nsRegion *aInvalidRegion) MOZ_OVERRIDE; diff --git a/layout/tables/nsTableFrame.cpp b/layout/tables/nsTableFrame.cpp index 071abc3b25b8..2b97f8b0a245 100644 --- a/layout/tables/nsTableFrame.cpp +++ b/layout/tables/nsTableFrame.cpp @@ -1062,7 +1062,7 @@ public: const nsDisplayItemGeometry* aGeometry, nsRegion *aInvalidRegion) MOZ_OVERRIDE; virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("TableBorderBackground", TYPE_TABLE_BORDER_BACKGROUND) }; @@ -4523,7 +4523,7 @@ public: nsDelayedCalcBCBorders(nsIFrame* aFrame) : mFrame(aFrame) {} - NS_IMETHOD Run() { + NS_IMETHOD Run() MOZ_OVERRIDE { if (mFrame) { nsTableFrame* tableFrame = static_cast (mFrame.GetFrame()); if (tableFrame->NeedToCalcBCBorders()) { diff --git a/layout/tables/nsTableOuterFrame.h b/layout/tables/nsTableOuterFrame.h index 364c13c3adba..b557ee7a8e7d 100644 --- a/layout/tables/nsTableOuterFrame.h +++ b/layout/tables/nsTableOuterFrame.h @@ -24,9 +24,9 @@ public: virtual nsSize ComputeAutoSize(nsRenderingContext *aRenderingContext, nsSize aCBSize, nscoord aAvailableWidth, nsSize aMargin, nsSize aBorder, - nsSize aPadding, bool aShrinkWrap); + nsSize aPadding, bool aShrinkWrap) MOZ_OVERRIDE; - virtual nsIFrame* GetParentStyleContextFrame() const; + virtual nsIFrame* GetParentStyleContextFrame() const MOZ_OVERRIDE; #ifdef ACCESSIBILITY virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE; diff --git a/layout/tables/nsTableRowFrame.cpp b/layout/tables/nsTableRowFrame.cpp index 8ac3bf6e0df4..e941a654ef6a 100644 --- a/layout/tables/nsTableRowFrame.cpp +++ b/layout/tables/nsTableRowFrame.cpp @@ -538,7 +538,7 @@ public: const nsDisplayItemGeometry* aGeometry, nsRegion *aInvalidRegion) MOZ_OVERRIDE; virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("TableRowBackground", TYPE_TABLE_ROW_BACKGROUND) }; diff --git a/layout/tables/nsTableRowGroupFrame.cpp b/layout/tables/nsTableRowGroupFrame.cpp index 8b19e9069bed..044eda6b5046 100644 --- a/layout/tables/nsTableRowGroupFrame.cpp +++ b/layout/tables/nsTableRowGroupFrame.cpp @@ -141,7 +141,7 @@ public: const nsDisplayItemGeometry* aGeometry, nsRegion *aInvalidRegion) MOZ_OVERRIDE; virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); + nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("TableRowGroupBackground", TYPE_TABLE_ROW_GROUP_BACKGROUND) }; diff --git a/layout/xul/nsBoxFrame.cpp b/layout/xul/nsBoxFrame.cpp index b5508e186366..5fea76f1a4b3 100644 --- a/layout/xul/nsBoxFrame.cpp +++ b/layout/xul/nsBoxFrame.cpp @@ -2010,7 +2010,7 @@ public: nsIFrame* aTargetFrame) : nsDisplayWrapList(aBuilder, aFrame, aList), mTargetFrame(aTargetFrame) {} virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames); + HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("XULEventRedirector", TYPE_XUL_EVENT_REDIRECTOR) private: nsIFrame* mTargetFrame; @@ -2053,12 +2053,12 @@ public: nsXULEventRedirectorWrapper(nsIFrame* aTargetFrame) : mTargetFrame(aTargetFrame) {} virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder, - nsIFrame* aFrame, nsDisplayList* aList) { + nsIFrame* aFrame, nsDisplayList* aList) MOZ_OVERRIDE { return new (aBuilder) nsDisplayXULEventRedirector(aBuilder, aFrame, aList, mTargetFrame); } virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder, - nsDisplayItem* aItem) { + nsDisplayItem* aItem) MOZ_OVERRIDE { return new (aBuilder) nsDisplayXULEventRedirector(aBuilder, aItem->Frame(), aItem, mTargetFrame); diff --git a/layout/xul/nsDocElementBoxFrame.cpp b/layout/xul/nsDocElementBoxFrame.cpp index a7c7a20a7cac..0b7a1864e906 100644 --- a/layout/xul/nsDocElementBoxFrame.cpp +++ b/layout/xul/nsDocElementBoxFrame.cpp @@ -30,7 +30,7 @@ class nsDocElementBoxFrame : public nsBoxFrame, public nsIAnonymousContentCreator { public: - virtual void DestroyFrom(nsIFrame* aDestructRoot); + virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; friend nsIFrame* NS_NewBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); @@ -42,11 +42,11 @@ public: NS_DECL_FRAMEARENA_HELPERS // nsIAnonymousContentCreator - virtual nsresult CreateAnonymousContent(nsTArray& aElements); + virtual nsresult CreateAnonymousContent(nsTArray& aElements) MOZ_OVERRIDE; virtual void AppendAnonymousContentTo(nsBaseContentList& aElements, - uint32_t aFilter); + uint32_t aFilter) MOZ_OVERRIDE; - virtual bool IsFrameOfType(uint32_t aFlags) const + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE { // Override nsBoxFrame. if (aFlags & (nsIFrame::eReplacedContainsBlock | nsIFrame::eReplaced)) @@ -55,7 +55,7 @@ public: } #ifdef DEBUG_FRAME_DUMP - virtual nsresult GetFrameName(nsAString& aResult) const; + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; #endif private: nsCOMPtr mPopupgroupContent; diff --git a/layout/xul/nsImageBoxFrame.cpp b/layout/xul/nsImageBoxFrame.cpp index 400b3a93aff6..fe605a5b7026 100644 --- a/layout/xul/nsImageBoxFrame.cpp +++ b/layout/xul/nsImageBoxFrame.cpp @@ -61,7 +61,7 @@ public: nsImageBoxFrameEvent(nsIContent *content, uint32_t message) : mContent(content), mMessage(message) {} - NS_IMETHOD Run(); + NS_IMETHOD Run() MOZ_OVERRIDE; private: nsCOMPtr mContent; diff --git a/layout/xul/nsListBoxObject.cpp b/layout/xul/nsListBoxObject.cpp index 3460f9485e07..8464e29f21a9 100644 --- a/layout/xul/nsListBoxObject.cpp +++ b/layout/xul/nsListBoxObject.cpp @@ -22,13 +22,13 @@ public: NS_DECL_NSILISTBOXOBJECT // nsPIListBoxObject - virtual nsListBoxBodyFrame* GetListBoxBody(bool aFlush); + virtual nsListBoxBodyFrame* GetListBoxBody(bool aFlush) MOZ_OVERRIDE; nsListBoxObject(); // nsPIBoxObject - virtual void Clear(); - virtual void ClearCachedValues(); + virtual void Clear() MOZ_OVERRIDE; + virtual void ClearCachedValues() MOZ_OVERRIDE; protected: nsListBoxBodyFrame *mListBoxBody; diff --git a/layout/xul/nsMenuBarFrame.cpp b/layout/xul/nsMenuBarFrame.cpp index 0881b4f64152..4fe4c4466057 100644 --- a/layout/xul/nsMenuBarFrame.cpp +++ b/layout/xul/nsMenuBarFrame.cpp @@ -291,7 +291,7 @@ public: { } - NS_IMETHOD Run() + NS_IMETHOD Run() MOZ_OVERRIDE { nsXULPopupManager* pm = nsXULPopupManager::GetInstance(); if (!pm) diff --git a/layout/xul/nsMenuFrame.cpp b/layout/xul/nsMenuFrame.cpp index cb549aa9b20e..5c843d9f54f1 100644 --- a/layout/xul/nsMenuFrame.cpp +++ b/layout/xul/nsMenuFrame.cpp @@ -76,7 +76,7 @@ public: { } - NS_IMETHOD Run() + NS_IMETHOD Run() MOZ_OVERRIDE { nsAutoString domEventToFire; @@ -123,7 +123,7 @@ public: { } - NS_IMETHOD Run() + NS_IMETHOD Run() MOZ_OVERRIDE { nsMenuFrame* frame = static_cast(mFrame.GetFrame()); NS_ENSURE_STATE(frame); @@ -220,7 +220,7 @@ public: { } - virtual bool ReflowFinished() + virtual bool ReflowFinished() MOZ_OVERRIDE { bool shouldFlush = false; nsMenuFrame* menu = do_QueryFrame(mWeakFrame.GetFrame()); @@ -232,7 +232,7 @@ public: return shouldFlush; } - virtual void ReflowCallbackCanceled() + virtual void ReflowCallbackCanceled() MOZ_OVERRIDE { delete this; } diff --git a/layout/xul/nsMenuPopupFrame.cpp b/layout/xul/nsMenuPopupFrame.cpp index cfb95d28b178..97a75feac6fd 100644 --- a/layout/xul/nsMenuPopupFrame.cpp +++ b/layout/xul/nsMenuPopupFrame.cpp @@ -341,7 +341,7 @@ public: { } - NS_IMETHOD Run() + NS_IMETHOD Run() MOZ_OVERRIDE { WidgetMouseEvent event(true, NS_XUL_POPUP_SHOWN, nullptr, WidgetMouseEvent::eReal); diff --git a/layout/xul/nsProgressMeterFrame.cpp b/layout/xul/nsProgressMeterFrame.cpp index f4f1565c82ce..b059753985a9 100644 --- a/layout/xul/nsProgressMeterFrame.cpp +++ b/layout/xul/nsProgressMeterFrame.cpp @@ -82,7 +82,7 @@ class nsAsyncProgressMeterInit MOZ_FINAL : public nsIReflowCallback public: nsAsyncProgressMeterInit(nsIFrame* aFrame) : mWeakFrame(aFrame) {} - virtual bool ReflowFinished() + virtual bool ReflowFinished() MOZ_OVERRIDE { bool shouldFlush = false; nsIFrame* frame = mWeakFrame.GetFrame(); @@ -95,7 +95,7 @@ public: return shouldFlush; } - virtual void ReflowCallbackCanceled() + virtual void ReflowCallbackCanceled() MOZ_OVERRIDE { delete this; } diff --git a/layout/xul/nsRootBoxFrame.cpp b/layout/xul/nsRootBoxFrame.cpp index 670a6829f6ed..70cfdd885817 100644 --- a/layout/xul/nsRootBoxFrame.cpp +++ b/layout/xul/nsRootBoxFrame.cpp @@ -51,28 +51,28 @@ public: NS_DECL_QUERYFRAME NS_DECL_FRAMEARENA_HELPERS - virtual nsPopupSetFrame* GetPopupSetFrame(); - virtual void SetPopupSetFrame(nsPopupSetFrame* aPopupSet); - virtual nsIContent* GetDefaultTooltip(); - virtual void SetDefaultTooltip(nsIContent* aTooltip); - virtual nsresult AddTooltipSupport(nsIContent* aNode); - virtual nsresult RemoveTooltipSupport(nsIContent* aNode); + virtual nsPopupSetFrame* GetPopupSetFrame() MOZ_OVERRIDE; + virtual void SetPopupSetFrame(nsPopupSetFrame* aPopupSet) MOZ_OVERRIDE; + virtual nsIContent* GetDefaultTooltip() MOZ_OVERRIDE; + virtual void SetDefaultTooltip(nsIContent* aTooltip) MOZ_OVERRIDE; + virtual nsresult AddTooltipSupport(nsIContent* aNode) MOZ_OVERRIDE; + virtual nsresult RemoveTooltipSupport(nsIContent* aNode) MOZ_OVERRIDE; virtual nsresult AppendFrames(ChildListID aListID, - nsFrameList& aFrameList); + nsFrameList& aFrameList) MOZ_OVERRIDE; virtual nsresult InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame, - nsFrameList& aFrameList); + nsFrameList& aFrameList) MOZ_OVERRIDE; virtual nsresult RemoveFrame(ChildListID aListID, - nsIFrame* aOldFrame); + nsIFrame* aOldFrame) MOZ_OVERRIDE; virtual nsresult Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, - nsReflowStatus& aStatus); + nsReflowStatus& aStatus) MOZ_OVERRIDE; virtual nsresult HandleEvent(nsPresContext* aPresContext, WidgetGUIEvent* aEvent, - nsEventStatus* aEventStatus); + nsEventStatus* aEventStatus) MOZ_OVERRIDE; virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsRect& aDirtyRect, @@ -83,9 +83,9 @@ public: * * @see nsGkAtoms::rootFrame */ - virtual nsIAtom* GetType() const; + virtual nsIAtom* GetType() const MOZ_OVERRIDE; - virtual bool IsFrameOfType(uint32_t aFlags) const + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE { // Override bogus IsFrameOfType in nsBoxFrame. if (aFlags & (nsIFrame::eReplacedContainsBlock | nsIFrame::eReplaced)) @@ -94,7 +94,7 @@ public: } #ifdef DEBUG_FRAME_DUMP - virtual nsresult GetFrameName(nsAString& aResult) const; + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; #endif nsPopupSetFrame* mPopupSetFrame; diff --git a/layout/xul/nsScrollBoxFrame.cpp b/layout/xul/nsScrollBoxFrame.cpp index 620e49fa1d08..3f226768aeb5 100644 --- a/layout/xul/nsScrollBoxFrame.cpp +++ b/layout/xul/nsScrollBoxFrame.cpp @@ -22,23 +22,23 @@ public: friend nsIFrame* NS_NewAutoRepeatBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); - virtual void DestroyFrom(nsIFrame* aDestructRoot); + virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsIAtom* aAttribute, - int32_t aModType); + int32_t aModType) MOZ_OVERRIDE; virtual nsresult HandleEvent(nsPresContext* aPresContext, WidgetGUIEvent* aEvent, - nsEventStatus* aEventStatus); + nsEventStatus* aEventStatus) MOZ_OVERRIDE; NS_IMETHOD HandlePress(nsPresContext* aPresContext, WidgetGUIEvent* aEvent, - nsEventStatus* aEventStatus); + nsEventStatus* aEventStatus) MOZ_OVERRIDE; NS_IMETHOD HandleRelease(nsPresContext* aPresContext, WidgetGUIEvent* aEvent, - nsEventStatus* aEventStatus); + nsEventStatus* aEventStatus) MOZ_OVERRIDE; protected: nsAutoRepeatBoxFrame(nsIPresShell* aPresShell, nsStyleContext* aContext): diff --git a/layout/xul/nsTextBoxFrame.cpp b/layout/xul/nsTextBoxFrame.cpp index d05a61fa8ae6..aa339026897d 100644 --- a/layout/xul/nsTextBoxFrame.cpp +++ b/layout/xul/nsTextBoxFrame.cpp @@ -166,7 +166,7 @@ public: { } - virtual bool ReflowFinished() + virtual bool ReflowFinished() MOZ_OVERRIDE { bool shouldFlush = false; nsTextBoxFrame* frame = @@ -178,7 +178,7 @@ public: return shouldFlush; } - virtual void ReflowCallbackCanceled() + virtual void ReflowCallbackCanceled() MOZ_OVERRIDE { delete this; } @@ -293,13 +293,13 @@ public: #endif virtual void Paint(nsDisplayListBuilder* aBuilder, - nsRenderingContext* aCtx); - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap); + nsRenderingContext* aCtx) MOZ_OVERRIDE; + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("XULTextBox", TYPE_XUL_TEXT_BOX) - virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder); + virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; - virtual void DisableComponentAlpha() { mDisableSubpixelAA = true; } + virtual void DisableComponentAlpha() MOZ_OVERRIDE { mDisableSubpixelAA = true; } void PaintTextToContext(nsRenderingContext* aCtx, nsPoint aOffset, diff --git a/layout/xul/tree/nsTreeBodyFrame.cpp b/layout/xul/tree/nsTreeBodyFrame.cpp index a90ef4f88d09..e5604b604311 100644 --- a/layout/xul/tree/nsTreeBodyFrame.cpp +++ b/layout/xul/tree/nsTreeBodyFrame.cpp @@ -4654,7 +4654,7 @@ class nsOverflowChecker : public nsRunnable { public: nsOverflowChecker(nsTreeBodyFrame* aFrame) : mFrame(aFrame) {} - NS_IMETHOD Run() + NS_IMETHOD Run() MOZ_OVERRIDE { if (mFrame.IsAlive()) { nsTreeBodyFrame* tree = static_cast(mFrame.GetFrame()); diff --git a/layout/xul/tree/nsTreeColFrame.cpp b/layout/xul/tree/nsTreeColFrame.cpp index 0842e0cb1304..cb074307fba6 100644 --- a/layout/xul/tree/nsTreeColFrame.cpp +++ b/layout/xul/tree/nsTreeColFrame.cpp @@ -66,7 +66,7 @@ public: #endif virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames); + HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("XULTreeColSplitterTarget", TYPE_XUL_TREE_COL_SPLITTER_TARGET) }; From e53280194e1f8cea75cbd41c67a476f653c724cf Mon Sep 17 00:00:00 2001 From: Arnaud Sourioux Date: Mon, 24 Feb 2014 09:41:56 -0500 Subject: [PATCH 13/48] Bug 974687 - Part 2: Fix more than 80cols issues caused by MOZ_OVERRIDE annotation. r=dholbert --- layout/base/nsDisplayList.h | 15 ++++++++++----- layout/forms/nsButtonFrameRenderer.cpp | 9 ++++++--- layout/forms/nsFieldSetFrame.cpp | 3 ++- layout/generic/TextOverflow.cpp | 3 ++- layout/generic/nsBRFrame.cpp | 5 +++-- layout/generic/nsBulletFrame.cpp | 6 ++++-- layout/generic/nsCanvasFrame.cpp | 3 ++- layout/generic/nsFrameSetFrame.cpp | 6 ++++-- layout/generic/nsHTMLCanvasFrame.cpp | 3 ++- layout/generic/nsImageFrame.cpp | 6 ++++-- layout/generic/nsObjectFrame.cpp | 6 ++++-- layout/generic/nsTextFrame.cpp | 14 ++++++++++---- layout/mathml/nsMathMLmfracFrame.cpp | 3 ++- layout/svg/SVGTextFrame.cpp | 3 ++- layout/svg/nsSVGIntegrationUtils.cpp | 3 ++- layout/svg/nsSVGOuterSVGFrame.cpp | 3 ++- layout/svg/nsSVGUtils.cpp | 3 ++- layout/tables/nsTableCellFrame.cpp | 6 ++++-- layout/xul/nsBoxFrame.cpp | 6 ++++-- layout/xul/nsTextBoxFrame.cpp | 7 +++++-- layout/xul/tree/nsTreeColFrame.cpp | 3 ++- 21 files changed, 78 insertions(+), 38 deletions(-) diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index bcac696cc47b..be5de2252a4d 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -1731,7 +1731,8 @@ public: } #endif - virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE { + virtual void Paint(nsDisplayListBuilder* aBuilder, + nsRenderingContext* aCtx) MOZ_OVERRIDE { mPaint(mFrame, aCtx, mVisibleRect, ToReferenceFrame()); } NS_DISPLAY_DECL_NAME(mName, mType) @@ -2596,7 +2597,8 @@ public: virtual ~nsDisplayMixBlendMode(); #endif - nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; + nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, + bool* aSnap) MOZ_OVERRIDE; virtual already_AddRefed BuildLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager, @@ -2923,15 +2925,18 @@ public: virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE; - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE { + HitTestState* aState, + nsTArray *aOutFrames) MOZ_OVERRIDE; + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, + bool* aSnap) MOZ_OVERRIDE { *aSnap = false; return mEffectsBounds + ToReferenceFrame(); } virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion, const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; - virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) MOZ_OVERRIDE; + virtual bool TryMerge(nsDisplayListBuilder* aBuilder, + nsDisplayItem* aItem) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("SVGEffects", TYPE_SVG_EFFECTS) virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder, diff --git a/layout/forms/nsButtonFrameRenderer.cpp b/layout/forms/nsButtonFrameRenderer.cpp index 2d823a3a2880..9ca0bf3e9d34 100644 --- a/layout/forms/nsButtonFrameRenderer.cpp +++ b/layout/forms/nsButtonFrameRenderer.cpp @@ -74,7 +74,8 @@ public: virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, + bool* aSnap) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("ButtonBoxShadowOuter", TYPE_BUTTON_BOX_SHADOW_OUTER) private: nsButtonFrameRenderer* mBFR; @@ -112,12 +113,14 @@ public: #endif virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE { + HitTestState* aState, + nsTArray *aOutFrames) MOZ_OVERRIDE { aOutFrames->AppendElement(mFrame); } virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, + bool* aSnap) MOZ_OVERRIDE; virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, const nsDisplayItemGeometry* aGeometry, nsRegion *aInvalidRegion) MOZ_OVERRIDE; diff --git a/layout/forms/nsFieldSetFrame.cpp b/layout/forms/nsFieldSetFrame.cpp index 93afd484f285..205204c6543d 100644 --- a/layout/forms/nsFieldSetFrame.cpp +++ b/layout/forms/nsFieldSetFrame.cpp @@ -106,7 +106,8 @@ public: #endif virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE; + HitTestState* aState, + nsTArray *aOutFrames) MOZ_OVERRIDE; virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, diff --git a/layout/generic/TextOverflow.cpp b/layout/generic/TextOverflow.cpp index d62468125e2c..c95b9c705bd0 100644 --- a/layout/generic/TextOverflow.cpp +++ b/layout/generic/TextOverflow.cpp @@ -167,7 +167,8 @@ public: MOZ_COUNT_DTOR(nsDisplayTextOverflowMarker); } #endif - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE { + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, + bool* aSnap) MOZ_OVERRIDE { *aSnap = false; nsRect shadowRect = nsLayoutUtils::GetTextShadowRectsUnion(mRect, mFrame); diff --git a/layout/generic/nsBRFrame.cpp b/layout/generic/nsBRFrame.cpp index 7a9ed768da53..3cf28195cf89 100644 --- a/layout/generic/nsBRFrame.cpp +++ b/layout/generic/nsBRFrame.cpp @@ -31,8 +31,9 @@ public: virtual bool PeekOffsetNoAmount(bool aForward, int32_t* aOffset) MOZ_OVERRIDE; virtual bool PeekOffsetCharacter(bool aForward, int32_t* aOffset, bool aRespectClusters = true) MOZ_OVERRIDE; - virtual bool PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, bool aIsKeyboardSelect, - int32_t* aOffset, PeekWordState* aState) MOZ_OVERRIDE; + virtual bool PeekOffsetWord(bool aForward, bool aWordSelectEatSpace, + bool aIsKeyboardSelect, int32_t* aOffset, + PeekWordState* aState) MOZ_OVERRIDE; virtual nsresult Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, diff --git a/layout/generic/nsBulletFrame.cpp b/layout/generic/nsBulletFrame.cpp index fdc8595b37dc..eabbb7bad81d 100644 --- a/layout/generic/nsBulletFrame.cpp +++ b/layout/generic/nsBulletFrame.cpp @@ -206,13 +206,15 @@ public: } #endif - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, + bool* aSnap) MOZ_OVERRIDE { *aSnap = false; return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame(); } virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE { + HitTestState* aState, + nsTArray *aOutFrames) MOZ_OVERRIDE { aOutFrames->AppendElement(mFrame); } virtual void Paint(nsDisplayListBuilder* aBuilder, diff --git a/layout/generic/nsCanvasFrame.cpp b/layout/generic/nsCanvasFrame.cpp index 0ecb58952472..07baddadc756 100644 --- a/layout/generic/nsCanvasFrame.cpp +++ b/layout/generic/nsCanvasFrame.cpp @@ -301,7 +301,8 @@ public: MOZ_COUNT_DTOR(nsDisplayCanvasFocus); } - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, + bool* aSnap) MOZ_OVERRIDE { *aSnap = false; // This is an overestimate, but that's not a problem. diff --git a/layout/generic/nsFrameSetFrame.cpp b/layout/generic/nsFrameSetFrame.cpp index ea6010f1bbfe..5bca66608e42 100644 --- a/layout/generic/nsFrameSetFrame.cpp +++ b/layout/generic/nsFrameSetFrame.cpp @@ -1470,7 +1470,8 @@ public: // REVIEW: see old GetFrameForPoint // Receives events in its bounds virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE { + HitTestState* aState, + nsTArray *aOutFrames) MOZ_OVERRIDE { aOutFrames->AppendElement(mFrame); } virtual void Paint(nsDisplayListBuilder* aBuilder, @@ -1673,7 +1674,8 @@ public: } #endif - virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; + virtual void Paint(nsDisplayListBuilder* aBuilder, + nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("FramesetBlank", TYPE_FRAMESET_BLANK) }; diff --git a/layout/generic/nsHTMLCanvasFrame.cpp b/layout/generic/nsHTMLCanvasFrame.cpp index fa75894c0751..fffdfc370f69 100644 --- a/layout/generic/nsHTMLCanvasFrame.cpp +++ b/layout/generic/nsHTMLCanvasFrame.cpp @@ -48,7 +48,8 @@ public: return result; } - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE { + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, + bool* aSnap) MOZ_OVERRIDE { *aSnap = true; nsHTMLCanvasFrame* f = static_cast(Frame()); return f->GetInnerArea() + ToReferenceFrame(); diff --git a/layout/generic/nsImageFrame.cpp b/layout/generic/nsImageFrame.cpp index 4e1daed2ece9..917defe4fcea 100644 --- a/layout/generic/nsImageFrame.cpp +++ b/layout/generic/nsImageFrame.cpp @@ -1072,13 +1072,15 @@ public: nsDisplayAltFeedback(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) : nsDisplayItem(aBuilder, aFrame) {} - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, + bool* aSnap) MOZ_OVERRIDE { *aSnap = false; return mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame(); } - virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE + virtual void Paint(nsDisplayListBuilder* aBuilder, + nsRenderingContext* aCtx) MOZ_OVERRIDE { nsImageFrame* f = static_cast(mFrame); nsEventStates state = f->GetContent()->AsElement()->State(); diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp index 8d2c513625f1..2a1b634ff69c 100644 --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -855,7 +855,8 @@ public: } #endif - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, + bool* aSnap) MOZ_OVERRIDE; virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion, const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; @@ -925,7 +926,8 @@ public: } #endif - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, + bool* aSnap) MOZ_OVERRIDE; virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion, const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE; diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 0ec392493296..eb5f0b283b18 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -3938,7 +3938,9 @@ public: mPrevContinuation = aPrevContinuation; RemoveStateBits(NS_FRAME_IS_FLUID_CONTINUATION); } - virtual nsIFrame* GetPrevInFlowVirtual() const MOZ_OVERRIDE { return GetPrevInFlow(); } + virtual nsIFrame* GetPrevInFlowVirtual() const MOZ_OVERRIDE { + return GetPrevInFlow(); + } nsIFrame* GetPrevInFlow() const { return (GetStateBits() & NS_FRAME_IS_FLUID_CONTINUATION) ? mPrevContinuation : nullptr; } @@ -4478,7 +4480,8 @@ public: } #endif - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE { + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, + bool* aSnap) MOZ_OVERRIDE { *aSnap = false; nsRect temp = mFrame->GetVisualOverflowRectRelativeToSelf() + ToReferenceFrame(); // Bug 748228 @@ -4486,7 +4489,8 @@ public: return temp; } virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE { + HitTestState* aState, + nsTArray *aOutFrames) MOZ_OVERRIDE { if (nsRect(ToReferenceFrame(), mFrame->GetSize()).Intersects(aRect)) { aOutFrames->AppendElement(mFrame); } @@ -4526,7 +4530,9 @@ public: } } - virtual void DisableComponentAlpha() MOZ_OVERRIDE { mDisableSubpixelAA = true; } + virtual void DisableComponentAlpha() MOZ_OVERRIDE { + mDisableSubpixelAA = true; + } bool mDisableSubpixelAA; }; diff --git a/layout/mathml/nsMathMLmfracFrame.cpp b/layout/mathml/nsMathMLmfracFrame.cpp index e23a39bbd660..a988171e7593 100644 --- a/layout/mathml/nsMathMLmfracFrame.cpp +++ b/layout/mathml/nsMathMLmfracFrame.cpp @@ -519,7 +519,8 @@ public: } #endif - virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; + virtual void Paint(nsDisplayListBuilder* aBuilder, + nsRenderingContext* aCtx) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("MathMLSlash", TYPE_MATHML_SLASH) private: diff --git a/layout/svg/SVGTextFrame.cpp b/layout/svg/SVGTextFrame.cpp index 9a0913ad4f16..28babedf5d57 100644 --- a/layout/svg/SVGTextFrame.cpp +++ b/layout/svg/SVGTextFrame.cpp @@ -3086,7 +3086,8 @@ public: mDisableSubpixelAA = true; } virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE; + HitTestState* aState, + nsTArray *aOutFrames) MOZ_OVERRIDE; virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; private: diff --git a/layout/svg/nsSVGIntegrationUtils.cpp b/layout/svg/nsSVGIntegrationUtils.cpp index bdce385e75e5..8dcb72c4dbb8 100644 --- a/layout/svg/nsSVGIntegrationUtils.cpp +++ b/layout/svg/nsSVGIntegrationUtils.cpp @@ -384,7 +384,8 @@ public: mOffset(aOffset) {} virtual void Paint(nsRenderingContext *aContext, nsIFrame *aTarget, - const nsIntRect* aDirtyRect, nsIFrame* aTransformRoot) MOZ_OVERRIDE + const nsIntRect* aDirtyRect, + nsIFrame* aTransformRoot) MOZ_OVERRIDE { BasicLayerManager* basic = static_cast(mLayerManager); basic->SetTarget(aContext->ThebesContext()); diff --git a/layout/svg/nsSVGOuterSVGFrame.cpp b/layout/svg/nsSVGOuterSVGFrame.cpp index 9158bfc7d067..81ae044367a2 100644 --- a/layout/svg/nsSVGOuterSVGFrame.cpp +++ b/layout/svg/nsSVGOuterSVGFrame.cpp @@ -507,7 +507,8 @@ public: #endif virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE; + HitTestState* aState, + nsTArray *aOutFrames) MOZ_OVERRIDE; virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; diff --git a/layout/svg/nsSVGUtils.cpp b/layout/svg/nsSVGUtils.cpp index 35845299cb0a..dbc51871c3ba 100644 --- a/layout/svg/nsSVGUtils.cpp +++ b/layout/svg/nsSVGUtils.cpp @@ -438,7 +438,8 @@ class SVGPaintCallback : public nsSVGFilterPaintCallback { public: virtual void Paint(nsRenderingContext *aContext, nsIFrame *aTarget, - const nsIntRect* aDirtyRect, nsIFrame* aTransformRoot) MOZ_OVERRIDE + const nsIntRect* aDirtyRect, + nsIFrame* aTransformRoot) MOZ_OVERRIDE { nsISVGChildFrame *svgChildFrame = do_QueryFrame(aTarget); NS_ASSERTION(svgChildFrame, "Expected SVG frame here"); diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp index 7ce0132b8f90..14bce44eb5bc 100644 --- a/layout/tables/nsTableCellFrame.cpp +++ b/layout/tables/nsTableCellFrame.cpp @@ -385,12 +385,14 @@ public: #endif virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE { + HitTestState* aState, + nsTArray *aOutFrames) MOZ_OVERRIDE { aOutFrames->AppendElement(mFrame); } virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, + bool* aSnap) MOZ_OVERRIDE; virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, const nsDisplayItemGeometry* aGeometry, nsRegion *aInvalidRegion) MOZ_OVERRIDE; diff --git a/layout/xul/nsBoxFrame.cpp b/layout/xul/nsBoxFrame.cpp index 5fea76f1a4b3..db55758c643d 100644 --- a/layout/xul/nsBoxFrame.cpp +++ b/layout/xul/nsBoxFrame.cpp @@ -2010,7 +2010,8 @@ public: nsIFrame* aTargetFrame) : nsDisplayWrapList(aBuilder, aFrame, aList), mTargetFrame(aTargetFrame) {} virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE; + HitTestState* aState, + nsTArray *aOutFrames) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("XULEventRedirector", TYPE_XUL_EVENT_REDIRECTOR) private: nsIFrame* mTargetFrame; @@ -2053,7 +2054,8 @@ public: nsXULEventRedirectorWrapper(nsIFrame* aTargetFrame) : mTargetFrame(aTargetFrame) {} virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder, - nsIFrame* aFrame, nsDisplayList* aList) MOZ_OVERRIDE { + nsIFrame* aFrame, + nsDisplayList* aList) MOZ_OVERRIDE { return new (aBuilder) nsDisplayXULEventRedirector(aBuilder, aFrame, aList, mTargetFrame); } diff --git a/layout/xul/nsTextBoxFrame.cpp b/layout/xul/nsTextBoxFrame.cpp index aa339026897d..6b295137ae28 100644 --- a/layout/xul/nsTextBoxFrame.cpp +++ b/layout/xul/nsTextBoxFrame.cpp @@ -294,12 +294,15 @@ public: virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; - virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE; + virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, + bool* aSnap) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("XULTextBox", TYPE_XUL_TEXT_BOX) virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE; - virtual void DisableComponentAlpha() MOZ_OVERRIDE { mDisableSubpixelAA = true; } + virtual void DisableComponentAlpha() MOZ_OVERRIDE { + mDisableSubpixelAA = true; + } void PaintTextToContext(nsRenderingContext* aCtx, nsPoint aOffset, diff --git a/layout/xul/tree/nsTreeColFrame.cpp b/layout/xul/tree/nsTreeColFrame.cpp index cb074307fba6..cd230a082139 100644 --- a/layout/xul/tree/nsTreeColFrame.cpp +++ b/layout/xul/tree/nsTreeColFrame.cpp @@ -66,7 +66,8 @@ public: #endif virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, - HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE; + HitTestState* aState, + nsTArray *aOutFrames) MOZ_OVERRIDE; NS_DISPLAY_DECL_NAME("XULTreeColSplitterTarget", TYPE_XUL_TREE_COL_SPLITTER_TARGET) }; From a0392d812ea859be67f7372123c6182c32e33821 Mon Sep 17 00:00:00 2001 From: Sankha Narayan Guria Date: Fri, 21 Feb 2014 21:17:22 +0530 Subject: [PATCH 14/48] Bug 975412 - Fix length properties of Map and Set constructors. r=jorendorff --- js/src/builtin/MapObject.cpp | 2 +- js/src/jit-test/tests/collections/Map-surfaces-1.js | 2 +- js/src/jit-test/tests/collections/Set-surfaces-1.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/js/src/builtin/MapObject.cpp b/js/src/builtin/MapObject.cpp index 004a4882e4bb..023e08878093 100644 --- a/js/src/builtin/MapObject.cpp +++ b/js/src/builtin/MapObject.cpp @@ -1048,7 +1048,7 @@ InitClass(JSContext *cx, Handle global, const Class *clasp, JSPro return nullptr; proto->setPrivate(nullptr); - Rooted ctor(cx, global->createConstructor(cx, construct, ClassName(key, cx), 1)); + Rooted ctor(cx, global->createConstructor(cx, construct, ClassName(key, cx), 0)); if (!ctor || !LinkConstructorAndPrototype(cx, ctor, proto) || !DefinePropertiesAndBrand(cx, proto, properties, methods) || diff --git a/js/src/jit-test/tests/collections/Map-surfaces-1.js b/js/src/jit-test/tests/collections/Map-surfaces-1.js index 254ad0312ca8..9931e7c49bc3 100644 --- a/js/src/jit-test/tests/collections/Map-surfaces-1.js +++ b/js/src/jit-test/tests/collections/Map-surfaces-1.js @@ -9,7 +9,7 @@ assertEq(desc.writable, true); assertEq(typeof Map, 'function'); assertEq(Object.keys(Map).length, 0); -assertEq(Map.length, 1); +assertEq(Map.length, 0); assertEq(Map.name, "Map"); assertEq(Object.getPrototypeOf(Map.prototype), Object.prototype); diff --git a/js/src/jit-test/tests/collections/Set-surfaces-1.js b/js/src/jit-test/tests/collections/Set-surfaces-1.js index bee9b78a8f03..73cac4c1a313 100644 --- a/js/src/jit-test/tests/collections/Set-surfaces-1.js +++ b/js/src/jit-test/tests/collections/Set-surfaces-1.js @@ -9,7 +9,7 @@ assertEq(desc.writable, true); assertEq(typeof Set, 'function'); assertEq(Object.keys(Set).length, 0); -assertEq(Set.length, 1); +assertEq(Set.length, 0); assertEq(Set.name, "Set"); assertEq(Object.getPrototypeOf(Set.prototype), Object.prototype); From de3035424b6c197fcd371f902128ee0dd37ee099 Mon Sep 17 00:00:00 2001 From: "Byron Campen [:bwc]" Date: Thu, 19 Dec 2013 16:19:05 -0800 Subject: [PATCH 15/48] Bug 786234 - Part 2: Implementation of the filtering logic itself plus a unit-test. r=abr --- media/webrtc/signaling/signaling.gyp | 2 + .../src/mediapipeline/MediaPipelineFilter.cpp | 88 ++++++++++ .../src/mediapipeline/MediaPipelineFilter.h | 83 ++++++++++ .../signaling/test/mediapipeline_unittest.cpp | 156 ++++++++++++++++++ media/webrtc/signaling/test/moz.build | 1 + 5 files changed, 330 insertions(+) create mode 100644 media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp create mode 100644 media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.h diff --git a/media/webrtc/signaling/signaling.gyp b/media/webrtc/signaling/signaling.gyp index 00bbd85f402a..5c48579ca8f3 100644 --- a/media/webrtc/signaling/signaling.gyp +++ b/media/webrtc/signaling/signaling.gyp @@ -155,6 +155,8 @@ # Media pipeline './src/mediapipeline/MediaPipeline.h', './src/mediapipeline/MediaPipeline.cpp', + './src/mediapipeline/MediaPipelineFilter.h', + './src/mediapipeline/MediaPipelineFilter.cpp', './src/mediapipeline/SrtpFlow.h', './src/mediapipeline/SrtpFlow.cpp', ], diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp b/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp new file mode 100644 index 000000000000..cb036e0e86f2 --- /dev/null +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: softtabstop=2:shiftwidth=2:expandtab + * */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Original author: bcampen@mozilla.com + +#include "MediaPipelineFilter.h" + +#include "webrtc/modules/interface/module_common_types.h" + +namespace mozilla { + +MediaPipelineFilter::MediaPipelineFilter() : correlator_(0) { +} + +bool MediaPipelineFilter::Filter(const webrtc::RTPHeader& header, + uint32_t correlator) { + if (correlator) { + // This special correlator header takes precedence. It also lets us learn + // about SSRC mappings if we don't know about them yet. + if (correlator == correlator_) { + AddRemoteSSRC(header.ssrc); + return true; + } else { + // Some other stream; it is possible that an SSRC has moved, so make sure + // we don't have that SSRC in our filter any more. + remote_ssrc_set_.erase(header.ssrc); + return false; + } + } + + if (remote_ssrc_set_.count(header.ssrc)) { + return true; + } + + // Last ditch effort... + if (payload_type_set_.count(header.payloadType)) { + // Actual match. We need to update the ssrc map so we can route rtcp + // sender reports correctly (these use a different payload-type field) + AddRemoteSSRC(header.ssrc); + return true; + } + + return false; +} + +bool MediaPipelineFilter::FilterRTCP(uint32_t ssrc) { + return remote_ssrc_set_.count(ssrc) != 0; +} + +bool MediaPipelineFilter::FilterRTCPReceiverReport(uint32_t ssrc) { + return local_ssrc_set_.count(ssrc) != 0; +} + +void MediaPipelineFilter::AddLocalSSRC(uint32_t ssrc) { + local_ssrc_set_.insert(ssrc); +} + +void MediaPipelineFilter::AddRemoteSSRC(uint32_t ssrc) { + remote_ssrc_set_.insert(ssrc); +} + +void MediaPipelineFilter::AddUniquePT(uint8_t payload_type) { + payload_type_set_.insert(payload_type); +} + +void MediaPipelineFilter::SetCorrelator(uint32_t correlator) { + correlator_ = correlator; +} + +void MediaPipelineFilter::IncorporateRemoteDescription( + const MediaPipelineFilter& remote_filter) { + // Update SSRCs; we completely replace the remote SSRCs, since this could be + // renegotiation. We leave our SSRCs alone, though. + if (!remote_filter.remote_ssrc_set_.empty()) { + remote_ssrc_set_ = remote_filter.remote_ssrc_set_; + } + + // We do not mess with the payload types or correlator here, since the remote + // SDP doesn't tell us anything about what we will be receiving. +} + +} // end namespace mozilla + + diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.h b/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.h new file mode 100644 index 000000000000..61a9741547b3 --- /dev/null +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.h @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: softtabstop=2:shiftwidth=2:expandtab + * */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// Original author: bcampen@mozilla.com + +#ifndef mediapipelinefilter_h__ +#define mediapipelinefilter_h__ + +#include +#include + +#include + +namespace webrtc { +class RTPHeader; +} + +namespace mozilla { + +// A class that handles the work of filtering RTP packets that arrive at a +// MediaPipeline. This is primarily important for the use of BUNDLE (ie; +// multiple m-lines share the same RTP stream). There are three ways that this +// can work; +// +// 1) In our SDP, we include a media-level extmap parameter with a unique +// integer of our choosing, with the hope that the other side will include +// this value in a header in the first few RTP packets it sends us. This +// allows us to perform correlation in cases where the other side has not +// informed us of the ssrcs it will be sending (either because it did not +// include them in its SDP, or their SDP has not arrived yet) +// and also gives us the opportunity to learn SSRCs from packets so adorned. +// +// 2) If the remote endpoint includes SSRC media-level attributes in its SDP, +// we can simply use this information to populate the filter. The only +// shortcoming here is when RTP packets arrive before the answer does. See +// above. +// +// 3) As a fallback, we can try to use payload type IDs to perform correlation, +// but only when the type id is unique to this media section. +// This too allows us to learn about SSRCs (mostly useful for filtering +// any RTCP packets that follow). +class MediaPipelineFilter { + public: + MediaPipelineFilter(); + + // Checks whether this packet passes the filter, possibly updating the filter + // in the process (if the correlator or payload types are used, they can teach + // the filter about ssrcs) + bool Filter(const webrtc::RTPHeader& header, uint32_t correlator = 0); + + // RTCP doesn't have things like the RTP correlator, and uses its own + // payload types too. + // RTCP receiver reports use _our_ ssrcs + bool FilterRTCPReceiverReport(uint32_t ssrc); + // The rest of RTCP uses their ssrcs + bool FilterRTCP(uint32_t ssrc); + + void AddLocalSSRC(uint32_t ssrc); + void AddRemoteSSRC(uint32_t ssrc); + + // When a payload type id is unique to our media section, add it here. + void AddUniquePT(uint8_t payload_type); + void SetCorrelator(uint32_t correlator); + + void IncorporateRemoteDescription(const MediaPipelineFilter& remote_filter); + + private: + uint32_t correlator_; + // The number of filters we manage here is quite small, so I am optimizing + // for readability. + std::set remote_ssrc_set_; + std::set local_ssrc_set_; + std::set payload_type_set_; +}; + +} // end namespace mozilla + +#endif // mediapipelinefilter_h__ + diff --git a/media/webrtc/signaling/test/mediapipeline_unittest.cpp b/media/webrtc/signaling/test/mediapipeline_unittest.cpp index 16930bf6f7a5..87a808278de3 100644 --- a/media/webrtc/signaling/test/mediapipeline_unittest.cpp +++ b/media/webrtc/signaling/test/mediapipeline_unittest.cpp @@ -22,6 +22,7 @@ #include "MediaConduitErrors.h" #include "MediaConduitInterface.h" #include "MediaPipeline.h" +#include "MediaPipelineFilter.h" #include "runnable_utils.h" #include "transportflow.h" #include "transportlayerprsock.h" @@ -32,6 +33,8 @@ #include "mtransport_test_utils.h" #include "runnable_utils.h" +#include "webrtc/modules/interface/module_common_types.h" + #define GTEST_HAS_RTTI 0 #include "gtest/gtest.h" #include "gtest_utils.h" @@ -342,6 +345,159 @@ protected: TestAgentReceive p2_; }; +class MediaPipelineFilterTest : public ::testing::Test { + public: + bool Filter(MediaPipelineFilter& filter, + int32_t correlator, + uint32_t ssrc, + uint8_t payload_type) { + + webrtc::RTPHeader header; + header.ssrc = ssrc; + header.payloadType = payload_type; + return filter.Filter(header, correlator); + } +}; + +TEST_F(MediaPipelineFilterTest, TestConstruct) { + MediaPipelineFilter filter; +} + +TEST_F(MediaPipelineFilterTest, TestDefault) { + MediaPipelineFilter filter; + ASSERT_FALSE(Filter(filter, 0, 233, 110)); +} + +TEST_F(MediaPipelineFilterTest, TestSSRCFilter) { + MediaPipelineFilter filter; + filter.AddRemoteSSRC(555); + ASSERT_TRUE(Filter(filter, 0, 555, 110)); + ASSERT_FALSE(Filter(filter, 0, 556, 110)); +} + +TEST_F(MediaPipelineFilterTest, TestSSRCFilterRTCP) { + MediaPipelineFilter filter; + filter.AddRemoteSSRC(555); + ASSERT_TRUE(filter.FilterRTCP(555)); + ASSERT_FALSE(filter.FilterRTCP(556)); + ASSERT_FALSE(filter.FilterRTCPReceiverReport(555)); +} + +TEST_F(MediaPipelineFilterTest, TestSSRCFilterReceiverReport) { + MediaPipelineFilter filter; + filter.AddLocalSSRC(555); + ASSERT_TRUE(filter.FilterRTCPReceiverReport(555)); + ASSERT_FALSE(filter.FilterRTCPReceiverReport(556)); + ASSERT_FALSE(filter.FilterRTCP(555)); +} + +TEST_F(MediaPipelineFilterTest, TestCorrelatorFilter) { + MediaPipelineFilter filter; + filter.SetCorrelator(7777); + ASSERT_TRUE(Filter(filter, 7777, 555, 110)); + ASSERT_FALSE(Filter(filter, 7778, 556, 110)); + // This should also have resulted in the SSRC 555 being added to the filter + ASSERT_TRUE(Filter(filter, 0, 555, 110)); + ASSERT_FALSE(Filter(filter, 0, 556, 110)); + + ASSERT_TRUE(filter.FilterRTCP(555)); +} + +TEST_F(MediaPipelineFilterTest, TestPayloadTypeFilter) { + MediaPipelineFilter filter; + filter.AddUniquePT(110); + ASSERT_TRUE(Filter(filter, 0, 555, 110)); + ASSERT_FALSE(Filter(filter, 0, 556, 111)); +} + +TEST_F(MediaPipelineFilterTest, TestPayloadTypeFilterSSRCUpdate) { + MediaPipelineFilter filter; + filter.AddUniquePT(110); + ASSERT_TRUE(Filter(filter, 0, 555, 110)); + ASSERT_TRUE(filter.FilterRTCP(555)); + ASSERT_FALSE(filter.FilterRTCP(556)); + ASSERT_FALSE(filter.FilterRTCPReceiverReport(555)); +} + +TEST_F(MediaPipelineFilterTest, TestAnswerAddsSSRCs) { + MediaPipelineFilter filter; + filter.SetCorrelator(7777); + ASSERT_TRUE(Filter(filter, 7777, 555, 110)); + ASSERT_FALSE(Filter(filter, 7778, 556, 110)); + // This should also have resulted in the SSRC 555 being added to the filter + ASSERT_TRUE(Filter(filter, 0, 555, 110)); + ASSERT_FALSE(Filter(filter, 0, 556, 110)); + + // This sort of thing can happen when getting an answer with SSRC attrs + // The answer will not contain the correlator. + MediaPipelineFilter filter2; + filter2.AddRemoteSSRC(555); + filter2.AddRemoteSSRC(556); + filter2.AddRemoteSSRC(557); + + filter.IncorporateRemoteDescription(filter2); + + // Ensure that the old SSRC still works. + ASSERT_TRUE(Filter(filter, 0, 555, 110)); + + // Ensure that the new SSRCs work. + ASSERT_TRUE(Filter(filter, 0, 556, 110)); + ASSERT_TRUE(Filter(filter, 0, 557, 110)); + + // Ensure that the correlator continues to work + ASSERT_TRUE(Filter(filter, 7777, 558, 110)); +} + +TEST_F(MediaPipelineFilterTest, TestSSRCMovedWithSDP) { + MediaPipelineFilter filter; + filter.SetCorrelator(7777); + filter.AddUniquePT(111); + ASSERT_TRUE(Filter(filter, 7777, 555, 110)); + + MediaPipelineFilter filter2; + filter2.AddRemoteSSRC(556); + + filter.IncorporateRemoteDescription(filter2); + + // Ensure that the old SSRC has been removed. + ASSERT_FALSE(Filter(filter, 0, 555, 110)); + + // Ensure that the new SSRC works. + ASSERT_TRUE(Filter(filter, 0, 556, 110)); + + // Ensure that the correlator continues to work + ASSERT_TRUE(Filter(filter, 7777, 558, 110)); + + // Ensure that the payload type mapping continues to work + ASSERT_TRUE(Filter(filter, 0, 559, 111)); +} + +TEST_F(MediaPipelineFilterTest, TestSSRCMovedWithCorrelator) { + MediaPipelineFilter filter; + filter.SetCorrelator(7777); + ASSERT_TRUE(Filter(filter, 7777, 555, 110)); + ASSERT_TRUE(Filter(filter, 0, 555, 110)); + ASSERT_FALSE(Filter(filter, 7778, 555, 110)); + ASSERT_FALSE(Filter(filter, 0, 555, 110)); +} + +TEST_F(MediaPipelineFilterTest, TestRemoteSDPNoSSRCs) { + // If the remote SDP doesn't have SSRCs, right now this is a no-op and + // there is no point of even incorporating a filter, but we make the behavior + // consistent to avoid confusion. + MediaPipelineFilter filter; + filter.SetCorrelator(7777); + filter.AddUniquePT(111); + ASSERT_TRUE(Filter(filter, 7777, 555, 110)); + + MediaPipelineFilter filter2; + + filter.IncorporateRemoteDescription(filter2); + + // Ensure that the old SSRC still works. + ASSERT_TRUE(Filter(filter, 7777, 555, 110)); +} + TEST_F(MediaPipelineTest, TestAudioSendNoMux) { TestAudioSend(false); } diff --git a/media/webrtc/signaling/test/moz.build b/media/webrtc/signaling/test/moz.build index 95cf28ab4b2e..c86e0901fe8c 100644 --- a/media/webrtc/signaling/test/moz.build +++ b/media/webrtc/signaling/test/moz.build @@ -49,6 +49,7 @@ LOCAL_INCLUDES += [ '/media/webrtc/signaling/src/sipcc/core/sdp', '/media/webrtc/signaling/src/sipcc/cpr/include', '/media/webrtc/signaling/src/sipcc/include', + '/media/webrtc/trunk', '/media/webrtc/trunk/testing/gtest/include', '/media/webrtc/trunk/third_party/libjingle/source', '/xpcom/base', From 8c01b21fd43744428daaa5f7e28e7887f6ab067e Mon Sep 17 00:00:00 2001 From: "Byron Campen [:bwc]" Date: Thu, 9 Jan 2014 15:12:25 -0800 Subject: [PATCH 16/48] Bug 786234 - Part 2.1: RTCP filtering logic. r=abr --- .../src/mediapipeline/MediaPipelineFilter.cpp | 110 ++++++- .../src/mediapipeline/MediaPipelineFilter.h | 37 ++- .../signaling/test/mediapipeline_unittest.cpp | 274 ++++++++++++++++-- 3 files changed, 387 insertions(+), 34 deletions(-) diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp b/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp index cb036e0e86f2..195e89ce4a07 100644 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp @@ -9,8 +9,13 @@ #include "MediaPipelineFilter.h" +#include "logging.h" + #include "webrtc/modules/interface/module_common_types.h" +// Logging context +MOZ_MTLOG_MODULE("mediapipeline") + namespace mozilla { MediaPipelineFilter::MediaPipelineFilter() : correlator_(0) { @@ -47,14 +52,6 @@ bool MediaPipelineFilter::Filter(const webrtc::RTPHeader& header, return false; } -bool MediaPipelineFilter::FilterRTCP(uint32_t ssrc) { - return remote_ssrc_set_.count(ssrc) != 0; -} - -bool MediaPipelineFilter::FilterRTCPReceiverReport(uint32_t ssrc) { - return local_ssrc_set_.count(ssrc) != 0; -} - void MediaPipelineFilter::AddLocalSSRC(uint32_t ssrc) { local_ssrc_set_.insert(ssrc); } @@ -83,6 +80,103 @@ void MediaPipelineFilter::IncorporateRemoteDescription( // SDP doesn't tell us anything about what we will be receiving. } +MediaPipelineFilter::Result +MediaPipelineFilter::FilterRTCP(const unsigned char* data, + size_t len) const { + if (len < FIRST_SSRC_OFFSET) { + return FAIL; + } + + uint8_t payload_type = data[PT_OFFSET]; + + switch (payload_type) { + case SENDER_REPORT_T: + return CheckRtcpReport(data, len, RECEIVER_REPORT_START_SR) ? PASS : FAIL; + case RECEIVER_REPORT_T: + return CheckRtcpReport(data, len, SENDER_REPORT_START_RR) ? PASS : FAIL; + default: + return UNSUPPORTED; + } + + return UNSUPPORTED; +} + +bool MediaPipelineFilter::CheckRtcpSsrc(const unsigned char* data, + size_t len, + size_t ssrc_offset, + uint8_t flags) const { + if (ssrc_offset + 4 > len) { + return false; + } + + uint32_t ssrc = 0; + ssrc += (uint32_t)data[ssrc_offset++] << 24; + ssrc += (uint32_t)data[ssrc_offset++] << 16; + ssrc += (uint32_t)data[ssrc_offset++] << 8; + ssrc += (uint32_t)data[ssrc_offset++]; + + if (flags | MAYBE_LOCAL_SSRC) { + if (local_ssrc_set_.count(ssrc)) { + return true; + } + } + + if (flags | MAYBE_REMOTE_SSRC) { + if (remote_ssrc_set_.count(ssrc)) { + return true; + } + } + return false; +} + +static uint8_t GetCount(const unsigned char* data, size_t len) { + // This might be a count of rr reports, or might be a count of stuff like + // SDES reports, or what-have-you. They all live in bits 3-7. + return data[0] & 0x1F; +} + +bool MediaPipelineFilter::CheckRtcpReport(const unsigned char* data, + size_t len, + size_t first_rr_offset) const { + bool remote_ssrc_matched = CheckRtcpSsrc(data, + len, + FIRST_SSRC_OFFSET, + MAYBE_REMOTE_SSRC); + + uint8_t rr_count = GetCount(data, len); + + // We need to check for consistency. If the remote ssrc matched, the local + // ssrcs must too. If it did not, this may just be because our filter is + // incomplete, so the local ssrcs could go either way. + bool ssrcs_must_match = remote_ssrc_matched; + bool ssrcs_must_not_match = false; + + for (uint8_t rr_num = 0; rr_num < rr_count; ++rr_num) { + size_t ssrc_offset = first_rr_offset + (rr_num * RECEIVER_REPORT_SIZE); + + if (!CheckRtcpSsrc(data, len, ssrc_offset, MAYBE_LOCAL_SSRC)) { + ssrcs_must_not_match = true; + if (ssrcs_must_match) { + break; + } + } else { + ssrcs_must_match = true; + if (ssrcs_must_not_match) { + break; + } + } + } + + if (ssrcs_must_match && ssrcs_must_not_match) { + MOZ_MTLOG(ML_ERROR, "Received an RTCP packet with SSRCs from " + "multiple m-lines! This is broken."); + return false; + } + + // This is set if any ssrc matched + return ssrcs_must_match; +} + } // end namespace mozilla diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.h b/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.h index 61a9741547b3..ff8fa4a794ba 100644 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.h +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.h @@ -52,12 +52,15 @@ class MediaPipelineFilter { // the filter about ssrcs) bool Filter(const webrtc::RTPHeader& header, uint32_t correlator = 0); + typedef enum { + FAIL, + PASS, + UNSUPPORTED + } Result; + // RTCP doesn't have things like the RTP correlator, and uses its own // payload types too. - // RTCP receiver reports use _our_ ssrcs - bool FilterRTCPReceiverReport(uint32_t ssrc); - // The rest of RTCP uses their ssrcs - bool FilterRTCP(uint32_t ssrc); + Result FilterRTCP(const unsigned char* data, size_t len) const; void AddLocalSSRC(uint32_t ssrc); void AddRemoteSSRC(uint32_t ssrc); @@ -68,7 +71,33 @@ class MediaPipelineFilter { void IncorporateRemoteDescription(const MediaPipelineFilter& remote_filter); + // Some payload types + static const uint8_t SENDER_REPORT_T = 200; + static const uint8_t RECEIVER_REPORT_T = 201; + private: + static const uint8_t MAYBE_LOCAL_SSRC = 1; + static const uint8_t MAYBE_REMOTE_SSRC = 2; + + // Payload type is always in the second byte + static const size_t PT_OFFSET = 1; + // First SSRC always starts at the fifth byte. + static const size_t FIRST_SSRC_OFFSET = 4; + + static const size_t RECEIVER_REPORT_START_SR = 7*4; + static const size_t SENDER_REPORT_START_RR = 2*4; + static const size_t RECEIVER_REPORT_SIZE = 6*4; + + bool CheckRtcpSsrc(const unsigned char* data, + size_t len, + size_t ssrc_offset, + uint8_t flags) const; + + + bool CheckRtcpReport(const unsigned char* data, + size_t len, + size_t first_rr_offset) const; + uint32_t correlator_; // The number of filters we manage here is quite small, so I am optimizing // for readability. diff --git a/media/webrtc/signaling/test/mediapipeline_unittest.cpp b/media/webrtc/signaling/test/mediapipeline_unittest.cpp index 87a808278de3..bee43898244b 100644 --- a/media/webrtc/signaling/test/mediapipeline_unittest.cpp +++ b/media/webrtc/signaling/test/mediapipeline_unittest.cpp @@ -375,32 +375,261 @@ TEST_F(MediaPipelineFilterTest, TestSSRCFilter) { ASSERT_FALSE(Filter(filter, 0, 556, 110)); } -TEST_F(MediaPipelineFilterTest, TestSSRCFilterRTCP) { +#define SSRC(ssrc) \ + ((ssrc >> 24) & 0xFF), \ + ((ssrc >> 16) & 0xFF), \ + ((ssrc >> 8 ) & 0xFF), \ + (ssrc & 0xFF) + +#define REPORT_FRAGMENT(ssrc) \ + SSRC(ssrc), \ + 0,0,0,0, \ + 0,0,0,0, \ + 0,0,0,0, \ + 0,0,0,0, \ + 0,0,0,0 + +#define RTCP_TYPEINFO(num_rrs, type, size) \ + 0x80 + num_rrs, type, 0, size + +const unsigned char rtcp_rr_s16[] = { + // zero rrs, size 1 words + RTCP_TYPEINFO(0, MediaPipelineFilter::RECEIVER_REPORT_T, 1), + SSRC(16) +}; + +const unsigned char rtcp_rr_s16_r17[] = { + // one rr, 7 words + RTCP_TYPEINFO(1, MediaPipelineFilter::RECEIVER_REPORT_T, 7), + SSRC(16), + REPORT_FRAGMENT(17) +}; + +const unsigned char rtcp_rr_s16_r17_18[] = { + // two rrs, size 13 words + RTCP_TYPEINFO(2, MediaPipelineFilter::RECEIVER_REPORT_T, 13), + SSRC(16), + REPORT_FRAGMENT(17), + REPORT_FRAGMENT(18) +}; + +const unsigned char rtcp_sr_s16[] = { + // zero rrs, size 6 words + RTCP_TYPEINFO(0, MediaPipelineFilter::SENDER_REPORT_T, 6), + REPORT_FRAGMENT(16) +}; + +const unsigned char rtcp_sr_s16_r17[] = { + // one rr, size 12 words + RTCP_TYPEINFO(1, MediaPipelineFilter::SENDER_REPORT_T, 12), + REPORT_FRAGMENT(16), + REPORT_FRAGMENT(17) +}; + +const unsigned char rtcp_sr_s16_r17_18[] = { + // two rrs, size 18 words + RTCP_TYPEINFO(2, MediaPipelineFilter::SENDER_REPORT_T, 18), + REPORT_FRAGMENT(16), + REPORT_FRAGMENT(17), + REPORT_FRAGMENT(18) +}; + +const unsigned char unknown_type[] = { + RTCP_TYPEINFO(1, 222, 0) +}; + +TEST_F(MediaPipelineFilterTest, TestEmptyFilterReport0) { MediaPipelineFilter filter; - filter.AddRemoteSSRC(555); - ASSERT_TRUE(filter.FilterRTCP(555)); - ASSERT_FALSE(filter.FilterRTCP(556)); - ASSERT_FALSE(filter.FilterRTCPReceiverReport(555)); + ASSERT_EQ(MediaPipelineFilter::FAIL, + filter.FilterRTCP(rtcp_sr_s16, sizeof(rtcp_sr_s16))); + ASSERT_EQ(MediaPipelineFilter::FAIL, + filter.FilterRTCP(rtcp_rr_s16, sizeof(rtcp_rr_s16))); } -TEST_F(MediaPipelineFilterTest, TestSSRCFilterReceiverReport) { +TEST_F(MediaPipelineFilterTest, TestFilterReport0) { MediaPipelineFilter filter; - filter.AddLocalSSRC(555); - ASSERT_TRUE(filter.FilterRTCPReceiverReport(555)); - ASSERT_FALSE(filter.FilterRTCPReceiverReport(556)); - ASSERT_FALSE(filter.FilterRTCP(555)); + filter.AddRemoteSSRC(16); + ASSERT_EQ(MediaPipelineFilter::PASS, + filter.FilterRTCP(rtcp_sr_s16, sizeof(rtcp_sr_s16))); + ASSERT_EQ(MediaPipelineFilter::PASS, + filter.FilterRTCP(rtcp_rr_s16, sizeof(rtcp_rr_s16))); +} + +TEST_F(MediaPipelineFilterTest, TestFilterReport0SSRCTruncated) { + MediaPipelineFilter filter; + filter.AddRemoteSSRC(16); + const unsigned char data[] = { + RTCP_TYPEINFO(0, MediaPipelineFilter::RECEIVER_REPORT_T, 1), + 0,0,0 + }; + ASSERT_EQ(MediaPipelineFilter::FAIL, + filter.FilterRTCP(data, sizeof(data))); +} + +TEST_F(MediaPipelineFilterTest, TestFilterReport0PTTruncated) { + MediaPipelineFilter filter; + filter.AddRemoteSSRC(16); + const unsigned char data[] = {0x80}; + ASSERT_EQ(MediaPipelineFilter::FAIL, + filter.FilterRTCP(data, sizeof(data))); +} + +TEST_F(MediaPipelineFilterTest, TestFilterReport0CountTruncated) { + MediaPipelineFilter filter; + filter.AddRemoteSSRC(16); + const unsigned char data[] = {}; + ASSERT_EQ(MediaPipelineFilter::FAIL, + filter.FilterRTCP(data, sizeof(data))); +} + +TEST_F(MediaPipelineFilterTest, TestFilterReport1BothMatch) { + MediaPipelineFilter filter; + filter.AddRemoteSSRC(16); + filter.AddLocalSSRC(17); + ASSERT_EQ(MediaPipelineFilter::PASS, + filter.FilterRTCP(rtcp_sr_s16_r17, sizeof(rtcp_sr_s16_r17))); + ASSERT_EQ(MediaPipelineFilter::PASS, + filter.FilterRTCP(rtcp_rr_s16_r17, sizeof(rtcp_rr_s16_r17))); +} + +TEST_F(MediaPipelineFilterTest, TestFilterReport1SSRCTruncated) { + MediaPipelineFilter filter; + filter.AddRemoteSSRC(16); + filter.AddLocalSSRC(17); + const unsigned char rr[] = { + RTCP_TYPEINFO(1, MediaPipelineFilter::RECEIVER_REPORT_T, 7), + SSRC(16), + 0,0,0 + }; + ASSERT_EQ(MediaPipelineFilter::FAIL, + filter.FilterRTCP(rr, sizeof(rr))); + const unsigned char sr[] = { + RTCP_TYPEINFO(1, MediaPipelineFilter::RECEIVER_REPORT_T, 12), + REPORT_FRAGMENT(16), + 0,0,0 + }; + ASSERT_EQ(MediaPipelineFilter::FAIL, + filter.FilterRTCP(sr, sizeof(rr))); +} + +TEST_F(MediaPipelineFilterTest, TestFilterReport1BigSSRC) { + MediaPipelineFilter filter; + filter.AddRemoteSSRC(0x01020304); + filter.AddLocalSSRC(0x11121314); + const unsigned char rr[] = { + RTCP_TYPEINFO(1, MediaPipelineFilter::RECEIVER_REPORT_T, 7), + SSRC(0x01020304), + REPORT_FRAGMENT(0x11121314) + }; + ASSERT_EQ(MediaPipelineFilter::PASS, + filter.FilterRTCP(rr, sizeof(rr))); + const unsigned char sr[] = { + RTCP_TYPEINFO(1, MediaPipelineFilter::RECEIVER_REPORT_T, 12), + SSRC(0x01020304), + REPORT_FRAGMENT(0x11121314) + }; + ASSERT_EQ(MediaPipelineFilter::PASS, + filter.FilterRTCP(sr, sizeof(rr))); +} + +TEST_F(MediaPipelineFilterTest, TestFilterReport1LocalMatch) { + MediaPipelineFilter filter; + filter.AddLocalSSRC(17); + ASSERT_EQ(MediaPipelineFilter::PASS, + filter.FilterRTCP(rtcp_sr_s16_r17, sizeof(rtcp_sr_s16_r17))); + ASSERT_EQ(MediaPipelineFilter::PASS, + filter.FilterRTCP(rtcp_rr_s16_r17, sizeof(rtcp_rr_s16_r17))); +} + +TEST_F(MediaPipelineFilterTest, TestFilterReport1Inconsistent) { + MediaPipelineFilter filter; + filter.AddRemoteSSRC(16); + // We assume that the filter is exactly correct in terms of local ssrcs. + // So, when RTCP shows up with a remote SSRC that matches, and a local + // ssrc that doesn't, we assume the other end has messed up and put ssrcs + // from more than one m-line in the packet. + ASSERT_EQ(MediaPipelineFilter::FAIL, + filter.FilterRTCP(rtcp_sr_s16_r17, sizeof(rtcp_sr_s16_r17))); + ASSERT_EQ(MediaPipelineFilter::FAIL, + filter.FilterRTCP(rtcp_rr_s16_r17, sizeof(rtcp_rr_s16_r17))); +} + +TEST_F(MediaPipelineFilterTest, TestFilterReport1NeitherMatch) { + MediaPipelineFilter filter; + filter.AddRemoteSSRC(17); + filter.AddLocalSSRC(18); + ASSERT_EQ(MediaPipelineFilter::PASS, + filter.FilterRTCP(rtcp_sr_s16_r17, sizeof(rtcp_sr_s16_r17))); + ASSERT_EQ(MediaPipelineFilter::PASS, + filter.FilterRTCP(rtcp_rr_s16_r17, sizeof(rtcp_rr_s16_r17))); +} + +TEST_F(MediaPipelineFilterTest, TestFilterReport2AllMatch) { + MediaPipelineFilter filter; + filter.AddRemoteSSRC(16); + filter.AddLocalSSRC(17); + filter.AddLocalSSRC(18); + ASSERT_EQ(MediaPipelineFilter::PASS, + filter.FilterRTCP(rtcp_sr_s16_r17_18, + sizeof(rtcp_sr_s16_r17_18))); +} + +TEST_F(MediaPipelineFilterTest, TestFilterReport2LocalMatch) { + MediaPipelineFilter filter; + filter.AddLocalSSRC(17); + filter.AddLocalSSRC(18); + ASSERT_EQ(MediaPipelineFilter::PASS, + filter.FilterRTCP(rtcp_sr_s16_r17_18, + sizeof(rtcp_sr_s16_r17_18))); + ASSERT_EQ(MediaPipelineFilter::PASS, + filter.FilterRTCP(rtcp_rr_s16_r17_18, + sizeof(rtcp_rr_s16_r17_18))); +} + +TEST_F(MediaPipelineFilterTest, TestFilterReport2Inconsistent101) { + MediaPipelineFilter filter; + filter.AddRemoteSSRC(16); + filter.AddLocalSSRC(18); + ASSERT_EQ(MediaPipelineFilter::FAIL, + filter.FilterRTCP(rtcp_sr_s16_r17_18, + sizeof(rtcp_sr_s16_r17_18))); + ASSERT_EQ(MediaPipelineFilter::FAIL, + filter.FilterRTCP(rtcp_rr_s16_r17_18, + sizeof(rtcp_rr_s16_r17_18))); +} + +TEST_F(MediaPipelineFilterTest, TestFilterReport2Inconsistent001) { + MediaPipelineFilter filter; + filter.AddLocalSSRC(18); + ASSERT_EQ(MediaPipelineFilter::FAIL, + filter.FilterRTCP(rtcp_sr_s16_r17_18, + sizeof(rtcp_sr_s16_r17_18))); + ASSERT_EQ(MediaPipelineFilter::FAIL, + filter.FilterRTCP(rtcp_rr_s16_r17_18, + sizeof(rtcp_rr_s16_r17_18))); +} + +TEST_F(MediaPipelineFilterTest, TestFilterUnknownRTCPType) { + MediaPipelineFilter filter; + filter.AddLocalSSRC(18); + ASSERT_EQ(MediaPipelineFilter::UNSUPPORTED, + filter.FilterRTCP(unknown_type, sizeof(unknown_type))); } TEST_F(MediaPipelineFilterTest, TestCorrelatorFilter) { MediaPipelineFilter filter; filter.SetCorrelator(7777); - ASSERT_TRUE(Filter(filter, 7777, 555, 110)); - ASSERT_FALSE(Filter(filter, 7778, 556, 110)); - // This should also have resulted in the SSRC 555 being added to the filter - ASSERT_TRUE(Filter(filter, 0, 555, 110)); - ASSERT_FALSE(Filter(filter, 0, 556, 110)); + ASSERT_TRUE(Filter(filter, 7777, 16, 110)); + ASSERT_FALSE(Filter(filter, 7778, 17, 110)); + // This should also have resulted in the SSRC 16 being added to the filter + ASSERT_TRUE(Filter(filter, 0, 16, 110)); + ASSERT_FALSE(Filter(filter, 0, 17, 110)); - ASSERT_TRUE(filter.FilterRTCP(555)); + // rtcp_sr_s16 has 16 as an SSRC + ASSERT_EQ(MediaPipelineFilter::PASS, + filter.FilterRTCP(rtcp_sr_s16, sizeof(rtcp_sr_s16))); + ASSERT_EQ(MediaPipelineFilter::PASS, + filter.FilterRTCP(rtcp_rr_s16, sizeof(rtcp_rr_s16))); } TEST_F(MediaPipelineFilterTest, TestPayloadTypeFilter) { @@ -413,10 +642,11 @@ TEST_F(MediaPipelineFilterTest, TestPayloadTypeFilter) { TEST_F(MediaPipelineFilterTest, TestPayloadTypeFilterSSRCUpdate) { MediaPipelineFilter filter; filter.AddUniquePT(110); - ASSERT_TRUE(Filter(filter, 0, 555, 110)); - ASSERT_TRUE(filter.FilterRTCP(555)); - ASSERT_FALSE(filter.FilterRTCP(556)); - ASSERT_FALSE(filter.FilterRTCPReceiverReport(555)); + ASSERT_TRUE(Filter(filter, 0, 16, 110)); + + // rtcp_sr_s16 has 16 as an SSRC + ASSERT_EQ(MediaPipelineFilter::PASS, + filter.FilterRTCP(rtcp_sr_s16, sizeof(rtcp_sr_s16))); } TEST_F(MediaPipelineFilterTest, TestAnswerAddsSSRCs) { @@ -483,8 +713,8 @@ TEST_F(MediaPipelineFilterTest, TestSSRCMovedWithCorrelator) { TEST_F(MediaPipelineFilterTest, TestRemoteSDPNoSSRCs) { // If the remote SDP doesn't have SSRCs, right now this is a no-op and - // there is no point of even incorporating a filter, but we make the behavior - // consistent to avoid confusion. + // there is no point of even incorporating a filter, but we make the + // behavior consistent to avoid confusion. MediaPipelineFilter filter; filter.SetCorrelator(7777); filter.AddUniquePT(111); From 749087b8302f651764d97ce856a3995401fb3e10 Mon Sep 17 00:00:00 2001 From: "Byron Campen [:bwc]" Date: Tue, 14 Jan 2014 16:31:27 -0800 Subject: [PATCH 17/48] Bug 786234 - Part 2.2: Compensate for some build system gotchas. r=abr --- media/webrtc/moz.build | 1 + .../signaling/src/mediapipeline/MediaPipelineFilter.cpp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/media/webrtc/moz.build b/media/webrtc/moz.build index 12ea7d13e099..0b7152d4de93 100644 --- a/media/webrtc/moz.build +++ b/media/webrtc/moz.build @@ -64,6 +64,7 @@ if CONFIG['MOZ_WEBRTC_SIGNALING']: 'signaling/src/media/CSFVideoControlWrapper.cpp', 'signaling/src/media/VcmSIPCCBinding.cpp', 'signaling/src/mediapipeline/MediaPipeline.cpp', + 'signaling/src/mediapipeline/MediaPipelineFilter.cpp', 'signaling/src/mediapipeline/SrtpFlow.cpp', 'signaling/src/peerconnection/MediaStreamList.cpp', 'signaling/src/peerconnection/PeerConnectionCtx.cpp', diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp b/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp index 195e89ce4a07..93ce053ac2e7 100644 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp @@ -7,10 +7,10 @@ // Original author: bcampen@mozilla.com -#include "MediaPipelineFilter.h" - #include "logging.h" +#include "MediaPipelineFilter.h" + #include "webrtc/modules/interface/module_common_types.h" // Logging context From 8e25fb36a1c79e61d51d59c756d5a0f90716939a Mon Sep 17 00:00:00 2001 From: "Byron Campen [:bwc]" Date: Tue, 14 Jan 2014 16:29:42 -0800 Subject: [PATCH 18/48] Bug 786234 - Part 3: Plumbing for filtration and bundle usage detection. r=abr --- media/mtransport/transportflow.cpp | 11 + media/mtransport/transportflow.h | 2 + .../signaling/src/media/VcmSIPCCBinding.cpp | 102 +++- .../src/mediapipeline/MediaPipeline.cpp | 531 ++++++++++++------ .../src/mediapipeline/MediaPipeline.h | 137 +++-- .../src/peerconnection/PeerConnectionImpl.cpp | 6 +- .../peerconnection/PeerConnectionMedia.cpp | 97 ++++ .../src/peerconnection/PeerConnectionMedia.h | 11 + .../signaling/test/mediapipeline_unittest.cpp | 152 ++++- 9 files changed, 832 insertions(+), 217 deletions(-) diff --git a/media/mtransport/transportflow.cpp b/media/mtransport/transportflow.cpp index 630b6f9459e9..4f1afe102059 100644 --- a/media/mtransport/transportflow.cpp +++ b/media/mtransport/transportflow.cpp @@ -199,6 +199,17 @@ TransportResult TransportFlow::SendPacket(const unsigned char *data, return top() ? top()->SendPacket(data, len) : TE_ERROR; } +bool TransportFlow::Contains(TransportLayer *layer) const { + if (layers_) { + for (auto l = layers_->begin(); l != layers_->end(); ++l) { + if (*l == layer) { + return true; + } + } + } + return false; +} + void TransportFlow::EnsureSameThread(TransportLayer *layer) { // Enforce that if any of the layers have a thread binding, // they all have the same binding. diff --git a/media/mtransport/transportflow.h b/media/mtransport/transportflow.h index a553050d6cf7..a22f26ed58bb 100644 --- a/media/mtransport/transportflow.h +++ b/media/mtransport/transportflow.h @@ -96,6 +96,8 @@ class TransportFlow : public sigslot::has_slots<> { sigslot::signal3 SignalPacketReceived; + bool Contains(TransportLayer *layer) const; + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TransportFlow) private: diff --git a/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp b/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp index 6aa201ee46a4..fd2a0a0f15dc 100644 --- a/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp +++ b/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp @@ -12,6 +12,7 @@ #include "MediaConduitErrors.h" #include "MediaConduitInterface.h" #include "MediaPipeline.h" +#include "MediaPipelineFilter.h" #include "VcmSIPCCBinding.h" #include "csf_common.h" #include "PeerConnectionImpl.h" @@ -1501,7 +1502,12 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id, const char *fingerprint, vcm_mediaAttrs_t *attrs) { - CSFLogDebug( logTag, "%s(%s)", __FUNCTION__, peerconnection); + CSFLogDebug( logTag, "%s(%s) track = %d, stream = %d, level = %d", + __FUNCTION__, + peerconnection, + pc_track_id, + pc_stream_id, + level); // Find the PC. sipcc::PeerConnectionWrapper pc(peerconnection); @@ -1537,7 +1543,7 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id, } mozilla::RefPtr rtcp_flow = nullptr; - if(!attrs->rtcp_mux) { + if (!attrs->rtcp_mux) { rtcp_flow = vcmCreateTransportFlow(pc.impl(), level, true, setup_type, fingerprint_alg, fingerprint); if (!rtcp_flow) { @@ -1546,6 +1552,60 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id, } } + // If we're offering bundle, a given MediaPipeline could receive traffic on + // two different network flows depending on whether the answerer accepts, + // before any answer comes in. We need to be prepared for both cases. + nsAutoPtr filter; + RefPtr bundle_rtp_flow; + RefPtr bundle_rtcp_flow; + if (attrs->bundle_level) { + filter = new MediaPipelineFilter; + // Record our correlator, if present in our offer. + filter->SetCorrelator(attrs->bundle_stream_correlator); + + // Record our own ssrcs (these are _not_ those of the remote end; that + // is handled in vcmTxStart) + for (int s = 0; s < attrs->num_ssrcs; ++s) { + filter->AddLocalSSRC(attrs->ssrcs[s]); + } + + // Record the unique payload types + for (int p = 0; p < attrs->num_unique_payload_types; ++p) { + filter->AddUniquePT(attrs->unique_payload_types[p]); + } + + // Do not pass additional TransportFlows if the pipeline will use the same + // flow regardless of whether bundle happens or not. + if (attrs->bundle_level != (unsigned int)level) { + // This might end up creating it, or might reuse it. + mozilla::RefPtr bundle_rtp_flow = + vcmCreateTransportFlow(pc.impl(), + attrs->bundle_level, + false, + setup_type, + fingerprint_alg, + fingerprint); + + if (!bundle_rtp_flow) { + CSFLogError( logTag, "Could not create bundle RTP flow"); + return VCM_ERROR; + } + + if (!attrs->rtcp_mux) { + bundle_rtcp_flow = vcmCreateTransportFlow(pc.impl(), + attrs->bundle_level, + true, + setup_type, + fingerprint_alg, + fingerprint); + if (!bundle_rtcp_flow) { + CSFLogError( logTag, "Could not create bundle RTCP flow"); + return VCM_ERROR; + } + } + } + } + if (CC_IS_AUDIO(mcap_id)) { std::vector configs; @@ -1580,7 +1640,6 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id, if (conduit->ConfigureRecvMediaCodecs(configs)) return VCM_ERROR; - // Now we have all the pieces, create the pipeline mozilla::RefPtr pipeline = new mozilla::MediaPipelineReceiveAudio( @@ -1590,7 +1649,12 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id, stream->GetMediaStream()->GetStream(), pc_track_id, level, - conduit, rtp_flow, rtcp_flow); + conduit, + rtp_flow, + rtcp_flow, + bundle_rtp_flow, + bundle_rtcp_flow, + filter); nsresult res = pipeline->Init(); if (NS_FAILED(res)) { @@ -1642,7 +1706,12 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id, stream->GetMediaStream()->GetStream(), pc_track_id, level, - conduit, rtp_flow, rtcp_flow); + conduit, + rtp_flow, + rtcp_flow, + bundle_rtp_flow, + bundle_rtcp_flow, + filter); nsresult res = pipeline->Init(); if (NS_FAILED(res)) { @@ -2182,7 +2251,12 @@ static int vcmTxStartICE_m(cc_mcapid_t mcap_id, const char *fingerprint, vcm_mediaAttrs_t *attrs) { - CSFLogDebug( logTag, "%s(%s)", __FUNCTION__, peerconnection); + CSFLogDebug( logTag, "%s(%s) track = %d, stream = %d, level = %d", + __FUNCTION__, + peerconnection, + pc_track_id, + pc_stream_id, + level); // Find the PC and get the stream sipcc::PeerConnectionWrapper pc(peerconnection); @@ -2208,6 +2282,22 @@ static int vcmTxStartICE_m(cc_mcapid_t mcap_id, } } + // This tells the receive MediaPipeline (if there is one) whether we are + // doing bundle, and if so, updates the filter. This does not affect the + // transmit MediaPipeline (created above) at all. + if (attrs->bundle_level) { + nsAutoPtr filter (new MediaPipelineFilter); + for (int s = 0; s < attrs->num_ssrcs; ++s) { + filter->AddRemoteSSRC(attrs->ssrcs[s]); + } + pc.impl()->media()->SetUsingBundle_m(level, true); + pc.impl()->media()->UpdateFilterFromRemoteDescription_m(level, filter); + } else { + // This will also clear the filter. + pc.impl()->media()->SetUsingBundle_m(level, false); + } + + if (CC_IS_AUDIO(mcap_id)) { mozilla::AudioCodecConfig *config_raw; config_raw = new mozilla::AudioCodecConfig( diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp index bffb9a0f8609..dd660106c6fd 100644 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp @@ -42,6 +42,9 @@ #include "mozilla/gfx/Point.h" #include "mozilla/gfx/Types.h" +#include "webrtc/modules/interface/module_common_types.h" +#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" + using namespace mozilla; using namespace mozilla::gfx; @@ -75,41 +78,35 @@ nsresult MediaPipeline::Init_s() { conduit_->AttachTransport(transport_); nsresult res; - MOZ_ASSERT(rtp_transport_); - // Look to see if the transport is ready - rtp_transport_->SignalStateChange.connect(this, - &MediaPipeline::StateChange); - - if (rtp_transport_->state() == TransportLayer::TS_OPEN) { - res = TransportReady_s(rtp_transport_); - if (NS_FAILED(res)) { - MOZ_MTLOG(ML_ERROR, "Error calling TransportReady(); res=" - << static_cast(res) << " in " << __FUNCTION__); - return res; - } - } else if (rtp_transport_->state() == TransportLayer::TS_ERROR) { - MOZ_MTLOG(ML_ERROR, "RTP transport is already in error state"); - TransportFailed_s(rtp_transport_); - return NS_ERROR_FAILURE; + MOZ_ASSERT(rtp_.transport_); + MOZ_ASSERT(rtcp_.transport_); + res = ConnectTransport_s(rtp_); + if (NS_FAILED(res)) { + return res; } - // If rtcp_transport_ is the same as rtp_transport_ then we are muxing. - // Otherwise, set it up separately. - if (rtcp_transport_ != rtp_transport_) { - rtcp_transport_->SignalStateChange.connect(this, - &MediaPipeline::StateChange); + if (rtcp_.transport_ != rtp_.transport_) { + res = ConnectTransport_s(rtcp_); + if (NS_FAILED(res)) { + return res; + } + } - if (rtcp_transport_->state() == TransportLayer::TS_OPEN) { - res = TransportReady_s(rtcp_transport_); + if (possible_bundle_rtp_) { + MOZ_ASSERT(possible_bundle_rtcp_); + MOZ_ASSERT(possible_bundle_rtp_->transport_); + MOZ_ASSERT(possible_bundle_rtcp_->transport_); + + res = ConnectTransport_s(*possible_bundle_rtp_); + if (NS_FAILED(res)) { + return res; + } + + if (possible_bundle_rtcp_->transport_ != possible_bundle_rtp_->transport_) { + res = ConnectTransport_s(*possible_bundle_rtcp_); if (NS_FAILED(res)) { - MOZ_MTLOG(ML_ERROR, "Error calling TransportReady(); res=" - << static_cast(res) << " in " << __FUNCTION__); return res; } - } else if (rtcp_transport_->state() == TransportLayer::TS_ERROR) { - MOZ_MTLOG(ML_ERROR, "RTCP transport is already in error state"); - TransportFailed_s(rtcp_transport_); - return NS_ERROR_FAILURE; } } @@ -126,55 +123,72 @@ void MediaPipeline::ShutdownTransport_s() { disconnect_all(); transport_->Detach(); - rtp_transport_ = nullptr; - rtcp_transport_ = nullptr; + rtp_.transport_ = nullptr; + rtcp_.transport_ = nullptr; + possible_bundle_rtp_ = nullptr; + possible_bundle_rtcp_ = nullptr; } void MediaPipeline::StateChange(TransportFlow *flow, TransportLayer::State state) { - // If rtcp_transport_ is the same as rtp_transport_ then we are muxing. - // So the only flow should be the RTP flow. - if (rtcp_transport_ == rtp_transport_) { - MOZ_ASSERT(flow == rtp_transport_); - } + TransportInfo* info = GetTransportInfo_s(flow); + MOZ_ASSERT(info); if (state == TransportLayer::TS_OPEN) { MOZ_MTLOG(ML_INFO, "Flow is ready"); - TransportReady_s(flow); + TransportReady_s(*info); } else if (state == TransportLayer::TS_CLOSED || state == TransportLayer::TS_ERROR) { - TransportFailed_s(flow); + TransportFailed_s(*info); } } -nsresult MediaPipeline::TransportReady_s(TransportFlow *flow) { +static bool MakeRtpTypeToStringArray(const char** array) { + static const char* RTP_str = "RTP"; + static const char* RTCP_str = "RTCP"; + static const char* MUX_str = "RTP/RTCP mux"; + array[MediaPipeline::RTP] = RTP_str; + array[MediaPipeline::RTCP] = RTCP_str; + array[MediaPipeline::MUX] = MUX_str; + return true; +} + +static const char* ToString(MediaPipeline::RtpType type) { + static const char* array[(int)MediaPipeline::MAX_RTP_TYPE] = {nullptr}; + // Dummy variable to cause init to happen only on first call + static bool dummy = MakeRtpTypeToStringArray(array); + (void)dummy; + return array[type]; +} + +nsresult MediaPipeline::TransportReady_s(TransportInfo &info) { MOZ_ASSERT(!description_.empty()); - bool rtcp = !(flow == rtp_transport_); - State *state = rtcp ? &rtcp_state_ : &rtp_state_; // TODO(ekr@rtfm.com): implement some kind of notification on // failure. bug 852665. - if (*state != MP_CONNECTING) { + if (info.state_ != MP_CONNECTING) { MOZ_MTLOG(ML_ERROR, "Transport ready for flow in wrong state:" << - description_ << ": " << (rtcp ? "rtcp" : "rtp")); + description_ << ": " << ToString(info.type_)); return NS_ERROR_FAILURE; } - nsresult res; - MOZ_MTLOG(ML_INFO, "Transport ready for pipeline " << static_cast(this) << " flow " << description_ << ": " << - (rtcp ? "rtcp" : "rtp")); + ToString(info.type_)); + + // TODO(bcampen@mozilla.com): Should we disconnect from the flow on failure? + nsresult res; // Now instantiate the SRTP objects TransportLayerDtls *dtls = static_cast( - flow->GetLayer(TransportLayerDtls::ID())); + info.transport_->GetLayer(TransportLayerDtls::ID())); MOZ_ASSERT(dtls); // DTLS is mandatory uint16_t cipher_suite; res = dtls->GetSrtpCipher(&cipher_suite); if (NS_FAILED(res)) { MOZ_MTLOG(ML_ERROR, "Failed to negotiate DTLS-SRTP. This is an error"); - *state = MP_CLOSED; + info.state_ = MP_CLOSED; + UpdateRtcpMuxState(info); return res; } @@ -184,7 +198,8 @@ nsresult MediaPipeline::TransportReady_s(TransportFlow *flow) { srtp_block, sizeof(srtp_block)); if (NS_FAILED(res)) { MOZ_MTLOG(ML_ERROR, "Failed to compute DTLS-SRTP keys. This is an error"); - *state = MP_CLOSED; + info.state_ = MP_CLOSED; + UpdateRtcpMuxState(info); MOZ_CRASH(); // TODO: Remove once we have enough field experience to // know it doesn't happen. bug 798797. Note that the // code after this never executes. @@ -218,88 +233,63 @@ nsresult MediaPipeline::TransportReady_s(TransportFlow *flow) { read_key = client_write_key; } - if (!rtcp) { - // RTP side - MOZ_ASSERT(!rtp_send_srtp_ && !rtp_recv_srtp_); - rtp_send_srtp_ = SrtpFlow::Create(cipher_suite, false, - write_key, SRTP_TOTAL_KEY_LENGTH); - rtp_recv_srtp_ = SrtpFlow::Create(cipher_suite, true, - read_key, SRTP_TOTAL_KEY_LENGTH); - if (!rtp_send_srtp_ || !rtp_recv_srtp_) { - MOZ_MTLOG(ML_ERROR, "Couldn't create SRTP flow for RTCP"); - *state = MP_CLOSED; - return NS_ERROR_FAILURE; - } - - // Start listening - // If rtcp_transport_ is the same as rtp_transport_ then we are muxing - if (rtcp_transport_ == rtp_transport_) { - MOZ_ASSERT(!rtcp_send_srtp_ && !rtcp_recv_srtp_); - rtcp_send_srtp_ = rtp_send_srtp_; - rtcp_recv_srtp_ = rtp_recv_srtp_; - - MOZ_MTLOG(ML_INFO, "Listening for packets received on " << - static_cast(dtls->downward())); - - dtls->downward()->SignalPacketReceived.connect(this, - &MediaPipeline:: - PacketReceived); - rtcp_state_ = MP_OPEN; - } else { - MOZ_MTLOG(ML_INFO, "Listening for RTP packets received on " << - static_cast(dtls->downward())); - - dtls->downward()->SignalPacketReceived.connect(this, - &MediaPipeline:: - RtpPacketReceived); - } - } - else { - MOZ_ASSERT(!rtcp_send_srtp_ && !rtcp_recv_srtp_); - rtcp_send_srtp_ = SrtpFlow::Create(cipher_suite, false, - write_key, SRTP_TOTAL_KEY_LENGTH); - rtcp_recv_srtp_ = SrtpFlow::Create(cipher_suite, true, - read_key, SRTP_TOTAL_KEY_LENGTH); - if (!rtcp_send_srtp_ || !rtcp_recv_srtp_) { - MOZ_MTLOG(ML_ERROR, "Couldn't create SRTCP flow for RTCP"); - *state = MP_CLOSED; - return NS_ERROR_FAILURE; - } - - MOZ_MTLOG(ML_DEBUG, "Listening for RTCP packets received on " << - static_cast(dtls->downward())); - - // Start listening - dtls->downward()->SignalPacketReceived.connect(this, - &MediaPipeline:: - RtcpPacketReceived); + MOZ_ASSERT(!info.send_srtp_ && !info.recv_srtp_); + info.send_srtp_ = SrtpFlow::Create(cipher_suite, false, write_key, + SRTP_TOTAL_KEY_LENGTH); + info.recv_srtp_ = SrtpFlow::Create(cipher_suite, true, read_key, + SRTP_TOTAL_KEY_LENGTH); + if (!info.send_srtp_ || !info.recv_srtp_) { + MOZ_MTLOG(ML_ERROR, "Couldn't create SRTP flow for " + << ToString(info.type_)); + info.state_ = MP_CLOSED; + UpdateRtcpMuxState(info); + return NS_ERROR_FAILURE; } - *state = MP_OPEN; + if (direction_ == RECEIVE) { + // The TRANSMIT pipeline does not process _any_ RTCP. This is the RECEIVE + // pipeline's job, even for receiver reports. + MOZ_MTLOG(ML_INFO, "Listening for " << ToString(info.type_) + << " packets received on " << + static_cast(dtls->downward())); + + switch (info.type_) { + case RTP: + dtls->downward()->SignalPacketReceived.connect( + this, + &MediaPipeline::RtpPacketReceived); + break; + case RTCP: + dtls->downward()->SignalPacketReceived.connect( + this, + &MediaPipeline::RtcpPacketReceived); + break; + case MUX: + dtls->downward()->SignalPacketReceived.connect( + this, + &MediaPipeline::PacketReceived); + break; + default: + MOZ_CRASH(); + } + } + + info.state_ = MP_OPEN; + UpdateRtcpMuxState(info); return NS_OK; } -nsresult MediaPipeline::TransportFailed_s(TransportFlow *flow) { +nsresult MediaPipeline::TransportFailed_s(TransportInfo &info) { ASSERT_ON_THREAD(sts_thread_); - bool rtcp = !(flow == rtp_transport_); - State *state = rtcp ? &rtcp_state_ : &rtp_state_; + info.state_ = MP_CLOSED; + UpdateRtcpMuxState(info); - *state = MP_CLOSED; - - // If rtcp_transport_ is the same as rtp_transport_ then we are muxing - if(rtcp_transport_ == rtp_transport_) { - MOZ_ASSERT(state != &rtcp_state_); - rtcp_state_ = MP_CLOSED; - } - - - MOZ_MTLOG(ML_INFO, "Transport closed for flow " << (rtcp ? "rtcp" : "rtp")); + MOZ_MTLOG(ML_INFO, "Transport closed for flow " << ToString(info.type_)); NS_WARNING( "MediaPipeline Transport failed. This is not properly cleaned up yet"); - // TODO(ekr@rtfm.com): SECURITY: Figure out how to clean up if the // connection was good and now it is bad. // TODO(ekr@rtfm.com): Report up so that the PC knows we @@ -308,6 +298,24 @@ nsresult MediaPipeline::TransportFailed_s(TransportFlow *flow) { return NS_OK; } +void MediaPipeline::UpdateRtcpMuxState(TransportInfo &info) { + if (info.type_ == MUX) { + if (info.transport_ == rtcp_.transport_) { + rtcp_.state_ = info.state_; + if (!rtcp_.send_srtp_) { + rtcp_.send_srtp_ = info.send_srtp_; + rtcp_.recv_srtp_ = info.recv_srtp_; + } + } else if (possible_bundle_rtcp_ && + info.transport_ == possible_bundle_rtcp_->transport_) { + possible_bundle_rtcp_->state_ = info.state_; + if (!possible_bundle_rtcp_->send_srtp_) { + possible_bundle_rtcp_->send_srtp_ = info.send_srtp_; + possible_bundle_rtcp_->recv_srtp_ = info.recv_srtp_; + } + } + } +} nsresult MediaPipeline::SendPacket(TransportFlow *flow, const void *data, int len) { @@ -340,7 +348,7 @@ void MediaPipeline::increment_rtp_packets_sent(int32_t bytes) { if (!(rtp_packets_sent_ % 100)) { MOZ_MTLOG(ML_INFO, "RTP sent packet count for " << description_ << " Pipeline " << static_cast(this) - << " Flow : " << static_cast(rtp_transport_) + << " Flow : " << static_cast(rtp_.transport_) << ": " << rtp_packets_sent_ << " (" << rtp_bytes_sent_ << " bytes)"); } @@ -351,7 +359,7 @@ void MediaPipeline::increment_rtcp_packets_sent() { if (!(rtcp_packets_sent_ % 100)) { MOZ_MTLOG(ML_INFO, "RTCP sent packet count for " << description_ << " Pipeline " << static_cast(this) - << " Flow : " << static_cast(rtcp_transport_) + << " Flow : " << static_cast(rtcp_.transport_) << ": " << rtcp_packets_sent_); } } @@ -362,7 +370,7 @@ void MediaPipeline::increment_rtp_packets_received(int32_t bytes) { if (!(rtp_packets_received_ % 100)) { MOZ_MTLOG(ML_INFO, "RTP received packet count for " << description_ << " Pipeline " << static_cast(this) - << " Flow : " << static_cast(rtp_transport_) + << " Flow : " << static_cast(rtp_.transport_) << ": " << rtp_packets_received_ << " (" << rtp_bytes_received_ << " bytes)"); } @@ -373,7 +381,7 @@ void MediaPipeline::increment_rtcp_packets_received() { if (!(rtcp_packets_received_ % 100)) { MOZ_MTLOG(ML_INFO, "RTCP received packet count for " << description_ << " Pipeline " << static_cast(this) - << " Flow : " << static_cast(rtcp_transport_) + << " Flow : " << static_cast(rtcp_.transport_) << ": " << rtcp_packets_received_); } } @@ -391,34 +399,84 @@ void MediaPipeline::RtpPacketReceived(TransportLayer *layer, return; } - if (rtp_state_ != MP_OPEN) { + TransportInfo* info = &rtp_; + + if (possible_bundle_rtp_ && + possible_bundle_rtp_->transport_->Contains(layer)) { + // Received this on our possible bundle transport. Override info. + info = possible_bundle_rtp_; + } + + // TODO(bcampen@mozilla.com): Can either of these actually happen? If not, + // the info variable can be removed, and this function gets simpler. + if (info->state_ != MP_OPEN) { MOZ_MTLOG(ML_ERROR, "Discarding incoming packet; pipeline not open"); return; } - if (rtp_transport_->state() != TransportLayer::TS_OPEN) { + if (info->transport_->state() != TransportLayer::TS_OPEN) { MOZ_MTLOG(ML_ERROR, "Discarding incoming packet; transport not open"); return; } - MOZ_ASSERT(rtp_recv_srtp_); // This should never happen + // This should never happen. + MOZ_ASSERT(info->recv_srtp_); if (direction_ == TRANSMIT) { - // Discard any media that is being transmitted to us - // This will be unnecessary when we have SSRC filtering. return; } - // TODO(ekr@rtfm.com): filter for DTLS here and in RtcpPacketReceived - // TODO(ekr@rtfm.com): filter on SSRC for bundle + if (possible_bundle_rtp_ && (info == &rtp_)) { + // We were not sure we would be using rtp_ or possible_bundle_rtp_, but we + // have just received traffic that clears this up. + // Don't let our filter prevent us from noticing this, if the filter is + // incomplete (ie; no SSRCs in remote SDP, or no remote SDP at all). + SetUsingBundle_s(false); + MOZ_MTLOG(ML_INFO, "Ruled out the possibility that we're receiving bundle " + "for " << description_); + // TODO(bcampen@mozilla.com): Might be nice to detect when every + // MediaPipeline but the master has determined that it isn't doing bundle, + // since that means the master isn't doing bundle either. We could maybe + // do this by putting some refcounted dummy variable in the filters, and + // checking the value of the refcount. It is not clear whether this is + // going to be useful in practice. + } + + if (!len) { + return; + } + + // Filter out everything but RTP/RTCP + if (data[0] < 128 || data[0] > 191) { + return; + } + + if (filter_) { + webrtc::RTPHeader header; + if (!rtp_parser_->Parse(data, len, &header) || + !filter_->Filter(header)) { + return; + } + } + + if (possible_bundle_rtp_) { + // Just got traffic that passed our filter on the potential bundle + // transport. Must be doing bundle. + SetUsingBundle_s(true); + MOZ_MTLOG(ML_INFO, "Confirmed the possibility that we're receiving bundle"); + } + + // Everything is decided now; just use rtp_ + MOZ_ASSERT(!possible_bundle_rtp_); + MOZ_ASSERT(!possible_bundle_rtcp_); // Make a copy rather than cast away constness ScopedDeletePtr inner_data( new unsigned char[len]); memcpy(inner_data, data, len); int out_len = 0; - nsresult res = rtp_recv_srtp_->UnprotectRtp(inner_data, - len, len, &out_len); + nsresult res = rtp_.recv_srtp_->UnprotectRtp(inner_data, + len, len, &out_len); if (!NS_SUCCEEDED(res)) { char tmp[16]; @@ -451,25 +509,58 @@ void MediaPipeline::RtcpPacketReceived(TransportLayer *layer, return; } - if (rtcp_state_ != MP_OPEN) { + TransportInfo* info = &rtcp_; + if (possible_bundle_rtcp_ && + possible_bundle_rtcp_->transport_->Contains(layer)) { + info = possible_bundle_rtcp_; + } + + if (info->state_ != MP_OPEN) { MOZ_MTLOG(ML_DEBUG, "Discarding incoming packet; pipeline not open"); return; } - if (rtcp_transport_->state() != TransportLayer::TS_OPEN) { + if (info->transport_->state() != TransportLayer::TS_OPEN) { MOZ_MTLOG(ML_ERROR, "Discarding incoming packet; transport not open"); return; } - if (direction_ == RECEIVE) { - // Discard any RTCP that is being transmitted to us - // This will be unnecessary when we have SSRC filtering. + if (possible_bundle_rtp_ && (info == &rtcp_)) { + // We have offered bundle, and received our first packet on a non-bundle + // address. We are definitely not using the bundle address. + SetUsingBundle_s(false); + } + + if (!len) { return; } + // Filter out everything but RTP/RTCP + if (data[0] < 128 || data[0] > 191) { + return; + } + + MediaPipelineFilter::Result filter_result = MediaPipelineFilter::PASS; + if (filter_) { + filter_result = filter_->FilterRTCP(data, len); + if (filter_result == MediaPipelineFilter::FAIL) { + return; + } + } + + if (filter_result == MediaPipelineFilter::PASS && possible_bundle_rtp_) { + // Just got traffic that passed our filter on the potential bundle + // transport. Must be doing bundle. + SetUsingBundle_s(true); + } + + // We continue using info here, since it is possible that the filter did not + // support the payload type (ie; returned MediaPipelineFilter::UNSUPPORTED). + // In this case, we just let it pass, and hope the webrtc.org code does + // something sane. increment_rtcp_packets_received(); - MOZ_ASSERT(rtcp_recv_srtp_); // This should never happen + MOZ_ASSERT(info->recv_srtp_); // This should never happen // Make a copy rather than cast away constness ScopedDeletePtr inner_data( @@ -477,7 +568,10 @@ void MediaPipeline::RtcpPacketReceived(TransportLayer *layer, memcpy(inner_data, data, len); int out_len; - nsresult res = rtcp_recv_srtp_->UnprotectRtcp(inner_data, len, len, &out_len); + nsresult res = info->recv_srtp_->UnprotectRtcp(inner_data, + len, + len, + &out_len); if (!NS_SUCCEEDED(res)) return; @@ -563,11 +657,14 @@ nsresult MediaPipelineTransmit::Init() { return MediaPipeline::Init(); } -nsresult MediaPipelineTransmit::TransportReady_s(TransportFlow *flow) { +nsresult MediaPipelineTransmit::TransportReady_s(TransportInfo &info) { + ASSERT_ON_THREAD(sts_thread_); // Call base ready function. - MediaPipeline::TransportReady_s(flow); + MediaPipeline::TransportReady_s(info); - if (flow == rtp_transport_) { + // Should not be set for a transmitter + MOZ_ASSERT(!possible_bundle_rtp_); + if (&info == &rtp_) { // TODO(ekr@rtfm.com): Move onto MSG thread. listener_->SetActive(true); } @@ -575,6 +672,121 @@ nsresult MediaPipelineTransmit::TransportReady_s(TransportFlow *flow) { return NS_OK; } +void MediaPipeline::DisconnectTransport_s(TransportInfo &info) { + MOZ_ASSERT(info.transport_); + ASSERT_ON_THREAD(sts_thread_); + + info.transport_->SignalStateChange.disconnect(this); + // We do this even if we're a transmitter, since we are still possibly + // registered to receive RTCP. + TransportLayerDtls *dtls = static_cast( + info.transport_->GetLayer(TransportLayerDtls::ID())); + MOZ_ASSERT(dtls); // DTLS is mandatory + MOZ_ASSERT(dtls->downward()); + dtls->downward()->SignalPacketReceived.disconnect(this); +} + +nsresult MediaPipeline::ConnectTransport_s(TransportInfo &info) { + MOZ_ASSERT(info.transport_); + ASSERT_ON_THREAD(sts_thread_); + + // Look to see if the transport is ready + if (info.transport_->state() == TransportLayer::TS_OPEN) { + nsresult res = TransportReady_s(info); + if (NS_FAILED(res)) { + MOZ_MTLOG(ML_ERROR, "Error calling TransportReady(); res=" + << static_cast(res) << " in " << __FUNCTION__); + return res; + } + } else if (info.transport_->state() == TransportLayer::TS_ERROR) { + MOZ_MTLOG(ML_ERROR, ToString(info.type_) + << "transport is already in error state"); + TransportFailed_s(info); + return NS_ERROR_FAILURE; + } + + info.transport_->SignalStateChange.connect(this, + &MediaPipeline::StateChange); + + return NS_OK; +} + +MediaPipeline::TransportInfo* MediaPipeline::GetTransportInfo_s( + TransportFlow *flow) { + ASSERT_ON_THREAD(sts_thread_); + if (flow == rtp_.transport_) { + return &rtp_; + } + + if (flow == rtcp_.transport_) { + return &rtcp_; + } + + if (possible_bundle_rtp_) { + if (flow == possible_bundle_rtp_->transport_) { + return possible_bundle_rtp_; + } + + if (flow == possible_bundle_rtcp_->transport_) { + return possible_bundle_rtcp_; + } + } + + return nullptr; +} + +void MediaPipeline::SetUsingBundle_s(bool decision) { + ASSERT_ON_THREAD(sts_thread_); + // Note: This can be called either because of events on the STS thread, or + // by events on the main thread (ie; receiving a remote description). It is + // best to be careful of races here, so don't assume that transports are open. + if (!possible_bundle_rtp_) { + if (!decision) { + // This can happen on the master pipeline. + filter_ = nullptr; + } + return; + } + + if (direction_ == RECEIVE) { + if (decision) { + MOZ_MTLOG(ML_INFO, "Non-master pipeline confirmed bundle for " + << description_); + // We're doing bundle. Release the unused flows, and copy the ones we + // are using into the less wishy-washy members. + DisconnectTransport_s(rtp_); + DisconnectTransport_s(rtcp_); + rtp_ = *possible_bundle_rtp_; + rtcp_ = *possible_bundle_rtcp_; + } else { + MOZ_MTLOG(ML_INFO, "Non-master pipeline confirmed no bundle for " + << description_); + // We are not doing bundle + DisconnectTransport_s(*possible_bundle_rtp_); + DisconnectTransport_s(*possible_bundle_rtcp_); + filter_ = nullptr; + } + + // We are no longer in an ambiguous state. + possible_bundle_rtp_ = nullptr; + possible_bundle_rtcp_ = nullptr; + } +} + +void MediaPipeline::UpdateFilterFromRemoteDescription_s( + nsAutoPtr filter) { + ASSERT_ON_THREAD(sts_thread_); + // This is only supposed to relax the filter. Relaxing a missing filter is + // not possible. + MOZ_ASSERT(filter_); + + if (!filter) { + filter_ = nullptr; + } else { + filter_->IncorporateRemoteDescription(*filter); + } +} + nsresult MediaPipeline::PipelineTransport::SendRtpPacket( const void *data, int len) { @@ -593,16 +805,17 @@ nsresult MediaPipeline::PipelineTransport::SendRtpPacket( nsresult MediaPipeline::PipelineTransport::SendRtpPacket_s( nsAutoPtr data) { + ASSERT_ON_THREAD(sts_thread_); if (!pipeline_) return NS_OK; // Detached - if (!pipeline_->rtp_send_srtp_) { + if (!pipeline_->rtp_.send_srtp_) { MOZ_MTLOG(ML_DEBUG, "Couldn't write RTP packet; SRTP not set up yet"); return NS_OK; } - MOZ_ASSERT(pipeline_->rtp_transport_); - NS_ENSURE_TRUE(pipeline_->rtp_transport_, NS_ERROR_NULL_POINTER); + MOZ_ASSERT(pipeline_->rtp_.transport_); + NS_ENSURE_TRUE(pipeline_->rtp_.transport_, NS_ERROR_NULL_POINTER); // libsrtp enciphers in place, so we need a new, big enough // buffer. @@ -614,15 +827,15 @@ nsresult MediaPipeline::PipelineTransport::SendRtpPacket_s( memcpy(inner_data, data->data(), data->len()); int out_len; - nsresult res = pipeline_->rtp_send_srtp_->ProtectRtp(inner_data, - data->len(), - max_len, - &out_len); + nsresult res = pipeline_->rtp_.send_srtp_->ProtectRtp(inner_data, + data->len(), + max_len, + &out_len); if (!NS_SUCCEEDED(res)) return res; pipeline_->increment_rtp_packets_sent(out_len); - return pipeline_->SendPacket(pipeline_->rtp_transport_, inner_data, + return pipeline_->SendPacket(pipeline_->rtp_.transport_, inner_data, out_len); } @@ -644,16 +857,17 @@ nsresult MediaPipeline::PipelineTransport::SendRtcpPacket( nsresult MediaPipeline::PipelineTransport::SendRtcpPacket_s( nsAutoPtr data) { + ASSERT_ON_THREAD(sts_thread_); if (!pipeline_) return NS_OK; // Detached - if (!pipeline_->rtcp_send_srtp_) { + if (!pipeline_->rtcp_.send_srtp_) { MOZ_MTLOG(ML_DEBUG, "Couldn't write RTCP packet; SRTCP not set up yet"); return NS_OK; } - MOZ_ASSERT(pipeline_->rtcp_transport_); - NS_ENSURE_TRUE(pipeline_->rtcp_transport_, NS_ERROR_NULL_POINTER); + MOZ_ASSERT(pipeline_->rtcp_.transport_); + NS_ENSURE_TRUE(pipeline_->rtcp_.transport_, NS_ERROR_NULL_POINTER); // libsrtp enciphers in place, so we need a new, big enough // buffer. @@ -665,15 +879,16 @@ nsresult MediaPipeline::PipelineTransport::SendRtcpPacket_s( memcpy(inner_data, data->data(), data->len()); int out_len; - nsresult res = pipeline_->rtcp_send_srtp_->ProtectRtcp(inner_data, - data->len(), - max_len, - &out_len); + nsresult res = pipeline_->rtcp_.send_srtp_->ProtectRtcp(inner_data, + data->len(), + max_len, + &out_len); + if (!NS_SUCCEEDED(res)) return res; pipeline_->increment_rtcp_packets_sent(); - return pipeline_->SendPacket(pipeline_->rtcp_transport_, inner_data, + return pipeline_->SendPacket(pipeline_->rtcp_.transport_, inner_data, out_len); } diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h index 9339deda1428..d48a5fc9806e 100644 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h @@ -18,6 +18,7 @@ #include "VideoUtils.h" #endif #include "MediaConduitInterface.h" +#include "MediaPipelineFilter.h" #include "AudioSegment.h" #include "mozilla/ReentrantMonitor.h" #include "SrtpFlow.h" @@ -29,6 +30,8 @@ #include "VideoSegment.h" #endif +#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" + namespace mozilla { // A class that represents the pipeline of audio and video @@ -80,16 +83,11 @@ class MediaPipeline : public sigslot::has_slots<> { track_id_(track_id), level_(level), conduit_(conduit), - rtp_transport_(rtp_transport), - rtp_state_(MP_CONNECTING), - rtcp_transport_(rtcp_transport), - rtcp_state_(MP_CONNECTING), + rtp_(rtp_transport, rtcp_transport ? RTP : MUX), + rtcp_(rtcp_transport ? rtcp_transport : rtp_transport, + rtcp_transport ? RTCP : MUX), main_thread_(main_thread), sts_thread_(sts_thread), - rtp_send_srtp_(), - rtcp_send_srtp_(), - rtp_recv_srtp_(), - rtcp_recv_srtp_(), rtp_packets_sent_(0), rtcp_packets_sent_(0), rtp_packets_received_(0), @@ -101,11 +99,8 @@ class MediaPipeline : public sigslot::has_slots<> { // To indicate rtcp-mux rtcp_transport should be nullptr. // Therefore it's an error to send in the same flow for // both rtp and rtcp. - MOZ_ASSERT(rtp_transport_ != rtcp_transport_); + MOZ_ASSERT(rtp_transport != rtcp_transport); - if (!rtcp_transport_) { - rtcp_transport_ = rtp_transport; - } // PipelineTransport() will access this->sts_thread_; moved here for safety transport_ = new PipelineTransport(this); } @@ -126,12 +121,22 @@ class MediaPipeline : public sigslot::has_slots<> { virtual nsresult Init(); + // When we have offered bundle, the MediaPipelines are created in an + // indeterminate state; we do not know whether the answerer will take us + // up on our offer. In the meantime, we need to behave in a manner that + // errs on the side of packet loss when it is unclear whether an arriving + // packet is meant for us. We want to get out of this indeterminate state + // ASAP, which is what this function can be used for. + void SetUsingBundle_s(bool decision); + void UpdateFilterFromRemoteDescription_s( + nsAutoPtr filter); + virtual Direction direction() const { return direction_; } virtual TrackID trackid() const { return track_id_; } virtual int level() const { return level_; } bool IsDoingRtcpMux() const { - return (rtp_transport_ == rtcp_transport_); + return (rtp_.type_ == MUX); } int32_t rtp_packets_sent() const { return rtp_packets_sent_; } @@ -146,6 +151,13 @@ class MediaPipeline : public sigslot::has_slots<> { // Thread counting NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaPipeline) + typedef enum { + RTP, + RTCP, + MUX, + MAX_RTP_TYPE + } RtpType; + protected: virtual void DetachMediaStream() {} @@ -153,7 +165,7 @@ class MediaPipeline : public sigslot::has_slots<> { class PipelineTransport : public TransportInterface { public: // Implement the TransportInterface functions - PipelineTransport(MediaPipeline *pipeline) + explicit PipelineTransport(MediaPipeline *pipeline) : pipeline_(pipeline), sts_thread_(pipeline->sts_thread_) {} @@ -172,15 +184,40 @@ class MediaPipeline : public sigslot::has_slots<> { }; friend class PipelineTransport; - virtual nsresult TransportFailed_s(TransportFlow *flow); // The transport is down - virtual nsresult TransportReady_s(TransportFlow *flow); // The transport is ready + class TransportInfo { + public: + TransportInfo(RefPtr flow, RtpType type) : + transport_(flow), + state_(MP_CONNECTING), + type_(type) { + MOZ_ASSERT(flow); + } + + RefPtr transport_; + State state_; + RefPtr send_srtp_; + RefPtr recv_srtp_; + RtpType type_; + }; + + // The transport is down + virtual nsresult TransportFailed_s(TransportInfo &info); + // The transport is ready + virtual nsresult TransportReady_s(TransportInfo &info); + void UpdateRtcpMuxState(TransportInfo &info); + + // Unhooks from signals + void DisconnectTransport_s(TransportInfo &info); + nsresult ConnectTransport_s(TransportInfo &info); + + TransportInfo* GetTransportInfo_s(TransportFlow *flow); void increment_rtp_packets_sent(int bytes); void increment_rtcp_packets_sent(); void increment_rtp_packets_received(int bytes); void increment_rtcp_packets_received(); - virtual nsresult SendPacket(TransportFlow *flow, const void* data, int len); + virtual nsresult SendPacket(TransportFlow *flow, const void *data, int len); // Process slots on transports void StateChange(TransportFlow *flow, TransportLayer::State); @@ -202,10 +239,18 @@ class MediaPipeline : public sigslot::has_slots<> { // thread. Read on STS thread. // The transport objects. Read/written on STS thread. - RefPtr rtp_transport_; - State rtp_state_; - RefPtr rtcp_transport_; - State rtcp_state_; + TransportInfo rtp_; + TransportInfo rtcp_; + // These are for bundle. We have a separate set because when we have offered + // bundle, we do not know whether we will receive traffic on the transport + // in this pipeline's m-line, or the transport in the "master" m-line for + // the bundle. We need to be ready for either. Once this ambiguity is + // resolved, the transport we know that we'll be using will be set in + // rtp_transport_ and rtcp_transport_, and these will be unset. + // TODO(bcampen@mozilla.com): I'm pretty sure this could be leveraged for + // re-offer with a new address on an m-line too, with a little work. + nsAutoPtr possible_bundle_rtp_; + nsAutoPtr possible_bundle_rtcp_; // Pointers to the threads we need. Initialized at creation // and used all over the place. @@ -216,15 +261,8 @@ class MediaPipeline : public sigslot::has_slots<> { // destroyed on the STS thread. RefPtr transport_; - // Used only on STS thread. - RefPtr rtp_send_srtp_; - RefPtr rtcp_send_srtp_; - RefPtr rtp_recv_srtp_; - RefPtr rtcp_recv_srtp_; - - // Written only on STS thread. May be read on other - // threads but since there is no mutex, the values - // will only be approximate. + // Only safe to access from STS thread. + // Build into TransportInfo? int32_t rtp_packets_sent_; int32_t rtcp_packets_sent_; int32_t rtp_packets_received_; @@ -236,6 +274,10 @@ class MediaPipeline : public sigslot::has_slots<> { std::string pc_; std::string description_; + // Written on Init, all following accesses are on the STS thread. + nsAutoPtr filter_; + nsAutoPtr rtp_parser_; + private: nsresult Init_s(); @@ -344,7 +386,7 @@ class MediaPipelineTransmit : public MediaPipeline { } // Override MediaPipeline::TransportReady. - virtual nsresult TransportReady_s(TransportFlow *flow); + virtual nsresult TransportReady_s(TransportInfo &info); // Separate class to allow ref counting class PipelineListener : public MediaStreamDirectListener { @@ -445,11 +487,26 @@ class MediaPipelineReceive : public MediaPipeline { int level, RefPtr conduit, RefPtr rtp_transport, - RefPtr rtcp_transport) : + RefPtr rtcp_transport, + RefPtr bundle_rtp_transport, + RefPtr bundle_rtcp_transport, + nsAutoPtr filter) : MediaPipeline(pc, RECEIVE, main_thread, sts_thread, stream, track_id, level, conduit, rtp_transport, rtcp_transport), segments_added_(0) { + filter_ = filter; + rtp_parser_ = webrtc::RtpHeaderParser::Create(); + if (bundle_rtp_transport) { + if (bundle_rtcp_transport) { + MOZ_ASSERT(bundle_rtp_transport != bundle_rtcp_transport); + possible_bundle_rtp_ = new TransportInfo(bundle_rtp_transport, RTP); + possible_bundle_rtcp_ = new TransportInfo(bundle_rtcp_transport, RTCP); + } else { + possible_bundle_rtp_ = new TransportInfo(bundle_rtp_transport, MUX); + possible_bundle_rtcp_ = new TransportInfo(bundle_rtp_transport, MUX); + } + } } int segments_added() const { return segments_added_; } @@ -473,10 +530,14 @@ class MediaPipelineReceiveAudio : public MediaPipelineReceive { int level, RefPtr conduit, RefPtr rtp_transport, - RefPtr rtcp_transport) : + RefPtr rtcp_transport, + RefPtr bundle_rtp_transport, + RefPtr bundle_rtcp_transport, + nsAutoPtr filter) : MediaPipelineReceive(pc, main_thread, sts_thread, stream, track_id, level, conduit, rtp_transport, - rtcp_transport), + rtcp_transport, bundle_rtp_transport, + bundle_rtcp_transport, filter), listener_(new PipelineListener(stream->AsSourceStream(), track_id, conduit)) { } @@ -536,10 +597,14 @@ class MediaPipelineReceiveVideo : public MediaPipelineReceive { int level, RefPtr conduit, RefPtr rtp_transport, - RefPtr rtcp_transport) : + RefPtr rtcp_transport, + RefPtr bundle_rtp_transport, + RefPtr bundle_rtcp_transport, + nsAutoPtr filter) : MediaPipelineReceive(pc, main_thread, sts_thread, stream, track_id, level, conduit, rtp_transport, - rtcp_transport), + rtcp_transport, bundle_rtp_transport, + bundle_rtcp_transport, filter), renderer_(new PipelineRenderer(MOZ_THIS_IN_INITIALIZER_LIST())), listener_(new PipelineListener(stream->AsSourceStream(), track_id)) { } diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp index b14b82709742..84a77a79c0a0 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp @@ -1327,9 +1327,11 @@ PeerConnectionImpl::GetStats(MediaStreamTrack *aSelector, bool internalStats) { if (temp.get()) { streams.push_back(temp); } else { - CSFLogError(logTag, "Failed to get NrIceMediaStream for level %u " + CSFLogError(logTag, "Failed to get NrIceMediaStream for level %zu " "in %s: %s", - uint32_t(level), __FUNCTION__, mHandle.c_str()); + static_cast(level), + __FUNCTION__, + mHandle.c_str()); MOZ_CRASH(); } } diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp index 4504ab82ce71..b6748455314d 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp @@ -396,6 +396,40 @@ PeerConnectionMedia::GetRemoteStream(int aIndex) return mRemoteSourceStreams[aIndex]; } +bool +PeerConnectionMedia::SetUsingBundle_m(int level, bool decision) +{ + ASSERT_ON_THREAD(mMainThread); + for (size_t i = 0; i < mRemoteSourceStreams.Length(); ++i) { + if (mRemoteSourceStreams[i]->SetUsingBundle_m(level, decision)) { + // Found the MediaPipeline for |level| + return true; + } + } + CSFLogWarn(logTag, "Could not locate level %d to set bundle flag to %s", + static_cast(level), + decision ? "true" : "false"); + return false; +} + +bool +PeerConnectionMedia::UpdateFilterFromRemoteDescription_m( + int level, + nsAutoPtr filter) +{ + ASSERT_ON_THREAD(mMainThread); + for (size_t i = 0; i < mRemoteSourceStreams.Length(); ++i) { + if (mRemoteSourceStreams[i]->UpdateFilterFromRemoteDescription_m(level, + filter)) { + // Found the MediaPipeline for |level| + return true; + } + } + CSFLogWarn(logTag, "Could not locate level %d to update filter", + static_cast(level)); + return false; +} + nsresult PeerConnectionMedia::AddRemoteStream(nsRefPtr aInfo, int *aIndex) @@ -503,5 +537,68 @@ RemoteSourceStreamInfo::StorePipeline(int aTrack, mTypes[aTrack] = aIsVideo; } +RefPtr RemoteSourceStreamInfo::GetPipelineByLevel_m(int level) { + ASSERT_ON_THREAD(mParent->GetMainThread()); + for (auto p = mPipelines.begin(); p != mPipelines.end(); ++p) { + if (p->second->level() == level) { + return p->second; + } + } + return nullptr; +} + +bool RemoteSourceStreamInfo::UpdateFilterFromRemoteDescription_m( + int aLevel, + nsAutoPtr aFilter) { + ASSERT_ON_THREAD(mParent->GetMainThread()); + + if (!mMediaStream) { + // Guard against dispatching once we've started teardown, since we don't + // want the RefPtr being the last one standing on the call + // to MediaPipeline::UpdateFilterFromRemoteDescription_s; it is not safe + // to delete a MediaPipeline anywhere other than the main thread. + return false; + } + + RefPtr pipeline(GetPipelineByLevel_m(aLevel)); + + if (pipeline) { + RUN_ON_THREAD(mParent->GetSTSThread(), + WrapRunnable( + pipeline, + &MediaPipeline::UpdateFilterFromRemoteDescription_s, + aFilter + ), + NS_DISPATCH_NORMAL); + return true; + } + return false; +} + +bool RemoteSourceStreamInfo::SetUsingBundle_m(int aLevel, bool decision) { + ASSERT_ON_THREAD(mParent->GetMainThread()); + + if (!mMediaStream) { + // Guard against dispatching once we've started teardown, since we don't + // want the RefPtr being the last one standing on the call + // to MediaPipeline::SetUsingBundle_s; it is not safe + // to delete a MediaPipeline anywhere other than the main thread. + return false; + } + + RefPtr pipeline(GetPipelineByLevel_m(aLevel)); + + if (pipeline) { + RUN_ON_THREAD(mParent->GetSTSThread(), + WrapRunnable( + pipeline, + &MediaPipeline::SetUsingBundle_s, + decision + ), + NS_DISPATCH_NORMAL); + return true; + } + return false; +} } // namespace sipcc diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h index b5e25017f3d8..4ec5cd614b56 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h @@ -244,6 +244,11 @@ class RemoteSourceStreamInfo : public SourceStreamInfo { void StorePipeline(int aTrack, bool aIsVideo, mozilla::RefPtr aPipeline); + bool UpdateFilterFromRemoteDescription_m( + int aLevel, + nsAutoPtr aFilter); + bool SetUsingBundle_m(int aLevel, bool decision); + void DetachTransport_s(); void DetachMedia_m(); @@ -252,6 +257,7 @@ class RemoteSourceStreamInfo : public SourceStreamInfo { public: DOMMediaStream::TrackTypeHints mTrackTypeHints; private: + mozilla::RefPtr GetPipelineByLevel_m(int level); std::map mTypes; }; @@ -296,6 +302,11 @@ class PeerConnectionMedia : public sigslot::has_slots<> { } RemoteSourceStreamInfo* GetRemoteStream(int index); + bool SetUsingBundle_m(int level, bool decision); + bool UpdateFilterFromRemoteDescription_m( + int level, + nsAutoPtr filter); + // Add a remote stream. Returns the index in index nsresult AddRemoteStream(nsRefPtr aInfo, int *aIndex); nsresult AddRemoteStreamHint(int aIndex, bool aIsVideo); diff --git a/media/webrtc/signaling/test/mediapipeline_unittest.cpp b/media/webrtc/signaling/test/mediapipeline_unittest.cpp index bee43898244b..5904843e0530 100644 --- a/media/webrtc/signaling/test/mediapipeline_unittest.cpp +++ b/media/webrtc/signaling/test/mediapipeline_unittest.cpp @@ -114,10 +114,20 @@ class TestAgent { audio_pipeline_() { } - void ConnectSocket(PRFileDesc *fd, bool client, bool isRtcp) { + void ConnectRtpSocket(PRFileDesc *fd, bool client) { + ConnectSocket(&audio_rtp_transport_, fd, client); + } + + void ConnectRtcpSocket(PRFileDesc *fd, bool client) { + ConnectSocket(&audio_rtcp_transport_, fd, client); + } + + void ConnectBundleSocket(PRFileDesc *fd, bool client) { + ConnectSocket(&bundle_transport_, fd, client); + } + + void ConnectSocket(TransportInfo *transport, PRFileDesc *fd, bool client) { nsresult res; - TransportInfo *transport = isRtcp ? - &audio_rtcp_transport_ : &audio_rtp_transport_; transport->Init(client); @@ -150,6 +160,7 @@ class TestAgent { audio_->GetStream()->Stop(); audio_rtp_transport_.Stop(); audio_rtcp_transport_.Stop(); + bundle_transport_.Stop(); if (audio_pipeline_) audio_pipeline_->ShutdownTransport_s(); } @@ -176,10 +187,13 @@ class TestAgent { mozilla::RefPtr audio_pipeline_; TransportInfo audio_rtp_transport_; TransportInfo audio_rtcp_transport_; + TransportInfo bundle_transport_; }; class TestAgentSend : public TestAgent { public: + TestAgentSend() : use_bundle_(false) {} + virtual void CreatePipelines_s(bool aIsRtcpMux) { audio_ = new Fake_DOMMediaStream(new Fake_AudioStreamSource()); @@ -194,6 +208,14 @@ class TestAgentSend : public TestAgent { ASSERT_FALSE(audio_rtcp_transport_.flow_); } + RefPtr rtp(audio_rtp_transport_.flow_); + RefPtr rtcp(audio_rtcp_transport_.flow_); + + if (use_bundle_) { + rtp = bundle_transport_.flow_; + rtcp = nullptr; + } + audio_pipeline_ = new mozilla::MediaPipelineTransmit( test_pc, nullptr, @@ -202,8 +224,8 @@ class TestAgentSend : public TestAgent { 1, 1, audio_conduit_, - audio_rtp_transport_.flow_, - audio_rtcp_transport_.flow_); + rtp, + rtcp); audio_pipeline_->Init(); } @@ -216,7 +238,12 @@ class TestAgentSend : public TestAgent { return audio_pipeline_->rtcp_packets_received(); } + void SetUsingBundle(bool use_bundle) { + use_bundle_ = use_bundle; + } + private: + bool use_bundle_; }; @@ -246,13 +273,24 @@ class TestAgentReceive : public TestAgent { ASSERT_FALSE(audio_rtcp_transport_.flow_); } + // For now, assume bundle always uses rtcp mux + RefPtr dummy; + RefPtr bundle_transport; + if (bundle_filter_) { + bundle_transport = bundle_transport_.flow_; + } + audio_pipeline_ = new mozilla::MediaPipelineReceiveAudio( test_pc, nullptr, test_utils->sts_target(), audio_->GetStream(), 1, 1, static_cast(audio_conduit_.get()), - audio_rtp_transport_.flow_, audio_rtcp_transport_.flow_); + audio_rtp_transport_.flow_, + audio_rtcp_transport_.flow_, + bundle_transport, + dummy, + bundle_filter_); audio_pipeline_->Init(); } @@ -265,7 +303,20 @@ class TestAgentReceive : public TestAgent { return audio_pipeline_->rtcp_packets_sent(); } + void SetBundleFilter(nsAutoPtr filter) { + bundle_filter_ = filter; + } + + void SetUsingBundle_s(bool decision) { + audio_pipeline_->SetUsingBundle_s(decision); + } + + void UpdateFilterFromRemoteDescription_s( + nsAutoPtr filter) { + audio_pipeline_->UpdateFilterFromRemoteDescription_s(filter); + } private: + nsAutoPtr bundle_filter_; }; @@ -274,6 +325,7 @@ class MediaPipelineTest : public ::testing::Test { MediaPipelineTest() : p1_() { rtp_fds_[0] = rtp_fds_[1] = nullptr; rtcp_fds_[0] = rtcp_fds_[1] = nullptr; + bundle_fds_[0] = bundle_fds_[1] = nullptr; } // Setup transport. @@ -285,12 +337,12 @@ class MediaPipelineTest : public ::testing::Test { // RTP, DTLS server mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), - WrapRunnable(&p1_, &TestAgent::ConnectSocket, rtp_fds_[0], false, false)); + WrapRunnable(&p1_, &TestAgent::ConnectRtpSocket, rtp_fds_[0], false)); // RTP, DTLS client mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), - WrapRunnable(&p2_, &TestAgent::ConnectSocket, rtp_fds_[1], true, false)); + WrapRunnable(&p2_, &TestAgent::ConnectRtpSocket, rtp_fds_[1], true)); // Create RTCP flows separately if we are not muxing them. if(!aIsRtcpMux) { @@ -300,17 +352,48 @@ class MediaPipelineTest : public ::testing::Test { // RTCP, DTLS server mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), - WrapRunnable(&p1_, &TestAgent::ConnectSocket, rtcp_fds_[0], false, true)); + WrapRunnable(&p1_, &TestAgent::ConnectRtcpSocket, rtcp_fds_[0], false)); // RTCP, DTLS client mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), - WrapRunnable(&p2_, &TestAgent::ConnectSocket, rtcp_fds_[1], true, true)); + WrapRunnable(&p2_, &TestAgent::ConnectRtcpSocket, rtcp_fds_[1], true)); } + + status = PR_NewTCPSocketPair(bundle_fds_); + // BUNDLE, DTLS server + mozilla::SyncRunnable::DispatchToThread( + test_utils->sts_target(), + WrapRunnable(&p1_, + &TestAgent::ConnectBundleSocket, + bundle_fds_[0], + false)); + + // BUNDLE, DTLS client + mozilla::SyncRunnable::DispatchToThread( + test_utils->sts_target(), + WrapRunnable(&p2_, + &TestAgent::ConnectBundleSocket, + bundle_fds_[1], + true)); + } // Verify RTP and RTCP - void TestAudioSend(bool aIsRtcpMux) { + void TestAudioSend(bool aIsRtcpMux, + bool bundle = false, + nsAutoPtr localFilter = + nsAutoPtr(nullptr), + nsAutoPtr remoteFilter = + nsAutoPtr(nullptr)) { + + // We do not support testing bundle without rtcp mux, since that doesn't + // make any sense. + ASSERT_FALSE(!aIsRtcpMux && bundle); + + p1_.SetUsingBundle(bundle); + p2_.SetBundleFilter(localFilter); + // Setup transport flows InitTransports(aIsRtcpMux); @@ -325,22 +408,51 @@ class MediaPipelineTest : public ::testing::Test { p2_.Start(); p1_.Start(); + // Simulate pre-answer traffic + PR_Sleep(500); + + mozilla::SyncRunnable::DispatchToThread( + test_utils->sts_target(), + WrapRunnable(&p2_, &TestAgentReceive::SetUsingBundle_s, bundle)); + + if (bundle) { + if (!remoteFilter) { + remoteFilter = new MediaPipelineFilter; + } + mozilla::SyncRunnable::DispatchToThread( + test_utils->sts_target(), + WrapRunnable(&p2_, + &TestAgentReceive::UpdateFilterFromRemoteDescription_s, + remoteFilter)); + } + + // wait for some RTP/RTCP tx and rx to happen PR_Sleep(10000); - ASSERT_GE(p1_.GetAudioRtpCount(), 40); + if (bundle) { + // Filter should have eaten everything, so no RTCP + } else { + ASSERT_GE(p1_.GetAudioRtpCount(), 40); // TODO: Fix to not fail or crash (Bug 947663) // ASSERT_GE(p2_.GetAudioRtpCount(), 40); - ASSERT_GE(p1_.GetAudioRtcpCount(), 1); - ASSERT_GE(p2_.GetAudioRtcpCount(), 1); + ASSERT_GE(p2_.GetAudioRtcpCount(), 1); + } p1_.Stop(); p2_.Stop(); } + void TestAudioReceiverOffersBundle(bool bundle_accepted, + nsAutoPtr localFilter, + nsAutoPtr remoteFilter = + nsAutoPtr(nullptr)) { + TestAudioSend(true, bundle_accepted, localFilter, remoteFilter); + } protected: PRFileDesc *rtp_fds_[2]; PRFileDesc *rtcp_fds_[2]; + PRFileDesc *bundle_fds_[2]; TestAgentSend p1_; TestAgentReceive p2_; }; @@ -713,7 +825,7 @@ TEST_F(MediaPipelineFilterTest, TestSSRCMovedWithCorrelator) { TEST_F(MediaPipelineFilterTest, TestRemoteSDPNoSSRCs) { // If the remote SDP doesn't have SSRCs, right now this is a no-op and - // there is no point of even incorporating a filter, but we make the + // there is no point of even incorporating a filter, but we make the // behavior consistent to avoid confusion. MediaPipelineFilter filter; filter.SetCorrelator(7777); @@ -736,6 +848,16 @@ TEST_F(MediaPipelineTest, TestAudioSendMux) { TestAudioSend(true); } +TEST_F(MediaPipelineTest, TestAudioSendBundleOfferedAndDeclined) { + nsAutoPtr filter(new MediaPipelineFilter); + TestAudioReceiverOffersBundle(false, filter); +} + +TEST_F(MediaPipelineTest, TestAudioSendBundleOfferedAndAccepted) { + nsAutoPtr filter(new MediaPipelineFilter); + TestAudioReceiverOffersBundle(true, filter); +} + } // end namespace From 90a124346afab08506384510616940036c08b7b3 Mon Sep 17 00:00:00 2001 From: "Byron Campen [:bwc]" Date: Fri, 17 Jan 2014 17:10:17 -0800 Subject: [PATCH 19/48] Bug 786234 - Part 4: Fix a bug in mediapipeline_unittest where RTP packets were mashed together into a single buffer five at a time, preventing the receive pipeline from successfully decrypting them and causing the packet counts to be wrong. r=ethanhugg --- .../signaling/test/mediapipeline_unittest.cpp | 128 +++++++----------- 1 file changed, 51 insertions(+), 77 deletions(-) diff --git a/media/webrtc/signaling/test/mediapipeline_unittest.cpp b/media/webrtc/signaling/test/mediapipeline_unittest.cpp index 5904843e0530..566693038f04 100644 --- a/media/webrtc/signaling/test/mediapipeline_unittest.cpp +++ b/media/webrtc/signaling/test/mediapipeline_unittest.cpp @@ -25,7 +25,7 @@ #include "MediaPipelineFilter.h" #include "runnable_utils.h" #include "transportflow.h" -#include "transportlayerprsock.h" +#include "transportlayerloopback.h" #include "transportlayerdtls.h" #include "mozilla/SyncRunnable.h" @@ -50,17 +50,26 @@ class TransportInfo { public: TransportInfo() : flow_(nullptr), - prsock_(nullptr), + loopback_(nullptr), dtls_(nullptr) {} + static void InitAndConnect(TransportInfo &client, TransportInfo &server) { + client.Init(true); + server.Init(false); + client.PushLayers(); + server.PushLayers(); + client.Connect(&server); + server.Connect(&client); + } + void Init(bool client) { nsresult res; flow_ = new TransportFlow(); - prsock_ = new TransportLayerPrsock(); + loopback_ = new TransportLayerLoopback(); dtls_ = new TransportLayerDtls(); - res = prsock_->Init(); + res = loopback_->Init(); if (res != NS_OK) { FreeLayers(); } @@ -80,7 +89,7 @@ class TransportInfo { nsAutoPtr > layers( new std::queue); - layers->push(prsock_); + layers->push(loopback_); layers->push(dtls_); res = flow_->PushLayers(layers); if (res != NS_OK) { @@ -89,19 +98,33 @@ class TransportInfo { ASSERT_EQ((nsresult)NS_OK, res); } + void Connect(TransportInfo* peer) { + MOZ_ASSERT(loopback_); + MOZ_ASSERT(peer->loopback_); + + loopback_->Connect(peer->loopback_); + } + // Free the memory allocated at the beginning of Init // if failure occurs before layers setup. void FreeLayers() { - delete prsock_; + delete loopback_; + loopback_ = nullptr; delete dtls_; + dtls_ = nullptr; } void Stop() { + if (loopback_) { + loopback_->Disconnect(); + } + loopback_ = nullptr; + dtls_ = nullptr; flow_ = nullptr; } mozilla::RefPtr flow_; - TransportLayerPrsock *prsock_; + TransportLayerLoopback *loopback_; TransportLayerDtls *dtls_; }; @@ -114,32 +137,19 @@ class TestAgent { audio_pipeline_() { } - void ConnectRtpSocket(PRFileDesc *fd, bool client) { - ConnectSocket(&audio_rtp_transport_, fd, client); + static void ConnectRtp(TestAgent *client, TestAgent *server) { + TransportInfo::InitAndConnect(client->audio_rtp_transport_, + server->audio_rtp_transport_); } - void ConnectRtcpSocket(PRFileDesc *fd, bool client) { - ConnectSocket(&audio_rtcp_transport_, fd, client); + static void ConnectRtcp(TestAgent *client, TestAgent *server) { + TransportInfo::InitAndConnect(client->audio_rtcp_transport_, + server->audio_rtcp_transport_); } - void ConnectBundleSocket(PRFileDesc *fd, bool client) { - ConnectSocket(&bundle_transport_, fd, client); - } - - void ConnectSocket(TransportInfo *transport, PRFileDesc *fd, bool client) { - nsresult res; - - transport->Init(client); - - mozilla::SyncRunnable::DispatchToThread( - test_utils->sts_target(), - WrapRunnable(transport->prsock_, &TransportLayerPrsock::Import, fd, &res)); - if (!NS_SUCCEEDED(res)) { - transport->FreeLayers(); - } - ASSERT_TRUE(NS_SUCCEEDED(res)); - - transport->PushLayers(); + static void ConnectBundle(TestAgent *client, TestAgent *server) { + TransportInfo::InitAndConnect(client->bundle_transport_, + server->bundle_transport_); } virtual void CreatePipelines_s(bool aIsRtcpMux) = 0; @@ -176,8 +186,6 @@ class TestAgent { WrapRunnable(this, &TestAgent::StopInt)); audio_pipeline_ = nullptr; - - PR_Sleep(1000); // Deal with race condition } protected: @@ -322,61 +330,30 @@ class TestAgentReceive : public TestAgent { class MediaPipelineTest : public ::testing::Test { public: - MediaPipelineTest() : p1_() { - rtp_fds_[0] = rtp_fds_[1] = nullptr; - rtcp_fds_[0] = rtcp_fds_[1] = nullptr; - bundle_fds_[0] = bundle_fds_[1] = nullptr; + ~MediaPipelineTest() { + p1_.Stop(); + p2_.Stop(); } // Setup transport. void InitTransports(bool aIsRtcpMux) { - // Create RTP related transport. - PRStatus status = PR_NewTCPSocketPair(rtp_fds_); - ASSERT_EQ(status, PR_SUCCESS); - - // RTP, DTLS server + // RTP, p1_ is server, p2_ is client mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), - WrapRunnable(&p1_, &TestAgent::ConnectRtpSocket, rtp_fds_[0], false)); - - // RTP, DTLS client - mozilla::SyncRunnable::DispatchToThread( - test_utils->sts_target(), - WrapRunnable(&p2_, &TestAgent::ConnectRtpSocket, rtp_fds_[1], true)); + WrapRunnableNM(&TestAgent::ConnectRtp, &p2_, &p1_)); // Create RTCP flows separately if we are not muxing them. if(!aIsRtcpMux) { - status = PR_NewTCPSocketPair(rtcp_fds_); - ASSERT_EQ(status, PR_SUCCESS); - - // RTCP, DTLS server + // RTCP, p1_ is server, p2_ is client mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), - WrapRunnable(&p1_, &TestAgent::ConnectRtcpSocket, rtcp_fds_[0], false)); - - // RTCP, DTLS client - mozilla::SyncRunnable::DispatchToThread( - test_utils->sts_target(), - WrapRunnable(&p2_, &TestAgent::ConnectRtcpSocket, rtcp_fds_[1], true)); + WrapRunnableNM(&TestAgent::ConnectRtcp, &p2_, &p1_)); } - status = PR_NewTCPSocketPair(bundle_fds_); - // BUNDLE, DTLS server + // BUNDLE, p1_ is server, p2_ is client mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), - WrapRunnable(&p1_, - &TestAgent::ConnectBundleSocket, - bundle_fds_[0], - false)); - - // BUNDLE, DTLS client - mozilla::SyncRunnable::DispatchToThread( - test_utils->sts_target(), - WrapRunnable(&p2_, - &TestAgent::ConnectBundleSocket, - bundle_fds_[1], - true)); - + WrapRunnableNM(&TestAgent::ConnectBundle, &p2_, &p1_)); } // Verify RTP and RTCP @@ -431,11 +408,11 @@ class MediaPipelineTest : public ::testing::Test { PR_Sleep(10000); if (bundle) { - // Filter should have eaten everything, so no RTCP + // Filter should have eaten everything + ASSERT_EQ(0, p2_.GetAudioRtpCount()); } else { ASSERT_GE(p1_.GetAudioRtpCount(), 40); -// TODO: Fix to not fail or crash (Bug 947663) -// ASSERT_GE(p2_.GetAudioRtpCount(), 40); + ASSERT_GE(p2_.GetAudioRtpCount(), 40); ASSERT_GE(p2_.GetAudioRtcpCount(), 1); } @@ -450,9 +427,6 @@ class MediaPipelineTest : public ::testing::Test { TestAudioSend(true, bundle_accepted, localFilter, remoteFilter); } protected: - PRFileDesc *rtp_fds_[2]; - PRFileDesc *rtcp_fds_[2]; - PRFileDesc *bundle_fds_[2]; TestAgentSend p1_; TestAgentReceive p2_; }; From 3d95737fdfb1798adb40558fec2fe3cbb0a06943 Mon Sep 17 00:00:00 2001 From: "Byron Campen [:bwc]" Date: Fri, 17 Jan 2014 17:11:00 -0800 Subject: [PATCH 20/48] Bug 786234 - Part 5: More detailed test-cases. r=ethanhugg --- .../signaling/test/mediapipeline_unittest.cpp | 154 +++++++++++++----- 1 file changed, 116 insertions(+), 38 deletions(-) diff --git a/media/webrtc/signaling/test/mediapipeline_unittest.cpp b/media/webrtc/signaling/test/mediapipeline_unittest.cpp index 566693038f04..a1f92ca7588d 100644 --- a/media/webrtc/signaling/test/mediapipeline_unittest.cpp +++ b/media/webrtc/signaling/test/mediapipeline_unittest.cpp @@ -114,7 +114,7 @@ class TransportInfo { dtls_ = nullptr; } - void Stop() { + void Shutdown() { if (loopback_) { loopback_->Disconnect(); } @@ -168,11 +168,6 @@ class TestAgent { void StopInt() { audio_->GetStream()->Stop(); - audio_rtp_transport_.Stop(); - audio_rtcp_transport_.Stop(); - bundle_transport_.Stop(); - if (audio_pipeline_) - audio_pipeline_->ShutdownTransport_s(); } void Stop() { @@ -184,14 +179,60 @@ class TestAgent { mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), WrapRunnable(this, &TestAgent::StopInt)); + } - audio_pipeline_ = nullptr; + void Shutdown_s() { + audio_rtp_transport_.Shutdown(); + audio_rtcp_transport_.Shutdown(); + bundle_transport_.Shutdown(); + if (audio_pipeline_) + audio_pipeline_->ShutdownTransport_s(); + } + + void Shutdown() { + if (audio_pipeline_) + audio_pipeline_->ShutdownMedia_m(); + + mozilla::SyncRunnable::DispatchToThread( + test_utils->sts_target(), + WrapRunnable(this, &TestAgent::Shutdown_s)); + } + + uint32_t GetRemoteSSRC() { + uint32_t res = 0; + audio_conduit_->GetRemoteSSRC(&res); + return res; + } + + uint32_t GetLocalSSRC() { + uint32_t res = 0; + audio_conduit_->GetLocalSSRC(&res); + return res; + } + + int GetAudioRtpCountSent() { + return audio_pipeline_->rtp_packets_sent(); + } + + int GetAudioRtpCountReceived() { + return audio_pipeline_->rtp_packets_received(); + } + + int GetAudioRtcpCountSent() { + return audio_pipeline_->rtcp_packets_sent(); + } + + int GetAudioRtcpCountReceived() { + return audio_pipeline_->rtcp_packets_received(); } protected: mozilla::AudioCodecConfig audio_config_; mozilla::RefPtr audio_conduit_; nsRefPtr audio_; + // TODO(bcampen@mozilla.com): Right now this does not let us test RTCP in + // both directions; only the sender's RTCP is sent, but the receiver should + // be sending it too. mozilla::RefPtr audio_pipeline_; TransportInfo audio_rtp_transport_; TransportInfo audio_rtcp_transport_; @@ -238,14 +279,6 @@ class TestAgentSend : public TestAgent { audio_pipeline_->Init(); } - int GetAudioRtpCount() { - return audio_pipeline_->rtp_packets_sent(); - } - - int GetAudioRtcpCount() { - return audio_pipeline_->rtcp_packets_received(); - } - void SetUsingBundle(bool use_bundle) { use_bundle_ = use_bundle; } @@ -286,6 +319,7 @@ class TestAgentReceive : public TestAgent { RefPtr bundle_transport; if (bundle_filter_) { bundle_transport = bundle_transport_.flow_; + bundle_filter_->AddLocalSSRC(GetLocalSSRC()); } audio_pipeline_ = new mozilla::MediaPipelineReceiveAudio( @@ -303,14 +337,6 @@ class TestAgentReceive : public TestAgent { audio_pipeline_->Init(); } - int GetAudioRtpCount() { - return audio_pipeline_->rtp_packets_received(); - } - - int GetAudioRtcpCount() { - return audio_pipeline_->rtcp_packets_sent(); - } - void SetBundleFilter(nsAutoPtr filter) { bundle_filter_ = filter; } @@ -323,6 +349,7 @@ class TestAgentReceive : public TestAgent { nsAutoPtr filter) { audio_pipeline_->UpdateFilterFromRemoteDescription_s(filter); } + private: nsAutoPtr bundle_filter_; }; @@ -333,6 +360,8 @@ class MediaPipelineTest : public ::testing::Test { ~MediaPipelineTest() { p1_.Stop(); p2_.Stop(); + p1_.Shutdown(); + p2_.Shutdown(); } // Setup transport. @@ -362,7 +391,9 @@ class MediaPipelineTest : public ::testing::Test { nsAutoPtr localFilter = nsAutoPtr(nullptr), nsAutoPtr remoteFilter = - nsAutoPtr(nullptr)) { + nsAutoPtr(nullptr), + unsigned int ms_until_answer = 500, + unsigned int ms_of_traffic_after_answer = 10000) { // We do not support testing bundle without rtcp mux, since that doesn't // make any sense. @@ -386,16 +417,20 @@ class MediaPipelineTest : public ::testing::Test { p1_.Start(); // Simulate pre-answer traffic - PR_Sleep(500); + PR_Sleep(ms_until_answer); mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), WrapRunnable(&p2_, &TestAgentReceive::SetUsingBundle_s, bundle)); if (bundle) { + // Leaving remoteFilter not set implies we want to test sunny-day if (!remoteFilter) { remoteFilter = new MediaPipelineFilter; + // Might not be safe, strictly speaking. + remoteFilter->AddRemoteSSRC(p1_.GetLocalSSRC()); } + mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), WrapRunnable(&p2_, @@ -405,26 +440,43 @@ class MediaPipelineTest : public ::testing::Test { // wait for some RTP/RTCP tx and rx to happen - PR_Sleep(10000); - - if (bundle) { - // Filter should have eaten everything - ASSERT_EQ(0, p2_.GetAudioRtpCount()); - } else { - ASSERT_GE(p1_.GetAudioRtpCount(), 40); - ASSERT_GE(p2_.GetAudioRtpCount(), 40); - ASSERT_GE(p2_.GetAudioRtcpCount(), 1); - } + PR_Sleep(ms_of_traffic_after_answer); p1_.Stop(); p2_.Stop(); + + // wait for any packets in flight to arrive + PR_Sleep(100); + + p1_.Shutdown(); + p2_.Shutdown(); + + if (!bundle) { + // If we are doing bundle, allow the test-case to do this checking. + ASSERT_GE(p1_.GetAudioRtpCountSent(), 40); + ASSERT_EQ(p1_.GetAudioRtpCountReceived(), p2_.GetAudioRtpCountSent()); + ASSERT_EQ(p1_.GetAudioRtpCountSent(), p2_.GetAudioRtpCountReceived()); + + // Calling ShutdownMedia_m on both pipelines does not stop the flow of + // RTCP. So, we might be off by one here. + ASSERT_LE(p2_.GetAudioRtcpCountReceived(), p1_.GetAudioRtcpCountSent()); + ASSERT_GE(p2_.GetAudioRtcpCountReceived() + 1, p1_.GetAudioRtcpCountSent()); + } + } void TestAudioReceiverOffersBundle(bool bundle_accepted, nsAutoPtr localFilter, nsAutoPtr remoteFilter = - nsAutoPtr(nullptr)) { - TestAudioSend(true, bundle_accepted, localFilter, remoteFilter); + nsAutoPtr(nullptr), + unsigned int ms_until_answer = 500, + unsigned int ms_of_traffic_after_answer = 10000) { + TestAudioSend(true, + bundle_accepted, + localFilter, + remoteFilter, + ms_until_answer, + ms_of_traffic_after_answer); } protected: TestAgentSend p1_; @@ -829,7 +881,33 @@ TEST_F(MediaPipelineTest, TestAudioSendBundleOfferedAndDeclined) { TEST_F(MediaPipelineTest, TestAudioSendBundleOfferedAndAccepted) { nsAutoPtr filter(new MediaPipelineFilter); - TestAudioReceiverOffersBundle(true, filter); + // These durations have to be _extremely_ long to have any assurance that + // some RTCP will be sent at all. This is because the first RTCP packet + // is sometimes sent before the transports are ready, which causes it to + // be dropped. + TestAudioReceiverOffersBundle(true, + filter, + // We do not specify the filter for the remote description, so it will be + // set to something sane after a short time. + nsAutoPtr(), + 10000, + 10000); + + // Some packets should have been dropped, but not all + ASSERT_GT(p1_.GetAudioRtpCountSent(), p2_.GetAudioRtpCountReceived()); + ASSERT_GT(p2_.GetAudioRtpCountReceived(), 40); + ASSERT_GT(p1_.GetAudioRtcpCountSent(), 1); + ASSERT_GT(p1_.GetAudioRtcpCountSent(), p2_.GetAudioRtcpCountReceived()); + ASSERT_GT(p2_.GetAudioRtcpCountReceived(), 0); +} + +TEST_F(MediaPipelineTest, TestAudioSendBundleOfferedAndAcceptedEmptyFilter) { + nsAutoPtr filter(new MediaPipelineFilter); + nsAutoPtr bad_answer_filter(new MediaPipelineFilter); + TestAudioReceiverOffersBundle(true, filter, bad_answer_filter); + // Filter is empty, so should drop everything. + ASSERT_EQ(0, p2_.GetAudioRtpCountReceived()); + ASSERT_EQ(0, p2_.GetAudioRtcpCountReceived()); } } // end namespace From fc45a7641dae7b6f0d4014bcdcdb3462e2926687 Mon Sep 17 00:00:00 2001 From: Mason Chang Date: Mon, 24 Feb 2014 10:09:55 -0500 Subject: [PATCH 21/48] Bug 917416 - Make App Renderframe Opaque. r=roc --- gfx/layers/composite/ContainerLayerComposite.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/gfx/layers/composite/ContainerLayerComposite.cpp b/gfx/layers/composite/ContainerLayerComposite.cpp index 26821ae05a56..150cbdc62fa2 100644 --- a/gfx/layers/composite/ContainerLayerComposite.cpp +++ b/gfx/layers/composite/ContainerLayerComposite.cpp @@ -55,12 +55,16 @@ static nsIntRect GetOpaqueRect(Layer* aLayer) { nsIntRect result; + gfx::Matrix matrix; + bool is2D = aLayer->GetBaseTransform().Is2D(&matrix); + // Just bail if there's anything difficult to handle. - if (!aLayer->GetEffectiveTransform().IsIdentity() || - aLayer->GetEffectiveOpacity() != 1.0f || - aLayer->GetMaskLayer()) { + if (!is2D || aLayer->GetMaskLayer() || + aLayer->GetEffectiveOpacity() != 1.0f || + matrix.HasNonIntegerTranslation()) { return result; } + if (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE) { result = aLayer->GetEffectiveVisibleRegion().GetLargestRectangle(); } else { @@ -72,10 +76,16 @@ GetOpaqueRect(Layer* aLayer) result = GetOpaqueRect(refLayer->GetFirstChild()); } } + + // Translate our opaque region to cover the child + gfx::Point point = matrix.GetTranslation(); + result.MoveBy(static_cast(point.x), static_cast(point.y)); + const nsIntRect* clipRect = aLayer->GetEffectiveClipRect(); if (clipRect) { result.IntersectRect(result, *clipRect); } + return result; } From 3187c543eb3ce63dff047d8719b99c9568d35440 Mon Sep 17 00:00:00 2001 From: Alex Xu Date: Mon, 24 Feb 2014 10:09:55 -0500 Subject: [PATCH 22/48] Bug 967006 - Fix Clang build failure in nICEr. r=abr --- media/mtransport/third_party/nICEr/src/stun/stun_build.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/media/mtransport/third_party/nICEr/src/stun/stun_build.h b/media/mtransport/third_party/nICEr/src/stun/stun_build.h index d84af002477b..4793e2f4b4d5 100644 --- a/media/mtransport/third_party/nICEr/src/stun/stun_build.h +++ b/media/mtransport/third_party/nICEr/src/stun/stun_build.h @@ -55,7 +55,8 @@ int nr_stun_build_req_no_auth(nr_stun_client_stun_binding_request_params *params typedef struct nr_stun_client_stun_keepalive_params_ { -#ifdef WIN32 // silly VC++ gives error if no members +#if defined(WIN32) || defined(__clang__) + // VC++ and clang give error and warning respectively if no members int dummy; #endif } nr_stun_client_stun_keepalive_params; From f7ba2109198cdb320c5310cec70daa157b6d0ff6 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Mon, 24 Feb 2014 10:09:55 -0500 Subject: [PATCH 23/48] Bug 972382 - [GTK3] Theme is not loaded in other WM's (MATE, XFCE and so). r=karlt --- widget/gtk/nsLookAndFeel.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/widget/gtk/nsLookAndFeel.cpp b/widget/gtk/nsLookAndFeel.cpp index a3a10d844b02..20586fb00668 100644 --- a/widget/gtk/nsLookAndFeel.cpp +++ b/widget/gtk/nsLookAndFeel.cpp @@ -946,6 +946,11 @@ nsLookAndFeel::Init() GdkRGBA color; GtkStyleContext *style; + // Gtk manages a screen's CSS in the settings object so we + // ask Gtk to create it explicitly. Otherwise we may end up + // with wrong color theme, see Bug 972382 + (void)gtk_settings_get_for_screen(gdk_screen_get_default()); + GtkWidgetPath *path = gtk_widget_path_new(); gtk_widget_path_append_type(path, GTK_TYPE_WINDOW); From 644084917e278a91c4d205871abc67c7a748c422 Mon Sep 17 00:00:00 2001 From: Morris Tseng Date: Mon, 24 Feb 2014 10:09:55 -0500 Subject: [PATCH 24/48] Bug 975121 - Fix reversed colors with gfx.xrender.enabled = false. r=gal --- gfx/layers/opengl/CompositorOGL.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gfx/layers/opengl/CompositorOGL.cpp b/gfx/layers/opengl/CompositorOGL.cpp index 7e2addb49e44..e425f01e61f0 100644 --- a/gfx/layers/opengl/CompositorOGL.cpp +++ b/gfx/layers/opengl/CompositorOGL.cpp @@ -824,8 +824,15 @@ CompositorOGL::GetShaderConfigFor(Effect *aEffect, MaskType aMask) const config.SetYCbCr(true); break; case EFFECT_COMPONENT_ALPHA: + { config.SetComponentAlpha(true); + EffectComponentAlpha* effectComponentAlpha = + static_cast(aEffect); + gfx::SurfaceFormat format = effectComponentAlpha->mOnWhite->GetFormat(); + config.SetRBSwap(format == gfx::SurfaceFormat::B8G8R8A8 || + format == gfx::SurfaceFormat::B8G8R8X8); break; + } case EFFECT_RENDER_TARGET: config.SetTextureTarget(mFBOTextureTarget); break; From b3d8b351973c2c13c20d38a704fc2c6b9543d8b0 Mon Sep 17 00:00:00 2001 From: Gijs Kruitbosch Date: Tue, 18 Feb 2014 17:07:27 +0000 Subject: [PATCH 25/48] Bug 966683 - Australis - automatically toggle accesskey-focuses on Linux to prevent menubar focus stealing, r=Neil,dao --HG-- extra : rebase_source : a12eba0c04d57df9a47185a6be250e04000f862e --- browser/app/profile/firefox.js | 5 +++++ browser/base/content/browser.js | 11 +++++++++-- layout/build/nsLayoutStatics.cpp | 6 ++++++ layout/xul/nsMenuBarListener.cpp | 9 +++++++-- layout/xul/nsMenuBarListener.h | 2 ++ modules/libpref/src/init/all.js | 2 -- 6 files changed, 29 insertions(+), 6 deletions(-) diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index e59a164c23d6..6f19f457684e 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -1381,6 +1381,11 @@ pref("identity.fxaccounts.settings.uri", "https://accounts.firefox.com/settings" // The URL of the Firefox Accounts auth server backend pref("identity.fxaccounts.auth.uri", "https://api.accounts.firefox.com/v1"); +// On GTK, we now default to showing the menubar only when alt is pressed: +#ifdef MOZ_WIDGET_GTK +pref("ui.key.menuAccessKeyFocuses", true); +#endif + // Temporarily turn the new http cache v2 on for Desktop Firefox only pref("browser.cache.use_new_backend_temp", true); diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 86a87cc82393..47f984cfa8f1 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -4278,8 +4278,15 @@ function onViewToolbarCommand(aEvent) { } function setToolbarVisibility(toolbar, isVisible) { - var hidingAttribute = toolbar.getAttribute("type") == "menubar" ? - "autohide" : "collapsed"; + let hidingAttribute; + if (toolbar.getAttribute("type") == "menubar") { + hidingAttribute = "autohide"; +#ifdef MOZ_WIDGET_GTK + Services.prefs.setBoolPref("ui.key.menuAccessKeyFocuses", !isVisible); +#endif + } else { + hidingAttribute = "collapsed"; + } toolbar.setAttribute(hidingAttribute, !isVisible); document.persist(toolbar.id, hidingAttribute); diff --git a/layout/build/nsLayoutStatics.cpp b/layout/build/nsLayoutStatics.cpp index 4e86bc48f8a2..2d1d6752e489 100644 --- a/layout/build/nsLayoutStatics.cpp +++ b/layout/build/nsLayoutStatics.cpp @@ -73,6 +73,8 @@ #include "nsXULTooltipListener.h" #include "inDOMView.h" + +#include "nsMenuBarListener.h" #endif #include "nsHTMLEditor.h" @@ -281,6 +283,10 @@ nsLayoutStatics::Initialize() HTMLVideoElement::Init(); +#ifdef MOZ_XUL + nsMenuBarListener::InitializeStatics(); +#endif + CacheObserver::Init(); return NS_OK; diff --git a/layout/xul/nsMenuBarListener.cpp b/layout/xul/nsMenuBarListener.cpp index 3e74903f399f..9b941ca22b0f 100644 --- a/layout/xul/nsMenuBarListener.cpp +++ b/layout/xul/nsMenuBarListener.cpp @@ -52,6 +52,13 @@ nsMenuBarListener::~nsMenuBarListener() { } +void +nsMenuBarListener::InitializeStatics() +{ + Preferences::AddBoolVarCache(&mAccessKeyFocuses, + "ui.key.menuAccessKeyFocuses"); +} + nsresult nsMenuBarListener::GetMenuAccessKey(int32_t* aAccessKey) { @@ -89,8 +96,6 @@ void nsMenuBarListener::InitAccessKey() mAccessKeyMask = MODIFIER_META; else if (mAccessKey == nsIDOMKeyEvent::DOM_VK_WIN) mAccessKeyMask = MODIFIER_OS; - - mAccessKeyFocuses = Preferences::GetBool("ui.key.menuAccessKeyFocuses"); } void diff --git a/layout/xul/nsMenuBarListener.h b/layout/xul/nsMenuBarListener.h index 7cda4b65e77b..6e47dbceedc8 100644 --- a/layout/xul/nsMenuBarListener.h +++ b/layout/xul/nsMenuBarListener.h @@ -27,6 +27,8 @@ public: /** default destructor */ virtual ~nsMenuBarListener(); + + static void InitializeStatics(); NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) MOZ_OVERRIDE; diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index b66875b13575..bac3858855eb 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -3654,8 +3654,6 @@ pref("ui.panel.default_level_parent", true); pref("mousewheel.system_scroll_override_on_root_content.enabled", false); -pref("ui.key.menuAccessKeyFocuses", true); - #if MOZ_WIDGET_GTK == 2 pref("intl.ime.use_simple_context_on_password_field", true); #else From 4cee698abce46eb8dca6aa301747abeefa0acfaf Mon Sep 17 00:00:00 2001 From: Max Vujovic Date: Mon, 24 Feb 2014 10:22:58 -0500 Subject: [PATCH 26/48] Bug 948265 - Pass an nsStyleFilter chain instead of an nsSVGFilterFrame into nsSVGFilterInstance. r=roc --- layout/base/nsDisplayList.cpp | 7 +- layout/svg/nsSVGEffects.cpp | 8 --- layout/svg/nsSVGEffects.h | 30 ++------ layout/svg/nsSVGFilterInstance.cpp | 104 +++++++++++++++++++++------ layout/svg/nsSVGFilterInstance.h | 30 +++++--- layout/svg/nsSVGIntegrationUtils.cpp | 36 ++++------ layout/svg/nsSVGUtils.cpp | 18 ++--- 7 files changed, 131 insertions(+), 102 deletions(-) diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index df267a871855..89a27a58ef02 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -4893,17 +4893,16 @@ nsDisplaySVGEffects::BuildLayer(nsDisplayListBuilder* aBuilder, nsSVGEffects::EffectProperties effectProperties = nsSVGEffects::GetEffectProperties(firstFrame); - bool isOK = true; + bool isOK = effectProperties.HasNoFilterOrHasValidFilter(); effectProperties.GetClipPathFrame(&isOK); effectProperties.GetMaskFrame(&isOK); - bool hasFilter = effectProperties.GetFilterFrame(&isOK) != nullptr; if (!isOK) { return nullptr; } ContainerLayerParameters newContainerParameters = aContainerParameters; - if (hasFilter) { + if (effectProperties.HasValidFilter()) { newContainerParameters.mDisableSubpixelAntialiasingInDescendants = true; } @@ -4972,7 +4971,7 @@ nsDisplaySVGEffects::PrintEffects(nsACString& aTo) aTo += nsPrintfCString("clip(%s)", clipPathFrame->IsTrivial() ? "trivial" : "non-trivial"); first = false; } - if (effectProperties.GetFilterFrame(&isOK)) { + if (effectProperties.HasValidFilter()) { if (!first) { aTo += ", "; } diff --git a/layout/svg/nsSVGEffects.cpp b/layout/svg/nsSVGEffects.cpp index 761532c98d98..9bc98cbee2b4 100644 --- a/layout/svg/nsSVGEffects.cpp +++ b/layout/svg/nsSVGEffects.cpp @@ -266,14 +266,6 @@ nsSVGFilterProperty::Invalidate() } } -nsSVGFilterFrame * -nsSVGFilterProperty::GetFilterFrame() -{ - // Eventually, callers will ask nsSVGFilterProperty for an nsStyleFilter - // chain, not a single nsSVGFilterFrame, and this function will go away. - return mReferences.Length() > 0 ? mReferences[0]->GetFilterFrame() : nullptr; -} - NS_IMPL_ISUPPORTS_INHERITED1(nsSVGFilterReference, nsSVGIDRenderingObserver, nsISVGFilterReference); diff --git a/layout/svg/nsSVGEffects.h b/layout/svg/nsSVGEffects.h index 6d077c272987..66033eb91380 100644 --- a/layout/svg/nsSVGEffects.h +++ b/layout/svg/nsSVGEffects.h @@ -207,11 +207,6 @@ public: bool IsInObserverLists() const; void Invalidate(); - /** - * @return the filter frame, or null if there is no filter frame - */ - nsSVGFilterFrame *GetFilterFrame(); - // nsISupports NS_DECL_ISUPPORTS @@ -374,20 +369,13 @@ public: * Otherwise *aOK is untouched. */ nsSVGMaskFrame *GetMaskFrame(bool *aOK); - /** - * @return the filter frame, or null if there is no filter frame - * @param aOK if a filter was specified but the designated element - * does not exist or is an element of the wrong type, *aOK is set - * to false. Otherwise *aOK is untouched. - */ - nsSVGFilterFrame *GetFilterFrame(bool *aOK) { - if (!mFilter) - return nullptr; - nsSVGFilterFrame *filter = mFilter->GetFilterFrame(); - if (!filter) { - *aOK = false; - } - return filter; + + bool HasValidFilter() { + return mFilter && mFilter->ReferencesValidResources(); + } + + bool HasNoFilterOrHasValidFilter() { + return !mFilter || mFilter->ReferencesValidResources(); } }; @@ -415,10 +403,6 @@ public: * @param aFrame should be the first continuation */ static nsSVGFilterProperty *GetFilterProperty(nsIFrame *aFrame); - static nsSVGFilterFrame *GetFilterFrame(nsIFrame *aFrame) { - nsSVGFilterProperty *prop = GetFilterProperty(aFrame); - return prop ? prop->GetFilterFrame() : nullptr; - } /** * @param aFrame must be a first-continuation. diff --git a/layout/svg/nsSVGFilterInstance.cpp b/layout/svg/nsSVGFilterInstance.cpp index 5a27bad455ae..f06cd477bf69 100644 --- a/layout/svg/nsSVGFilterInstance.cpp +++ b/layout/svg/nsSVGFilterInstance.cpp @@ -12,6 +12,7 @@ #include "nsISVGChildFrame.h" #include "nsRenderingContext.h" #include "mozilla/dom/SVGFilterElement.h" +#include "nsReferencedElement.h" #include "nsSVGFilterFrame.h" #include "nsSVGFilterPaintCallback.h" #include "nsSVGUtils.h" @@ -24,15 +25,14 @@ using namespace mozilla::dom; using namespace mozilla::gfx; nsresult -nsSVGFilterInstance::PaintFilteredFrame(nsSVGFilterFrame* aFilterFrame, - nsRenderingContext *aContext, +nsSVGFilterInstance::PaintFilteredFrame(nsRenderingContext *aContext, nsIFrame *aFilteredFrame, nsSVGFilterPaintCallback *aPaintCallback, const nsRect *aDirtyArea, nsIFrame* aTransformRoot) { - nsSVGFilterInstance instance(aFilteredFrame, aFilterFrame, aPaintCallback, - aDirtyArea, nullptr, nullptr, nullptr, + nsSVGFilterInstance instance(aFilteredFrame, aPaintCallback, aDirtyArea, + nullptr, nullptr, nullptr, aTransformRoot); if (!instance.IsInitialized()) { return NS_OK; @@ -41,15 +41,14 @@ nsSVGFilterInstance::PaintFilteredFrame(nsSVGFilterFrame* aFilterFrame, } nsRect -nsSVGFilterInstance::GetPostFilterDirtyArea(nsSVGFilterFrame* aFilterFrame, - nsIFrame *aFilteredFrame, +nsSVGFilterInstance::GetPostFilterDirtyArea(nsIFrame *aFilteredFrame, const nsRect& aPreFilterDirtyRect) { if (aPreFilterDirtyRect.IsEmpty()) { return nsRect(); } - nsSVGFilterInstance instance(aFilteredFrame, aFilterFrame, nullptr, nullptr, + nsSVGFilterInstance instance(aFilteredFrame, nullptr, nullptr, &aPreFilterDirtyRect); if (!instance.IsInitialized()) { return nsRect(); @@ -66,12 +65,10 @@ nsSVGFilterInstance::GetPostFilterDirtyArea(nsSVGFilterFrame* aFilterFrame, } nsRect -nsSVGFilterInstance::GetPreFilterNeededArea(nsSVGFilterFrame* aFilterFrame, - nsIFrame *aFilteredFrame, +nsSVGFilterInstance::GetPreFilterNeededArea(nsIFrame *aFilteredFrame, const nsRect& aPostFilterDirtyRect) { - nsSVGFilterInstance instance(aFilteredFrame, aFilterFrame, nullptr, - &aPostFilterDirtyRect); + nsSVGFilterInstance instance(aFilteredFrame, nullptr, &aPostFilterDirtyRect); if (!instance.IsInitialized()) { return nsRect(); } @@ -86,8 +83,7 @@ nsSVGFilterInstance::GetPreFilterNeededArea(nsSVGFilterFrame* aFilterFrame, } nsRect -nsSVGFilterInstance::GetPostFilterBounds(nsSVGFilterFrame* aFilterFrame, - nsIFrame *aFilteredFrame, +nsSVGFilterInstance::GetPostFilterBounds(nsIFrame *aFilteredFrame, const gfxRect *aOverrideBBox, const nsRect *aPreFilterBounds) { @@ -95,7 +91,7 @@ nsSVGFilterInstance::GetPostFilterBounds(nsSVGFilterFrame* aFilterFrame, !(aFilteredFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY), "Non-display SVG do not maintain visual overflow rects"); - nsSVGFilterInstance instance(aFilteredFrame, aFilterFrame, nullptr, nullptr, + nsSVGFilterInstance instance(aFilteredFrame, nullptr, nullptr, aPreFilterBounds, aPreFilterBounds, aOverrideBBox); if (!instance.IsInitialized()) { @@ -110,7 +106,6 @@ nsSVGFilterInstance::GetPostFilterBounds(nsSVGFilterFrame* aFilterFrame, } nsSVGFilterInstance::nsSVGFilterInstance(nsIFrame *aTargetFrame, - nsSVGFilterFrame *aFilterFrame, nsSVGFilterPaintCallback *aPaintCallback, const nsRect *aPostFilterDirtyRect, const nsRect *aPreFilterDirtyRect, @@ -118,14 +113,26 @@ nsSVGFilterInstance::nsSVGFilterInstance(nsIFrame *aTargetFrame, const gfxRect *aOverrideBBox, nsIFrame* aTransformRoot) : mTargetFrame(aTargetFrame), + mFilters(aTargetFrame->StyleSVGReset()->mFilters), mPaintCallback(aPaintCallback), mTransformRoot(aTransformRoot), mInitialized(false) { - mFilterElement = aFilterFrame->GetFilterContent(); + // Get the filter frame. + mFilterFrame = GetFilterFrame(); + if (!mFilterFrame) { + return; + } + + // Get the filter element. + mFilterElement = mFilterFrame->GetFilterContent(); + if (!mFilterElement) { + NS_NOTREACHED("filter frame should have a related element"); + return; + } mPrimitiveUnits = - aFilterFrame->GetEnumValue(SVGFilterElement::PRIMITIVEUNITS); + mFilterFrame->GetEnumValue(SVGFilterElement::PRIMITIVEUNITS); mTargetBBox = aOverrideBBox ? *aOverrideBBox : nsSVGUtils::GetBBox(mTargetFrame); @@ -147,12 +154,12 @@ nsSVGFilterInstance::nsSVGFilterInstance(nsIFrame *aTargetFrame, "XYWH size incorrect"); memcpy(XYWH, mFilterElement->mLengthAttributes, sizeof(mFilterElement->mLengthAttributes)); - XYWH[0] = *aFilterFrame->GetLengthValue(SVGFilterElement::ATTR_X); - XYWH[1] = *aFilterFrame->GetLengthValue(SVGFilterElement::ATTR_Y); - XYWH[2] = *aFilterFrame->GetLengthValue(SVGFilterElement::ATTR_WIDTH); - XYWH[3] = *aFilterFrame->GetLengthValue(SVGFilterElement::ATTR_HEIGHT); + XYWH[0] = *mFilterFrame->GetLengthValue(SVGFilterElement::ATTR_X); + XYWH[1] = *mFilterFrame->GetLengthValue(SVGFilterElement::ATTR_Y); + XYWH[2] = *mFilterFrame->GetLengthValue(SVGFilterElement::ATTR_WIDTH); + XYWH[3] = *mFilterFrame->GetLengthValue(SVGFilterElement::ATTR_HEIGHT); uint16_t filterUnits = - aFilterFrame->GetEnumValue(SVGFilterElement::FILTERUNITS); + mFilterFrame->GetEnumValue(SVGFilterElement::FILTERUNITS); // The filter region in user space, in user units: mFilterRegion = nsSVGUtils::GetRelativeRect(filterUnits, XYWH, mTargetBBox, mTargetFrame); @@ -171,7 +178,7 @@ nsSVGFilterInstance::nsSVGFilterInstance(nsIFrame *aTargetFrame, gfxIntSize filterRes; const nsSVGIntegerPair* filterResAttrs = - aFilterFrame->GetIntegerPairValue(SVGFilterElement::FILTERRES); + mFilterFrame->GetIntegerPairValue(SVGFilterElement::FILTERRES); if (filterResAttrs->IsExplicitlySet()) { int32_t filterResX = filterResAttrs->GetAnimValue(nsSVGIntegerPair::eFirst); int32_t filterResY = filterResAttrs->GetAnimValue(nsSVGIntegerPair::eSecond); @@ -250,6 +257,57 @@ nsSVGFilterInstance::nsSVGFilterInstance(nsIFrame *aTargetFrame, mInitialized = true; } +nsSVGFilterFrame* +nsSVGFilterInstance::GetFilterFrame() +{ + if (mFilters.Length() <= 0) { + // There are no filters. + return nullptr; + } + + // For now, use the first filter in the chain. Later, nsSVGFilterInstance will + // receive the exact filter that it should use, instead of choosing one from a + // chain of filters. + const nsStyleFilter& filter = mFilters[0]; + if (filter.GetType() != NS_STYLE_FILTER_URL) { + // The filter is not an SVG reference filter. + return nullptr; + } + + nsIURI* url = filter.GetURL(); + if (!url) { + NS_NOTREACHED("an nsStyleFilter of type URL should have a non-null URL"); + return nullptr; + } + + // Get the target element to use as a point of reference for looking up the + // filter element. + nsIContent* targetElement = mTargetFrame->GetContent(); + if (!targetElement) { + // There is no element associated with the target frame. + return nullptr; + } + + // Look up the filter element by URL. + nsReferencedElement filterElement; + bool watch = false; + filterElement.Reset(targetElement, url, watch); + Element* element = filterElement.get(); + if (!element) { + // The URL points to no element. + return nullptr; + } + + // Get the frame of the filter element. + nsIFrame* frame = element->GetPrimaryFrame(); + if (frame->GetType() != nsGkAtoms::svgFilterFrame) { + // The URL points to an element that's not an SVG filter element. + return nullptr; + } + + return static_cast(frame); +} + float nsSVGFilterInstance::GetPrimitiveNumber(uint8_t aCtxType, float aValue) const { diff --git a/layout/svg/nsSVGFilterInstance.h b/layout/svg/nsSVGFilterInstance.h index 6947e630d769..8d578fc91b1e 100644 --- a/layout/svg/nsSVGFilterInstance.h +++ b/layout/svg/nsSVGFilterInstance.h @@ -65,8 +65,7 @@ public: * frame space (i.e. relative to its origin, the top-left corner of its * border box). */ - static nsresult PaintFilteredFrame(nsSVGFilterFrame* aFilterFrame, - nsRenderingContext *aContext, + static nsresult PaintFilteredFrame(nsRenderingContext *aContext, nsIFrame *aFilteredFrame, nsSVGFilterPaintCallback *aPaintCallback, const nsRect* aDirtyArea, @@ -78,8 +77,7 @@ public: * @param aPreFilterDirtyRect The pre-filter area of aFilteredFrame that has * changed, relative to aFilteredFrame, in app units. */ - static nsRect GetPostFilterDirtyArea(nsSVGFilterFrame* aFilterFrame, - nsIFrame *aFilteredFrame, + static nsRect GetPostFilterDirtyArea(nsIFrame *aFilteredFrame, const nsRect& aPreFilterDirtyRect); /** @@ -88,8 +86,7 @@ public: * @param aPostFilterDirtyRect The post-filter area that is dirty, relative * to aFilteredFrame, in app units. */ - static nsRect GetPreFilterNeededArea(nsSVGFilterFrame* aFilterFrame, - nsIFrame *aFilteredFrame, + static nsRect GetPreFilterNeededArea(nsIFrame *aFilteredFrame, const nsRect& aPostFilterDirtyRect); /** @@ -100,14 +97,13 @@ public: * @param aPreFilterBounds The pre-filter visual overflow rect of * aFilteredFrame, if non-null. */ - static nsRect GetPostFilterBounds(nsSVGFilterFrame* aFilterFrame, - nsIFrame *aFilteredFrame, + static nsRect GetPostFilterBounds(nsIFrame *aFilteredFrame, const gfxRect *aOverrideBBox = nullptr, const nsRect *aPreFilterBounds = nullptr); /** * @param aTargetFrame The frame of the filtered element under consideration. - * @param aFilterFrame The frame of the SVG filter element. + * @param aFilters The CSS and SVG filter chain from the style system. * @param aPaintCallback [optional] The callback that Render() should use to * paint. Only required if you will call Render(). * @param aPostFilterDirtyRect [optional] The bounds of the post-filter area @@ -123,7 +119,6 @@ public: * @param aTransformRoot [optional] The transform root frame for painting. */ nsSVGFilterInstance(nsIFrame *aTargetFrame, - nsSVGFilterFrame *aFilterFrame, nsSVGFilterPaintCallback *aPaintCallback, const nsRect *aPostFilterDirtyRect = nullptr, const nsRect *aPreFilterDirtyRect = nullptr, @@ -273,6 +268,11 @@ private: nsresult BuildSourceImage(gfxASurface* aTargetSurface, DrawTarget* aTargetDT); + /** + * Finds the filter frame associated with this SVG filter. + */ + nsSVGFilterFrame* GetFilterFrame(); + /** * Build the list of FilterPrimitiveDescriptions that describes the filter's * filter primitives and their connections. This populates @@ -329,6 +329,11 @@ private: */ nsIFrame* mTargetFrame; + /** + * The CSS and SVG filter chain from the style system. + */ + const nsTArray mFilters; + nsSVGFilterPaintCallback* mPaintCallback; /** @@ -336,6 +341,11 @@ private: */ const mozilla::dom::SVGFilterElement* mFilterElement; + /** + * The frame for the SVG filter element. + */ + nsSVGFilterFrame* mFilterFrame; + /** * The SVG bbox of the element that is being filtered, in user space. */ diff --git a/layout/svg/nsSVGIntegrationUtils.cpp b/layout/svg/nsSVGIntegrationUtils.cpp index 8dcb72c4dbb8..31737ad140f1 100644 --- a/layout/svg/nsSVGIntegrationUtils.cpp +++ b/layout/svg/nsSVGIntegrationUtils.cpp @@ -15,7 +15,6 @@ #include "nsSVGClipPathFrame.h" #include "nsSVGEffects.h" #include "nsSVGElement.h" -#include "nsSVGFilterFrame.h" #include "nsSVGFilterInstance.h" #include "nsSVGFilterPaintCallback.h" #include "nsSVGMaskFrame.h" @@ -258,10 +257,9 @@ nsRect nsLayoutUtils::FirstContinuationOrIBSplitSibling(aFrame); nsSVGEffects::EffectProperties effectProperties = nsSVGEffects::GetEffectProperties(firstFrame); - nsSVGFilterFrame *filterFrame = effectProperties.mFilter ? - effectProperties.mFilter->GetFilterFrame() : nullptr; - if (!filterFrame) + if (!effectProperties.HasValidFilter()) { return aPreEffectsOverflowRect; + } // Create an override bbox - see comment above: nsPoint firstFrameToUserSpace = GetOffsetToUserSpace(firstFrame); @@ -277,7 +275,7 @@ nsRect overrideBBox.RoundOut(); nsRect overflowRect = - nsSVGFilterInstance::GetPostFilterBounds(filterFrame, firstFrame, &overrideBBox); + nsSVGFilterInstance::GetPostFilterBounds(firstFrame, &overrideBBox); // Return overflowRect relative to aFrame, rather than "user space": return overflowRect - (aFrame->GetOffsetTo(firstFrame) + firstFrameToUserSpace); @@ -296,11 +294,6 @@ nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(nsIFrame* aFrame, // already have been set up during reflow/ComputeFrameEffectsRect nsIFrame* firstFrame = nsLayoutUtils::FirstContinuationOrIBSplitSibling(aFrame); - nsSVGEffects::EffectProperties effectProperties = - nsSVGEffects::GetEffectProperties(firstFrame); - if (!effectProperties.mFilter) - return aInvalidRect; - nsSVGFilterProperty *prop = nsSVGEffects::GetFilterProperty(firstFrame); if (!prop || !prop->IsInObserverLists()) { return aInvalidRect; @@ -308,8 +301,7 @@ nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(nsIFrame* aFrame, int32_t appUnitsPerDevPixel = aFrame->PresContext()->AppUnitsPerDevPixel(); - nsSVGFilterFrame* filterFrame = prop->GetFilterFrame(); - if (!filterFrame) { + if (!prop || !prop->ReferencesValidResources()) { // The frame is either not there or not currently available, // perhaps because we're in the middle of tearing stuff down. // Be conservative, return our visual overflow rect relative @@ -328,8 +320,8 @@ nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(nsIFrame* aFrame, // Adjust the dirty area for effects, and shift it back to being relative to // the reference frame. - nsRect result = nsSVGFilterInstance::GetPostFilterDirtyArea(filterFrame, - firstFrame, preEffectsRect) - toUserSpace; + nsRect result = nsSVGFilterInstance::GetPostFilterDirtyArea(firstFrame, + preEffectsRect) - toUserSpace; // Return the result, in pixels relative to the reference frame. return result.ToOutsidePixels(appUnitsPerDevPixel); } @@ -342,10 +334,10 @@ nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(nsIFrame* aFrame, // already have been set up during reflow/ComputeFrameEffectsRect nsIFrame* firstFrame = nsLayoutUtils::FirstContinuationOrIBSplitSibling(aFrame); - nsSVGFilterFrame* filterFrame = - nsSVGEffects::GetFilterFrame(firstFrame); - if (!filterFrame) + nsSVGFilterProperty *prop = nsSVGEffects::GetFilterProperty(firstFrame); + if (!prop || !prop->ReferencesValidResources()) { return aDirtyRect; + } // Convert aDirtyRect into "user space" in app units: nsPoint toUserSpace = @@ -353,7 +345,7 @@ nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(nsIFrame* aFrame, nsRect postEffectsRect = aDirtyRect + toUserSpace; // Return ther result, relative to aFrame, not in user space: - return nsSVGFilterInstance::GetPreFilterNeededArea(filterFrame, firstFrame, + return nsSVGFilterInstance::GetPreFilterNeededArea(firstFrame, postEffectsRect) - toUserSpace; } @@ -456,9 +448,8 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx, nsSVGEffects::EffectProperties effectProperties = nsSVGEffects::GetEffectProperties(firstFrame); - bool isOK = true; + bool isOK = effectProperties.HasNoFilterOrHasValidFilter(); nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame(&isOK); - nsSVGFilterFrame *filterFrame = effectProperties.GetFilterFrame(&isOK); nsSVGMaskFrame *maskFrame = effectProperties.GetMaskFrame(&isOK); if (!isOK) { return; // Some resource is missing. We shouldn't paint anything. @@ -515,12 +506,11 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx, } /* Paint the child */ - if (filterFrame) { + if (effectProperties.HasValidFilter()) { RegularFramePaintCallback callback(aBuilder, aLayerManager, offsetWithoutSVGGeomFramePos); nsRect dirtyRect = aDirtyRect - offset; - nsSVGFilterInstance::PaintFilteredFrame(filterFrame, aCtx, aFrame, - &callback, &dirtyRect); + nsSVGFilterInstance::PaintFilteredFrame(aCtx, aFrame, &callback, &dirtyRect); } else { gfx->SetMatrix(matrixAutoSaveRestore.Matrix()); aLayerManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer, aBuilder); diff --git a/layout/svg/nsSVGUtils.cpp b/layout/svg/nsSVGUtils.cpp index dbc51871c3ba..fd0e4936db4f 100644 --- a/layout/svg/nsSVGUtils.cpp +++ b/layout/svg/nsSVGUtils.cpp @@ -35,7 +35,6 @@ #include "nsSVGClipPathFrame.h" #include "nsSVGContainerFrame.h" #include "nsSVGEffects.h" -#include "nsSVGFilterFrame.h" #include "nsSVGFilterInstance.h" #include "nsSVGFilterPaintCallback.h" #include "nsSVGForeignObjectFrame.h" @@ -160,13 +159,12 @@ nsSVGUtils::GetPostFilterVisualOverflowRect(nsIFrame *aFrame, NS_ABORT_IF_FALSE(aFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT, "Called on invalid frame type"); - nsSVGFilterFrame *filterFrame = nsSVGEffects::GetFilterFrame(aFrame); - if (!filterFrame) { + nsSVGFilterProperty *property = nsSVGEffects::GetFilterProperty(aFrame); + if (!property || !property->ReferencesValidResources()) { return aPreFilterRect; } - return nsSVGFilterInstance::GetPostFilterBounds(filterFrame, aFrame, nullptr, - &aPreFilterRect); + return nsSVGFilterInstance::GetPostFilterBounds(aFrame, nullptr, &aPreFilterRect); } bool @@ -499,8 +497,7 @@ nsSVGUtils::PaintFrameWithEffects(nsRenderingContext *aContext, nsSVGEffects::EffectProperties effectProperties = nsSVGEffects::GetEffectProperties(aFrame); - bool isOK = true; - nsSVGFilterFrame *filterFrame = effectProperties.GetFilterFrame(&isOK); + bool isOK = effectProperties.HasNoFilterOrHasValidFilter(); if (aDirtyRect && !(aFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY)) { @@ -601,7 +598,7 @@ nsSVGUtils::PaintFrameWithEffects(nsRenderingContext *aContext, } /* Paint the child */ - if (filterFrame) { + if (effectProperties.HasValidFilter()) { nsRect* dirtyRect = nullptr; nsRect tmpDirtyRect; if (aDirtyRect) { @@ -624,9 +621,8 @@ nsSVGUtils::PaintFrameWithEffects(nsRenderingContext *aContext, dirtyRect = &tmpDirtyRect; } SVGPaintCallback paintCallback; - nsSVGFilterInstance::PaintFilteredFrame(filterFrame, aContext, aFrame, - &paintCallback, dirtyRect, - aTransformRoot); + nsSVGFilterInstance::PaintFilteredFrame(aContext, aFrame, &paintCallback, + dirtyRect, aTransformRoot); } else { svgChildFrame->PaintSVG(aContext, aDirtyRect, aTransformRoot); } From 4cf3acd9d81627eff0b66c166bf3f905014ecf0c Mon Sep 17 00:00:00 2001 From: Max Vujovic Date: Mon, 24 Feb 2014 10:22:58 -0500 Subject: [PATCH 27/48] Bug 948265 - Split out rendering code from nsSVGFilterInstance into nsFilterInstance. r=roc --HG-- rename : layout/svg/nsSVGFilterInstance.cpp => layout/svg/nsFilterInstance.cpp rename : layout/svg/nsSVGFilterInstance.h => layout/svg/nsFilterInstance.h --- layout/svg/moz.build | 2 + layout/svg/nsFilterInstance.cpp | 586 +++++++++++++++++++++++++++ layout/svg/nsFilterInstance.h | 308 ++++++++++++++ layout/svg/nsSVGFilterInstance.cpp | 571 +------------------------- layout/svg/nsSVGFilterInstance.h | 286 ++----------- layout/svg/nsSVGIntegrationUtils.cpp | 12 +- layout/svg/nsSVGUtils.cpp | 8 +- 7 files changed, 955 insertions(+), 818 deletions(-) create mode 100644 layout/svg/nsFilterInstance.cpp create mode 100644 layout/svg/nsFilterInstance.h diff --git a/layout/svg/moz.build b/layout/svg/moz.build index c79489214853..4971db010144 100644 --- a/layout/svg/moz.build +++ b/layout/svg/moz.build @@ -5,6 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. EXPORTS += [ + 'nsFilterInstance.h', 'nsSVGEffects.h', 'nsSVGFilterInstance.h', 'nsSVGForeignObjectFrame.h', @@ -14,6 +15,7 @@ EXPORTS += [ ] UNIFIED_SOURCES += [ + 'nsFilterInstance.cpp', 'nsSVGAFrame.cpp', 'nsSVGClipPathFrame.cpp', 'nsSVGContainerFrame.cpp', diff --git a/layout/svg/nsFilterInstance.cpp b/layout/svg/nsFilterInstance.cpp new file mode 100644 index 000000000000..ba3fb8688f40 --- /dev/null +++ b/layout/svg/nsFilterInstance.cpp @@ -0,0 +1,586 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. */ + +// Main header first: +#include "nsFilterInstance.h" + +// Keep others in (case-insensitive) order: +#include "gfxPlatform.h" +#include "gfxUtils.h" +#include "nsISVGChildFrame.h" +#include "nsRenderingContext.h" +#include "nsSVGFilterInstance.h" +#include "nsSVGFilterPaintCallback.h" +#include "nsSVGUtils.h" +#include "SVGContentUtils.h" +#include "FilterSupport.h" +#include "gfx2DGlue.h" + +using namespace mozilla; +using namespace mozilla::dom; +using namespace mozilla::gfx; + +nsresult +nsFilterInstance::PaintFilteredFrame(nsRenderingContext *aContext, + nsIFrame *aFilteredFrame, + nsSVGFilterPaintCallback *aPaintCallback, + const nsRect *aDirtyArea, + nsIFrame* aTransformRoot) +{ + nsFilterInstance instance(aFilteredFrame, aPaintCallback, aDirtyArea, + nullptr, nullptr, nullptr, + aTransformRoot); + if (!instance.IsInitialized()) { + return NS_OK; + } + return instance.Render(aContext->ThebesContext()); +} + +nsRect +nsFilterInstance::GetPostFilterDirtyArea(nsIFrame *aFilteredFrame, + const nsRect& aPreFilterDirtyRect) +{ + if (aPreFilterDirtyRect.IsEmpty()) { + return nsRect(); + } + + nsFilterInstance instance(aFilteredFrame, nullptr, nullptr, + &aPreFilterDirtyRect); + if (!instance.IsInitialized()) { + return nsRect(); + } + // We've passed in the source's dirty area so the instance knows about it. + // Now we can ask the instance to compute the area of the filter output + // that's dirty. + nsRect dirtyRect; + nsresult rv = instance.ComputePostFilterDirtyRect(&dirtyRect); + if (NS_SUCCEEDED(rv)) { + return dirtyRect; + } + return nsRect(); +} + +nsRect +nsFilterInstance::GetPreFilterNeededArea(nsIFrame *aFilteredFrame, + const nsRect& aPostFilterDirtyRect) +{ + nsFilterInstance instance(aFilteredFrame, nullptr, &aPostFilterDirtyRect); + if (!instance.IsInitialized()) { + return nsRect(); + } + // Now we can ask the instance to compute the area of the source + // that's needed. + nsRect neededRect; + nsresult rv = instance.ComputeSourceNeededRect(&neededRect); + if (NS_SUCCEEDED(rv)) { + return neededRect; + } + return nsRect(); +} + +nsRect +nsFilterInstance::GetPostFilterBounds(nsIFrame *aFilteredFrame, + const gfxRect *aOverrideBBox, + const nsRect *aPreFilterBounds) +{ + MOZ_ASSERT(!(aFilteredFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) || + !(aFilteredFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY), + "Non-display SVG do not maintain visual overflow rects"); + + nsFilterInstance instance(aFilteredFrame, nullptr, nullptr, + aPreFilterBounds, aPreFilterBounds, + aOverrideBBox); + if (!instance.IsInitialized()) { + return nsRect(); + } + nsRect bbox; + nsresult rv = instance.ComputePostFilterExtents(&bbox); + if (NS_SUCCEEDED(rv)) { + return bbox; + } + return nsRect(); +} + +nsFilterInstance::nsFilterInstance(nsIFrame *aTargetFrame, + nsSVGFilterPaintCallback *aPaintCallback, + const nsRect *aPostFilterDirtyRect, + const nsRect *aPreFilterDirtyRect, + const nsRect *aPreFilterVisualOverflowRectOverride, + const gfxRect *aOverrideBBox, + nsIFrame* aTransformRoot) : + mTargetFrame(aTargetFrame), + mPaintCallback(aPaintCallback), + mTransformRoot(aTransformRoot), + mInitialized(false) { + + mTargetBBox = aOverrideBBox ? + *aOverrideBBox : nsSVGUtils::GetBBox(mTargetFrame); + + nsresult rv = BuildPrimitives(); + if (NS_FAILED(rv)) { + return; + } + + if (mPrimitiveDescriptions.IsEmpty()) { + // Nothing should be rendered. + return; + } + + // Get various transforms: + + gfxMatrix filterToUserSpace(mFilterRegion.Width() / mFilterSpaceBounds.width, 0.0f, + 0.0f, mFilterRegion.Height() / mFilterSpaceBounds.height, + mFilterRegion.X(), mFilterRegion.Y()); + + // Only used (so only set) when we paint: + if (mPaintCallback) { + mFilterSpaceToDeviceSpaceTransform = filterToUserSpace * + nsSVGUtils::GetCanvasTM(mTargetFrame, nsISVGChildFrame::FOR_PAINTING); + } + + // Convert the passed in rects from frame to filter space: + + mAppUnitsPerCSSPx = mTargetFrame->PresContext()->AppUnitsPerCSSPixel(); + + mFilterSpaceToFrameSpaceInCSSPxTransform = + filterToUserSpace * GetUserSpaceToFrameSpaceInCSSPxTransform(); + // mFilterSpaceToFrameSpaceInCSSPxTransform is always invertible + mFrameSpaceInCSSPxToFilterSpaceTransform = + mFilterSpaceToFrameSpaceInCSSPxTransform; + mFrameSpaceInCSSPxToFilterSpaceTransform.Invert(); + + mPostFilterDirtyRect = FrameSpaceToFilterSpace(aPostFilterDirtyRect); + mPreFilterDirtyRect = FrameSpaceToFilterSpace(aPreFilterDirtyRect); + if (aPreFilterVisualOverflowRectOverride) { + mTargetBounds = + FrameSpaceToFilterSpace(aPreFilterVisualOverflowRectOverride); + } else { + nsRect preFilterVOR = mTargetFrame->GetPreEffectsVisualOverflowRect(); + mTargetBounds = FrameSpaceToFilterSpace(&preFilterVOR); + } + + mInitialized = true; +} + +gfxRect +nsFilterInstance::UserSpaceToFilterSpace(const gfxRect& aRect) const +{ + gfxRect r = aRect - mFilterRegion.TopLeft(); + r.Scale(mFilterSpaceBounds.width / mFilterRegion.Width(), + mFilterSpaceBounds.height / mFilterRegion.Height()); + return r; +} + +gfxMatrix +nsFilterInstance::GetUserSpaceToFilterSpaceTransform() const +{ + gfxFloat widthScale = mFilterSpaceBounds.width / mFilterRegion.Width(); + gfxFloat heightScale = mFilterSpaceBounds.height / mFilterRegion.Height(); + return gfxMatrix(widthScale, 0.0f, + 0.0f, heightScale, + -mFilterRegion.X() * widthScale, -mFilterRegion.Y() * heightScale); +} + +nsresult +nsFilterInstance::BuildPrimitives() +{ + NS_ASSERTION(!mPrimitiveDescriptions.Length(), + "expected to start building primitives from scratch"); + + const nsTArray& filters = mTargetFrame->StyleSVGReset()->mFilters; + for (uint32_t i = 0; i < filters.Length(); i++) { + nsresult rv = BuildPrimitivesForFilter(filters[i]); + if (NS_FAILED(rv)) { + return rv; + } + } + return NS_OK; +} + +nsresult +nsFilterInstance::BuildPrimitivesForFilter(const nsStyleFilter& aFilter) +{ + if (aFilter.GetType() == NS_STYLE_FILTER_URL) { + // Build primitives for an SVG filter. + nsSVGFilterInstance svgFilterInstance(aFilter, mTargetFrame, mTargetBBox); + if (!svgFilterInstance.IsInitialized()) { + return NS_ERROR_FAILURE; + } + + // For now, we use the last SVG filter region as the overall filter region + // for the filter chain. Eventually, we will compute the overall filter + // using all of the generated FilterPrimitiveDescriptions. + mFilterRegion = svgFilterInstance.GetFilterRegion(); + mFilterSpaceBounds = svgFilterInstance.GetFilterSpaceBounds(); + + return svgFilterInstance.BuildPrimitives(mPrimitiveDescriptions, mInputImages); + } + + // Eventually, we will build primitives for CSS filters, too. + return NS_ERROR_FAILURE; +} + +void +nsFilterInstance::ComputeNeededBoxes() +{ + if (mPrimitiveDescriptions.IsEmpty()) + return; + + nsIntRegion sourceGraphicNeededRegion; + nsIntRegion fillPaintNeededRegion; + nsIntRegion strokePaintNeededRegion; + + FilterDescription filter(mPrimitiveDescriptions, ToIntRect(mFilterSpaceBounds)); + FilterSupport::ComputeSourceNeededRegions( + filter, mPostFilterDirtyRect, + sourceGraphicNeededRegion, fillPaintNeededRegion, strokePaintNeededRegion); + + nsIntRect sourceBoundsInt; + gfxRect sourceBounds = UserSpaceToFilterSpace(mTargetBBox); + sourceBounds.RoundOut(); + // Detect possible float->int overflow + if (!gfxUtils::GfxRectToIntRect(sourceBounds, &sourceBoundsInt)) + return; + sourceBoundsInt.UnionRect(sourceBoundsInt, mTargetBounds); + + sourceGraphicNeededRegion.And(sourceGraphicNeededRegion, sourceBoundsInt); + + mSourceGraphic.mNeededBounds = sourceGraphicNeededRegion.GetBounds(); + mFillPaint.mNeededBounds = fillPaintNeededRegion.GetBounds(); + mStrokePaint.mNeededBounds = strokePaintNeededRegion.GetBounds(); +} + +nsresult +nsFilterInstance::BuildSourcePaint(SourceInfo *aSource, + gfxASurface* aTargetSurface, + DrawTarget* aTargetDT) +{ + nsIntRect neededRect = aSource->mNeededBounds; + + RefPtr offscreenDT; + nsRefPtr offscreenSurface; + nsRefPtr ctx; + if (aTargetSurface) { + offscreenSurface = gfxPlatform::GetPlatform()->CreateOffscreenSurface( + neededRect.Size().ToIntSize(), gfxContentType::COLOR_ALPHA); + if (!offscreenSurface || offscreenSurface->CairoStatus()) { + return NS_ERROR_OUT_OF_MEMORY; + } + ctx = new gfxContext(offscreenSurface); + } else { + offscreenDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget( + ToIntSize(neededRect.Size()), SurfaceFormat::B8G8R8A8); + if (!offscreenDT) { + return NS_ERROR_OUT_OF_MEMORY; + } + ctx = new gfxContext(offscreenDT); + } + + ctx->Translate(-neededRect.TopLeft()); + + nsRenderingContext tmpCtx; + tmpCtx.Init(mTargetFrame->PresContext()->DeviceContext(), ctx); + + gfxMatrix m = GetUserSpaceToFilterSpaceTransform(); + m.Invert(); + gfxRect r = m.TransformBounds(mFilterSpaceBounds); + + gfxMatrix deviceToFilterSpace = GetFilterSpaceToDeviceSpaceTransform().Invert(); + gfxContext *gfx = tmpCtx.ThebesContext(); + gfx->Multiply(deviceToFilterSpace); + + gfx->Save(); + + gfxMatrix matrix = + nsSVGUtils::GetCanvasTM(mTargetFrame, nsISVGChildFrame::FOR_PAINTING, + mTransformRoot); + if (!matrix.IsSingular()) { + gfx->Multiply(matrix); + gfx->Rectangle(r); + if ((aSource == &mFillPaint && + nsSVGUtils::SetupCairoFillPaint(mTargetFrame, gfx)) || + (aSource == &mStrokePaint && + nsSVGUtils::SetupCairoStrokePaint(mTargetFrame, gfx))) { + gfx->Fill(); + } + } + gfx->Restore(); + + if (offscreenSurface) { + aSource->mSourceSurface = + gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(aTargetDT, offscreenSurface); + } else { + aSource->mSourceSurface = offscreenDT->Snapshot(); + } + aSource->mSurfaceRect = ToIntRect(neededRect); + + return NS_OK; +} + +nsresult +nsFilterInstance::BuildSourcePaints(gfxASurface* aTargetSurface, + DrawTarget* aTargetDT) +{ + nsresult rv = NS_OK; + + if (!mFillPaint.mNeededBounds.IsEmpty()) { + rv = BuildSourcePaint(&mFillPaint, aTargetSurface, aTargetDT); + NS_ENSURE_SUCCESS(rv, rv); + } + + if (!mStrokePaint.mNeededBounds.IsEmpty()) { + rv = BuildSourcePaint(&mStrokePaint, aTargetSurface, aTargetDT); + NS_ENSURE_SUCCESS(rv, rv); + } + return rv; +} + +nsresult +nsFilterInstance::BuildSourceImage(gfxASurface* aTargetSurface, + DrawTarget* aTargetDT) +{ + nsIntRect neededRect = mSourceGraphic.mNeededBounds; + if (neededRect.IsEmpty()) { + return NS_OK; + } + + RefPtr offscreenDT; + nsRefPtr offscreenSurface; + nsRefPtr ctx; + if (aTargetSurface) { + offscreenSurface = gfxPlatform::GetPlatform()->CreateOffscreenSurface( + neededRect.Size().ToIntSize(), gfxContentType::COLOR_ALPHA); + if (!offscreenSurface || offscreenSurface->CairoStatus()) { + return NS_ERROR_OUT_OF_MEMORY; + } + ctx = new gfxContext(offscreenSurface); + } else { + offscreenDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget( + ToIntSize(neededRect.Size()), SurfaceFormat::B8G8R8A8); + if (!offscreenDT) { + return NS_ERROR_OUT_OF_MEMORY; + } + ctx = new gfxContext(offscreenDT); + } + + ctx->Translate(-neededRect.TopLeft()); + + nsRenderingContext tmpCtx; + tmpCtx.Init(mTargetFrame->PresContext()->DeviceContext(), ctx); + + gfxMatrix m = GetUserSpaceToFilterSpaceTransform(); + m.Invert(); + gfxRect r = m.TransformBounds(neededRect); + r.RoundOut(); + nsIntRect dirty; + if (!gfxUtils::GfxRectToIntRect(r, &dirty)) + return NS_ERROR_FAILURE; + + // SVG graphics paint to device space, so we need to set an initial device + // space to filter space transform on the gfxContext that SourceGraphic + // and SourceAlpha will paint to. + // + // (In theory it would be better to minimize error by having filtered SVG + // graphics temporarily paint to user space when painting the sources and + // only set a user space to filter space transform on the gfxContext + // (since that would eliminate the transform multiplications from user + // space to device space and back again). However, that would make the + // code more complex while being hard to get right without introducing + // subtle bugs, and in practice it probably makes no real difference.) + gfxMatrix deviceToFilterSpace = GetFilterSpaceToDeviceSpaceTransform().Invert(); + tmpCtx.ThebesContext()->Multiply(deviceToFilterSpace); + mPaintCallback->Paint(&tmpCtx, mTargetFrame, &dirty, mTransformRoot); + + RefPtr sourceGraphicSource; + + if (offscreenSurface) { + sourceGraphicSource = + gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(aTargetDT, offscreenSurface); + } else { + sourceGraphicSource = offscreenDT->Snapshot(); + } + + mSourceGraphic.mSourceSurface = sourceGraphicSource; + mSourceGraphic.mSurfaceRect = ToIntRect(neededRect); + + return NS_OK; +} + +nsresult +nsFilterInstance::Render(gfxContext* aContext) +{ + nsIntRect filterRect = mPostFilterDirtyRect.Intersect(mFilterSpaceBounds); + gfxMatrix ctm = GetFilterSpaceToDeviceSpaceTransform(); + + if (filterRect.IsEmpty() || ctm.IsSingular()) { + return NS_OK; + } + + Matrix oldDTMatrix; + nsRefPtr resultImage; + RefPtr dt; + if (aContext->IsCairo()) { + resultImage = + gfxPlatform::GetPlatform()->CreateOffscreenSurface(filterRect.Size().ToIntSize(), + gfxContentType::COLOR_ALPHA); + if (!resultImage || resultImage->CairoStatus()) + return NS_ERROR_OUT_OF_MEMORY; + + // Create a Cairo DrawTarget around resultImage. + dt = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface( + resultImage, ToIntSize(filterRect.Size())); + } else { + // When we have a DrawTarget-backed context, we can call DrawFilter + // directly on the target DrawTarget and don't need a temporary DT. + dt = aContext->GetDrawTarget(); + oldDTMatrix = dt->GetTransform(); + Matrix matrix = ToMatrix(ctm); + matrix.Translate(filterRect.x, filterRect.y); + dt->SetTransform(matrix * oldDTMatrix); + } + + ComputeNeededBoxes(); + + nsresult rv = BuildSourceImage(resultImage, dt); + if (NS_FAILED(rv)) + return rv; + rv = BuildSourcePaints(resultImage, dt); + if (NS_FAILED(rv)) + return rv; + + IntRect filterSpaceBounds = ToIntRect(mFilterSpaceBounds); + FilterDescription filter(mPrimitiveDescriptions, filterSpaceBounds); + + FilterSupport::RenderFilterDescription( + dt, filter, ToRect(filterRect), + mSourceGraphic.mSourceSurface, mSourceGraphic.mSurfaceRect, + mFillPaint.mSourceSurface, mFillPaint.mSurfaceRect, + mStrokePaint.mSourceSurface, mStrokePaint.mSurfaceRect, + mInputImages); + + if (resultImage) { + aContext->Save(); + aContext->Multiply(ctm); + aContext->Translate(filterRect.TopLeft()); + aContext->SetSource(resultImage); + aContext->Paint(); + aContext->Restore(); + } else { + dt->SetTransform(oldDTMatrix); + } + + return NS_OK; +} + +nsresult +nsFilterInstance::ComputePostFilterDirtyRect(nsRect* aPostFilterDirtyRect) +{ + *aPostFilterDirtyRect = nsRect(); + if (mPreFilterDirtyRect.IsEmpty()) { + return NS_OK; + } + + IntRect filterSpaceBounds = ToIntRect(mFilterSpaceBounds); + FilterDescription filter(mPrimitiveDescriptions, filterSpaceBounds); + nsIntRegion resultChangeRegion = + FilterSupport::ComputeResultChangeRegion(filter, + mPreFilterDirtyRect, nsIntRegion(), nsIntRegion()); + *aPostFilterDirtyRect = + FilterSpaceToFrameSpace(resultChangeRegion.GetBounds()); + return NS_OK; +} + +nsresult +nsFilterInstance::ComputePostFilterExtents(nsRect* aPostFilterExtents) +{ + *aPostFilterExtents = nsRect(); + + nsIntRect sourceBoundsInt; + gfxRect sourceBounds = UserSpaceToFilterSpace(mTargetBBox); + sourceBounds.RoundOut(); + // Detect possible float->int overflow + if (!gfxUtils::GfxRectToIntRect(sourceBounds, &sourceBoundsInt)) + return NS_ERROR_FAILURE; + sourceBoundsInt.UnionRect(sourceBoundsInt, mTargetBounds); + + IntRect filterSpaceBounds = ToIntRect(mFilterSpaceBounds); + FilterDescription filter(mPrimitiveDescriptions, filterSpaceBounds); + nsIntRegion postFilterExtents = + FilterSupport::ComputePostFilterExtents(filter, sourceBoundsInt); + *aPostFilterExtents = FilterSpaceToFrameSpace(postFilterExtents.GetBounds()); + return NS_OK; +} + +nsresult +nsFilterInstance::ComputeSourceNeededRect(nsRect* aDirty) +{ + ComputeNeededBoxes(); + *aDirty = FilterSpaceToFrameSpace(mSourceGraphic.mNeededBounds); + + return NS_OK; +} + +nsIntRect +nsFilterInstance::FrameSpaceToFilterSpace(const nsRect* aRect) const +{ + nsIntRect rect = mFilterSpaceBounds; + if (aRect) { + if (aRect->IsEmpty()) { + return nsIntRect(); + } + gfxRect rectInCSSPx = + nsLayoutUtils::RectToGfxRect(*aRect, mAppUnitsPerCSSPx); + gfxRect rectInFilterSpace = + mFrameSpaceInCSSPxToFilterSpaceTransform.TransformBounds(rectInCSSPx); + rectInFilterSpace.RoundOut(); + nsIntRect intRect; + if (gfxUtils::GfxRectToIntRect(rectInFilterSpace, &intRect)) { + rect = intRect; + } + } + return rect; +} + +nsRect +nsFilterInstance::FilterSpaceToFrameSpace(const nsIntRect& aRect) const +{ + if (aRect.IsEmpty()) { + return nsRect(); + } + gfxRect r(aRect.x, aRect.y, aRect.width, aRect.height); + r = mFilterSpaceToFrameSpaceInCSSPxTransform.TransformBounds(r); + return nsLayoutUtils::RoundGfxRectToAppRect(r, mAppUnitsPerCSSPx); +} + +gfxMatrix +nsFilterInstance::GetUserSpaceToFrameSpaceInCSSPxTransform() const +{ + gfxMatrix userToFrameSpaceInCSSPx; + + if ((mTargetFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)) { + // As currently implemented by Mozilla for the purposes of filters, user + // space is the coordinate system established by GetCanvasTM(), since + // that's what we use to set filterToDeviceSpace above. In other words, + // for SVG, user space is actually the coordinate system aTarget + // establishes for _its_ children (i.e. after taking account of any x/y + // and viewBox attributes), not the coordinate system that is established + // for it by its 'transform' attribute (or by its _parent_) as it's + // normally defined. (XXX We should think about fixing this.) The only + // frame type for which these extra transforms are not simply an x/y + // translation is nsSVGInnerSVGFrame, hence we treat it specially here. + if (mTargetFrame->GetType() == nsGkAtoms::svgInnerSVGFrame) { + userToFrameSpaceInCSSPx = + static_cast(mTargetFrame->GetContent())-> + PrependLocalTransformsTo(gfxMatrix()); + } else { + gfxPoint targetsUserSpaceOffset = + nsLayoutUtils::RectToGfxRect(mTargetFrame->GetRect(), + mAppUnitsPerCSSPx).TopLeft(); + userToFrameSpaceInCSSPx.Translate(-targetsUserSpaceOffset); + } + } + // else, for all other frames, leave as the identity matrix + return userToFrameSpaceInCSSPx; +} diff --git a/layout/svg/nsFilterInstance.h b/layout/svg/nsFilterInstance.h new file mode 100644 index 000000000000..475ea1876aa3 --- /dev/null +++ b/layout/svg/nsFilterInstance.h @@ -0,0 +1,308 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. */ + +#ifndef __NS_FILTERINSTANCE_H__ +#define __NS_FILTERINSTANCE_H__ + +#include "gfxMatrix.h" +#include "gfxPoint.h" +#include "gfxRect.h" +#include "nsCOMPtr.h" +#include "nsHashKeys.h" +#include "nsPoint.h" +#include "nsRect.h" +#include "nsSize.h" +#include "nsSVGFilters.h" +#include "nsSVGNumber2.h" +#include "nsSVGNumberPair.h" +#include "nsTArray.h" +#include "nsIFrame.h" +#include "mozilla/gfx/2D.h" + +class gfxASurface; +class nsIFrame; +class nsSVGFilterPaintCallback; + +/** + * This class performs all filter processing. + * + * We build a graph of the filter image data flow, essentially + * converting the filter graph to SSA. This lets us easily propagate + * analysis data (such as bounding-boxes) over the filter primitive graph. + * + * Definition of "filter space": filter space is a coordinate system that is + * aligned with the user space of the filtered element, with its origin located + * at the top left of the filter region, and with one unit equal in size to one + * pixel of the offscreen surface into which the filter output would/will be + * painted. + * + * The definition of "filter region" can be found here: + * http://www.w3.org/TR/SVG11/filters.html#FilterEffectsRegion + */ +class nsFilterInstance +{ + typedef mozilla::gfx::IntRect IntRect; + typedef mozilla::gfx::SourceSurface SourceSurface; + typedef mozilla::gfx::DrawTarget DrawTarget; + typedef mozilla::gfx::FilterPrimitiveDescription FilterPrimitiveDescription; + +public: + /** + * Paint the given filtered frame. + * @param aDirtyArea The area than needs to be painted, in aFilteredFrame's + * frame space (i.e. relative to its origin, the top-left corner of its + * border box). + */ + static nsresult PaintFilteredFrame(nsRenderingContext *aContext, + nsIFrame *aFilteredFrame, + nsSVGFilterPaintCallback *aPaintCallback, + const nsRect* aDirtyArea, + nsIFrame* aTransformRoot = nullptr); + + /** + * Returns the post-filter area that could be dirtied when the given + * pre-filter area of aFilteredFrame changes. + * @param aPreFilterDirtyRect The pre-filter area of aFilteredFrame that has + * changed, relative to aFilteredFrame, in app units. + */ + static nsRect GetPostFilterDirtyArea(nsIFrame *aFilteredFrame, + const nsRect& aPreFilterDirtyRect); + + /** + * Returns the pre-filter area that is needed from aFilteredFrame when the + * given post-filter area needs to be repainted. + * @param aPostFilterDirtyRect The post-filter area that is dirty, relative + * to aFilteredFrame, in app units. + */ + static nsRect GetPreFilterNeededArea(nsIFrame *aFilteredFrame, + const nsRect& aPostFilterDirtyRect); + + /** + * Returns the post-filter visual overflow rect (paint bounds) of + * aFilteredFrame. + * @param aOverrideBBox A user space rect, in user units, that should be used + * as aFilteredFrame's bbox ('bbox' is a specific SVG term), if non-null. + * @param aPreFilterBounds The pre-filter visual overflow rect of + * aFilteredFrame, if non-null. + */ + static nsRect GetPostFilterBounds(nsIFrame *aFilteredFrame, + const gfxRect *aOverrideBBox = nullptr, + const nsRect *aPreFilterBounds = nullptr); + + /** + * @param aTargetFrame The frame of the filtered element under consideration. + * @param aPaintCallback [optional] The callback that Render() should use to + * paint. Only required if you will call Render(). + * @param aPostFilterDirtyRect [optional] The bounds of the post-filter area + * that has to be repainted, in filter space. Only required if you will + * call ComputeSourceNeededRect() or Render(). + * @param aPreFilterDirtyRect [optional] The bounds of the pre-filter area of + * the filtered element that changed, in filter space. Only required if you + * will call ComputePostFilterDirtyRect(). + * @param aOverridePreFilterVisualOverflowRect [optional] Use a different + * visual overflow rect for the target element. + * @param aOverrideBBox [optional] Use a different SVG bbox for the target + * element. + * @param aTransformRoot [optional] The transform root frame for painting. + */ + nsFilterInstance(nsIFrame *aTargetFrame, + nsSVGFilterPaintCallback *aPaintCallback, + const nsRect *aPostFilterDirtyRect = nullptr, + const nsRect *aPreFilterDirtyRect = nullptr, + const nsRect *aOverridePreFilterVisualOverflowRect = nullptr, + const gfxRect *aOverrideBBox = nullptr, + nsIFrame* aTransformRoot = nullptr); + + /** + * Returns true if the filter instance was created successfully. + */ + bool IsInitialized() const { return mInitialized; } + + /** + * Draws the filter output into aContext. The area that + * needs to be painted must have been specified before calling this method + * by passing it as the aPostFilterDirtyRect argument to the + * nsFilterInstance constructor. + */ + nsresult Render(gfxContext* aContext); + + /** + * Sets the aPostFilterDirtyRect outparam to the post-filter bounds in frame + * space of the area that would be dirtied by mTargetFrame when a given + * pre-filter area of mTargetFrame is dirtied. The pre-filter area must have + * been specified before calling this method by passing it as the + * aPreFilterDirtyRect argument to the nsFilterInstance constructor. + */ + nsresult ComputePostFilterDirtyRect(nsRect* aPostFilterDirtyRect); + + /** + * Sets the aPostFilterExtents outparam to the post-filter bounds in frame + * space for the whole filter output. This is not necessarily equivalent to + * the area that would be dirtied in the result when the entire pre-filter + * area is dirtied, because some filter primitives can generate output + * without any input. + */ + nsresult ComputePostFilterExtents(nsRect* aPostFilterExtents); + + /** + * Sets the aDirty outparam to the pre-filter bounds in frame space of the + * area of mTargetFrame that is needed in order to paint the filtered output + * for a given post-filter dirtied area. The post-filter area must have been + * specified before calling this method by passing it as the aPostFilterDirtyRect + * argument to the nsFilterInstance constructor. + */ + nsresult ComputeSourceNeededRect(nsRect* aDirty); + + /** + * Returns the transform from the filtered element's user space to filter + * space. This will be a simple translation and/or scale. + */ + gfxMatrix GetUserSpaceToFilterSpaceTransform() const; + + /** + * Returns the transform from filter space to outer- device space. + */ + gfxMatrix GetFilterSpaceToDeviceSpaceTransform() const { + return mFilterSpaceToDeviceSpaceTransform; + } + +private: + struct SourceInfo { + // Specifies which parts of the source need to be rendered. + // Set by ComputeNeededBoxes(). + nsIntRect mNeededBounds; + + // The surface that contains the input rendering. + // Set by BuildSourceImage / BuildSourcePaint. + mozilla::RefPtr mSourceSurface; + + // The position and size of mSourceSurface in filter space. + // Set by BuildSourceImage / BuildSourcePaint. + IntRect mSurfaceRect; + }; + + /** + * Creates a SourceSurface for either the FillPaint or StrokePaint graph + * nodes + */ + nsresult BuildSourcePaint(SourceInfo *aPrimitive, + gfxASurface* aTargetSurface, + DrawTarget* aTargetDT); + + /** + * Creates a SourceSurface for either the FillPaint and StrokePaint graph + * nodes, fills its contents and assigns it to mFillPaint.mSourceSurface and + * mStrokePaint.mSourceSurface respectively. + */ + nsresult BuildSourcePaints(gfxASurface* aTargetSurface, + DrawTarget* aTargetDT); + + /** + * Creates the SourceSurface for the SourceGraphic graph node, paints its + * contents, and assigns it to mSourceGraphic.mSourceSurface. + */ + nsresult BuildSourceImage(gfxASurface* aTargetSurface, + DrawTarget* aTargetDT); + + /** + * Build the list of FilterPrimitiveDescriptions that describes the filter's + * filter primitives and their connections. This populates + * mPrimitiveDescriptions and mInputImages. + */ + nsresult BuildPrimitives(); + + /** + * Add to the list of FilterPrimitiveDescriptions for a particular SVG + * reference filter or CSS filter. This populates mPrimitiveDescrs and + * mInputImages. + */ + nsresult BuildPrimitivesForFilter(const nsStyleFilter& aFilter); + + /** + * Computes the filter space bounds of the areas that we actually *need* from + * the filter sources, based on the value of mPostFilterDirtyRect. + * This sets mNeededBounds on the corresponding SourceInfo structs. + */ + void ComputeNeededBoxes(); + + gfxRect UserSpaceToFilterSpace(const gfxRect& aUserSpace) const; + + /** + * Converts an nsRect that is relative to a filtered frame's origin (i.e. the + * top-left corner of its border box) into filter space. + * Returns the entire filter region if aRect is null, or if the result is too + * large to be stored in an nsIntRect. + */ + nsIntRect FrameSpaceToFilterSpace(const nsRect* aRect) const; + nsRect FilterSpaceToFrameSpace(const nsIntRect& aRect) const; + + /** + * Returns the transform from frame space to the coordinate space that + * GetCanvasTM transforms to. "Frame space" is the origin of a frame, aka the + * top-left corner of its border box, aka the top left corner of its mRect. + */ + gfxMatrix GetUserSpaceToFrameSpaceInCSSPxTransform() const; + + /** + * The frame for the element that is currently being filtered. + */ + nsIFrame* mTargetFrame; + + nsSVGFilterPaintCallback* mPaintCallback; + + /** + * The SVG bbox of the element that is being filtered, in user space. + */ + gfxRect mTargetBBox; + + /** + * The transform from filter space to outer- device space. + */ + gfxMatrix mFilterSpaceToDeviceSpaceTransform; + + /** + * Transform rects between filter space and frame space in CSS pixels. + */ + gfxMatrix mFilterSpaceToFrameSpaceInCSSPxTransform; + gfxMatrix mFrameSpaceInCSSPxToFilterSpaceTransform; + + /** + * The "filter region", in the filtered element's user space. + */ + gfxRect mFilterRegion; + nsIntRect mFilterSpaceBounds; + + /** + * Pre-filter paint bounds of the element that is being filtered, in filter + * space. + */ + nsIntRect mTargetBounds; + + /** + * If set, this is the filter space bounds of the outer- device space + * bounds of the dirty area that needs to be repainted. (As bounds-of-bounds, + * this may be a fair bit bigger than we actually need, unfortunately.) + */ + nsIntRect mPostFilterDirtyRect; + + /** + * If set, this is the filter space bounds of the outer- device bounds + * of the pre-filter area of the filtered element that changed. (As + * bounds-of-bounds, this may be a fair bit bigger than we actually need, + * unfortunately.) + */ + nsIntRect mPreFilterDirtyRect; + + SourceInfo mSourceGraphic; + SourceInfo mFillPaint; + SourceInfo mStrokePaint; + nsIFrame* mTransformRoot; + nsTArray> mInputImages; + nsTArray mPrimitiveDescriptions; + int32_t mAppUnitsPerCSSPx; + bool mInitialized; +}; + +#endif diff --git a/layout/svg/nsSVGFilterInstance.cpp b/layout/svg/nsSVGFilterInstance.cpp index f06cd477bf69..226c2649e1a5 100644 --- a/layout/svg/nsSVGFilterInstance.cpp +++ b/layout/svg/nsSVGFilterInstance.cpp @@ -24,98 +24,12 @@ using namespace mozilla; using namespace mozilla::dom; using namespace mozilla::gfx; -nsresult -nsSVGFilterInstance::PaintFilteredFrame(nsRenderingContext *aContext, - nsIFrame *aFilteredFrame, - nsSVGFilterPaintCallback *aPaintCallback, - const nsRect *aDirtyArea, - nsIFrame* aTransformRoot) -{ - nsSVGFilterInstance instance(aFilteredFrame, aPaintCallback, aDirtyArea, - nullptr, nullptr, nullptr, - aTransformRoot); - if (!instance.IsInitialized()) { - return NS_OK; - } - return instance.Render(aContext->ThebesContext()); -} - -nsRect -nsSVGFilterInstance::GetPostFilterDirtyArea(nsIFrame *aFilteredFrame, - const nsRect& aPreFilterDirtyRect) -{ - if (aPreFilterDirtyRect.IsEmpty()) { - return nsRect(); - } - - nsSVGFilterInstance instance(aFilteredFrame, nullptr, nullptr, - &aPreFilterDirtyRect); - if (!instance.IsInitialized()) { - return nsRect(); - } - // We've passed in the source's dirty area so the instance knows about it. - // Now we can ask the instance to compute the area of the filter output - // that's dirty. - nsRect dirtyRect; - nsresult rv = instance.ComputePostFilterDirtyRect(&dirtyRect); - if (NS_SUCCEEDED(rv)) { - return dirtyRect; - } - return nsRect(); -} - -nsRect -nsSVGFilterInstance::GetPreFilterNeededArea(nsIFrame *aFilteredFrame, - const nsRect& aPostFilterDirtyRect) -{ - nsSVGFilterInstance instance(aFilteredFrame, nullptr, &aPostFilterDirtyRect); - if (!instance.IsInitialized()) { - return nsRect(); - } - // Now we can ask the instance to compute the area of the source - // that's needed. - nsRect neededRect; - nsresult rv = instance.ComputeSourceNeededRect(&neededRect); - if (NS_SUCCEEDED(rv)) { - return neededRect; - } - return nsRect(); -} - -nsRect -nsSVGFilterInstance::GetPostFilterBounds(nsIFrame *aFilteredFrame, - const gfxRect *aOverrideBBox, - const nsRect *aPreFilterBounds) -{ - MOZ_ASSERT(!(aFilteredFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT) || - !(aFilteredFrame->GetStateBits() & NS_FRAME_IS_NONDISPLAY), - "Non-display SVG do not maintain visual overflow rects"); - - nsSVGFilterInstance instance(aFilteredFrame, nullptr, nullptr, - aPreFilterBounds, aPreFilterBounds, - aOverrideBBox); - if (!instance.IsInitialized()) { - return nsRect(); - } - nsRect bbox; - nsresult rv = instance.ComputePostFilterExtents(&bbox); - if (NS_SUCCEEDED(rv)) { - return bbox; - } - return nsRect(); -} - -nsSVGFilterInstance::nsSVGFilterInstance(nsIFrame *aTargetFrame, - nsSVGFilterPaintCallback *aPaintCallback, - const nsRect *aPostFilterDirtyRect, - const nsRect *aPreFilterDirtyRect, - const nsRect *aPreFilterVisualOverflowRectOverride, - const gfxRect *aOverrideBBox, - nsIFrame* aTransformRoot) : +nsSVGFilterInstance::nsSVGFilterInstance(const nsStyleFilter& aFilter, + nsIFrame *aTargetFrame, + const gfxRect& aTargetBBox) : + mFilter(aFilter), mTargetFrame(aTargetFrame), - mFilters(aTargetFrame->StyleSVGReset()->mFilters), - mPaintCallback(aPaintCallback), - mTransformRoot(aTransformRoot), + mTargetBBox(aTargetBBox), mInitialized(false) { // Get the filter frame. @@ -134,9 +48,6 @@ nsSVGFilterInstance::nsSVGFilterInstance(nsIFrame *aTargetFrame, mPrimitiveUnits = mFilterFrame->GetEnumValue(SVGFilterElement::PRIMITIVEUNITS); - mTargetBBox = aOverrideBBox ? - *aOverrideBBox : nsSVGUtils::GetBBox(mTargetFrame); - // Get the filter region (in the filtered element's user space): // XXX if filterUnits is set (or has defaulted) to objectBoundingBox, we @@ -221,60 +132,18 @@ nsSVGFilterInstance::nsSVGFilterInstance(nsIFrame *aTargetFrame, mFilterSpaceBounds.SetRect(nsIntPoint(0, 0), filterRes); - // Get various transforms: - - gfxMatrix filterToUserSpace(mFilterRegion.Width() / filterRes.width, 0.0f, - 0.0f, mFilterRegion.Height() / filterRes.height, - mFilterRegion.X(), mFilterRegion.Y()); - - // Only used (so only set) when we paint: - if (mPaintCallback) { - mFilterSpaceToDeviceSpaceTransform = filterToUserSpace * - nsSVGUtils::GetCanvasTM(mTargetFrame, nsISVGChildFrame::FOR_PAINTING); - } - - // Convert the passed in rects from frame to filter space: - - mAppUnitsPerCSSPx = mTargetFrame->PresContext()->AppUnitsPerCSSPixel(); - - mFilterSpaceToFrameSpaceInCSSPxTransform = - filterToUserSpace * GetUserSpaceToFrameSpaceInCSSPxTransform(); - // mFilterSpaceToFrameSpaceInCSSPxTransform is always invertible - mFrameSpaceInCSSPxToFilterSpaceTransform = - mFilterSpaceToFrameSpaceInCSSPxTransform; - mFrameSpaceInCSSPxToFilterSpaceTransform.Invert(); - - mPostFilterDirtyRect = FrameSpaceToFilterSpace(aPostFilterDirtyRect); - mPreFilterDirtyRect = FrameSpaceToFilterSpace(aPreFilterDirtyRect); - if (aPreFilterVisualOverflowRectOverride) { - mTargetBounds = - FrameSpaceToFilterSpace(aPreFilterVisualOverflowRectOverride); - } else { - nsRect preFilterVOR = mTargetFrame->GetPreEffectsVisualOverflowRect(); - mTargetBounds = FrameSpaceToFilterSpace(&preFilterVOR); - } - mInitialized = true; } nsSVGFilterFrame* nsSVGFilterInstance::GetFilterFrame() { - if (mFilters.Length() <= 0) { - // There are no filters. - return nullptr; - } - - // For now, use the first filter in the chain. Later, nsSVGFilterInstance will - // receive the exact filter that it should use, instead of choosing one from a - // chain of filters. - const nsStyleFilter& filter = mFilters[0]; - if (filter.GetType() != NS_STYLE_FILTER_URL) { + if (mFilter.GetType() != NS_STYLE_FILTER_URL) { // The filter is not an SVG reference filter. return nullptr; } - nsIURI* url = filter.GetURL(); + nsIURI* url = mFilter.GetURL(); if (!url) { NS_NOTREACHED("an nsStyleFilter of type URL should have a non-null URL"); return nullptr; @@ -364,13 +233,6 @@ nsSVGFilterInstance::UserSpaceToFilterSpace(const gfxRect& aRect) const return r; } -gfxPoint -nsSVGFilterInstance::FilterSpaceToUserSpace(const gfxPoint& aPt) const -{ - return gfxPoint(aPt.x * mFilterRegion.Width() / mFilterSpaceBounds.width + mFilterRegion.X(), - aPt.y * mFilterRegion.Height() / mFilterSpaceBounds.height + mFilterRegion.Y()); -} - gfxMatrix nsSVGFilterInstance::GetUserSpaceToFilterSpaceTransform() const { @@ -383,6 +245,7 @@ nsSVGFilterInstance::GetUserSpaceToFilterSpaceTransform() const IntRect nsSVGFilterInstance::ComputeFilterPrimitiveSubregion(nsSVGFE* aFilterElement, + const nsTArray& aPrimitiveDescrs, const nsTArray& aInputIndices) { nsSVGFE* fE = aFilterElement; @@ -392,7 +255,7 @@ nsSVGFilterInstance::ComputeFilterPrimitiveSubregion(nsSVGFE* aFilterElement, for (uint32_t i = 0; i < aInputIndices.Length(); ++i) { int32_t inputIndex = aInputIndices[i]; IntRect inputSubregion = inputIndex >= 0 ? - mPrimitiveDescriptions[inputIndex].PrimitiveSubregion() : + aPrimitiveDescrs[inputIndex].PrimitiveSubregion() : ToIntRect(mFilterSpaceBounds); defaultFilterSubregion = defaultFilterSubregion.Union(inputSubregion); @@ -423,7 +286,8 @@ nsSVGFilterInstance::ComputeFilterPrimitiveSubregion(nsSVGFE* aFilterElement, } void -nsSVGFilterInstance::GetInputsAreTainted(const nsTArray& aInputIndices, +nsSVGFilterInstance::GetInputsAreTainted(const nsTArray& aPrimitiveDescrs, + const nsTArray& aInputIndices, nsTArray& aOutInputsAreTainted) { for (uint32_t i = 0; i < aInputIndices.Length(); i++) { @@ -432,7 +296,7 @@ nsSVGFilterInstance::GetInputsAreTainted(const nsTArray& aInputIndices, // SourceGraphic, SourceAlpha, FillPaint and StrokePaint are tainted. aOutInputsAreTainted.AppendElement(true); } else { - aOutInputsAreTainted.AppendElement(mPrimitiveDescriptions[inputIndex].IsTainted()); + aOutInputsAreTainted.AppendElement(aPrimitiveDescrs[inputIndex].IsTainted()); } } } @@ -479,7 +343,8 @@ GetSourceIndices(nsSVGFE* aFilterElement, } nsresult -nsSVGFilterInstance::BuildPrimitives() +nsSVGFilterInstance::BuildPrimitives(nsTArray& aPrimitiveDescrs, + nsTArray>& aInputImages) { nsTArray > primitives; for (nsIContent* child = mFilterElement->nsINode::GetFirstChild(); @@ -508,13 +373,13 @@ nsSVGFilterInstance::BuildPrimitives() } IntRect primitiveSubregion = - ComputeFilterPrimitiveSubregion(filter, sourceIndices); + ComputeFilterPrimitiveSubregion(filter, aPrimitiveDescrs, sourceIndices); nsTArray sourcesAreTainted; - GetInputsAreTainted(sourceIndices, sourcesAreTainted); + GetInputsAreTainted(aPrimitiveDescrs, sourceIndices, sourcesAreTainted); FilterPrimitiveDescription descr = - filter->GetPrimitiveDescription(this, primitiveSubregion, sourcesAreTainted, mInputImages); + filter->GetPrimitiveDescription(this, primitiveSubregion, sourcesAreTainted, aInputImages); descr.SetIsTainted(filter->OutputIsTainted(sourcesAreTainted, principal)); descr.SetPrimitiveSubregion(primitiveSubregion); @@ -523,7 +388,7 @@ nsSVGFilterInstance::BuildPrimitives() int32_t inputIndex = sourceIndices[j]; descr.SetInputPrimitive(j, inputIndex); ColorSpace inputColorSpace = - inputIndex < 0 ? SRGB : mPrimitiveDescriptions[inputIndex].OutputColorSpace(); + inputIndex < 0 ? SRGB : aPrimitiveDescrs[inputIndex].OutputColorSpace(); ColorSpace desiredInputColorSpace = filter->GetInputColorSpace(j, inputColorSpace); descr.SetInputColorSpace(j, desiredInputColorSpace); if (j == 0) { @@ -536,7 +401,7 @@ nsSVGFilterInstance::BuildPrimitives() descr.SetOutputColorSpace(filter->GetOutputColorSpace()); } - mPrimitiveDescriptions.AppendElement(descr); + aPrimitiveDescrs.AppendElement(descr); nsAutoString str; filter->GetResultImageName().GetAnimValue(str, filter); @@ -545,401 +410,3 @@ nsSVGFilterInstance::BuildPrimitives() return NS_OK; } - -void -nsSVGFilterInstance::ComputeNeededBoxes() -{ - if (mPrimitiveDescriptions.IsEmpty()) - return; - - nsIntRegion sourceGraphicNeededRegion; - nsIntRegion fillPaintNeededRegion; - nsIntRegion strokePaintNeededRegion; - - FilterDescription filter(mPrimitiveDescriptions, ToIntRect(mFilterSpaceBounds)); - FilterSupport::ComputeSourceNeededRegions( - filter, mPostFilterDirtyRect, - sourceGraphicNeededRegion, fillPaintNeededRegion, strokePaintNeededRegion); - - nsIntRect sourceBoundsInt; - gfxRect sourceBounds = UserSpaceToFilterSpace(mTargetBBox); - sourceBounds.RoundOut(); - // Detect possible float->int overflow - if (!gfxUtils::GfxRectToIntRect(sourceBounds, &sourceBoundsInt)) - return; - sourceBoundsInt.UnionRect(sourceBoundsInt, mTargetBounds); - - sourceGraphicNeededRegion.And(sourceGraphicNeededRegion, sourceBoundsInt); - - mSourceGraphic.mNeededBounds = sourceGraphicNeededRegion.GetBounds(); - mFillPaint.mNeededBounds = fillPaintNeededRegion.GetBounds(); - mStrokePaint.mNeededBounds = strokePaintNeededRegion.GetBounds(); -} - -nsresult -nsSVGFilterInstance::BuildSourcePaint(SourceInfo *aSource, - gfxASurface* aTargetSurface, - DrawTarget* aTargetDT) -{ - nsIntRect neededRect = aSource->mNeededBounds; - - RefPtr offscreenDT; - nsRefPtr offscreenSurface; - nsRefPtr ctx; - if (aTargetSurface) { - offscreenSurface = gfxPlatform::GetPlatform()->CreateOffscreenSurface( - neededRect.Size().ToIntSize(), gfxContentType::COLOR_ALPHA); - if (!offscreenSurface || offscreenSurface->CairoStatus()) { - return NS_ERROR_OUT_OF_MEMORY; - } - ctx = new gfxContext(offscreenSurface); - } else { - offscreenDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget( - ToIntSize(neededRect.Size()), SurfaceFormat::B8G8R8A8); - if (!offscreenDT) { - return NS_ERROR_OUT_OF_MEMORY; - } - ctx = new gfxContext(offscreenDT); - } - - ctx->Translate(-neededRect.TopLeft()); - - nsRenderingContext tmpCtx; - tmpCtx.Init(mTargetFrame->PresContext()->DeviceContext(), ctx); - - gfxMatrix m = GetUserSpaceToFilterSpaceTransform(); - m.Invert(); - gfxRect r = m.TransformBounds(mFilterSpaceBounds); - - gfxMatrix deviceToFilterSpace = GetFilterSpaceToDeviceSpaceTransform().Invert(); - gfxContext *gfx = tmpCtx.ThebesContext(); - gfx->Multiply(deviceToFilterSpace); - - gfx->Save(); - - gfxMatrix matrix = - nsSVGUtils::GetCanvasTM(mTargetFrame, nsISVGChildFrame::FOR_PAINTING, - mTransformRoot); - if (!matrix.IsSingular()) { - gfx->Multiply(matrix); - gfx->Rectangle(r); - if ((aSource == &mFillPaint && - nsSVGUtils::SetupCairoFillPaint(mTargetFrame, gfx)) || - (aSource == &mStrokePaint && - nsSVGUtils::SetupCairoStrokePaint(mTargetFrame, gfx))) { - gfx->Fill(); - } - } - gfx->Restore(); - - if (offscreenSurface) { - aSource->mSourceSurface = - gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(aTargetDT, offscreenSurface); - } else { - aSource->mSourceSurface = offscreenDT->Snapshot(); - } - aSource->mSurfaceRect = ToIntRect(neededRect); - - return NS_OK; -} - -nsresult -nsSVGFilterInstance::BuildSourcePaints(gfxASurface* aTargetSurface, - DrawTarget* aTargetDT) -{ - nsresult rv = NS_OK; - - if (!mFillPaint.mNeededBounds.IsEmpty()) { - rv = BuildSourcePaint(&mFillPaint, aTargetSurface, aTargetDT); - NS_ENSURE_SUCCESS(rv, rv); - } - - if (!mStrokePaint.mNeededBounds.IsEmpty()) { - rv = BuildSourcePaint(&mStrokePaint, aTargetSurface, aTargetDT); - NS_ENSURE_SUCCESS(rv, rv); - } - return rv; -} - -nsresult -nsSVGFilterInstance::BuildSourceImage(gfxASurface* aTargetSurface, - DrawTarget* aTargetDT) -{ - nsIntRect neededRect = mSourceGraphic.mNeededBounds; - if (neededRect.IsEmpty()) { - return NS_OK; - } - - RefPtr offscreenDT; - nsRefPtr offscreenSurface; - nsRefPtr ctx; - if (aTargetSurface) { - offscreenSurface = gfxPlatform::GetPlatform()->CreateOffscreenSurface( - neededRect.Size().ToIntSize(), gfxContentType::COLOR_ALPHA); - if (!offscreenSurface || offscreenSurface->CairoStatus()) { - return NS_ERROR_OUT_OF_MEMORY; - } - ctx = new gfxContext(offscreenSurface); - } else { - offscreenDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget( - ToIntSize(neededRect.Size()), SurfaceFormat::B8G8R8A8); - if (!offscreenDT) { - return NS_ERROR_OUT_OF_MEMORY; - } - ctx = new gfxContext(offscreenDT); - } - - ctx->Translate(-neededRect.TopLeft()); - - nsRenderingContext tmpCtx; - tmpCtx.Init(mTargetFrame->PresContext()->DeviceContext(), ctx); - - gfxMatrix m = GetUserSpaceToFilterSpaceTransform(); - m.Invert(); - gfxRect r = m.TransformBounds(neededRect); - r.RoundOut(); - nsIntRect dirty; - if (!gfxUtils::GfxRectToIntRect(r, &dirty)) - return NS_ERROR_FAILURE; - - // SVG graphics paint to device space, so we need to set an initial device - // space to filter space transform on the gfxContext that SourceGraphic - // and SourceAlpha will paint to. - // - // (In theory it would be better to minimize error by having filtered SVG - // graphics temporarily paint to user space when painting the sources and - // only set a user space to filter space transform on the gfxContext - // (since that would eliminate the transform multiplications from user - // space to device space and back again). However, that would make the - // code more complex while being hard to get right without introducing - // subtle bugs, and in practice it probably makes no real difference.) - gfxMatrix deviceToFilterSpace = GetFilterSpaceToDeviceSpaceTransform().Invert(); - tmpCtx.ThebesContext()->Multiply(deviceToFilterSpace); - mPaintCallback->Paint(&tmpCtx, mTargetFrame, &dirty, mTransformRoot); - - RefPtr sourceGraphicSource; - - if (offscreenSurface) { - sourceGraphicSource = - gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(aTargetDT, offscreenSurface); - } else { - sourceGraphicSource = offscreenDT->Snapshot(); - } - - mSourceGraphic.mSourceSurface = sourceGraphicSource; - mSourceGraphic.mSurfaceRect = ToIntRect(neededRect); - - return NS_OK; -} - -nsresult -nsSVGFilterInstance::Render(gfxContext* aContext) -{ - nsresult rv = BuildPrimitives(); - if (NS_FAILED(rv)) - return rv; - - if (mPrimitiveDescriptions.IsEmpty()) { - // Nothing should be rendered. - return NS_OK; - } - - nsIntRect filterRect = mPostFilterDirtyRect.Intersect(mFilterSpaceBounds); - gfxMatrix ctm = GetFilterSpaceToDeviceSpaceTransform(); - - if (filterRect.IsEmpty() || ctm.IsSingular()) { - return NS_OK; - } - - Matrix oldDTMatrix; - nsRefPtr resultImage; - RefPtr dt; - if (aContext->IsCairo()) { - resultImage = - gfxPlatform::GetPlatform()->CreateOffscreenSurface(filterRect.Size().ToIntSize(), - gfxContentType::COLOR_ALPHA); - if (!resultImage || resultImage->CairoStatus()) - return NS_ERROR_OUT_OF_MEMORY; - - // Create a Cairo DrawTarget around resultImage. - dt = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface( - resultImage, ToIntSize(filterRect.Size())); - } else { - // When we have a DrawTarget-backed context, we can call DrawFilter - // directly on the target DrawTarget and don't need a temporary DT. - dt = aContext->GetDrawTarget(); - oldDTMatrix = dt->GetTransform(); - Matrix matrix = ToMatrix(ctm); - matrix.Translate(filterRect.x, filterRect.y); - dt->SetTransform(matrix * oldDTMatrix); - } - - ComputeNeededBoxes(); - - rv = BuildSourceImage(resultImage, dt); - if (NS_FAILED(rv)) - return rv; - rv = BuildSourcePaints(resultImage, dt); - if (NS_FAILED(rv)) - return rv; - - IntRect filterSpaceBounds = ToIntRect(mFilterSpaceBounds); - FilterDescription filter(mPrimitiveDescriptions, filterSpaceBounds); - - FilterSupport::RenderFilterDescription( - dt, filter, ToRect(filterRect), - mSourceGraphic.mSourceSurface, mSourceGraphic.mSurfaceRect, - mFillPaint.mSourceSurface, mFillPaint.mSurfaceRect, - mStrokePaint.mSourceSurface, mStrokePaint.mSurfaceRect, - mInputImages); - - if (resultImage) { - aContext->Save(); - aContext->Multiply(ctm); - aContext->Translate(filterRect.TopLeft()); - aContext->SetSource(resultImage); - aContext->Paint(); - aContext->Restore(); - } else { - dt->SetTransform(oldDTMatrix); - } - - return NS_OK; -} - -nsresult -nsSVGFilterInstance::ComputePostFilterDirtyRect(nsRect* aPostFilterDirtyRect) -{ - *aPostFilterDirtyRect = nsRect(); - if (mPreFilterDirtyRect.IsEmpty()) { - return NS_OK; - } - - nsresult rv = BuildPrimitives(); - if (NS_FAILED(rv)) - return rv; - - if (mPrimitiveDescriptions.IsEmpty()) { - // Nothing should be rendered, so nothing can be dirty. - return NS_OK; - } - - IntRect filterSpaceBounds = ToIntRect(mFilterSpaceBounds); - FilterDescription filter(mPrimitiveDescriptions, filterSpaceBounds); - nsIntRegion resultChangeRegion = - FilterSupport::ComputeResultChangeRegion(filter, - mPreFilterDirtyRect, nsIntRegion(), nsIntRegion()); - *aPostFilterDirtyRect = - FilterSpaceToFrameSpace(resultChangeRegion.GetBounds()); - return NS_OK; -} - -nsresult -nsSVGFilterInstance::ComputePostFilterExtents(nsRect* aPostFilterExtents) -{ - *aPostFilterExtents = nsRect(); - - nsresult rv = BuildPrimitives(); - if (NS_FAILED(rv)) - return rv; - - if (mPrimitiveDescriptions.IsEmpty()) { - return NS_OK; - } - - nsIntRect sourceBoundsInt; - gfxRect sourceBounds = UserSpaceToFilterSpace(mTargetBBox); - sourceBounds.RoundOut(); - // Detect possible float->int overflow - if (!gfxUtils::GfxRectToIntRect(sourceBounds, &sourceBoundsInt)) - return NS_ERROR_FAILURE; - sourceBoundsInt.UnionRect(sourceBoundsInt, mTargetBounds); - - IntRect filterSpaceBounds = ToIntRect(mFilterSpaceBounds); - FilterDescription filter(mPrimitiveDescriptions, filterSpaceBounds); - nsIntRegion postFilterExtents = - FilterSupport::ComputePostFilterExtents(filter, sourceBoundsInt); - *aPostFilterExtents = FilterSpaceToFrameSpace(postFilterExtents.GetBounds()); - return NS_OK; -} - -nsresult -nsSVGFilterInstance::ComputeSourceNeededRect(nsRect* aDirty) -{ - nsresult rv = BuildPrimitives(); - if (NS_FAILED(rv)) - return rv; - - if (mPrimitiveDescriptions.IsEmpty()) { - // Nothing should be rendered, so nothing is needed. - return NS_OK; - } - - ComputeNeededBoxes(); - *aDirty = FilterSpaceToFrameSpace(mSourceGraphic.mNeededBounds); - - return NS_OK; -} - -nsIntRect -nsSVGFilterInstance::FrameSpaceToFilterSpace(const nsRect* aRect) const -{ - nsIntRect rect = mFilterSpaceBounds; - if (aRect) { - if (aRect->IsEmpty()) { - return nsIntRect(); - } - gfxRect rectInCSSPx = - nsLayoutUtils::RectToGfxRect(*aRect, mAppUnitsPerCSSPx); - gfxRect rectInFilterSpace = - mFrameSpaceInCSSPxToFilterSpaceTransform.TransformBounds(rectInCSSPx); - rectInFilterSpace.RoundOut(); - nsIntRect intRect; - if (gfxUtils::GfxRectToIntRect(rectInFilterSpace, &intRect)) { - rect = intRect; - } - } - return rect; -} - -nsRect -nsSVGFilterInstance::FilterSpaceToFrameSpace(const nsIntRect& aRect) const -{ - if (aRect.IsEmpty()) { - return nsRect(); - } - gfxRect r(aRect.x, aRect.y, aRect.width, aRect.height); - r = mFilterSpaceToFrameSpaceInCSSPxTransform.TransformBounds(r); - return nsLayoutUtils::RoundGfxRectToAppRect(r, mAppUnitsPerCSSPx); -} - -gfxMatrix -nsSVGFilterInstance::GetUserSpaceToFrameSpaceInCSSPxTransform() const -{ - gfxMatrix userToFrameSpaceInCSSPx; - - if ((mTargetFrame->GetStateBits() & NS_FRAME_SVG_LAYOUT)) { - // As currently implemented by Mozilla for the purposes of filters, user - // space is the coordinate system established by GetCanvasTM(), since - // that's what we use to set filterToDeviceSpace above. In other words, - // for SVG, user space is actually the coordinate system aTarget - // establishes for _its_ children (i.e. after taking account of any x/y - // and viewBox attributes), not the coordinate system that is established - // for it by its 'transform' attribute (or by its _parent_) as it's - // normally defined. (XXX We should think about fixing this.) The only - // frame type for which these extra transforms are not simply an x/y - // translation is nsSVGInnerSVGFrame, hence we treat it specially here. - if (mTargetFrame->GetType() == nsGkAtoms::svgInnerSVGFrame) { - userToFrameSpaceInCSSPx = - static_cast(mTargetFrame->GetContent())-> - PrependLocalTransformsTo(gfxMatrix()); - } else { - gfxPoint targetsUserSpaceOffset = - nsLayoutUtils::RectToGfxRect(mTargetFrame->GetRect(), - mAppUnitsPerCSSPx).TopLeft(); - userToFrameSpaceInCSSPx.Translate(-targetsUserSpaceOffset); - } - } - // else, for all other frames, leave as the identity matrix - return userToFrameSpaceInCSSPx; -} diff --git a/layout/svg/nsSVGFilterInstance.h b/layout/svg/nsSVGFilterInstance.h index 8d578fc91b1e..496099af707f 100644 --- a/layout/svg/nsSVGFilterInstance.h +++ b/layout/svg/nsSVGFilterInstance.h @@ -7,22 +7,13 @@ #define __NS_SVGFILTERINSTANCE_H__ #include "gfxMatrix.h" -#include "gfxPoint.h" #include "gfxRect.h" -#include "nsCOMPtr.h" -#include "nsHashKeys.h" -#include "nsPoint.h" -#include "nsRect.h" -#include "nsSize.h" #include "nsSVGFilters.h" #include "nsSVGNumber2.h" #include "nsSVGNumberPair.h" #include "nsTArray.h" #include "nsIFrame.h" -#include "mozilla/gfx/2D.h" -class gfxASurface; -class gfxImageSurface; class nsIFrame; class nsSVGFilterFrame; class nsSVGFilterPaintCallback; @@ -34,103 +25,45 @@ class SVGFilterElement; } /** - * This class performs all filter processing. - * - * We build a graph of the filter image data flow, essentially - * converting the filter graph to SSA. This lets us easily propagate - * analysis data (such as bounding-boxes) over the filter primitive graph. + * This class helps nsFilterInstance build its filter graph by processing a + * single SVG reference filter. * - * Definition of "filter space": filter space is a coordinate system that is - * aligned with the user space of the filtered element, with its origin located - * at the top left of the filter region (as specified by our ctor's - * aFilterRegion, and returned by our GetFilterRegion, specifically), and with - * one unit equal in size to one pixel of the offscreen surface into which the - * filter output would/will be painted. - * - * The definition of "filter region" can be found here: - * http://www.w3.org/TR/SVG11/filters.html#FilterEffectsRegion + * In BuildPrimitives, this class iterates through the referenced + * element's primitive elements, creating a FilterPrimitiveDescription for + * each one. */ class nsSVGFilterInstance { typedef mozilla::gfx::Point3D Point3D; typedef mozilla::gfx::IntRect IntRect; typedef mozilla::gfx::SourceSurface SourceSurface; - typedef mozilla::gfx::DrawTarget DrawTarget; typedef mozilla::gfx::FilterPrimitiveDescription FilterPrimitiveDescription; public: /** - * Paint the given filtered frame. - * @param aDirtyArea The area than needs to be painted, in aFilteredFrame's - * frame space (i.e. relative to its origin, the top-left corner of its - * border box). - */ - static nsresult PaintFilteredFrame(nsRenderingContext *aContext, - nsIFrame *aFilteredFrame, - nsSVGFilterPaintCallback *aPaintCallback, - const nsRect* aDirtyArea, - nsIFrame* aTransformRoot = nullptr); - - /** - * Returns the post-filter area that could be dirtied when the given - * pre-filter area of aFilteredFrame changes. - * @param aPreFilterDirtyRect The pre-filter area of aFilteredFrame that has - * changed, relative to aFilteredFrame, in app units. - */ - static nsRect GetPostFilterDirtyArea(nsIFrame *aFilteredFrame, - const nsRect& aPreFilterDirtyRect); - - /** - * Returns the pre-filter area that is needed from aFilteredFrame when the - * given post-filter area needs to be repainted. - * @param aPostFilterDirtyRect The post-filter area that is dirty, relative - * to aFilteredFrame, in app units. - */ - static nsRect GetPreFilterNeededArea(nsIFrame *aFilteredFrame, - const nsRect& aPostFilterDirtyRect); - - /** - * Returns the post-filter visual overflow rect (paint bounds) of - * aFilteredFrame. - * @param aOverrideBBox A user space rect, in user units, that should be used - * as aFilteredFrame's bbox ('bbox' is a specific SVG term), if non-null. - * @param aPreFilterBounds The pre-filter visual overflow rect of - * aFilteredFrame, if non-null. - */ - static nsRect GetPostFilterBounds(nsIFrame *aFilteredFrame, - const gfxRect *aOverrideBBox = nullptr, - const nsRect *aPreFilterBounds = nullptr); - - /** + * @param aFilter The SVG reference filter to process. * @param aTargetFrame The frame of the filtered element under consideration. - * @param aFilters The CSS and SVG filter chain from the style system. - * @param aPaintCallback [optional] The callback that Render() should use to - * paint. Only required if you will call Render(). - * @param aPostFilterDirtyRect [optional] The bounds of the post-filter area - * that has to be repainted, in filter space. Only required if you will - * call ComputeSourceNeededRect() or Render(). - * @param aPreFilterDirtyRect [optional] The bounds of the pre-filter area of - * the filtered element that changed, in filter space. Only required if you - * will call ComputePostFilterDirtyRect(). - * @param aOverridePreFilterVisualOverflowRect [optional] Use a different - * visual overflow rect for the target element. - * @param aOverrideBBox [optional] Use a different SVG bbox for the target - * element. - * @param aTransformRoot [optional] The transform root frame for painting. + * @param aTargetBBox The SVG bbox to use for the target frame, computed by + * the caller. The caller may decide to override the actual SVG bbox. */ - nsSVGFilterInstance(nsIFrame *aTargetFrame, - nsSVGFilterPaintCallback *aPaintCallback, - const nsRect *aPostFilterDirtyRect = nullptr, - const nsRect *aPreFilterDirtyRect = nullptr, - const nsRect *aOverridePreFilterVisualOverflowRect = nullptr, - const gfxRect *aOverrideBBox = nullptr, - nsIFrame* aTransformRoot = nullptr); + nsSVGFilterInstance(const nsStyleFilter& aFilter, + nsIFrame *aTargetFrame, + const gfxRect& aTargetBBox); /** * Returns true if the filter instance was created successfully. */ bool IsInitialized() const { return mInitialized; } + /** + * Iterates through the element's primitive elements, creating a + * FilterPrimitiveDescription for each one. Appends the new + * FilterPrimitiveDescription(s) to the aPrimitiveDescrs list. Also, appends + * new images from feImage filter primitive elements to the aInputImages list. + */ + nsresult BuildPrimitives(nsTArray& aPrimitiveDescrs, + nsTArray>& aInputImages); + /** * Returns the user specified "filter region", in the filtered element's user * space, after it has been adjusted out (if necessary) so that its edges @@ -143,47 +76,9 @@ public: * Returns the size of the user specified "filter region", in filter space. * The size will be {filterRes.x by filterRes.y}, whether the user specified * the filter's filterRes attribute explicitly, or the implementation chose - * the filterRes values. (The top-left of the filter region is the origin of - * filter space, which is why this method returns an nsIntSize and not an - * nsIntRect.) + * the filterRes values. */ - uint32_t GetFilterResX() const { return mFilterSpaceBounds.width; } - uint32_t GetFilterResY() const { return mFilterSpaceBounds.height; } - - /** - * Draws the filter output into aContext. The area that - * needs to be painted must have been specified before calling this method - * by passing it as the aPostFilterDirtyRect argument to the - * nsSVGFilterInstance constructor. - */ - nsresult Render(gfxContext* aContext); - - /** - * Sets the aPostFilterDirtyRect outparam to the post-filter bounds in frame - * space of the area that would be dirtied by mTargetFrame when a given - * pre-filter area of mTargetFrame is dirtied. The pre-filter area must have - * been specified before calling this method by passing it as the - * aPreFilterDirtyRect argument to the nsSVGFilterInstance constructor. - */ - nsresult ComputePostFilterDirtyRect(nsRect* aPostFilterDirtyRect); - - /** - * Sets the aPostFilterExtents outparam to the post-filter bounds in frame - * space for the whole filter output. This is not necessarily equivalent to - * the area that would be dirtied in the result when the entire pre-filter - * area is dirtied, because some filter primitives can generate output - * without any input. - */ - nsresult ComputePostFilterExtents(nsRect* aPostFilterExtents); - - /** - * Sets the aDirty outparam to the pre-filter bounds in frame space of the - * area of mTargetFrame that is needed in order to paint the filtered output - * for a given post-filter dirtied area. The post-filter area must have been - * specified before calling this method by passing it as the aPostFilterDirtyRect - * argument to the nsSVGFilterInstance constructor. - */ - nsresult ComputeSourceNeededRect(nsRect* aDirty); + nsIntRect GetFilterSpaceBounds() const { return mFilterSpaceBounds; } float GetPrimitiveNumber(uint8_t aCtxType, const nsSVGNumber2 *aNumber) const { @@ -208,96 +103,25 @@ public: */ gfxMatrix GetUserSpaceToFilterSpaceTransform() const; - /** - * Returns the transform from filter space to outer- device space. - */ - gfxMatrix GetFilterSpaceToDeviceSpaceTransform() const { - return mFilterSpaceToDeviceSpaceTransform; - } - - gfxPoint FilterSpaceToUserSpace(const gfxPoint& aPt) const; - - /** - * Returns the transform from filter space to frame space, in CSS px. This - * transform does not transform to frame space in its normal app units, since - * app units are ints, requiring appropriate rounding which can't be done by - * a transform matrix. Callers have to do that themselves as appropriate for - * their needs. - */ - gfxMatrix GetFilterSpaceToFrameSpaceInCSSPxTransform() const { - return mFilterSpaceToFrameSpaceInCSSPxTransform; - } - - int32_t AppUnitsPerCSSPixel() const { return mAppUnitsPerCSSPx; } - private: - struct SourceInfo { - // Specifies which parts of the source need to be rendered. - // Set by ComputeNeededBoxes(). - nsIntRect mNeededBounds; - - // The surface that contains the input rendering. - // Set by BuildSourceImage / BuildSourcePaint. - mozilla::RefPtr mSourceSurface; - - // The position and size of mSourceSurface in filter space. - // Set by BuildSourceImage / BuildSourcePaint. - IntRect mSurfaceRect; - }; - - /** - * Creates a SourceSurface for either the FillPaint or StrokePaint graph - * nodes - */ - nsresult BuildSourcePaint(SourceInfo *aPrimitive, - gfxASurface* aTargetSurface, - DrawTarget* aTargetDT); - - /** - * Creates a SourceSurface for either the FillPaint and StrokePaint graph - * nodes, fills its contents and assigns it to mFillPaint.mSourceSurface and - * mStrokePaint.mSourceSurface respectively. - */ - nsresult BuildSourcePaints(gfxASurface* aTargetSurface, - DrawTarget* aTargetDT); - - /** - * Creates the SourceSurface for the SourceGraphic graph node, paints its - * contents, and assigns it to mSourceGraphic.mSourceSurface. - */ - nsresult BuildSourceImage(gfxASurface* aTargetSurface, - DrawTarget* aTargetDT); - /** * Finds the filter frame associated with this SVG filter. */ nsSVGFilterFrame* GetFilterFrame(); - /** - * Build the list of FilterPrimitiveDescriptions that describes the filter's - * filter primitives and their connections. This populates - * mPrimitiveDescriptions and mInputImages. - */ - nsresult BuildPrimitives(); - - /** - * Computes the filter space bounds of the areas that we actually *need* from - * the filter sources, based on the value of mPostFilterDirtyRect. - * This sets mNeededBounds on the corresponding SourceInfo structs. - */ - void ComputeNeededBoxes(); - /** * Computes the filter primitive subregion for the given primitive. */ IntRect ComputeFilterPrimitiveSubregion(nsSVGFE* aFilterElement, + const nsTArray& aPrimitiveDescrs, const nsTArray& aInputIndices); /** * Takes the input indices of a filter primitive and returns for each input * whether the input's output is tainted. */ - void GetInputsAreTainted(const nsTArray& aInputIndices, + void GetInputsAreTainted(const nsTArray& aPrimitiveDescrs, + const nsTArray& aInputIndices, nsTArray& aOutInputsAreTainted); /** @@ -308,15 +132,6 @@ private: gfxRect UserSpaceToFilterSpace(const gfxRect& aUserSpace) const; - /** - * Converts an nsRect that is relative to a filtered frame's origin (i.e. the - * top-left corner of its border box) into filter space. - * Returns the entire filter region if aRect is null, or if the result is too - * large to be stored in an nsIntRect. - */ - nsIntRect FrameSpaceToFilterSpace(const nsRect* aRect) const; - nsRect FilterSpaceToFrameSpace(const nsIntRect& aRect) const; - /** * Returns the transform from frame space to the coordinate space that * GetCanvasTM transforms to. "Frame space" is the origin of a frame, aka the @@ -324,18 +139,16 @@ private: */ gfxMatrix GetUserSpaceToFrameSpaceInCSSPxTransform() const; + /** + * The SVG reference filter originally from the style system. + */ + const nsStyleFilter mFilter; + /** * The frame for the element that is currently being filtered. */ nsIFrame* mTargetFrame; - /** - * The CSS and SVG filter chain from the style system. - */ - const nsTArray mFilters; - - nsSVGFilterPaintCallback* mPaintCallback; - /** * The filter element referenced by mTargetFrame's element. */ @@ -351,56 +164,17 @@ private: */ gfxRect mTargetBBox; - /** - * The transform from filter space to outer- device space. - */ - gfxMatrix mFilterSpaceToDeviceSpaceTransform; - - /** - * Transform rects between filter space and frame space in CSS pixels. - */ - gfxMatrix mFilterSpaceToFrameSpaceInCSSPxTransform; - gfxMatrix mFrameSpaceInCSSPxToFilterSpaceTransform; - /** * The "filter region", in the filtered element's user space. */ gfxRect mFilterRegion; nsIntRect mFilterSpaceBounds; - /** - * Pre-filter paint bounds of the element that is being filtered, in filter - * space. - */ - nsIntRect mTargetBounds; - - /** - * If set, this is the filter space bounds of the outer- device space - * bounds of the dirty area that needs to be repainted. (As bounds-of-bounds, - * this may be a fair bit bigger than we actually need, unfortunately.) - */ - nsIntRect mPostFilterDirtyRect; - - /** - * If set, this is the filter space bounds of the outer- device bounds - * of the pre-filter area of the filtered element that changed. (As - * bounds-of-bounds, this may be a fair bit bigger than we actually need, - * unfortunately.) - */ - nsIntRect mPreFilterDirtyRect; - /** * The 'primitiveUnits' attribute value (objectBoundingBox or userSpaceOnUse). */ uint16_t mPrimitiveUnits; - SourceInfo mSourceGraphic; - SourceInfo mFillPaint; - SourceInfo mStrokePaint; - nsIFrame* mTransformRoot; - nsTArray> mInputImages; - nsTArray mPrimitiveDescriptions; - int32_t mAppUnitsPerCSSPx; bool mInitialized; }; diff --git a/layout/svg/nsSVGIntegrationUtils.cpp b/layout/svg/nsSVGIntegrationUtils.cpp index 31737ad140f1..131c2da5c6d4 100644 --- a/layout/svg/nsSVGIntegrationUtils.cpp +++ b/layout/svg/nsSVGIntegrationUtils.cpp @@ -10,12 +10,12 @@ #include "gfxDrawable.h" #include "nsCSSAnonBoxes.h" #include "nsDisplayList.h" +#include "nsFilterInstance.h" #include "nsLayoutUtils.h" #include "nsRenderingContext.h" #include "nsSVGClipPathFrame.h" #include "nsSVGEffects.h" #include "nsSVGElement.h" -#include "nsSVGFilterInstance.h" #include "nsSVGFilterPaintCallback.h" #include "nsSVGMaskFrame.h" #include "nsSVGPaintServerFrame.h" @@ -275,7 +275,7 @@ nsRect overrideBBox.RoundOut(); nsRect overflowRect = - nsSVGFilterInstance::GetPostFilterBounds(firstFrame, &overrideBBox); + nsFilterInstance::GetPostFilterBounds(firstFrame, &overrideBBox); // Return overflowRect relative to aFrame, rather than "user space": return overflowRect - (aFrame->GetOffsetTo(firstFrame) + firstFrameToUserSpace); @@ -320,7 +320,7 @@ nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(nsIFrame* aFrame, // Adjust the dirty area for effects, and shift it back to being relative to // the reference frame. - nsRect result = nsSVGFilterInstance::GetPostFilterDirtyArea(firstFrame, + nsRect result = nsFilterInstance::GetPostFilterDirtyArea(firstFrame, preEffectsRect) - toUserSpace; // Return the result, in pixels relative to the reference frame. return result.ToOutsidePixels(appUnitsPerDevPixel); @@ -345,8 +345,8 @@ nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(nsIFrame* aFrame, nsRect postEffectsRect = aDirtyRect + toUserSpace; // Return ther result, relative to aFrame, not in user space: - return nsSVGFilterInstance::GetPreFilterNeededArea(firstFrame, - postEffectsRect) - toUserSpace; + return nsFilterInstance::GetPreFilterNeededArea(firstFrame, postEffectsRect) + - toUserSpace; } bool @@ -510,7 +510,7 @@ nsSVGIntegrationUtils::PaintFramesWithEffects(nsRenderingContext* aCtx, RegularFramePaintCallback callback(aBuilder, aLayerManager, offsetWithoutSVGGeomFramePos); nsRect dirtyRect = aDirtyRect - offset; - nsSVGFilterInstance::PaintFilteredFrame(aCtx, aFrame, &callback, &dirtyRect); + nsFilterInstance::PaintFilteredFrame(aCtx, aFrame, &callback, &dirtyRect); } else { gfx->SetMatrix(matrixAutoSaveRestore.Matrix()); aLayerManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer, aBuilder); diff --git a/layout/svg/nsSVGUtils.cpp b/layout/svg/nsSVGUtils.cpp index fd0e4936db4f..77b02b25d61b 100644 --- a/layout/svg/nsSVGUtils.cpp +++ b/layout/svg/nsSVGUtils.cpp @@ -20,6 +20,7 @@ #include "mozilla/Preferences.h" #include "nsCSSFrameConstructor.h" #include "nsDisplayList.h" +#include "nsFilterInstance.h" #include "nsFrameList.h" #include "nsGkAtoms.h" #include "nsIContent.h" @@ -35,7 +36,6 @@ #include "nsSVGClipPathFrame.h" #include "nsSVGContainerFrame.h" #include "nsSVGEffects.h" -#include "nsSVGFilterInstance.h" #include "nsSVGFilterPaintCallback.h" #include "nsSVGForeignObjectFrame.h" #include "gfxSVGGlyphs.h" @@ -164,7 +164,7 @@ nsSVGUtils::GetPostFilterVisualOverflowRect(nsIFrame *aFrame, return aPreFilterRect; } - return nsSVGFilterInstance::GetPostFilterBounds(aFrame, nullptr, &aPreFilterRect); + return nsFilterInstance::GetPostFilterBounds(aFrame, nullptr, &aPreFilterRect); } bool @@ -621,8 +621,8 @@ nsSVGUtils::PaintFrameWithEffects(nsRenderingContext *aContext, dirtyRect = &tmpDirtyRect; } SVGPaintCallback paintCallback; - nsSVGFilterInstance::PaintFilteredFrame(aContext, aFrame, &paintCallback, - dirtyRect, aTransformRoot); + nsFilterInstance::PaintFilteredFrame(aContext, aFrame, &paintCallback, + dirtyRect, aTransformRoot); } else { svgChildFrame->PaintSVG(aContext, aDirtyRect, aTransformRoot); } From 0f87ca573ec5557bb5a27b4002339f345dfec6a4 Mon Sep 17 00:00:00 2001 From: Alex Xu Date: Mon, 24 Feb 2014 10:22:59 -0500 Subject: [PATCH 28/48] Bug 967927 - Fix Clang build warning in gstreamer. r=eflores --- content/media/gstreamer/GStreamerAllocator.cpp | 4 ++++ content/media/gstreamer/GStreamerMozVideoBuffer.cpp | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/content/media/gstreamer/GStreamerAllocator.cpp b/content/media/gstreamer/GStreamerAllocator.cpp index e5e32da30a67..fd8dee2409b7 100644 --- a/content/media/gstreamer/GStreamerAllocator.cpp +++ b/content/media/gstreamer/GStreamerAllocator.cpp @@ -46,8 +46,12 @@ typedef struct GstVideoBufferPool pool; } MozGfxBufferPool; +// working around GTK+ bug https://bugzilla.gnome.org/show_bug.cgi?id=723899 +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" G_DEFINE_TYPE(MozGfxMemoryAllocator, moz_gfx_memory_allocator, GST_TYPE_ALLOCATOR); G_DEFINE_TYPE(MozGfxBufferPool, moz_gfx_buffer_pool, GST_TYPE_VIDEO_BUFFER_POOL); +#pragma clang diagnostic pop void moz_gfx_memory_reset(MozGfxMemory *mem) diff --git a/content/media/gstreamer/GStreamerMozVideoBuffer.cpp b/content/media/gstreamer/GStreamerMozVideoBuffer.cpp index 411dedda4817..44946d6162df 100644 --- a/content/media/gstreamer/GStreamerMozVideoBuffer.cpp +++ b/content/media/gstreamer/GStreamerMozVideoBuffer.cpp @@ -14,7 +14,11 @@ namespace mozilla { static GstMozVideoBuffer *gst_moz_video_buffer_copy(GstMozVideoBuffer* self); static void gst_moz_video_buffer_finalize(GstMozVideoBuffer* self); +// working around GTK+ bug https://bugzilla.gnome.org/show_bug.cgi?id=723899 +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" G_DEFINE_TYPE(GstMozVideoBuffer, gst_moz_video_buffer, GST_TYPE_BUFFER); +#pragma clang diagnostic pop static void gst_moz_video_buffer_class_init(GstMozVideoBufferClass* klass) From 09c5bf31d9c7df4c717d7d549b4bd53efcf3a179 Mon Sep 17 00:00:00 2001 From: Benjamin Bouvier Date: Mon, 24 Feb 2014 16:23:50 +0100 Subject: [PATCH 29/48] Bug 959119: Take into account the use's index when determining whether a mir node can consume a float32; r=sstangl --- .../jit-test/tests/TypedObject/bug959119.js | 21 +++++++++ js/src/jit/IonAnalysis.cpp | 10 ++--- js/src/jit/MIR.cpp | 2 +- js/src/jit/MIR.h | 45 +++++++++++-------- 4 files changed, 53 insertions(+), 25 deletions(-) create mode 100644 js/src/jit-test/tests/TypedObject/bug959119.js diff --git a/js/src/jit-test/tests/TypedObject/bug959119.js b/js/src/jit-test/tests/TypedObject/bug959119.js new file mode 100644 index 000000000000..f329acc3f3b6 --- /dev/null +++ b/js/src/jit-test/tests/TypedObject/bug959119.js @@ -0,0 +1,21 @@ +// This test exposed a bug in float32 optimization. +// The (inlined and optimized) code for `add()` created +// MDiv instructions specialized to integers, which was +// then "respecialized" to float32, leading to internal +// assertion errors. +// +// Public domain. + +if (!this.hasOwnProperty("TypedObject")) + quit(); + +var {StructType,uint8,float32} = TypedObject; +var RgbColor2 = new StructType({r: uint8, g: float32, b: uint8}); +RgbColor2.prototype.add = function(c) { + this.g += c; + this.b += c; +}; +var gray = new RgbColor2({r: 129, g: 128, b: 127}); +gray.add(1); +gray.add(2); + diff --git a/js/src/jit/IonAnalysis.cpp b/js/src/jit/IonAnalysis.cpp index 33c45b051deb..0cfa76bbe714 100644 --- a/js/src/jit/IonAnalysis.cpp +++ b/js/src/jit/IonAnalysis.cpp @@ -799,7 +799,7 @@ TypeAnalyzer::markPhiConsumers() bool canConsumeFloat32 = true; for (MUseDefIterator use(*phi); canConsumeFloat32 && use; use++) { MDefinition *usedef = use.def(); - canConsumeFloat32 &= usedef->isPhi() || usedef->canConsumeFloat32(); + canConsumeFloat32 &= usedef->isPhi() || usedef->canConsumeFloat32(use.use()); } phi->setCanConsumeFloat32(canConsumeFloat32); if (canConsumeFloat32 && !addPhiToWorklist(*phi)) @@ -812,12 +812,12 @@ TypeAnalyzer::markPhiConsumers() return false; MPhi *phi = popPhi(); - JS_ASSERT(phi->canConsumeFloat32()); + JS_ASSERT(phi->canConsumeFloat32(nullptr /* unused */)); bool validConsumer = true; for (MUseDefIterator use(phi); use; use++) { MDefinition *def = use.def(); - if (def->isPhi() && !def->canConsumeFloat32()) { + if (def->isPhi() && !def->canConsumeFloat32(use.use())) { validConsumer = false; break; } @@ -830,7 +830,7 @@ TypeAnalyzer::markPhiConsumers() phi->setCanConsumeFloat32(false); for (size_t i = 0, e = phi->numOperands(); i < e; ++i) { MDefinition *input = phi->getOperand(i); - if (input->isPhi() && !input->isInWorklist() && input->canConsumeFloat32()) + if (input->isPhi() && !input->isInWorklist() && input->canConsumeFloat32(nullptr /* unused */)) { if (!addPhiToWorklist(input->toPhi())) return false; @@ -976,7 +976,7 @@ TypeAnalyzer::checkFloatCoherency() for (MUseDefIterator use(*def); use; use++) { MDefinition *consumer = use.def(); - JS_ASSERT(consumer->isConsistentFloat32Use()); + JS_ASSERT(consumer->isConsistentFloat32Use(use.use())); } } } diff --git a/js/src/jit/MIR.cpp b/js/src/jit/MIR.cpp index 4de7b6d894bd..7aa215310aaa 100644 --- a/js/src/jit/MIR.cpp +++ b/js/src/jit/MIR.cpp @@ -43,7 +43,7 @@ CheckUsesAreFloat32Consumers(MInstruction *ins) { bool allConsumerUses = true; for (MUseDefIterator use(ins); allConsumerUses && use; use++) - allConsumerUses &= use.def()->canConsumeFloat32(); + allConsumerUses &= use.def()->canConsumeFloat32(use.use()); return allConsumerUses; } diff --git a/js/src/jit/MIR.h b/js/src/jit/MIR.h index 15500ee29039..489aa11b5a13 100644 --- a/js/src/jit/MIR.h +++ b/js/src/jit/MIR.h @@ -470,12 +470,12 @@ class MDefinition : public MNode // specialization algorithm). virtual bool isFloat32Commutative() const { return false; } virtual bool canProduceFloat32() const { return false; } - virtual bool canConsumeFloat32() const { return false; } + virtual bool canConsumeFloat32(MUse *use) const { return false; } virtual void trySpecializeFloat32(TempAllocator &alloc) {} #ifdef DEBUG // Used during the pass that checks that Float32 flow into valid MDefinitions - virtual bool isConsistentFloat32Use() const { - return type() == MIRType_Float32 || canConsumeFloat32(); + virtual bool isConsistentFloat32Use(MUse *use) const { + return type() == MIRType_Float32 || canConsumeFloat32(use); } #endif @@ -1329,7 +1329,7 @@ class MTest return operandMightEmulateUndefined_; } #ifdef DEBUG - bool isConsistentFloat32Use() const { + bool isConsistentFloat32Use(MUse *use) const { return true; } #endif @@ -2060,7 +2060,7 @@ class MAssertFloat32 : public MUnaryInstruction return new(alloc) MAssertFloat32(value, mustBeFloat32); } - bool canConsumeFloat32() const { return true; } + bool canConsumeFloat32(MUse *use) const { return true; } bool mustBeFloat32() const { return mustBeFloat32_; } }; @@ -2336,7 +2336,8 @@ class MCompare bool isOperandTruncated(size_t index) const; # ifdef DEBUG - bool isConsistentFloat32Use() const { + bool isConsistentFloat32Use(MUse *use) const { + // Both sides of the compare can be Float32 return compareType_ == Compare_Float32; } # endif @@ -2902,7 +2903,7 @@ class MToDouble bool isOperandTruncated(size_t index) const; #ifdef DEBUG - bool isConsistentFloat32Use() const { return true; } + bool isConsistentFloat32Use(MUse *use) const { return true; } #endif }; @@ -2961,7 +2962,7 @@ class MToFloat32 void computeRange(TempAllocator &alloc); - bool canConsumeFloat32() const { return true; } + bool canConsumeFloat32(MUse *use) const { return true; } bool canProduceFloat32() const { return true; } }; @@ -3077,7 +3078,7 @@ class MToInt32 void computeRange(TempAllocator &alloc); #ifdef DEBUG - bool isConsistentFloat32Use() const { return true; } + bool isConsistentFloat32Use(MUse *use) const { return true; } #endif }; @@ -3113,7 +3114,7 @@ class MTruncateToInt32 : public MUnaryInstruction void computeRange(TempAllocator &alloc); bool isOperandTruncated(size_t index) const; # ifdef DEBUG - bool isConsistentFloat32Use() const { + bool isConsistentFloat32Use(MUse *use) const { return true; } #endif @@ -4574,7 +4575,7 @@ class MPhi MOZ_FINAL : public MDefinition, public InlineForwardListNode canProduceFloat32_ = can; } - bool canConsumeFloat32() const { + bool canConsumeFloat32(MUse *use) const { return canConsumeFloat32_; } @@ -5666,7 +5667,7 @@ class MNot void trySpecializeFloat32(TempAllocator &alloc); bool isFloat32Commutative() const { return true; } #ifdef DEBUG - bool isConsistentFloat32Use() const { + bool isConsistentFloat32Use(MUse *use) const { return true; } #endif @@ -6358,7 +6359,9 @@ class MStoreTypedArrayElement } bool isOperandTruncated(size_t index) const; - bool canConsumeFloat32() const { return arrayType_ == ScalarTypeDescr::TYPE_FLOAT32; } + bool canConsumeFloat32(MUse *use) const { + return use->index() == 2 && arrayType_ == ScalarTypeDescr::TYPE_FLOAT32; + } }; class MStoreTypedArrayElementHole @@ -6424,7 +6427,9 @@ class MStoreTypedArrayElementHole } bool isOperandTruncated(size_t index) const; - bool canConsumeFloat32() const { return arrayType_ == ScalarTypeDescr::TYPE_FLOAT32; } + bool canConsumeFloat32(MUse *use) const { + return use->index() == 3 && arrayType_ == ScalarTypeDescr::TYPE_FLOAT32; + } }; // Store a value infallibly to a statically known typed array. @@ -6469,7 +6474,9 @@ class MStoreTypedArrayElementStatic : } bool isOperandTruncated(size_t index) const; - bool canConsumeFloat32() const { return typedArray_->type() == ScalarTypeDescr::TYPE_FLOAT32; } + bool canConsumeFloat32(MUse *use) const { + return use->index() == 1 && typedArray_->type() == ScalarTypeDescr::TYPE_FLOAT32; + } }; // Compute an "effective address", i.e., a compound computation of the form: @@ -7857,7 +7864,7 @@ class MSetElementCache return this; } - bool canConsumeFloat32() const { return true; } + bool canConsumeFloat32(MUse *use) const { return use->index() == 2; } }; class MCallGetProperty @@ -8243,7 +8250,7 @@ class MFloor } void trySpecializeFloat32(TempAllocator &alloc); #ifdef DEBUG - bool isConsistentFloat32Use() const { + bool isConsistentFloat32Use(MUse *use) const { return true; } #endif @@ -8888,10 +8895,10 @@ class MPostWriteBarrier return getOperand(1); } #ifdef DEBUG - bool isConsistentFloat32Use() const { + bool isConsistentFloat32Use(MUse *use) const { // During lowering, values that neither have object nor value MIR type // are ignored, thus Float32 can show up at this point without any issue. - return true; + return use->index() == 1; } #endif }; From b49aeb2bf3fb4e2a9d788374845535a16972e151 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Qu=C3=A8ze?= Date: Mon, 24 Feb 2014 16:33:32 +0100 Subject: [PATCH 30/48] Bug 975177 - The WebRTC toolbar icon sometimes stays visible when no device is shared, r=jesup. --- dom/media/MediaManager.cpp | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index 9c67666ad280..e564e883707f 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -1770,17 +1770,33 @@ WindowsHashToArrayFunc (const uint64_t& aId, StreamListeners* aData, void *userArg) { - nsISupportsArray *array = - static_cast(userArg); - nsPIDOMWindow *window = static_cast - (nsGlobalWindow::GetInnerWindowWithId(aId)); - (void) aData; + nsISupportsArray *array = + static_cast(userArg); + nsPIDOMWindow *window = static_cast + (nsGlobalWindow::GetInnerWindowWithId(aId)); - MOZ_ASSERT(window); - if (window) { - array->AppendElement(window); + MOZ_ASSERT(window); + if (window) { + // mActiveWindows contains both windows that have requested device + // access and windows that are currently capturing media. We want + // to return only the latter. See bug 975177. + bool capturing = false; + if (aData) { + uint32_t length = aData->Length(); + for (uint32_t i = 0; i < length; ++i) { + nsRefPtr listener = + aData->ElementAt(i); + if (listener->CapturingVideo() || listener->CapturingAudio()) { + capturing = true; + break; + } + } } - return PL_DHASH_NEXT; + + if (capturing) + array->AppendElement(window); + } + return PL_DHASH_NEXT; } From 76aac23414518e4c2ce16564f74449dff733d19c Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Mon, 24 Feb 2014 10:56:37 -0500 Subject: [PATCH 31/48] Backed out changeset d22ac63d67f1 (bug 967927) for bustage. CLOSED TREE --- content/media/gstreamer/GStreamerAllocator.cpp | 4 ---- content/media/gstreamer/GStreamerMozVideoBuffer.cpp | 4 ---- 2 files changed, 8 deletions(-) diff --git a/content/media/gstreamer/GStreamerAllocator.cpp b/content/media/gstreamer/GStreamerAllocator.cpp index fd8dee2409b7..e5e32da30a67 100644 --- a/content/media/gstreamer/GStreamerAllocator.cpp +++ b/content/media/gstreamer/GStreamerAllocator.cpp @@ -46,12 +46,8 @@ typedef struct GstVideoBufferPool pool; } MozGfxBufferPool; -// working around GTK+ bug https://bugzilla.gnome.org/show_bug.cgi?id=723899 -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-function" G_DEFINE_TYPE(MozGfxMemoryAllocator, moz_gfx_memory_allocator, GST_TYPE_ALLOCATOR); G_DEFINE_TYPE(MozGfxBufferPool, moz_gfx_buffer_pool, GST_TYPE_VIDEO_BUFFER_POOL); -#pragma clang diagnostic pop void moz_gfx_memory_reset(MozGfxMemory *mem) diff --git a/content/media/gstreamer/GStreamerMozVideoBuffer.cpp b/content/media/gstreamer/GStreamerMozVideoBuffer.cpp index 44946d6162df..411dedda4817 100644 --- a/content/media/gstreamer/GStreamerMozVideoBuffer.cpp +++ b/content/media/gstreamer/GStreamerMozVideoBuffer.cpp @@ -14,11 +14,7 @@ namespace mozilla { static GstMozVideoBuffer *gst_moz_video_buffer_copy(GstMozVideoBuffer* self); static void gst_moz_video_buffer_finalize(GstMozVideoBuffer* self); -// working around GTK+ bug https://bugzilla.gnome.org/show_bug.cgi?id=723899 -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-function" G_DEFINE_TYPE(GstMozVideoBuffer, gst_moz_video_buffer, GST_TYPE_BUFFER); -#pragma clang diagnostic pop static void gst_moz_video_buffer_class_init(GstMozVideoBufferClass* klass) From 408b05701cf872cd801ab9f80fc6007f51d6691a Mon Sep 17 00:00:00 2001 From: Romain Perier Date: Mon, 24 Feb 2014 16:39:28 +0100 Subject: [PATCH 32/48] Bug 975373 - IonMonkey: Use MutableHandleValue for out-parameter in vm calls, r=h4writer --- js/src/builtin/RegExp.cpp | 5 ++- js/src/builtin/RegExp.h | 2 +- js/src/jit/BaselineIC.cpp | 12 +++---- js/src/jit/CodeGenerator.cpp | 6 ++-- js/src/jit/ParallelFunctions.cpp | 4 +-- js/src/jit/ParallelFunctions.h | 2 +- js/src/vm/Interpreter-inl.h | 4 +-- js/src/vm/Interpreter.cpp | 56 ++++++++++++++++++-------------- js/src/vm/Interpreter.h | 12 +++---- 9 files changed, 54 insertions(+), 49 deletions(-) diff --git a/js/src/builtin/RegExp.cpp b/js/src/builtin/RegExp.cpp index eebc16ac46e1..e1b02b319658 100644 --- a/js/src/builtin/RegExp.cpp +++ b/js/src/builtin/RegExp.cpp @@ -636,10 +636,9 @@ js::regexp_exec(JSContext *cx, unsigned argc, Value *vp) /* Separate interface for use by IonMonkey. */ bool -js::regexp_exec_raw(JSContext *cx, HandleObject regexp, HandleString input, Value *vp) +js::regexp_exec_raw(JSContext *cx, HandleObject regexp, HandleString input, MutableHandleValue output) { - MutableHandleValue vpHandle = MutableHandleValue::fromMarkedLocation(vp); - return regexp_exec_impl(cx, regexp, input, UpdateRegExpStatics, vpHandle); + return regexp_exec_impl(cx, regexp, input, UpdateRegExpStatics, output); } bool diff --git a/js/src/builtin/RegExp.h b/js/src/builtin/RegExp.h index 7149a8b1f4d1..e92324c290bf 100644 --- a/js/src/builtin/RegExp.h +++ b/js/src/builtin/RegExp.h @@ -45,7 +45,7 @@ CreateRegExpMatchResult(JSContext *cx, HandleString input, const MatchPairs &mat MutableHandleValue rval); extern bool -regexp_exec_raw(JSContext *cx, HandleObject regexp, HandleString input, Value *vp); +regexp_exec_raw(JSContext *cx, HandleObject regexp, HandleString input, MutableHandleValue output); extern bool regexp_exec(JSContext *cx, unsigned argc, Value *vp); diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index 3dc216771b8c..0a4ccc9c761d 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -2481,23 +2481,23 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac switch(op) { case JSOP_ADD: // Do an add. - if (!AddValues(cx, &lhsCopy, &rhsCopy, ret.address())) + if (!AddValues(cx, &lhsCopy, &rhsCopy, ret)) return false; break; case JSOP_SUB: - if (!SubValues(cx, &lhsCopy, &rhsCopy, ret.address())) + if (!SubValues(cx, &lhsCopy, &rhsCopy, ret)) return false; break; case JSOP_MUL: - if (!MulValues(cx, &lhsCopy, &rhsCopy, ret.address())) + if (!MulValues(cx, &lhsCopy, &rhsCopy, ret)) return false; break; case JSOP_DIV: - if (!DivValues(cx, &lhsCopy, &rhsCopy, ret.address())) + if (!DivValues(cx, &lhsCopy, &rhsCopy, ret)) return false; break; case JSOP_MOD: - if (!ModValues(cx, &lhsCopy, &rhsCopy, ret.address())) + if (!ModValues(cx, &lhsCopy, &rhsCopy, ret)) return false; break; case JSOP_BITOR: { @@ -2536,7 +2536,7 @@ DoBinaryArithFallback(JSContext *cx, BaselineFrame *frame, ICBinaryArith_Fallbac break; } case JSOP_URSH: { - if (!UrshOperation(cx, lhs, rhs, ret.address())) + if (!UrshOperation(cx, lhs, rhs, ret)) return false; break; } diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index 02e4ba2f1dfa..58f22f215c1e 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -877,7 +877,7 @@ CodeGenerator::visitRegExp(LRegExp *lir) } typedef bool (*RegExpExecRawFn)(JSContext *cx, HandleObject regexp, - HandleString input, Value *vp); + HandleString input, MutableHandleValue output); static const VMFunction RegExpExecRawInfo = FunctionInfo(regexp_exec_raw); bool @@ -4366,8 +4366,8 @@ CodeGenerator::visitModD(LModD *ins) return true; } -typedef bool (*BinaryFn)(JSContext *, MutableHandleValue, MutableHandleValue, Value *); -typedef bool (*BinaryParFn)(ForkJoinContext *, HandleValue, HandleValue, Value *); +typedef bool (*BinaryFn)(JSContext *, MutableHandleValue, MutableHandleValue, MutableHandleValue); +typedef bool (*BinaryParFn)(ForkJoinContext *, HandleValue, HandleValue, MutableHandleValue); static const VMFunction AddInfo = FunctionInfo(js::AddValues); static const VMFunction SubInfo = FunctionInfo(js::SubValues); diff --git a/js/src/jit/ParallelFunctions.cpp b/js/src/jit/ParallelFunctions.cpp index 6060c55b01a1..6dbb8102814a 100644 --- a/js/src/jit/ParallelFunctions.cpp +++ b/js/src/jit/ParallelFunctions.cpp @@ -541,7 +541,7 @@ jit::BitRshPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, int32_t *o bool jit::UrshValuesPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, - Value *out) + MutableHandleValue out) { uint32_t left; int32_t right; @@ -550,7 +550,7 @@ jit::UrshValuesPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, if (!NonObjectToUint32(cx, lhs, &left) || !NonObjectToInt32(cx, rhs, &right)) return false; left >>= right & 31; - out->setNumber(uint32_t(left)); + out.setNumber(uint32_t(left)); return true; } diff --git a/js/src/jit/ParallelFunctions.h b/js/src/jit/ParallelFunctions.h index 83780f8b1f62..02c9dc02c11e 100644 --- a/js/src/jit/ParallelFunctions.h +++ b/js/src/jit/ParallelFunctions.h @@ -63,7 +63,7 @@ bool BitAndPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, int32_t *o bool BitLshPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, int32_t *out); bool BitRshPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, int32_t *out); -bool UrshValuesPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, Value *out); +bool UrshValuesPar(ForkJoinContext *cx, HandleValue lhs, HandleValue rhs, MutableHandleValue out); // Make a new rest parameter in parallel. JSObject *InitRestParameterPar(ForkJoinContext *cx, uint32_t length, Value *rest, diff --git a/js/src/vm/Interpreter-inl.h b/js/src/vm/Interpreter-inl.h index c51b18c31e1c..05030b3e186c 100644 --- a/js/src/vm/Interpreter-inl.h +++ b/js/src/vm/Interpreter-inl.h @@ -622,14 +622,14 @@ BitRsh(JSContext *cx, HandleValue lhs, HandleValue rhs, int *out) } static MOZ_ALWAYS_INLINE bool -UrshOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *out) +UrshOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, MutableHandleValue out) { uint32_t left; int32_t right; if (!ToUint32(cx, lhs, &left) || !ToInt32(cx, rhs, &right)) return false; left >>= right & 31; - out->setNumber(uint32_t(left)); + out.setNumber(uint32_t(left)); return true; } diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index e59674635136..733d26caf5a3 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -1204,13 +1204,13 @@ ComputeImplicitThis(JSContext *cx, HandleObject obj, MutableHandleValue vp) } static MOZ_ALWAYS_INLINE bool -AddOperation(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res) +AddOperation(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res) { if (lhs.isInt32() && rhs.isInt32()) { int32_t l = lhs.toInt32(), r = rhs.toInt32(); int32_t t; if (MOZ_LIKELY(SafeAdd(l, r, &t))) { - res->setInt32(t); + res.setInt32(t); return true; } } @@ -1247,55 +1247,55 @@ AddOperation(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Valu if (!str) return false; } - res->setString(str); + res.setString(str); } else { double l, r; if (!ToNumber(cx, lhs, &l) || !ToNumber(cx, rhs, &r)) return false; - res->setNumber(l + r); + res.setNumber(l + r); } return true; } static MOZ_ALWAYS_INLINE bool -SubOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res) +SubOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res) { double d1, d2; if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2)) return false; - res->setNumber(d1 - d2); + res.setNumber(d1 - d2); return true; } static MOZ_ALWAYS_INLINE bool -MulOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res) +MulOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res) { double d1, d2; if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2)) return false; - res->setNumber(d1 * d2); + res.setNumber(d1 * d2); return true; } static MOZ_ALWAYS_INLINE bool -DivOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res) +DivOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res) { double d1, d2; if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2)) return false; - res->setNumber(NumberDiv(d1, d2)); + res.setNumber(NumberDiv(d1, d2)); return true; } static MOZ_ALWAYS_INLINE bool -ModOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res) +ModOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, MutableHandleValue res) { int32_t l, r; if (lhs.isInt32() && rhs.isInt32() && (l = lhs.toInt32()) >= 0 && (r = rhs.toInt32()) > 0) { int32_t mod = l % r; - res->setInt32(mod); + res.setInt32(mod); return true; } @@ -1303,7 +1303,7 @@ ModOperation(JSContext *cx, HandleValue lhs, HandleValue rhs, Value *res) if (!ToNumber(cx, lhs, &d1) || !ToNumber(cx, rhs, &d2)) return false; - res->setNumber(NumberMod(d1, d2)); + res.setNumber(NumberMod(d1, d2)); return true; } @@ -2199,7 +2199,8 @@ CASE(JSOP_URSH) { HandleValue lval = REGS.stackHandleAt(-2); HandleValue rval = REGS.stackHandleAt(-1); - if (!UrshOperation(cx, lval, rval, ®S.sp[-2])) + MutableHandleValue res = REGS.stackHandleAt(-2); + if (!UrshOperation(cx, lval, rval, res)) goto error; REGS.sp--; } @@ -2209,7 +2210,8 @@ CASE(JSOP_ADD) { MutableHandleValue lval = REGS.stackHandleAt(-2); MutableHandleValue rval = REGS.stackHandleAt(-1); - if (!AddOperation(cx, lval, rval, ®S.sp[-2])) + MutableHandleValue res = REGS.stackHandleAt(-2); + if (!AddOperation(cx, lval, rval, res)) goto error; REGS.sp--; } @@ -2220,7 +2222,8 @@ CASE(JSOP_SUB) RootedValue &lval = rootValue0, &rval = rootValue1; lval = REGS.sp[-2]; rval = REGS.sp[-1]; - if (!SubOperation(cx, lval, rval, ®S.sp[-2])) + MutableHandleValue res = REGS.stackHandleAt(-2); + if (!SubOperation(cx, lval, rval, res)) goto error; REGS.sp--; } @@ -2231,7 +2234,8 @@ CASE(JSOP_MUL) RootedValue &lval = rootValue0, &rval = rootValue1; lval = REGS.sp[-2]; rval = REGS.sp[-1]; - if (!MulOperation(cx, lval, rval, ®S.sp[-2])) + MutableHandleValue res = REGS.stackHandleAt(-2); + if (!MulOperation(cx, lval, rval, res)) goto error; REGS.sp--; } @@ -2242,7 +2246,8 @@ CASE(JSOP_DIV) RootedValue &lval = rootValue0, &rval = rootValue1; lval = REGS.sp[-2]; rval = REGS.sp[-1]; - if (!DivOperation(cx, lval, rval, ®S.sp[-2])) + MutableHandleValue res = REGS.stackHandleAt(-2); + if (!DivOperation(cx, lval, rval, res)) goto error; REGS.sp--; } @@ -2253,7 +2258,8 @@ CASE(JSOP_MOD) RootedValue &lval = rootValue0, &rval = rootValue1; lval = REGS.sp[-2]; rval = REGS.sp[-1]; - if (!ModOperation(cx, lval, rval, ®S.sp[-2])) + MutableHandleValue res = REGS.stackHandleAt(-2); + if (!ModOperation(cx, lval, rval, res)) goto error; REGS.sp--; } @@ -3826,37 +3832,37 @@ js::InitElementArray(JSContext *cx, jsbytecode *pc, HandleObject obj, uint32_t i } bool -js::AddValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res) +js::AddValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res) { return AddOperation(cx, lhs, rhs, res); } bool -js::SubValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res) +js::SubValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res) { return SubOperation(cx, lhs, rhs, res); } bool -js::MulValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res) +js::MulValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res) { return MulOperation(cx, lhs, rhs, res); } bool -js::DivValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res) +js::DivValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res) { return DivOperation(cx, lhs, rhs, res); } bool -js::ModValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res) +js::ModValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res) { return ModOperation(cx, lhs, rhs, res); } bool -js::UrshValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res) +js::UrshValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res) { return UrshOperation(cx, lhs, rhs, res); } diff --git a/js/src/vm/Interpreter.h b/js/src/vm/Interpreter.h index 673d883c6bc4..f49d7abe6b48 100644 --- a/js/src/vm/Interpreter.h +++ b/js/src/vm/Interpreter.h @@ -388,22 +388,22 @@ InitElementArray(JSContext *cx, jsbytecode *pc, HandleObject obj, uint32_t index, HandleValue value); bool -AddValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res); +AddValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res); bool -SubValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res); +SubValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res); bool -MulValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res); +MulValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res); bool -DivValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res); +DivValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res); bool -ModValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res); +ModValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res); bool -UrshValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, Value *res); +UrshValues(JSContext *cx, MutableHandleValue lhs, MutableHandleValue rhs, MutableHandleValue res); template bool From 0f044770cf39f9ae69ea68ca60c487de2d9cad02 Mon Sep 17 00:00:00 2001 From: Malini Das Date: Mon, 24 Feb 2014 12:11:08 -0500 Subject: [PATCH 33/48] Bug 975169 - Marionette test runner should not override textrunnerclass, version bump, r=jgriffiin,dburns --- .../client/marionette/runner/base.py | 60 +++++++------------ testing/marionette/client/setup.py | 2 +- 2 files changed, 22 insertions(+), 40 deletions(-) diff --git a/testing/marionette/client/marionette/runner/base.py b/testing/marionette/client/marionette/runner/base.py index 892f893ad374..ba431a1b6fae 100644 --- a/testing/marionette/client/marionette/runner/base.py +++ b/testing/marionette/client/marionette/runner/base.py @@ -42,10 +42,16 @@ class MarionetteTestResult(unittest._TextTestResult, TestResultCollection): def __init__(self, *args, **kwargs): self.marionette = kwargs.pop('marionette') TestResultCollection.__init__(self, 'MarionetteTest') - unittest._TextTestResult.__init__(self, *args, **kwargs) self.passed = 0 self.testsRun = 0 self.result_modifiers = [] # used by mixins to modify the result + pid = kwargs.pop('b2g_pid') + if pid: + bases = [b for b in self.__class__.__bases__] + bases.append(B2GTestResultMixin) + self.__class__.__bases__ = tuple(bases) + B2GTestResultMixin.__init__(self, b2g_pid=pid) + unittest._TextTestResult.__init__(self, *args, **kwargs) @property def skipped(self): @@ -240,17 +246,30 @@ class MarionetteTextTestRunner(unittest.TextTestRunner): def __init__(self, **kwargs): self.marionette = kwargs['marionette'] self.capabilities = kwargs.pop('capabilities') + self.pre_run_functions = [] + self.b2g_pid = None del kwargs['marionette'] + + if self.capabilities['device'] != 'desktop' and self.capabilities['b2g']: + def b2g_pre_run(): + dm_type = os.environ.get('DM_TRANS', 'adb') + if dm_type == 'adb': + self.b2g_pid = get_b2g_pid(get_dm(self.marionette)) + self.pre_run_functions.append(b2g_pre_run) + unittest.TextTestRunner.__init__(self, **kwargs) def _makeResult(self): return self.resultclass(self.stream, self.descriptions, self.verbosity, - marionette=self.marionette) + marionette=self.marionette, + b2g_pid=self.b2g_pid) def run(self, test): "Run the given test case or test suite." + for pre_run_func in self.pre_run_functions: + pre_run_func() result = self._makeResult() if hasattr(self, 'failfast'): result.failfast = self.failfast @@ -311,40 +330,6 @@ class MarionetteTextTestRunner(unittest.TextTestRunner): return result -class B2GMarionetteTestResult(MarionetteTestResult, B2GTestResultMixin): - - def __init__(self, *args, **kwargs): - # stupid hack because _TextTestRunner doesn't accept **kwargs - b2g_pid = kwargs.pop('b2g_pid') - MarionetteTestResult.__init__(self, *args, **kwargs) - kwargs['b2g_pid'] = b2g_pid - B2GTestResultMixin.__init__(self, *args, **kwargs) - - -class B2GMarionetteTextTestRunner(MarionetteTextTestRunner): - - resultclass = B2GMarionetteTestResult - - def __init__(self, **kwargs): - MarionetteTextTestRunner.__init__(self, **kwargs) - if self.capabilities['device'] != 'desktop': - self.resultclass = B2GMarionetteTestResult - self.b2g_pid = None - - def _makeResult(self): - return self.resultclass(self.stream, - self.descriptions, - self.verbosity, - marionette=self.marionette, - b2g_pid=self.b2g_pid) - - def run(self, test): - dm_type = os.environ.get('DM_TRANS', 'adb') - if dm_type == 'adb': - self.b2g_pid = get_b2g_pid(get_dm(self.marionette)) - return super(B2GMarionetteTextTestRunner, self).run(test) - - class BaseMarionetteOptions(OptionParser): def __init__(self, **kwargs): OptionParser.__init__(self, **kwargs) @@ -764,9 +749,6 @@ class BaseMarionetteTestRunner(object): if not self._capabilities: self.capabilities - if self.capabilities['device'] != 'desktop': - self.textrunnerclass = B2GMarionetteTextTestRunner - for test in tests: self.add_test(test) diff --git a/testing/marionette/client/setup.py b/testing/marionette/client/setup.py index ca39ed79cf3f..d960c0b9715e 100644 --- a/testing/marionette/client/setup.py +++ b/testing/marionette/client/setup.py @@ -1,7 +1,7 @@ import os from setuptools import setup, find_packages -version = '0.7.4' +version = '0.7.5' # get documentation from the README try: From a6e6fc47d150fa41c8e50c69bba2704adb189d4f Mon Sep 17 00:00:00 2001 From: Jim Chen Date: Mon, 24 Feb 2014 12:27:58 -0500 Subject: [PATCH 34/48] Bug 974560 - Send compositionupdate event for each text event; r=cpeterson --- widget/android/nsWindow.cpp | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index 70b041b5879f..d1707c91e169 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -1708,12 +1708,9 @@ nsWindow::OnKeyEvent(AndroidGeckoEvent *ae) msg = NS_KEY_UP; break; case AKEY_EVENT_ACTION_MULTIPLE: - { - WidgetTextEvent event(true, NS_TEXT_TEXT, this); - event.theText.Assign(ae->Characters()); - DispatchEvent(&event); - } - return; + // Keys with multiple action are handled in Java, + // and we should never see one here + MOZ_CRASH("Cannot handle key with multiple action"); default: ALOG("Unknown key action event!"); return; @@ -1910,6 +1907,12 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *ae) InitEvent(event, nullptr); DispatchEvent(&event); } + { + WidgetCompositionEvent event(true, NS_COMPOSITION_UPDATE, this); + InitEvent(event, nullptr); + event.data = ae->Characters(); + DispatchEvent(&event); + } { WidgetTextEvent event(true, NS_TEXT_TEXT, this); InitEvent(event, nullptr); @@ -2032,17 +2035,13 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *ae) InitEvent(event, nullptr); DispatchEvent(&event); } - - if (mIMEComposing && - event.theText != mIMEComposingText) { + { WidgetCompositionEvent compositionUpdate(true, NS_COMPOSITION_UPDATE, this); InitEvent(compositionUpdate, nullptr); compositionUpdate.data = event.theText; DispatchEvent(&compositionUpdate); - if (Destroyed()) - return; } #ifdef DEBUG_ANDROID_IME @@ -2126,6 +2125,11 @@ nsWindow::NotifyIME(const IMENotification& aIMENotification) if (mIMEComposing) { nsRefPtr kungFuDeathGrip(this); + WidgetCompositionEvent updateEvent(true, NS_COMPOSITION_UPDATE, + this); + InitEvent(updateEvent, nullptr); + DispatchEvent(&updateEvent); + WidgetTextEvent textEvent(true, NS_TEXT_TEXT, this); InitEvent(textEvent, nullptr); DispatchEvent(&textEvent); From dca2479fd2a1c92fc6527f08fde3077fc7efb49c Mon Sep 17 00:00:00 2001 From: Jim Chen Date: Mon, 24 Feb 2014 12:27:58 -0500 Subject: [PATCH 35/48] Bug 974980 - Always push a js:RunScript frame in pseudostack; r=BenWa --- js/public/ProfilingStack.h | 4 ++++ js/src/vm/SPSProfiler.cpp | 6 +++--- js/src/vm/SPSProfiler.h | 6 ++++++ tools/profiler/PseudoStack.h | 4 ++-- 4 files changed, 15 insertions(+), 5 deletions(-) diff --git a/js/public/ProfilingStack.h b/js/public/ProfilingStack.h index 500c1ee09fa8..34f8ed10107a 100644 --- a/js/public/ProfilingStack.h +++ b/js/public/ProfilingStack.h @@ -78,6 +78,10 @@ class ProfileEntry // a pc into a script's code. To signify a nullptr pc, use a -1 index. This // is checked against in pc() and setPC() to set/get the right pc. static const int32_t NullPCIndex = -1; + + // This bit is added to the stack address to indicate that copying the + // frame label is not necessary when taking a sample of the pseudostack. + static const uintptr_t NoCopyBit = 1; }; JS_FRIEND_API(void) diff --git a/js/src/vm/SPSProfiler.cpp b/js/src/vm/SPSProfiler.cpp index 73d365786900..e9d680aa2b22 100644 --- a/js/src/vm/SPSProfiler.cpp +++ b/js/src/vm/SPSProfiler.cpp @@ -212,7 +212,7 @@ SPSProfiler::push(const char *string, void *sp, JSScript *script, jsbytecode *pc volatile uint32_t *size = size_; uint32_t current = *size; - JS_ASSERT(enabled()); + JS_ASSERT(installed()); if (current < max_) { stack[current].setLabel(string); stack[current].setStackAddress(sp); @@ -291,12 +291,12 @@ SPSEntryMarker::SPSEntryMarker(JSRuntime *rt : profiler(&rt->spsProfiler) { MOZ_GUARD_OBJECT_NOTIFIER_INIT; - if (!profiler->enabled()) { + if (!profiler->installed()) { profiler = nullptr; return; } size_before = *profiler->size_; - profiler->push("js::RunScript", this, nullptr, nullptr); + profiler->pushNoCopy("js::RunScript", this, nullptr, nullptr); } SPSEntryMarker::~SPSEntryMarker() diff --git a/js/src/vm/SPSProfiler.h b/js/src/vm/SPSProfiler.h index 1bbda0f3e053..38862186c8f8 100644 --- a/js/src/vm/SPSProfiler.h +++ b/js/src/vm/SPSProfiler.h @@ -128,6 +128,12 @@ class SPSProfiler const char *allocProfileString(JSScript *script, JSFunction *function); void push(const char *string, void *sp, JSScript *script, jsbytecode *pc); + void pushNoCopy(const char *string, void *sp, + JSScript *script, jsbytecode *pc) { + push(string, reinterpret_cast( + reinterpret_cast(sp) | ProfileEntry::NoCopyBit), + script, pc); + } void pop(); public: diff --git a/tools/profiler/PseudoStack.h b/tools/profiler/PseudoStack.h index 98bb01c3365a..fdf5c8fa5323 100644 --- a/tools/profiler/PseudoStack.h +++ b/tools/profiler/PseudoStack.h @@ -93,10 +93,10 @@ public: // Last bit 1 = Don't copy, Last bit 0 = Copy. if (copy) { setStackAddress(reinterpret_cast( - reinterpret_cast(sparg) & ~0x1)); + reinterpret_cast(sparg) & ~NoCopyBit)); } else { setStackAddress(reinterpret_cast( - reinterpret_cast(sparg) | 0x1)); + reinterpret_cast(sparg) | NoCopyBit)); } } }; From bfa117a21f76ea8d982e240a0b188463cdb0b8f7 Mon Sep 17 00:00:00 2001 From: Jim Chen Date: Mon, 24 Feb 2014 12:27:58 -0500 Subject: [PATCH 36/48] Bug 974986 - Always specify stack address in SamplerStackFramePrintfRAII; r=BenWa --- tools/profiler/GeckoProfilerImpl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/profiler/GeckoProfilerImpl.h b/tools/profiler/GeckoProfilerImpl.h index 451c4d81e925..32b39515f1b9 100644 --- a/tools/profiler/GeckoProfilerImpl.h +++ b/tools/profiler/GeckoProfilerImpl.h @@ -332,7 +332,7 @@ public: mHandle = mozilla_sampler_call_enter(mDest, this, true, line); va_end(args); } else { - mHandle = mozilla_sampler_call_enter(aDefault, nullptr, false, line); + mHandle = mozilla_sampler_call_enter(aDefault, this, false, line); } } ~SamplerStackFramePrintfRAII() { From a14cf7102b0082ee69cfb40fcc4db50bc4f925cc Mon Sep 17 00:00:00 2001 From: Luke Wagner Date: Mon, 24 Feb 2014 12:20:04 -0600 Subject: [PATCH 37/48] Bug 975182 - OdinMonkey: unprotect code while cloning (r=benj) --- js/src/jit-test/tests/asm.js/testBug975182.js | 18 +++++ js/src/jit/AsmJSModule.cpp | 77 ++++++++++++++++++- js/src/jit/AsmJSModule.h | 13 +++- js/src/jit/AsmJSSignalHandlers.cpp | 23 ++---- 4 files changed, 111 insertions(+), 20 deletions(-) create mode 100644 js/src/jit-test/tests/asm.js/testBug975182.js diff --git a/js/src/jit-test/tests/asm.js/testBug975182.js b/js/src/jit-test/tests/asm.js/testBug975182.js new file mode 100644 index 000000000000..3ff0bb5bd326 --- /dev/null +++ b/js/src/jit-test/tests/asm.js/testBug975182.js @@ -0,0 +1,18 @@ +Function("\ + g = (function(t,foreign){\ + \"use asm\";\ + var ff = foreign.ff;\ + function f() {\ + +ff()\ + }\ + return f\ + })(this, {\ + ff: arguments.callee\ + }, ArrayBuffer(4096))\ +")() +function m(f) { + for (var j = 0; j < 6000; ++j) { + f(); + } +} +m(g); diff --git a/js/src/jit/AsmJSModule.cpp b/js/src/jit/AsmJSModule.cpp index 1aad44118ef3..c2aacb1fb67b 100644 --- a/js/src/jit/AsmJSModule.cpp +++ b/js/src/jit/AsmJSModule.cpp @@ -833,9 +833,40 @@ AsmJSModule::deserialize(ExclusiveContext *cx, const uint8_t *cursor) return cursor; } -bool -AsmJSModule::clone(ExclusiveContext *cx, ScopedJSDeletePtr *moduleOut) const +// When a module is cloned, we memcpy its executable code. If, right before or +// during the clone, another thread calls AsmJSModule::protectCode() then the +// executable code will become inaccessible. In theory, we could take away only +// PROT_EXEC, but this seems to break emulators. +class AutoUnprotectCodeForClone { + JSRuntime *rt_; + JSRuntime::AutoLockForOperationCallback lock_; + const AsmJSModule &module_; + const bool protectedBefore_; + + public: + AutoUnprotectCodeForClone(JSContext *cx, const AsmJSModule &module) + : rt_(cx->runtime()), + lock_(rt_), + module_(module), + protectedBefore_(module_.codeIsProtected(rt_)) + { + if (protectedBefore_) + module_.unprotectCode(rt_); + } + + ~AutoUnprotectCodeForClone() + { + if (protectedBefore_) + module_.protectCode(rt_); + } +}; + +bool +AsmJSModule::clone(JSContext *cx, ScopedJSDeletePtr *moduleOut) const +{ + AutoUnprotectCodeForClone cloneGuard(cx, *this); + *moduleOut = cx->new_(scriptSource_, charsBegin_); if (!*moduleOut) return false; @@ -871,6 +902,48 @@ AsmJSModule::clone(ExclusiveContext *cx, ScopedJSDeletePtr *moduleO return true; } +void +AsmJSModule::protectCode(JSRuntime *rt) const +{ + JS_ASSERT(rt->currentThreadOwnsOperationCallbackLock()); + + // Technically, we should be able to only take away the execute permissions, + // however this seems to break our emulators which don't always check + // execute permissions while executing code. +#if defined(XP_WIN) + DWORD oldProtect; + if (!VirtualProtect(codeBase(), functionBytes(), PAGE_NOACCESS, &oldProtect)) + MOZ_CRASH(); +#else // assume Unix + if (mprotect(codeBase(), functionBytes(), PROT_NONE)) + MOZ_CRASH(); +#endif + + codeIsProtected_ = true; +} + +void +AsmJSModule::unprotectCode(JSRuntime *rt) const +{ +#if defined(XP_WIN) + DWORD oldProtect; + if (!VirtualProtect(codeBase(), functionBytes(), PAGE_EXECUTE_READWRITE, &oldProtect)) + MOZ_CRASH(); +#else // assume Unix + if (mprotect(codeBase(), functionBytes(), PROT_READ | PROT_WRITE | PROT_EXEC)) + MOZ_CRASH(); +#endif + + codeIsProtected_ = false; +} + +bool +AsmJSModule::codeIsProtected(JSRuntime *rt) const +{ + JS_ASSERT(rt->currentThreadOwnsOperationCallbackLock()); + return codeIsProtected_; +} + static bool GetCPUID(uint32_t *cpuId) { diff --git a/js/src/jit/AsmJSModule.h b/js/src/jit/AsmJSModule.h index 98788f11a1da..7b4b500d2f71 100644 --- a/js/src/jit/AsmJSModule.h +++ b/js/src/jit/AsmJSModule.h @@ -416,6 +416,11 @@ class AsmJSModule FunctionCountsVector functionCounts_; + // This field is accessed concurrently when triggering the operation + // callback and access must be sychronized via the runtime's operation + // callback lock. + mutable bool codeIsProtected_; + public: explicit AsmJSModule(ScriptSource *scriptSource, uint32_t charsBegin); ~AsmJSModule(); @@ -806,7 +811,13 @@ class AsmJSModule const uint8_t *deserialize(ExclusiveContext *cx, const uint8_t *cursor); bool loadedFromCache() const { return loadedFromCache_; } - bool clone(ExclusiveContext *cx, ScopedJSDeletePtr *moduleOut) const; + bool clone(JSContext *cx, ScopedJSDeletePtr *moduleOut) const; + + // These methods may only be called while holding the Runtime's operation + // callback lock. + void protectCode(JSRuntime *rt) const; + void unprotectCode(JSRuntime *rt) const; + bool codeIsProtected(JSRuntime *rt) const; }; // Store the just-parsed module in the cache using AsmJSCacheOps. diff --git a/js/src/jit/AsmJSSignalHandlers.cpp b/js/src/jit/AsmJSSignalHandlers.cpp index 040026306c03..61f841c1596b 100644 --- a/js/src/jit/AsmJSSignalHandlers.cpp +++ b/js/src/jit/AsmJSSignalHandlers.cpp @@ -458,9 +458,7 @@ HandleException(PEXCEPTION_POINTERS exception) if (module.containsPC(faultingAddress)) { activation->setResumePC(pc); *ppc = module.operationCallbackExit(); - DWORD oldProtect; - if (!VirtualProtect(module.codeBase(), module.functionBytes(), PAGE_EXECUTE, &oldProtect)) - MOZ_CRASH(); + module.unprotectCode(rt); return true; } @@ -645,7 +643,7 @@ HandleMachException(JSRuntime *rt, const ExceptionRequest &request) const AsmJSModule &module = activation->module(); if (HandleSimulatorInterrupt(rt, activation, faultingAddress)) { - mprotect(module.codeBase(), module.functionBytes(), PROT_EXEC); + module.unprotectCode(rt); return true; } @@ -660,7 +658,7 @@ HandleMachException(JSRuntime *rt, const ExceptionRequest &request) if (module.containsPC(faultingAddress)) { activation->setResumePC(pc); *ppc = module.operationCallbackExit(); - mprotect(module.codeBase(), module.functionBytes(), PROT_EXEC); + module.unprotectCode(rt); // Update the thread state with the new pc. kret = thread_set_state(rtThread, x86_THREAD_STATE, (thread_state_t)&state, x86_THREAD_STATE_COUNT); @@ -892,7 +890,7 @@ HandleSignal(int signum, siginfo_t *info, void *ctx) const AsmJSModule &module = activation->module(); if (HandleSimulatorInterrupt(rt, activation, faultingAddress)) { - mprotect(module.codeBase(), module.functionBytes(), PROT_EXEC); + module.unprotectCode(rt); return true; } @@ -907,7 +905,7 @@ HandleSignal(int signum, siginfo_t *info, void *ctx) if (module.containsPC(faultingAddress)) { activation->setResumePC(pc); *ppc = module.operationCallbackExit(); - mprotect(module.codeBase(), module.functionBytes(), PROT_EXEC); + module.unprotectCode(rt); return true; } @@ -1027,16 +1025,7 @@ js::TriggerOperationCallbackForAsmJSCode(JSRuntime *rt) if (!activation) return; - const AsmJSModule &module = activation->module(); - -#if defined(XP_WIN) - DWORD oldProtect; - if (!VirtualProtect(module.codeBase(), module.functionBytes(), PAGE_NOACCESS, &oldProtect)) - MOZ_CRASH(); -#else // assume Unix - if (mprotect(module.codeBase(), module.functionBytes(), PROT_NONE)) - MOZ_CRASH(); -#endif + activation->module().protectCode(rt); } #if defined(MOZ_ASAN) && defined(JS_STANDALONE) From d5f7bfce096b180f0e2113a1a1e3648966b13c4e Mon Sep 17 00:00:00 2001 From: "Adam Roach [:abr]" Date: Mon, 24 Feb 2014 12:29:09 -0600 Subject: [PATCH 38/48] Backed out changeset 2d1f70b91712 (bug 786234) --- .../signaling/test/mediapipeline_unittest.cpp | 154 +++++------------- 1 file changed, 38 insertions(+), 116 deletions(-) diff --git a/media/webrtc/signaling/test/mediapipeline_unittest.cpp b/media/webrtc/signaling/test/mediapipeline_unittest.cpp index a1f92ca7588d..566693038f04 100644 --- a/media/webrtc/signaling/test/mediapipeline_unittest.cpp +++ b/media/webrtc/signaling/test/mediapipeline_unittest.cpp @@ -114,7 +114,7 @@ class TransportInfo { dtls_ = nullptr; } - void Shutdown() { + void Stop() { if (loopback_) { loopback_->Disconnect(); } @@ -168,6 +168,11 @@ class TestAgent { void StopInt() { audio_->GetStream()->Stop(); + audio_rtp_transport_.Stop(); + audio_rtcp_transport_.Stop(); + bundle_transport_.Stop(); + if (audio_pipeline_) + audio_pipeline_->ShutdownTransport_s(); } void Stop() { @@ -179,60 +184,14 @@ class TestAgent { mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), WrapRunnable(this, &TestAgent::StopInt)); - } - void Shutdown_s() { - audio_rtp_transport_.Shutdown(); - audio_rtcp_transport_.Shutdown(); - bundle_transport_.Shutdown(); - if (audio_pipeline_) - audio_pipeline_->ShutdownTransport_s(); - } - - void Shutdown() { - if (audio_pipeline_) - audio_pipeline_->ShutdownMedia_m(); - - mozilla::SyncRunnable::DispatchToThread( - test_utils->sts_target(), - WrapRunnable(this, &TestAgent::Shutdown_s)); - } - - uint32_t GetRemoteSSRC() { - uint32_t res = 0; - audio_conduit_->GetRemoteSSRC(&res); - return res; - } - - uint32_t GetLocalSSRC() { - uint32_t res = 0; - audio_conduit_->GetLocalSSRC(&res); - return res; - } - - int GetAudioRtpCountSent() { - return audio_pipeline_->rtp_packets_sent(); - } - - int GetAudioRtpCountReceived() { - return audio_pipeline_->rtp_packets_received(); - } - - int GetAudioRtcpCountSent() { - return audio_pipeline_->rtcp_packets_sent(); - } - - int GetAudioRtcpCountReceived() { - return audio_pipeline_->rtcp_packets_received(); + audio_pipeline_ = nullptr; } protected: mozilla::AudioCodecConfig audio_config_; mozilla::RefPtr audio_conduit_; nsRefPtr audio_; - // TODO(bcampen@mozilla.com): Right now this does not let us test RTCP in - // both directions; only the sender's RTCP is sent, but the receiver should - // be sending it too. mozilla::RefPtr audio_pipeline_; TransportInfo audio_rtp_transport_; TransportInfo audio_rtcp_transport_; @@ -279,6 +238,14 @@ class TestAgentSend : public TestAgent { audio_pipeline_->Init(); } + int GetAudioRtpCount() { + return audio_pipeline_->rtp_packets_sent(); + } + + int GetAudioRtcpCount() { + return audio_pipeline_->rtcp_packets_received(); + } + void SetUsingBundle(bool use_bundle) { use_bundle_ = use_bundle; } @@ -319,7 +286,6 @@ class TestAgentReceive : public TestAgent { RefPtr bundle_transport; if (bundle_filter_) { bundle_transport = bundle_transport_.flow_; - bundle_filter_->AddLocalSSRC(GetLocalSSRC()); } audio_pipeline_ = new mozilla::MediaPipelineReceiveAudio( @@ -337,6 +303,14 @@ class TestAgentReceive : public TestAgent { audio_pipeline_->Init(); } + int GetAudioRtpCount() { + return audio_pipeline_->rtp_packets_received(); + } + + int GetAudioRtcpCount() { + return audio_pipeline_->rtcp_packets_sent(); + } + void SetBundleFilter(nsAutoPtr filter) { bundle_filter_ = filter; } @@ -349,7 +323,6 @@ class TestAgentReceive : public TestAgent { nsAutoPtr filter) { audio_pipeline_->UpdateFilterFromRemoteDescription_s(filter); } - private: nsAutoPtr bundle_filter_; }; @@ -360,8 +333,6 @@ class MediaPipelineTest : public ::testing::Test { ~MediaPipelineTest() { p1_.Stop(); p2_.Stop(); - p1_.Shutdown(); - p2_.Shutdown(); } // Setup transport. @@ -391,9 +362,7 @@ class MediaPipelineTest : public ::testing::Test { nsAutoPtr localFilter = nsAutoPtr(nullptr), nsAutoPtr remoteFilter = - nsAutoPtr(nullptr), - unsigned int ms_until_answer = 500, - unsigned int ms_of_traffic_after_answer = 10000) { + nsAutoPtr(nullptr)) { // We do not support testing bundle without rtcp mux, since that doesn't // make any sense. @@ -417,20 +386,16 @@ class MediaPipelineTest : public ::testing::Test { p1_.Start(); // Simulate pre-answer traffic - PR_Sleep(ms_until_answer); + PR_Sleep(500); mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), WrapRunnable(&p2_, &TestAgentReceive::SetUsingBundle_s, bundle)); if (bundle) { - // Leaving remoteFilter not set implies we want to test sunny-day if (!remoteFilter) { remoteFilter = new MediaPipelineFilter; - // Might not be safe, strictly speaking. - remoteFilter->AddRemoteSSRC(p1_.GetLocalSSRC()); } - mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), WrapRunnable(&p2_, @@ -440,43 +405,26 @@ class MediaPipelineTest : public ::testing::Test { // wait for some RTP/RTCP tx and rx to happen - PR_Sleep(ms_of_traffic_after_answer); + PR_Sleep(10000); + + if (bundle) { + // Filter should have eaten everything + ASSERT_EQ(0, p2_.GetAudioRtpCount()); + } else { + ASSERT_GE(p1_.GetAudioRtpCount(), 40); + ASSERT_GE(p2_.GetAudioRtpCount(), 40); + ASSERT_GE(p2_.GetAudioRtcpCount(), 1); + } p1_.Stop(); p2_.Stop(); - - // wait for any packets in flight to arrive - PR_Sleep(100); - - p1_.Shutdown(); - p2_.Shutdown(); - - if (!bundle) { - // If we are doing bundle, allow the test-case to do this checking. - ASSERT_GE(p1_.GetAudioRtpCountSent(), 40); - ASSERT_EQ(p1_.GetAudioRtpCountReceived(), p2_.GetAudioRtpCountSent()); - ASSERT_EQ(p1_.GetAudioRtpCountSent(), p2_.GetAudioRtpCountReceived()); - - // Calling ShutdownMedia_m on both pipelines does not stop the flow of - // RTCP. So, we might be off by one here. - ASSERT_LE(p2_.GetAudioRtcpCountReceived(), p1_.GetAudioRtcpCountSent()); - ASSERT_GE(p2_.GetAudioRtcpCountReceived() + 1, p1_.GetAudioRtcpCountSent()); - } - } void TestAudioReceiverOffersBundle(bool bundle_accepted, nsAutoPtr localFilter, nsAutoPtr remoteFilter = - nsAutoPtr(nullptr), - unsigned int ms_until_answer = 500, - unsigned int ms_of_traffic_after_answer = 10000) { - TestAudioSend(true, - bundle_accepted, - localFilter, - remoteFilter, - ms_until_answer, - ms_of_traffic_after_answer); + nsAutoPtr(nullptr)) { + TestAudioSend(true, bundle_accepted, localFilter, remoteFilter); } protected: TestAgentSend p1_; @@ -881,33 +829,7 @@ TEST_F(MediaPipelineTest, TestAudioSendBundleOfferedAndDeclined) { TEST_F(MediaPipelineTest, TestAudioSendBundleOfferedAndAccepted) { nsAutoPtr filter(new MediaPipelineFilter); - // These durations have to be _extremely_ long to have any assurance that - // some RTCP will be sent at all. This is because the first RTCP packet - // is sometimes sent before the transports are ready, which causes it to - // be dropped. - TestAudioReceiverOffersBundle(true, - filter, - // We do not specify the filter for the remote description, so it will be - // set to something sane after a short time. - nsAutoPtr(), - 10000, - 10000); - - // Some packets should have been dropped, but not all - ASSERT_GT(p1_.GetAudioRtpCountSent(), p2_.GetAudioRtpCountReceived()); - ASSERT_GT(p2_.GetAudioRtpCountReceived(), 40); - ASSERT_GT(p1_.GetAudioRtcpCountSent(), 1); - ASSERT_GT(p1_.GetAudioRtcpCountSent(), p2_.GetAudioRtcpCountReceived()); - ASSERT_GT(p2_.GetAudioRtcpCountReceived(), 0); -} - -TEST_F(MediaPipelineTest, TestAudioSendBundleOfferedAndAcceptedEmptyFilter) { - nsAutoPtr filter(new MediaPipelineFilter); - nsAutoPtr bad_answer_filter(new MediaPipelineFilter); - TestAudioReceiverOffersBundle(true, filter, bad_answer_filter); - // Filter is empty, so should drop everything. - ASSERT_EQ(0, p2_.GetAudioRtpCountReceived()); - ASSERT_EQ(0, p2_.GetAudioRtcpCountReceived()); + TestAudioReceiverOffersBundle(true, filter); } } // end namespace From a231c2f65acb96c1ed5161be2d00fdf76810800d Mon Sep 17 00:00:00 2001 From: "Adam Roach [:abr]" Date: Mon, 24 Feb 2014 12:29:10 -0600 Subject: [PATCH 39/48] Backed out changeset c8083d830fa6 (bug 786234) --- .../signaling/test/mediapipeline_unittest.cpp | 128 +++++++++++------- 1 file changed, 77 insertions(+), 51 deletions(-) diff --git a/media/webrtc/signaling/test/mediapipeline_unittest.cpp b/media/webrtc/signaling/test/mediapipeline_unittest.cpp index 566693038f04..5904843e0530 100644 --- a/media/webrtc/signaling/test/mediapipeline_unittest.cpp +++ b/media/webrtc/signaling/test/mediapipeline_unittest.cpp @@ -25,7 +25,7 @@ #include "MediaPipelineFilter.h" #include "runnable_utils.h" #include "transportflow.h" -#include "transportlayerloopback.h" +#include "transportlayerprsock.h" #include "transportlayerdtls.h" #include "mozilla/SyncRunnable.h" @@ -50,26 +50,17 @@ class TransportInfo { public: TransportInfo() : flow_(nullptr), - loopback_(nullptr), + prsock_(nullptr), dtls_(nullptr) {} - static void InitAndConnect(TransportInfo &client, TransportInfo &server) { - client.Init(true); - server.Init(false); - client.PushLayers(); - server.PushLayers(); - client.Connect(&server); - server.Connect(&client); - } - void Init(bool client) { nsresult res; flow_ = new TransportFlow(); - loopback_ = new TransportLayerLoopback(); + prsock_ = new TransportLayerPrsock(); dtls_ = new TransportLayerDtls(); - res = loopback_->Init(); + res = prsock_->Init(); if (res != NS_OK) { FreeLayers(); } @@ -89,7 +80,7 @@ class TransportInfo { nsAutoPtr > layers( new std::queue); - layers->push(loopback_); + layers->push(prsock_); layers->push(dtls_); res = flow_->PushLayers(layers); if (res != NS_OK) { @@ -98,33 +89,19 @@ class TransportInfo { ASSERT_EQ((nsresult)NS_OK, res); } - void Connect(TransportInfo* peer) { - MOZ_ASSERT(loopback_); - MOZ_ASSERT(peer->loopback_); - - loopback_->Connect(peer->loopback_); - } - // Free the memory allocated at the beginning of Init // if failure occurs before layers setup. void FreeLayers() { - delete loopback_; - loopback_ = nullptr; + delete prsock_; delete dtls_; - dtls_ = nullptr; } void Stop() { - if (loopback_) { - loopback_->Disconnect(); - } - loopback_ = nullptr; - dtls_ = nullptr; flow_ = nullptr; } mozilla::RefPtr flow_; - TransportLayerLoopback *loopback_; + TransportLayerPrsock *prsock_; TransportLayerDtls *dtls_; }; @@ -137,19 +114,32 @@ class TestAgent { audio_pipeline_() { } - static void ConnectRtp(TestAgent *client, TestAgent *server) { - TransportInfo::InitAndConnect(client->audio_rtp_transport_, - server->audio_rtp_transport_); + void ConnectRtpSocket(PRFileDesc *fd, bool client) { + ConnectSocket(&audio_rtp_transport_, fd, client); } - static void ConnectRtcp(TestAgent *client, TestAgent *server) { - TransportInfo::InitAndConnect(client->audio_rtcp_transport_, - server->audio_rtcp_transport_); + void ConnectRtcpSocket(PRFileDesc *fd, bool client) { + ConnectSocket(&audio_rtcp_transport_, fd, client); } - static void ConnectBundle(TestAgent *client, TestAgent *server) { - TransportInfo::InitAndConnect(client->bundle_transport_, - server->bundle_transport_); + void ConnectBundleSocket(PRFileDesc *fd, bool client) { + ConnectSocket(&bundle_transport_, fd, client); + } + + void ConnectSocket(TransportInfo *transport, PRFileDesc *fd, bool client) { + nsresult res; + + transport->Init(client); + + mozilla::SyncRunnable::DispatchToThread( + test_utils->sts_target(), + WrapRunnable(transport->prsock_, &TransportLayerPrsock::Import, fd, &res)); + if (!NS_SUCCEEDED(res)) { + transport->FreeLayers(); + } + ASSERT_TRUE(NS_SUCCEEDED(res)); + + transport->PushLayers(); } virtual void CreatePipelines_s(bool aIsRtcpMux) = 0; @@ -186,6 +176,8 @@ class TestAgent { WrapRunnable(this, &TestAgent::StopInt)); audio_pipeline_ = nullptr; + + PR_Sleep(1000); // Deal with race condition } protected: @@ -330,30 +322,61 @@ class TestAgentReceive : public TestAgent { class MediaPipelineTest : public ::testing::Test { public: - ~MediaPipelineTest() { - p1_.Stop(); - p2_.Stop(); + MediaPipelineTest() : p1_() { + rtp_fds_[0] = rtp_fds_[1] = nullptr; + rtcp_fds_[0] = rtcp_fds_[1] = nullptr; + bundle_fds_[0] = bundle_fds_[1] = nullptr; } // Setup transport. void InitTransports(bool aIsRtcpMux) { - // RTP, p1_ is server, p2_ is client + // Create RTP related transport. + PRStatus status = PR_NewTCPSocketPair(rtp_fds_); + ASSERT_EQ(status, PR_SUCCESS); + + // RTP, DTLS server mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), - WrapRunnableNM(&TestAgent::ConnectRtp, &p2_, &p1_)); + WrapRunnable(&p1_, &TestAgent::ConnectRtpSocket, rtp_fds_[0], false)); + + // RTP, DTLS client + mozilla::SyncRunnable::DispatchToThread( + test_utils->sts_target(), + WrapRunnable(&p2_, &TestAgent::ConnectRtpSocket, rtp_fds_[1], true)); // Create RTCP flows separately if we are not muxing them. if(!aIsRtcpMux) { - // RTCP, p1_ is server, p2_ is client + status = PR_NewTCPSocketPair(rtcp_fds_); + ASSERT_EQ(status, PR_SUCCESS); + + // RTCP, DTLS server mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), - WrapRunnableNM(&TestAgent::ConnectRtcp, &p2_, &p1_)); + WrapRunnable(&p1_, &TestAgent::ConnectRtcpSocket, rtcp_fds_[0], false)); + + // RTCP, DTLS client + mozilla::SyncRunnable::DispatchToThread( + test_utils->sts_target(), + WrapRunnable(&p2_, &TestAgent::ConnectRtcpSocket, rtcp_fds_[1], true)); } - // BUNDLE, p1_ is server, p2_ is client + status = PR_NewTCPSocketPair(bundle_fds_); + // BUNDLE, DTLS server mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), - WrapRunnableNM(&TestAgent::ConnectBundle, &p2_, &p1_)); + WrapRunnable(&p1_, + &TestAgent::ConnectBundleSocket, + bundle_fds_[0], + false)); + + // BUNDLE, DTLS client + mozilla::SyncRunnable::DispatchToThread( + test_utils->sts_target(), + WrapRunnable(&p2_, + &TestAgent::ConnectBundleSocket, + bundle_fds_[1], + true)); + } // Verify RTP and RTCP @@ -408,11 +431,11 @@ class MediaPipelineTest : public ::testing::Test { PR_Sleep(10000); if (bundle) { - // Filter should have eaten everything - ASSERT_EQ(0, p2_.GetAudioRtpCount()); + // Filter should have eaten everything, so no RTCP } else { ASSERT_GE(p1_.GetAudioRtpCount(), 40); - ASSERT_GE(p2_.GetAudioRtpCount(), 40); +// TODO: Fix to not fail or crash (Bug 947663) +// ASSERT_GE(p2_.GetAudioRtpCount(), 40); ASSERT_GE(p2_.GetAudioRtcpCount(), 1); } @@ -427,6 +450,9 @@ class MediaPipelineTest : public ::testing::Test { TestAudioSend(true, bundle_accepted, localFilter, remoteFilter); } protected: + PRFileDesc *rtp_fds_[2]; + PRFileDesc *rtcp_fds_[2]; + PRFileDesc *bundle_fds_[2]; TestAgentSend p1_; TestAgentReceive p2_; }; From 34d7d2d6991b37c7abd57f1ca1613b4c3819a774 Mon Sep 17 00:00:00 2001 From: "Adam Roach [:abr]" Date: Mon, 24 Feb 2014 12:29:10 -0600 Subject: [PATCH 40/48] Backed out changeset c5334aea6433 (bug 786234) --- media/mtransport/transportflow.cpp | 11 - media/mtransport/transportflow.h | 2 - .../signaling/src/media/VcmSIPCCBinding.cpp | 102 +--- .../src/mediapipeline/MediaPipeline.cpp | 517 +++++------------- .../src/mediapipeline/MediaPipeline.h | 137 ++--- .../src/peerconnection/PeerConnectionImpl.cpp | 6 +- .../peerconnection/PeerConnectionMedia.cpp | 97 ---- .../src/peerconnection/PeerConnectionMedia.h | 11 - .../signaling/test/mediapipeline_unittest.cpp | 152 +---- 9 files changed, 210 insertions(+), 825 deletions(-) diff --git a/media/mtransport/transportflow.cpp b/media/mtransport/transportflow.cpp index 4f1afe102059..630b6f9459e9 100644 --- a/media/mtransport/transportflow.cpp +++ b/media/mtransport/transportflow.cpp @@ -199,17 +199,6 @@ TransportResult TransportFlow::SendPacket(const unsigned char *data, return top() ? top()->SendPacket(data, len) : TE_ERROR; } -bool TransportFlow::Contains(TransportLayer *layer) const { - if (layers_) { - for (auto l = layers_->begin(); l != layers_->end(); ++l) { - if (*l == layer) { - return true; - } - } - } - return false; -} - void TransportFlow::EnsureSameThread(TransportLayer *layer) { // Enforce that if any of the layers have a thread binding, // they all have the same binding. diff --git a/media/mtransport/transportflow.h b/media/mtransport/transportflow.h index a22f26ed58bb..a553050d6cf7 100644 --- a/media/mtransport/transportflow.h +++ b/media/mtransport/transportflow.h @@ -96,8 +96,6 @@ class TransportFlow : public sigslot::has_slots<> { sigslot::signal3 SignalPacketReceived; - bool Contains(TransportLayer *layer) const; - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TransportFlow) private: diff --git a/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp b/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp index fd2a0a0f15dc..6aa201ee46a4 100644 --- a/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp +++ b/media/webrtc/signaling/src/media/VcmSIPCCBinding.cpp @@ -12,7 +12,6 @@ #include "MediaConduitErrors.h" #include "MediaConduitInterface.h" #include "MediaPipeline.h" -#include "MediaPipelineFilter.h" #include "VcmSIPCCBinding.h" #include "csf_common.h" #include "PeerConnectionImpl.h" @@ -1502,12 +1501,7 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id, const char *fingerprint, vcm_mediaAttrs_t *attrs) { - CSFLogDebug( logTag, "%s(%s) track = %d, stream = %d, level = %d", - __FUNCTION__, - peerconnection, - pc_track_id, - pc_stream_id, - level); + CSFLogDebug( logTag, "%s(%s)", __FUNCTION__, peerconnection); // Find the PC. sipcc::PeerConnectionWrapper pc(peerconnection); @@ -1543,7 +1537,7 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id, } mozilla::RefPtr rtcp_flow = nullptr; - if (!attrs->rtcp_mux) { + if(!attrs->rtcp_mux) { rtcp_flow = vcmCreateTransportFlow(pc.impl(), level, true, setup_type, fingerprint_alg, fingerprint); if (!rtcp_flow) { @@ -1552,60 +1546,6 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id, } } - // If we're offering bundle, a given MediaPipeline could receive traffic on - // two different network flows depending on whether the answerer accepts, - // before any answer comes in. We need to be prepared for both cases. - nsAutoPtr filter; - RefPtr bundle_rtp_flow; - RefPtr bundle_rtcp_flow; - if (attrs->bundle_level) { - filter = new MediaPipelineFilter; - // Record our correlator, if present in our offer. - filter->SetCorrelator(attrs->bundle_stream_correlator); - - // Record our own ssrcs (these are _not_ those of the remote end; that - // is handled in vcmTxStart) - for (int s = 0; s < attrs->num_ssrcs; ++s) { - filter->AddLocalSSRC(attrs->ssrcs[s]); - } - - // Record the unique payload types - for (int p = 0; p < attrs->num_unique_payload_types; ++p) { - filter->AddUniquePT(attrs->unique_payload_types[p]); - } - - // Do not pass additional TransportFlows if the pipeline will use the same - // flow regardless of whether bundle happens or not. - if (attrs->bundle_level != (unsigned int)level) { - // This might end up creating it, or might reuse it. - mozilla::RefPtr bundle_rtp_flow = - vcmCreateTransportFlow(pc.impl(), - attrs->bundle_level, - false, - setup_type, - fingerprint_alg, - fingerprint); - - if (!bundle_rtp_flow) { - CSFLogError( logTag, "Could not create bundle RTP flow"); - return VCM_ERROR; - } - - if (!attrs->rtcp_mux) { - bundle_rtcp_flow = vcmCreateTransportFlow(pc.impl(), - attrs->bundle_level, - true, - setup_type, - fingerprint_alg, - fingerprint); - if (!bundle_rtcp_flow) { - CSFLogError( logTag, "Could not create bundle RTCP flow"); - return VCM_ERROR; - } - } - } - } - if (CC_IS_AUDIO(mcap_id)) { std::vector configs; @@ -1640,6 +1580,7 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id, if (conduit->ConfigureRecvMediaCodecs(configs)) return VCM_ERROR; + // Now we have all the pieces, create the pipeline mozilla::RefPtr pipeline = new mozilla::MediaPipelineReceiveAudio( @@ -1649,12 +1590,7 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id, stream->GetMediaStream()->GetStream(), pc_track_id, level, - conduit, - rtp_flow, - rtcp_flow, - bundle_rtp_flow, - bundle_rtcp_flow, - filter); + conduit, rtp_flow, rtcp_flow); nsresult res = pipeline->Init(); if (NS_FAILED(res)) { @@ -1706,12 +1642,7 @@ static int vcmRxStartICE_m(cc_mcapid_t mcap_id, stream->GetMediaStream()->GetStream(), pc_track_id, level, - conduit, - rtp_flow, - rtcp_flow, - bundle_rtp_flow, - bundle_rtcp_flow, - filter); + conduit, rtp_flow, rtcp_flow); nsresult res = pipeline->Init(); if (NS_FAILED(res)) { @@ -2251,12 +2182,7 @@ static int vcmTxStartICE_m(cc_mcapid_t mcap_id, const char *fingerprint, vcm_mediaAttrs_t *attrs) { - CSFLogDebug( logTag, "%s(%s) track = %d, stream = %d, level = %d", - __FUNCTION__, - peerconnection, - pc_track_id, - pc_stream_id, - level); + CSFLogDebug( logTag, "%s(%s)", __FUNCTION__, peerconnection); // Find the PC and get the stream sipcc::PeerConnectionWrapper pc(peerconnection); @@ -2282,22 +2208,6 @@ static int vcmTxStartICE_m(cc_mcapid_t mcap_id, } } - // This tells the receive MediaPipeline (if there is one) whether we are - // doing bundle, and if so, updates the filter. This does not affect the - // transmit MediaPipeline (created above) at all. - if (attrs->bundle_level) { - nsAutoPtr filter (new MediaPipelineFilter); - for (int s = 0; s < attrs->num_ssrcs; ++s) { - filter->AddRemoteSSRC(attrs->ssrcs[s]); - } - pc.impl()->media()->SetUsingBundle_m(level, true); - pc.impl()->media()->UpdateFilterFromRemoteDescription_m(level, filter); - } else { - // This will also clear the filter. - pc.impl()->media()->SetUsingBundle_m(level, false); - } - - if (CC_IS_AUDIO(mcap_id)) { mozilla::AudioCodecConfig *config_raw; config_raw = new mozilla::AudioCodecConfig( diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp index dd660106c6fd..bffb9a0f8609 100644 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.cpp @@ -42,9 +42,6 @@ #include "mozilla/gfx/Point.h" #include "mozilla/gfx/Types.h" -#include "webrtc/modules/interface/module_common_types.h" -#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" - using namespace mozilla; using namespace mozilla::gfx; @@ -78,35 +75,41 @@ nsresult MediaPipeline::Init_s() { conduit_->AttachTransport(transport_); nsresult res; - MOZ_ASSERT(rtp_.transport_); - MOZ_ASSERT(rtcp_.transport_); - res = ConnectTransport_s(rtp_); - if (NS_FAILED(res)) { - return res; - } + MOZ_ASSERT(rtp_transport_); + // Look to see if the transport is ready + rtp_transport_->SignalStateChange.connect(this, + &MediaPipeline::StateChange); - if (rtcp_.transport_ != rtp_.transport_) { - res = ConnectTransport_s(rtcp_); + if (rtp_transport_->state() == TransportLayer::TS_OPEN) { + res = TransportReady_s(rtp_transport_); if (NS_FAILED(res)) { + MOZ_MTLOG(ML_ERROR, "Error calling TransportReady(); res=" + << static_cast(res) << " in " << __FUNCTION__); return res; } + } else if (rtp_transport_->state() == TransportLayer::TS_ERROR) { + MOZ_MTLOG(ML_ERROR, "RTP transport is already in error state"); + TransportFailed_s(rtp_transport_); + return NS_ERROR_FAILURE; } - if (possible_bundle_rtp_) { - MOZ_ASSERT(possible_bundle_rtcp_); - MOZ_ASSERT(possible_bundle_rtp_->transport_); - MOZ_ASSERT(possible_bundle_rtcp_->transport_); + // If rtcp_transport_ is the same as rtp_transport_ then we are muxing. + // Otherwise, set it up separately. + if (rtcp_transport_ != rtp_transport_) { + rtcp_transport_->SignalStateChange.connect(this, + &MediaPipeline::StateChange); - res = ConnectTransport_s(*possible_bundle_rtp_); - if (NS_FAILED(res)) { - return res; - } - - if (possible_bundle_rtcp_->transport_ != possible_bundle_rtp_->transport_) { - res = ConnectTransport_s(*possible_bundle_rtcp_); + if (rtcp_transport_->state() == TransportLayer::TS_OPEN) { + res = TransportReady_s(rtcp_transport_); if (NS_FAILED(res)) { + MOZ_MTLOG(ML_ERROR, "Error calling TransportReady(); res=" + << static_cast(res) << " in " << __FUNCTION__); return res; } + } else if (rtcp_transport_->state() == TransportLayer::TS_ERROR) { + MOZ_MTLOG(ML_ERROR, "RTCP transport is already in error state"); + TransportFailed_s(rtcp_transport_); + return NS_ERROR_FAILURE; } } @@ -123,72 +126,55 @@ void MediaPipeline::ShutdownTransport_s() { disconnect_all(); transport_->Detach(); - rtp_.transport_ = nullptr; - rtcp_.transport_ = nullptr; - possible_bundle_rtp_ = nullptr; - possible_bundle_rtcp_ = nullptr; + rtp_transport_ = nullptr; + rtcp_transport_ = nullptr; } void MediaPipeline::StateChange(TransportFlow *flow, TransportLayer::State state) { - TransportInfo* info = GetTransportInfo_s(flow); - MOZ_ASSERT(info); + // If rtcp_transport_ is the same as rtp_transport_ then we are muxing. + // So the only flow should be the RTP flow. + if (rtcp_transport_ == rtp_transport_) { + MOZ_ASSERT(flow == rtp_transport_); + } if (state == TransportLayer::TS_OPEN) { MOZ_MTLOG(ML_INFO, "Flow is ready"); - TransportReady_s(*info); + TransportReady_s(flow); } else if (state == TransportLayer::TS_CLOSED || state == TransportLayer::TS_ERROR) { - TransportFailed_s(*info); + TransportFailed_s(flow); } } -static bool MakeRtpTypeToStringArray(const char** array) { - static const char* RTP_str = "RTP"; - static const char* RTCP_str = "RTCP"; - static const char* MUX_str = "RTP/RTCP mux"; - array[MediaPipeline::RTP] = RTP_str; - array[MediaPipeline::RTCP] = RTCP_str; - array[MediaPipeline::MUX] = MUX_str; - return true; -} - -static const char* ToString(MediaPipeline::RtpType type) { - static const char* array[(int)MediaPipeline::MAX_RTP_TYPE] = {nullptr}; - // Dummy variable to cause init to happen only on first call - static bool dummy = MakeRtpTypeToStringArray(array); - (void)dummy; - return array[type]; -} - -nsresult MediaPipeline::TransportReady_s(TransportInfo &info) { +nsresult MediaPipeline::TransportReady_s(TransportFlow *flow) { MOZ_ASSERT(!description_.empty()); + bool rtcp = !(flow == rtp_transport_); + State *state = rtcp ? &rtcp_state_ : &rtp_state_; // TODO(ekr@rtfm.com): implement some kind of notification on // failure. bug 852665. - if (info.state_ != MP_CONNECTING) { + if (*state != MP_CONNECTING) { MOZ_MTLOG(ML_ERROR, "Transport ready for flow in wrong state:" << - description_ << ": " << ToString(info.type_)); + description_ << ": " << (rtcp ? "rtcp" : "rtp")); return NS_ERROR_FAILURE; } + nsresult res; + MOZ_MTLOG(ML_INFO, "Transport ready for pipeline " << static_cast(this) << " flow " << description_ << ": " << - ToString(info.type_)); - - // TODO(bcampen@mozilla.com): Should we disconnect from the flow on failure? - nsresult res; + (rtcp ? "rtcp" : "rtp")); // Now instantiate the SRTP objects TransportLayerDtls *dtls = static_cast( - info.transport_->GetLayer(TransportLayerDtls::ID())); + flow->GetLayer(TransportLayerDtls::ID())); MOZ_ASSERT(dtls); // DTLS is mandatory uint16_t cipher_suite; res = dtls->GetSrtpCipher(&cipher_suite); if (NS_FAILED(res)) { MOZ_MTLOG(ML_ERROR, "Failed to negotiate DTLS-SRTP. This is an error"); - info.state_ = MP_CLOSED; - UpdateRtcpMuxState(info); + *state = MP_CLOSED; return res; } @@ -198,8 +184,7 @@ nsresult MediaPipeline::TransportReady_s(TransportInfo &info) { srtp_block, sizeof(srtp_block)); if (NS_FAILED(res)) { MOZ_MTLOG(ML_ERROR, "Failed to compute DTLS-SRTP keys. This is an error"); - info.state_ = MP_CLOSED; - UpdateRtcpMuxState(info); + *state = MP_CLOSED; MOZ_CRASH(); // TODO: Remove once we have enough field experience to // know it doesn't happen. bug 798797. Note that the // code after this never executes. @@ -233,63 +218,88 @@ nsresult MediaPipeline::TransportReady_s(TransportInfo &info) { read_key = client_write_key; } - MOZ_ASSERT(!info.send_srtp_ && !info.recv_srtp_); - info.send_srtp_ = SrtpFlow::Create(cipher_suite, false, write_key, - SRTP_TOTAL_KEY_LENGTH); - info.recv_srtp_ = SrtpFlow::Create(cipher_suite, true, read_key, - SRTP_TOTAL_KEY_LENGTH); - if (!info.send_srtp_ || !info.recv_srtp_) { - MOZ_MTLOG(ML_ERROR, "Couldn't create SRTP flow for " - << ToString(info.type_)); - info.state_ = MP_CLOSED; - UpdateRtcpMuxState(info); - return NS_ERROR_FAILURE; - } + if (!rtcp) { + // RTP side + MOZ_ASSERT(!rtp_send_srtp_ && !rtp_recv_srtp_); + rtp_send_srtp_ = SrtpFlow::Create(cipher_suite, false, + write_key, SRTP_TOTAL_KEY_LENGTH); + rtp_recv_srtp_ = SrtpFlow::Create(cipher_suite, true, + read_key, SRTP_TOTAL_KEY_LENGTH); + if (!rtp_send_srtp_ || !rtp_recv_srtp_) { + MOZ_MTLOG(ML_ERROR, "Couldn't create SRTP flow for RTCP"); + *state = MP_CLOSED; + return NS_ERROR_FAILURE; + } - if (direction_ == RECEIVE) { - // The TRANSMIT pipeline does not process _any_ RTCP. This is the RECEIVE - // pipeline's job, even for receiver reports. - MOZ_MTLOG(ML_INFO, "Listening for " << ToString(info.type_) - << " packets received on " << - static_cast(dtls->downward())); + // Start listening + // If rtcp_transport_ is the same as rtp_transport_ then we are muxing + if (rtcp_transport_ == rtp_transport_) { + MOZ_ASSERT(!rtcp_send_srtp_ && !rtcp_recv_srtp_); + rtcp_send_srtp_ = rtp_send_srtp_; + rtcp_recv_srtp_ = rtp_recv_srtp_; - switch (info.type_) { - case RTP: - dtls->downward()->SignalPacketReceived.connect( - this, - &MediaPipeline::RtpPacketReceived); - break; - case RTCP: - dtls->downward()->SignalPacketReceived.connect( - this, - &MediaPipeline::RtcpPacketReceived); - break; - case MUX: - dtls->downward()->SignalPacketReceived.connect( - this, - &MediaPipeline::PacketReceived); - break; - default: - MOZ_CRASH(); + MOZ_MTLOG(ML_INFO, "Listening for packets received on " << + static_cast(dtls->downward())); + + dtls->downward()->SignalPacketReceived.connect(this, + &MediaPipeline:: + PacketReceived); + rtcp_state_ = MP_OPEN; + } else { + MOZ_MTLOG(ML_INFO, "Listening for RTP packets received on " << + static_cast(dtls->downward())); + + dtls->downward()->SignalPacketReceived.connect(this, + &MediaPipeline:: + RtpPacketReceived); } } + else { + MOZ_ASSERT(!rtcp_send_srtp_ && !rtcp_recv_srtp_); + rtcp_send_srtp_ = SrtpFlow::Create(cipher_suite, false, + write_key, SRTP_TOTAL_KEY_LENGTH); + rtcp_recv_srtp_ = SrtpFlow::Create(cipher_suite, true, + read_key, SRTP_TOTAL_KEY_LENGTH); + if (!rtcp_send_srtp_ || !rtcp_recv_srtp_) { + MOZ_MTLOG(ML_ERROR, "Couldn't create SRTCP flow for RTCP"); + *state = MP_CLOSED; + return NS_ERROR_FAILURE; + } - info.state_ = MP_OPEN; - UpdateRtcpMuxState(info); + MOZ_MTLOG(ML_DEBUG, "Listening for RTCP packets received on " << + static_cast(dtls->downward())); + + // Start listening + dtls->downward()->SignalPacketReceived.connect(this, + &MediaPipeline:: + RtcpPacketReceived); + } + + *state = MP_OPEN; return NS_OK; } -nsresult MediaPipeline::TransportFailed_s(TransportInfo &info) { +nsresult MediaPipeline::TransportFailed_s(TransportFlow *flow) { ASSERT_ON_THREAD(sts_thread_); + bool rtcp = !(flow == rtp_transport_); - info.state_ = MP_CLOSED; - UpdateRtcpMuxState(info); + State *state = rtcp ? &rtcp_state_ : &rtp_state_; - MOZ_MTLOG(ML_INFO, "Transport closed for flow " << ToString(info.type_)); + *state = MP_CLOSED; + + // If rtcp_transport_ is the same as rtp_transport_ then we are muxing + if(rtcp_transport_ == rtp_transport_) { + MOZ_ASSERT(state != &rtcp_state_); + rtcp_state_ = MP_CLOSED; + } + + + MOZ_MTLOG(ML_INFO, "Transport closed for flow " << (rtcp ? "rtcp" : "rtp")); NS_WARNING( "MediaPipeline Transport failed. This is not properly cleaned up yet"); + // TODO(ekr@rtfm.com): SECURITY: Figure out how to clean up if the // connection was good and now it is bad. // TODO(ekr@rtfm.com): Report up so that the PC knows we @@ -298,24 +308,6 @@ nsresult MediaPipeline::TransportFailed_s(TransportInfo &info) { return NS_OK; } -void MediaPipeline::UpdateRtcpMuxState(TransportInfo &info) { - if (info.type_ == MUX) { - if (info.transport_ == rtcp_.transport_) { - rtcp_.state_ = info.state_; - if (!rtcp_.send_srtp_) { - rtcp_.send_srtp_ = info.send_srtp_; - rtcp_.recv_srtp_ = info.recv_srtp_; - } - } else if (possible_bundle_rtcp_ && - info.transport_ == possible_bundle_rtcp_->transport_) { - possible_bundle_rtcp_->state_ = info.state_; - if (!possible_bundle_rtcp_->send_srtp_) { - possible_bundle_rtcp_->send_srtp_ = info.send_srtp_; - possible_bundle_rtcp_->recv_srtp_ = info.recv_srtp_; - } - } - } -} nsresult MediaPipeline::SendPacket(TransportFlow *flow, const void *data, int len) { @@ -348,7 +340,7 @@ void MediaPipeline::increment_rtp_packets_sent(int32_t bytes) { if (!(rtp_packets_sent_ % 100)) { MOZ_MTLOG(ML_INFO, "RTP sent packet count for " << description_ << " Pipeline " << static_cast(this) - << " Flow : " << static_cast(rtp_.transport_) + << " Flow : " << static_cast(rtp_transport_) << ": " << rtp_packets_sent_ << " (" << rtp_bytes_sent_ << " bytes)"); } @@ -359,7 +351,7 @@ void MediaPipeline::increment_rtcp_packets_sent() { if (!(rtcp_packets_sent_ % 100)) { MOZ_MTLOG(ML_INFO, "RTCP sent packet count for " << description_ << " Pipeline " << static_cast(this) - << " Flow : " << static_cast(rtcp_.transport_) + << " Flow : " << static_cast(rtcp_transport_) << ": " << rtcp_packets_sent_); } } @@ -370,7 +362,7 @@ void MediaPipeline::increment_rtp_packets_received(int32_t bytes) { if (!(rtp_packets_received_ % 100)) { MOZ_MTLOG(ML_INFO, "RTP received packet count for " << description_ << " Pipeline " << static_cast(this) - << " Flow : " << static_cast(rtp_.transport_) + << " Flow : " << static_cast(rtp_transport_) << ": " << rtp_packets_received_ << " (" << rtp_bytes_received_ << " bytes)"); } @@ -381,7 +373,7 @@ void MediaPipeline::increment_rtcp_packets_received() { if (!(rtcp_packets_received_ % 100)) { MOZ_MTLOG(ML_INFO, "RTCP received packet count for " << description_ << " Pipeline " << static_cast(this) - << " Flow : " << static_cast(rtcp_.transport_) + << " Flow : " << static_cast(rtcp_transport_) << ": " << rtcp_packets_received_); } } @@ -399,84 +391,34 @@ void MediaPipeline::RtpPacketReceived(TransportLayer *layer, return; } - TransportInfo* info = &rtp_; - - if (possible_bundle_rtp_ && - possible_bundle_rtp_->transport_->Contains(layer)) { - // Received this on our possible bundle transport. Override info. - info = possible_bundle_rtp_; - } - - // TODO(bcampen@mozilla.com): Can either of these actually happen? If not, - // the info variable can be removed, and this function gets simpler. - if (info->state_ != MP_OPEN) { + if (rtp_state_ != MP_OPEN) { MOZ_MTLOG(ML_ERROR, "Discarding incoming packet; pipeline not open"); return; } - if (info->transport_->state() != TransportLayer::TS_OPEN) { + if (rtp_transport_->state() != TransportLayer::TS_OPEN) { MOZ_MTLOG(ML_ERROR, "Discarding incoming packet; transport not open"); return; } - // This should never happen. - MOZ_ASSERT(info->recv_srtp_); + MOZ_ASSERT(rtp_recv_srtp_); // This should never happen if (direction_ == TRANSMIT) { + // Discard any media that is being transmitted to us + // This will be unnecessary when we have SSRC filtering. return; } - if (possible_bundle_rtp_ && (info == &rtp_)) { - // We were not sure we would be using rtp_ or possible_bundle_rtp_, but we - // have just received traffic that clears this up. - // Don't let our filter prevent us from noticing this, if the filter is - // incomplete (ie; no SSRCs in remote SDP, or no remote SDP at all). - SetUsingBundle_s(false); - MOZ_MTLOG(ML_INFO, "Ruled out the possibility that we're receiving bundle " - "for " << description_); - // TODO(bcampen@mozilla.com): Might be nice to detect when every - // MediaPipeline but the master has determined that it isn't doing bundle, - // since that means the master isn't doing bundle either. We could maybe - // do this by putting some refcounted dummy variable in the filters, and - // checking the value of the refcount. It is not clear whether this is - // going to be useful in practice. - } - - if (!len) { - return; - } - - // Filter out everything but RTP/RTCP - if (data[0] < 128 || data[0] > 191) { - return; - } - - if (filter_) { - webrtc::RTPHeader header; - if (!rtp_parser_->Parse(data, len, &header) || - !filter_->Filter(header)) { - return; - } - } - - if (possible_bundle_rtp_) { - // Just got traffic that passed our filter on the potential bundle - // transport. Must be doing bundle. - SetUsingBundle_s(true); - MOZ_MTLOG(ML_INFO, "Confirmed the possibility that we're receiving bundle"); - } - - // Everything is decided now; just use rtp_ - MOZ_ASSERT(!possible_bundle_rtp_); - MOZ_ASSERT(!possible_bundle_rtcp_); + // TODO(ekr@rtfm.com): filter for DTLS here and in RtcpPacketReceived + // TODO(ekr@rtfm.com): filter on SSRC for bundle // Make a copy rather than cast away constness ScopedDeletePtr inner_data( new unsigned char[len]); memcpy(inner_data, data, len); int out_len = 0; - nsresult res = rtp_.recv_srtp_->UnprotectRtp(inner_data, - len, len, &out_len); + nsresult res = rtp_recv_srtp_->UnprotectRtp(inner_data, + len, len, &out_len); if (!NS_SUCCEEDED(res)) { char tmp[16]; @@ -509,58 +451,25 @@ void MediaPipeline::RtcpPacketReceived(TransportLayer *layer, return; } - TransportInfo* info = &rtcp_; - if (possible_bundle_rtcp_ && - possible_bundle_rtcp_->transport_->Contains(layer)) { - info = possible_bundle_rtcp_; - } - - if (info->state_ != MP_OPEN) { + if (rtcp_state_ != MP_OPEN) { MOZ_MTLOG(ML_DEBUG, "Discarding incoming packet; pipeline not open"); return; } - if (info->transport_->state() != TransportLayer::TS_OPEN) { + if (rtcp_transport_->state() != TransportLayer::TS_OPEN) { MOZ_MTLOG(ML_ERROR, "Discarding incoming packet; transport not open"); return; } - if (possible_bundle_rtp_ && (info == &rtcp_)) { - // We have offered bundle, and received our first packet on a non-bundle - // address. We are definitely not using the bundle address. - SetUsingBundle_s(false); - } - - if (!len) { + if (direction_ == RECEIVE) { + // Discard any RTCP that is being transmitted to us + // This will be unnecessary when we have SSRC filtering. return; } - // Filter out everything but RTP/RTCP - if (data[0] < 128 || data[0] > 191) { - return; - } - - MediaPipelineFilter::Result filter_result = MediaPipelineFilter::PASS; - if (filter_) { - filter_result = filter_->FilterRTCP(data, len); - if (filter_result == MediaPipelineFilter::FAIL) { - return; - } - } - - if (filter_result == MediaPipelineFilter::PASS && possible_bundle_rtp_) { - // Just got traffic that passed our filter on the potential bundle - // transport. Must be doing bundle. - SetUsingBundle_s(true); - } - - // We continue using info here, since it is possible that the filter did not - // support the payload type (ie; returned MediaPipelineFilter::UNSUPPORTED). - // In this case, we just let it pass, and hope the webrtc.org code does - // something sane. increment_rtcp_packets_received(); - MOZ_ASSERT(info->recv_srtp_); // This should never happen + MOZ_ASSERT(rtcp_recv_srtp_); // This should never happen // Make a copy rather than cast away constness ScopedDeletePtr inner_data( @@ -568,10 +477,7 @@ void MediaPipeline::RtcpPacketReceived(TransportLayer *layer, memcpy(inner_data, data, len); int out_len; - nsresult res = info->recv_srtp_->UnprotectRtcp(inner_data, - len, - len, - &out_len); + nsresult res = rtcp_recv_srtp_->UnprotectRtcp(inner_data, len, len, &out_len); if (!NS_SUCCEEDED(res)) return; @@ -657,14 +563,11 @@ nsresult MediaPipelineTransmit::Init() { return MediaPipeline::Init(); } -nsresult MediaPipelineTransmit::TransportReady_s(TransportInfo &info) { - ASSERT_ON_THREAD(sts_thread_); +nsresult MediaPipelineTransmit::TransportReady_s(TransportFlow *flow) { // Call base ready function. - MediaPipeline::TransportReady_s(info); + MediaPipeline::TransportReady_s(flow); - // Should not be set for a transmitter - MOZ_ASSERT(!possible_bundle_rtp_); - if (&info == &rtp_) { + if (flow == rtp_transport_) { // TODO(ekr@rtfm.com): Move onto MSG thread. listener_->SetActive(true); } @@ -672,121 +575,6 @@ nsresult MediaPipelineTransmit::TransportReady_s(TransportInfo &info) { return NS_OK; } -void MediaPipeline::DisconnectTransport_s(TransportInfo &info) { - MOZ_ASSERT(info.transport_); - ASSERT_ON_THREAD(sts_thread_); - - info.transport_->SignalStateChange.disconnect(this); - // We do this even if we're a transmitter, since we are still possibly - // registered to receive RTCP. - TransportLayerDtls *dtls = static_cast( - info.transport_->GetLayer(TransportLayerDtls::ID())); - MOZ_ASSERT(dtls); // DTLS is mandatory - MOZ_ASSERT(dtls->downward()); - dtls->downward()->SignalPacketReceived.disconnect(this); -} - -nsresult MediaPipeline::ConnectTransport_s(TransportInfo &info) { - MOZ_ASSERT(info.transport_); - ASSERT_ON_THREAD(sts_thread_); - - // Look to see if the transport is ready - if (info.transport_->state() == TransportLayer::TS_OPEN) { - nsresult res = TransportReady_s(info); - if (NS_FAILED(res)) { - MOZ_MTLOG(ML_ERROR, "Error calling TransportReady(); res=" - << static_cast(res) << " in " << __FUNCTION__); - return res; - } - } else if (info.transport_->state() == TransportLayer::TS_ERROR) { - MOZ_MTLOG(ML_ERROR, ToString(info.type_) - << "transport is already in error state"); - TransportFailed_s(info); - return NS_ERROR_FAILURE; - } - - info.transport_->SignalStateChange.connect(this, - &MediaPipeline::StateChange); - - return NS_OK; -} - -MediaPipeline::TransportInfo* MediaPipeline::GetTransportInfo_s( - TransportFlow *flow) { - ASSERT_ON_THREAD(sts_thread_); - if (flow == rtp_.transport_) { - return &rtp_; - } - - if (flow == rtcp_.transport_) { - return &rtcp_; - } - - if (possible_bundle_rtp_) { - if (flow == possible_bundle_rtp_->transport_) { - return possible_bundle_rtp_; - } - - if (flow == possible_bundle_rtcp_->transport_) { - return possible_bundle_rtcp_; - } - } - - return nullptr; -} - -void MediaPipeline::SetUsingBundle_s(bool decision) { - ASSERT_ON_THREAD(sts_thread_); - // Note: This can be called either because of events on the STS thread, or - // by events on the main thread (ie; receiving a remote description). It is - // best to be careful of races here, so don't assume that transports are open. - if (!possible_bundle_rtp_) { - if (!decision) { - // This can happen on the master pipeline. - filter_ = nullptr; - } - return; - } - - if (direction_ == RECEIVE) { - if (decision) { - MOZ_MTLOG(ML_INFO, "Non-master pipeline confirmed bundle for " - << description_); - // We're doing bundle. Release the unused flows, and copy the ones we - // are using into the less wishy-washy members. - DisconnectTransport_s(rtp_); - DisconnectTransport_s(rtcp_); - rtp_ = *possible_bundle_rtp_; - rtcp_ = *possible_bundle_rtcp_; - } else { - MOZ_MTLOG(ML_INFO, "Non-master pipeline confirmed no bundle for " - << description_); - // We are not doing bundle - DisconnectTransport_s(*possible_bundle_rtp_); - DisconnectTransport_s(*possible_bundle_rtcp_); - filter_ = nullptr; - } - - // We are no longer in an ambiguous state. - possible_bundle_rtp_ = nullptr; - possible_bundle_rtcp_ = nullptr; - } -} - -void MediaPipeline::UpdateFilterFromRemoteDescription_s( - nsAutoPtr filter) { - ASSERT_ON_THREAD(sts_thread_); - // This is only supposed to relax the filter. Relaxing a missing filter is - // not possible. - MOZ_ASSERT(filter_); - - if (!filter) { - filter_ = nullptr; - } else { - filter_->IncorporateRemoteDescription(*filter); - } -} - nsresult MediaPipeline::PipelineTransport::SendRtpPacket( const void *data, int len) { @@ -805,17 +593,16 @@ nsresult MediaPipeline::PipelineTransport::SendRtpPacket( nsresult MediaPipeline::PipelineTransport::SendRtpPacket_s( nsAutoPtr data) { - ASSERT_ON_THREAD(sts_thread_); if (!pipeline_) return NS_OK; // Detached - if (!pipeline_->rtp_.send_srtp_) { + if (!pipeline_->rtp_send_srtp_) { MOZ_MTLOG(ML_DEBUG, "Couldn't write RTP packet; SRTP not set up yet"); return NS_OK; } - MOZ_ASSERT(pipeline_->rtp_.transport_); - NS_ENSURE_TRUE(pipeline_->rtp_.transport_, NS_ERROR_NULL_POINTER); + MOZ_ASSERT(pipeline_->rtp_transport_); + NS_ENSURE_TRUE(pipeline_->rtp_transport_, NS_ERROR_NULL_POINTER); // libsrtp enciphers in place, so we need a new, big enough // buffer. @@ -827,15 +614,15 @@ nsresult MediaPipeline::PipelineTransport::SendRtpPacket_s( memcpy(inner_data, data->data(), data->len()); int out_len; - nsresult res = pipeline_->rtp_.send_srtp_->ProtectRtp(inner_data, - data->len(), - max_len, - &out_len); + nsresult res = pipeline_->rtp_send_srtp_->ProtectRtp(inner_data, + data->len(), + max_len, + &out_len); if (!NS_SUCCEEDED(res)) return res; pipeline_->increment_rtp_packets_sent(out_len); - return pipeline_->SendPacket(pipeline_->rtp_.transport_, inner_data, + return pipeline_->SendPacket(pipeline_->rtp_transport_, inner_data, out_len); } @@ -857,17 +644,16 @@ nsresult MediaPipeline::PipelineTransport::SendRtcpPacket( nsresult MediaPipeline::PipelineTransport::SendRtcpPacket_s( nsAutoPtr data) { - ASSERT_ON_THREAD(sts_thread_); if (!pipeline_) return NS_OK; // Detached - if (!pipeline_->rtcp_.send_srtp_) { + if (!pipeline_->rtcp_send_srtp_) { MOZ_MTLOG(ML_DEBUG, "Couldn't write RTCP packet; SRTCP not set up yet"); return NS_OK; } - MOZ_ASSERT(pipeline_->rtcp_.transport_); - NS_ENSURE_TRUE(pipeline_->rtcp_.transport_, NS_ERROR_NULL_POINTER); + MOZ_ASSERT(pipeline_->rtcp_transport_); + NS_ENSURE_TRUE(pipeline_->rtcp_transport_, NS_ERROR_NULL_POINTER); // libsrtp enciphers in place, so we need a new, big enough // buffer. @@ -879,16 +665,15 @@ nsresult MediaPipeline::PipelineTransport::SendRtcpPacket_s( memcpy(inner_data, data->data(), data->len()); int out_len; - nsresult res = pipeline_->rtcp_.send_srtp_->ProtectRtcp(inner_data, - data->len(), - max_len, - &out_len); - + nsresult res = pipeline_->rtcp_send_srtp_->ProtectRtcp(inner_data, + data->len(), + max_len, + &out_len); if (!NS_SUCCEEDED(res)) return res; pipeline_->increment_rtcp_packets_sent(); - return pipeline_->SendPacket(pipeline_->rtcp_.transport_, inner_data, + return pipeline_->SendPacket(pipeline_->rtcp_transport_, inner_data, out_len); } diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h index d48a5fc9806e..9339deda1428 100644 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipeline.h @@ -18,7 +18,6 @@ #include "VideoUtils.h" #endif #include "MediaConduitInterface.h" -#include "MediaPipelineFilter.h" #include "AudioSegment.h" #include "mozilla/ReentrantMonitor.h" #include "SrtpFlow.h" @@ -30,8 +29,6 @@ #include "VideoSegment.h" #endif -#include "webrtc/modules/rtp_rtcp/interface/rtp_header_parser.h" - namespace mozilla { // A class that represents the pipeline of audio and video @@ -83,11 +80,16 @@ class MediaPipeline : public sigslot::has_slots<> { track_id_(track_id), level_(level), conduit_(conduit), - rtp_(rtp_transport, rtcp_transport ? RTP : MUX), - rtcp_(rtcp_transport ? rtcp_transport : rtp_transport, - rtcp_transport ? RTCP : MUX), + rtp_transport_(rtp_transport), + rtp_state_(MP_CONNECTING), + rtcp_transport_(rtcp_transport), + rtcp_state_(MP_CONNECTING), main_thread_(main_thread), sts_thread_(sts_thread), + rtp_send_srtp_(), + rtcp_send_srtp_(), + rtp_recv_srtp_(), + rtcp_recv_srtp_(), rtp_packets_sent_(0), rtcp_packets_sent_(0), rtp_packets_received_(0), @@ -99,8 +101,11 @@ class MediaPipeline : public sigslot::has_slots<> { // To indicate rtcp-mux rtcp_transport should be nullptr. // Therefore it's an error to send in the same flow for // both rtp and rtcp. - MOZ_ASSERT(rtp_transport != rtcp_transport); + MOZ_ASSERT(rtp_transport_ != rtcp_transport_); + if (!rtcp_transport_) { + rtcp_transport_ = rtp_transport; + } // PipelineTransport() will access this->sts_thread_; moved here for safety transport_ = new PipelineTransport(this); } @@ -121,22 +126,12 @@ class MediaPipeline : public sigslot::has_slots<> { virtual nsresult Init(); - // When we have offered bundle, the MediaPipelines are created in an - // indeterminate state; we do not know whether the answerer will take us - // up on our offer. In the meantime, we need to behave in a manner that - // errs on the side of packet loss when it is unclear whether an arriving - // packet is meant for us. We want to get out of this indeterminate state - // ASAP, which is what this function can be used for. - void SetUsingBundle_s(bool decision); - void UpdateFilterFromRemoteDescription_s( - nsAutoPtr filter); - virtual Direction direction() const { return direction_; } virtual TrackID trackid() const { return track_id_; } virtual int level() const { return level_; } bool IsDoingRtcpMux() const { - return (rtp_.type_ == MUX); + return (rtp_transport_ == rtcp_transport_); } int32_t rtp_packets_sent() const { return rtp_packets_sent_; } @@ -151,13 +146,6 @@ class MediaPipeline : public sigslot::has_slots<> { // Thread counting NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaPipeline) - typedef enum { - RTP, - RTCP, - MUX, - MAX_RTP_TYPE - } RtpType; - protected: virtual void DetachMediaStream() {} @@ -165,7 +153,7 @@ class MediaPipeline : public sigslot::has_slots<> { class PipelineTransport : public TransportInterface { public: // Implement the TransportInterface functions - explicit PipelineTransport(MediaPipeline *pipeline) + PipelineTransport(MediaPipeline *pipeline) : pipeline_(pipeline), sts_thread_(pipeline->sts_thread_) {} @@ -184,40 +172,15 @@ class MediaPipeline : public sigslot::has_slots<> { }; friend class PipelineTransport; - class TransportInfo { - public: - TransportInfo(RefPtr flow, RtpType type) : - transport_(flow), - state_(MP_CONNECTING), - type_(type) { - MOZ_ASSERT(flow); - } - - RefPtr transport_; - State state_; - RefPtr send_srtp_; - RefPtr recv_srtp_; - RtpType type_; - }; - - // The transport is down - virtual nsresult TransportFailed_s(TransportInfo &info); - // The transport is ready - virtual nsresult TransportReady_s(TransportInfo &info); - void UpdateRtcpMuxState(TransportInfo &info); - - // Unhooks from signals - void DisconnectTransport_s(TransportInfo &info); - nsresult ConnectTransport_s(TransportInfo &info); - - TransportInfo* GetTransportInfo_s(TransportFlow *flow); + virtual nsresult TransportFailed_s(TransportFlow *flow); // The transport is down + virtual nsresult TransportReady_s(TransportFlow *flow); // The transport is ready void increment_rtp_packets_sent(int bytes); void increment_rtcp_packets_sent(); void increment_rtp_packets_received(int bytes); void increment_rtcp_packets_received(); - virtual nsresult SendPacket(TransportFlow *flow, const void *data, int len); + virtual nsresult SendPacket(TransportFlow *flow, const void* data, int len); // Process slots on transports void StateChange(TransportFlow *flow, TransportLayer::State); @@ -239,18 +202,10 @@ class MediaPipeline : public sigslot::has_slots<> { // thread. Read on STS thread. // The transport objects. Read/written on STS thread. - TransportInfo rtp_; - TransportInfo rtcp_; - // These are for bundle. We have a separate set because when we have offered - // bundle, we do not know whether we will receive traffic on the transport - // in this pipeline's m-line, or the transport in the "master" m-line for - // the bundle. We need to be ready for either. Once this ambiguity is - // resolved, the transport we know that we'll be using will be set in - // rtp_transport_ and rtcp_transport_, and these will be unset. - // TODO(bcampen@mozilla.com): I'm pretty sure this could be leveraged for - // re-offer with a new address on an m-line too, with a little work. - nsAutoPtr possible_bundle_rtp_; - nsAutoPtr possible_bundle_rtcp_; + RefPtr rtp_transport_; + State rtp_state_; + RefPtr rtcp_transport_; + State rtcp_state_; // Pointers to the threads we need. Initialized at creation // and used all over the place. @@ -261,8 +216,15 @@ class MediaPipeline : public sigslot::has_slots<> { // destroyed on the STS thread. RefPtr transport_; - // Only safe to access from STS thread. - // Build into TransportInfo? + // Used only on STS thread. + RefPtr rtp_send_srtp_; + RefPtr rtcp_send_srtp_; + RefPtr rtp_recv_srtp_; + RefPtr rtcp_recv_srtp_; + + // Written only on STS thread. May be read on other + // threads but since there is no mutex, the values + // will only be approximate. int32_t rtp_packets_sent_; int32_t rtcp_packets_sent_; int32_t rtp_packets_received_; @@ -274,10 +236,6 @@ class MediaPipeline : public sigslot::has_slots<> { std::string pc_; std::string description_; - // Written on Init, all following accesses are on the STS thread. - nsAutoPtr filter_; - nsAutoPtr rtp_parser_; - private: nsresult Init_s(); @@ -386,7 +344,7 @@ class MediaPipelineTransmit : public MediaPipeline { } // Override MediaPipeline::TransportReady. - virtual nsresult TransportReady_s(TransportInfo &info); + virtual nsresult TransportReady_s(TransportFlow *flow); // Separate class to allow ref counting class PipelineListener : public MediaStreamDirectListener { @@ -487,26 +445,11 @@ class MediaPipelineReceive : public MediaPipeline { int level, RefPtr conduit, RefPtr rtp_transport, - RefPtr rtcp_transport, - RefPtr bundle_rtp_transport, - RefPtr bundle_rtcp_transport, - nsAutoPtr filter) : + RefPtr rtcp_transport) : MediaPipeline(pc, RECEIVE, main_thread, sts_thread, stream, track_id, level, conduit, rtp_transport, rtcp_transport), segments_added_(0) { - filter_ = filter; - rtp_parser_ = webrtc::RtpHeaderParser::Create(); - if (bundle_rtp_transport) { - if (bundle_rtcp_transport) { - MOZ_ASSERT(bundle_rtp_transport != bundle_rtcp_transport); - possible_bundle_rtp_ = new TransportInfo(bundle_rtp_transport, RTP); - possible_bundle_rtcp_ = new TransportInfo(bundle_rtcp_transport, RTCP); - } else { - possible_bundle_rtp_ = new TransportInfo(bundle_rtp_transport, MUX); - possible_bundle_rtcp_ = new TransportInfo(bundle_rtp_transport, MUX); - } - } } int segments_added() const { return segments_added_; } @@ -530,14 +473,10 @@ class MediaPipelineReceiveAudio : public MediaPipelineReceive { int level, RefPtr conduit, RefPtr rtp_transport, - RefPtr rtcp_transport, - RefPtr bundle_rtp_transport, - RefPtr bundle_rtcp_transport, - nsAutoPtr filter) : + RefPtr rtcp_transport) : MediaPipelineReceive(pc, main_thread, sts_thread, stream, track_id, level, conduit, rtp_transport, - rtcp_transport, bundle_rtp_transport, - bundle_rtcp_transport, filter), + rtcp_transport), listener_(new PipelineListener(stream->AsSourceStream(), track_id, conduit)) { } @@ -597,14 +536,10 @@ class MediaPipelineReceiveVideo : public MediaPipelineReceive { int level, RefPtr conduit, RefPtr rtp_transport, - RefPtr rtcp_transport, - RefPtr bundle_rtp_transport, - RefPtr bundle_rtcp_transport, - nsAutoPtr filter) : + RefPtr rtcp_transport) : MediaPipelineReceive(pc, main_thread, sts_thread, stream, track_id, level, conduit, rtp_transport, - rtcp_transport, bundle_rtp_transport, - bundle_rtcp_transport, filter), + rtcp_transport), renderer_(new PipelineRenderer(MOZ_THIS_IN_INITIALIZER_LIST())), listener_(new PipelineListener(stream->AsSourceStream(), track_id)) { } diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp index 84a77a79c0a0..b14b82709742 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionImpl.cpp @@ -1327,11 +1327,9 @@ PeerConnectionImpl::GetStats(MediaStreamTrack *aSelector, bool internalStats) { if (temp.get()) { streams.push_back(temp); } else { - CSFLogError(logTag, "Failed to get NrIceMediaStream for level %zu " + CSFLogError(logTag, "Failed to get NrIceMediaStream for level %u " "in %s: %s", - static_cast(level), - __FUNCTION__, - mHandle.c_str()); + uint32_t(level), __FUNCTION__, mHandle.c_str()); MOZ_CRASH(); } } diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp index b6748455314d..4504ab82ce71 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp @@ -396,40 +396,6 @@ PeerConnectionMedia::GetRemoteStream(int aIndex) return mRemoteSourceStreams[aIndex]; } -bool -PeerConnectionMedia::SetUsingBundle_m(int level, bool decision) -{ - ASSERT_ON_THREAD(mMainThread); - for (size_t i = 0; i < mRemoteSourceStreams.Length(); ++i) { - if (mRemoteSourceStreams[i]->SetUsingBundle_m(level, decision)) { - // Found the MediaPipeline for |level| - return true; - } - } - CSFLogWarn(logTag, "Could not locate level %d to set bundle flag to %s", - static_cast(level), - decision ? "true" : "false"); - return false; -} - -bool -PeerConnectionMedia::UpdateFilterFromRemoteDescription_m( - int level, - nsAutoPtr filter) -{ - ASSERT_ON_THREAD(mMainThread); - for (size_t i = 0; i < mRemoteSourceStreams.Length(); ++i) { - if (mRemoteSourceStreams[i]->UpdateFilterFromRemoteDescription_m(level, - filter)) { - // Found the MediaPipeline for |level| - return true; - } - } - CSFLogWarn(logTag, "Could not locate level %d to update filter", - static_cast(level)); - return false; -} - nsresult PeerConnectionMedia::AddRemoteStream(nsRefPtr aInfo, int *aIndex) @@ -537,68 +503,5 @@ RemoteSourceStreamInfo::StorePipeline(int aTrack, mTypes[aTrack] = aIsVideo; } -RefPtr RemoteSourceStreamInfo::GetPipelineByLevel_m(int level) { - ASSERT_ON_THREAD(mParent->GetMainThread()); - for (auto p = mPipelines.begin(); p != mPipelines.end(); ++p) { - if (p->second->level() == level) { - return p->second; - } - } - return nullptr; -} - -bool RemoteSourceStreamInfo::UpdateFilterFromRemoteDescription_m( - int aLevel, - nsAutoPtr aFilter) { - ASSERT_ON_THREAD(mParent->GetMainThread()); - - if (!mMediaStream) { - // Guard against dispatching once we've started teardown, since we don't - // want the RefPtr being the last one standing on the call - // to MediaPipeline::UpdateFilterFromRemoteDescription_s; it is not safe - // to delete a MediaPipeline anywhere other than the main thread. - return false; - } - - RefPtr pipeline(GetPipelineByLevel_m(aLevel)); - - if (pipeline) { - RUN_ON_THREAD(mParent->GetSTSThread(), - WrapRunnable( - pipeline, - &MediaPipeline::UpdateFilterFromRemoteDescription_s, - aFilter - ), - NS_DISPATCH_NORMAL); - return true; - } - return false; -} - -bool RemoteSourceStreamInfo::SetUsingBundle_m(int aLevel, bool decision) { - ASSERT_ON_THREAD(mParent->GetMainThread()); - - if (!mMediaStream) { - // Guard against dispatching once we've started teardown, since we don't - // want the RefPtr being the last one standing on the call - // to MediaPipeline::SetUsingBundle_s; it is not safe - // to delete a MediaPipeline anywhere other than the main thread. - return false; - } - - RefPtr pipeline(GetPipelineByLevel_m(aLevel)); - - if (pipeline) { - RUN_ON_THREAD(mParent->GetSTSThread(), - WrapRunnable( - pipeline, - &MediaPipeline::SetUsingBundle_s, - decision - ), - NS_DISPATCH_NORMAL); - return true; - } - return false; -} } // namespace sipcc diff --git a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h index 4ec5cd614b56..b5e25017f3d8 100644 --- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h +++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.h @@ -244,11 +244,6 @@ class RemoteSourceStreamInfo : public SourceStreamInfo { void StorePipeline(int aTrack, bool aIsVideo, mozilla::RefPtr aPipeline); - bool UpdateFilterFromRemoteDescription_m( - int aLevel, - nsAutoPtr aFilter); - bool SetUsingBundle_m(int aLevel, bool decision); - void DetachTransport_s(); void DetachMedia_m(); @@ -257,7 +252,6 @@ class RemoteSourceStreamInfo : public SourceStreamInfo { public: DOMMediaStream::TrackTypeHints mTrackTypeHints; private: - mozilla::RefPtr GetPipelineByLevel_m(int level); std::map mTypes; }; @@ -302,11 +296,6 @@ class PeerConnectionMedia : public sigslot::has_slots<> { } RemoteSourceStreamInfo* GetRemoteStream(int index); - bool SetUsingBundle_m(int level, bool decision); - bool UpdateFilterFromRemoteDescription_m( - int level, - nsAutoPtr filter); - // Add a remote stream. Returns the index in index nsresult AddRemoteStream(nsRefPtr aInfo, int *aIndex); nsresult AddRemoteStreamHint(int aIndex, bool aIsVideo); diff --git a/media/webrtc/signaling/test/mediapipeline_unittest.cpp b/media/webrtc/signaling/test/mediapipeline_unittest.cpp index 5904843e0530..bee43898244b 100644 --- a/media/webrtc/signaling/test/mediapipeline_unittest.cpp +++ b/media/webrtc/signaling/test/mediapipeline_unittest.cpp @@ -114,20 +114,10 @@ class TestAgent { audio_pipeline_() { } - void ConnectRtpSocket(PRFileDesc *fd, bool client) { - ConnectSocket(&audio_rtp_transport_, fd, client); - } - - void ConnectRtcpSocket(PRFileDesc *fd, bool client) { - ConnectSocket(&audio_rtcp_transport_, fd, client); - } - - void ConnectBundleSocket(PRFileDesc *fd, bool client) { - ConnectSocket(&bundle_transport_, fd, client); - } - - void ConnectSocket(TransportInfo *transport, PRFileDesc *fd, bool client) { + void ConnectSocket(PRFileDesc *fd, bool client, bool isRtcp) { nsresult res; + TransportInfo *transport = isRtcp ? + &audio_rtcp_transport_ : &audio_rtp_transport_; transport->Init(client); @@ -160,7 +150,6 @@ class TestAgent { audio_->GetStream()->Stop(); audio_rtp_transport_.Stop(); audio_rtcp_transport_.Stop(); - bundle_transport_.Stop(); if (audio_pipeline_) audio_pipeline_->ShutdownTransport_s(); } @@ -187,13 +176,10 @@ class TestAgent { mozilla::RefPtr audio_pipeline_; TransportInfo audio_rtp_transport_; TransportInfo audio_rtcp_transport_; - TransportInfo bundle_transport_; }; class TestAgentSend : public TestAgent { public: - TestAgentSend() : use_bundle_(false) {} - virtual void CreatePipelines_s(bool aIsRtcpMux) { audio_ = new Fake_DOMMediaStream(new Fake_AudioStreamSource()); @@ -208,14 +194,6 @@ class TestAgentSend : public TestAgent { ASSERT_FALSE(audio_rtcp_transport_.flow_); } - RefPtr rtp(audio_rtp_transport_.flow_); - RefPtr rtcp(audio_rtcp_transport_.flow_); - - if (use_bundle_) { - rtp = bundle_transport_.flow_; - rtcp = nullptr; - } - audio_pipeline_ = new mozilla::MediaPipelineTransmit( test_pc, nullptr, @@ -224,8 +202,8 @@ class TestAgentSend : public TestAgent { 1, 1, audio_conduit_, - rtp, - rtcp); + audio_rtp_transport_.flow_, + audio_rtcp_transport_.flow_); audio_pipeline_->Init(); } @@ -238,12 +216,7 @@ class TestAgentSend : public TestAgent { return audio_pipeline_->rtcp_packets_received(); } - void SetUsingBundle(bool use_bundle) { - use_bundle_ = use_bundle; - } - private: - bool use_bundle_; }; @@ -273,24 +246,13 @@ class TestAgentReceive : public TestAgent { ASSERT_FALSE(audio_rtcp_transport_.flow_); } - // For now, assume bundle always uses rtcp mux - RefPtr dummy; - RefPtr bundle_transport; - if (bundle_filter_) { - bundle_transport = bundle_transport_.flow_; - } - audio_pipeline_ = new mozilla::MediaPipelineReceiveAudio( test_pc, nullptr, test_utils->sts_target(), audio_->GetStream(), 1, 1, static_cast(audio_conduit_.get()), - audio_rtp_transport_.flow_, - audio_rtcp_transport_.flow_, - bundle_transport, - dummy, - bundle_filter_); + audio_rtp_transport_.flow_, audio_rtcp_transport_.flow_); audio_pipeline_->Init(); } @@ -303,20 +265,7 @@ class TestAgentReceive : public TestAgent { return audio_pipeline_->rtcp_packets_sent(); } - void SetBundleFilter(nsAutoPtr filter) { - bundle_filter_ = filter; - } - - void SetUsingBundle_s(bool decision) { - audio_pipeline_->SetUsingBundle_s(decision); - } - - void UpdateFilterFromRemoteDescription_s( - nsAutoPtr filter) { - audio_pipeline_->UpdateFilterFromRemoteDescription_s(filter); - } private: - nsAutoPtr bundle_filter_; }; @@ -325,7 +274,6 @@ class MediaPipelineTest : public ::testing::Test { MediaPipelineTest() : p1_() { rtp_fds_[0] = rtp_fds_[1] = nullptr; rtcp_fds_[0] = rtcp_fds_[1] = nullptr; - bundle_fds_[0] = bundle_fds_[1] = nullptr; } // Setup transport. @@ -337,12 +285,12 @@ class MediaPipelineTest : public ::testing::Test { // RTP, DTLS server mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), - WrapRunnable(&p1_, &TestAgent::ConnectRtpSocket, rtp_fds_[0], false)); + WrapRunnable(&p1_, &TestAgent::ConnectSocket, rtp_fds_[0], false, false)); // RTP, DTLS client mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), - WrapRunnable(&p2_, &TestAgent::ConnectRtpSocket, rtp_fds_[1], true)); + WrapRunnable(&p2_, &TestAgent::ConnectSocket, rtp_fds_[1], true, false)); // Create RTCP flows separately if we are not muxing them. if(!aIsRtcpMux) { @@ -352,48 +300,17 @@ class MediaPipelineTest : public ::testing::Test { // RTCP, DTLS server mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), - WrapRunnable(&p1_, &TestAgent::ConnectRtcpSocket, rtcp_fds_[0], false)); + WrapRunnable(&p1_, &TestAgent::ConnectSocket, rtcp_fds_[0], false, true)); // RTCP, DTLS client mozilla::SyncRunnable::DispatchToThread( test_utils->sts_target(), - WrapRunnable(&p2_, &TestAgent::ConnectRtcpSocket, rtcp_fds_[1], true)); + WrapRunnable(&p2_, &TestAgent::ConnectSocket, rtcp_fds_[1], true, true)); } - - status = PR_NewTCPSocketPair(bundle_fds_); - // BUNDLE, DTLS server - mozilla::SyncRunnable::DispatchToThread( - test_utils->sts_target(), - WrapRunnable(&p1_, - &TestAgent::ConnectBundleSocket, - bundle_fds_[0], - false)); - - // BUNDLE, DTLS client - mozilla::SyncRunnable::DispatchToThread( - test_utils->sts_target(), - WrapRunnable(&p2_, - &TestAgent::ConnectBundleSocket, - bundle_fds_[1], - true)); - } // Verify RTP and RTCP - void TestAudioSend(bool aIsRtcpMux, - bool bundle = false, - nsAutoPtr localFilter = - nsAutoPtr(nullptr), - nsAutoPtr remoteFilter = - nsAutoPtr(nullptr)) { - - // We do not support testing bundle without rtcp mux, since that doesn't - // make any sense. - ASSERT_FALSE(!aIsRtcpMux && bundle); - - p1_.SetUsingBundle(bundle); - p2_.SetBundleFilter(localFilter); - + void TestAudioSend(bool aIsRtcpMux) { // Setup transport flows InitTransports(aIsRtcpMux); @@ -408,51 +325,22 @@ class MediaPipelineTest : public ::testing::Test { p2_.Start(); p1_.Start(); - // Simulate pre-answer traffic - PR_Sleep(500); - - mozilla::SyncRunnable::DispatchToThread( - test_utils->sts_target(), - WrapRunnable(&p2_, &TestAgentReceive::SetUsingBundle_s, bundle)); - - if (bundle) { - if (!remoteFilter) { - remoteFilter = new MediaPipelineFilter; - } - mozilla::SyncRunnable::DispatchToThread( - test_utils->sts_target(), - WrapRunnable(&p2_, - &TestAgentReceive::UpdateFilterFromRemoteDescription_s, - remoteFilter)); - } - - // wait for some RTP/RTCP tx and rx to happen PR_Sleep(10000); - if (bundle) { - // Filter should have eaten everything, so no RTCP - } else { - ASSERT_GE(p1_.GetAudioRtpCount(), 40); + ASSERT_GE(p1_.GetAudioRtpCount(), 40); // TODO: Fix to not fail or crash (Bug 947663) // ASSERT_GE(p2_.GetAudioRtpCount(), 40); - ASSERT_GE(p2_.GetAudioRtcpCount(), 1); - } + ASSERT_GE(p1_.GetAudioRtcpCount(), 1); + ASSERT_GE(p2_.GetAudioRtcpCount(), 1); p1_.Stop(); p2_.Stop(); } - void TestAudioReceiverOffersBundle(bool bundle_accepted, - nsAutoPtr localFilter, - nsAutoPtr remoteFilter = - nsAutoPtr(nullptr)) { - TestAudioSend(true, bundle_accepted, localFilter, remoteFilter); - } protected: PRFileDesc *rtp_fds_[2]; PRFileDesc *rtcp_fds_[2]; - PRFileDesc *bundle_fds_[2]; TestAgentSend p1_; TestAgentReceive p2_; }; @@ -825,7 +713,7 @@ TEST_F(MediaPipelineFilterTest, TestSSRCMovedWithCorrelator) { TEST_F(MediaPipelineFilterTest, TestRemoteSDPNoSSRCs) { // If the remote SDP doesn't have SSRCs, right now this is a no-op and - // there is no point of even incorporating a filter, but we make the + // there is no point of even incorporating a filter, but we make the // behavior consistent to avoid confusion. MediaPipelineFilter filter; filter.SetCorrelator(7777); @@ -848,16 +736,6 @@ TEST_F(MediaPipelineTest, TestAudioSendMux) { TestAudioSend(true); } -TEST_F(MediaPipelineTest, TestAudioSendBundleOfferedAndDeclined) { - nsAutoPtr filter(new MediaPipelineFilter); - TestAudioReceiverOffersBundle(false, filter); -} - -TEST_F(MediaPipelineTest, TestAudioSendBundleOfferedAndAccepted) { - nsAutoPtr filter(new MediaPipelineFilter); - TestAudioReceiverOffersBundle(true, filter); -} - } // end namespace From 647ea2ac5a936641bfd6c53dac91b0a249309ee7 Mon Sep 17 00:00:00 2001 From: "Adam Roach [:abr]" Date: Mon, 24 Feb 2014 12:29:10 -0600 Subject: [PATCH 41/48] Backed out changeset 53d8b186e574 (bug 786234) --- media/webrtc/moz.build | 1 - .../signaling/src/mediapipeline/MediaPipelineFilter.cpp | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/media/webrtc/moz.build b/media/webrtc/moz.build index 0b7152d4de93..12ea7d13e099 100644 --- a/media/webrtc/moz.build +++ b/media/webrtc/moz.build @@ -64,7 +64,6 @@ if CONFIG['MOZ_WEBRTC_SIGNALING']: 'signaling/src/media/CSFVideoControlWrapper.cpp', 'signaling/src/media/VcmSIPCCBinding.cpp', 'signaling/src/mediapipeline/MediaPipeline.cpp', - 'signaling/src/mediapipeline/MediaPipelineFilter.cpp', 'signaling/src/mediapipeline/SrtpFlow.cpp', 'signaling/src/peerconnection/MediaStreamList.cpp', 'signaling/src/peerconnection/PeerConnectionCtx.cpp', diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp b/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp index 93ce053ac2e7..195e89ce4a07 100644 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp @@ -7,10 +7,10 @@ // Original author: bcampen@mozilla.com -#include "logging.h" - #include "MediaPipelineFilter.h" +#include "logging.h" + #include "webrtc/modules/interface/module_common_types.h" // Logging context From 114fcd66752c7cefa49ee6fa249a2855ee98ec5c Mon Sep 17 00:00:00 2001 From: "Adam Roach [:abr]" Date: Mon, 24 Feb 2014 12:29:10 -0600 Subject: [PATCH 42/48] Backed out changeset 1dea344fa608 (bug 786234) --- .../src/mediapipeline/MediaPipelineFilter.cpp | 110 +------ .../src/mediapipeline/MediaPipelineFilter.h | 37 +-- .../signaling/test/mediapipeline_unittest.cpp | 274 ++---------------- 3 files changed, 34 insertions(+), 387 deletions(-) diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp b/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp index 195e89ce4a07..cb036e0e86f2 100644 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp @@ -9,13 +9,8 @@ #include "MediaPipelineFilter.h" -#include "logging.h" - #include "webrtc/modules/interface/module_common_types.h" -// Logging context -MOZ_MTLOG_MODULE("mediapipeline") - namespace mozilla { MediaPipelineFilter::MediaPipelineFilter() : correlator_(0) { @@ -52,6 +47,14 @@ bool MediaPipelineFilter::Filter(const webrtc::RTPHeader& header, return false; } +bool MediaPipelineFilter::FilterRTCP(uint32_t ssrc) { + return remote_ssrc_set_.count(ssrc) != 0; +} + +bool MediaPipelineFilter::FilterRTCPReceiverReport(uint32_t ssrc) { + return local_ssrc_set_.count(ssrc) != 0; +} + void MediaPipelineFilter::AddLocalSSRC(uint32_t ssrc) { local_ssrc_set_.insert(ssrc); } @@ -80,103 +83,6 @@ void MediaPipelineFilter::IncorporateRemoteDescription( // SDP doesn't tell us anything about what we will be receiving. } -MediaPipelineFilter::Result -MediaPipelineFilter::FilterRTCP(const unsigned char* data, - size_t len) const { - if (len < FIRST_SSRC_OFFSET) { - return FAIL; - } - - uint8_t payload_type = data[PT_OFFSET]; - - switch (payload_type) { - case SENDER_REPORT_T: - return CheckRtcpReport(data, len, RECEIVER_REPORT_START_SR) ? PASS : FAIL; - case RECEIVER_REPORT_T: - return CheckRtcpReport(data, len, SENDER_REPORT_START_RR) ? PASS : FAIL; - default: - return UNSUPPORTED; - } - - return UNSUPPORTED; -} - -bool MediaPipelineFilter::CheckRtcpSsrc(const unsigned char* data, - size_t len, - size_t ssrc_offset, - uint8_t flags) const { - if (ssrc_offset + 4 > len) { - return false; - } - - uint32_t ssrc = 0; - ssrc += (uint32_t)data[ssrc_offset++] << 24; - ssrc += (uint32_t)data[ssrc_offset++] << 16; - ssrc += (uint32_t)data[ssrc_offset++] << 8; - ssrc += (uint32_t)data[ssrc_offset++]; - - if (flags | MAYBE_LOCAL_SSRC) { - if (local_ssrc_set_.count(ssrc)) { - return true; - } - } - - if (flags | MAYBE_REMOTE_SSRC) { - if (remote_ssrc_set_.count(ssrc)) { - return true; - } - } - return false; -} - -static uint8_t GetCount(const unsigned char* data, size_t len) { - // This might be a count of rr reports, or might be a count of stuff like - // SDES reports, or what-have-you. They all live in bits 3-7. - return data[0] & 0x1F; -} - -bool MediaPipelineFilter::CheckRtcpReport(const unsigned char* data, - size_t len, - size_t first_rr_offset) const { - bool remote_ssrc_matched = CheckRtcpSsrc(data, - len, - FIRST_SSRC_OFFSET, - MAYBE_REMOTE_SSRC); - - uint8_t rr_count = GetCount(data, len); - - // We need to check for consistency. If the remote ssrc matched, the local - // ssrcs must too. If it did not, this may just be because our filter is - // incomplete, so the local ssrcs could go either way. - bool ssrcs_must_match = remote_ssrc_matched; - bool ssrcs_must_not_match = false; - - for (uint8_t rr_num = 0; rr_num < rr_count; ++rr_num) { - size_t ssrc_offset = first_rr_offset + (rr_num * RECEIVER_REPORT_SIZE); - - if (!CheckRtcpSsrc(data, len, ssrc_offset, MAYBE_LOCAL_SSRC)) { - ssrcs_must_not_match = true; - if (ssrcs_must_match) { - break; - } - } else { - ssrcs_must_match = true; - if (ssrcs_must_not_match) { - break; - } - } - } - - if (ssrcs_must_match && ssrcs_must_not_match) { - MOZ_MTLOG(ML_ERROR, "Received an RTCP packet with SSRCs from " - "multiple m-lines! This is broken."); - return false; - } - - // This is set if any ssrc matched - return ssrcs_must_match; -} - } // end namespace mozilla diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.h b/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.h index ff8fa4a794ba..61a9741547b3 100644 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.h +++ b/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.h @@ -52,15 +52,12 @@ class MediaPipelineFilter { // the filter about ssrcs) bool Filter(const webrtc::RTPHeader& header, uint32_t correlator = 0); - typedef enum { - FAIL, - PASS, - UNSUPPORTED - } Result; - // RTCP doesn't have things like the RTP correlator, and uses its own // payload types too. - Result FilterRTCP(const unsigned char* data, size_t len) const; + // RTCP receiver reports use _our_ ssrcs + bool FilterRTCPReceiverReport(uint32_t ssrc); + // The rest of RTCP uses their ssrcs + bool FilterRTCP(uint32_t ssrc); void AddLocalSSRC(uint32_t ssrc); void AddRemoteSSRC(uint32_t ssrc); @@ -71,33 +68,7 @@ class MediaPipelineFilter { void IncorporateRemoteDescription(const MediaPipelineFilter& remote_filter); - // Some payload types - static const uint8_t SENDER_REPORT_T = 200; - static const uint8_t RECEIVER_REPORT_T = 201; - private: - static const uint8_t MAYBE_LOCAL_SSRC = 1; - static const uint8_t MAYBE_REMOTE_SSRC = 2; - - // Payload type is always in the second byte - static const size_t PT_OFFSET = 1; - // First SSRC always starts at the fifth byte. - static const size_t FIRST_SSRC_OFFSET = 4; - - static const size_t RECEIVER_REPORT_START_SR = 7*4; - static const size_t SENDER_REPORT_START_RR = 2*4; - static const size_t RECEIVER_REPORT_SIZE = 6*4; - - bool CheckRtcpSsrc(const unsigned char* data, - size_t len, - size_t ssrc_offset, - uint8_t flags) const; - - - bool CheckRtcpReport(const unsigned char* data, - size_t len, - size_t first_rr_offset) const; - uint32_t correlator_; // The number of filters we manage here is quite small, so I am optimizing // for readability. diff --git a/media/webrtc/signaling/test/mediapipeline_unittest.cpp b/media/webrtc/signaling/test/mediapipeline_unittest.cpp index bee43898244b..87a808278de3 100644 --- a/media/webrtc/signaling/test/mediapipeline_unittest.cpp +++ b/media/webrtc/signaling/test/mediapipeline_unittest.cpp @@ -375,261 +375,32 @@ TEST_F(MediaPipelineFilterTest, TestSSRCFilter) { ASSERT_FALSE(Filter(filter, 0, 556, 110)); } -#define SSRC(ssrc) \ - ((ssrc >> 24) & 0xFF), \ - ((ssrc >> 16) & 0xFF), \ - ((ssrc >> 8 ) & 0xFF), \ - (ssrc & 0xFF) - -#define REPORT_FRAGMENT(ssrc) \ - SSRC(ssrc), \ - 0,0,0,0, \ - 0,0,0,0, \ - 0,0,0,0, \ - 0,0,0,0, \ - 0,0,0,0 - -#define RTCP_TYPEINFO(num_rrs, type, size) \ - 0x80 + num_rrs, type, 0, size - -const unsigned char rtcp_rr_s16[] = { - // zero rrs, size 1 words - RTCP_TYPEINFO(0, MediaPipelineFilter::RECEIVER_REPORT_T, 1), - SSRC(16) -}; - -const unsigned char rtcp_rr_s16_r17[] = { - // one rr, 7 words - RTCP_TYPEINFO(1, MediaPipelineFilter::RECEIVER_REPORT_T, 7), - SSRC(16), - REPORT_FRAGMENT(17) -}; - -const unsigned char rtcp_rr_s16_r17_18[] = { - // two rrs, size 13 words - RTCP_TYPEINFO(2, MediaPipelineFilter::RECEIVER_REPORT_T, 13), - SSRC(16), - REPORT_FRAGMENT(17), - REPORT_FRAGMENT(18) -}; - -const unsigned char rtcp_sr_s16[] = { - // zero rrs, size 6 words - RTCP_TYPEINFO(0, MediaPipelineFilter::SENDER_REPORT_T, 6), - REPORT_FRAGMENT(16) -}; - -const unsigned char rtcp_sr_s16_r17[] = { - // one rr, size 12 words - RTCP_TYPEINFO(1, MediaPipelineFilter::SENDER_REPORT_T, 12), - REPORT_FRAGMENT(16), - REPORT_FRAGMENT(17) -}; - -const unsigned char rtcp_sr_s16_r17_18[] = { - // two rrs, size 18 words - RTCP_TYPEINFO(2, MediaPipelineFilter::SENDER_REPORT_T, 18), - REPORT_FRAGMENT(16), - REPORT_FRAGMENT(17), - REPORT_FRAGMENT(18) -}; - -const unsigned char unknown_type[] = { - RTCP_TYPEINFO(1, 222, 0) -}; - -TEST_F(MediaPipelineFilterTest, TestEmptyFilterReport0) { +TEST_F(MediaPipelineFilterTest, TestSSRCFilterRTCP) { MediaPipelineFilter filter; - ASSERT_EQ(MediaPipelineFilter::FAIL, - filter.FilterRTCP(rtcp_sr_s16, sizeof(rtcp_sr_s16))); - ASSERT_EQ(MediaPipelineFilter::FAIL, - filter.FilterRTCP(rtcp_rr_s16, sizeof(rtcp_rr_s16))); + filter.AddRemoteSSRC(555); + ASSERT_TRUE(filter.FilterRTCP(555)); + ASSERT_FALSE(filter.FilterRTCP(556)); + ASSERT_FALSE(filter.FilterRTCPReceiverReport(555)); } -TEST_F(MediaPipelineFilterTest, TestFilterReport0) { +TEST_F(MediaPipelineFilterTest, TestSSRCFilterReceiverReport) { MediaPipelineFilter filter; - filter.AddRemoteSSRC(16); - ASSERT_EQ(MediaPipelineFilter::PASS, - filter.FilterRTCP(rtcp_sr_s16, sizeof(rtcp_sr_s16))); - ASSERT_EQ(MediaPipelineFilter::PASS, - filter.FilterRTCP(rtcp_rr_s16, sizeof(rtcp_rr_s16))); -} - -TEST_F(MediaPipelineFilterTest, TestFilterReport0SSRCTruncated) { - MediaPipelineFilter filter; - filter.AddRemoteSSRC(16); - const unsigned char data[] = { - RTCP_TYPEINFO(0, MediaPipelineFilter::RECEIVER_REPORT_T, 1), - 0,0,0 - }; - ASSERT_EQ(MediaPipelineFilter::FAIL, - filter.FilterRTCP(data, sizeof(data))); -} - -TEST_F(MediaPipelineFilterTest, TestFilterReport0PTTruncated) { - MediaPipelineFilter filter; - filter.AddRemoteSSRC(16); - const unsigned char data[] = {0x80}; - ASSERT_EQ(MediaPipelineFilter::FAIL, - filter.FilterRTCP(data, sizeof(data))); -} - -TEST_F(MediaPipelineFilterTest, TestFilterReport0CountTruncated) { - MediaPipelineFilter filter; - filter.AddRemoteSSRC(16); - const unsigned char data[] = {}; - ASSERT_EQ(MediaPipelineFilter::FAIL, - filter.FilterRTCP(data, sizeof(data))); -} - -TEST_F(MediaPipelineFilterTest, TestFilterReport1BothMatch) { - MediaPipelineFilter filter; - filter.AddRemoteSSRC(16); - filter.AddLocalSSRC(17); - ASSERT_EQ(MediaPipelineFilter::PASS, - filter.FilterRTCP(rtcp_sr_s16_r17, sizeof(rtcp_sr_s16_r17))); - ASSERT_EQ(MediaPipelineFilter::PASS, - filter.FilterRTCP(rtcp_rr_s16_r17, sizeof(rtcp_rr_s16_r17))); -} - -TEST_F(MediaPipelineFilterTest, TestFilterReport1SSRCTruncated) { - MediaPipelineFilter filter; - filter.AddRemoteSSRC(16); - filter.AddLocalSSRC(17); - const unsigned char rr[] = { - RTCP_TYPEINFO(1, MediaPipelineFilter::RECEIVER_REPORT_T, 7), - SSRC(16), - 0,0,0 - }; - ASSERT_EQ(MediaPipelineFilter::FAIL, - filter.FilterRTCP(rr, sizeof(rr))); - const unsigned char sr[] = { - RTCP_TYPEINFO(1, MediaPipelineFilter::RECEIVER_REPORT_T, 12), - REPORT_FRAGMENT(16), - 0,0,0 - }; - ASSERT_EQ(MediaPipelineFilter::FAIL, - filter.FilterRTCP(sr, sizeof(rr))); -} - -TEST_F(MediaPipelineFilterTest, TestFilterReport1BigSSRC) { - MediaPipelineFilter filter; - filter.AddRemoteSSRC(0x01020304); - filter.AddLocalSSRC(0x11121314); - const unsigned char rr[] = { - RTCP_TYPEINFO(1, MediaPipelineFilter::RECEIVER_REPORT_T, 7), - SSRC(0x01020304), - REPORT_FRAGMENT(0x11121314) - }; - ASSERT_EQ(MediaPipelineFilter::PASS, - filter.FilterRTCP(rr, sizeof(rr))); - const unsigned char sr[] = { - RTCP_TYPEINFO(1, MediaPipelineFilter::RECEIVER_REPORT_T, 12), - SSRC(0x01020304), - REPORT_FRAGMENT(0x11121314) - }; - ASSERT_EQ(MediaPipelineFilter::PASS, - filter.FilterRTCP(sr, sizeof(rr))); -} - -TEST_F(MediaPipelineFilterTest, TestFilterReport1LocalMatch) { - MediaPipelineFilter filter; - filter.AddLocalSSRC(17); - ASSERT_EQ(MediaPipelineFilter::PASS, - filter.FilterRTCP(rtcp_sr_s16_r17, sizeof(rtcp_sr_s16_r17))); - ASSERT_EQ(MediaPipelineFilter::PASS, - filter.FilterRTCP(rtcp_rr_s16_r17, sizeof(rtcp_rr_s16_r17))); -} - -TEST_F(MediaPipelineFilterTest, TestFilterReport1Inconsistent) { - MediaPipelineFilter filter; - filter.AddRemoteSSRC(16); - // We assume that the filter is exactly correct in terms of local ssrcs. - // So, when RTCP shows up with a remote SSRC that matches, and a local - // ssrc that doesn't, we assume the other end has messed up and put ssrcs - // from more than one m-line in the packet. - ASSERT_EQ(MediaPipelineFilter::FAIL, - filter.FilterRTCP(rtcp_sr_s16_r17, sizeof(rtcp_sr_s16_r17))); - ASSERT_EQ(MediaPipelineFilter::FAIL, - filter.FilterRTCP(rtcp_rr_s16_r17, sizeof(rtcp_rr_s16_r17))); -} - -TEST_F(MediaPipelineFilterTest, TestFilterReport1NeitherMatch) { - MediaPipelineFilter filter; - filter.AddRemoteSSRC(17); - filter.AddLocalSSRC(18); - ASSERT_EQ(MediaPipelineFilter::PASS, - filter.FilterRTCP(rtcp_sr_s16_r17, sizeof(rtcp_sr_s16_r17))); - ASSERT_EQ(MediaPipelineFilter::PASS, - filter.FilterRTCP(rtcp_rr_s16_r17, sizeof(rtcp_rr_s16_r17))); -} - -TEST_F(MediaPipelineFilterTest, TestFilterReport2AllMatch) { - MediaPipelineFilter filter; - filter.AddRemoteSSRC(16); - filter.AddLocalSSRC(17); - filter.AddLocalSSRC(18); - ASSERT_EQ(MediaPipelineFilter::PASS, - filter.FilterRTCP(rtcp_sr_s16_r17_18, - sizeof(rtcp_sr_s16_r17_18))); -} - -TEST_F(MediaPipelineFilterTest, TestFilterReport2LocalMatch) { - MediaPipelineFilter filter; - filter.AddLocalSSRC(17); - filter.AddLocalSSRC(18); - ASSERT_EQ(MediaPipelineFilter::PASS, - filter.FilterRTCP(rtcp_sr_s16_r17_18, - sizeof(rtcp_sr_s16_r17_18))); - ASSERT_EQ(MediaPipelineFilter::PASS, - filter.FilterRTCP(rtcp_rr_s16_r17_18, - sizeof(rtcp_rr_s16_r17_18))); -} - -TEST_F(MediaPipelineFilterTest, TestFilterReport2Inconsistent101) { - MediaPipelineFilter filter; - filter.AddRemoteSSRC(16); - filter.AddLocalSSRC(18); - ASSERT_EQ(MediaPipelineFilter::FAIL, - filter.FilterRTCP(rtcp_sr_s16_r17_18, - sizeof(rtcp_sr_s16_r17_18))); - ASSERT_EQ(MediaPipelineFilter::FAIL, - filter.FilterRTCP(rtcp_rr_s16_r17_18, - sizeof(rtcp_rr_s16_r17_18))); -} - -TEST_F(MediaPipelineFilterTest, TestFilterReport2Inconsistent001) { - MediaPipelineFilter filter; - filter.AddLocalSSRC(18); - ASSERT_EQ(MediaPipelineFilter::FAIL, - filter.FilterRTCP(rtcp_sr_s16_r17_18, - sizeof(rtcp_sr_s16_r17_18))); - ASSERT_EQ(MediaPipelineFilter::FAIL, - filter.FilterRTCP(rtcp_rr_s16_r17_18, - sizeof(rtcp_rr_s16_r17_18))); -} - -TEST_F(MediaPipelineFilterTest, TestFilterUnknownRTCPType) { - MediaPipelineFilter filter; - filter.AddLocalSSRC(18); - ASSERT_EQ(MediaPipelineFilter::UNSUPPORTED, - filter.FilterRTCP(unknown_type, sizeof(unknown_type))); + filter.AddLocalSSRC(555); + ASSERT_TRUE(filter.FilterRTCPReceiverReport(555)); + ASSERT_FALSE(filter.FilterRTCPReceiverReport(556)); + ASSERT_FALSE(filter.FilterRTCP(555)); } TEST_F(MediaPipelineFilterTest, TestCorrelatorFilter) { MediaPipelineFilter filter; filter.SetCorrelator(7777); - ASSERT_TRUE(Filter(filter, 7777, 16, 110)); - ASSERT_FALSE(Filter(filter, 7778, 17, 110)); - // This should also have resulted in the SSRC 16 being added to the filter - ASSERT_TRUE(Filter(filter, 0, 16, 110)); - ASSERT_FALSE(Filter(filter, 0, 17, 110)); + ASSERT_TRUE(Filter(filter, 7777, 555, 110)); + ASSERT_FALSE(Filter(filter, 7778, 556, 110)); + // This should also have resulted in the SSRC 555 being added to the filter + ASSERT_TRUE(Filter(filter, 0, 555, 110)); + ASSERT_FALSE(Filter(filter, 0, 556, 110)); - // rtcp_sr_s16 has 16 as an SSRC - ASSERT_EQ(MediaPipelineFilter::PASS, - filter.FilterRTCP(rtcp_sr_s16, sizeof(rtcp_sr_s16))); - ASSERT_EQ(MediaPipelineFilter::PASS, - filter.FilterRTCP(rtcp_rr_s16, sizeof(rtcp_rr_s16))); + ASSERT_TRUE(filter.FilterRTCP(555)); } TEST_F(MediaPipelineFilterTest, TestPayloadTypeFilter) { @@ -642,11 +413,10 @@ TEST_F(MediaPipelineFilterTest, TestPayloadTypeFilter) { TEST_F(MediaPipelineFilterTest, TestPayloadTypeFilterSSRCUpdate) { MediaPipelineFilter filter; filter.AddUniquePT(110); - ASSERT_TRUE(Filter(filter, 0, 16, 110)); - - // rtcp_sr_s16 has 16 as an SSRC - ASSERT_EQ(MediaPipelineFilter::PASS, - filter.FilterRTCP(rtcp_sr_s16, sizeof(rtcp_sr_s16))); + ASSERT_TRUE(Filter(filter, 0, 555, 110)); + ASSERT_TRUE(filter.FilterRTCP(555)); + ASSERT_FALSE(filter.FilterRTCP(556)); + ASSERT_FALSE(filter.FilterRTCPReceiverReport(555)); } TEST_F(MediaPipelineFilterTest, TestAnswerAddsSSRCs) { @@ -713,8 +483,8 @@ TEST_F(MediaPipelineFilterTest, TestSSRCMovedWithCorrelator) { TEST_F(MediaPipelineFilterTest, TestRemoteSDPNoSSRCs) { // If the remote SDP doesn't have SSRCs, right now this is a no-op and - // there is no point of even incorporating a filter, but we make the - // behavior consistent to avoid confusion. + // there is no point of even incorporating a filter, but we make the behavior + // consistent to avoid confusion. MediaPipelineFilter filter; filter.SetCorrelator(7777); filter.AddUniquePT(111); From 1702c9b31d99716387398142da61c990911fd288 Mon Sep 17 00:00:00 2001 From: "Adam Roach [:abr]" Date: Mon, 24 Feb 2014 12:29:10 -0600 Subject: [PATCH 43/48] Backed out changeset 4f7eac2b16ca (bug 786234) --- media/webrtc/signaling/signaling.gyp | 2 - .../src/mediapipeline/MediaPipelineFilter.cpp | 88 ---------- .../src/mediapipeline/MediaPipelineFilter.h | 83 ---------- .../signaling/test/mediapipeline_unittest.cpp | 156 ------------------ media/webrtc/signaling/test/moz.build | 1 - 5 files changed, 330 deletions(-) delete mode 100644 media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp delete mode 100644 media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.h diff --git a/media/webrtc/signaling/signaling.gyp b/media/webrtc/signaling/signaling.gyp index 5c48579ca8f3..00bbd85f402a 100644 --- a/media/webrtc/signaling/signaling.gyp +++ b/media/webrtc/signaling/signaling.gyp @@ -155,8 +155,6 @@ # Media pipeline './src/mediapipeline/MediaPipeline.h', './src/mediapipeline/MediaPipeline.cpp', - './src/mediapipeline/MediaPipelineFilter.h', - './src/mediapipeline/MediaPipelineFilter.cpp', './src/mediapipeline/SrtpFlow.h', './src/mediapipeline/SrtpFlow.cpp', ], diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp b/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp deleted file mode 100644 index cb036e0e86f2..000000000000 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: softtabstop=2:shiftwidth=2:expandtab - * */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -// Original author: bcampen@mozilla.com - -#include "MediaPipelineFilter.h" - -#include "webrtc/modules/interface/module_common_types.h" - -namespace mozilla { - -MediaPipelineFilter::MediaPipelineFilter() : correlator_(0) { -} - -bool MediaPipelineFilter::Filter(const webrtc::RTPHeader& header, - uint32_t correlator) { - if (correlator) { - // This special correlator header takes precedence. It also lets us learn - // about SSRC mappings if we don't know about them yet. - if (correlator == correlator_) { - AddRemoteSSRC(header.ssrc); - return true; - } else { - // Some other stream; it is possible that an SSRC has moved, so make sure - // we don't have that SSRC in our filter any more. - remote_ssrc_set_.erase(header.ssrc); - return false; - } - } - - if (remote_ssrc_set_.count(header.ssrc)) { - return true; - } - - // Last ditch effort... - if (payload_type_set_.count(header.payloadType)) { - // Actual match. We need to update the ssrc map so we can route rtcp - // sender reports correctly (these use a different payload-type field) - AddRemoteSSRC(header.ssrc); - return true; - } - - return false; -} - -bool MediaPipelineFilter::FilterRTCP(uint32_t ssrc) { - return remote_ssrc_set_.count(ssrc) != 0; -} - -bool MediaPipelineFilter::FilterRTCPReceiverReport(uint32_t ssrc) { - return local_ssrc_set_.count(ssrc) != 0; -} - -void MediaPipelineFilter::AddLocalSSRC(uint32_t ssrc) { - local_ssrc_set_.insert(ssrc); -} - -void MediaPipelineFilter::AddRemoteSSRC(uint32_t ssrc) { - remote_ssrc_set_.insert(ssrc); -} - -void MediaPipelineFilter::AddUniquePT(uint8_t payload_type) { - payload_type_set_.insert(payload_type); -} - -void MediaPipelineFilter::SetCorrelator(uint32_t correlator) { - correlator_ = correlator; -} - -void MediaPipelineFilter::IncorporateRemoteDescription( - const MediaPipelineFilter& remote_filter) { - // Update SSRCs; we completely replace the remote SSRCs, since this could be - // renegotiation. We leave our SSRCs alone, though. - if (!remote_filter.remote_ssrc_set_.empty()) { - remote_ssrc_set_ = remote_filter.remote_ssrc_set_; - } - - // We do not mess with the payload types or correlator here, since the remote - // SDP doesn't tell us anything about what we will be receiving. -} - -} // end namespace mozilla - - diff --git a/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.h b/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.h deleted file mode 100644 index 61a9741547b3..000000000000 --- a/media/webrtc/signaling/src/mediapipeline/MediaPipelineFilter.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: softtabstop=2:shiftwidth=2:expandtab - * */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this file, - * You can obtain one at http://mozilla.org/MPL/2.0/. */ - -// Original author: bcampen@mozilla.com - -#ifndef mediapipelinefilter_h__ -#define mediapipelinefilter_h__ - -#include -#include - -#include - -namespace webrtc { -class RTPHeader; -} - -namespace mozilla { - -// A class that handles the work of filtering RTP packets that arrive at a -// MediaPipeline. This is primarily important for the use of BUNDLE (ie; -// multiple m-lines share the same RTP stream). There are three ways that this -// can work; -// -// 1) In our SDP, we include a media-level extmap parameter with a unique -// integer of our choosing, with the hope that the other side will include -// this value in a header in the first few RTP packets it sends us. This -// allows us to perform correlation in cases where the other side has not -// informed us of the ssrcs it will be sending (either because it did not -// include them in its SDP, or their SDP has not arrived yet) -// and also gives us the opportunity to learn SSRCs from packets so adorned. -// -// 2) If the remote endpoint includes SSRC media-level attributes in its SDP, -// we can simply use this information to populate the filter. The only -// shortcoming here is when RTP packets arrive before the answer does. See -// above. -// -// 3) As a fallback, we can try to use payload type IDs to perform correlation, -// but only when the type id is unique to this media section. -// This too allows us to learn about SSRCs (mostly useful for filtering -// any RTCP packets that follow). -class MediaPipelineFilter { - public: - MediaPipelineFilter(); - - // Checks whether this packet passes the filter, possibly updating the filter - // in the process (if the correlator or payload types are used, they can teach - // the filter about ssrcs) - bool Filter(const webrtc::RTPHeader& header, uint32_t correlator = 0); - - // RTCP doesn't have things like the RTP correlator, and uses its own - // payload types too. - // RTCP receiver reports use _our_ ssrcs - bool FilterRTCPReceiverReport(uint32_t ssrc); - // The rest of RTCP uses their ssrcs - bool FilterRTCP(uint32_t ssrc); - - void AddLocalSSRC(uint32_t ssrc); - void AddRemoteSSRC(uint32_t ssrc); - - // When a payload type id is unique to our media section, add it here. - void AddUniquePT(uint8_t payload_type); - void SetCorrelator(uint32_t correlator); - - void IncorporateRemoteDescription(const MediaPipelineFilter& remote_filter); - - private: - uint32_t correlator_; - // The number of filters we manage here is quite small, so I am optimizing - // for readability. - std::set remote_ssrc_set_; - std::set local_ssrc_set_; - std::set payload_type_set_; -}; - -} // end namespace mozilla - -#endif // mediapipelinefilter_h__ - diff --git a/media/webrtc/signaling/test/mediapipeline_unittest.cpp b/media/webrtc/signaling/test/mediapipeline_unittest.cpp index 87a808278de3..16930bf6f7a5 100644 --- a/media/webrtc/signaling/test/mediapipeline_unittest.cpp +++ b/media/webrtc/signaling/test/mediapipeline_unittest.cpp @@ -22,7 +22,6 @@ #include "MediaConduitErrors.h" #include "MediaConduitInterface.h" #include "MediaPipeline.h" -#include "MediaPipelineFilter.h" #include "runnable_utils.h" #include "transportflow.h" #include "transportlayerprsock.h" @@ -33,8 +32,6 @@ #include "mtransport_test_utils.h" #include "runnable_utils.h" -#include "webrtc/modules/interface/module_common_types.h" - #define GTEST_HAS_RTTI 0 #include "gtest/gtest.h" #include "gtest_utils.h" @@ -345,159 +342,6 @@ protected: TestAgentReceive p2_; }; -class MediaPipelineFilterTest : public ::testing::Test { - public: - bool Filter(MediaPipelineFilter& filter, - int32_t correlator, - uint32_t ssrc, - uint8_t payload_type) { - - webrtc::RTPHeader header; - header.ssrc = ssrc; - header.payloadType = payload_type; - return filter.Filter(header, correlator); - } -}; - -TEST_F(MediaPipelineFilterTest, TestConstruct) { - MediaPipelineFilter filter; -} - -TEST_F(MediaPipelineFilterTest, TestDefault) { - MediaPipelineFilter filter; - ASSERT_FALSE(Filter(filter, 0, 233, 110)); -} - -TEST_F(MediaPipelineFilterTest, TestSSRCFilter) { - MediaPipelineFilter filter; - filter.AddRemoteSSRC(555); - ASSERT_TRUE(Filter(filter, 0, 555, 110)); - ASSERT_FALSE(Filter(filter, 0, 556, 110)); -} - -TEST_F(MediaPipelineFilterTest, TestSSRCFilterRTCP) { - MediaPipelineFilter filter; - filter.AddRemoteSSRC(555); - ASSERT_TRUE(filter.FilterRTCP(555)); - ASSERT_FALSE(filter.FilterRTCP(556)); - ASSERT_FALSE(filter.FilterRTCPReceiverReport(555)); -} - -TEST_F(MediaPipelineFilterTest, TestSSRCFilterReceiverReport) { - MediaPipelineFilter filter; - filter.AddLocalSSRC(555); - ASSERT_TRUE(filter.FilterRTCPReceiverReport(555)); - ASSERT_FALSE(filter.FilterRTCPReceiverReport(556)); - ASSERT_FALSE(filter.FilterRTCP(555)); -} - -TEST_F(MediaPipelineFilterTest, TestCorrelatorFilter) { - MediaPipelineFilter filter; - filter.SetCorrelator(7777); - ASSERT_TRUE(Filter(filter, 7777, 555, 110)); - ASSERT_FALSE(Filter(filter, 7778, 556, 110)); - // This should also have resulted in the SSRC 555 being added to the filter - ASSERT_TRUE(Filter(filter, 0, 555, 110)); - ASSERT_FALSE(Filter(filter, 0, 556, 110)); - - ASSERT_TRUE(filter.FilterRTCP(555)); -} - -TEST_F(MediaPipelineFilterTest, TestPayloadTypeFilter) { - MediaPipelineFilter filter; - filter.AddUniquePT(110); - ASSERT_TRUE(Filter(filter, 0, 555, 110)); - ASSERT_FALSE(Filter(filter, 0, 556, 111)); -} - -TEST_F(MediaPipelineFilterTest, TestPayloadTypeFilterSSRCUpdate) { - MediaPipelineFilter filter; - filter.AddUniquePT(110); - ASSERT_TRUE(Filter(filter, 0, 555, 110)); - ASSERT_TRUE(filter.FilterRTCP(555)); - ASSERT_FALSE(filter.FilterRTCP(556)); - ASSERT_FALSE(filter.FilterRTCPReceiverReport(555)); -} - -TEST_F(MediaPipelineFilterTest, TestAnswerAddsSSRCs) { - MediaPipelineFilter filter; - filter.SetCorrelator(7777); - ASSERT_TRUE(Filter(filter, 7777, 555, 110)); - ASSERT_FALSE(Filter(filter, 7778, 556, 110)); - // This should also have resulted in the SSRC 555 being added to the filter - ASSERT_TRUE(Filter(filter, 0, 555, 110)); - ASSERT_FALSE(Filter(filter, 0, 556, 110)); - - // This sort of thing can happen when getting an answer with SSRC attrs - // The answer will not contain the correlator. - MediaPipelineFilter filter2; - filter2.AddRemoteSSRC(555); - filter2.AddRemoteSSRC(556); - filter2.AddRemoteSSRC(557); - - filter.IncorporateRemoteDescription(filter2); - - // Ensure that the old SSRC still works. - ASSERT_TRUE(Filter(filter, 0, 555, 110)); - - // Ensure that the new SSRCs work. - ASSERT_TRUE(Filter(filter, 0, 556, 110)); - ASSERT_TRUE(Filter(filter, 0, 557, 110)); - - // Ensure that the correlator continues to work - ASSERT_TRUE(Filter(filter, 7777, 558, 110)); -} - -TEST_F(MediaPipelineFilterTest, TestSSRCMovedWithSDP) { - MediaPipelineFilter filter; - filter.SetCorrelator(7777); - filter.AddUniquePT(111); - ASSERT_TRUE(Filter(filter, 7777, 555, 110)); - - MediaPipelineFilter filter2; - filter2.AddRemoteSSRC(556); - - filter.IncorporateRemoteDescription(filter2); - - // Ensure that the old SSRC has been removed. - ASSERT_FALSE(Filter(filter, 0, 555, 110)); - - // Ensure that the new SSRC works. - ASSERT_TRUE(Filter(filter, 0, 556, 110)); - - // Ensure that the correlator continues to work - ASSERT_TRUE(Filter(filter, 7777, 558, 110)); - - // Ensure that the payload type mapping continues to work - ASSERT_TRUE(Filter(filter, 0, 559, 111)); -} - -TEST_F(MediaPipelineFilterTest, TestSSRCMovedWithCorrelator) { - MediaPipelineFilter filter; - filter.SetCorrelator(7777); - ASSERT_TRUE(Filter(filter, 7777, 555, 110)); - ASSERT_TRUE(Filter(filter, 0, 555, 110)); - ASSERT_FALSE(Filter(filter, 7778, 555, 110)); - ASSERT_FALSE(Filter(filter, 0, 555, 110)); -} - -TEST_F(MediaPipelineFilterTest, TestRemoteSDPNoSSRCs) { - // If the remote SDP doesn't have SSRCs, right now this is a no-op and - // there is no point of even incorporating a filter, but we make the behavior - // consistent to avoid confusion. - MediaPipelineFilter filter; - filter.SetCorrelator(7777); - filter.AddUniquePT(111); - ASSERT_TRUE(Filter(filter, 7777, 555, 110)); - - MediaPipelineFilter filter2; - - filter.IncorporateRemoteDescription(filter2); - - // Ensure that the old SSRC still works. - ASSERT_TRUE(Filter(filter, 7777, 555, 110)); -} - TEST_F(MediaPipelineTest, TestAudioSendNoMux) { TestAudioSend(false); } diff --git a/media/webrtc/signaling/test/moz.build b/media/webrtc/signaling/test/moz.build index c86e0901fe8c..95cf28ab4b2e 100644 --- a/media/webrtc/signaling/test/moz.build +++ b/media/webrtc/signaling/test/moz.build @@ -49,7 +49,6 @@ LOCAL_INCLUDES += [ '/media/webrtc/signaling/src/sipcc/core/sdp', '/media/webrtc/signaling/src/sipcc/cpr/include', '/media/webrtc/signaling/src/sipcc/include', - '/media/webrtc/trunk', '/media/webrtc/trunk/testing/gtest/include', '/media/webrtc/trunk/third_party/libjingle/source', '/xpcom/base', From b4d881fd2f5d30f6f2170816ec51b52fcba2c346 Mon Sep 17 00:00:00 2001 From: Andrew McCreight Date: Mon, 24 Feb 2014 11:12:54 -0800 Subject: [PATCH 44/48] Backout bug 972591, part 3, for a top crash. --- dom/xbl/nsXBLDocumentInfo.cpp | 106 +++++++++++++++++++++------------- dom/xbl/nsXBLDocumentInfo.h | 6 +- 2 files changed, 68 insertions(+), 44 deletions(-) diff --git a/dom/xbl/nsXBLDocumentInfo.cpp b/dom/xbl/nsXBLDocumentInfo.cpp index f93791c57076..eae376863b84 100644 --- a/dom/xbl/nsXBLDocumentInfo.cpp +++ b/dom/xbl/nsXBLDocumentInfo.cpp @@ -223,20 +223,22 @@ nsXBLDocGlobalObject::GetPrincipal() /* Implementation file */ -static PLDHashOperator -TraverseProtos(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure) +static bool +TraverseProtos(nsHashKey *aKey, void *aData, void* aClosure) { - nsCycleCollectionTraversalCallback *cb = + nsCycleCollectionTraversalCallback *cb = static_cast(aClosure); - aProto->Traverse(*cb); - return PL_DHASH_NEXT; + nsXBLPrototypeBinding *proto = static_cast(aData); + proto->Traverse(*cb); + return kHashEnumerateNext; } -static PLDHashOperator -UnlinkProtoJSObjects(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure) +static bool +UnlinkProtoJSObjects(nsHashKey *aKey, void *aData, void* aClosure) { - aProto->UnlinkJSObjects(); - return PL_DHASH_NEXT; + nsXBLPrototypeBinding *proto = static_cast(aData); + proto->UnlinkJSObjects(); + return kHashEnumerateNext; } struct ProtoTracer @@ -245,19 +247,20 @@ struct ProtoTracer void *mClosure; }; -static PLDHashOperator -TraceProtos(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure) +static bool +TraceProtos(nsHashKey *aKey, void *aData, void* aClosure) { ProtoTracer* closure = static_cast(aClosure); - aProto->Trace(closure->mCallbacks, closure->mClosure); - return PL_DHASH_NEXT; + nsXBLPrototypeBinding *proto = static_cast(aData); + proto->Trace(closure->mCallbacks, closure->mClosure); + return kHashEnumerateNext; } NS_IMPL_CYCLE_COLLECTION_CLASS(nsXBLDocumentInfo) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsXBLDocumentInfo) if (tmp->mBindingTable) { - tmp->mBindingTable->EnumerateRead(UnlinkProtoJSObjects, nullptr); + tmp->mBindingTable->Enumerate(UnlinkProtoJSObjects, nullptr); } NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocument) NS_IMPL_CYCLE_COLLECTION_UNLINK(mGlobalObject) @@ -270,7 +273,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsXBLDocumentInfo) } NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocument) if (tmp->mBindingTable) { - tmp->mBindingTable->EnumerateRead(TraverseProtos, &cb); + tmp->mBindingTable->Enumerate(TraverseProtos, &cb); } NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobalObject) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS @@ -278,7 +281,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsXBLDocumentInfo) if (tmp->mBindingTable) { ProtoTracer closure = { aCallbacks, aClosure }; - tmp->mBindingTable->EnumerateRead(TraceProtos, &closure); + tmp->mBindingTable->Enumerate(TraceProtos, &closure); } NS_IMPL_CYCLE_COLLECTION_TRACE_END @@ -288,11 +291,12 @@ UnmarkXBLJSObject(void* aP, const char* aName, void* aClosure) JS::ExposeObjectToActiveJS(static_cast(aP)); } -static PLDHashOperator -UnmarkProtos(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure) +static bool +UnmarkProtos(nsHashKey* aKey, void* aData, void* aClosure) { - aProto->Trace(TraceCallbackFunc(UnmarkXBLJSObject), nullptr); - return PL_DHASH_NEXT; + nsXBLPrototypeBinding* proto = static_cast(aData); + proto->Trace(TraceCallbackFunc(UnmarkXBLJSObject), nullptr); + return kHashEnumerateNext; } void @@ -303,7 +307,7 @@ nsXBLDocumentInfo::MarkInCCGeneration(uint32_t aGeneration) } // Unmark any JS we hold if (mBindingTable) { - mBindingTable->EnumerateRead(UnmarkProtos, nullptr); + mBindingTable->Enumerate(UnmarkProtos, nullptr); } if (mGlobalObject) { mGlobalObject->UnmarkCompilationGlobal(); @@ -322,6 +326,7 @@ nsXBLDocumentInfo::nsXBLDocumentInfo(nsIDocument* aDocument) : mDocument(aDocument), mScriptAccess(true), mIsChrome(false), + mBindingTable(nullptr), mFirstBinding(nullptr) { nsIURI* uri = aDocument->GetDocumentURI(); @@ -362,7 +367,11 @@ nsXBLDocumentInfo::~nsXBLDocumentInfo() if (mGlobalObject) { mGlobalObject->ClearGlobalObjectOwner(); // just in case } - mozilla::DropJSObjects(this); + if (mBindingTable) { + delete mBindingTable; + mBindingTable = nullptr; + mozilla::DropJSObjects(this); + } } nsXBLPrototypeBinding* @@ -376,19 +385,32 @@ nsXBLDocumentInfo::GetPrototypeBinding(const nsACString& aRef) return mFirstBinding; } - return mBindingTable->Get(aRef); + const nsPromiseFlatCString& flat = PromiseFlatCString(aRef); + nsCStringKey key(flat.get()); + return static_cast(mBindingTable->Get(&key)); +} + +static bool +DeletePrototypeBinding(nsHashKey* aKey, void* aData, void* aClosure) +{ + nsXBLPrototypeBinding* binding = static_cast(aData); + delete binding; + return true; } nsresult nsXBLDocumentInfo::SetPrototypeBinding(const nsACString& aRef, nsXBLPrototypeBinding* aBinding) { if (!mBindingTable) { - mBindingTable = new nsClassHashtable(); + mBindingTable = new nsObjectHashtable(nullptr, nullptr, DeletePrototypeBinding, nullptr); + mozilla::HoldJSObjects(this); } - NS_ENSURE_STATE(!mBindingTable->Get(aRef)); - mBindingTable->Put(aRef, aBinding); + const nsPromiseFlatCString& flat = PromiseFlatCString(aRef); + nsCStringKey key(flat.get()); + NS_ENSURE_STATE(!mBindingTable->Get(&key)); + mBindingTable->Put(&key, aBinding); return NS_OK; } @@ -397,18 +419,22 @@ void nsXBLDocumentInfo::RemovePrototypeBinding(const nsACString& aRef) { if (mBindingTable) { - mBindingTable->Remove(aRef); + // Use a flat string to avoid making a copy. + const nsPromiseFlatCString& flat = PromiseFlatCString(aRef); + nsCStringKey key(flat); + mBindingTable->Remove(&key); } } // Callback to enumerate over the bindings from this document and write them // out to the cache. -static PLDHashOperator -WriteBinding(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure) +bool +WriteBinding(nsHashKey *aKey, void *aData, void* aClosure) { - aProto->Write((nsIObjectOutputStream*)aClosure); + nsXBLPrototypeBinding* binding = static_cast(aData); + binding->Write((nsIObjectOutputStream*)aClosure); - return PL_DHASH_NEXT; + return kHashEnumerateNext; } // static @@ -504,9 +530,8 @@ nsXBLDocumentInfo::WritePrototypeBindings() rv = stream->Write32(XBLBinding_Serialize_Version); NS_ENSURE_SUCCESS(rv, rv); - if (mBindingTable) { - mBindingTable->EnumerateRead(WriteBinding, stream); - } + if (mBindingTable) + mBindingTable->Enumerate(WriteBinding, stream); // write a end marker at the end rv = stream->Write8(XBLBinding_Serialize_NoMoreBindings); @@ -529,19 +554,18 @@ nsXBLDocumentInfo::SetFirstPrototypeBinding(nsXBLPrototypeBinding* aBinding) mFirstBinding = aBinding; } -static PLDHashOperator -FlushScopedSkinSheets(const nsACString &aKey, nsXBLPrototypeBinding *aProto, void* aClosure) +bool FlushScopedSkinSheets(nsHashKey* aKey, void* aData, void* aClosure) { - aProto->FlushSkinSheets(); - return PL_DHASH_NEXT; + nsXBLPrototypeBinding* proto = (nsXBLPrototypeBinding*)aData; + proto->FlushSkinSheets(); + return true; } void nsXBLDocumentInfo::FlushSkinStylesheets() { - if (mBindingTable) { - mBindingTable->EnumerateRead(FlushScopedSkinSheets, nullptr); - } + if (mBindingTable) + mBindingTable->Enumerate(FlushScopedSkinSheets); } JSObject* diff --git a/dom/xbl/nsXBLDocumentInfo.h b/dom/xbl/nsXBLDocumentInfo.h index adbb00035c2c..412738a4118d 100644 --- a/dom/xbl/nsXBLDocumentInfo.h +++ b/dom/xbl/nsXBLDocumentInfo.h @@ -13,6 +13,7 @@ #include "nsCycleCollectionParticipant.h" class nsXBLPrototypeBinding; +class nsObjectHashtable; class nsXBLDocGlobalObject; class nsXBLDocumentInfo : public nsSupportsWeakReference @@ -40,7 +41,7 @@ public: nsresult WritePrototypeBindings(); void SetFirstPrototypeBinding(nsXBLPrototypeBinding* aBinding); - + void FlushSkinStylesheets(); bool IsChrome() { return mIsChrome; } @@ -59,8 +60,7 @@ private: bool mScriptAccess; bool mIsChrome; // the binding table owns each nsXBLPrototypeBinding - nsAutoPtr> mBindingTable; - + nsObjectHashtable* mBindingTable; // non-owning pointer to the first binding in the table nsXBLPrototypeBinding* mFirstBinding; From bd8e6a16ad6a9b9c53301aec82194b6a2418b60f Mon Sep 17 00:00:00 2001 From: "Nicholas D. Matsakis" Date: Wed, 12 Feb 2014 18:49:46 -0500 Subject: [PATCH 45/48] Bug 970285 -- Detect negative lengths supplied to unsized array constructor r=shu --- js/src/builtin/TypedObject.cpp | 5 +++++ js/src/jit-test/tests/TypedObject/bug970285.js | 11 +++++++++++ 2 files changed, 16 insertions(+) create mode 100644 js/src/jit-test/tests/TypedObject/bug970285.js diff --git a/js/src/builtin/TypedObject.cpp b/js/src/builtin/TypedObject.cpp index 6fd28c29f529..a2a84115de36 100644 --- a/js/src/builtin/TypedObject.cpp +++ b/js/src/builtin/TypedObject.cpp @@ -2427,6 +2427,11 @@ TypedObject::constructUnsized(JSContext *cx, unsigned int argc, Value *vp) // Length constructor. if (args[0].isInt32()) { int32_t length = args[0].toInt32(); + if (length < 0) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, + nullptr, JSMSG_TYPEDOBJECT_BAD_ARGS); + return nullptr; + } Rooted obj(cx, createZeroed(cx, callee, length)); if (!obj) return false; diff --git a/js/src/jit-test/tests/TypedObject/bug970285.js b/js/src/jit-test/tests/TypedObject/bug970285.js new file mode 100644 index 000000000000..f5d36cdc97b3 --- /dev/null +++ b/js/src/jit-test/tests/TypedObject/bug970285.js @@ -0,0 +1,11 @@ +// |jit-test| error:TypeError + +if (!this.hasOwnProperty("TypedObject")) + throw new TypeError(); + +// Test that we detect invalid lengths supplied to unsized array +// constructor. Public domain. + +var AA = TypedObject.uint8.array(2147483647).array(); +var aa = new AA(-1); + From bf210fa5d2a272d1f370901bac64057bf159571f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Moln=C3=A1r?= Date: Mon, 24 Feb 2014 11:42:15 -0800 Subject: [PATCH 46/48] Bug 961616 - simple HTTP2 Cookie crumbling unit tests --- netwerk/test/unit/test_http2.js | 33 ++++++++++++++++++++++--- testing/xpcshell/moz-http2/moz-http2.js | 22 +++++++++++++++++ 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/netwerk/test/unit/test_http2.js b/netwerk/test/unit/test_http2.js index 56c361114a4c..c4a67efd04c4 100644 --- a/netwerk/test/unit/test_http2.js +++ b/netwerk/test/unit/test_http2.js @@ -115,8 +115,9 @@ Http2MultiplexListener.prototype.onStopRequest = function(request, ctx, status) }; // Does the appropriate checks for header gatewaying -var Http2HeaderListener = function(value) { - this.value = value +var Http2HeaderListener = function(name, callback) { + this.name = name; + this.callback = callback; }; Http2HeaderListener.prototype = new Http2CheckListener(); @@ -125,7 +126,9 @@ Http2HeaderListener.prototype.value = ""; Http2HeaderListener.prototype.onDataAvailable = function(request, ctx, stream, off, cnt) { this.onDataAvailableFired = true; this.isHttp2Connection = checkIsHttp2(request); - do_check_eq(request.getResponseHeader("X-Received-Test-Header"), this.value); + var hvalue = request.getResponseHeader(this.name); + do_check_neq(hvalue, ""); + this.callback(hvalue); read_stream(stream, cnt); }; @@ -235,8 +238,29 @@ function test_http2_multiplex() { function test_http2_header() { var chan = makeChan("https://localhost:6944/header"); var hvalue = "Headers are fun"; - var listener = new Http2HeaderListener(hvalue); chan.setRequestHeader("X-Test-Header", hvalue, false); + var listener = new Http2HeaderListener("X-Received-Test-Header", function(received_hvalue) { + do_check_eq(received_hvalue, hvalue); + }); + chan.asyncOpen(listener, null); +} + +// Test to make sure cookies are split into separate fields before compression +function test_http2_cookie_crumbling() { + var chan = makeChan("https://localhost:6944/cookie_crumbling"); + var cookiesSent = ['a=b', 'c=d', 'e=f'].sort(); + chan.setRequestHeader("Cookie", cookiesSent.join('; '), false); + var listener = new Http2HeaderListener("X-Received-Header-Pairs", function(pairsReceived) { + var cookiesReceived = JSON.parse(pairsReceived).filter(function(pair) { + return pair[0] == 'cookie'; + }).map(function(pair) { + return pair[1]; + }).sort(); + do_check_eq(cookiesReceived.length, cookiesSent.length); + cookiesReceived.forEach(function(cookieReceived, index) { + do_check_eq(cookiesSent[index], cookieReceived) + }); + }); chan.asyncOpen(listener, null); } @@ -316,6 +340,7 @@ var tests = [ test_http2_post_big , test_http2_push4 , test_http2_xhr , test_http2_header + , test_http2_cookie_crumbling , test_http2_multiplex , test_http2_big , test_http2_post diff --git a/testing/xpcshell/moz-http2/moz-http2.js b/testing/xpcshell/moz-http2/moz-http2.js index 89079cf7142c..5364452558b1 100644 --- a/testing/xpcshell/moz-http2/moz-http2.js +++ b/testing/xpcshell/moz-http2/moz-http2.js @@ -7,6 +7,24 @@ var fs = require('fs'); var url = require('url'); var crypto = require('crypto'); +// Hook into the decompression code to log the decompressed name-value pairs +var http2_compression = require('../node-http2/node_modules/http2-protocol/lib/compressor'); +var HeaderSetDecompressor = http2_compression.HeaderSetDecompressor; +var originalRead = HeaderSetDecompressor.prototype.read; +var lastDecompressor; +var decompressedPairs; +HeaderSetDecompressor.prototype.read = function() { + if (this != lastDecompressor) { + lastDecompressor = this; + decompressedPairs = []; + } + var pair = originalRead.apply(this, arguments); + if (pair) { + decompressedPairs.push(pair); + } + return pair; +} + function getHttpContent(path) { var content = '' + '' + @@ -96,6 +114,10 @@ function handleRequest(req, res) { } } + else if (u.pathname === "/cookie_crumbling") { + res.setHeader("X-Received-Header-Pairs", JSON.stringify(decompressedPairs)); + } + else if (u.pathname === "/push") { push = res.push('/push.js'); push.writeHead(200, { From 12d0416fc62052e26f5e11dacf8f1b359bf5a26d Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Mon, 24 Feb 2014 14:52:14 -0500 Subject: [PATCH 47/48] Backed out 5 changesets (bug 951827) for causing bug 975820. Backed out changeset 16b840c2de31 (bug 951827) Backed out changeset 8fb155711dfe (bug 951827) Backed out changeset 1109dba48e6b (bug 951827) Backed out changeset 236ed76eea8b (bug 951827) Backed out changeset 96cf7c13a8cb (bug 951827) --- mozglue/build/WindowsDllBlocklist.cpp | 3 +- toolkit/xre/nsWindowsDllInterceptor.h | 177 +++++--------------- toolkit/xre/test/win/TestDllInterceptor.cpp | 107 ------------ 3 files changed, 39 insertions(+), 248 deletions(-) diff --git a/mozglue/build/WindowsDllBlocklist.cpp b/mozglue/build/WindowsDllBlocklist.cpp index e7d5b096c0ab..9f3dff61049e 100644 --- a/mozglue/build/WindowsDllBlocklist.cpp +++ b/mozglue/build/WindowsDllBlocklist.cpp @@ -614,8 +614,7 @@ DllBlocklist_Initialize() ReentrancySentinel::InitializeStatics(); - // Use a shared hook since other software may also hook this API (bug 951827) - bool ok = NtDllIntercept.AddSharedHook("LdrLoadDll", reinterpret_cast(patched_LdrLoadDll), (void**) &stub_LdrLoadDll); + bool ok = NtDllIntercept.AddHook("LdrLoadDll", reinterpret_cast(patched_LdrLoadDll), (void**) &stub_LdrLoadDll); if (!ok) { sBlocklistInitFailed = true; diff --git a/toolkit/xre/nsWindowsDllInterceptor.h b/toolkit/xre/nsWindowsDllInterceptor.h index cee93d0ef59a..04aba4eb0397 100644 --- a/toolkit/xre/nsWindowsDllInterceptor.h +++ b/toolkit/xre/nsWindowsDllInterceptor.h @@ -41,13 +41,8 @@ * 1. Save first N bytes of OrigFunction to trampoline, where N is a * number of bytes >= 5 that are instruction aligned. * - * 2. (Usually) Replace first 5 bytes of OrigFunction with a jump to the hook + * 2. Replace first 5 bytes of OrigFunction with a jump to the Hook * function. - * (Special "shared" mode) Replace first 6 bytes of OrigFunction with an - * indirect jump to the hook function. "Shared" means that other software - * also tries to hook the same function. The indirect jump uses an absolute - * address, which allows us to coexist with other hooks that don't know how - * to relocate our 5-byte PC-relative jump. * * 3. After N bytes of the trampoline, add a jump to OrigFunction+N to * continue original program flow. @@ -81,8 +76,6 @@ class WindowsDllNopSpacePatcher byteptr_t mPatchedFns[maxPatchedFns]; int mPatchedFnsLen; - static const uint16_t opTrampolineShortJump = 0xf9eb; - public: WindowsDllNopSpacePatcher() : mModule(0) @@ -96,11 +89,6 @@ public: for (int i = 0; i < mPatchedFnsLen; i++) { byteptr_t fn = mPatchedFns[i]; - // If other code has changed this function, it is not safe to modify. - if (*((uint16_t*)fn) != opTrampolineShortJump) { - continue; - } - // Ensure we can write to the code. DWORD op; if (!VirtualProtectEx(GetCurrentProcess(), fn, 2, PAGE_EXECUTE_READWRITE, &op)) { @@ -202,7 +190,7 @@ public: *origFunc = fn + 2; // Short jump up into our long jump. - *((uint16_t*)(fn)) = opTrampolineShortJump; // jmp $-5 + *((uint16_t*)(fn)) = 0xf9eb; // jmp $-5 // I think this routine is safe without this, but it can't hurt. FlushInstructionCache(GetCurrentProcess(), @@ -224,12 +212,6 @@ class WindowsDllDetourPatcher { typedef unsigned char *byteptr_t; public: - enum JumpType - { - JUMP_DONTCARE, - JUMP_ABSOLUTE - }; - WindowsDllDetourPatcher() : mModule(0), mHookPage(0), mMaxHooks(0), mCurHooks(0) { @@ -247,28 +229,7 @@ public: #else #error "Unknown processor type" #endif - Trampoline *tramp = (Trampoline*)p; - byteptr_t origBytes = (byteptr_t)tramp->origFunction; - - // If CreateTrampoline failed, we may have an empty trampoline. - if (!origBytes) { - continue; - } - - // If other code has changed this function, it is not safe to modify. -#if defined(_M_IX86) - if (tramp->jumpType != JUMP_ABSOLUTE && - *origBytes != opTrampolineRelativeJump) { - continue; - } -#elif defined(_M_X64) - if (*((uint16_t*)origBytes) != opTrampolineRegLoad) { - continue; - } -#else -#error "Unknown processor type" -#endif - + byteptr_t origBytes = *((byteptr_t *)p); // ensure we can modify the original code DWORD op; if (!VirtualProtectEx(GetCurrentProcess(), origBytes, nBytes, PAGE_EXECUTE_READWRITE, &op)) { @@ -277,14 +238,9 @@ public: } // Remove the hook by making the original function jump directly // in the trampoline. - intptr_t dest = (intptr_t)(&tramp->code[0]); + intptr_t dest = (intptr_t)(p + sizeof(void *)); #if defined(_M_IX86) - if (tramp->jumpType == JUMP_ABSOLUTE) { - // Absolute jumps on x86 are done indirectly via tramp->jumpTarget - tramp->jumpTarget = dest; - } else { - *((intptr_t*)(origBytes+1)) = dest - (intptr_t)(origBytes+5); // target displacement - } + *((intptr_t*)(origBytes+1)) = dest - (intptr_t)(origBytes+5); // target displacement #elif defined(_M_X64) *((intptr_t*)(origBytes+2)) = dest; #else @@ -339,7 +295,7 @@ public: mModule = 0; } - bool AddHook(const char *pname, intptr_t hookDest, JumpType jumpType, void **origFunc) + bool AddHook(const char *pname, intptr_t hookDest, void **origFunc) { if (!mModule) return false; @@ -350,7 +306,7 @@ public: return false; } - CreateTrampoline(pAddr, hookDest, jumpType, origFunc); + CreateTrampoline(pAddr, hookDest, origFunc); if (!*origFunc) { //printf ("CreateTrampoline failed\n"); return false; @@ -362,35 +318,19 @@ public: protected: const static int kPageSize = 4096; const static int kHookSize = 128; - const static int kCodeSize = 100; - - const static uint8_t opTrampolineRelativeJump = 0xe9; - const static uint16_t opTrampolineIndirectJump = 0x25ff; - const static uint16_t opTrampolineRegLoad = 0xbb49; HMODULE mModule; byteptr_t mHookPage; int mMaxHooks; int mCurHooks; - struct Trampoline - { - void *origFunction; - JumpType jumpType; - intptr_t jumpTarget; - uint8_t code[kCodeSize]; - }; - - static_assert(sizeof(Trampoline) <= kHookSize, "Trampolines too big"); - void CreateTrampoline(void *origFunction, intptr_t dest, - JumpType jumpType, void **outTramp) { *outTramp = nullptr; - Trampoline *tramp = FindTrampolineSpace(); + byteptr_t tramp = FindTrampolineSpace(); if (!tramp) return; @@ -400,9 +340,7 @@ protected: int pJmp32 = -1; #if defined(_M_IX86) - const int bytesNeeded = (jumpType == JUMP_ABSOLUTE) ? 6 : 5; - - while (nBytes < bytesNeeded) { + while (nBytes < 5) { // Understand some simple instructions that might be found in a // prologue; we might need to extend this as necessary. // @@ -446,22 +384,10 @@ protected: } else if (origBytes[nBytes] == 0x6A) { // PUSH imm8 nBytes += 2; - } else if (origBytes[nBytes] == 0xa1) { - // MOV EAX, dword ptr [m32] - nBytes += 5; } else if (origBytes[nBytes] == 0xe9) { pJmp32 = nBytes; // jmp 32bit offset nBytes += 5; - } else if (origBytes[nBytes] == 0xf6 && - origBytes[nBytes+1] == 0x05) { - // TEST byte ptr [m32], imm8 - nBytes += 7; - } else if (origBytes[nBytes] == 0xff && - origBytes[nBytes+1] == 0x25) { - // JMP dword ptr [m32] - // This is an indirect absolute jump; don't set pJmp32 - nBytes += 6; } else { //printf ("Unknown x86 instruction byte 0x%02x, aborting trampoline\n", origBytes[nBytes]); return; @@ -613,18 +539,17 @@ protected: #error "Unknown processor type" #endif - if (nBytes > kCodeSize) { + if (nBytes > 100) { //printf ("Too big!"); return; } // We keep the address of the original function in the first bytes of // the trampoline buffer - tramp->origFunction = origFunction; - tramp->jumpType = jumpType; - tramp->jumpTarget = dest; + *((void **)tramp) = origFunction; + tramp += sizeof(void *); - memcpy(&tramp->code[0], origFunction, nBytes); + memcpy(tramp, origFunction, nBytes); // OrigFunction+N, the target of the trampoline byteptr_t trampDest = origBytes + nBytes; @@ -634,36 +559,38 @@ protected: // Jump directly to the original target of the jump instead of jumping to the // original function. // Adjust jump target displacement to jump location in the trampoline. - *((intptr_t*)(&tramp->code[pJmp32+1])) += origBytes - &tramp->code[0]; + *((intptr_t*)(tramp+pJmp32+1)) += origBytes - tramp; } else { - tramp->code[nBytes] = opTrampolineRelativeJump; // jmp - *((intptr_t*)(&tramp->code[nBytes+1])) = (intptr_t)trampDest - (intptr_t)(&tramp->code[nBytes+5]); // target displacement + tramp[nBytes] = 0xE9; // jmp + *((intptr_t*)(tramp+nBytes+1)) = (intptr_t)trampDest - (intptr_t)(tramp+nBytes+5); // target displacement } #elif defined(_M_X64) // If JMP32 opcode found, we don't insert to trampoline jump if (pJmp32 >= 0) { // mov r11, address - *((uint16_t*)(&tramp->code[pJmp32])) = opTrampolineRegLoad; - *((intptr_t*)(&tramp->code[pJmp32+2])) = (intptr_t)directJmpAddr; + tramp[pJmp32] = 0x49; + tramp[pJmp32+1] = 0xbb; + *((intptr_t*)(tramp+pJmp32+2)) = (intptr_t)directJmpAddr; // jmp r11 - tramp->code[pJmp32+10] = 0x41; - tramp->code[pJmp32+11] = 0xff; - tramp->code[pJmp32+12] = 0xe3; + tramp[pJmp32+10] = 0x41; + tramp[pJmp32+11] = 0xff; + tramp[pJmp32+12] = 0xe3; } else { // mov r11, address - *((uint16_t*)(&tramp->code[nBytes])) = opTrampolineRegLoad; - *((intptr_t*)(&tramp->code[nBytes+2])) = (intptr_t)trampDest; + tramp[nBytes] = 0x49; + tramp[nBytes+1] = 0xbb; + *((intptr_t*)(tramp+nBytes+2)) = (intptr_t)trampDest; // jmp r11 - tramp->code[nBytes+10] = 0x41; - tramp->code[nBytes+11] = 0xff; - tramp->code[nBytes+12] = 0xe3; + tramp[nBytes+10] = 0x41; + tramp[nBytes+11] = 0xff; + tramp[nBytes+12] = 0xe3; } #endif // The trampoline is now valid. - *outTramp = &tramp->code[0]; + *outTramp = tramp; // ensure we can modify the original code DWORD op; @@ -674,18 +601,13 @@ protected: #if defined(_M_IX86) // now modify the original bytes - if (jumpType == JUMP_ABSOLUTE) { - // Indirect jump with absolute address of pointer - // jmp dword ptr [&tramp->jumpTarget] - *((uint16_t*)(origBytes)) = opTrampolineIndirectJump; - *((intptr_t*)(origBytes+2)) = (intptr_t)&tramp->jumpTarget; - } else { - origBytes[0] = opTrampolineRelativeJump; // jmp rel32 - *((intptr_t*)(origBytes+1)) = dest - (intptr_t)(origBytes+5); // target displacement - } + origBytes[0] = 0xE9; // jmp + *((intptr_t*)(origBytes+1)) = dest - (intptr_t)(origBytes+5); // target displacement #elif defined(_M_X64) // mov r11, address - *((uint16_t*)(origBytes)) = opTrampolineRegLoad; + origBytes[0] = 0x49; + origBytes[1] = 0xbb; + *((intptr_t*)(origBytes+2)) = dest; // jmp r11 @@ -698,16 +620,16 @@ protected: VirtualProtectEx(GetCurrentProcess(), origFunction, nBytes, op, &op); } - Trampoline* FindTrampolineSpace() + byteptr_t FindTrampolineSpace() { if (mCurHooks >= mMaxHooks) - return nullptr; + return 0; byteptr_t p = mHookPage + mCurHooks*kHookSize; mCurHooks++; - return (Trampoline*)p; + return p; } }; @@ -717,7 +639,6 @@ class WindowsDllInterceptor { internal::WindowsDllNopSpacePatcher mNopSpacePatcher; internal::WindowsDllDetourPatcher mDetourPatcher; - typedef internal::WindowsDllDetourPatcher::JumpType JumpType; const char *mModuleName; int mNHooks; @@ -765,32 +686,10 @@ public: mDetourPatcher.Init(mModuleName, mNHooks); } - bool rv = mDetourPatcher.AddHook(pname, hookDest, JumpType::JUMP_DONTCARE, - origFunc); - + bool rv = mDetourPatcher.AddHook(pname, hookDest, origFunc); // printf("detourPatcher returned %d\n", rv); return rv; } - - bool AddSharedHook(const char *pname, intptr_t hookDest, void **origFunc) - { - if (!mModuleName) { - return false; - } - - // Skip the nop-space patcher and use only the detour patcher. Nop-space - // patches use relative jumps, which are not safe to share. - - if (!mDetourPatcher.Initialized()) { - mDetourPatcher.Init(mModuleName, mNHooks); - } - - bool rv = mDetourPatcher.AddHook(pname, hookDest, JumpType::JUMP_ABSOLUTE, - origFunc); - - return rv; - } - }; } // namespace mozilla diff --git a/toolkit/xre/test/win/TestDllInterceptor.cpp b/toolkit/xre/test/win/TestDllInterceptor.cpp index 0cd47cb3cadd..31171dbedb5c 100644 --- a/toolkit/xre/test/win/TestDllInterceptor.cpp +++ b/toolkit/xre/test/win/TestDllInterceptor.cpp @@ -38,31 +38,6 @@ patched_rotatePayload(payload p) return orig_rotatePayload(p); } -__declspec(noinline) bool AlwaysTrue(int, int, int, int, int, int) { - // Dummy function that makes the caller recognizable by the detour patcher - return true; -} - -extern "C" __declspec(dllexport) __declspec(noinline) uint32_t SetBits(uint32_t x) -{ - if (AlwaysTrue(1, 2, 3, 4, 5, 6)) { - return x | 0x11; - } - return 0; -} - -static uint32_t (*orig_SetBits_early)(uint32_t); -static uint32_t patched_SetBits_early(uint32_t x) -{ - return orig_SetBits_early(x) | 0x2200; -} - -static uint32_t (*orig_SetBits_late)(uint32_t); -static uint32_t patched_SetBits_late(uint32_t x) -{ - return orig_SetBits_late(x) | 0x330000; -} - bool TestHook(const char *dll, const char *func) { void *orig_func; @@ -82,25 +57,6 @@ bool TestHook(const char *dll, const char *func) } } -bool TestSharedHook(const char *dll, const char *func) -{ - void *orig_func; - bool successful = false; - { - WindowsDllInterceptor TestIntercept; - TestIntercept.Init(dll); - successful = TestIntercept.AddSharedHook(func, 0, &orig_func); - } - - if (successful) { - printf("TEST-PASS | WindowsDllInterceptor | Could hook (shared) %s from %s\n", func, dll); - return true; - } else { - printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Failed to hook (shared) %s from %s\n", func, dll); - return false; - } -} - int main() { payload initial = { 0x12345678, 0xfc4e9d31, 0x87654321 }; @@ -156,66 +112,6 @@ int main() return 1; } -#ifdef _M_IX86 - // The x64 detour patcher does understand the assembly code of SetBits. - // We only need these shared hook tests on x86 anyway, because shared hooks - // are the same as regular hooks on x64. - - // Despite the noinline annotation, the compiler may try to re-use the - // return value of SetBits(0). Force it to call the function every time. - uint32_t (*volatile SetBitsVolatile)(uint32_t) = SetBits; - - { - WindowsDllInterceptor ExeInterceptEarly; - ExeInterceptEarly.Init("TestDllInterceptor.exe"); - if (ExeInterceptEarly.AddSharedHook("SetBits", reinterpret_cast(patched_SetBits_early), (void**) &orig_SetBits_early)) { - printf("TEST-PASS | WindowsDllInterceptor | Early hook added\n"); - } else { - printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Failed to add early hook\n"); - return 1; - } - - if (SetBitsVolatile(0) == 0x2211) { - printf("TEST-PASS | WindowsDllInterceptor | Early hook was called\n"); - } else { - printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Early hook was not called\n"); - return 1; - } - - { - WindowsDllInterceptor ExeInterceptLate; - ExeInterceptLate.Init("TestDllInterceptor.exe"); - if (ExeInterceptLate.AddHook("SetBits", reinterpret_cast(patched_SetBits_late), (void**) &orig_SetBits_late)) { - printf("TEST-PASS | WindowsDllInterceptor | Late hook added\n"); - } else { - printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Failed to add late hook\n"); - return 1; - } - - if (SetBitsVolatile(0) == 0x332211) { - printf("TEST-PASS | WindowsDllInterceptor | Late hook was called\n"); - } else { - printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Late hook was not called\n"); - return 1; - } - } - - if (SetBitsVolatile(0) == 0x2211) { - printf("TEST-PASS | WindowsDllInterceptor | Late hook was unregistered\n"); - } else { - printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Late hook was not unregistered\n"); - return 1; - } - } - - if (SetBitsVolatile(0) == 0x11) { - printf("TEST-PASS | WindowsDllInterceptor | Early hook was unregistered\n"); - } else { - printf("TEST-UNEXPECTED-FAIL | WindowsDllInterceptor | Early hook was not unregistered\n"); - return 1; - } -#endif - if (TestHook("user32.dll", "GetWindowInfo") && #ifdef _WIN64 TestHook("user32.dll", "SetWindowLongPtrA") && @@ -242,9 +138,6 @@ int main() TestHook("kernel32.dll", "VirtualAlloc") && TestHook("kernel32.dll", "MapViewOfFile") && TestHook("gdi32.dll", "CreateDIBSection") && -#endif -#ifdef _M_IX86 // Shared hooks are the same as regular hooks on x64 - TestSharedHook("ntdll.dll", "LdrLoadDll") && #endif TestHook("ntdll.dll", "LdrLoadDll")) { printf("TEST-PASS | WindowsDllInterceptor | all checks passed\n"); From 1b60c67eea16d82448524307dc776542533649be Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Mon, 24 Feb 2014 15:04:53 -0500 Subject: [PATCH 48/48] Backed out changeset 2b3bda5a4744 (bug 975169) for Marionette-webapi failures. --- .../client/marionette/runner/base.py | 60 ++++++++++++------- testing/marionette/client/setup.py | 2 +- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/testing/marionette/client/marionette/runner/base.py b/testing/marionette/client/marionette/runner/base.py index ba431a1b6fae..892f893ad374 100644 --- a/testing/marionette/client/marionette/runner/base.py +++ b/testing/marionette/client/marionette/runner/base.py @@ -42,16 +42,10 @@ class MarionetteTestResult(unittest._TextTestResult, TestResultCollection): def __init__(self, *args, **kwargs): self.marionette = kwargs.pop('marionette') TestResultCollection.__init__(self, 'MarionetteTest') + unittest._TextTestResult.__init__(self, *args, **kwargs) self.passed = 0 self.testsRun = 0 self.result_modifiers = [] # used by mixins to modify the result - pid = kwargs.pop('b2g_pid') - if pid: - bases = [b for b in self.__class__.__bases__] - bases.append(B2GTestResultMixin) - self.__class__.__bases__ = tuple(bases) - B2GTestResultMixin.__init__(self, b2g_pid=pid) - unittest._TextTestResult.__init__(self, *args, **kwargs) @property def skipped(self): @@ -246,30 +240,17 @@ class MarionetteTextTestRunner(unittest.TextTestRunner): def __init__(self, **kwargs): self.marionette = kwargs['marionette'] self.capabilities = kwargs.pop('capabilities') - self.pre_run_functions = [] - self.b2g_pid = None del kwargs['marionette'] - - if self.capabilities['device'] != 'desktop' and self.capabilities['b2g']: - def b2g_pre_run(): - dm_type = os.environ.get('DM_TRANS', 'adb') - if dm_type == 'adb': - self.b2g_pid = get_b2g_pid(get_dm(self.marionette)) - self.pre_run_functions.append(b2g_pre_run) - unittest.TextTestRunner.__init__(self, **kwargs) def _makeResult(self): return self.resultclass(self.stream, self.descriptions, self.verbosity, - marionette=self.marionette, - b2g_pid=self.b2g_pid) + marionette=self.marionette) def run(self, test): "Run the given test case or test suite." - for pre_run_func in self.pre_run_functions: - pre_run_func() result = self._makeResult() if hasattr(self, 'failfast'): result.failfast = self.failfast @@ -330,6 +311,40 @@ class MarionetteTextTestRunner(unittest.TextTestRunner): return result +class B2GMarionetteTestResult(MarionetteTestResult, B2GTestResultMixin): + + def __init__(self, *args, **kwargs): + # stupid hack because _TextTestRunner doesn't accept **kwargs + b2g_pid = kwargs.pop('b2g_pid') + MarionetteTestResult.__init__(self, *args, **kwargs) + kwargs['b2g_pid'] = b2g_pid + B2GTestResultMixin.__init__(self, *args, **kwargs) + + +class B2GMarionetteTextTestRunner(MarionetteTextTestRunner): + + resultclass = B2GMarionetteTestResult + + def __init__(self, **kwargs): + MarionetteTextTestRunner.__init__(self, **kwargs) + if self.capabilities['device'] != 'desktop': + self.resultclass = B2GMarionetteTestResult + self.b2g_pid = None + + def _makeResult(self): + return self.resultclass(self.stream, + self.descriptions, + self.verbosity, + marionette=self.marionette, + b2g_pid=self.b2g_pid) + + def run(self, test): + dm_type = os.environ.get('DM_TRANS', 'adb') + if dm_type == 'adb': + self.b2g_pid = get_b2g_pid(get_dm(self.marionette)) + return super(B2GMarionetteTextTestRunner, self).run(test) + + class BaseMarionetteOptions(OptionParser): def __init__(self, **kwargs): OptionParser.__init__(self, **kwargs) @@ -749,6 +764,9 @@ class BaseMarionetteTestRunner(object): if not self._capabilities: self.capabilities + if self.capabilities['device'] != 'desktop': + self.textrunnerclass = B2GMarionetteTextTestRunner + for test in tests: self.add_test(test) diff --git a/testing/marionette/client/setup.py b/testing/marionette/client/setup.py index d960c0b9715e..ca39ed79cf3f 100644 --- a/testing/marionette/client/setup.py +++ b/testing/marionette/client/setup.py @@ -1,7 +1,7 @@ import os from setuptools import setup, find_packages -version = '0.7.5' +version = '0.7.4' # get documentation from the README try: