From ba9597df4e5e46d4c1383ecf8e5abf39dd1489f4 Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Sun, 14 Apr 2013 18:56:34 -0400 Subject: [PATCH 01/29] Bug 846995 Part 1: Fix all the files that reference SVGAnimatedTransformList r=jwatt --- content/svg/content/src/DOMSVGTransformList.cpp | 6 +++--- content/svg/content/src/DOMSVGTransformList.h | 2 +- content/svg/content/src/Makefile.in | 4 +++- content/svg/content/src/SVGGradientElement.cpp | 10 +++++----- content/svg/content/src/SVGGradientElement.h | 13 ++++++------- content/svg/content/src/SVGPatternElement.cpp | 10 +++++----- content/svg/content/src/SVGTransform.cpp | 6 +++--- content/svg/content/src/SVGTransformList.h | 2 +- content/svg/content/src/SVGTransformableElement.cpp | 10 +++++----- content/svg/content/src/SVGTransformableElement.h | 11 +++++------ content/svg/content/src/nsSVGElement.cpp | 8 ++++---- content/svg/content/src/nsSVGElement.h | 12 ++++++------ dom/bindings/Bindings.conf | 3 +-- 13 files changed, 48 insertions(+), 49 deletions(-) diff --git a/content/svg/content/src/DOMSVGTransformList.cpp b/content/svg/content/src/DOMSVGTransformList.cpp index b5d02df99553..bb3e2c6e07dd 100644 --- a/content/svg/content/src/DOMSVGTransformList.cpp +++ b/content/svg/content/src/DOMSVGTransformList.cpp @@ -6,7 +6,7 @@ #include "DOMSVGTransformList.h" #include "mozilla/dom/SVGTransform.h" #include "mozilla/dom/SVGMatrix.h" -#include "SVGAnimatedTransformList.h" +#include "nsSVGAnimatedTransformList.h" #include "nsSVGElement.h" #include "nsContentUtils.h" #include "mozilla/dom/SVGTransformListBinding.h" @@ -36,7 +36,7 @@ namespace mozilla { using namespace dom; // We could use NS_IMPL_CYCLE_COLLECTION_1, except that in Unlink() we need to -// clear our DOMSVGAnimatedTransformList's weak ref to us to be safe. (The other +// clear our SVGAnimatedTransformList's weak ref to us to be safe. (The other // option would be to not unlink and rely on the breaking of the other edges in // the cycle, as NS_SVG_VAL_IMPL_CYCLE_COLLECTION does.) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMSVGTransformList) @@ -116,7 +116,7 @@ DOMSVGTransformList::InternalListLengthWillChange(uint32_t aNewLength) SVGTransformList& DOMSVGTransformList::InternalList() const { - SVGAnimatedTransformList *alist = Element()->GetAnimatedTransformList(); + nsSVGAnimatedTransformList *alist = Element()->GetAnimatedTransformList(); return IsAnimValList() && alist->mAnimVal ? *alist->mAnimVal : alist->mBaseVal; diff --git a/content/svg/content/src/DOMSVGTransformList.h b/content/svg/content/src/DOMSVGTransformList.h index fa32a80691ba..e308d9102653 100644 --- a/content/svg/content/src/DOMSVGTransformList.h +++ b/content/svg/content/src/DOMSVGTransformList.h @@ -7,7 +7,7 @@ #ifndef MOZILLA_DOMSVGTRANSFORMLIST_H__ #define MOZILLA_DOMSVGTRANSFORMLIST_H__ -#include "DOMSVGAnimatedTransformList.h" +#include "mozilla/dom/SVGAnimatedTransformList.h" #include "nsAutoPtr.h" #include "nsCycleCollectionParticipant.h" #include "nsDebug.h" diff --git a/content/svg/content/src/Makefile.in b/content/svg/content/src/Makefile.in index 5d2274fb1727..5052914c3a8e 100644 --- a/content/svg/content/src/Makefile.in +++ b/content/svg/content/src/Makefile.in @@ -17,7 +17,6 @@ FAIL_ON_WARNINGS = 1 CPPSRCS = \ DOMSVGAnimatedLengthList.cpp \ DOMSVGAnimatedNumberList.cpp \ - DOMSVGAnimatedTransformList.cpp \ DOMSVGLength.cpp \ DOMSVGLengthList.cpp \ DOMSVGNumber.cpp \ @@ -31,6 +30,7 @@ CPPSRCS = \ nsDOMSVGZoomEvent.cpp \ nsISVGPoint.cpp \ nsSVGAngle.cpp \ + nsSVGAnimatedTransformList.cpp \ nsSVGBoolean.cpp \ nsSVGClass.cpp \ nsSVGDataParser.cpp \ @@ -172,12 +172,14 @@ EXPORTS = \ EXPORTS_NAMESPACES = mozilla/dom EXPORTS_mozilla/dom = \ + nsSVGAnimatedTransformList.h \ SVGAElement.h \ SVGAltGlyphElement.h \ SVGAngle.h \ SVGAnimatedAngle.h \ SVGAnimatedBoolean.h \ SVGAnimatedLength.h \ + SVGAnimatedTransformList.h \ SVGAnimateElement.h \ SVGAnimateTransformElement.h \ SVGAnimateMotionElement.h \ diff --git a/content/svg/content/src/SVGGradientElement.cpp b/content/svg/content/src/SVGGradientElement.cpp index 085b363abdd5..375eaa6d0dc6 100644 --- a/content/svg/content/src/SVGGradientElement.cpp +++ b/content/svg/content/src/SVGGradientElement.cpp @@ -5,7 +5,7 @@ #include "mozilla/dom/SVGGradientElement.h" -#include "DOMSVGAnimatedTransformList.h" +#include "mozilla/dom/SVGAnimatedTransformList.h" #include "mozilla/dom/SVGRadialGradientElementBinding.h" #include "mozilla/dom/SVGLinearGradientElementBinding.h" #include "mozilla/Util.h" @@ -78,12 +78,12 @@ SVGGradientElement::GradientUnits() } /* readonly attribute SVGAnimatedTransformList gradientTransform; */ -already_AddRefed +already_AddRefed SVGGradientElement::GradientTransform() { // We're creating a DOM wrapper, so we must tell GetAnimatedTransformList // to allocate the SVGAnimatedTransformList if it hasn't already done so: - return DOMSVGAnimatedTransformList::GetDOMWrapper( + return SVGAnimatedTransformList::GetDOMWrapper( GetAnimatedTransformList(DO_ALLOCATE), this); } @@ -172,11 +172,11 @@ SVGLinearGradientElement::Y2() //---------------------------------------------------------------------- // nsSVGElement methods -SVGAnimatedTransformList* +nsSVGAnimatedTransformList* SVGGradientElement::GetAnimatedTransformList(uint32_t aFlags) { if (!mGradientTransform && (aFlags & DO_ALLOCATE)) { - mGradientTransform = new SVGAnimatedTransformList(); + mGradientTransform = new nsSVGAnimatedTransformList(); } return mGradientTransform; } diff --git a/content/svg/content/src/SVGGradientElement.h b/content/svg/content/src/SVGGradientElement.h index 63608e46a653..b2a9c7c66bfb 100644 --- a/content/svg/content/src/SVGGradientElement.h +++ b/content/svg/content/src/SVGGradientElement.h @@ -6,11 +6,11 @@ #ifndef __NS_SVGGRADIENTELEMENT_H__ #define __NS_SVGGRADIENTELEMENT_H__ +#include "nsSVGAnimatedTransformList.h" #include "nsSVGElement.h" #include "nsSVGLength2.h" #include "nsSVGEnum.h" #include "nsSVGString.h" -#include "SVGAnimatedTransformList.h" static const unsigned short SVG_SPREADMETHOD_UNKNOWN = 0; static const unsigned short SVG_SPREADMETHOD_PAD = 1; @@ -29,11 +29,10 @@ NS_NewSVGRadialGradientElement(nsIContent** aResult, already_AddRefed aNodeInfo); namespace mozilla { - -class DOMSVGAnimatedTransformList; - namespace dom { +class SVGAnimatedTransformList; + //--------------------- Gradients------------------------ typedef nsSVGElement SVGGradientElementBase; @@ -53,7 +52,7 @@ public: // nsIContent NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const; - virtual SVGAnimatedTransformList* + virtual nsSVGAnimatedTransformList* GetAnimatedTransformList(uint32_t aFlags = 0); virtual nsIAtom* GetTransformListAttrName() const { return nsGkAtoms::gradientTransform; @@ -61,7 +60,7 @@ public: // WebIDL already_AddRefed GradientUnits(); - already_AddRefed GradientTransform(); + already_AddRefed GradientTransform(); already_AddRefed SpreadMethod(); already_AddRefed Href(); @@ -79,7 +78,7 @@ protected: static StringInfo sStringInfo[1]; // SVGGradientElement values - nsAutoPtr mGradientTransform; + nsAutoPtr mGradientTransform; }; //---------------------Linear Gradients------------------------ diff --git a/content/svg/content/src/SVGPatternElement.cpp b/content/svg/content/src/SVGPatternElement.cpp index 9bbfcd992257..632d150ab86d 100644 --- a/content/svg/content/src/SVGPatternElement.cpp +++ b/content/svg/content/src/SVGPatternElement.cpp @@ -5,9 +5,9 @@ #include "mozilla/Util.h" -#include "DOMSVGAnimatedTransformList.h" #include "nsCOMPtr.h" #include "nsGkAtoms.h" +#include "mozilla/dom/SVGAnimatedTransformList.h" #include "mozilla/dom/SVGPatternElement.h" #include "mozilla/dom/SVGPatternElementBinding.h" @@ -94,12 +94,12 @@ SVGPatternElement::PatternContentUnits() return mEnumAttributes[PATTERNCONTENTUNITS].ToDOMAnimatedEnum(this); } -already_AddRefed +already_AddRefed SVGPatternElement::PatternTransform() { // We're creating a DOM wrapper, so we must tell GetAnimatedTransformList // to allocate the SVGAnimatedTransformList if it hasn't already done so: - return DOMSVGAnimatedTransformList::GetDOMWrapper( + return SVGAnimatedTransformList::GetDOMWrapper( GetAnimatedTransformList(DO_ALLOCATE), this); } @@ -157,11 +157,11 @@ SVGPatternElement::IsAttributeMapped(const nsIAtom* name) const //---------------------------------------------------------------------- // nsSVGElement methods -SVGAnimatedTransformList* +nsSVGAnimatedTransformList* SVGPatternElement::GetAnimatedTransformList(uint32_t aFlags) { if (!mPatternTransform && (aFlags & DO_ALLOCATE)) { - mPatternTransform = new SVGAnimatedTransformList(); + mPatternTransform = new nsSVGAnimatedTransformList(); } return mPatternTransform; } diff --git a/content/svg/content/src/SVGTransform.cpp b/content/svg/content/src/SVGTransform.cpp index d803e5a5629b..a3816ff50327 100644 --- a/content/svg/content/src/SVGTransform.cpp +++ b/content/svg/content/src/SVGTransform.cpp @@ -6,10 +6,10 @@ #include "mozilla/dom/SVGTransform.h" #include "mozilla/dom/SVGMatrix.h" -#include "SVGAnimatedTransformList.h" #include "nsError.h" #include "nsContentUtils.h" #include "nsAttrValueInlines.h" +#include "nsSVGAnimatedTransformList.h" #include "nsSVGAttrTearoffTable.h" #include "mozilla/dom/SVGTransformBinding.h" @@ -283,7 +283,7 @@ SVGTransform::RemovingFromList() nsSVGTransform& SVGTransform::InternalItem() { - SVGAnimatedTransformList *alist = Element()->GetAnimatedTransformList(); + nsSVGAnimatedTransformList *alist = Element()->GetAnimatedTransformList(); return mIsAnimValItem && alist->mAnimVal ? (*alist->mAnimVal)[mListIndex] : alist->mBaseVal[mListIndex]; @@ -299,7 +299,7 @@ SVGTransform::InternalItem() const bool SVGTransform::IndexIsValid() { - SVGAnimatedTransformList *alist = Element()->GetAnimatedTransformList(); + nsSVGAnimatedTransformList *alist = Element()->GetAnimatedTransformList(); return (mIsAnimValItem && mListIndex < alist->GetAnimValue().Length()) || (!mIsAnimValItem && diff --git a/content/svg/content/src/SVGTransformList.h b/content/svg/content/src/SVGTransformList.h index c7e4eea86cb2..9f0d34afc7f7 100644 --- a/content/svg/content/src/SVGTransformList.h +++ b/content/svg/content/src/SVGTransformList.h @@ -29,7 +29,7 @@ class SVGTransform; */ class SVGTransformList { - friend class SVGAnimatedTransformList; + friend class nsSVGAnimatedTransformList; friend class DOMSVGTransformList; friend class dom::SVGTransform; diff --git a/content/svg/content/src/SVGTransformableElement.cpp b/content/svg/content/src/SVGTransformableElement.cpp index fd488fe1b28c..5c04fa081938 100644 --- a/content/svg/content/src/SVGTransformableElement.cpp +++ b/content/svg/content/src/SVGTransformableElement.cpp @@ -3,10 +3,10 @@ * 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/. */ +#include "mozilla/dom/SVGAnimatedTransformList.h" #include "mozilla/dom/SVGTransformableElement.h" #include "mozilla/dom/SVGMatrix.h" #include "mozilla/dom/SVGSVGElement.h" -#include "DOMSVGAnimatedTransformList.h" #include "nsContentUtils.h" #include "nsIDOMMutationEvent.h" #include "nsIFrame.h" @@ -18,12 +18,12 @@ namespace mozilla { namespace dom { -already_AddRefed +already_AddRefed SVGTransformableElement::Transform() { // We're creating a DOM wrapper, so we must tell GetAnimatedTransformList // to allocate the SVGAnimatedTransformList if it hasn't already done so: - return DOMSVGAnimatedTransformList::GetDOMWrapper( + return SVGAnimatedTransformList::GetDOMWrapper( GetAnimatedTransformList(DO_ALLOCATE), this).get(); } @@ -136,11 +136,11 @@ SVGTransformableElement::SetAnimateMotionTransform(const gfxMatrix* aMatrix) DidAnimateTransformList(); } -SVGAnimatedTransformList* +nsSVGAnimatedTransformList* SVGTransformableElement::GetAnimatedTransformList(uint32_t aFlags) { if (!mTransforms && (aFlags & DO_ALLOCATE)) { - mTransforms = new SVGAnimatedTransformList(); + mTransforms = new nsSVGAnimatedTransformList(); } return mTransforms; } diff --git a/content/svg/content/src/SVGTransformableElement.h b/content/svg/content/src/SVGTransformableElement.h index 26711f139638..dc51b9527ed6 100644 --- a/content/svg/content/src/SVGTransformableElement.h +++ b/content/svg/content/src/SVGTransformableElement.h @@ -6,15 +6,14 @@ #ifndef SVGTransformableElement_h #define SVGTransformableElement_h +#include "nsSVGAnimatedTransformList.h" #include "nsSVGElement.h" #include "gfxMatrix.h" -#include "SVGAnimatedTransformList.h" namespace mozilla { -class DOMSVGAnimatedTransformList; - namespace dom { +class SVGAnimatedTransformList; class SVGGraphicsElement; class SVGMatrix; class SVGIRect; @@ -29,7 +28,7 @@ public: virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE = 0; // WebIDL - already_AddRefed Transform(); + already_AddRefed Transform(); nsSVGElement* GetNearestViewportElement(); nsSVGElement* GetFarthestViewportElement(); already_AddRefed GetBBox(ErrorResult& rv); @@ -53,7 +52,7 @@ public: virtual const gfxMatrix* GetAnimateMotionTransform() const; virtual void SetAnimateMotionTransform(const gfxMatrix* aMatrix); - virtual SVGAnimatedTransformList* + virtual nsSVGAnimatedTransformList* GetAnimatedTransformList(uint32_t aFlags = 0); virtual nsIAtom* GetTransformListAttrName() const { return nsGkAtoms::transform; @@ -64,7 +63,7 @@ public: protected: // nsSVGElement overrides - nsAutoPtr mTransforms; + nsAutoPtr mTransforms; // XXX maybe move this to property table, to save space on un-animated elems? nsAutoPtr mAnimateMotionTransform; diff --git a/content/svg/content/src/nsSVGElement.cpp b/content/svg/content/src/nsSVGElement.cpp index a79a52453b30..3310a491c4f8 100644 --- a/content/svg/content/src/nsSVGElement.cpp +++ b/content/svg/content/src/nsSVGElement.cpp @@ -24,6 +24,7 @@ #include "nsCSSProps.h" #include "nsCSSParser.h" #include "nsEventListenerManager.h" +#include "nsSVGAnimatedTransformList.h" #include "nsSVGLength2.h" #include "nsSVGNumber2.h" #include "nsSVGNumberPair.h" @@ -38,7 +39,6 @@ #include "SVGAnimatedLengthList.h" #include "SVGAnimatedPointList.h" #include "SVGAnimatedPathSegList.h" -#include "SVGAnimatedTransformList.h" #include "SVGContentUtils.h" #include "nsIFrame.h" #include @@ -601,8 +601,8 @@ nsSVGElement::ParseAttribute(int32_t aNamespaceID, // Check for SVGAnimatedTransformList attribute } else if (GetTransformListAttrName() == aAttribute) { // The transform attribute is being set, so we must ensure that the - // SVGAnimatedTransformList is/has been allocated: - SVGAnimatedTransformList *transformList = + // nsSVGAnimatedTransformList is/has been allocated: + nsSVGAnimatedTransformList *transformList = GetAnimatedTransformList(DO_ALLOCATE); rv = transformList->SetBaseValueString(aValue); if (NS_FAILED(rv)) { @@ -820,7 +820,7 @@ nsSVGElement::UnsetAttrInternal(int32_t aNamespaceID, nsIAtom* aName, // Check if this is a transform list attribute going away if (GetTransformListAttrName() == aName) { - SVGAnimatedTransformList *transformList = GetAnimatedTransformList(); + nsSVGAnimatedTransformList *transformList = GetAnimatedTransformList(); if (transformList) { MaybeSerializeAttrBeforeRemoval(aName, aNotify); transformList->ClearBaseValue(); diff --git a/content/svg/content/src/nsSVGElement.h b/content/svg/content/src/nsSVGElement.h index e361728350d9..f2a2dded7422 100644 --- a/content/svg/content/src/nsSVGElement.h +++ b/content/svg/content/src/nsSVGElement.h @@ -52,7 +52,7 @@ class SVGUserUnitList; class SVGAnimatedPointList; class SVGAnimatedPathSegList; class SVGAnimatedPreserveAspectRatio; -class SVGAnimatedTransformList; +class nsSVGAnimatedTransformList; class SVGStringList; class DOMSVGStringList; } @@ -83,7 +83,7 @@ public: typedef mozilla::SVGAnimatedPointList SVGAnimatedPointList; typedef mozilla::SVGAnimatedPathSegList SVGAnimatedPathSegList; typedef mozilla::SVGAnimatedPreserveAspectRatio SVGAnimatedPreserveAspectRatio; - typedef mozilla::SVGAnimatedTransformList SVGAnimatedTransformList; + typedef mozilla::nsSVGAnimatedTransformList nsSVGAnimatedTransformList; typedef mozilla::SVGStringList SVGStringList; // nsISupports @@ -264,18 +264,18 @@ public: return nullptr; } /** - * Get the SVGAnimatedTransformList for this element. + * Get the nsSVGAnimatedTransformList for this element. * * Despite the fact that animated transform lists are used for a variety of * attributes, no SVG element uses more than one. * * It's relatively uncommon for elements to have their transform attribute - * set, so to save memory the SVGAnimatedTransformList is not allocated until + * set, so to save memory the nsSVGAnimatedTransformList is not allocated until * the attribute is set/animated or its DOM wrapper is created. Callers that - * require the SVGAnimatedTransformList to be allocated and for this method + * require the nsSVGAnimatedTransformList to be allocated and for this method * to return non-null must pass the DO_ALLOCATE flag. */ - virtual SVGAnimatedTransformList* GetAnimatedTransformList( + virtual nsSVGAnimatedTransformList* GetAnimatedTransformList( uint32_t aFlags = 0) { return nullptr; } diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index d321435b91bc..5c934109e029 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -740,8 +740,7 @@ DOMInterfaces = { }, 'SVGAnimatedTransformList': { - 'nativeType': 'mozilla::DOMSVGAnimatedTransformList', - 'headerFile': 'DOMSVGAnimatedTransformList.h' + # 'nativeOwnership': 'refcounted', }, 'SVGAnimationElement': { From a5dffaf138b26ca3427643aa8f8b1b08be787d53 Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Sun, 14 Apr 2013 18:56:34 -0400 Subject: [PATCH 02/29] Bug 846995 Part 2: Rename SVGAnimatedTransformList to nsSVGAnimatedTransformList r=jwatt --HG-- rename : content/svg/content/src/SVGAnimatedTransformList.cpp => content/svg/content/src/nsSVGAnimatedTransformList.cpp rename : content/svg/content/src/SVGAnimatedTransformList.h => content/svg/content/src/nsSVGAnimatedTransformList.h --- ...ist.cpp => nsSVGAnimatedTransformList.cpp} | 51 ++++++++++--------- ...ormList.h => nsSVGAnimatedTransformList.h} | 16 +++--- 2 files changed, 34 insertions(+), 33 deletions(-) rename content/svg/content/src/{SVGAnimatedTransformList.cpp => nsSVGAnimatedTransformList.cpp} (85%) rename content/svg/content/src/{SVGAnimatedTransformList.h => nsSVGAnimatedTransformList.h} (90%) diff --git a/content/svg/content/src/SVGAnimatedTransformList.cpp b/content/svg/content/src/nsSVGAnimatedTransformList.cpp similarity index 85% rename from content/svg/content/src/SVGAnimatedTransformList.cpp rename to content/svg/content/src/nsSVGAnimatedTransformList.cpp index 169eb3099173..bfd38ec2a3c3 100644 --- a/content/svg/content/src/SVGAnimatedTransformList.cpp +++ b/content/svg/content/src/nsSVGAnimatedTransformList.cpp @@ -3,9 +3,8 @@ * 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/. */ -#include "SVGAnimatedTransformList.h" -#include "DOMSVGAnimatedTransformList.h" - +#include "nsSVGAnimatedTransformList.h" +#include "mozilla/dom/SVGAnimatedTransformList.h" #include "mozilla/dom/SVGAnimationElement.h" #include "nsSMILValue.h" #include "prdtoa.h" @@ -15,8 +14,10 @@ namespace mozilla { +using namespace dom; + nsresult -SVGAnimatedTransformList::SetBaseValueString(const nsAString& aValue) +nsSVGAnimatedTransformList::SetBaseValueString(const nsAString& aValue) { SVGTransformList newBaseValue; nsresult rv = newBaseValue.SetValueFromString(aValue); @@ -24,8 +25,8 @@ SVGAnimatedTransformList::SetBaseValueString(const nsAString& aValue) return rv; } - DOMSVGAnimatedTransformList *domWrapper = - DOMSVGAnimatedTransformList::GetDOMWrapperIfExists(this); + SVGAnimatedTransformList *domWrapper = + SVGAnimatedTransformList::GetDOMWrapperIfExists(this); if (domWrapper) { // We must send this notification *before* changing mBaseVal! If the length // of our baseVal is being reduced, our baseVal's DOM wrapper list may have @@ -51,10 +52,10 @@ SVGAnimatedTransformList::SetBaseValueString(const nsAString& aValue) } void -SVGAnimatedTransformList::ClearBaseValue() +nsSVGAnimatedTransformList::ClearBaseValue() { - DOMSVGAnimatedTransformList *domWrapper = - DOMSVGAnimatedTransformList::GetDOMWrapperIfExists(this); + SVGAnimatedTransformList *domWrapper = + SVGAnimatedTransformList::GetDOMWrapperIfExists(this); if (domWrapper) { // We must send this notification *before* changing mBaseVal! (See above.) domWrapper->InternalBaseValListWillChangeLengthTo(0); @@ -65,17 +66,17 @@ SVGAnimatedTransformList::ClearBaseValue() } nsresult -SVGAnimatedTransformList::SetAnimValue(const SVGTransformList& aValue, - nsSVGElement *aElement) +nsSVGAnimatedTransformList::SetAnimValue(const SVGTransformList& aValue, + nsSVGElement *aElement) { - DOMSVGAnimatedTransformList *domWrapper = - DOMSVGAnimatedTransformList::GetDOMWrapperIfExists(this); + SVGAnimatedTransformList *domWrapper = + SVGAnimatedTransformList::GetDOMWrapperIfExists(this); if (domWrapper) { // A new animation may totally change the number of items in the animVal // list, replacing what was essentially a mirror of the baseVal list, or // else replacing and overriding an existing animation. When this happens // we must try and keep our animVal's DOM wrapper in sync (see the comment - // in DOMSVGAnimatedTransformList::InternalBaseValListWillChangeLengthTo). + // in SVGAnimatedTransformList::InternalBaseValListWillChangeLengthTo). // // It's not possible for us to reliably distinguish between calls to this // method that are setting a new sample for an existing animation, and @@ -104,10 +105,10 @@ SVGAnimatedTransformList::SetAnimValue(const SVGTransformList& aValue, } void -SVGAnimatedTransformList::ClearAnimValue(nsSVGElement *aElement) +nsSVGAnimatedTransformList::ClearAnimValue(nsSVGElement *aElement) { - DOMSVGAnimatedTransformList *domWrapper = - DOMSVGAnimatedTransformList::GetDOMWrapperIfExists(this); + SVGAnimatedTransformList *domWrapper = + SVGAnimatedTransformList::GetDOMWrapperIfExists(this); if (domWrapper) { // When all animation ends, animVal simply mirrors baseVal, which may have // a different number of items to the last active animated value. We must @@ -121,7 +122,7 @@ SVGAnimatedTransformList::ClearAnimValue(nsSVGElement *aElement) } bool -SVGAnimatedTransformList::IsExplicitlySet() const +nsSVGAnimatedTransformList::IsExplicitlySet() const { // Like other methods of this name, we need to know when a transform value has // been explicitly set. @@ -138,13 +139,13 @@ SVGAnimatedTransformList::IsExplicitlySet() const } nsISMILAttr* -SVGAnimatedTransformList::ToSMILAttr(nsSVGElement* aSVGElement) +nsSVGAnimatedTransformList::ToSMILAttr(nsSVGElement* aSVGElement) { return new SMILAnimatedTransformList(this, aSVGElement); } nsresult -SVGAnimatedTransformList::SMILAnimatedTransformList::ValueFromString( +nsSVGAnimatedTransformList::SMILAnimatedTransformList::ValueFromString( const nsAString& aStr, const dom::SVGAnimationElement* aSrcElement, nsSMILValue& aValue, @@ -172,7 +173,7 @@ SVGAnimatedTransformList::SMILAnimatedTransformList::ValueFromString( } void -SVGAnimatedTransformList::SMILAnimatedTransformList::ParseValue( +nsSVGAnimatedTransformList::SMILAnimatedTransformList::ParseValue( const nsAString& aSpec, const nsIAtom* aTransformType, nsSMILValue& aResult) @@ -240,7 +241,7 @@ namespace } // end anonymous namespace block int32_t -SVGAnimatedTransformList::SMILAnimatedTransformList::ParseParameterList( +nsSVGAnimatedTransformList::SMILAnimatedTransformList::ParseParameterList( const nsAString& aSpec, float* aVars, int32_t aNVars) @@ -280,7 +281,7 @@ SVGAnimatedTransformList::SMILAnimatedTransformList::ParseParameterList( } nsSMILValue -SVGAnimatedTransformList::SMILAnimatedTransformList::GetBaseValue() const +nsSVGAnimatedTransformList::SMILAnimatedTransformList::GetBaseValue() const { // To benefit from Return Value Optimization and avoid copy constructor calls // due to our use of return-by-value, we must return the exact same object @@ -294,7 +295,7 @@ SVGAnimatedTransformList::SMILAnimatedTransformList::GetBaseValue() const } nsresult -SVGAnimatedTransformList::SMILAnimatedTransformList::SetAnimValue( +nsSVGAnimatedTransformList::SMILAnimatedTransformList::SetAnimValue( const nsSMILValue& aNewAnimValue) { NS_ABORT_IF_FALSE( @@ -310,7 +311,7 @@ SVGAnimatedTransformList::SMILAnimatedTransformList::SetAnimValue( } void -SVGAnimatedTransformList::SMILAnimatedTransformList::ClearAnimValue() +nsSVGAnimatedTransformList::SMILAnimatedTransformList::ClearAnimValue() { if (mVal->mAnimVal) { mVal->ClearAnimValue(mElement); diff --git a/content/svg/content/src/SVGAnimatedTransformList.h b/content/svg/content/src/nsSVGAnimatedTransformList.h similarity index 90% rename from content/svg/content/src/SVGAnimatedTransformList.h rename to content/svg/content/src/nsSVGAnimatedTransformList.h index a2a374169263..c218d47cfc17 100644 --- a/content/svg/content/src/SVGAnimatedTransformList.h +++ b/content/svg/content/src/nsSVGAnimatedTransformList.h @@ -23,32 +23,32 @@ class SVGTransform; } /** - * Class SVGAnimatedTransformList + * Class nsSVGAnimatedTransformList * * This class is very different to the SVG DOM interface of the same name found * in the SVG specification. This is a lightweight internal class - see - * DOMSVGAnimatedTransformList for the heavier DOM class that wraps instances of + * SVGAnimatedTransformList for the heavier DOM class that wraps instances of * this class and implements the SVG specification's SVGAnimatedTransformList * DOM interface. * * Except where noted otherwise, this class' methods take care of keeping the * appropriate DOM wrappers in sync (see the comment in - * DOMSVGAnimatedTransformList::InternalBaseValListWillChangeTo) so that their + * SVGAnimatedTransformList::InternalBaseValListWillChangeTo) so that their * consumers don't need to concern themselves with that. */ -class SVGAnimatedTransformList +class nsSVGAnimatedTransformList { // friends so that they can get write access to mBaseVal friend class dom::SVGTransform; friend class DOMSVGTransformList; public: - SVGAnimatedTransformList() : mIsAttrSet(false) { } + nsSVGAnimatedTransformList() : mIsAttrSet(false) { } /** * Because it's so important that mBaseVal and its DOMSVGTransformList wrapper * (if any) be kept in sync (see the comment in - * DOMSVGAnimatedTransformList::InternalBaseValListWillChangeTo), this method + * SVGAnimatedTransformList::InternalBaseValListWillChangeTo), this method * returns a const reference. Only our friend classes may get mutable * references to mBaseVal. */ @@ -106,7 +106,7 @@ private: struct SMILAnimatedTransformList : public nsISMILAttr { public: - SMILAnimatedTransformList(SVGAnimatedTransformList* aVal, + SMILAnimatedTransformList(nsSVGAnimatedTransformList* aVal, nsSVGElement* aSVGElement) : mVal(aVal) , mElement(aSVGElement) @@ -131,7 +131,7 @@ private: // These will stay alive because a nsISMILAttr only lives as long // as the Compositing step, and DOM elements don't get a chance to // die during that. - SVGAnimatedTransformList* mVal; + nsSVGAnimatedTransformList* mVal; nsSVGElement* mElement; }; }; From eeb5fc72075dbcc733342254280e70b7e3793218 Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Sun, 14 Apr 2013 18:56:34 -0400 Subject: [PATCH 03/29] Bug 846995 Part 3: Rename DOMSVGAnimatedTransformList and kill nsISupports r=jwatt --HG-- rename : content/svg/content/src/DOMSVGAnimatedTransformList.cpp => content/svg/content/src/SVGAnimatedTransformList.cpp rename : content/svg/content/src/DOMSVGAnimatedTransformList.h => content/svg/content/src/SVGAnimatedTransformList.h --- content/svg/content/src/DOMSVGTransformList.h | 6 +- ...mList.cpp => SVGAnimatedTransformList.cpp} | 61 +++++++++---------- ...sformList.h => SVGAnimatedTransformList.h} | 54 ++++++++-------- .../svg/content/src/SVGFragmentIdentifier.cpp | 4 +- content/svg/content/src/SVGPatternElement.h | 11 ++-- dom/bindings/Bindings.conf | 2 +- layout/svg/nsSVGContainerFrame.cpp | 4 +- layout/svg/nsSVGForeignObjectFrame.cpp | 2 +- layout/svg/nsSVGGradientFrame.cpp | 8 +-- layout/svg/nsSVGGradientFrame.h | 4 +- layout/svg/nsSVGPathGeometryFrame.cpp | 2 +- layout/svg/nsSVGPatternFrame.cpp | 8 +-- layout/svg/nsSVGPatternFrame.h | 4 +- 13 files changed, 84 insertions(+), 86 deletions(-) rename content/svg/content/src/{DOMSVGAnimatedTransformList.cpp => SVGAnimatedTransformList.cpp} (63%) rename content/svg/content/src/{DOMSVGAnimatedTransformList.h => SVGAnimatedTransformList.h} (70%) diff --git a/content/svg/content/src/DOMSVGTransformList.h b/content/svg/content/src/DOMSVGTransformList.h index e308d9102653..b4a701413594 100644 --- a/content/svg/content/src/DOMSVGTransformList.h +++ b/content/svg/content/src/DOMSVGTransformList.h @@ -31,7 +31,7 @@ class SVGTransform; * This class is used to create the DOM tearoff objects that wrap internal * SVGTransformList objects. * - * See the architecture comment in DOMSVGAnimatedTransformList.h. + * See the architecture comment in SVGAnimatedTransformList.h. */ class DOMSVGTransformList MOZ_FINAL : public nsISupports, public nsWrapperCache @@ -42,7 +42,7 @@ public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGTransformList) - DOMSVGTransformList(DOMSVGAnimatedTransformList *aAList, + DOMSVGTransformList(dom::SVGAnimatedTransformList *aAList, const SVGTransformList &aInternalList) : mAList(aAList) { @@ -160,7 +160,7 @@ private: // of clearing our pointer to them when they die. FallibleTArray mItems; - nsRefPtr mAList; + nsRefPtr mAList; }; } // namespace mozilla diff --git a/content/svg/content/src/DOMSVGAnimatedTransformList.cpp b/content/svg/content/src/SVGAnimatedTransformList.cpp similarity index 63% rename from content/svg/content/src/DOMSVGAnimatedTransformList.cpp rename to content/svg/content/src/SVGAnimatedTransformList.cpp index 8bac16a01a1e..717061df1207 100644 --- a/content/svg/content/src/DOMSVGAnimatedTransformList.cpp +++ b/content/svg/content/src/SVGAnimatedTransformList.cpp @@ -3,38 +3,34 @@ * 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/. */ -#include "DOMSVGAnimatedTransformList.h" +#include "mozilla/dom/SVGAnimatedTransformList.h" #include "DOMSVGTransformList.h" -#include "SVGAnimatedTransformList.h" +#include "nsSVGAnimatedTransformList.h" #include "nsSVGAttrTearoffTable.h" #include "mozilla/dom/SVGAnimatedTransformListBinding.h" #include "nsContentUtils.h" namespace mozilla { +namespace dom { static - nsSVGAttrTearoffTable + nsSVGAttrTearoffTable sSVGAnimatedTransformListTearoffTable; -NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(DOMSVGAnimatedTransformList, mElement) +NS_SVG_VAL_IMPL_CYCLE_COLLECTION_WRAPPERCACHED(SVGAnimatedTransformList, mElement) -NS_IMPL_CYCLE_COLLECTING_ADDREF(DOMSVGAnimatedTransformList) -NS_IMPL_CYCLE_COLLECTING_RELEASE(DOMSVGAnimatedTransformList) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DOMSVGAnimatedTransformList) - NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END +NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(SVGAnimatedTransformList, AddRef) +NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(SVGAnimatedTransformList, Release) JSObject* -DOMSVGAnimatedTransformList::WrapObject(JSContext* aCx, JSObject* aScope) +SVGAnimatedTransformList::WrapObject(JSContext* aCx, JSObject* aScope) { - return mozilla::dom::SVGAnimatedTransformListBinding::Wrap(aCx, aScope, this); + return SVGAnimatedTransformListBinding::Wrap(aCx, aScope, this); } //---------------------------------------------------------------------- already_AddRefed -DOMSVGAnimatedTransformList::BaseVal() +SVGAnimatedTransformList::BaseVal() { if (!mBaseVal) { mBaseVal = new DOMSVGTransformList(this, InternalAList().GetBaseValue()); @@ -44,7 +40,7 @@ DOMSVGAnimatedTransformList::BaseVal() } already_AddRefed -DOMSVGAnimatedTransformList::AnimVal() +SVGAnimatedTransformList::AnimVal() { if (!mAnimVal) { mAnimVal = new DOMSVGTransformList(this, InternalAList().GetAnimValue()); @@ -53,27 +49,27 @@ DOMSVGAnimatedTransformList::AnimVal() return animVal.forget(); } -/* static */ already_AddRefed -DOMSVGAnimatedTransformList::GetDOMWrapper(SVGAnimatedTransformList *aList, - nsSVGElement *aElement) +/* static */ already_AddRefed +SVGAnimatedTransformList::GetDOMWrapper(nsSVGAnimatedTransformList *aList, + nsSVGElement *aElement) { - nsRefPtr wrapper = + nsRefPtr wrapper = sSVGAnimatedTransformListTearoffTable.GetTearoff(aList); if (!wrapper) { - wrapper = new DOMSVGAnimatedTransformList(aElement); + wrapper = new SVGAnimatedTransformList(aElement); sSVGAnimatedTransformListTearoffTable.AddTearoff(aList, wrapper); } return wrapper.forget(); } -/* static */ DOMSVGAnimatedTransformList* -DOMSVGAnimatedTransformList::GetDOMWrapperIfExists( - SVGAnimatedTransformList *aList) +/* static */ SVGAnimatedTransformList* +SVGAnimatedTransformList::GetDOMWrapperIfExists( + nsSVGAnimatedTransformList *aList) { return sSVGAnimatedTransformListTearoffTable.GetTearoff(aList); } -DOMSVGAnimatedTransformList::~DOMSVGAnimatedTransformList() +SVGAnimatedTransformList::~SVGAnimatedTransformList() { // Script no longer has any references to us, to our base/animVal objects, or // to any of their list items. @@ -81,7 +77,7 @@ DOMSVGAnimatedTransformList::~DOMSVGAnimatedTransformList() } void -DOMSVGAnimatedTransformList::InternalBaseValListWillChangeLengthTo( +SVGAnimatedTransformList::InternalBaseValListWillChangeLengthTo( uint32_t aNewLength) { // When the number of items in our internal counterpart's baseVal changes, @@ -91,7 +87,7 @@ DOMSVGAnimatedTransformList::InternalBaseValListWillChangeLengthTo( // able to access "items" at indexes that are out of bounds (read/write to // bad memory)!! - nsRefPtr kungFuDeathGrip; + nsRefPtr kungFuDeathGrip; if (mBaseVal) { if (aNewLength < mBaseVal->LengthNoFlush()) { // InternalListLengthWillChange might clear last reference to |this|. @@ -112,7 +108,7 @@ DOMSVGAnimatedTransformList::InternalBaseValListWillChangeLengthTo( } void -DOMSVGAnimatedTransformList::InternalAnimValListWillChangeLengthTo( +SVGAnimatedTransformList::InternalAnimValListWillChangeLengthTo( uint32_t aNewLength) { if (mAnimVal) { @@ -121,21 +117,22 @@ DOMSVGAnimatedTransformList::InternalAnimValListWillChangeLengthTo( } bool -DOMSVGAnimatedTransformList::IsAnimating() const +SVGAnimatedTransformList::IsAnimating() const { return InternalAList().IsAnimating(); } -SVGAnimatedTransformList& -DOMSVGAnimatedTransformList::InternalAList() +nsSVGAnimatedTransformList& +SVGAnimatedTransformList::InternalAList() { return *mElement->GetAnimatedTransformList(); } -const SVGAnimatedTransformList& -DOMSVGAnimatedTransformList::InternalAList() const +const nsSVGAnimatedTransformList& +SVGAnimatedTransformList::InternalAList() const { return *mElement->GetAnimatedTransformList(); } +} // namespace dom } // namespace mozilla diff --git a/content/svg/content/src/DOMSVGAnimatedTransformList.h b/content/svg/content/src/SVGAnimatedTransformList.h similarity index 70% rename from content/svg/content/src/DOMSVGAnimatedTransformList.h rename to content/svg/content/src/SVGAnimatedTransformList.h index 36b7b399b220..dbad9bb43e38 100644 --- a/content/svg/content/src/DOMSVGAnimatedTransformList.h +++ b/content/svg/content/src/SVGAnimatedTransformList.h @@ -4,8 +4,8 @@ * 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 MOZILLA_DOMSVGANIMATEDTRANSFORMLIST_H__ -#define MOZILLA_DOMSVGANIMATEDTRANSFORMLIST_H__ +#ifndef mozilla_dom_SVGAnimatedTransformList_h +#define mozilla_dom_SVGAnimatedTransformList_h #include "nsAutoPtr.h" #include "nsCOMPtr.h" @@ -17,13 +17,15 @@ namespace mozilla { class DOMSVGTransformList; -class SVGAnimatedTransformList; +class nsSVGAnimatedTransformList; + +namespace dom { /** - * Class DOMSVGAnimatedTransformList + * Class SVGAnimatedTransformList * * This class is used to create the DOM tearoff objects that wrap internal - * SVGAnimatedTransformList objects. + * nsSVGAnimatedTransformList objects. * * See the architecture comment in DOMSVGAnimatedLengthList.h (that's * LENGTH list). The comment for that class largly applies to this one too @@ -35,36 +37,35 @@ class SVGAnimatedTransformList; * nulling out our pointers to them when they die (making our pointers to them * true weak refs). */ -class DOMSVGAnimatedTransformList MOZ_FINAL : public nsISupports, - public nsWrapperCache +class SVGAnimatedTransformList MOZ_FINAL : public nsWrapperCache { - friend class DOMSVGTransformList; + friend class mozilla::DOMSVGTransformList; public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DOMSVGAnimatedTransformList) + NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(SVGAnimatedTransformList) + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(SVGAnimatedTransformList) /** - * Factory method to create and return a DOMSVGAnimatedTransformList wrapper - * for a given internal SVGAnimatedTransformList object. The factory takes + * Factory method to create and return a SVGAnimatedTransformList wrapper + * for a given internal nsSVGAnimatedTransformList object. The factory takes * care of caching the object that it returns so that the same object can be - * returned for the given SVGAnimatedTransformList each time it is requested. + * returned for the given nsSVGAnimatedTransformList each time it is requested. * The cached object is only removed from the cache when it is destroyed due * to there being no more references to it or to any of its descendant * objects. If that happens, any subsequent call requesting the DOM wrapper - * for the SVGAnimatedTransformList will naturally result in a new - * DOMSVGAnimatedTransformList being returned. + * for the nsSVGAnimatedTransformList will naturally result in a new + * SVGAnimatedTransformList being returned. */ - static already_AddRefed - GetDOMWrapper(SVGAnimatedTransformList *aList, nsSVGElement *aElement); + static already_AddRefed + GetDOMWrapper(nsSVGAnimatedTransformList *aList, nsSVGElement *aElement); /** - * This method returns the DOMSVGAnimatedTransformList wrapper for an internal - * SVGAnimatedTransformList object if it currently has a wrapper. If it does + * This method returns the SVGAnimatedTransformList wrapper for an internal + * nsSVGAnimatedTransformList object if it currently has a wrapper. If it does * not, then nullptr is returned. */ - static DOMSVGAnimatedTransformList* - GetDOMWrapperIfExists(SVGAnimatedTransformList *aList); + static SVGAnimatedTransformList* + GetDOMWrapperIfExists(nsSVGAnimatedTransformList *aList); /** * Called by internal code to notify us when we need to sync the length of @@ -100,7 +101,7 @@ private: * Only our static GetDOMWrapper() factory method may create objects of our * type. */ - explicit DOMSVGAnimatedTransformList(nsSVGElement *aElement) + explicit SVGAnimatedTransformList(nsSVGElement *aElement) : mBaseVal(nullptr) , mAnimVal(nullptr) , mElement(aElement) @@ -108,11 +109,11 @@ private: SetIsDOMBinding(); } - ~DOMSVGAnimatedTransformList(); + ~SVGAnimatedTransformList(); /// Get a reference to this DOM wrapper object's internal counterpart. - SVGAnimatedTransformList& InternalAList(); - const SVGAnimatedTransformList& InternalAList() const; + nsSVGAnimatedTransformList& InternalAList(); + const nsSVGAnimatedTransformList& InternalAList() const; // Weak refs to our DOMSVGTransformList baseVal/animVal objects. These objects // are friends and take care of clearing these pointers when they die, making @@ -125,6 +126,7 @@ private: nsRefPtr mElement; }; +} // namespace dom } // namespace mozilla -#endif // MOZILLA_DOMSVGANIMATEDTRANSFORMLIST_H__ +#endif // mozilla_dom_SVGAnimatedTransformList_h diff --git a/content/svg/content/src/SVGFragmentIdentifier.cpp b/content/svg/content/src/SVGFragmentIdentifier.cpp index 54620386611b..f2a5b9af5d33 100644 --- a/content/svg/content/src/SVGFragmentIdentifier.cpp +++ b/content/svg/content/src/SVGFragmentIdentifier.cpp @@ -6,7 +6,7 @@ #include "SVGFragmentIdentifier.h" #include "mozilla/dom/SVGSVGElement.h" #include "mozilla/dom/SVGViewElement.h" -#include "SVGAnimatedTransformList.h" +#include "nsSVGAnimatedTransformList.h" using namespace mozilla; @@ -156,7 +156,7 @@ SVGFragmentIdentifier::ProcessSVGViewSpec(const nsAString &aViewSpec, } preserveAspectRatioFound = true; } else if (IsMatchingParameter(token, NS_LITERAL_STRING("transform"))) { - SVGAnimatedTransformList transforms; + nsSVGAnimatedTransformList transforms; if (transformFound || NS_FAILED(transforms.SetBaseValueString(params))) { return false; diff --git a/content/svg/content/src/SVGPatternElement.h b/content/svg/content/src/SVGPatternElement.h index 13c383b99e51..72292c92b349 100644 --- a/content/svg/content/src/SVGPatternElement.h +++ b/content/svg/content/src/SVGPatternElement.h @@ -12,7 +12,7 @@ #include "nsSVGElement.h" #include "nsSVGViewBox.h" #include "SVGAnimatedPreserveAspectRatio.h" -#include "SVGAnimatedTransformList.h" +#include "nsSVGAnimatedTransformList.h" class nsSVGPatternFrame; @@ -20,9 +20,8 @@ nsresult NS_NewSVGPatternElement(nsIContent **aResult, already_AddRefed aNodeInfo); namespace mozilla { -class DOMSVGAnimatedTransformList; - namespace dom { +class SVGAnimatedTransformList; typedef nsSVGElement SVGPatternElementBase; @@ -47,7 +46,7 @@ public: // nsSVGSVGElement methods: virtual bool HasValidDimensions() const; - virtual mozilla::SVGAnimatedTransformList* + virtual mozilla::nsSVGAnimatedTransformList* GetAnimatedTransformList(uint32_t aFlags = 0); virtual nsIAtom* GetTransformListAttrName() const { return nsGkAtoms::patternTransform; @@ -58,7 +57,7 @@ public: already_AddRefed PreserveAspectRatio(); already_AddRefed PatternUnits(); already_AddRefed PatternContentUnits(); - already_AddRefed PatternTransform(); + already_AddRefed PatternTransform(); already_AddRefed X(); already_AddRefed Y(); already_AddRefed Width(); @@ -81,7 +80,7 @@ protected: nsSVGEnum mEnumAttributes[2]; static EnumInfo sEnumInfo[2]; - nsAutoPtr mPatternTransform; + nsAutoPtr mPatternTransform; enum { HREF }; nsSVGString mStringAttributes[1]; diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index 5c934109e029..ed8afa6c2132 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -740,7 +740,7 @@ DOMInterfaces = { }, 'SVGAnimatedTransformList': { - # 'nativeOwnership': 'refcounted', + 'nativeOwnership': 'refcounted', }, 'SVGAnimationElement': { diff --git a/layout/svg/nsSVGContainerFrame.cpp b/layout/svg/nsSVGContainerFrame.cpp index e4bced090052..f84941dea1a9 100644 --- a/layout/svg/nsSVGContainerFrame.cpp +++ b/layout/svg/nsSVGContainerFrame.cpp @@ -10,7 +10,7 @@ #include "nsSVGEffects.h" #include "nsSVGElement.h" #include "nsSVGUtils.h" -#include "SVGAnimatedTransformList.h" +#include "nsSVGAnimatedTransformList.h" using namespace mozilla; @@ -179,7 +179,7 @@ nsSVGDisplayContainerFrame::IsSVGTransformed(gfxMatrix *aOwnTransform, if (mContent->IsSVG()) { nsSVGElement *content = static_cast(mContent); - SVGAnimatedTransformList* transformList = + nsSVGAnimatedTransformList* transformList = content->GetAnimatedTransformList(); if ((transformList && transformList->HasTransform()) || content->GetAnimateMotionTransform()) { diff --git a/layout/svg/nsSVGForeignObjectFrame.cpp b/layout/svg/nsSVGForeignObjectFrame.cpp index ed10b9f9852e..bf247c46880b 100644 --- a/layout/svg/nsSVGForeignObjectFrame.cpp +++ b/layout/svg/nsSVGForeignObjectFrame.cpp @@ -192,7 +192,7 @@ nsSVGForeignObjectFrame::IsSVGTransformed(gfxMatrix *aOwnTransform, } nsSVGElement *content = static_cast(mContent); - SVGAnimatedTransformList* transformList = + nsSVGAnimatedTransformList* transformList = content->GetAnimatedTransformList(); if (transformList && transformList->HasTransform()) { if (aOwnTransform) { diff --git a/layout/svg/nsSVGGradientFrame.cpp b/layout/svg/nsSVGGradientFrame.cpp index 538dfe627633..0177f192d803 100644 --- a/layout/svg/nsSVGGradientFrame.cpp +++ b/layout/svg/nsSVGGradientFrame.cpp @@ -14,7 +14,7 @@ #include "nsContentUtils.h" #include "nsIDOMSVGAnimatedNumber.h" #include "nsSVGEffects.h" -#include "SVGAnimatedTransformList.h" +#include "nsSVGAnimatedTransformList.h" // XXX Tight coupling with content classes ahead! @@ -157,10 +157,10 @@ nsSVGGradientFrame::GetSpreadMethod() return GetEnumValue(dom::SVGGradientElement::SPREADMETHOD); } -const SVGAnimatedTransformList* +const nsSVGAnimatedTransformList* nsSVGGradientFrame::GetGradientTransformList(nsIContent* aDefault) { - SVGAnimatedTransformList *thisTransformList = + nsSVGAnimatedTransformList *thisTransformList = static_cast(mContent)->GetAnimatedTransformList(); if (thisTransformList && thisTransformList->IsExplicitlySet()) @@ -201,7 +201,7 @@ nsSVGGradientFrame::GetGradientTransform(nsIFrame *aSource, gfxMatrix(bbox.Width(), 0, 0, bbox.Height(), bbox.X(), bbox.Y()); } - const SVGAnimatedTransformList* animTransformList = + const nsSVGAnimatedTransformList* animTransformList = GetGradientTransformList(mContent); if (!animTransformList) return bboxMatrix; diff --git a/layout/svg/nsSVGGradientFrame.h b/layout/svg/nsSVGGradientFrame.h index dfb7e7aefcfc..a31d9adcbbac 100644 --- a/layout/svg/nsSVGGradientFrame.h +++ b/layout/svg/nsSVGGradientFrame.h @@ -22,7 +22,7 @@ class nsStyleContext; struct gfxRect; namespace mozilla { -class SVGAnimatedTransformList; +class nsSVGAnimatedTransformList; namespace dom { class SVGLinearGradientElement; @@ -79,7 +79,7 @@ private: void GetStopInformation(int32_t aIndex, float *aOffset, nscolor *aColor, float *aStopOpacity); - const mozilla::SVGAnimatedTransformList* GetGradientTransformList( + const mozilla::nsSVGAnimatedTransformList* GetGradientTransformList( nsIContent* aDefault); // Will be singular for gradientUnits="objectBoundingBox" with an empty bbox. gfxMatrix GetGradientTransform(nsIFrame *aSource, diff --git a/layout/svg/nsSVGPathGeometryFrame.cpp b/layout/svg/nsSVGPathGeometryFrame.cpp index dd02a5b71464..f85718e9128a 100644 --- a/layout/svg/nsSVGPathGeometryFrame.cpp +++ b/layout/svg/nsSVGPathGeometryFrame.cpp @@ -152,7 +152,7 @@ nsSVGPathGeometryFrame::IsSVGTransformed(gfxMatrix *aOwnTransform, } nsSVGElement *content = static_cast(mContent); - SVGAnimatedTransformList* transformList = + nsSVGAnimatedTransformList* transformList = content->GetAnimatedTransformList(); if ((transformList && transformList->HasTransform()) || content->GetAnimateMotionTransform()) { diff --git a/layout/svg/nsSVGPatternFrame.cpp b/layout/svg/nsSVGPatternFrame.cpp index 933dd922cfc5..7ac54f881bad 100644 --- a/layout/svg/nsSVGPatternFrame.cpp +++ b/layout/svg/nsSVGPatternFrame.cpp @@ -20,7 +20,7 @@ #include "nsSVGGeometryFrame.h" #include "mozilla/dom/SVGPatternElement.h" #include "nsSVGUtils.h" -#include "SVGAnimatedTransformList.h" +#include "nsSVGAnimatedTransformList.h" #include "SVGContentUtils.h" using namespace mozilla; @@ -443,10 +443,10 @@ nsSVGPatternFrame::GetEnumValue(uint32_t aIndex, nsIContent *aDefault) mEnumAttributes[aIndex].GetAnimValue(); } -SVGAnimatedTransformList* +nsSVGAnimatedTransformList* nsSVGPatternFrame::GetPatternTransformList(nsIContent* aDefault) { - SVGAnimatedTransformList *thisTransformList = + nsSVGAnimatedTransformList *thisTransformList = static_cast(mContent)->GetAnimatedTransformList(); if (thisTransformList && thisTransformList->IsExplicitlySet()) @@ -462,7 +462,7 @@ nsSVGPatternFrame::GetPatternTransformList(nsIContent* aDefault) gfxMatrix nsSVGPatternFrame::GetPatternTransform() { - SVGAnimatedTransformList* animTransformList = + nsSVGAnimatedTransformList* animTransformList = GetPatternTransformList(mContent); if (!animTransformList) return gfxMatrix(); diff --git a/layout/svg/nsSVGPatternFrame.h b/layout/svg/nsSVGPatternFrame.h index 31255190d8f9..3d35110480cf 100644 --- a/layout/svg/nsSVGPatternFrame.h +++ b/layout/svg/nsSVGPatternFrame.h @@ -18,7 +18,7 @@ class nsSVGViewBox; namespace mozilla { class SVGAnimatedPreserveAspectRatio; -class SVGAnimatedTransformList; +class nsSVGAnimatedTransformList; } // namespace mozilla typedef nsSVGPaintServerFrame nsSVGPatternFrameBase; @@ -90,7 +90,7 @@ protected: { return GetEnumValue(aIndex, mContent); } - mozilla::SVGAnimatedTransformList* GetPatternTransformList( + mozilla::nsSVGAnimatedTransformList* GetPatternTransformList( nsIContent* aDefault); gfxMatrix GetPatternTransform(); const nsSVGViewBox &GetViewBox(nsIContent *aDefault); From 93285490628d8e7ffc897e81fcc62239a9b049ca Mon Sep 17 00:00:00 2001 From: Gijs Kruitbosch Date: Sun, 14 Apr 2013 11:47:31 -0700 Subject: [PATCH 04/29] Bug 125082 - use GetChildren in inDOMUtils and inDeepTreeWalker to get native anonymous content, too. r=roc --- layout/inspector/src/inDOMUtils.cpp | 9 +-------- layout/inspector/src/inDeepTreeWalker.cpp | 20 +++++++------------- 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/layout/inspector/src/inDOMUtils.cpp b/layout/inspector/src/inDOMUtils.cpp index 23eaab48ca85..23414c69e564 100644 --- a/layout/inspector/src/inDOMUtils.cpp +++ b/layout/inspector/src/inDOMUtils.cpp @@ -132,14 +132,7 @@ inDOMUtils::GetChildrenForNode(nsIDOMNode* aNode, if (aShowingAnonymousContent) { nsCOMPtr content = do_QueryInterface(aNode); if (content) { - nsRefPtr bindingManager = - inLayoutUtils::GetBindingManagerFor(aNode); - if (bindingManager) { - bindingManager->GetAnonymousNodesFor(content, getter_AddRefs(kids)); - if (!kids) { - bindingManager->GetContentListFor(content, getter_AddRefs(kids)); - } - } + kids = content->GetChildren(nsIContent::eAllChildren); } } diff --git a/layout/inspector/src/inDeepTreeWalker.cpp b/layout/inspector/src/inDeepTreeWalker.cpp index 3dad890feaab..103056d26fa9 100644 --- a/layout/inspector/src/inDeepTreeWalker.cpp +++ b/layout/inspector/src/inDeepTreeWalker.cpp @@ -337,19 +337,13 @@ inDeepTreeWalker::PushNode(nsIDOMNode* aNode) } if (!kids) { - if (mShowAnonymousContent) { - nsCOMPtr content = do_QueryInterface(aNode); - nsRefPtr bindingManager; - if (content && - (bindingManager = inLayoutUtils::GetBindingManagerFor(aNode))) { - bindingManager->GetAnonymousNodesFor(content, getter_AddRefs(kids)); - if (!kids) - bindingManager->GetContentListFor(content, getter_AddRefs(kids)); - } else { - aNode->GetChildNodes(getter_AddRefs(kids)); - } - } else - aNode->GetChildNodes(getter_AddRefs(kids)); + nsCOMPtr content = do_QueryInterface(aNode); + if (content && mShowAnonymousContent) { + kids = content->GetChildren(nsIContent::eAllChildren); + } + } + if (!kids) { + aNode->GetChildNodes(getter_AddRefs(kids)); } item.kids = kids; From be9cbe79ed0d477f494d24992540f3b92d1766f4 Mon Sep 17 00:00:00 2001 From: Jim Blandy Date: Sun, 14 Apr 2013 17:49:40 -0700 Subject: [PATCH 05/29] Bug 857715: In testing/xpcshell/head.js, use 'uneval' to quote values passed to the child process. r=ted --- testing/xpcshell/head.js | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/testing/xpcshell/head.js b/testing/xpcshell/head.js index 9396444a0111..38fc9ab057da 100644 --- a/testing/xpcshell/head.js +++ b/testing/xpcshell/head.js @@ -977,28 +977,21 @@ function do_load_child_test_harness() if (typeof do_load_child_test_harness.alreadyRun != "undefined") return; do_load_child_test_harness.alreadyRun = 1; - - function addQuotes (str) { - return '"' + str + '"'; - } - var quoted_head_files = _HEAD_FILES.map(addQuotes); - var quoted_tail_files = _TAIL_FILES.map(addQuotes); _XPCSHELL_PROCESS = "parent"; let command = - "const _HEAD_JS_PATH='" + _HEAD_JS_PATH + "'; " - + "const _HTTPD_JS_PATH='" + _HTTPD_JS_PATH + "'; " - + "const _HEAD_FILES=[" + quoted_head_files.join() + "];" - + "const _TAIL_FILES=[" + quoted_tail_files.join() + "];" + "const _HEAD_JS_PATH=" + uneval(_HEAD_JS_PATH) + "; " + + "const _HTTPD_JS_PATH=" + uneval(_HTTPD_JS_PATH) + "; " + + "const _HEAD_FILES=" + uneval(_HEAD_FILES) + "; " + + "const _TAIL_FILES=" + uneval(_TAIL_FILES) + "; " + "const _XPCSHELL_PROCESS='child';"; if (this._TESTING_MODULES_DIR) { - normalized = this._TESTING_MODULES_DIR.replace('\\', '\\\\', 'g'); - command += "const _TESTING_MODULES_DIR='" + normalized + "'; "; + command += " const _TESTING_MODULES_DIR=" + uneval(_TESTING_MODULES_DIR) + ";"; } - command += "load(_HEAD_JS_PATH);"; + command += " load(_HEAD_JS_PATH);"; sendCommand(command); } From 7e452fa8da1e0daa06301bae3c956d6ae3848838 Mon Sep 17 00:00:00 2001 From: Nicholas Cameron Date: Mon, 15 Apr 2013 13:25:14 +1200 Subject: [PATCH 06/29] Bug 861127, refactor ContentClientRemote::CreateBuffer. r=Bas --- gfx/layers/client/ContentClient.cpp | 35 +++++++++++------------------ gfx/layers/client/ContentClient.h | 5 +++++ 2 files changed, 18 insertions(+), 22 deletions(-) diff --git a/gfx/layers/client/ContentClient.cpp b/gfx/layers/client/ContentClient.cpp index 9f689438e2de..a58806971b31 100644 --- a/gfx/layers/client/ContentClient.cpp +++ b/gfx/layers/client/ContentClient.cpp @@ -104,10 +104,10 @@ ContentClientRemote::EndPaint() } } -TemporaryRef -ContentClientRemote::CreateDTBuffer(ContentType aType, - const nsIntRect& aRect, - uint32_t aFlags) +void +ContentClientRemote::BuildTextureClient(ContentType aType, + const nsIntRect& aRect, + uint32_t aFlags) { NS_ABORT_IF_FALSE(!mIsNewBuffer, "Bad! Did we create a buffer twice without painting?"); @@ -127,6 +127,14 @@ ContentClientRemote::CreateDTBuffer(ContentType aType, MOZ_ASSERT(IsSurfaceDescriptorValid(*mTextureClient->GetDescriptor())); CreateFrontBufferAndNotify(aRect); +} + +TemporaryRef +ContentClientRemote::CreateDTBuffer(ContentType aType, + const nsIntRect& aRect, + uint32_t aFlags) +{ + BuildTextureClient(aType, aRect, aFlags); RefPtr ret = mTextureClient->LockDrawTarget(); return ret.forget(); @@ -137,24 +145,7 @@ ContentClientRemote::CreateBuffer(ContentType aType, const nsIntRect& aRect, uint32_t aFlags) { - NS_ABORT_IF_FALSE(!mIsNewBuffer, - "Bad! Did we create a buffer twice without painting?"); - - mIsNewBuffer = true; - - if (mTextureClient) { - mOldTextures.AppendElement(mTextureClient); - DestroyBuffers(); - } - mTextureInfo.mTextureFlags = aFlags | HostRelease; - mTextureClient = CreateTextureClient(TEXTURE_CONTENT); - - mContentType = aType; - mSize = gfx::IntSize(aRect.width, aRect.height); - mTextureClient->EnsureAllocated(mSize, mContentType); - MOZ_ASSERT(IsSurfaceDescriptorValid(*mTextureClient->GetDescriptor())); - - CreateFrontBufferAndNotify(aRect); + BuildTextureClient(aType, aRect, aFlags); nsRefPtr ret = mTextureClient->LockSurface(); return ret.forget(); diff --git a/gfx/layers/client/ContentClient.h b/gfx/layers/client/ContentClient.h index b09542b7e9e2..928a602ddc96 100644 --- a/gfx/layers/client/ContentClient.h +++ b/gfx/layers/client/ContentClient.h @@ -215,6 +215,11 @@ protected: const nsIntRegion& aVisibleRegion, bool aDidSelfCopy); + // create and configure mTextureClient + void BuildTextureClient(ContentType aType, + const nsIntRect& aRect, + uint32_t aFlags); + // Create the front buffer for the ContentClient/Host pair if necessary // and notify the compositor that we have created the buffer(s). virtual void CreateFrontBufferAndNotify(const nsIntRect& aBufferRect) = 0; From 963496b717044a10f9a7bbcfb26ae04f5137d432 Mon Sep 17 00:00:00 2001 From: Valentin Gosu Date: Sun, 14 Apr 2013 21:32:06 -0400 Subject: [PATCH 07/29] Bug 843865 - Implement Networking Dashboard using webidl. r=bz --- dom/webidl/DummyBinding.webidl | 4 + dom/webidl/NetDashboard.webidl | 45 +++++ dom/webidl/WebIDL.mk | 1 + netwerk/base/src/Dashboard.cpp | 344 ++++++++++++++++++--------------- netwerk/base/src/Dashboard.h | 1 - 5 files changed, 235 insertions(+), 160 deletions(-) create mode 100644 dom/webidl/NetDashboard.webidl diff --git a/dom/webidl/DummyBinding.webidl b/dom/webidl/DummyBinding.webidl index 4631cf3d8665..3782e6f8f757 100644 --- a/dom/webidl/DummyBinding.webidl +++ b/dom/webidl/DummyBinding.webidl @@ -15,6 +15,10 @@ interface DummyInterface { USSDReceivedEventDict ussdReceivedEvent(); InspectorRGBTriple rgbTriple(); Function getFunction(); + void funcSocketsDict(optional SocketsDict arg); + void funcHttpConnDict(optional HttpConnDict arg); + void funcWebSocketDict(optional WebSocketDict arg); + void funcDNSCacheDict(optional DNSCacheDict arg); }; interface DummyInterfaceWorkers { diff --git a/dom/webidl/NetDashboard.webidl b/dom/webidl/NetDashboard.webidl new file mode 100644 index 000000000000..f5c59b79ea42 --- /dev/null +++ b/dom/webidl/NetDashboard.webidl @@ -0,0 +1,45 @@ +/* -*- Mode: IDL; 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/. */ + +dictionary SocketsDict { + sequence host; + sequence port; + sequence active; + sequence tcp; + sequence socksent; + sequence sockreceived; + double sent = 0; + double received = 0; +}; + +dictionary HttpConnInfoDict { + sequence rtt; + sequence ttl; +}; + +dictionary HttpConnDict { + sequence host; + sequence port; + sequence active; + sequence idle; + sequence spdy; + sequence ssl; +}; + +dictionary WebSocketDict { + sequence hostport; + sequence msgsent; + sequence msgreceived; + sequence sentsize; + sequence receivedsize; + sequence encrypted; +}; + +dictionary DNSCacheDict { + sequence hostname; + sequence> hostaddr; + sequence family; + sequence expiration; +}; diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index 35a5dae875fc..2223107f176c 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -158,6 +158,7 @@ webidl_files = \ MozActivity.webidl \ MutationEvent.webidl \ MutationObserver.webidl \ + NetDashboard.webidl \ Node.webidl \ NodeFilter.webidl \ NodeIterator.webidl \ diff --git a/netwerk/base/src/Dashboard.cpp b/netwerk/base/src/Dashboard.cpp index fc8c9ec21554..994be332544f 100644 --- a/netwerk/base/src/Dashboard.cpp +++ b/netwerk/base/src/Dashboard.cpp @@ -5,27 +5,14 @@ #include "nsContentUtils.h" #include "mozilla/net/Dashboard.h" #include "mozilla/net/HttpInfo.h" +#include "mozilla/dom/NetDashboardBinding.h" +#include "jsapi.h" namespace mozilla { namespace net { NS_IMPL_THREADSAFE_ISUPPORTS2(Dashboard, nsIDashboard, nsIDashboardEventNotifier) - -#define CREATE_ARRAY_OBJECT(object) \ -JSObject* object = JS_NewArrayObject(cx, 0, nullptr); \ -if (!object) \ - return NS_ERROR_OUT_OF_MEMORY ; \ - -#define SET_ELEMENT(object, func, param, index) \ -if (!JS_DefineElement(cx, object, index, func(param), \ - nullptr, nullptr, JSPROP_ENUMERATE)) \ - return NS_ERROR_OUT_OF_MEMORY; \ - -#define SET_PROPERTY(finalObject, object, property) \ -val = OBJECT_TO_JSVAL(object); \ -if (!JS_DefineProperty(cx, finalObject, #property, \ - val, nullptr, nullptr, JSPROP_ENUMERATE)) \ - return NS_ERROR_OUT_OF_MEMORY; \ +using mozilla::dom::Sequence; Dashboard::Dashboard() { @@ -62,50 +49,53 @@ Dashboard::GetSocketsDispatch() nsresult Dashboard::GetSockets() { - JS::Value val; JSContext* cx = nsContentUtils::GetSafeJSContext(); JSAutoRequest request(cx); - JSObject* finalObject = JS_NewObject(cx, nullptr, nullptr, nullptr); - if (!finalObject) - return NS_ERROR_OUT_OF_MEMORY; + mozilla::dom::SocketsDict dict; + dict.mHost.Construct(); + dict.mPort.Construct(); + dict.mActive.Construct(); + dict.mTcp.Construct(); + dict.mSocksent.Construct(); + dict.mSockreceived.Construct(); + dict.mSent = 0; + dict.mReceived = 0; - CREATE_ARRAY_OBJECT(hostJs); - CREATE_ARRAY_OBJECT(portJs); - CREATE_ARRAY_OBJECT(activeJs); - CREATE_ARRAY_OBJECT(sentJs); - CREATE_ARRAY_OBJECT(receivedJs); - CREATE_ARRAY_OBJECT(tcpJs); - CREATE_ARRAY_OBJECT(sockSentJs); - CREATE_ARRAY_OBJECT(sockRecJs); - mSock.totalSent = 0; - mSock.totalRecv = 0; + Sequence &ports = dict.mPort.Value(); + Sequence &hosts = dict.mHost.Value(); + Sequence &active = dict.mActive.Value(); + Sequence &tcp = dict.mTcp.Value(); + Sequence &sent = dict.mSocksent.Value(); + Sequence &received = dict.mSockreceived.Value(); - for (uint32_t i = 0; i < mSock.data.Length(); i++) { - JSString* hostString = JS_NewStringCopyZ(cx, mSock.data[i].host.get()); - SET_ELEMENT(hostJs, STRING_TO_JSVAL, hostString, i); - SET_ELEMENT(portJs, INT_TO_JSVAL, mSock.data[i].port, i); - SET_ELEMENT(activeJs, BOOLEAN_TO_JSVAL, mSock.data[i].active, i); - SET_ELEMENT(tcpJs, INT_TO_JSVAL, mSock.data[i].tcp, i); - SET_ELEMENT(sockSentJs, DOUBLE_TO_JSVAL, (double) mSock.data[i].sent, i); - SET_ELEMENT(sockRecJs, DOUBLE_TO_JSVAL, (double) mSock.data[i].received, i); - mSock.totalSent += mSock.data[i].sent; - mSock.totalRecv += mSock.data[i].received; + uint32_t length = mSock.data.Length(); + if (!ports.SetCapacity(length) || !hosts.SetCapacity(length) || + !active.SetCapacity(length) || !tcp.SetCapacity(length) || + !sent.SetCapacity(length) || !received.SetCapacity(length)) { + mSock.cb = nullptr; + mSock.data.Clear(); + JS_ReportOutOfMemory(cx); + return NS_ERROR_OUT_OF_MEMORY; } - SET_ELEMENT(sentJs, DOUBLE_TO_JSVAL, (double) mSock.totalSent, 0); - SET_ELEMENT(receivedJs, DOUBLE_TO_JSVAL, (double) mSock.totalRecv, 0); + for (uint32_t i = 0; i < mSock.data.Length(); i++) { + CopyASCIItoUTF16(mSock.data[i].host, *hosts.AppendElement()); + *ports.AppendElement() = mSock.data[i].port; + *active.AppendElement() = mSock.data[i].active; + *tcp.AppendElement() = mSock.data[i].tcp; + *sent.AppendElement() = (double) mSock.data[i].sent; + *received.AppendElement() = (double) mSock.data[i].received; + dict.mSent += mSock.data[i].sent; + dict.mReceived += mSock.data[i].received; + } - SET_PROPERTY(finalObject, hostJs, host); - SET_PROPERTY(finalObject, portJs, port); - SET_PROPERTY(finalObject, activeJs, active); - SET_PROPERTY(finalObject, tcpJs, tcp); - SET_PROPERTY(finalObject, sockSentJs, socksent); - SET_PROPERTY(finalObject, sockRecJs, sockreceived); - SET_PROPERTY(finalObject, sentJs, sent); - SET_PROPERTY(finalObject, receivedJs, received); - - val = OBJECT_TO_JSVAL(finalObject); + JS::Value val; + if (!dict.ToObject(cx, nullptr, &val)) { + mSock.cb = nullptr; + mSock.data.Clear(); + return NS_ERROR_FAILURE; + } mSock.cb->OnDashboardDataAvailable(val); mSock.cb = nullptr; @@ -138,60 +128,81 @@ Dashboard::GetHttpDispatch() nsresult Dashboard::GetHttpConnections() { - JS::Value val; JSContext* cx = nsContentUtils::GetSafeJSContext(); JSAutoRequest request(cx); - JSObject* finalObject = JS_NewObject(cx, nullptr, nullptr, nullptr); - if (!finalObject) - return NS_ERROR_OUT_OF_MEMORY; + mozilla::dom::HttpConnDict dict; + dict.mActive.Construct(); + dict.mHost.Construct(); + dict.mIdle.Construct(); + dict.mPort.Construct(); + dict.mSpdy.Construct(); + dict.mSsl.Construct(); - CREATE_ARRAY_OBJECT(hostJs); - CREATE_ARRAY_OBJECT(portJs); - CREATE_ARRAY_OBJECT(activeJs); - CREATE_ARRAY_OBJECT(idleJs); - CREATE_ARRAY_OBJECT(spdyJs); - CREATE_ARRAY_OBJECT(sslJs); + using mozilla::dom::HttpConnInfoDict; + Sequence &active = dict.mActive.Value(); + Sequence &hosts = dict.mHost.Value(); + Sequence &idle = dict.mIdle.Value(); + Sequence &ports = dict.mPort.Value(); + Sequence &spdy = dict.mSpdy.Value(); + Sequence &ssl = dict.mSsl.Value(); - for (uint32_t i = 0; i < mHttp.data.Length(); i++) { - JSString* hostString = JS_NewStringCopyZ(cx, mHttp.data[i].host.get()); - SET_ELEMENT(hostJs, STRING_TO_JSVAL, hostString, i); - SET_ELEMENT(portJs, INT_TO_JSVAL, mHttp.data[i].port, i); - - JSObject* rtt_Active = JS_NewArrayObject(cx, 0, nullptr); - JSObject* timeToLive_Active = JS_NewArrayObject(cx, 0, nullptr); - for (uint32_t j = 0; j < mHttp.data[i].active.Length(); j++) { - SET_ELEMENT(rtt_Active, INT_TO_JSVAL, mHttp.data[i].active[j].rtt, j); - SET_ELEMENT(timeToLive_Active, INT_TO_JSVAL, mHttp.data[i].active[j].ttl, j); - } - JSObject* active = JS_NewObject(cx, nullptr, nullptr, nullptr); - SET_PROPERTY(active, rtt_Active, rtt); - SET_PROPERTY(active, timeToLive_Active, ttl); - SET_ELEMENT(activeJs, OBJECT_TO_JSVAL, active, i); - - JSObject* rtt_Idle = JS_NewArrayObject(cx, 0, nullptr); - JSObject* timeToLive_Idle = JS_NewArrayObject(cx, 0, nullptr); - for (uint32_t j = 0; j < mHttp.data[i].idle.Length(); j++) { - SET_ELEMENT(rtt_Idle, INT_TO_JSVAL, mHttp.data[i].idle[j].rtt, j); - SET_ELEMENT(timeToLive_Idle, INT_TO_JSVAL, mHttp.data[i].idle[j].ttl, j); - } - JSObject* idle = JS_NewObject(cx, nullptr, nullptr, nullptr); - SET_PROPERTY(idle, rtt_Idle, rtt); - SET_PROPERTY(idle, timeToLive_Idle, ttl); - SET_ELEMENT(idleJs, OBJECT_TO_JSVAL, idle, i); - - SET_ELEMENT(spdyJs, BOOLEAN_TO_JSVAL, mHttp.data[i].spdy, i); - SET_ELEMENT(sslJs, BOOLEAN_TO_JSVAL, mHttp.data[i].ssl, i); + uint32_t length = mHttp.data.Length(); + if (!active.SetCapacity(length) || !hosts.SetCapacity(length) || + !idle.SetCapacity(length) || !ports.SetCapacity(length) || + !spdy.SetCapacity(length) || !ssl.SetCapacity(length)) { + mHttp.cb = nullptr; + mHttp.data.Clear(); + JS_ReportOutOfMemory(cx); + return NS_ERROR_OUT_OF_MEMORY; } - SET_PROPERTY(finalObject, hostJs, host); - SET_PROPERTY(finalObject, portJs, port); - SET_PROPERTY(finalObject, activeJs, active); - SET_PROPERTY(finalObject, idleJs, idle); - SET_PROPERTY(finalObject, spdyJs, spdy); - SET_PROPERTY(finalObject, sslJs, ssl); + for (uint32_t i = 0; i < mHttp.data.Length(); i++) { + CopyASCIItoUTF16(mHttp.data[i].host,*hosts.AppendElement()); + *ports.AppendElement() = mHttp.data[i].port; + *spdy.AppendElement() = mHttp.data[i].spdy; + *ssl.AppendElement() = mHttp.data[i].ssl; + HttpConnInfoDict &activeInfo = *active.AppendElement(); + activeInfo.mRtt.Construct(); + activeInfo.mTtl.Construct(); + Sequence &active_rtt = activeInfo.mRtt.Value(); + Sequence &active_ttl = activeInfo.mTtl.Value(); + if (!active_rtt.SetCapacity(mHttp.data[i].active.Length()) || + !active_ttl.SetCapacity(mHttp.data[i].active.Length())) { + mHttp.cb = nullptr; + mHttp.data.Clear(); + JS_ReportOutOfMemory(cx); + return NS_ERROR_OUT_OF_MEMORY; + } + for (uint32_t j = 0; j < mHttp.data[i].active.Length(); j++) { + *active_rtt.AppendElement() = mHttp.data[i].active[j].rtt; + *active_ttl.AppendElement() = mHttp.data[i].active[j].ttl; + } - val = OBJECT_TO_JSVAL(finalObject); + HttpConnInfoDict &idleInfo = *idle.AppendElement(); + idleInfo.mRtt.Construct(); + idleInfo.mTtl.Construct(); + Sequence &idle_rtt = idleInfo.mRtt.Value(); + Sequence &idle_ttl = idleInfo.mTtl.Value(); + if (!idle_rtt.SetCapacity(mHttp.data[i].idle.Length()) || + !idle_ttl.SetCapacity(mHttp.data[i].idle.Length())) { + mHttp.cb = nullptr; + mHttp.data.Clear(); + JS_ReportOutOfMemory(cx); + return NS_ERROR_OUT_OF_MEMORY; + } + for (uint32_t j = 0; j < mHttp.data[i].idle.Length(); j++) { + *idle_rtt.AppendElement() = mHttp.data[i].idle[j].rtt; + *idle_ttl.AppendElement() = mHttp.data[i].idle[j].ttl; + } + } + + JS::Value val; + if (!dict.ToObject(cx, nullptr, &val)) { + mHttp.cb = nullptr; + mHttp.data.Clear(); + return NS_ERROR_FAILURE; + } mHttp.cb->OnDashboardDataAvailable(val); mHttp.cb = nullptr; @@ -288,41 +299,50 @@ Dashboard::RequestWebsocketConnections(NetDashboardCallback* cb) nsresult Dashboard::GetWebSocketConnections() { - JS::Value val; - JSString* jsstring; JSContext* cx = nsContentUtils::GetSafeJSContext(); JSAutoRequest request(cx); - JSObject* finalObject = JS_NewObject(cx, nullptr, nullptr, nullptr); - if (!finalObject) - return NS_ERROR_OUT_OF_MEMORY; + mozilla::dom::WebSocketDict dict; + dict.mEncrypted.Construct(); + dict.mHostport.Construct(); + dict.mMsgreceived.Construct(); + dict.mMsgsent.Construct(); + dict.mReceivedsize.Construct(); + dict.mSentsize.Construct(); - CREATE_ARRAY_OBJECT(hostJs); - CREATE_ARRAY_OBJECT(msgSentJs); - CREATE_ARRAY_OBJECT(msgRecvJs); - CREATE_ARRAY_OBJECT(sizeSentJs); - CREATE_ARRAY_OBJECT(sizeRecvJs); - CREATE_ARRAY_OBJECT(encryptJs); + Sequence &encrypted = dict.mEncrypted.Value(); + Sequence &hostport = dict.mHostport.Value(); + Sequence &received = dict.mMsgreceived.Value(); + Sequence &sent = dict.mMsgsent.Value(); + Sequence &receivedSize = dict.mReceivedsize.Value(); + Sequence &sentSize = dict.mSentsize.Value(); + + uint32_t length = mWs.data.Length(); + if (!encrypted.SetCapacity(length) || !hostport.SetCapacity(length) || + !received.SetCapacity(length) || !sent.SetCapacity(length) || + !receivedSize.SetCapacity(length) || !sentSize.SetCapacity(length)) { + mWs.cb = nullptr; + mWs.data.Clear(); + JS_ReportOutOfMemory(cx); + return NS_ERROR_OUT_OF_MEMORY; + } mozilla::MutexAutoLock lock(mWs.lock); for (uint32_t i = 0; i < mWs.data.Length(); i++) { - jsstring = JS_NewStringCopyN(cx, mWs.data[i].mHost.get(), mWs.data[i].mHost.Length()); - SET_ELEMENT(hostJs, STRING_TO_JSVAL, jsstring, i); - SET_ELEMENT(msgSentJs, INT_TO_JSVAL, mWs.data[i].mMsgSent, i); - SET_ELEMENT(msgRecvJs, INT_TO_JSVAL, mWs.data[i].mMsgReceived, i); - SET_ELEMENT(sizeSentJs, DOUBLE_TO_JSVAL, (double) mWs.data[i].mSizeSent, i); - SET_ELEMENT(sizeRecvJs, DOUBLE_TO_JSVAL, (double) mWs.data[i].mSizeReceived, i); - SET_ELEMENT(encryptJs, BOOLEAN_TO_JSVAL, mWs.data[i].mEncrypted, i); + CopyASCIItoUTF16(mWs.data[i].mHost, *hostport.AppendElement()); + *sent.AppendElement() = mWs.data[i].mMsgSent; + *received.AppendElement() = mWs.data[i].mMsgReceived; + *receivedSize.AppendElement() = mWs.data[i].mSizeSent; + *sentSize.AppendElement() = mWs.data[i].mSizeReceived; + *encrypted.AppendElement() = mWs.data[i].mEncrypted; } - SET_PROPERTY(finalObject, hostJs, hostport); - SET_PROPERTY(finalObject, msgSentJs, msgsent); - SET_PROPERTY(finalObject, msgRecvJs, msgreceived); - SET_PROPERTY(finalObject, sizeSentJs, sentsize); - SET_PROPERTY(finalObject, sizeRecvJs, receivedsize); - SET_PROPERTY(finalObject, encryptJs, encrypted); - - val = OBJECT_TO_JSVAL(finalObject); + JS::Value val; + if (!dict.ToObject(cx, nullptr, &val)) { + mWs.cb = nullptr; + mWs.data.Clear(); + return NS_ERROR_FAILURE; + } mWs.cb->OnDashboardDataAvailable(val); mWs.cb = nullptr; @@ -362,50 +382,56 @@ Dashboard::GetDnsInfoDispatch() nsresult Dashboard::GetDNSCacheEntries() { - JS::Value val; JSContext* cx = nsContentUtils::GetSafeJSContext(); JSAutoRequest request(cx); - JSObject* finalObject = JS_NewObject(cx, nullptr, nullptr, nullptr); - if (!finalObject) - return NS_ERROR_OUT_OF_MEMORY; + mozilla::dom::DNSCacheDict dict; + dict.mExpiration.Construct(); + dict.mFamily.Construct(); + dict.mHostaddr.Construct(); + dict.mHostname.Construct(); - CREATE_ARRAY_OBJECT(nameJs); - CREATE_ARRAY_OBJECT(addrJs); - CREATE_ARRAY_OBJECT(familyJs); - CREATE_ARRAY_OBJECT(expiresJs); + Sequence &expiration = dict.mExpiration.Value(); + Sequence &family = dict.mFamily.Value(); + Sequence> &hostaddr = dict.mHostaddr.Value(); + Sequence &hostname = dict.mHostname.Value(); - for (uint32_t i = 0; i < mDns.data.Length(); i++) { - JSString* hostnameString = JS_NewStringCopyZ(cx, mDns.data[i].hostname.get()); - SET_ELEMENT(nameJs, STRING_TO_JSVAL, hostnameString, i); - - JSObject* addrObject = JS_NewObject(cx, nullptr, nullptr, nullptr); - if (!addrObject) + uint32_t length = mDns.data.Length(); + if (!expiration.SetCapacity(length) || !family.SetCapacity(length) || + !hostaddr.SetCapacity(length) || !hostname.SetCapacity(length)) { + mDns.cb = nullptr; + mDns.data.Clear(); + JS_ReportOutOfMemory(cx); return NS_ERROR_OUT_OF_MEMORY; - - for (uint32_t j = 0; j < mDns.data[i].hostaddr.Length(); j++) { - JSString* addrString = JS_NewStringCopyZ(cx, mDns.data[i].hostaddr[j].get()); - SET_ELEMENT(addrObject, STRING_TO_JSVAL, addrString, j); - } - - SET_ELEMENT(addrJs, OBJECT_TO_JSVAL, addrObject, i); - - JSString* familyString; - if (mDns.data[i].family == PR_AF_INET6) - familyString = JS_NewStringCopyZ(cx, "ipv6"); - else - familyString = JS_NewStringCopyZ(cx, "ipv4"); - - SET_ELEMENT(familyJs, STRING_TO_JSVAL, familyString, i); - SET_ELEMENT(expiresJs, DOUBLE_TO_JSVAL, (double) mDns.data[i].expiration, i); } - SET_PROPERTY(finalObject, nameJs, hostname); - SET_PROPERTY(finalObject, addrJs, hostaddr); - SET_PROPERTY(finalObject, familyJs, family); - SET_PROPERTY(finalObject, expiresJs, expiration); + for (uint32_t i = 0; i < mDns.data.Length(); i++) { + CopyASCIItoUTF16(mDns.data[i].hostname, *hostname.AppendElement()); + *expiration.AppendElement() = mDns.data[i].expiration; - val = OBJECT_TO_JSVAL(finalObject); + Sequence &addrs = *hostaddr.AppendElement(); + if (!addrs.SetCapacity(mDns.data[i].hostaddr.Length())) { + mDns.cb = nullptr; + mDns.data.Clear(); + JS_ReportOutOfMemory(cx); + return NS_ERROR_OUT_OF_MEMORY; + } + for (uint32_t j = 0; j < mDns.data[i].hostaddr.Length(); j++) { + CopyASCIItoUTF16(mDns.data[i].hostaddr[j], *addrs.AppendElement()); + } + + if (mDns.data[i].family == PR_AF_INET6) + CopyASCIItoUTF16("ipv6", *family.AppendElement()); + else + CopyASCIItoUTF16("ipv4", *family.AppendElement()); + } + + JS::Value val; + if (!dict.ToObject(cx, nullptr, &val)) { + mDns.cb = nullptr; + mDns.data.Clear(); + return NS_ERROR_FAILURE; + } mDns.cb->OnDashboardDataAvailable(val); mDns.cb = nullptr; diff --git a/netwerk/base/src/Dashboard.h b/netwerk/base/src/Dashboard.h index d02b63419aaa..3cad4c55750b 100644 --- a/netwerk/base/src/Dashboard.h +++ b/netwerk/base/src/Dashboard.h @@ -9,7 +9,6 @@ #include "nsIDashboardEventNotifier.h" #include "nsTArray.h" #include "nsString.h" -#include "jsapi.h" #include "nsIDNSService.h" #include "nsIServiceManager.h" #include "nsIThread.h" From 6bb683dd1600a06ffb798618df64dc8ad1d5f855 Mon Sep 17 00:00:00 2001 From: Raymond Lee Date: Wed, 10 Apr 2013 17:10:33 +0800 Subject: [PATCH 08/29] Bug 852032 - Create a PlacesBackups.jsm. r=mak --- toolkit/components/places/Makefile.in | 1 + toolkit/components/places/PlacesBackups.jsm | 222 ++++++++++++++++++++ 2 files changed, 223 insertions(+) create mode 100644 toolkit/components/places/PlacesBackups.jsm diff --git a/toolkit/components/places/Makefile.in b/toolkit/components/places/Makefile.in index 722d8db521d5..6d6769597080 100644 --- a/toolkit/components/places/Makefile.in +++ b/toolkit/components/places/Makefile.in @@ -63,6 +63,7 @@ EXTRA_JS_MODULES = \ ColorConversion.js \ ClusterLib.js \ BookmarkJSONUtils.jsm \ + PlacesBackups.jsm \ $(NULL) EXTRA_PP_JS_MODULES = \ diff --git a/toolkit/components/places/PlacesBackups.jsm b/toolkit/components/places/PlacesBackups.jsm new file mode 100644 index 000000000000..fef047df3140 --- /dev/null +++ b/toolkit/components/places/PlacesBackups.jsm @@ -0,0 +1,222 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * vim: sw=2 ts=2 sts=2 expandtab filetype=javascript + * 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/. */ + +this.EXPORTED_SYMBOLS = ["PlacesBackups"]; + +const Ci = Components.interfaces; +const Cu = Components.utils; + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/PlacesUtils.jsm"); +Cu.import("resource://gre/modules/BookmarkJSONUtils.jsm"); +Cu.import("resource://gre/modules/Task.jsm"); + +this.PlacesBackups = { + get _filenamesRegex() { + // Get the localized backup filename, will be used to clear out + // old backups with a localized name (bug 445704). + let localizedFilename = + PlacesUtils.getFormattedString("bookmarksArchiveFilename", [new Date()]); + let localizedFilenamePrefix = + localizedFilename.substr(0, localizedFilename.indexOf("-")); + delete this._filenamesRegex; + return this._filenamesRegex = + new RegExp("^(bookmarks|" + localizedFilenamePrefix + ")-([0-9-]+)\.(json|html)"); + }, + + get folder() { + let bookmarksBackupDir = Services.dirsvc.get("ProfD", Ci.nsILocalFile); + bookmarksBackupDir.append("bookmarkbackups"); + if (!bookmarksBackupDir.exists()) { + bookmarksBackupDir.create(Ci.nsIFile.DIRECTORY_TYPE, parseInt("0700", 8)); + if (!bookmarksBackupDir.exists()) + throw("Unable to create bookmarks backup folder"); + } + delete this.folder; + return this.folder = bookmarksBackupDir; + }, + + /** + * Cache current backups in a sorted (by date DESC) array. + */ + get entries() { + delete this.entries; + this.entries = []; + let files = this.folder.directoryEntries; + while (files.hasMoreElements()) { + let entry = files.getNext().QueryInterface(Ci.nsIFile); + // A valid backup is any file that matches either the localized or + // not-localized filename (bug 445704). + let matches = entry.leafName.match(this._filenamesRegex); + if (!entry.isHidden() && matches) { + // Remove bogus backups in future dates. + if (this.getDateForFile(entry) > new Date()) { + entry.remove(false); + continue; + } + this.entries.push(entry); + } + } + this.entries.sort((a, b) => { + let aDate = this.getDateForFile(a); + let bDate = this.getDateForFile(b); + return aDate < bDate ? 1 : aDate > bDate ? -1 : 0; + }); + return this.entries; + }, + + /** + * Creates a filename for bookmarks backup files. + * + * @param [optional] aDateObj + * Date object used to build the filename. + * Will use current date if empty. + * @return A bookmarks backup filename. + */ + getFilenameForDate: function PB_getFilenameForDate(aDateObj) { + let dateObj = aDateObj || new Date(); + // Use YYYY-MM-DD (ISO 8601) as it doesn't contain illegal characters + // and makes the alphabetical order of multiple backup files more useful. + return "bookmarks-" + dateObj.toLocaleFormat("%Y-%m-%d") + ".json"; + }, + + /** + * Creates a Date object from a backup file. The date is the backup + * creation date. + * + * @param aBackupFile + * nsIFile of the backup. + * @return A Date object for the backup's creation time. + */ + getDateForFile: function PB_getDateForFile(aBackupFile) { + let filename = aBackupFile.leafName; + let matches = filename.match(this._filenamesRegex); + if (!matches) + throw("Invalid backup file name: " + filename); + return new Date(matches[2].replace(/-/g, "/")); + }, + + /** + * Get the most recent backup file. + * + * @param [optional] aFileExt + * Force file extension. Either "html" or "json". + * Will check for both if not defined. + * @returns nsIFile backup file + */ + getMostRecent: function PB_getMostRecent(aFileExt) { + let fileExt = aFileExt || "(json|html)"; + for (let i = 0; i < this.entries.length; i++) { + let rx = new RegExp("\." + fileExt + "$"); + if (this.entries[i].leafName.match(rx)) + return this.entries[i]; + } + return null; + }, + + /** + * Serializes bookmarks using JSON, and writes to the supplied file. + * Note: any item that should not be backed up must be annotated with + * "places/excludeFromBackup". + * + * @param aFile + * nsIFile where to save JSON backup. + * @return {Promise} + */ + saveBookmarksToJSONFile: function PB_saveBookmarksToJSONFile(aFile) { + return Task.spawn(function() { + if (!aFile.exists()) + aFile.create(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt("0600", 8)); + if (!aFile.exists() || !aFile.isWritable()) { + throw new Error("Unable to create bookmarks backup file: " + aFile.leafName); + } + + yield BookmarkJSONUtils.exportToFile(aFile); + + if (aFile.parent.equals(this.folder)) { + // Update internal cache. + this.entries.push(aFile); + } else { + // If we are saving to a folder different than our backups folder, then + // we also want to copy this new backup to it. + // This way we ensure the latest valid backup is the same saved by the + // user. See bug 424389. + let latestBackup = this.getMostRecent("json"); + if (!latestBackup || latestBackup != aFile) { + let name = this.getFilenameForDate(); + let file = this.folder.clone(); + file.append(name); + if (file.exists()) { + file.remove(false); + } else { + // Update internal cache if we are not replacing an existing + // backup file. + this.entries.push(file); + } + aFile.copyTo(this.folder, name); + } + } + }.bind(this)); + }, + + /** + * Creates a dated backup in /bookmarkbackups. + * Stores the bookmarks using JSON. + * Note: any item that should not be backed up must be annotated with + * "places/excludeFromBackup". + * + * @param [optional] int aMaxBackups + * The maximum number of backups to keep. + * @param [optional] bool aForceBackup + * Forces creating a backup even if one was already + * created that day (overwrites). + * @return {Promise} + */ + create: function PB_create(aMaxBackups, aForceBackup) { + return Task.spawn(function() { + // Construct the new leafname. + let newBackupFilename = this.getFilenameForDate(); + let mostRecentBackupFile = this.getMostRecent(); + + if (!aForceBackup) { + let numberOfBackupsToDelete = 0; + if (aMaxBackups !== undefined && aMaxBackups > -1) + numberOfBackupsToDelete = this.entries.length - aMaxBackups; + + if (numberOfBackupsToDelete > 0) { + // If we don't have today's backup, remove one more so that + // the total backups after this operation does not exceed the + // number specified in the pref. + if (!mostRecentBackupFile || + mostRecentBackupFile.leafName != newBackupFilename) + numberOfBackupsToDelete++; + + while (numberOfBackupsToDelete--) { + let oldestBackup = this.entries.pop(); + oldestBackup.remove(false); + } + } + + // Do nothing if we already have this backup or we don't want backups. + if (aMaxBackups === 0 || + (mostRecentBackupFile && + mostRecentBackupFile.leafName == newBackupFilename)) + return; + } + + let newBackupFile = this.folder.clone(); + newBackupFile.append(newBackupFilename); + + if (aForceBackup && newBackupFile.exists()) + newBackupFile.remove(false); + + if (newBackupFile.exists()) + return; + + yield this.saveBookmarksToJSONFile(newBackupFile); + }.bind(this)); + } +} From ab5e0c6548ef75e8bd73cb918685a83e2bd8053d Mon Sep 17 00:00:00 2001 From: Ralph Giles Date: Wed, 10 Apr 2013 16:37:00 -0700 Subject: [PATCH 09/29] Bug 860338 - Remove MOZ_WEBVTT. r=khuey, r=ted The webvtt dom implementation and parser are a small amount of code. Given the tendency of build-time switches to bitrot, it's not worth keeping this one. --- configure.in | 6 ------ layout/media/Makefile.in | 2 -- toolkit/toolkit.mozbuild | 3 +-- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/configure.in b/configure.in index ce53b7153f1e..da9746f4e9d9 100644 --- a/configure.in +++ b/configure.in @@ -4219,7 +4219,6 @@ MOZ_OMX_PLUGIN= MOZ_VP8= MOZ_VP8_ERROR_CONCEALMENT= MOZ_VP8_ENCODER= -MOZ_WEBVTT=1 MOZ_WEBSPEECH=1 VPX_AS= VPX_ASFLAGS= @@ -5701,10 +5700,6 @@ if test -n "$MOZ_OPUS"; then AC_DEFINE(MOZ_OPUS) fi -if test -n "$MOZ_WEBVTT"; then - AC_DEFINE(MOZ_WEBVTT) -fi - dnl ======================================================== dnl = Check alsa availability on Linux if using sydneyaudio dnl ======================================================== @@ -8909,7 +8904,6 @@ AC_SUBST(MOZ_VORBIS) AC_SUBST(MOZ_TREMOR) AC_SUBST(MOZ_OPUS) AC_SUBST(MOZ_WEBM) -AC_SUBST(MOZ_WEBVTT) AC_SUBST(MOZ_DASH) AC_SUBST(MOZ_WMF) AC_SUBST(MOZ_MEDIA_PLUGINS) diff --git a/layout/media/Makefile.in b/layout/media/Makefile.in index 54f1c1728720..606803736124 100644 --- a/layout/media/Makefile.in +++ b/layout/media/Makefile.in @@ -114,11 +114,9 @@ ifdef MOZ_ENABLE_SKIA SHARED_LIBRARY_LIBS += $(MOZ_SKIA_LIBS) endif -ifdef MOZ_WEBVTT SHARED_LIBRARY_LIBS += \ $(DEPTH)/media/webvtt/$(LIB_PREFIX)webvtt.$(LIB_SUFFIX) \ $(NULL) -endif ifdef MOZ_WEBRTC ifndef MOZ_WEBRTC_IN_LIBXUL diff --git a/toolkit/toolkit.mozbuild b/toolkit/toolkit.mozbuild index dcfc41651dad..a8a55dd8c539 100644 --- a/toolkit/toolkit.mozbuild +++ b/toolkit/toolkit.mozbuild @@ -76,8 +76,7 @@ if CONFIG['MOZ_OPUS']: if CONFIG['MOZ_WEBM']: add_tier_dir('platform', 'media/libnestegg') -if CONFIG['MOZ_WEBVTT']: - add_tier_dir('platform', 'media/webvtt') +add_tier_dir('platform', 'media/webvtt') if CONFIG['MOZ_VP8'] and not CONFIG['MOZ_NATIVE_LIBVPX']: add_tier_dir('platform', 'media/libvpx') From 01ffb34bc6e477a0fbf616c2aaf495c88f08ec55 Mon Sep 17 00:00:00 2001 From: Yura Zenevich Date: Sun, 14 Apr 2013 21:32:07 -0400 Subject: [PATCH 10/29] Bug 861264 - Add support for options argument for OS.File.read method. r=Yoric --- toolkit/components/osfile/osfile_async_front.jsm | 5 +++-- .../components/osfile/tests/mochi/main_test_osfile_async.js | 6 +++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/toolkit/components/osfile/osfile_async_front.jsm b/toolkit/components/osfile/osfile_async_front.jsm index a2ce27725216..3b559d8e90a1 100644 --- a/toolkit/components/osfile/osfile_async_front.jsm +++ b/toolkit/components/osfile/osfile_async_front.jsm @@ -549,13 +549,14 @@ File.makeDir = function makeDir(path, options) { * @param {string} path The path to the file. * @param {number=} bytes Optionally, an upper bound to the number of bytes * to read. + * @param {JSON} options Additional options. * * @resolves {Uint8Array} A buffer holding the bytes * read from the file. */ -File.read = function read(path, bytes) { +File.read = function read(path, bytes, options) { let promise = Scheduler.post("read", - [Type.path.toMsg(path), bytes], path); + [Type.path.toMsg(path), bytes, options], path); return promise.then( function onSuccess(data) { return new Uint8Array(data.buffer, data.byteOffset, data.byteLength); diff --git a/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js b/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js index 28104f827793..bac0e64355fd 100644 --- a/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js +++ b/toolkit/components/osfile/tests/mochi/main_test_osfile_async.js @@ -889,7 +889,11 @@ let test_duration = maketest("duration", function duration(test) { let pathDest = OS.Path.join(OS.Constants.Path.tmpDir, "osfile async test read writeAtomic.tmp"); let tmpPath = pathDest + ".tmp"; - let contents = yield OS.File.read(pathSource); + let readOptions = { + outExecutionDuration: null + }; + let contents = yield OS.File.read(pathSource, undefined, readOptions); + testOptions(readOptions); // Options structure passed to a OS.File writeAtomic method. let writeAtomicOptions = { // This field should be first initialized with the actual From a45b84df9b85efe931dd3655613aca73ad62b6c2 Mon Sep 17 00:00:00 2001 From: Colby Russell Date: Sun, 14 Apr 2013 21:32:07 -0400 Subject: [PATCH 11/29] Bug 861557 - nsIClassInfo.idl references non-existent nsIClassInfo.h. r=jlebar --- xpcom/components/nsIClassInfo.idl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xpcom/components/nsIClassInfo.idl b/xpcom/components/nsIClassInfo.idl index 5cd45c275980..bab59adde77f 100644 --- a/xpcom/components/nsIClassInfo.idl +++ b/xpcom/components/nsIClassInfo.idl @@ -20,8 +20,8 @@ /** * Provides information about a specific implementation class. If you want - * your class to implement nsIClassInfo, see nsIClassInfo.h for instructions -- - * you most likely do not want to inherit from nsIClassInfo. + * your class to implement nsIClassInfo, see nsIClassInfoImpl.h for + * instructions--you most likely do not want to inherit from nsIClassInfo. */ [scriptable, uuid(986c11d0-f340-11d4-9075-0010a4e73d9a)] From 5461190dc4c7a25efe55f62b2552023cff5684a7 Mon Sep 17 00:00:00 2001 From: Vincent Chang Date: Tue, 26 Mar 2013 14:55:56 +0800 Subject: [PATCH 12/29] Bug 854302 - [Buri][WIFI]Cann't disconnect WIFI when connect AP use WPS. r=mrbkap --- dom/wifi/WifiWorker.js | 44 ++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/dom/wifi/WifiWorker.js b/dom/wifi/WifiWorker.js index 641e06d6d83c..9a5e2e7690b0 100644 --- a/dom/wifi/WifiWorker.js +++ b/dom/wifi/WifiWorker.js @@ -2731,31 +2731,37 @@ WifiWorker.prototype = { return; } - let ssid = network.ssid; - let networkKey = getNetworkKey(network); - - if (!(networkKey in this.configuredNetworks)) { - this._sendMessage(message, false, "Trying to forget an unknown network", msg); - return; - } - - let self = this; - let configured = this.configuredNetworks[networkKey]; - this._reconnectOnDisconnect = (this.currentNetwork && - (this.currentNetwork.ssid === ssid)); - WifiManager.removeNetwork(configured.netId, function(ok) { + this._reloadConfiguredNetworks((function(ok) { + // Give it a chance to remove the network even if reload is failed. if (!ok) { - self._sendMessage(message, false, "Unable to remove the network", msg); - self._reconnectOnDisconnect = false; + debug("Warning !!! Failed to reload the configured networks"); + } + + let ssid = network.ssid; + let networkKey = getNetworkKey(network); + if (!(networkKey in this.configuredNetworks)) { + this._sendMessage(message, false, "Trying to forget an unknown network", msg); return; } - WifiManager.saveConfig(function() { - self._reloadConfiguredNetworks(function() { - self._sendMessage(message, true, true, msg); + let self = this; + let configured = this.configuredNetworks[networkKey]; + this._reconnectOnDisconnect = (this.currentNetwork && + (this.currentNetwork.ssid === ssid)); + WifiManager.removeNetwork(configured.netId, function(ok) { + if (!ok) { + self._sendMessage(message, false, "Unable to remove the network", msg); + self._reconnectOnDisconnect = false; + return; + } + + WifiManager.saveConfig(function() { + self._reloadConfiguredNetworks(function() { + self._sendMessage(message, true, true, msg); + }); }); }); - }); + }).bind(this)); }, wps: function(msg) { From 21fef81a586d6d84f8c6f444d3d319d8d5e6f87e Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Sun, 14 Apr 2013 21:52:55 -0400 Subject: [PATCH 13/29] Bug 853298 - Part 1: Switch the ownership model of audio nodes to be based the cycle collector with wrapper caches; r=roc Here is what this patch does: * Got rid of the JSBindingFinalized stuff * Made all nodes wrappercached * Started to hold a self reference while the AudioBufferSourceNode is playing back * Converted the input references to weak references * Got rid of all of the SetProduceOwnOutput and UpdateOutputEnded logic The nodes are now collected by the cycle collector which calls into DisconnectFromGraph which drops the references to other nodes and destroys the media stream. Note that most of the cycles that are now inherent in the ownership model are between nodes and their AudioParams (that is, the cycles not created by content.) --- content/media/AudioNodeStream.cpp | 12 +++ content/media/AudioNodeStream.h | 1 + .../media/webaudio/AudioBufferSourceNode.cpp | 12 ++- .../media/webaudio/AudioBufferSourceNode.h | 17 +--- content/media/webaudio/AudioContext.cpp | 10 ++- .../media/webaudio/AudioDestinationNode.cpp | 16 +--- content/media/webaudio/AudioDestinationNode.h | 15 +--- content/media/webaudio/AudioNode.cpp | 76 ++++-------------- content/media/webaudio/AudioNode.h | 79 +++++++++---------- content/media/webaudio/DelayNode.cpp | 71 +++++++++++++++-- content/media/webaudio/DelayNode.h | 2 + content/media/webaudio/PannerNode.cpp | 4 +- dom/bindings/Bindings.conf | 10 --- 13 files changed, 162 insertions(+), 163 deletions(-) diff --git a/content/media/AudioNodeStream.cpp b/content/media/AudioNodeStream.cpp index e0ec04afad68..eae26d5ae3a1 100644 --- a/content/media/AudioNodeStream.cpp +++ b/content/media/AudioNodeStream.cpp @@ -177,6 +177,18 @@ AudioNodeStream::EnsureTrack() return track; } +bool +AudioNodeStream::AllInputsFinished() const +{ + uint32_t inputCount = mInputs.Length(); + for (uint32_t i = 0; i < inputCount; ++i) { + if (!mInputs[i]->GetSource()->IsFinishedOnGraphThread()) { + return false; + } + } + return !!inputCount; +} + AudioChunk* AudioNodeStream::ObtainInputBlock(AudioChunk* aTmpChunk) { diff --git a/content/media/AudioNodeStream.h b/content/media/AudioNodeStream.h index 99ff3a8965ef..5441a68d7571 100644 --- a/content/media/AudioNodeStream.h +++ b/content/media/AudioNodeStream.h @@ -74,6 +74,7 @@ public: double aStreamTime); virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo); TrackTicks GetCurrentPosition(); + bool AllInputsFinished() const; // Any thread AudioNodeEngine* Engine() { return mEngine; } diff --git a/content/media/webaudio/AudioBufferSourceNode.cpp b/content/media/webaudio/AudioBufferSourceNode.cpp index 1d8aa78a6920..61512aaf3bcb 100644 --- a/content/media/webaudio/AudioBufferSourceNode.cpp +++ b/content/media/webaudio/AudioBufferSourceNode.cpp @@ -413,12 +413,11 @@ AudioBufferSourceNode::AudioBufferSourceNode(AudioContext* aContext) : AudioNode(aContext) , mLoopStart(0.0) , mLoopEnd(0.0) - , mLoop(false) - , mStartCalled(false) , mPlaybackRate(new AudioParam(this, SendPlaybackRateToStream, 1.0f)) , mPannerNode(nullptr) + , mLoop(false) + , mStartCalled(false) { - SetProduceOwnOutput(true); mStream = aContext->Graph()->CreateAudioNodeStream( new AudioBufferSourceNodeEngine(aContext->Destination()), MediaStreamGraph::INTERNAL_STREAM); @@ -503,6 +502,9 @@ AudioBufferSourceNode::Start(JSContext* aCx, double aWhen, double aOffset, ns->SetInt32Parameter(AudioBufferSourceNodeEngine::DURATION, NS_lround(endOffset*rate) - offsetTicks); ns->SetInt32Parameter(AudioBufferSourceNodeEngine::SAMPLE_RATE, rate); + + MOZ_ASSERT(!mPlayingRef, "We can only accept a successful start() call once"); + mPlayingRef.Take(this); } void @@ -528,7 +530,9 @@ void AudioBufferSourceNode::NotifyMainThreadStateChanged() { if (mStream->IsFinished()) { - SetProduceOwnOutput(false); + // Drop the playing reference + // Warning: The below line might delete this. + mPlayingRef.Drop(this); } } diff --git a/content/media/webaudio/AudioBufferSourceNode.h b/content/media/webaudio/AudioBufferSourceNode.h index 18c041de7f6e..7e55b8a04980 100644 --- a/content/media/webaudio/AudioBufferSourceNode.h +++ b/content/media/webaudio/AudioBufferSourceNode.h @@ -50,16 +50,6 @@ public: mPannerNode = aPannerNode; } - void JSBindingFinalized() - { - // If the JS binding goes away on a node which never received a start() - // call, then it can no longer produce output. - if (!mStartCalled) { - SetProduceOwnOutput(false); - } - AudioNode::JSBindingFinalized(); - } - NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioBufferSourceNode, AudioNode) @@ -126,13 +116,14 @@ public: private: static void SendPlaybackRateToStream(AudioNode* aNode); - nsRefPtr mBuffer; double mLoopStart; double mLoopEnd; - bool mLoop; - bool mStartCalled; + nsRefPtr mBuffer; nsRefPtr mPlaybackRate; PannerNode* mPannerNode; + SelfReference mPlayingRef; // a reference to self while playing + bool mLoop; + bool mStartCalled; }; } diff --git a/content/media/webaudio/AudioContext.cpp b/content/media/webaudio/AudioContext.cpp index 09cbc57cae22..5c1c5f677ddd 100644 --- a/content/media/webaudio/AudioContext.cpp +++ b/content/media/webaudio/AudioContext.cpp @@ -233,13 +233,19 @@ AudioContext::CurrentTime() const void AudioContext::Suspend() { - DestinationStream()->ChangeExplicitBlockerCount(1); + MediaStream* ds = DestinationStream(); + if (ds) { + ds->ChangeExplicitBlockerCount(1); + } } void AudioContext::Resume() { - DestinationStream()->ChangeExplicitBlockerCount(-1); + MediaStream* ds = DestinationStream(); + if (ds) { + ds->ChangeExplicitBlockerCount(-1); + } } } diff --git a/content/media/webaudio/AudioDestinationNode.cpp b/content/media/webaudio/AudioDestinationNode.cpp index e1ee3d258f33..df000b625e44 100644 --- a/content/media/webaudio/AudioDestinationNode.cpp +++ b/content/media/webaudio/AudioDestinationNode.cpp @@ -9,31 +9,17 @@ #include "AudioNodeEngine.h" #include "AudioNodeStream.h" #include "MediaStreamGraph.h" -#include "nsContentUtils.h" namespace mozilla { namespace dom { -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(AudioDestinationNode, AudioNode) - NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER -NS_IMPL_CYCLE_COLLECTION_UNLINK_END -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(AudioDestinationNode, AudioNode) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END -NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(AudioDestinationNode) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioDestinationNode) -NS_INTERFACE_MAP_END_INHERITING(AudioNode) - -NS_IMPL_CYCLE_COLLECTING_ADDREF(AudioDestinationNode) -NS_IMPL_CYCLE_COLLECTING_RELEASE(AudioDestinationNode) +NS_IMPL_ISUPPORTS_INHERITED0(AudioDestinationNode, AudioNode) AudioDestinationNode::AudioDestinationNode(AudioContext* aContext, MediaStreamGraph* aGraph) : AudioNode(aContext) { mStream = aGraph->CreateAudioNodeStream(new AudioNodeEngine(), MediaStreamGraph::EXTERNAL_STREAM); - SetIsDOMBinding(); } JSObject* diff --git a/content/media/webaudio/AudioDestinationNode.h b/content/media/webaudio/AudioDestinationNode.h index d2f5b978cc97..b83319f6950d 100644 --- a/content/media/webaudio/AudioDestinationNode.h +++ b/content/media/webaudio/AudioDestinationNode.h @@ -14,19 +14,12 @@ namespace dom { class AudioContext; -/** - * Need to have an nsWrapperCache on AudioDestinationNodes since - * AudioContext.destination returns them. - */ -class AudioDestinationNode : public AudioNode, - public nsWrapperCache +class AudioDestinationNode : public AudioNode { public: AudioDestinationNode(AudioContext* aContext, MediaStreamGraph* aGraph); NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(AudioDestinationNode, - AudioNode) virtual JSObject* WrapObject(JSContext* aCx, JSObject* aScope) MOZ_OVERRIDE; @@ -35,12 +28,6 @@ public: return 0; } - void JSBindingFinalized() - { - // Don't do anything special for destination nodes, as they will always - // remain accessible through the AudioContext. - } - }; } diff --git a/content/media/webaudio/AudioNode.cpp b/content/media/webaudio/AudioNode.cpp index 67b79ad7eb13..d8b902e88c2f 100644 --- a/content/media/webaudio/AudioNode.cpp +++ b/content/media/webaudio/AudioNode.cpp @@ -13,44 +13,36 @@ namespace mozilla { namespace dom { -inline void -ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback, - AudioNode::InputNode& aField, - const char* aName, - unsigned aFlags) -{ - CycleCollectionNoteChild(aCallback, aField.mInputNode.get(), aName, aFlags); -} - -inline void -ImplCycleCollectionUnlink(nsCycleCollectionTraversalCallback& aCallback, - AudioNode::InputNode& aField, - const char* aName, - unsigned aFlags) -{ - aField.mInputNode = nullptr; -} - -NS_IMPL_CYCLE_COLLECTION_3(AudioNode, mContext, mInputNodes, mOutputNodes) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioNode) + tmp->DisconnectFromGraph(); + NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext) + NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutputNodes) + NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER +NS_IMPL_CYCLE_COLLECTION_UNLINK_END +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AudioNode) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputNodes) + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END +NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(AudioNode) NS_IMPL_CYCLE_COLLECTING_ADDREF(AudioNode) NS_IMPL_CYCLE_COLLECTING_RELEASE(AudioNode) NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AudioNode) + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY NS_INTERFACE_MAP_ENTRY(nsISupports) NS_INTERFACE_MAP_END AudioNode::AudioNode(AudioContext* aContext) : mContext(aContext) - , mJSBindingFinalized(false) - , mCanProduceOwnOutput(false) - , mOutputEnded(false) { MOZ_ASSERT(aContext); + SetIsDOMBinding(); } AudioNode::~AudioNode() { - DestroyMediaStream(); + DisconnectFromGraph(); MOZ_ASSERT(mInputNodes.IsEmpty()); MOZ_ASSERT(mOutputNodes.IsEmpty()); } @@ -81,21 +73,8 @@ FindIndexOfNodeWithPorts(const nsTArray& aInputNodes, cons } void -AudioNode::UpdateOutputEnded() +AudioNode::DisconnectFromGraph() { - if (mOutputEnded) { - // Already ended, so nothing to do. - return; - } - if (mCanProduceOwnOutput || - !mInputNodes.IsEmpty() || - (!mJSBindingFinalized && NumberOfInputs() > 0)) { - // This node could still produce output in the future. - return; - } - - mOutputEnded = true; - // Addref this temporarily so the refcount bumping below doesn't destroy us // prematurely nsRefPtr kungFuDeathGrip = this; @@ -106,9 +85,8 @@ AudioNode::UpdateOutputEnded() // Disconnect inputs. We don't need them anymore. while (!mInputNodes.IsEmpty()) { uint32_t i = mInputNodes.Length() - 1; - nsRefPtr input = mInputNodes[i].mInputNode.forget(); + nsRefPtr input = mInputNodes[i].mInputNode; mInputNodes.RemoveElementAt(i); - NS_ASSERTION(mOutputNodes.Contains(this), "input/output inconsistency"); input->mOutputNodes.RemoveElement(this); } @@ -117,12 +95,9 @@ AudioNode::UpdateOutputEnded() nsRefPtr output = mOutputNodes[i].forget(); mOutputNodes.RemoveElementAt(i); uint32_t inputIndex = FindIndexOfNode(output->mInputNodes, this); - NS_ASSERTION(inputIndex != nsTArray::NoIndex, "input/output inconsistency"); // It doesn't matter which one we remove, since we're going to remove all // entries for this node anyway. output->mInputNodes.RemoveElementAt(inputIndex); - - output->UpdateOutputEnded(); } DestroyMediaStream(); @@ -143,11 +118,6 @@ AudioNode::Connect(AudioNode& aDestination, uint32_t aOutput, return; } - if (IsOutputEnded() || aDestination.IsOutputEnded()) { - // No need to connect since we're not going to produce anything other - // than silence. - return; - } if (FindIndexOfNodeWithPorts(aDestination.mInputNodes, this, aInput, aOutput) != nsTArray::NoIndex) { // connection already exists. @@ -157,9 +127,6 @@ AudioNode::Connect(AudioNode& aDestination, uint32_t aOutput, // The MediaStreamGraph will handle cycle detection. We don't need to do it // here. - // Addref this temporarily so the refcount bumping below doesn't destroy us - nsRefPtr kungFuDeathGrip = this; - mOutputNodes.AppendElement(&aDestination); InputNode* input = aDestination.mInputNodes.AppendElement(); input->mInputNode = this; @@ -219,10 +186,6 @@ AudioNode::Disconnect(uint32_t aOutput, ErrorResult& aRv) return; } - // Disconnect everything connected to this output. First find the - // corresponding inputs and remove them. - nsAutoTArray,4> outputsToUpdate; - for (int32_t i = mOutputNodes.Length() - 1; i >= 0; --i) { AudioNode* dest = mOutputNodes[i]; for (int32_t j = dest->mInputNodes.Length() - 1; j >= 0; --j) { @@ -232,17 +195,12 @@ AudioNode::Disconnect(uint32_t aOutput, ErrorResult& aRv) // Remove one instance of 'dest' from mOutputNodes. There could be // others, and it's not correct to remove them all since some of them // could be for different output ports. - *outputsToUpdate.AppendElement() = mOutputNodes[i].forget(); mOutputNodes.RemoveElementAt(i); break; } } } - for (uint32_t i = 0; i < outputsToUpdate.Length(); ++i) { - outputsToUpdate[i]->UpdateOutputEnded(); - } - // This disconnection may have disconnected a panner and a source. Context()->UpdatePannerSource(); } diff --git a/content/media/webaudio/AudioNode.h b/content/media/webaudio/AudioNode.h index 8041fc2f4e6e..c2d56583f363 100644 --- a/content/media/webaudio/AudioNode.h +++ b/content/media/webaudio/AudioNode.h @@ -7,6 +7,7 @@ #ifndef AudioNode_h_ #define AudioNode_h_ +#include "nsWrapperCache.h" #include "nsCycleCollectionParticipant.h" #include "mozilla/Attributes.h" #include "EnableWebAudioCheck.h" @@ -26,6 +27,36 @@ namespace dom { struct ThreeDPoint; +template +class SelfReference { +public: + SelfReference() : mHeld(false) {} + ~SelfReference() + { + NS_ASSERTION(!mHeld, "Forgot to drop the self reference?"); + } + + void Take(T* t) + { + if (!mHeld) { + mHeld = true; + t->AddRef(); + } + } + void Drop(T* t) + { + if (mHeld) { + mHeld = false; + t->Release(); + } + } + + operator bool() const { return mHeld; } + +private: + bool mHeld; +}; + /** * The DOM object representing a Web Audio AudioNode. * @@ -38,14 +69,9 @@ struct ThreeDPoint; * in the future. If it isn't, then we break its connections to its inputs * and outputs, allowing nodes to be immediately disconnected. This * disconnection is done internally, invisible to DOM users. - * - * We say that a node cannot produce output in the future if it has no inputs - * that can, and it is not producing output itself without any inputs, and - * either it can never have any inputs or it has no JS wrapper. (If it has a - * JS wrapper and can accept inputs, then a new input could be added in - * the future.) */ class AudioNode : public nsISupports, + public nsWrapperCache, public EnableWebAudioCheck { public: @@ -71,14 +97,7 @@ public: } NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_CLASS(AudioNode) - - void JSBindingFinalized() - { - NS_ASSERTION(!mJSBindingFinalized, "JS binding already finalized"); - mJSBindingFinalized = true; - UpdateOutputEnded(); - } + NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AudioNode) virtual AudioBufferSourceNode* AsAudioBufferSourceNode() { return nullptr; @@ -105,10 +124,6 @@ public: virtual uint32_t NumberOfInputs() const { return 1; } virtual uint32_t NumberOfOutputs() const { return 1; } - // This could possibly delete 'this'. - void UpdateOutputEnded(); - bool IsOutputEnded() const { return mOutputEnded; } - struct InputNode { ~InputNode() { @@ -117,9 +132,8 @@ public: } } - // Strong reference. - // May be null if the source node has gone away. - nsRefPtr mInputNode; + // Weak reference. + AudioNode* mInputNode; nsRefPtr mStreamPort; // The index of the input port this node feeds into. uint32_t mInputPort; @@ -129,21 +143,15 @@ public: MediaStream* Stream() { return mStream; } - // Set this to true when the node can produce its own output even if there - // are no inputs. - void SetProduceOwnOutput(bool aCanProduceOwnOutput) - { - mCanProduceOwnOutput = aCanProduceOwnOutput; - if (!aCanProduceOwnOutput) { - UpdateOutputEnded(); - } - } - const nsTArray& InputNodes() const { return mInputNodes; } +private: + // This could possibly delete 'this'. + void DisconnectFromGraph(); + protected: static void Callback(AudioNode* aNode) { /* not implemented */ } @@ -171,15 +179,6 @@ private: // exact matching entry, since mOutputNodes doesn't include the port // identifiers and the same node could be connected on multiple ports. nsTArray > mOutputNodes; - // True if the JS binding has been finalized (so script no longer has - // a reference to this node). - bool mJSBindingFinalized; - // True if this node can produce its own output even when all inputs - // have ended their output. - bool mCanProduceOwnOutput; - // True if this node can never produce anything except silence in the future. - // Updated by UpdateOutputEnded(). - bool mOutputEnded; }; } diff --git a/content/media/webaudio/DelayNode.cpp b/content/media/webaudio/DelayNode.cpp index 96137989e9ec..6abad957fea8 100644 --- a/content/media/webaudio/DelayNode.cpp +++ b/content/media/webaudio/DelayNode.cpp @@ -25,14 +25,41 @@ NS_IMPL_RELEASE_INHERITED(DelayNode, AudioNode) class DelayNodeEngine : public AudioNodeEngine { + class PlayingRefChanged : public nsRunnable + { + public: + enum ChangeType { ADDREF, RELEASE }; + PlayingRefChanged(DelayNode& aNode, ChangeType aChange) + : mNode(aNode) + , mChange(aChange) + { + } + + NS_IMETHOD Run() + { + if (mChange == ADDREF) { + mNode.mPlayingRef.Take(&mNode); + } else if (mChange == RELEASE) { + mNode.mPlayingRef.Drop(&mNode); + } + return NS_OK; + } + + private: + DelayNode& mNode; + ChangeType mChange; + }; + public: - explicit DelayNodeEngine(AudioDestinationNode* aDestination) + DelayNodeEngine(AudioDestinationNode* aDestination, DelayNode& aDelay) : mSource(nullptr) , mDestination(static_cast (aDestination->Stream())) + , mDelayNode(aDelay) // Keep the default value in sync with the default value in DelayNode::DelayNode. , mDelay(0.f) , mMaxDelay(0.) , mWriteIndex(0) + , mLeftOverData(INT32_MIN) , mCurrentDelayTime(0.) { } @@ -98,7 +125,30 @@ public: MOZ_ASSERT(mSource == aStream, "Invalid source stream"); const bool firstTime = !!!mBuffer.Length(); - const uint32_t numChannels = aInput.mChannelData.Length(); + const uint32_t numChannels = aInput.IsNull() ? + mBuffer.Length() : + aInput.mChannelData.Length(); + + bool playedBackAllLeftOvers = false; + if (!mBuffer.IsEmpty() && + mLeftOverData == INT32_MIN && + aStream->AllInputsFinished()) { + mLeftOverData = static_cast(mCurrentDelayTime * IdealAudioRate()); + + nsRefPtr refchanged = + new PlayingRefChanged(mDelayNode, PlayingRefChanged::ADDREF); + NS_DispatchToMainThread(refchanged); + } else if (mLeftOverData != INT32_MIN) { + mLeftOverData -= WEBAUDIO_BLOCK_SIZE; + if (mLeftOverData <= 0) { + mLeftOverData = INT32_MIN; + playedBackAllLeftOvers = true; + + nsRefPtr refchanged = + new PlayingRefChanged(mDelayNode, PlayingRefChanged::RELEASE); + NS_DispatchToMainThread(refchanged); + } + } if (!EnsureBuffer(numChannels)) { aOutput->SetNull(0); @@ -134,7 +184,7 @@ public: float* buffer = mBuffer[channel].Elements(); const uint32_t bufferLength = mBuffer[channel].Length(); - const float* input = static_cast(aInput.mChannelData[channel]); + const float* input = static_cast(aInput.mChannelData.SafeElementAt(channel)); float* output = static_cast(const_cast(aOutput->mChannelData[channel])); for (uint32_t i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) { @@ -146,7 +196,9 @@ public: } // Write the input sample to the correct location in our buffer - buffer[writeIndex] = input[i]; + if (input) { + buffer[writeIndex] = input[i]; + } // Now, determine the correct read position. We adjust the read position to be // from currentDelayTime seconds in the past. We also interpolate the two input @@ -183,10 +235,16 @@ public: mWriteIndex = writeIndex; } } + + if (playedBackAllLeftOvers) { + // Delete our buffered data once we no longer need it + mBuffer.Clear(); + } } AudioNodeStream* mSource; AudioNodeStream* mDestination; + DelayNode& mDelayNode; AudioParamTimeline mDelay; // Maximum delay time in seconds double mMaxDelay; @@ -195,6 +253,9 @@ public: // Write index for the buffer, to write the frames to the correct index of the buffer // given the current delay. uint32_t mWriteIndex; + // How much data we have in our buffer which needs to be flushed out when our inputs + // finish. + int32_t mLeftOverData; // Current delay time, in seconds double mCurrentDelayTime; }; @@ -203,7 +264,7 @@ DelayNode::DelayNode(AudioContext* aContext, double aMaxDelay) : AudioNode(aContext) , mDelay(new AudioParam(this, SendDelayToStream, 0.0f)) { - DelayNodeEngine* engine = new DelayNodeEngine(aContext->Destination()); + DelayNodeEngine* engine = new DelayNodeEngine(aContext->Destination(), *this); mStream = aContext->Graph()->CreateAudioNodeStream(engine, MediaStreamGraph::INTERNAL_STREAM); engine->SetSourceStream(static_cast (mStream.get())); AudioNodeStream* ns = static_cast(mStream.get()); diff --git a/content/media/webaudio/DelayNode.h b/content/media/webaudio/DelayNode.h index cef827212b28..73919c099dda 100644 --- a/content/media/webaudio/DelayNode.h +++ b/content/media/webaudio/DelayNode.h @@ -37,9 +37,11 @@ public: private: static void SendDelayToStream(AudioNode* aNode); + friend class DelayNodeEngine; private: nsRefPtr mDelay; + SelfReference mPlayingRef; }; } diff --git a/content/media/webaudio/PannerNode.cpp b/content/media/webaudio/PannerNode.cpp index bb785b8f812d..ced4aa235d8d 100644 --- a/content/media/webaudio/PannerNode.cpp +++ b/content/media/webaudio/PannerNode.cpp @@ -180,7 +180,9 @@ PannerNode::PannerNode(AudioContext* aContext) PannerNode::~PannerNode() { - Context()->UnregisterPannerNode(this); + if (Context()) { + Context()->UnregisterPannerNode(this); + } DestroyMediaStream(); } diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index ed8afa6c2132..b4d09d3eabe1 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -82,10 +82,6 @@ DOMInterfaces = { 'nativeType': 'mozilla::dom::Activity', }, -'AnalyserNode': { - 'wrapperCache': False -}, - 'AnimationEvent': { 'nativeType': 'nsDOMAnimationEvent', }, @@ -112,7 +108,6 @@ DOMInterfaces = { 'AudioBufferSourceNode': { 'implicitJSContext': [ 'start', 'noteOn', 'noteGrainOn' ], 'resultNotAddRefed': [ 'playbackRate' ], - 'wrapperCache': False }, 'AudioListener' : { @@ -133,7 +128,6 @@ DOMInterfaces = { 'BiquadFilterNode': { 'resultNotAddRefed': [ 'frequency', 'q', 'gain' ], - 'wrapperCache': False }, 'Blob': [ @@ -229,7 +223,6 @@ DOMInterfaces = { 'DelayNode': [ { 'resultNotAddRefed': [ 'delayTime' ], - 'wrapperCache': False }], 'DesktopNotificationCenter': { @@ -292,7 +285,6 @@ DOMInterfaces = { 'binaryNames': { 'release': 'getRelease' }, - 'wrapperCache': False }, 'Element': { @@ -378,7 +370,6 @@ DOMInterfaces = { 'GainNode': { 'resultNotAddRefed': [ 'gain' ], - 'wrapperCache': False }, 'Gamepad': { @@ -656,7 +647,6 @@ DOMInterfaces = { 'PannerNode': [ { 'resultNotAddRefed': [ 'coneGain', 'distanceGain' ], - 'wrapperCache': False }], 'Performance': { From 24a63e7a4e7523fe41e44e29d5de830aff0bd3b5 Mon Sep 17 00:00:00 2001 From: Ehsan Akhgari Date: Fri, 12 Apr 2013 11:28:33 -0400 Subject: [PATCH 14/29] Bug 853298 - Part 2: Make AudioNode an EventTarget; r=smaug --- content/media/webaudio/AudioContext.cpp | 3 +-- content/media/webaudio/AudioContext.h | 9 ++++----- content/media/webaudio/AudioNode.cpp | 18 +++++++----------- content/media/webaudio/AudioNode.h | 8 ++++---- .../webaudio/test/test_singleSourceDest.html | 1 + dom/webidl/AudioNode.webidl | 2 +- 6 files changed, 18 insertions(+), 23 deletions(-) diff --git a/content/media/webaudio/AudioContext.cpp b/content/media/webaudio/AudioContext.cpp index 5c1c5f677ddd..078f7715c8a4 100644 --- a/content/media/webaudio/AudioContext.cpp +++ b/content/media/webaudio/AudioContext.cpp @@ -6,7 +6,6 @@ #include "AudioContext.h" #include "nsContentUtils.h" -#include "nsIDOMWindow.h" #include "nsPIDOMWindow.h" #include "mozilla/ErrorResult.h" #include "MediaStreamGraph.h" @@ -33,7 +32,7 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AudioContext, Release) static uint8_t gWebAudioOutputKey; -AudioContext::AudioContext(nsIDOMWindow* aWindow) +AudioContext::AudioContext(nsPIDOMWindow* aWindow) : mWindow(aWindow) , mDestination(new AudioDestinationNode(this, MediaStreamGraph::GetInstance())) { diff --git a/content/media/webaudio/AudioContext.h b/content/media/webaudio/AudioContext.h index bfd848bcd145..4ca8b006c09d 100644 --- a/content/media/webaudio/AudioContext.h +++ b/content/media/webaudio/AudioContext.h @@ -19,7 +19,6 @@ #include "MediaBufferDecoder.h" #include "StreamBuffer.h" #include "MediaStreamGraph.h" -#include "nsIDOMWindow.h" // X11 has a #define for CurrentTime. Unbelievable :-(. // See content/media/DOMMediaStream.h for more fun! @@ -29,7 +28,7 @@ struct JSContext; class JSObject; -class nsIDOMWindow; +class nsPIDOMWindow; namespace mozilla { @@ -53,14 +52,14 @@ class PannerNode; class AudioContext MOZ_FINAL : public nsWrapperCache, public EnableWebAudioCheck { - explicit AudioContext(nsIDOMWindow* aParentWindow); + explicit AudioContext(nsPIDOMWindow* aParentWindow); ~AudioContext(); public: NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AudioContext) NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AudioContext) - nsIDOMWindow* GetParentObject() const + nsPIDOMWindow* GetParentObject() const { return mWindow; } @@ -148,7 +147,7 @@ private: friend struct ::mozilla::WebAudioDecodeJob; private: - nsCOMPtr mWindow; + nsCOMPtr mWindow; nsRefPtr mDestination; nsRefPtr mListener; MediaBufferDecoder mDecoder; diff --git a/content/media/webaudio/AudioNode.cpp b/content/media/webaudio/AudioNode.cpp index d8b902e88c2f..97e1656a3583 100644 --- a/content/media/webaudio/AudioNode.cpp +++ b/content/media/webaudio/AudioNode.cpp @@ -13,30 +13,26 @@ namespace mozilla { namespace dom { -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(AudioNode) +NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(AudioNode, nsDOMEventTargetHelper) tmp->DisconnectFromGraph(); NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext) NS_IMPL_CYCLE_COLLECTION_UNLINK(mOutputNodes) - NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER NS_IMPL_CYCLE_COLLECTION_UNLINK_END -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(AudioNode) +NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(AudioNode, nsDOMEventTargetHelper) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContext) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOutputNodes) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END -NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(AudioNode) -NS_IMPL_CYCLE_COLLECTING_ADDREF(AudioNode) -NS_IMPL_CYCLE_COLLECTING_RELEASE(AudioNode) -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AudioNode) - NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END +NS_IMPL_ADDREF_INHERITED(AudioNode, nsDOMEventTargetHelper) +NS_IMPL_RELEASE_INHERITED(AudioNode, nsDOMEventTargetHelper) +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AudioNode) +NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper) AudioNode::AudioNode(AudioContext* aContext) : mContext(aContext) { MOZ_ASSERT(aContext); + nsDOMEventTargetHelper::BindToOwner(aContext->GetParentObject()); SetIsDOMBinding(); } diff --git a/content/media/webaudio/AudioNode.h b/content/media/webaudio/AudioNode.h index c2d56583f363..95b376440a37 100644 --- a/content/media/webaudio/AudioNode.h +++ b/content/media/webaudio/AudioNode.h @@ -7,7 +7,7 @@ #ifndef AudioNode_h_ #define AudioNode_h_ -#include "nsWrapperCache.h" +#include "nsDOMEventTargetHelper.h" #include "nsCycleCollectionParticipant.h" #include "mozilla/Attributes.h" #include "EnableWebAudioCheck.h" @@ -70,8 +70,7 @@ private: * and outputs, allowing nodes to be immediately disconnected. This * disconnection is done internally, invisible to DOM users. */ -class AudioNode : public nsISupports, - public nsWrapperCache, +class AudioNode : public nsDOMEventTargetHelper, public EnableWebAudioCheck { public: @@ -97,7 +96,8 @@ public: } NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AudioNode) + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AudioNode, + nsDOMEventTargetHelper) virtual AudioBufferSourceNode* AsAudioBufferSourceNode() { return nullptr; diff --git a/content/media/webaudio/test/test_singleSourceDest.html b/content/media/webaudio/test/test_singleSourceDest.html index 843951b390b3..5877843ac1f9 100644 --- a/content/media/webaudio/test/test_singleSourceDest.html +++ b/content/media/webaudio/test/test_singleSourceDest.html @@ -25,6 +25,7 @@ addLoadEvent(function() { is(destination.context, context, "Destination node has proper context"); is(destination.numberOfInputs, 1, "Destination node has 1 inputs"); is(destination.numberOfOutputs, 0, "Destination node has 0 outputs"); + ok(destination instanceof EventTarget, "AudioNodes must be EventTargets"); testWith(context, buffer, destination, function(source) { source.start(0); diff --git a/dom/webidl/AudioNode.webidl b/dom/webidl/AudioNode.webidl index 23a8b122da65..c961aa371fba 100644 --- a/dom/webidl/AudioNode.webidl +++ b/dom/webidl/AudioNode.webidl @@ -11,7 +11,7 @@ */ [PrefControlled] -interface AudioNode { +interface AudioNode : EventTarget { [Throws] void connect(AudioNode destination, optional unsigned long output = 0, optional unsigned long input = 0); From 52b6c3eadda0d57cae66e824a69cebea16eec421 Mon Sep 17 00:00:00 2001 From: Justin Busby Date: Sun, 14 Apr 2013 14:27:02 +0100 Subject: [PATCH 15/29] Bug 755240 - Allow Fennec axis locking behaviour to be controlled by a pref. r=kats --- mobile/android/app/mobile.js | 3 + .../base/gfx/JavaPanZoomController.java | 146 +++++++++++++----- 2 files changed, 113 insertions(+), 36 deletions(-) diff --git a/mobile/android/app/mobile.js b/mobile/android/app/mobile.js index 8efb8a690d90..2ee9b0c7297c 100644 --- a/mobile/android/app/mobile.js +++ b/mobile/android/app/mobile.js @@ -628,6 +628,9 @@ pref("ui.scrolling.overscroll_snap_limit", -1); // The minimum amount of space that must be present for an axis to be considered scrollable, // in 1/1000ths of pixels. pref("ui.scrolling.min_scrollable_distance", -1); +// The axis lock mode for panning behaviour - set between standard, free and sticky +pref("ui.scrolling.axis_lock_mode", "standard"); + // Enable accessibility mode if platform accessibility is enabled. pref("accessibility.accessfu.activate", 2); diff --git a/mobile/android/base/gfx/JavaPanZoomController.java b/mobile/android/base/gfx/JavaPanZoomController.java index 25865c8bc7a0..4198ee444282 100644 --- a/mobile/android/base/gfx/JavaPanZoomController.java +++ b/mobile/android/base/gfx/JavaPanZoomController.java @@ -7,6 +7,7 @@ package org.mozilla.gecko.gfx; import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.GeckoEvent; +import org.mozilla.gecko.PrefsHelper; import org.mozilla.gecko.Tab; import org.mozilla.gecko.Tabs; import org.mozilla.gecko.ZoomConstraints; @@ -61,6 +62,12 @@ class JavaPanZoomController // Angle from axis within which we stay axis-locked private static final double AXIS_LOCK_ANGLE = Math.PI / 6.0; // 30 degrees + // Axis-lock breakout angle + private static final double AXIS_BREAKOUT_ANGLE = Math.PI / 8.0; + + // The distance the user has to pan before we consider breaking out of a locked axis + public static final float AXIS_BREAKOUT_THRESHOLD = 1/32f * GeckoAppShell.getDpi(); + // The maximum amount we allow you to zoom into a page private static final float MAX_ZOOM = 4.0f; @@ -74,24 +81,31 @@ class JavaPanZoomController private static final int BOUNCE_ANIMATION_DURATION = 250; private enum PanZoomState { - NOTHING, /* no touch-start events received */ - FLING, /* all touches removed, but we're still scrolling page */ - TOUCHING, /* one touch-start event received */ - PANNING_LOCKED, /* touch-start followed by move (i.e. panning with axis lock) */ - PANNING, /* panning without axis lock */ - PANNING_HOLD, /* in panning, but not moving. - * similar to TOUCHING but after starting a pan */ - PANNING_HOLD_LOCKED, /* like PANNING_HOLD, but axis lock still in effect */ - PINCHING, /* nth touch-start, where n > 1. this mode allows pan and zoom */ - ANIMATED_ZOOM, /* animated zoom to a new rect */ - BOUNCE, /* in a bounce animation */ + NOTHING, /* no touch-start events received */ + FLING, /* all touches removed, but we're still scrolling page */ + TOUCHING, /* one touch-start event received */ + PANNING_LOCKED_X, /* touch-start followed by move (i.e. panning with axis lock) X axis */ + PANNING_LOCKED_Y, /* as above for Y axis */ + PANNING, /* panning without axis lock */ + PANNING_HOLD, /* in panning, but not moving. + * similar to TOUCHING but after starting a pan */ + PANNING_HOLD_LOCKED_X, /* like PANNING_HOLD, but axis lock still in effect for X axis */ + PANNING_HOLD_LOCKED_Y, /* as above but for Y axis */ + PINCHING, /* nth touch-start, where n > 1. this mode allows pan and zoom */ + ANIMATED_ZOOM, /* animated zoom to a new rect */ + BOUNCE, /* in a bounce animation */ + WAITING_LISTENERS, /* a state halfway between NOTHING and TOUCHING - the user has + put a finger down, but we don't yet know if a touch listener has + prevented the default actions yet. we still need to abort animations. */ + AUTONAV, /* We are scrolling using an AutonavRunnable animation. This is similar + to the FLING state except that it must be stopped manually by the code that + started it, and it's velocity can be updated while it's running. */ + } - WAITING_LISTENERS, /* a state halfway between NOTHING and TOUCHING - the user has - put a finger down, but we don't yet know if a touch listener has - prevented the default actions yet. we still need to abort animations. */ - AUTONAV, /* We are scrolling using an AutonavRunnable animation. This is similar - to the FLING state except that it must be stopped manually by the code that - started it, and it's velocity can be updated while it's running. */ + private enum AxisLockMode { + STANDARD, /* Default axis locking mode that doesn't break out until finger release */ + FREE, /* No locking at all */ + STICKY /* Break out with hysteresis so that it feels as free as possible whilst locking */ } private final PanZoomTarget mTarget; @@ -113,6 +127,8 @@ class JavaPanZoomController private PanZoomState mState; /* The per-frame zoom delta for the currently-running AUTONAV animation. */ private float mAutonavZoomDelta; + /* The user selected panning mode */ + private AxisLockMode mMode; public JavaPanZoomController(PanZoomTarget target, View view, EventDispatcher eventDispatcher) { mTarget = target; @@ -130,6 +146,26 @@ class JavaPanZoomController registerEventListener(MESSAGE_ZOOM_PAGE); registerEventListener(MESSAGE_TOUCH_LISTENER); + mMode = AxisLockMode.STANDARD; + + PrefsHelper.getPref("ui.scrolling.axis_lock_mode", new PrefsHelper.PrefHandlerBase() { + @Override public void prefValue(String pref, String value) { + if (value.equals("standard")) { + mMode = AxisLockMode.STANDARD; + } else if (value.equals("free")) { + mMode = AxisLockMode.FREE; + } else { + mMode = AxisLockMode.STICKY; + } + } + + @Override + public boolean isObserver() { + return true; + } + + }); + Axis.initPrefs(); } @@ -383,9 +419,11 @@ class JavaPanZoomController return false; case TOUCHING: case PANNING: - case PANNING_LOCKED: + case PANNING_LOCKED_X: + case PANNING_LOCKED_Y: case PANNING_HOLD: - case PANNING_HOLD_LOCKED: + case PANNING_HOLD_LOCKED_X: + case PANNING_HOLD_LOCKED_Y: case PINCHING: Log.e(LOGTAG, "Received impossible touch down while in " + mState); return false; @@ -420,10 +458,15 @@ class JavaPanZoomController track(event); return true; - case PANNING_HOLD_LOCKED: - setState(PanZoomState.PANNING_LOCKED); + case PANNING_HOLD_LOCKED_X: + setState(PanZoomState.PANNING_LOCKED_X); + track(event); + return true; + case PANNING_HOLD_LOCKED_Y: + setState(PanZoomState.PANNING_LOCKED_Y); // fall through - case PANNING_LOCKED: + case PANNING_LOCKED_X: + case PANNING_LOCKED_Y: track(event); return true; @@ -466,9 +509,11 @@ class JavaPanZoomController return false; case PANNING: - case PANNING_LOCKED: + case PANNING_LOCKED_X: + case PANNING_LOCKED_Y: case PANNING_HOLD: - case PANNING_HOLD_LOCKED: + case PANNING_HOLD_LOCKED_X: + case PANNING_HOLD_LOCKED_Y: setState(PanZoomState.FLING); fling(); return true; @@ -571,15 +616,19 @@ class JavaPanZoomController mY.startTouch(y); mLastEventTime = time; - if (!mX.scrollable() || !mY.scrollable()) { - setState(PanZoomState.PANNING); - } else if (angle < AXIS_LOCK_ANGLE || angle > (Math.PI - AXIS_LOCK_ANGLE)) { - mY.setScrollingDisabled(true); - setState(PanZoomState.PANNING_LOCKED); - } else if (Math.abs(angle - (Math.PI / 2)) < AXIS_LOCK_ANGLE) { - mX.setScrollingDisabled(true); - setState(PanZoomState.PANNING_LOCKED); - } else { + if (mMode == AxisLockMode.STANDARD || mMode == AxisLockMode.STICKY) { + if (!mX.scrollable() || !mY.scrollable()) { + setState(PanZoomState.PANNING); + } else if (angle < AXIS_LOCK_ANGLE || angle > (Math.PI - AXIS_LOCK_ANGLE)) { + mY.setScrollingDisabled(true); + setState(PanZoomState.PANNING_LOCKED_X); + } else if (Math.abs(angle - (Math.PI / 2)) < AXIS_LOCK_ANGLE) { + mX.setScrollingDisabled(true); + setState(PanZoomState.PANNING_LOCKED_Y); + } else { + setState(PanZoomState.PANNING); + } + } else if (mMode == AxisLockMode.FREE) { setState(PanZoomState.PANNING); } } @@ -599,6 +648,29 @@ class JavaPanZoomController } mLastEventTime = time; + + // if we're axis-locked check if the user is trying to scroll away from the lock + if (mMode == AxisLockMode.STICKY) { + float dx = mX.panDistance(x); + float dy = mY.panDistance(y); + double angle = Math.atan2(dy, dx); // range [-pi, pi] + angle = Math.abs(angle); // range [0, pi] + + if (Math.abs(dx) > AXIS_BREAKOUT_THRESHOLD || Math.abs(dy) > AXIS_BREAKOUT_THRESHOLD) { + if (mState == PanZoomState.PANNING_LOCKED_X) { + if (angle > AXIS_BREAKOUT_ANGLE && angle < (Math.PI - AXIS_BREAKOUT_ANGLE)) { + mY.setScrollingDisabled(false); + setState(PanZoomState.PANNING); + } + } else if (mState == PanZoomState.PANNING_LOCKED_Y) { + if (Math.abs(angle - (Math.PI / 2)) > AXIS_BREAKOUT_ANGLE) { + mX.setScrollingDisabled(false); + setState(PanZoomState.PANNING); + } + } + } + } + mX.updateWithTouchAt(x, timeDelta); mY.updateWithTouchAt(y, timeDelta); } @@ -617,12 +689,14 @@ class JavaPanZoomController if (stopped()) { if (mState == PanZoomState.PANNING) { setState(PanZoomState.PANNING_HOLD); - } else if (mState == PanZoomState.PANNING_LOCKED) { - setState(PanZoomState.PANNING_HOLD_LOCKED); + } else if (mState == PanZoomState.PANNING_LOCKED_X) { + setState(PanZoomState.PANNING_HOLD_LOCKED_X); + } else if (mState == PanZoomState.PANNING_LOCKED_Y) { + setState(PanZoomState.PANNING_HOLD_LOCKED_Y); } else { // should never happen, but handle anyway for robustness Log.e(LOGTAG, "Impossible case " + mState + " when stopped in track"); - setState(PanZoomState.PANNING_HOLD_LOCKED); + setState(PanZoomState.PANNING_HOLD); } } From ef676729bcd4eb1d822d7f6fd16ebf78d0e31ee0 Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Mon, 15 Apr 2013 06:01:38 +0100 Subject: [PATCH 16/29] Bug 860701 - Check for error in nsRangeFrame::GetValueAtEventPoint so that we don't change the value of when we can't convert an event to a valid point. r=me --- layout/forms/nsRangeFrame.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/layout/forms/nsRangeFrame.cpp b/layout/forms/nsRangeFrame.cpp index cf3b7d918e37..fd418856ff2b 100644 --- a/layout/forms/nsRangeFrame.cpp +++ b/layout/forms/nsRangeFrame.cpp @@ -409,6 +409,11 @@ nsRangeFrame::GetValueAtEventPoint(nsGUIEvent* aEvent) nsPoint point = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, absPoint, this); + if (point == nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)) { + // We don't want to change the current value for this error state. + return GetValue(); + } + nsRect rangeContentRect = GetContentRectRelativeToSelf(); nsSize thumbSize; From 2efce68b212f4fb2d3cbe9b85caa96233380bd81 Mon Sep 17 00:00:00 2001 From: Jonathan Watt Date: Mon, 15 Apr 2013 06:03:57 +0100 Subject: [PATCH 17/29] Bug 859139 - Allow to keep its native styling when authors set its padding. r=mounir --- layout/forms/nsRangeFrame.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/layout/forms/nsRangeFrame.cpp b/layout/forms/nsRangeFrame.cpp index fd418856ff2b..140aeea71d4c 100644 --- a/layout/forms/nsRangeFrame.cpp +++ b/layout/forms/nsRangeFrame.cpp @@ -734,7 +734,8 @@ nsRangeFrame::ShouldUseNativeStyle() const { return (StyleDisplay()->mAppearance == NS_THEME_RANGE) && !PresContext()->HasAuthorSpecifiedRules(const_cast(this), - STYLES_DISABLING_NATIVE_THEMING) && + (NS_AUTHOR_SPECIFIED_BORDER | + NS_AUTHOR_SPECIFIED_BACKGROUND)) && !PresContext()->HasAuthorSpecifiedRules(mTrackDiv->GetPrimaryFrame(), STYLES_DISABLING_NATIVE_THEMING) && !PresContext()->HasAuthorSpecifiedRules(mProgressDiv->GetPrimaryFrame(), From 7394d7ef479c638d298fca98addd936c14c060da Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Mon, 15 Apr 2013 18:55:29 +1200 Subject: [PATCH 18/29] Bug 857817 - Make AreLayerMarkedActive aware of preserve-3d transformed frames. r=roc --- layout/generic/nsFrame.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index a0c3655d8428..7e28cbd8cde1 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -4583,7 +4583,14 @@ nsIFrame::AreLayersMarkedActive(nsChangeHint aChangeHint) { LayerActivity* layerActivity = static_cast(Properties().Get(LayerActivityProperty())); - return layerActivity && (layerActivity->mChangeHint & aChangeHint); + if (layerActivity && (layerActivity->mChangeHint & aChangeHint)) { + return true; + } + if (aChangeHint & nsChangeHint_UpdateTransformLayer && + Preserves3D()) { + return GetParent()->AreLayersMarkedActive(nsChangeHint_UpdateTransformLayer); + } + return false; } /* static */ void From fa950ebd97764c3938bc54be6936fea3bad1b7b5 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Mon, 15 Apr 2013 18:55:32 +1200 Subject: [PATCH 19/29] Bug 861042 - Manually invalidate frames with both opacity and svg effects, as this isn't caught by DLBI. r=roc --- layout/base/nsCSSFrameConstructor.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index d91a8edd894d..deab4aed4a7e 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -91,6 +91,7 @@ #include "nsStyleStructInlines.h" #include "nsAnimationManager.h" #include "nsTransitionManager.h" +#include "nsSVGIntegrationUtils.h" #include #ifdef MOZ_XUL @@ -7752,6 +7753,11 @@ DoApplyRenderingChangeToTree(nsIFrame* aFrame, // opacity updates in many cases. needInvalidatingPaint = true; aFrame->MarkLayersActive(nsChangeHint_UpdateOpacityLayer); + if (nsSVGIntegrationUtils::UsingEffectsForFrame(aFrame)) { + // SVG effects paints the opacity without using + // nsDisplayOpacity. We need to invalidate manually. + aFrame->InvalidateFrameSubtree(); + } } if ((aChange & nsChangeHint_UpdateTransformLayer) && aFrame->IsTransformed()) { From ddf019654293ab2248cd81670c3edf3c24ef6789 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Mon, 15 Apr 2013 18:55:34 +1200 Subject: [PATCH 20/29] Bug 859526 - Null check parent frames when wrapping preserve-3d display lists. r=roc --- layout/base/crashtests/859526-1.html | 7 +++++++ layout/base/crashtests/crashtests.list | 1 + layout/generic/nsFrame.cpp | 4 +++- 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 layout/base/crashtests/859526-1.html diff --git a/layout/base/crashtests/859526-1.html b/layout/base/crashtests/859526-1.html new file mode 100644 index 000000000000..9e2574fd7fa8 --- /dev/null +++ b/layout/base/crashtests/859526-1.html @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/layout/base/crashtests/crashtests.list b/layout/base/crashtests/crashtests.list index 6935bd6c7b34..b3853b8e1855 100644 --- a/layout/base/crashtests/crashtests.list +++ b/layout/base/crashtests/crashtests.list @@ -391,3 +391,4 @@ load 770381-1.html load 795646.html load 813372-1.html load 836990-1.html +pref(layers.force-active,true) load 859526-1.html diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 7e28cbd8cde1..96f5e12f9525 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1673,7 +1673,9 @@ WrapPreserve3DListInternal(nsIFrame* aFrame, nsDisplayListBuilder *aBuilder, nsD // and then flush this list into aOutput by wrapping the whole lot with a single // nsDisplayTransform. - if (childFrame && (childFrame->GetParent()->Preserves3DChildren() || childFrame == aFrame)) { + if (childFrame && + childFrame->GetParent() && + (childFrame->GetParent()->Preserves3DChildren() || childFrame == aFrame)) { switch (item->GetType()) { case nsDisplayItem::TYPE_TRANSFORM: { if (!aTemp->IsEmpty()) { From b2957b8f1d1645ea4b88965106bce9e5efc5500c Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Mon, 15 Apr 2013 18:55:36 +1200 Subject: [PATCH 21/29] Bug 859630 - Use the PresContext's document in FindContentInDocument when the frame doesn't have an associated nsIContent. r=roc --- layout/base/crashtests/859630-1.html | 7 +++++++ layout/base/crashtests/crashtests.list | 1 + layout/base/nsDisplayList.cpp | 18 +++++++++++------- 3 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 layout/base/crashtests/859630-1.html diff --git a/layout/base/crashtests/859630-1.html b/layout/base/crashtests/859630-1.html new file mode 100644 index 000000000000..ca0cd9df85cb --- /dev/null +++ b/layout/base/crashtests/859630-1.html @@ -0,0 +1,7 @@ + + + + +
+ + \ No newline at end of file diff --git a/layout/base/crashtests/crashtests.list b/layout/base/crashtests/crashtests.list index b3853b8e1855..b3deafebf51e 100644 --- a/layout/base/crashtests/crashtests.list +++ b/layout/base/crashtests/crashtests.list @@ -392,3 +392,4 @@ load 795646.html load 813372-1.html load 836990-1.html pref(layers.force-active,true) load 859526-1.html +pref(layers.force-active,true) load 859630-1.html diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index efc6f3365617..bd3b89d3d8b7 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -1395,10 +1395,16 @@ static void Sort(nsDisplayList* aList, int32_t aCount, nsDisplayList::SortLEQ aC } } -static nsIContent* FindContentInDocument(nsIContent* aContent, nsIDocument* aDoc) { - nsIContent* c = aContent; +static nsIContent* FindContentInDocument(nsDisplayItem* aItem, nsIDocument* aDoc) { + nsIFrame* frame = aItem->GetUnderlyingFrame(); + nsIContent* c = frame->GetContent(); for (;;) { - nsIDocument* d = c->OwnerDoc(); + nsIDocument* d; + if (c) { + d = c->OwnerDoc(); + } else { + d = frame->PresContext()->Document(); + } if (d == aDoc) { return c; } @@ -1422,10 +1428,8 @@ static bool IsContentLEQ(nsDisplayItem* aItem1, nsDisplayItem* aItem2, // mixed into the same list. Ensure that we're looking at content // in commonAncestor's document. nsIDocument* commonAncestorDoc = commonAncestor->OwnerDoc(); - nsIContent* content1 = FindContentInDocument(aItem1->GetUnderlyingFrame()->GetContent(), - commonAncestorDoc); - nsIContent* content2 = FindContentInDocument(aItem2->GetUnderlyingFrame()->GetContent(), - commonAncestorDoc); + nsIContent* content1 = FindContentInDocument(aItem1, commonAncestorDoc); + nsIContent* content2 = FindContentInDocument(aItem2, commonAncestorDoc); if (!content1 || !content2) { NS_ERROR("Document trees are mixed up!"); // Something weird going on From a16a8c0d7706a67abf6027eff7aa3b7fa770703a Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Mon, 15 Apr 2013 17:16:07 +1000 Subject: [PATCH 22/29] Bug 843917 - Don't call InvalidateBounds() in nsSVGTextFrame2; leave invalidation to DLBI. r=jwatt --- layout/svg/nsSVGTextFrame2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/svg/nsSVGTextFrame2.cpp b/layout/svg/nsSVGTextFrame2.cpp index 55fe513c5f89..0c6e55e7d0e4 100644 --- a/layout/svg/nsSVGTextFrame2.cpp +++ b/layout/svg/nsSVGTextFrame2.cpp @@ -2880,7 +2880,7 @@ void GlyphMetricsUpdater::Run(nsSVGTextFrame2* aFrame) { aFrame->mPositioningDirty = true; - nsSVGUtils::InvalidateBounds(aFrame, false); + nsSVGEffects::InvalidateRenderingObservers(aFrame); nsSVGUtils::ScheduleReflowSVG(aFrame); aFrame->mGlyphMetricsUpdater = nullptr; } From 9b79bd3d3cff13263b694b7adeb53be2dd3ed6a0 Mon Sep 17 00:00:00 2001 From: Chris Lord Date: Mon, 15 Apr 2013 09:31:45 +0100 Subject: [PATCH 23/29] Bug 856932 - Fix fixed margins on position:fixed hierarchies. r=roc Make sure that fixed margins aren't applied to auto-positioned frames, unless their containing block is the primary frame of the body element. --- layout/generic/nsAbsoluteContainingBlock.cpp | 54 +++++++++++--------- layout/generic/nsAbsoluteContainingBlock.h | 7 +-- layout/generic/nsBlockFrame.cpp | 4 +- layout/generic/nsFrame.cpp | 3 +- layout/generic/nsViewportFrame.cpp | 12 +++-- 5 files changed, 43 insertions(+), 37 deletions(-) diff --git a/layout/generic/nsAbsoluteContainingBlock.cpp b/layout/generic/nsAbsoluteContainingBlock.cpp index 974c0f262630..8ce3feb26d21 100644 --- a/layout/generic/nsAbsoluteContainingBlock.cpp +++ b/layout/generic/nsAbsoluteContainingBlock.cpp @@ -18,6 +18,7 @@ #include "nsPresContext.h" #include "nsFrameManager.h" #include "nsCSSFrameConstructor.h" +#include "nsIDocumentInlines.h" #ifdef DEBUG #include "nsBlockFrame.h" @@ -115,8 +116,7 @@ nsAbsoluteContainingBlock::Reflow(nsContainerFrame* aDelegatingFrame, nsPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aReflowStatus, - nscoord aContainingBlockWidth, - nscoord aContainingBlockHeight, + const nsRect& aContainingBlock, bool aConstrainHeight, bool aCBWidthChanged, bool aCBHeightChanged, @@ -135,7 +135,7 @@ nsAbsoluteContainingBlock::Reflow(nsContainerFrame* aDelegatingFrame, // Reflow the frame nsReflowStatus kidStatus = NS_FRAME_COMPLETE; ReflowAbsoluteFrame(aDelegatingFrame, aPresContext, aReflowState, - aContainingBlockWidth, aContainingBlockHeight, + aContainingBlock, aConstrainHeight, kidFrame, kidStatus, aOverflowAreas); nsIFrame* nextFrame = kidFrame->GetNextInFlow(); @@ -348,10 +348,9 @@ nsAbsoluteContainingBlock::DoMarkFramesDirty(bool aMarkAllDirty) nsresult nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegatingFrame, - nsPresContext* aPresContext, + nsPresContext* aPresContext, const nsHTMLReflowState& aReflowState, - nscoord aContainingBlockWidth, - nscoord aContainingBlockHeight, + const nsRect& aContainingBlock, bool aConstrainHeight, nsIFrame* aKidFrame, nsReflowStatus& aStatus, @@ -379,21 +378,7 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat AutoNoisyIndenter indent(nsBlockFrame::gNoisy); #endif // DEBUG - nsresult rv; - // Get the border values - nsMargin border = aReflowState.mStyleBorder->GetComputedBorder(); - - // Respect fixed position margins. - if (aDelegatingFrame->GetAbsoluteListID() == nsIFrame::kFixedList) { - const nsMargin& fixedMargins = aPresContext->PresShell()-> - GetContentDocumentFixedPositionMargins(); - - border += fixedMargins; - aContainingBlockWidth -= fixedMargins.left + fixedMargins.right; - aContainingBlockHeight -= fixedMargins.top + fixedMargins.bottom; - } - - nscoord availWidth = aContainingBlockWidth; + nscoord availWidth = aContainingBlock.width; if (availWidth == -1) { NS_ASSERTION(aReflowState.ComputedWidth() != NS_UNCONSTRAINEDSIZE, "Must have a useful width _somewhere_"); @@ -404,12 +389,15 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat nsHTMLReflowMetrics kidDesiredSize; nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aKidFrame, nsSize(availWidth, NS_UNCONSTRAINEDSIZE), - aContainingBlockWidth, - aContainingBlockHeight); + aContainingBlock.width, + aContainingBlock.height); // Send the WillReflow() notification and position the frame aKidFrame->WillReflow(aPresContext); + // Get the border values + const nsMargin& border = aReflowState.mStyleBorder->GetComputedBorder(); + bool constrainHeight = (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) && aConstrainHeight // Don't split if told not to (e.g. for fixed frames) @@ -427,12 +415,15 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat } // Do the reflow - rv = aKidFrame->Reflow(aPresContext, kidDesiredSize, kidReflowState, aStatus); + nsresult rv = aKidFrame->Reflow(aPresContext, kidDesiredSize, kidReflowState, aStatus); // If we're solving for 'left' or 'top', then compute it now that we know the // width/height if ((NS_AUTOOFFSET == kidReflowState.mComputedOffsets.left) || (NS_AUTOOFFSET == kidReflowState.mComputedOffsets.top)) { + nscoord aContainingBlockWidth = aContainingBlock.width; + nscoord aContainingBlockHeight = aContainingBlock.height; + if (-1 == aContainingBlockWidth) { // Get the containing block width/height kidReflowState.ComputeContainingBlockRectangle(aPresContext, @@ -463,6 +454,21 @@ nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegat nsRect rect(border.left + kidReflowState.mComputedOffsets.left + kidReflowState.mComputedMargin.left, border.top + kidReflowState.mComputedOffsets.top + kidReflowState.mComputedMargin.top, kidDesiredSize.width, kidDesiredSize.height); + + // Offset the frame rect by the given origin of the absolute containing block. + // If the frame is auto-positioned on both sides of an axis, it will be + // positioned based on its containing block and we don't need to offset. + if (aContainingBlock.TopLeft() != nsPoint(0, 0)) { + if (!(kidReflowState.mStylePosition->mOffset.GetLeftUnit() == eStyleUnit_Auto && + kidReflowState.mStylePosition->mOffset.GetRightUnit() == eStyleUnit_Auto)) { + rect.x += aContainingBlock.x; + } + if (!(kidReflowState.mStylePosition->mOffset.GetTopUnit() == eStyleUnit_Auto && + kidReflowState.mStylePosition->mOffset.GetBottomUnit() == eStyleUnit_Auto)) { + rect.y += aContainingBlock.y; + } + } + aKidFrame->SetRect(rect); nsView* view = aKidFrame->GetView(); diff --git a/layout/generic/nsAbsoluteContainingBlock.h b/layout/generic/nsAbsoluteContainingBlock.h index 25cc5ab1128a..245e6a17e5d6 100644 --- a/layout/generic/nsAbsoluteContainingBlock.h +++ b/layout/generic/nsAbsoluteContainingBlock.h @@ -86,14 +86,12 @@ public: nsPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aReflowStatus, - nscoord aContainingBlockWidth, - nscoord aContainingBlockHeight, + const nsRect& aContainingBlock, bool aConstrainHeight, bool aCBWidthChanged, bool aCBHeightChanged, nsOverflowAreas* aOverflowAreas); - void DestroyFrames(nsIFrame* aDelegatingFrame, nsIFrame* aDestructRoot); @@ -122,8 +120,7 @@ protected: nsresult ReflowAbsoluteFrame(nsIFrame* aDelegatingFrame, nsPresContext* aPresContext, const nsHTMLReflowState& aReflowState, - nscoord aContainingBlockWidth, - nscoord aContainingBlockHeight, + const nsRect& aContainingBlockRect, bool aConstrainHeight, nsIFrame* aKidFrame, nsReflowStatus& aStatus, diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index 21805ae5b605..a9dd893e26b1 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -1229,10 +1229,10 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext, !(isRoot && NS_UNCONSTRAINEDSIZE == reflowState->ComputedHeight()) && aMetrics.height != oldSize.height; + nsRect containingBlock(nsPoint(0, 0), containingBlockSize); absoluteContainer->Reflow(this, aPresContext, *reflowState, state.mReflowStatus, - containingBlockSize.width, - containingBlockSize.height, true, + containingBlock, true, cbWidthChanged, cbHeightChanged, &aMetrics.mOverflowAreas); diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 96f5e12f9525..e458d7d430ac 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -4116,8 +4116,9 @@ nsFrame::ReflowAbsoluteFrames(nsPresContext* aPresContext, nsContainerFrame* container = do_QueryFrame(this); NS_ASSERTION(container, "Abs-pos children only supported on container frames for now"); + nsRect containingBlock(0, 0, containingBlockWidth, containingBlockHeight); absoluteContainer->Reflow(container, aPresContext, aReflowState, aStatus, - containingBlockWidth, containingBlockHeight, + containingBlock, aConstrainHeight, true, true, // XXX could be optimized &aDesiredSize.mOverflowAreas); } diff --git a/layout/generic/nsViewportFrame.cpp b/layout/generic/nsViewportFrame.cpp index 38a6448e1a73..1b9fd6d3b9ee 100644 --- a/layout/generic/nsViewportFrame.cpp +++ b/layout/generic/nsViewportFrame.cpp @@ -250,18 +250,20 @@ ViewportFrame::Reflow(nsPresContext* aPresContext, // If a scroll position clamping scroll-port size has been set, layout // fixed position elements to this size instead of the computed size. - nscoord width = reflowState.ComputedWidth(); - nscoord height = reflowState.ComputedHeight(); + nsRect rect(0, 0, reflowState.ComputedWidth(), reflowState.ComputedHeight()); if (aPresContext->PresShell()->IsScrollPositionClampingScrollPortSizeSet()) { nsSize size = aPresContext->PresShell()-> GetScrollPositionClampingScrollPortSize(); - width = size.width; - height = size.height; + rect.width = size.width; + rect.height = size.height; } + // Make sure content document fixed-position margins are respected. + rect.Deflate(aPresContext->PresShell()->GetContentDocumentFixedPositionMargins()); + // Just reflow all the fixed-pos frames. rv = GetAbsoluteContainingBlock()->Reflow(this, aPresContext, reflowState, aStatus, - width, height, + rect, false, true, true, // XXX could be optimized &aDesiredSize.mOverflowAreas); } From d3109edb44199ae2b3e3c93f860c76234bcf0748 Mon Sep 17 00:00:00 2001 From: Chris Lord Date: Mon, 15 Apr 2013 09:31:48 +0100 Subject: [PATCH 24/29] Bug 856932 - Fix async scrolling of auto-positioned fixed position elements. r=nrc Layers representing auto-positioned fixed position elements should not be offset by the fixed layer margins. --- gfx/layers/Layers.h | 3 +++ gfx/layers/ipc/CompositorParent.cpp | 23 +++++++++++++++-------- layout/base/nsDisplayList.cpp | 13 +++++++++++++ 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 0eaf4ef5af3b..94c3407a433e 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -859,6 +859,9 @@ public: * will be mirrored here. This allows for asynchronous animation of the * margins by reconciling the difference between this value and a value that * is updated more frequently. + * If the left or top margins are negative, it means that the elements this + * layer represents are auto-positioned, and so fixed position margins should + * not have an effect on the corresponding axis. */ void SetFixedPositionMargins(const gfx::Margin& aMargins) { diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index d1ef5a66fe32..d77fabf682e1 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -642,17 +642,24 @@ CompositorParent::TransformFixedLayers(Layer* aLayer, // aFixedLayerMargins are the margins we expect to be at at the current // time, obtained via SyncViewportInfo, and fixedMargins are the margins // that were used during layout. + // If top/left of fixedMargins are negative, that indicates that this layer + // represents auto-positioned elements, and should not be affected by + // fixed margins at all. const gfx::Margin& fixedMargins = aLayer->GetFixedPositionMargins(); - if (anchor.x > 0) { - translation.x -= aFixedLayerMargins.right - fixedMargins.right; - } else { - translation.x += aFixedLayerMargins.left - fixedMargins.left; + if (fixedMargins.left >= 0) { + if (anchor.x > 0) { + translation.x -= aFixedLayerMargins.right - fixedMargins.right; + } else { + translation.x += aFixedLayerMargins.left - fixedMargins.left; + } } - if (anchor.y > 0) { - translation.y -= aFixedLayerMargins.bottom - fixedMargins.bottom; - } else { - translation.y += aFixedLayerMargins.top - fixedMargins.top; + if (fixedMargins.top >= 0) { + if (anchor.y > 0) { + translation.y -= aFixedLayerMargins.bottom - fixedMargins.bottom; + } else { + translation.y += aFixedLayerMargins.top - fixedMargins.top; + } } // The transform already takes the resolution scale into account. Since we diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index bd3b89d3d8b7..a01878d57b0e 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -2961,6 +2961,19 @@ nsDisplayFixedPosition::BuildLayer(nsDisplayListBuilder* aBuilder, aContainerParameters.mYScale, NSAppUnitsToFloatPixels(fixedMargins.left, factor) * aContainerParameters.mXScale); + + // If the frame is auto-positioned on either axis, set the top/left layer + // margins to -1, to indicate to the compositor that this layer is + // unaffected by fixed margins. + if (position->mOffset.GetLeftUnit() == eStyleUnit_Auto && + position->mOffset.GetRightUnit() == eStyleUnit_Auto) { + fixedLayerMargins.left = -1; + } + if (position->mOffset.GetTopUnit() == eStyleUnit_Auto && + position->mOffset.GetBottomUnit() == eStyleUnit_Auto) { + fixedLayerMargins.top = -1; + } + layer->SetFixedPositionMargins(fixedLayerMargins); return layer.forget(); From 5365eb220736cb009a2c0b5649cc4ce9e3c06a60 Mon Sep 17 00:00:00 2001 From: Jonathan Griffin Date: Mon, 15 Apr 2013 01:40:08 -0700 Subject: [PATCH 25/29] Bug 860104 - Disable another click test, a=test-only --- .../marionette/tests/unit/test_click.py | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/testing/marionette/client/marionette/tests/unit/test_click.py b/testing/marionette/client/marionette/tests/unit/test_click.py index db4946da8cf8..bd27ad5e782b 100644 --- a/testing/marionette/client/marionette/tests/unit/test_click.py +++ b/testing/marionette/client/marionette/tests/unit/test_click.py @@ -5,6 +5,8 @@ import time from marionette_test import MarionetteTestCase +""" +### Disabled due to bug 860104 class TestClick(MarionetteTestCase): def test_click(self): test_html = self.marionette.absolute_url("test.html") @@ -13,19 +15,19 @@ class TestClick(MarionetteTestCase): link.click() self.assertEqual("Clicked", self.marionette.execute_script("return document.getElementById('mozLink').innerHTML;")) - # disabled due to bug 860104 - #def testClickingALinkMadeUpOfNumbersIsHandledCorrectly(self): - # test_html = self.marionette.absolute_url("clicks.html") - # self.marionette.navigate(test_html) - # self.marionette.find_element("link text", "333333").click() - # count = 0 - # while len(self.marionette.find_elements("id", "username")) == 0: - # count += 1 - # time.sleep(1) - # if count == 30: - # self.fail("Element id=username not found after 30 seconds") + def testClickingALinkMadeUpOfNumbersIsHandledCorrectly(self): + test_html = self.marionette.absolute_url("clicks.html") + self.marionette.navigate(test_html) + self.marionette.find_element("link text", "333333").click() + count = 0 + while len(self.marionette.find_elements("id", "username")) == 0: + count += 1 + time.sleep(1) + if count == 30: + self.fail("Element id=username not found after 30 seconds") - # self.assertEqual(self.marionette.title, "XHTML Test Page") + self.assertEqual(self.marionette.title, "XHTML Test Page") +""" class TestClickChrome(MarionetteTestCase): def setUp(self): From 5b0746d2750dbc951272d112002fe5c870a056a1 Mon Sep 17 00:00:00 2001 From: Jonathan Griffin Date: Mon, 15 Apr 2013 01:43:14 -0700 Subject: [PATCH 26/29] Backed out changeset c2449e6144d1 (wrong bug #) --- .../marionette/tests/unit/test_click.py | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/testing/marionette/client/marionette/tests/unit/test_click.py b/testing/marionette/client/marionette/tests/unit/test_click.py index bd27ad5e782b..db4946da8cf8 100644 --- a/testing/marionette/client/marionette/tests/unit/test_click.py +++ b/testing/marionette/client/marionette/tests/unit/test_click.py @@ -5,8 +5,6 @@ import time from marionette_test import MarionetteTestCase -""" -### Disabled due to bug 860104 class TestClick(MarionetteTestCase): def test_click(self): test_html = self.marionette.absolute_url("test.html") @@ -15,19 +13,19 @@ class TestClick(MarionetteTestCase): link.click() self.assertEqual("Clicked", self.marionette.execute_script("return document.getElementById('mozLink').innerHTML;")) - def testClickingALinkMadeUpOfNumbersIsHandledCorrectly(self): - test_html = self.marionette.absolute_url("clicks.html") - self.marionette.navigate(test_html) - self.marionette.find_element("link text", "333333").click() - count = 0 - while len(self.marionette.find_elements("id", "username")) == 0: - count += 1 - time.sleep(1) - if count == 30: - self.fail("Element id=username not found after 30 seconds") + # disabled due to bug 860104 + #def testClickingALinkMadeUpOfNumbersIsHandledCorrectly(self): + # test_html = self.marionette.absolute_url("clicks.html") + # self.marionette.navigate(test_html) + # self.marionette.find_element("link text", "333333").click() + # count = 0 + # while len(self.marionette.find_elements("id", "username")) == 0: + # count += 1 + # time.sleep(1) + # if count == 30: + # self.fail("Element id=username not found after 30 seconds") - self.assertEqual(self.marionette.title, "XHTML Test Page") -""" + # self.assertEqual(self.marionette.title, "XHTML Test Page") class TestClickChrome(MarionetteTestCase): def setUp(self): From a1f0729a3ff785abb6a7f7e11afc8876922d0362 Mon Sep 17 00:00:00 2001 From: Jonathan Griffin Date: Mon, 15 Apr 2013 01:40:08 -0700 Subject: [PATCH 27/29] Bug 838607 - Disable another click test, a=test-only --- .../marionette/tests/unit/test_click.py | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/testing/marionette/client/marionette/tests/unit/test_click.py b/testing/marionette/client/marionette/tests/unit/test_click.py index db4946da8cf8..f36a332901ef 100644 --- a/testing/marionette/client/marionette/tests/unit/test_click.py +++ b/testing/marionette/client/marionette/tests/unit/test_click.py @@ -5,6 +5,8 @@ import time from marionette_test import MarionetteTestCase +""" +### Disabled due to bug 838607 class TestClick(MarionetteTestCase): def test_click(self): test_html = self.marionette.absolute_url("test.html") @@ -13,19 +15,19 @@ class TestClick(MarionetteTestCase): link.click() self.assertEqual("Clicked", self.marionette.execute_script("return document.getElementById('mozLink').innerHTML;")) - # disabled due to bug 860104 - #def testClickingALinkMadeUpOfNumbersIsHandledCorrectly(self): - # test_html = self.marionette.absolute_url("clicks.html") - # self.marionette.navigate(test_html) - # self.marionette.find_element("link text", "333333").click() - # count = 0 - # while len(self.marionette.find_elements("id", "username")) == 0: - # count += 1 - # time.sleep(1) - # if count == 30: - # self.fail("Element id=username not found after 30 seconds") + def testClickingALinkMadeUpOfNumbersIsHandledCorrectly(self): + test_html = self.marionette.absolute_url("clicks.html") + self.marionette.navigate(test_html) + self.marionette.find_element("link text", "333333").click() + count = 0 + while len(self.marionette.find_elements("id", "username")) == 0: + count += 1 + time.sleep(1) + if count == 30: + self.fail("Element id=username not found after 30 seconds") - # self.assertEqual(self.marionette.title, "XHTML Test Page") + self.assertEqual(self.marionette.title, "XHTML Test Page") +""" class TestClickChrome(MarionetteTestCase): def setUp(self): From aa1f479bdf738d21406dd00b64953e863e5bf726 Mon Sep 17 00:00:00 2001 From: Jonathan Griffin Date: Mon, 8 Apr 2013 14:12:32 -0700 Subject: [PATCH 28/29] Bug 843793 - Throw specific errors when iframe is crashed or hung, r=mdas --- .../marionette/client/marionette/errors.py | 7 + .../client/marionette/marionette.py | 6 +- testing/marionette/marionette-actors.js | 342 ++++++++++++------ 3 files changed, 236 insertions(+), 119 deletions(-) diff --git a/testing/marionette/client/marionette/errors.py b/testing/marionette/client/marionette/errors.py index 5a224320940f..47f05c7801f3 100644 --- a/testing/marionette/client/marionette/errors.py +++ b/testing/marionette/client/marionette/errors.py @@ -28,6 +28,8 @@ class ErrorCodes(object): INVALID_XPATH_SELECTOR = 51 INVALID_XPATH_SELECTOR_RETURN_TYPER = 52 INVALID_RESPONSE = 53 + FRAME_SEND_NOT_INITIALIZED_ERROR = 54 + FRAME_SEND_FAILURE_ERROR = 55 MARIONETTE_ERROR = 500 class MarionetteException(Exception): @@ -97,3 +99,8 @@ class InvalidSelectorException(MarionetteException): class MoveTargetOutOfBoundsException(MarionetteException): pass +class FrameSendNotInitializedError(MarionetteException): + pass + +class FrameSendFailureError(MarionetteException): + pass diff --git a/testing/marionette/client/marionette/marionette.py b/testing/marionette/client/marionette/marionette.py index 59cccc0f6cfc..49b9da3601df 100644 --- a/testing/marionette/client/marionette/marionette.py +++ b/testing/marionette/client/marionette/marionette.py @@ -372,7 +372,11 @@ class Marionette(object): or status == ErrorCodes.INVALID_XPATH_SELECTOR_RETURN_TYPER: raise InvalidSelectorException(message=message, status=status, stacktrace=stacktrace) elif status == ErrorCodes.MOVE_TARGET_OUT_OF_BOUNDS: - MoveTargetOutOfBoundsException(message=message, status=status, stacktrace=stacktrace) + raise MoveTargetOutOfBoundsException(message=message, status=status, stacktrace=stacktrace) + elif status == ErrorCodes.FRAME_SEND_NOT_INITIALIZED_ERROR: + raise FrameSendNotInitializedError(message=message, status=status, stacktrace=stacktrace) + elif status == ErrorCodes.FRAME_SEND_FAILURE_ERROR: + raise FrameSendFailureError(message=message, status=status, stacktrace=stacktrace) else: raise MarionetteException(message=message, status=status, stacktrace=stacktrace) raise MarionetteException(message=response, status=500) diff --git a/testing/marionette/marionette-actors.js b/testing/marionette/marionette-actors.js index 75e5458b8a80..b589072a2a51 100644 --- a/testing/marionette/marionette-actors.js +++ b/testing/marionette/marionette-actors.js @@ -150,6 +150,27 @@ function MarionetteRemoteFrame(windowId, frameId) { // persistent list of remote frames that Marionette has loaded a frame script in let remoteFrames = []; +/* + * Custom exceptions + */ +function FrameSendNotInitializedError(frame) { + this.code = 54; + this.frame = frame; + this.message = "Error sending message to frame (NS_ERROR_NOT_INITIALIZED)"; + this.toString = function() { + return this.message + " " + this.frame + "; frame has closed."; + } +} + +function FrameSendFailureError(frame) { + this.code = 55; + this.frame = frame; + this.message = "Error sending message to frame (NS_ERROR_FAILURE)"; + this.toString = function() { + return this.message + " " + this.frame + "; frame not responding."; + } +} + /** * This actor is responsible for all marionette API calls. It gets created * for each connection and manages all chrome and browser based calls. It @@ -203,11 +224,7 @@ MarionetteDriverActor.prototype = { switchToGlobalMessageManager: function MDA_switchToGlobalMM() { if (this.currentRemoteFrame !== null) { this.removeMessageManagerListeners(this.messageManager); - try { - // this can fail if the frame is already gone - this.sendAsync("sleepSession"); - } - catch(e) {} + this.sendAsync("sleepSession", null, null, true); } this.messageManager = this.globalMessageManager; this.currentRemoteFrame = null; @@ -221,15 +238,40 @@ MarionetteDriverActor.prototype = { * @param object values * Object to send to the listener */ - sendAsync: function MDA_sendAsync(name, values) { + sendAsync: function MDA_sendAsync(name, values, commandId, ignoreFailure) { + let success = true; + if (values instanceof Object && commandId) { + values.command_id = commandId; + } if (this.currentRemoteFrame !== null) { - this.messageManager.sendAsyncMessage( - "Marionette:" + name + this.currentRemoteFrame.targetFrameId, values); + try { + this.messageManager.sendAsyncMessage( + "Marionette:" + name + this.currentRemoteFrame.targetFrameId, values); + } + catch(e) { + if (!ignoreFailure) { + success = false; + let error = e; + switch(e.result) { + case Components.results.NS_ERROR_FAILURE: + error = new FrameSendFailureError(this.currentRemoteFrame); + break; + case Components.results.NS_ERROR_NOT_INITIALIZED: + error = new FrameSendNotInitializedError(this.currentRemoteFrame); + break; + default: + break; + } + code = error.hasOwnProperty('code') ? e.code : 500; + this.sendError(error.toString(), code, error.stack, commandId); + } + } } else { this.messageManager.broadcastAsyncMessage( "Marionette:" + name + this.curBrowser.curFrameId, values); } + return success; }, /** @@ -764,12 +806,15 @@ MarionetteDriverActor.prototype = { aRequest.newSandbox = true; } if (this.context == "content") { - this.sendAsync("executeScript", {value: aRequest.value, - args: aRequest.args, - newSandbox: aRequest.newSandbox, - timeout: timeout, - command_id: command_id, - specialPowers: aRequest.specialPowers}); + this.sendAsync("executeScript", + { + value: aRequest.value, + args: aRequest.args, + newSandbox: aRequest.newSandbox, + timeout: timeout, + specialPowers: aRequest.specialPowers + }, + command_id); return; } @@ -852,13 +897,16 @@ MarionetteDriverActor.prototype = { } } else { - this.sendAsync("executeJSScript", { value: aRequest.value, - args: aRequest.args, - newSandbox: aRequest.newSandbox, - async: aRequest.async, - timeout: timeout, - command_id: command_id, - specialPowers: aRequest.specialPowers }); + this.sendAsync("executeJSScript", + { + value: aRequest.value, + args: aRequest.args, + newSandbox: aRequest.newSandbox, + async: aRequest.async, + timeout: timeout, + specialPowers: aRequest.specialPowers + }, + command_id); } }, @@ -888,13 +936,16 @@ MarionetteDriverActor.prototype = { } if (this.context == "content") { - this.sendAsync("executeAsyncScript", {value: aRequest.value, - args: aRequest.args, - id: this.command_id, - newSandbox: aRequest.newSandbox, - timeout: timeout, - command_id: command_id, - specialPowers: aRequest.specialPowers}); + this.sendAsync("executeAsyncScript", + { + value: aRequest.value, + args: aRequest.args, + id: this.command_id, + newSandbox: aRequest.newSandbox, + timeout: timeout, + specialPowers: aRequest.specialPowers + }, + command_id); return; } @@ -994,7 +1045,7 @@ MarionetteDriverActor.prototype = { if (this.context != "chrome") { aRequest.command_id = command_id; aRequest.pageTimeout = this.pageTimeout; - this.sendAsync("goUrl", aRequest); + this.sendAsync("goUrl", aRequest, command_id); return; } @@ -1031,7 +1082,7 @@ MarionetteDriverActor.prototype = { this.sendResponse(this.getCurrentWindow().location.href, this.command_id); } else { - this.sendAsync("getUrl", {command_id: this.command_id}); + this.sendAsync("getUrl", {}, this.command_id); } }, @@ -1040,7 +1091,7 @@ MarionetteDriverActor.prototype = { */ getTitle: function MDA_getTitle() { this.command_id = this.getCommandId(); - this.sendAsync("getTitle", {command_id: this.command_id}); + this.sendAsync("getTitle", {}, this.command_id); }, /** @@ -1055,7 +1106,7 @@ MarionetteDriverActor.prototype = { this.sendResponse(pageSource, this.command_id); } else { - this.sendAsync("getPageSource", {command_id: this.command_id}); + this.sendAsync("getPageSource", {}, this.command_id); } }, @@ -1064,7 +1115,7 @@ MarionetteDriverActor.prototype = { */ goBack: function MDA_goBack() { this.command_id = this.getCommandId(); - this.sendAsync("goBack", {command_id: this.command_id}); + this.sendAsync("goBack", {}, this.command_id); }, /** @@ -1072,7 +1123,7 @@ MarionetteDriverActor.prototype = { */ goForward: function MDA_goForward() { this.command_id = this.getCommandId(); - this.sendAsync("goForward", {command_id: this.command_id}); + this.sendAsync("goForward", {}, this.command_id); }, /** @@ -1080,7 +1131,7 @@ MarionetteDriverActor.prototype = { */ refresh: function MDA_refresh() { this.command_id = this.getCommandId(); - this.sendAsync("refresh", {command_id: this.command_id}); + this.sendAsync("refresh", {}, this.command_id); }, /** @@ -1245,7 +1296,7 @@ MarionetteDriverActor.prototype = { this.switchToGlobalMessageManager(); } aRequest.command_id = command_id; - this.sendAsync("switchToFrame", aRequest); + this.sendAsync("switchToFrame", aRequest, command_id); } }, @@ -1267,8 +1318,9 @@ MarionetteDriverActor.prototype = { } } else { - this.sendAsync("setSearchTimeout", {value: aRequest.value, - command_id: this.command_id}); + this.sendAsync("setSearchTimeout", + { value: aRequest.value }, + this.command_id); } }, @@ -1318,10 +1370,13 @@ MarionetteDriverActor.prototype = { this.sendError("Not in Chrome", 500, null, this.command_id); } else { - this.sendAsync("singleTap", {value: serId, - corx: x, - cory: y, - command_id: this.command_id}); + this.sendAsync("singleTap", + { + value: serId, + corx: x, + cory: y + }, + this.command_id); } }, @@ -1340,10 +1395,13 @@ MarionetteDriverActor.prototype = { this.sendError("Not in Chrome", 500, null, this.command_id); } else { - this.sendAsync("doubleTap", {value: serId, - corx: x, - cory: y, - command_id: this.command_id}); + this.sendAsync("doubleTap", + { + value: serId, + corx: x, + cory: y + }, + this.command_id); } }, @@ -1362,10 +1420,13 @@ MarionetteDriverActor.prototype = { this.sendError("Not in Chrome", 500, null, this.command_id); } else { - this.sendAsync("press", {value: element, - corx: x, - cory: y, - command_id: this.command_id}); + this.sendAsync("press", + { + value: element, + corx: x, + cory: y + }, + this.command_id); } }, @@ -1383,9 +1444,12 @@ MarionetteDriverActor.prototype = { this.sendError("Not in Chrome", 500, null, this.command_id); } else { - this.sendAsync("cancelTouch", {value: element, - touchId: touchId, - command_id: this.command_id}); + this.sendAsync("cancelTouch", + { + value: element, + touchId: touchId + }, + this.command_id); } }, @@ -1405,11 +1469,14 @@ MarionetteDriverActor.prototype = { this.sendError("Not in Chrome", 500, null, this.command_id); } else { - this.sendAsync("release", {value: element, - touchId: touchId, - corx: x, - cory: y, - command_id: this.command_id}); + this.sendAsync("release", + { + value: element, + touchId: touchId, + corx: x, + cory: y + }, + this.command_id); } }, @@ -1425,9 +1492,12 @@ MarionetteDriverActor.prototype = { this.sendError("Not in Chrome", 500, null, this.command_id); } else { - this.sendAsync("actionChain", {chain: aRequest.chain, - nextId: aRequest.nextId, - command_id: this.command_id}); + this.sendAsync("actionChain", + { + chain: aRequest.chain, + nextId: aRequest.nextId + }, + this.command_id); } }, @@ -1446,9 +1516,12 @@ MarionetteDriverActor.prototype = { this.sendError("Not in Chrome", 500, null, this.command_id); } else { - this.sendAsync("multiAction", {value: aRequest.value, - maxlen: aRequest.max_length, - command_id: this.command_id}); + this.sendAsync("multiAction", + { + value: aRequest.value, + maxlen: aRequest.max_length + }, + this.command_id); } }, @@ -1480,10 +1553,13 @@ MarionetteDriverActor.prototype = { } } else { - this.sendAsync("findElementContent", {value: aRequest.value, - using: aRequest.using, - element: aRequest.element, - command_id: command_id}); + this.sendAsync("findElementContent", + { + value: aRequest.value, + using: aRequest.using, + element: aRequest.element + }, + command_id); } }, @@ -1514,10 +1590,13 @@ MarionetteDriverActor.prototype = { } } else { - this.sendAsync("findElementsContent", {value: aRequest.value, - using: aRequest.using, - element: aRequest.element, - command_id: command_id}); + this.sendAsync("findElementsContent", + { + value: aRequest.value, + using: aRequest.using, + element: aRequest.element + }, + command_id); } }, @@ -1526,7 +1605,7 @@ MarionetteDriverActor.prototype = { */ getActiveElement: function MDA_getActiveElement(){ let command_id = this.command_id = this.getCommandId(); - this.sendAsync("getActiveElement", {command_id: command_id}); + this.sendAsync("getActiveElement", {}, command_id); }, /** @@ -1563,8 +1642,9 @@ MarionetteDriverActor.prototype = { self.sendError("The frame closed during the click, recovering to allow further communications", 500, null, command_id); }; curWindow.addEventListener('mozbrowserclose', this.mozBrowserClose, true); - this.sendAsync("clickElement", {element: aRequest.element, - command_id: command_id}); + this.sendAsync("clickElement", + { element: aRequest.element }, + command_id); } }, @@ -1590,9 +1670,12 @@ MarionetteDriverActor.prototype = { } } else { - this.sendAsync("getElementAttribute", {element: aRequest.element, - name: aRequest.name, - command_id: command_id}); + this.sendAsync("getElementAttribute", + { + element: aRequest.element, + name: aRequest.name + }, + command_id); } }, @@ -1620,8 +1703,9 @@ MarionetteDriverActor.prototype = { } } else { - this.sendAsync("getElementText", {element: aRequest.element, - command_id: command_id}); + this.sendAsync("getElementText", + { element: aRequest.element }, + command_id); } }, @@ -1645,8 +1729,9 @@ MarionetteDriverActor.prototype = { } } else { - this.sendAsync("getElementTagName", {element: aRequest.element, - command_id: command_id}); + this.sendAsync("getElementTagName", + { element: aRequest.element }, + command_id); } }, @@ -1670,8 +1755,9 @@ MarionetteDriverActor.prototype = { } } else { - this.sendAsync("isElementDisplayed", {element:aRequest.element, - command_id: command_id}); + this.sendAsync("isElementDisplayed", + { element:aRequest.element }, + command_id); } }, @@ -1701,8 +1787,9 @@ MarionetteDriverActor.prototype = { } } else { - this.sendAsync("isElementEnabled", {element:aRequest.element, - command_id: command_id}); + this.sendAsync("isElementEnabled", + { element:aRequest.element }, + command_id); } }, @@ -1735,8 +1822,9 @@ MarionetteDriverActor.prototype = { } } else { - this.sendAsync("isElementSelected", {element:aRequest.element, - command_id: command_id}); + this.sendAsync("isElementSelected", + { element:aRequest.element }, + command_id); } }, @@ -1755,8 +1843,9 @@ MarionetteDriverActor.prototype = { } } else { - this.sendAsync("getElementSize", {element:aRequest.element, - command_id: command_id}); + this.sendAsync("getElementSize", + { element:aRequest.element }, + command_id); } }, @@ -1783,9 +1872,12 @@ MarionetteDriverActor.prototype = { } } else { - this.sendAsync("sendKeysToElement", {element:aRequest.element, - value: aRequest.value, - command_id: command_id}); + this.sendAsync("sendKeysToElement", + { + element:aRequest.element, + value: aRequest.value + }, + command_id); } }, @@ -1798,8 +1890,9 @@ MarionetteDriverActor.prototype = { this.command_id = this.getCommandId(); this.logRequest("setTestName", aRequest); this.testName = aRequest.value; - this.sendAsync("setTestName", {value: aRequest.value, - command_id: this.command_id}); + this.sendAsync("setTestName", + { value: aRequest.value }, + this.command_id); }, /** @@ -1829,15 +1922,17 @@ MarionetteDriverActor.prototype = { } } else { - this.sendAsync("clearElement", {element:aRequest.element, - command_id: command_id}); + this.sendAsync("clearElement", + { element:aRequest.element }, + command_id); } }, getElementPosition: function MDA_getElementPosition(aRequest) { this.command_id = this.getCommandId(); - this.sendAsync("getElementPosition", {element:aRequest.element, - command_id: this.command_id}); + this.sendAsync("getElementPosition", + { element:aRequest.element }, + this.command_id); }, /** @@ -1845,8 +1940,9 @@ MarionetteDriverActor.prototype = { */ addCookie: function MDA_addCookie(aRequest) { this.command_id = this.getCommandId(); - this.sendAsync("addCookie", {cookie:aRequest.cookie, - command_id: this.command_id}); + this.sendAsync("addCookie", + { cookie:aRequest.cookie }, + this.command_id); }, /** @@ -1854,7 +1950,7 @@ MarionetteDriverActor.prototype = { */ getAllCookies: function MDA_getAllCookies() { this.command_id = this.getCommandId(); - this.sendAsync("getAllCookies", {command_id: this.command_id}); + this.sendAsync("getAllCookies", {}, this.command_id); }, /** @@ -1862,7 +1958,7 @@ MarionetteDriverActor.prototype = { */ deleteAllCookies: function MDA_deleteAllCookies() { this.command_id = this.getCommandId(); - this.sendAsync("deleteAllCookies", {command_id: this.command_id}); + this.sendAsync("deleteAllCookies", {}, this.command_id); }, /** @@ -1870,8 +1966,9 @@ MarionetteDriverActor.prototype = { */ deleteCookie: function MDA_deleteCookie(aRequest) { this.command_id = this.getCommandId(); - this.sendAsync("deleteCookie", {name:aRequest.name, - command_id: this.command_id}); + this.sendAsync("deleteCookie", + { name:aRequest.name }, + this.command_id); }, /** @@ -1970,7 +2067,7 @@ MarionetteDriverActor.prototype = { */ getAppCacheStatus: function MDA_getAppCacheStatus(aRequest) { this.command_id = this.getCommandId(); - this.sendAsync("getAppCacheStatus", {command_id: this.command_id}); + this.sendAsync("getAppCacheStatus", {}, this.command_id); }, _emu_cb_id: 0, @@ -1988,7 +2085,7 @@ MarionetteDriverActor.prototype = { emulatorCmdResult: function emulatorCmdResult(message) { if (this.context != "chrome") { - this.sendAsync("emulatorCmdResult", message); + this.sendAsync("emulatorCmdResult", message, -1); return; } @@ -2031,8 +2128,9 @@ MarionetteDriverActor.prototype = { this.sendOk(command_id); } else { - this.sendAsync("importScript", {script: aRequest.script, - command_id: command_id}); + this.sendAsync("importScript", + { script: aRequest.script }, + command_id); } }, @@ -2042,9 +2140,12 @@ MarionetteDriverActor.prototype = { */ screenShot: function MDA_saveScreenshot(aRequest) { this.command_id = this.getCommandId(); - this.sendAsync("screenShot", {element: aRequest.element, - highlights: aRequest.highlights, - command_id: this.command_id}); + this.sendAsync("screenShot", + { + element: aRequest.element, + highlights: aRequest.highlights + }, + this.command_id); }, /** @@ -2148,11 +2249,12 @@ MarionetteDriverActor.prototype = { // XXX: Should have a better way of determining that this message // is from a remote frame. this.currentRemoteFrame.targetFrameId = this.generateFrameId(message.json.value); - this.sendAsync( - "setState", - {scriptTimeout: this.scriptTimeout, - searchTimeout: this.curBrowser.elementManager.searchTimeout, - command_id: this.currentRemoteFrame.command_id}); + this.sendAsync("setState", + { + scriptTimeout: this.scriptTimeout, + searchTimeout: this.curBrowser.elementManager.searchTimeout + }, + this.currentRemoteFrame.command_id); } let browserType; @@ -2169,7 +2271,11 @@ MarionetteDriverActor.prototype = { this.curBrowser.elementManager.seenItems[reg.id] = Cu.getWeakReference(listenerWindow); //add to seenItems reg.importedScripts = this.importedScripts.path; if (nullPrevious && (this.curBrowser.curFrameId != null)) { - this.sendAsync("newSession", {B2G: (appName == "B2G")}); + if (!this.sendAsync("newSession", + { B2G: (appName == "B2G") }, + this.newSessionCommandId)) { + return; + } if (this.curBrowser.newSession) { this.sendResponse(reg.id, this.newSessionCommandId); this.newSessionCommandId = null; From d602676c914c648f33bde737db7a0f09a0bfdb37 Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Mon, 15 Apr 2013 19:50:57 +1000 Subject: [PATCH 29/29] Bug 843917 - Test. --- layout/svg/crashtests/843917-1.svg | 19 +++++++++++++++++++ layout/svg/crashtests/crashtests.list | 1 + 2 files changed, 20 insertions(+) create mode 100644 layout/svg/crashtests/843917-1.svg diff --git a/layout/svg/crashtests/843917-1.svg b/layout/svg/crashtests/843917-1.svg new file mode 100644 index 000000000000..55cf7ab1867a --- /dev/null +++ b/layout/svg/crashtests/843917-1.svg @@ -0,0 +1,19 @@ + + + + + + a𞠯 + + + + + diff --git a/layout/svg/crashtests/crashtests.list b/layout/svg/crashtests/crashtests.list index e26d18c13b70..fb851f123d3f 100644 --- a/layout/svg/crashtests/crashtests.list +++ b/layout/svg/crashtests/crashtests.list @@ -157,6 +157,7 @@ load 842009-1.svg load 842630-1.svg load 842909-1.svg load 843072-1.svg +load 843917-1.svg load 847139-1.svg load 849688-1.svg load 849688-2.svg