nsDOMCSSAttrDeclaration.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /* -*- Mode: C++; tab-width: 2; 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. /* DOM object for element.style */
  6. #include "nsDOMCSSAttrDeclaration.h"
  7. #include "mozilla/css/Declaration.h"
  8. #include "mozilla/css/StyleRule.h"
  9. #include "mozilla/dom/Element.h"
  10. #include "mozilla/dom/DocGroup.h"
  11. #include "nsIDocument.h"
  12. #include "nsIDOMMutationEvent.h"
  13. #include "nsIURI.h"
  14. #include "nsNodeUtils.h"
  15. #include "nsWrapperCacheInlines.h"
  16. #include "nsIFrame.h"
  17. #include "ActiveLayerTracker.h"
  18. #include "ServoDeclarationBlock.h"
  19. #include "StyleSetHandle.h"
  20. #include "DeclarationBlockInlines.h"
  21. using namespace mozilla;
  22. using namespace mozilla::dom;
  23. nsDOMCSSAttributeDeclaration::nsDOMCSSAttributeDeclaration(dom::Element* aElement,
  24. bool aIsSMILOverride)
  25. : mElement(aElement)
  26. , mIsSMILOverride(aIsSMILOverride)
  27. {
  28. MOZ_COUNT_CTOR(nsDOMCSSAttributeDeclaration);
  29. NS_ASSERTION(aElement, "Inline style for a NULL element?");
  30. }
  31. nsDOMCSSAttributeDeclaration::~nsDOMCSSAttributeDeclaration()
  32. {
  33. MOZ_COUNT_DTOR(nsDOMCSSAttributeDeclaration);
  34. }
  35. NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsDOMCSSAttributeDeclaration, mElement)
  36. // mElement holds a strong ref to us, so if it's going to be
  37. // skipped, the attribute declaration can't be part of a garbage
  38. // cycle.
  39. NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsDOMCSSAttributeDeclaration)
  40. if (tmp->mElement && Element::CanSkip(tmp->mElement, true)) {
  41. if (tmp->PreservingWrapper()) {
  42. // This marks the wrapper black.
  43. tmp->GetWrapper();
  44. }
  45. return true;
  46. }
  47. return tmp->IsBlack();
  48. NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
  49. NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsDOMCSSAttributeDeclaration)
  50. return tmp->IsBlack() ||
  51. (tmp->mElement && Element::CanSkipInCC(tmp->mElement));
  52. NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
  53. NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsDOMCSSAttributeDeclaration)
  54. return tmp->IsBlack() ||
  55. (tmp->mElement && Element::CanSkipThis(tmp->mElement));
  56. NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
  57. NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMCSSAttributeDeclaration)
  58. NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
  59. NS_IMPL_QUERY_TAIL_INHERITING(nsDOMCSSDeclaration)
  60. NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMCSSAttributeDeclaration)
  61. NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMCSSAttributeDeclaration)
  62. nsresult
  63. nsDOMCSSAttributeDeclaration::SetCSSDeclaration(DeclarationBlock* aDecl)
  64. {
  65. NS_ASSERTION(mElement, "Must have Element to set the declaration!");
  66. return mIsSMILOverride
  67. ? mElement->SetSMILOverrideStyleDeclaration(aDecl, true)
  68. : mElement->SetInlineStyleDeclaration(aDecl, nullptr, true);
  69. }
  70. nsIDocument*
  71. nsDOMCSSAttributeDeclaration::DocToUpdate()
  72. {
  73. // We need OwnerDoc() rather than GetUncomposedDoc() because it might
  74. // be the BeginUpdate call that inserts mElement into the document.
  75. return mElement->OwnerDoc();
  76. }
  77. DeclarationBlock*
  78. nsDOMCSSAttributeDeclaration::GetCSSDeclaration(Operation aOperation)
  79. {
  80. if (!mElement)
  81. return nullptr;
  82. DeclarationBlock* declaration;
  83. if (mIsSMILOverride) {
  84. declaration = mElement->GetSMILOverrideStyleDeclaration();
  85. } else {
  86. declaration = mElement->GetInlineStyleDeclaration();
  87. }
  88. // Notify observers that our style="" attribute is going to change
  89. // unless:
  90. // * this is a declaration that holds SMIL animation values (which
  91. // aren't reflected in the DOM style="" attribute), or
  92. // * we're getting the declaration for reading, or
  93. // * we're getting it for property removal but we don't currently have
  94. // a declaration.
  95. // XXXbz this is a bit of a hack, especially doing it before the
  96. // BeginUpdate(), but this is a good chokepoint where we know we
  97. // plan to modify the CSSDeclaration, so need to notify
  98. // AttributeWillChange if this is inline style.
  99. if (!mIsSMILOverride &&
  100. ((aOperation == eOperation_Modify) ||
  101. (aOperation == eOperation_RemoveProperty && declaration))) {
  102. nsNodeUtils::AttributeWillChange(mElement, kNameSpaceID_None,
  103. nsGkAtoms::style,
  104. nsIDOMMutationEvent::MODIFICATION,
  105. nullptr);
  106. }
  107. if (declaration) {
  108. return declaration;
  109. }
  110. if (aOperation != eOperation_Modify) {
  111. return nullptr;
  112. }
  113. // cannot fail
  114. RefPtr<DeclarationBlock> decl;
  115. if (mElement->IsStyledByServo()) {
  116. decl = new ServoDeclarationBlock();
  117. } else {
  118. decl = new css::Declaration();
  119. decl->AsGecko()->InitializeEmpty();
  120. }
  121. // this *can* fail (inside SetAttrAndNotify, at least).
  122. nsresult rv;
  123. if (mIsSMILOverride) {
  124. rv = mElement->SetSMILOverrideStyleDeclaration(decl, false);
  125. } else {
  126. rv = mElement->SetInlineStyleDeclaration(decl, nullptr, false);
  127. }
  128. if (NS_FAILED(rv)) {
  129. return nullptr; // the decl will be destroyed along with the style rule
  130. }
  131. return decl;
  132. }
  133. void
  134. nsDOMCSSAttributeDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
  135. {
  136. NS_ASSERTION(mElement, "Something is severely broken -- there should be an Element here!");
  137. nsIDocument* doc = mElement->OwnerDoc();
  138. aCSSParseEnv.mSheetURI = doc->GetDocumentURI();
  139. aCSSParseEnv.mBaseURI = mElement->GetBaseURI();
  140. aCSSParseEnv.mPrincipal = mElement->NodePrincipal();
  141. aCSSParseEnv.mCSSLoader = doc->CSSLoader();
  142. }
  143. NS_IMETHODIMP
  144. nsDOMCSSAttributeDeclaration::GetParentRule(nsIDOMCSSRule **aParent)
  145. {
  146. NS_ENSURE_ARG_POINTER(aParent);
  147. *aParent = nullptr;
  148. return NS_OK;
  149. }
  150. /* virtual */ nsINode*
  151. nsDOMCSSAttributeDeclaration::GetParentObject()
  152. {
  153. return mElement;
  154. }
  155. /* virtual */ DocGroup*
  156. nsDOMCSSAttributeDeclaration::GetDocGroup() const
  157. {
  158. return mElement ? mElement->OwnerDoc()->GetDocGroup() : nullptr;
  159. }
  160. NS_IMETHODIMP
  161. nsDOMCSSAttributeDeclaration::SetPropertyValue(const nsCSSPropertyID aPropID,
  162. const nsAString& aValue)
  163. {
  164. // Scripted modifications to style.opacity or style.transform
  165. // could immediately force us into the animated state if heuristics suggest
  166. // this is scripted animation.
  167. // FIXME: This is missing the margin shorthand and the logical versions of
  168. // the margin properties, see bug 1266287.
  169. if (aPropID == eCSSProperty_opacity || aPropID == eCSSProperty_transform ||
  170. aPropID == eCSSProperty_left || aPropID == eCSSProperty_top ||
  171. aPropID == eCSSProperty_right || aPropID == eCSSProperty_bottom ||
  172. aPropID == eCSSProperty_margin_left || aPropID == eCSSProperty_margin_top ||
  173. aPropID == eCSSProperty_margin_right || aPropID == eCSSProperty_margin_bottom ||
  174. aPropID == eCSSProperty_background_position_x ||
  175. aPropID == eCSSProperty_background_position_y ||
  176. aPropID == eCSSProperty_background_position) {
  177. nsIFrame* frame = mElement->GetPrimaryFrame();
  178. if (frame) {
  179. ActiveLayerTracker::NotifyInlineStyleRuleModified(frame, aPropID, aValue, this);
  180. }
  181. }
  182. return nsDOMCSSDeclaration::SetPropertyValue(aPropID, aValue);
  183. }