SVGStyleElement.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "mozilla/dom/Element.h"
  6. #include "mozilla/dom/SVGStyleElement.h"
  7. #include "nsContentUtils.h"
  8. #include "mozilla/dom/SVGStyleElementBinding.h"
  9. NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT(Style)
  10. namespace mozilla {
  11. namespace dom {
  12. JSObject*
  13. SVGStyleElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
  14. {
  15. return SVGStyleElementBinding::Wrap(aCx, this, aGivenProto);
  16. }
  17. //----------------------------------------------------------------------
  18. // nsISupports methods
  19. NS_IMPL_ADDREF_INHERITED(SVGStyleElement, SVGStyleElementBase)
  20. NS_IMPL_RELEASE_INHERITED(SVGStyleElement, SVGStyleElementBase)
  21. NS_INTERFACE_TABLE_HEAD_CYCLE_COLLECTION_INHERITED(SVGStyleElement)
  22. NS_INTERFACE_TABLE_INHERITED(SVGStyleElement,
  23. nsIStyleSheetLinkingElement,
  24. nsIMutationObserver)
  25. NS_INTERFACE_TABLE_TAIL_INHERITING(SVGStyleElementBase)
  26. NS_IMPL_CYCLE_COLLECTION_CLASS(SVGStyleElement)
  27. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SVGStyleElement,
  28. SVGStyleElementBase)
  29. tmp->nsStyleLinkElement::Traverse(cb);
  30. NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
  31. NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SVGStyleElement,
  32. SVGStyleElementBase)
  33. tmp->nsStyleLinkElement::Unlink();
  34. NS_IMPL_CYCLE_COLLECTION_UNLINK_END
  35. //----------------------------------------------------------------------
  36. // Implementation
  37. SVGStyleElement::SVGStyleElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
  38. : SVGStyleElementBase(aNodeInfo)
  39. {
  40. AddMutationObserver(this);
  41. }
  42. SVGStyleElement::~SVGStyleElement()
  43. {
  44. }
  45. //----------------------------------------------------------------------
  46. // nsIDOMNode methods
  47. NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGStyleElement)
  48. //----------------------------------------------------------------------
  49. // nsIContent methods
  50. nsresult
  51. SVGStyleElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
  52. nsIContent* aBindingParent,
  53. bool aCompileEventHandlers)
  54. {
  55. nsresult rv = SVGStyleElementBase::BindToTree(aDocument, aParent,
  56. aBindingParent,
  57. aCompileEventHandlers);
  58. NS_ENSURE_SUCCESS(rv, rv);
  59. void (SVGStyleElement::*update)() = &SVGStyleElement::UpdateStyleSheetInternal;
  60. nsContentUtils::AddScriptRunner(NewRunnableMethod(this, update));
  61. return rv;
  62. }
  63. void
  64. SVGStyleElement::UnbindFromTree(bool aDeep, bool aNullParent)
  65. {
  66. nsCOMPtr<nsIDocument> oldDoc = GetUncomposedDoc();
  67. ShadowRoot* oldShadow = GetContainingShadow();
  68. SVGStyleElementBase::UnbindFromTree(aDeep, aNullParent);
  69. UpdateStyleSheetInternal(oldDoc, oldShadow);
  70. }
  71. nsresult
  72. SVGStyleElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
  73. nsIAtom* aPrefix, const nsAString& aValue,
  74. bool aNotify)
  75. {
  76. nsresult rv = SVGStyleElementBase::SetAttr(aNameSpaceID, aName, aPrefix,
  77. aValue, aNotify);
  78. if (NS_SUCCEEDED(rv) && aNameSpaceID == kNameSpaceID_None) {
  79. if (aName == nsGkAtoms::title ||
  80. aName == nsGkAtoms::media ||
  81. aName == nsGkAtoms::type) {
  82. UpdateStyleSheetInternal(nullptr, nullptr, true);
  83. } else if (aName == nsGkAtoms::scoped) {
  84. UpdateStyleSheetScopedness(true);
  85. }
  86. }
  87. return rv;
  88. }
  89. nsresult
  90. SVGStyleElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
  91. bool aNotify)
  92. {
  93. nsresult rv = SVGStyleElementBase::UnsetAttr(aNameSpaceID, aAttribute,
  94. aNotify);
  95. if (NS_SUCCEEDED(rv) && aNameSpaceID == kNameSpaceID_None) {
  96. if (aAttribute == nsGkAtoms::title ||
  97. aAttribute == nsGkAtoms::media ||
  98. aAttribute == nsGkAtoms::type) {
  99. UpdateStyleSheetInternal(nullptr, nullptr, true);
  100. } else if (aAttribute == nsGkAtoms::scoped) {
  101. UpdateStyleSheetScopedness(false);
  102. }
  103. }
  104. return rv;
  105. }
  106. bool
  107. SVGStyleElement::ParseAttribute(int32_t aNamespaceID,
  108. nsIAtom* aAttribute,
  109. const nsAString& aValue,
  110. nsAttrValue& aResult)
  111. {
  112. if (aNamespaceID == kNameSpaceID_None &&
  113. aAttribute == nsGkAtoms::crossorigin) {
  114. ParseCORSValue(aValue, aResult);
  115. return true;
  116. }
  117. return SVGStyleElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue,
  118. aResult);
  119. }
  120. //----------------------------------------------------------------------
  121. // nsIMutationObserver methods
  122. void
  123. SVGStyleElement::CharacterDataChanged(nsIDocument* aDocument,
  124. nsIContent* aContent,
  125. CharacterDataChangeInfo* aInfo)
  126. {
  127. ContentChanged(aContent);
  128. }
  129. void
  130. SVGStyleElement::ContentAppended(nsIDocument* aDocument,
  131. nsIContent* aContainer,
  132. nsIContent* aFirstNewContent,
  133. int32_t aNewIndexInContainer)
  134. {
  135. ContentChanged(aContainer);
  136. }
  137. void
  138. SVGStyleElement::ContentInserted(nsIDocument* aDocument,
  139. nsIContent* aContainer,
  140. nsIContent* aChild,
  141. int32_t aIndexInContainer)
  142. {
  143. ContentChanged(aChild);
  144. }
  145. void
  146. SVGStyleElement::ContentRemoved(nsIDocument* aDocument,
  147. nsIContent* aContainer,
  148. nsIContent* aChild,
  149. int32_t aIndexInContainer,
  150. nsIContent* aPreviousSibling)
  151. {
  152. ContentChanged(aChild);
  153. }
  154. void
  155. SVGStyleElement::ContentChanged(nsIContent* aContent)
  156. {
  157. if (nsContentUtils::IsInSameAnonymousTree(this, aContent)) {
  158. UpdateStyleSheetInternal(nullptr, nullptr);
  159. }
  160. }
  161. //----------------------------------------------------------------------
  162. void
  163. SVGStyleElement::GetXmlspace(nsAString & aXmlspace)
  164. {
  165. GetAttr(kNameSpaceID_XML, nsGkAtoms::space, aXmlspace);
  166. }
  167. void
  168. SVGStyleElement::SetXmlspace(const nsAString & aXmlspace, ErrorResult& rv)
  169. {
  170. rv = SetAttr(kNameSpaceID_XML, nsGkAtoms::space, aXmlspace, true);
  171. }
  172. void
  173. SVGStyleElement::GetMedia(nsAString & aMedia)
  174. {
  175. GetAttr(kNameSpaceID_None, nsGkAtoms::media, aMedia);
  176. }
  177. void
  178. SVGStyleElement::SetMedia(const nsAString& aMedia, ErrorResult& rv)
  179. {
  180. rv = SetAttr(kNameSpaceID_None, nsGkAtoms::media, aMedia, true);
  181. }
  182. bool
  183. SVGStyleElement::Scoped() const
  184. {
  185. return GetBoolAttr(nsGkAtoms::scoped);
  186. }
  187. void
  188. SVGStyleElement::SetScoped(bool aScoped, ErrorResult& rv)
  189. {
  190. rv = SetBoolAttr(nsGkAtoms::scoped, aScoped);
  191. }
  192. void
  193. SVGStyleElement::GetType(nsAString & aType)
  194. {
  195. GetAttr(kNameSpaceID_None, nsGkAtoms::type, aType);
  196. }
  197. void
  198. SVGStyleElement::SetType(const nsAString& aType, ErrorResult& rv)
  199. {
  200. rv = SetAttr(kNameSpaceID_None, nsGkAtoms::type, aType, true);
  201. }
  202. void
  203. SVGStyleElement::GetTitle(nsAString & aTitle)
  204. {
  205. GetAttr(kNameSpaceID_None, nsGkAtoms::title, aTitle);
  206. }
  207. void
  208. SVGStyleElement::SetTitle(const nsAString& aTitle, ErrorResult& rv)
  209. {
  210. rv = SetAttr(kNameSpaceID_None, nsGkAtoms::title, aTitle, true);
  211. }
  212. //----------------------------------------------------------------------
  213. // nsStyleLinkElement methods
  214. already_AddRefed<nsIURI>
  215. SVGStyleElement::GetStyleSheetURL(bool* aIsInline)
  216. {
  217. *aIsInline = true;
  218. return nullptr;
  219. }
  220. void
  221. SVGStyleElement::GetStyleSheetInfo(nsAString& aTitle,
  222. nsAString& aType,
  223. nsAString& aMedia,
  224. bool* aIsScoped,
  225. bool* aIsAlternate,
  226. bool* aIsExplicitlyEnabled)
  227. {
  228. *aIsAlternate = false;
  229. *aIsExplicitlyEnabled = false;
  230. nsAutoString title;
  231. GetAttr(kNameSpaceID_None, nsGkAtoms::title, title);
  232. title.CompressWhitespace();
  233. aTitle.Assign(title);
  234. GetAttr(kNameSpaceID_None, nsGkAtoms::media, aMedia);
  235. // The SVG spec is formulated in terms of the CSS2 spec,
  236. // which specifies that media queries are case insensitive.
  237. nsContentUtils::ASCIIToLower(aMedia);
  238. GetAttr(kNameSpaceID_None, nsGkAtoms::type, aType);
  239. if (aType.IsEmpty()) {
  240. aType.AssignLiteral("text/css");
  241. }
  242. *aIsScoped = HasAttr(kNameSpaceID_None, nsGkAtoms::scoped);
  243. return;
  244. }
  245. CORSMode
  246. SVGStyleElement::GetCORSMode() const
  247. {
  248. return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin));
  249. }
  250. } // namespace dom
  251. } // namespace mozilla