From 21f47f8140ba27114a6ab0e23c23c21751516c57 Mon Sep 17 00:00:00 2001 From: Ryo HIKOSAKA Date: Tue, 18 Feb 2014 10:24:40 +0900 Subject: [PATCH] Bug 949435, part 3 - Implement an SVGIFrameELement class. r=bz,jwatt for the webidl, r=longsonr for the rest --- content/svg/content/src/SVGIFrameElement.cpp | 344 +++++++++++++++++++ content/svg/content/src/SVGIFrameElement.h | 110 ++++++ content/svg/content/src/SVGTagList.h | 1 + content/svg/content/src/moz.build | 2 + dom/webidl/SVGIFrameElement.webidl | 47 +++ dom/webidl/moz.build | 1 + modules/libpref/src/init/all.js | 6 + 7 files changed, 511 insertions(+) create mode 100644 content/svg/content/src/SVGIFrameElement.cpp create mode 100644 content/svg/content/src/SVGIFrameElement.h create mode 100644 dom/webidl/SVGIFrameElement.webidl diff --git a/content/svg/content/src/SVGIFrameElement.cpp b/content/svg/content/src/SVGIFrameElement.cpp new file mode 100644 index 000000000000..a8ae129546c3 --- /dev/null +++ b/content/svg/content/src/SVGIFrameElement.cpp @@ -0,0 +1,344 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "SVGIFrameElement.h" + +#include "GeckoProfiler.h" +#include "mozilla/ArrayUtils.h" +#include "nsCOMPtr.h" +#include "nsGkAtoms.h" +#include "mozilla/dom/SVGDocumentBinding.h" +#include "mozilla/dom/SVGIFrameElementBinding.h" +#include "mozilla/dom/SVGMatrix.h" +#include "mozilla/dom/SVGSVGElement.h" +#include "mozilla/Preferences.h" +#include "nsStyleConsts.h" + +NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT_CHECK_PARSER(IFrame) + +namespace mozilla { +namespace dom { + +JSObject* +SVGIFrameElement::WrapNode(JSContext *aCx) +{ + return SVGIFrameElementBinding::Wrap(aCx, this); +} + +//--------------------- IFrame ------------------------ + +nsSVGElement::LengthInfo SVGIFrameElement::sLengthInfo[4] = +{ + { &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X }, + { &nsGkAtoms::y, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y }, + { &nsGkAtoms::width, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X }, + { &nsGkAtoms::height, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y } +}; + +//---------------------------------------------------------------------- +// nsISupports methods +NS_IMPL_ISUPPORTS_INHERITED(SVGIFrameElement, SVGIFrameElementBase, + nsIFrameLoaderOwner, + nsIDOMNode, nsIDOMElement, + nsIDOMSVGElement) +//---------------------------------------------------------------------- +// Implementation + +SVGIFrameElement::SVGIFrameElement(already_AddRefed& aNodeInfo, + FromParser aFromParser) + : SVGIFrameElementBase(aNodeInfo) + , nsElementFrameLoaderOwner(aFromParser) +{ +} + +//---------------------------------------------------------------------- +// nsSVGElement methods + +/* virtual */ gfxMatrix +SVGIFrameElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix, + TransformTypes aWhich) const +{ + NS_ABORT_IF_FALSE(aWhich != eChildToUserSpace || aMatrix.IsIdentity(), + "Skipping eUserSpaceToParent transforms makes no sense"); + + // 'transform' attribute: + gfxMatrix fromUserSpace = + SVGGraphicsElement::PrependLocalTransformsTo(aMatrix, aWhich); + if (aWhich == eUserSpaceToParent) { + return fromUserSpace; + } + // our 'x' and 'y' attributes: + float x, y; + const_cast(this)-> + GetAnimatedLengthValues(&x, &y, nullptr); + gfxMatrix toUserSpace = gfxMatrix().Translate(gfxPoint(x, y)); + if (aWhich == eChildToUserSpace) { + return toUserSpace; + } + NS_ABORT_IF_FALSE(aWhich == eAllTransforms, "Unknown TransformTypes"); + return toUserSpace * fromUserSpace; +} + + +//---------------------------------------------------------------------- +// nsIDOMNode methods + +nsresult +SVGIFrameElement::Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const +{ + *aResult = nullptr; + already_AddRefed ni = nsCOMPtr(aNodeInfo).forget(); + SVGIFrameElement *it = new SVGIFrameElement(ni, NOT_FROM_PARSER); + + nsCOMPtr kungFuDeathGrip = it; + nsresult rv1 = it->Init(); + nsresult rv2 = const_cast(this)->CopyInnerTo(it); + if (NS_SUCCEEDED(rv1) && NS_SUCCEEDED(rv2)) { + kungFuDeathGrip.swap(*aResult); + } + + return NS_FAILED(rv1) ? rv1 : rv2; +} + +//---------------------------------------------------------------------- +// nsSVGElement methods + +nsSVGElement::LengthAttributesInfo +SVGIFrameElement::GetLengthInfo() +{ + return LengthAttributesInfo(mLengthAttributes, sLengthInfo, + ArrayLength(sLengthInfo)); +} + +SVGAnimatedPreserveAspectRatio * +SVGIFrameElement::GetPreserveAspectRatio() +{ + return &mPreserveAspectRatio; +} + +//---------------------------------------------------------------------- +// nsIDOMSVGIFrameElement methods: + +already_AddRefed +SVGIFrameElement::X() +{ + return mLengthAttributes[ATTR_X].ToDOMAnimatedLength(this); +} + +already_AddRefed +SVGIFrameElement::Y() +{ + return mLengthAttributes[ATTR_Y].ToDOMAnimatedLength(this); +} + +already_AddRefed +SVGIFrameElement::Width() +{ + return mLengthAttributes[ATTR_WIDTH].ToDOMAnimatedLength(this); +} + +already_AddRefed +SVGIFrameElement::Height() +{ + return mLengthAttributes[ATTR_HEIGHT].ToDOMAnimatedLength(this); +} + +already_AddRefed +SVGIFrameElement::PreserveAspectRatio() +{ + nsRefPtr ratio; + mPreserveAspectRatio.ToDOMAnimatedPreserveAspectRatio(getter_AddRefs(ratio), + this); + return ratio.forget(); +} + +void +SVGIFrameElement::GetName(DOMString& name) +{ + GetAttr(kNameSpaceID_None, nsGkAtoms::name, name); +} + +void +SVGIFrameElement::GetSrc(DOMString& src) +{ + GetAttr(kNameSpaceID_None, nsGkAtoms::src, src); +} + +void +SVGIFrameElement::GetSrcdoc(DOMString& srcdoc) +{ + GetAttr(kNameSpaceID_None, nsGkAtoms::srcdoc, srcdoc); +} + +already_AddRefed +SVGIFrameElement::Sandbox() +{ + return GetTokenList(nsGkAtoms::sandbox); +} + +bool +SVGIFrameElement::ParseAttribute(int32_t aNamespaceID, + nsIAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult) +{ + if (aNamespaceID == kNameSpaceID_None) { + if (aAttribute == nsGkAtoms::sandbox) { + aResult.ParseAtomArray(aValue); + return true; + } + } + return SVGIFrameElementBase::ParseAttribute(aNamespaceID, aAttribute, + aValue, aResult); +} + +nsresult +SVGIFrameElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName, + nsIAtom* aPrefix, const nsAString& aValue, + bool aNotify) +{ + nsresult rv = nsSVGElement::SetAttr(aNameSpaceID, aName, aPrefix, + aValue, aNotify); + NS_ENSURE_SUCCESS(rv, rv); + + if (aNameSpaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::src && + !HasAttr(kNameSpaceID_None,nsGkAtoms::srcdoc)) { + // Don't propagate error here. The attribute was successfully set, that's + // what we should reflect. + LoadSrc(); + } + if (aName == nsGkAtoms::srcdoc) { + // Don't propagate error here. The attribute was successfully set, that's + // what we should reflect. + LoadSrc(); + } + } + return NS_OK; +} + +nsresult +SVGIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, + const nsAttrValue* aValue, + bool aNotify) +{ + if (aNameSpaceID == kNameSpaceID_None) { + if (aName == nsGkAtoms::sandbox && mFrameLoader) { + // If we have an nsFrameLoader, apply the new sandbox flags. + // Since this is called after the setter, the sandbox flags have + // alreay been updated. + mFrameLoader->ApplySandboxFlags(GetSandboxFlags()); + } + } + return nsSVGElement::AfterSetAttr(aNameSpaceID, aName, aValue, aNotify); +} + +nsresult +SVGIFrameElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, + bool aNotify) +{ + // Invoke on the superclass. + nsresult rv = nsSVGElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify); + NS_ENSURE_SUCCESS(rv, rv); + + if (aNameSpaceID == kNameSpaceID_None) { + if (aAttribute == nsGkAtoms::srcdoc) { + // Fall back to the src attribute, if any + LoadSrc(); + } + } + + return NS_OK; +} + +uint32_t +SVGIFrameElement::GetSandboxFlags() +{ + const nsAttrValue* sandboxAttr = GetParsedAttr(nsGkAtoms::sandbox); + return nsContentUtils::ParseSandboxAttributeToFlags(sandboxAttr); +} + +nsresult +SVGIFrameElement::BindToTree(nsIDocument* aDocument, + nsIContent* aParent, + nsIContent* aBindingParent, + bool aCompileEventHandlers) +{ + nsresult rv = nsSVGElement::BindToTree(aDocument, aParent, + aBindingParent, + aCompileEventHandlers); + NS_ENSURE_SUCCESS(rv, rv); + + if (aDocument) { + NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(), + "Missing a script blocker!"); + + PROFILER_LABEL("SVGIFrameElement", "BindToTree"); + + // We're in a document now. Kick off the frame load. + LoadSrc(); + + if (HasAttr(kNameSpaceID_None, nsGkAtoms::sandbox)) { + if (mFrameLoader) { + mFrameLoader->ApplySandboxFlags(GetSandboxFlags()); + } + } + } + + // We're now in document and scripts may move us, so clear + // the mNetworkCreated flag. + mNetworkCreated = false; + return rv; +} + +void +SVGIFrameElement::UnbindFromTree(bool aDeep, bool aNullParent) +{ + if (mFrameLoader) { + // This iframe is being taken out of the document, destroy the + // iframe's frame loader (doing that will tear down the window in + // this iframe). + // XXXbz we really want to only partially destroy the frame + // loader... we don't want to tear down the docshell. Food for + // later bug. + mFrameLoader->Destroy(); + mFrameLoader = nullptr; + } + + nsSVGElement::UnbindFromTree(aDeep, aNullParent); +} + +void +SVGIFrameElement::DestroyContent() +{ + if (mFrameLoader) { + mFrameLoader->Destroy(); + mFrameLoader = nullptr; + } + + nsSVGElement::DestroyContent(); +} + +nsresult +SVGIFrameElement::CopyInnerTo(Element* aDest) +{ + nsresult rv = nsSVGElement::CopyInnerTo(aDest); + NS_ENSURE_SUCCESS(rv, rv); + + nsIDocument* doc = aDest->OwnerDoc(); + if (doc->IsStaticDocument() && mFrameLoader) { + SVGIFrameElement* dest = + static_cast(aDest); + nsFrameLoader* fl = nsFrameLoader::Create(dest, false); + NS_ENSURE_STATE(fl); + dest->mFrameLoader = fl; + static_cast(mFrameLoader.get())->CreateStaticClone(fl); + } + + return rv; +} + +} // namespace dom +} // namespace mozilla diff --git a/content/svg/content/src/SVGIFrameElement.h b/content/svg/content/src/SVGIFrameElement.h new file mode 100644 index 000000000000..fbf6e4cf5ae4 --- /dev/null +++ b/content/svg/content/src/SVGIFrameElement.h @@ -0,0 +1,110 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/dom/DOMString.h" +#include "mozilla/dom/FromParser.h" +#include "mozilla/dom/SVGGraphicsElement.h" +#include "nsContentUtils.h" +#include "nsDOMSettableTokenList.h" +#include "nsFrameLoader.h" +#include "nsElementFrameLoaderOwner.h" +#include "nsIDocument.h" +#include "nsIDOMDocument.h" +#include "nsIDOMEventListener.h" +#include "nsIFrameLoader.h" +#include "nsIWebNavigation.h" +#include "nsSVGElement.h" +#include "nsSVGLength2.h" +#include "SVGAnimatedPreserveAspectRatio.h" + +nsresult NS_NewSVGIFrameElement(nsIContent **aResult, + already_AddRefed&& aNodeInfo, + mozilla::dom::FromParser aFromParser); + +typedef mozilla::dom::SVGGraphicsElement SVGIFrameElementBase; + +class nsSVGIFrameFrame; + +namespace mozilla { +namespace dom { +class DOMSVGAnimatedPreserveAspectRatio; + +class SVGIFrameElement MOZ_FINAL : public SVGIFrameElementBase, + public nsElementFrameLoaderOwner +{ + friend class ::nsSVGIFrameFrame; + friend nsresult (::NS_NewSVGIFrameElement(nsIContent **aResult, + already_AddRefed&& aNodeInfo, + mozilla::dom::FromParser aFromParser)); + + SVGIFrameElement(already_AddRefed& aNodeInfo, + mozilla::dom::FromParser aFromParser); + virtual JSObject* WrapNode(JSContext *aCx) MOZ_OVERRIDE; + +public: + // interface + NS_DECL_ISUPPORTS_INHERITED + + // nsSVGElement specializations: + virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix, + TransformTypes aWhich = eAllTransforms) const MOZ_OVERRIDE; + + // nsIContent + virtual bool ParseAttribute(int32_t aNamespaceID, + nsIAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult) MOZ_OVERRIDE; + virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, + nsIContent* aBindingParent, + bool aCompileEventHandlers) MOZ_OVERRIDE; + virtual void UnbindFromTree(bool aDeep = true, + bool aNullParent = true) MOZ_OVERRIDE; + virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName, + nsIAtom* aPrefix, const nsAString& aValue, + bool aNotify) MOZ_OVERRIDE; + virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, + const nsAttrValue* aValue, + bool aNotify) MOZ_OVERRIDE; + virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute, + bool aNotify) MOZ_OVERRIDE; + + virtual void DestroyContent() MOZ_OVERRIDE; + nsresult CopyInnerTo(mozilla::dom::Element* aDest); + virtual nsresult Clone(nsINodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE; + + // WebIDL + already_AddRefed X(); + already_AddRefed Y(); + already_AddRefed Width(); + already_AddRefed Height(); + already_AddRefed PreserveAspectRatio(); + void GetName(DOMString& name); + void GetSrc(DOMString& src); + void GetSrcdoc(DOMString& srcdoc); + already_AddRefed Sandbox(); + using nsElementFrameLoaderOwner::GetContentDocument; + using nsElementFrameLoaderOwner::GetContentWindow; + + // Parses a sandbox attribute and converts it to the set of flags used internally. + // Returns 0 if there isn't the attribute. + uint32_t GetSandboxFlags(); + +private: + virtual LengthAttributesInfo GetLengthInfo(); + virtual SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio(); + virtual mozilla::dom::Element* ThisFrameElement() MOZ_OVERRIDE + { + return this; + } + + enum { ATTR_X, ATTR_Y, ATTR_WIDTH, ATTR_HEIGHT }; + nsSVGLength2 mLengthAttributes[4]; + static LengthInfo sLengthInfo[4]; + + SVGAnimatedPreserveAspectRatio mPreserveAspectRatio; +}; + +} // namespace dom +} // namespace mozilla diff --git a/content/svg/content/src/SVGTagList.h b/content/svg/content/src/SVGTagList.h index 984f74b196d7..957817329e52 100644 --- a/content/svg/content/src/SVGTagList.h +++ b/content/svg/content/src/SVGTagList.h @@ -65,6 +65,7 @@ SVG_TAG(feTurbulence, FETurbulence) SVG_TAG(filter, Filter) SVG_TAG(foreignObject, ForeignObject) SVG_TAG(g, G) +SVG_FROM_PARSER_TAG(iframe, IFrame) SVG_TAG(image, Image) SVG_TAG(line, Line) SVG_TAG(linearGradient, LinearGradient) diff --git a/content/svg/content/src/moz.build b/content/svg/content/src/moz.build index 5a0dba450162..8c0e76336dae 100644 --- a/content/svg/content/src/moz.build +++ b/content/svg/content/src/moz.build @@ -63,6 +63,7 @@ EXPORTS.mozilla.dom += [ 'SVGGElement.h', 'SVGGradientElement.h', 'SVGGraphicsElement.h', + 'SVGIFrameElement.h', 'SVGImageElement.h', 'SVGIRect.h', 'SVGLineElement.h', @@ -188,6 +189,7 @@ UNIFIED_SOURCES += [ 'SVGGElement.cpp', 'SVGGradientElement.cpp', 'SVGGraphicsElement.cpp', + 'SVGIFrameElement.cpp', 'SVGImageElement.cpp', 'SVGIntegerPairSMILType.cpp', 'SVGLength.cpp', diff --git a/dom/webidl/SVGIFrameElement.webidl b/dom/webidl/SVGIFrameElement.webidl new file mode 100644 index 000000000000..578035f94c8b --- /dev/null +++ b/dom/webidl/SVGIFrameElement.webidl @@ -0,0 +1,47 @@ +/* -*- 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/. + * + * The origin of this IDL file is + * http://www.w3.org/Graphics/SVG/WG/wiki/Proposals/IFrame_Like_Syntax#5.12.14_Interface_SVGIFrameElement + * but based + * http://www.whatwg.org/specs/web-apps/current-work/#the-iframe-element + * + * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and + * Opera Software ASA. You are granted a license to use, reproduce + * and create derivative works of this document. + * Copyright © 2013 KDDI, Inc. + */ + +[Pref="svg.svg-iframe.enabled"] +interface SVGIFrameElement : SVGGraphicsElement { + [Constant] + readonly attribute SVGAnimatedLength x; + [Constant] + readonly attribute SVGAnimatedLength y; + [Constant] + readonly attribute SVGAnimatedLength width; + [Constant] + readonly attribute SVGAnimatedLength height; + [Constant] + readonly attribute SVGAnimatedPreserveAspectRatio preserveAspectRatio; + + [Constant] + readonly attribute DOMString name; + [Constant] + readonly attribute DOMString src; + [Constant] + readonly attribute DOMString srcdoc; + [PutForwards=value] + readonly attribute DOMSettableTokenList sandbox; + + // not implemented yet + //[Constant] + //readonly attribute SVGAnimatedBoolean seamless; + + readonly attribute Document? contentDocument; + readonly attribute WindowProxy? contentWindow; + // not implemented yet + //readonly attribute SVGAnimatedBoolean postpone; +}; diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index 23a5bcb1bdf2..e5c77fd7644e 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -370,6 +370,7 @@ WEBIDL_FILES = [ 'SVGGElement.webidl', 'SVGGradientElement.webidl', 'SVGGraphicsElement.webidl', + 'SVGIFrameElement.webidl', 'SVGImageElement.webidl', 'SVGLength.webidl', 'SVGLengthList.webidl', diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 89fb351657ec..6bd0ca4a551c 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -2067,6 +2067,12 @@ pref("svg.marker-improvements.enabled", false); pref("svg.marker-improvements.enabled", true); #endif +#ifdef RELEASE_BUILD +pref("svg.svg-iframe.enabled", false); +#else +pref("svg.svg-iframe.enabled", false); +#endif + // Default font types and sizes by locale pref("font.default.ar", "sans-serif");