1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/style/nsDOMCSSAttrDeclaration.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,192 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* DOM object for element.style */ 1.10 + 1.11 +#include "nsDOMCSSAttrDeclaration.h" 1.12 + 1.13 +#include "mozilla/css/Declaration.h" 1.14 +#include "mozilla/css/StyleRule.h" 1.15 +#include "mozilla/dom/Element.h" 1.16 +#include "nsIDocument.h" 1.17 +#include "nsIDOMMutationEvent.h" 1.18 +#include "nsIURI.h" 1.19 +#include "nsNodeUtils.h" 1.20 +#include "nsWrapperCacheInlines.h" 1.21 +#include "nsIFrame.h" 1.22 +#include "ActiveLayerTracker.h" 1.23 + 1.24 +using namespace mozilla; 1.25 + 1.26 +nsDOMCSSAttributeDeclaration::nsDOMCSSAttributeDeclaration(dom::Element* aElement, 1.27 + bool aIsSMILOverride) 1.28 + : mElement(aElement) 1.29 + , mIsSMILOverride(aIsSMILOverride) 1.30 +{ 1.31 + MOZ_COUNT_CTOR(nsDOMCSSAttributeDeclaration); 1.32 + 1.33 + NS_ASSERTION(aElement, "Inline style for a NULL element?"); 1.34 +} 1.35 + 1.36 +nsDOMCSSAttributeDeclaration::~nsDOMCSSAttributeDeclaration() 1.37 +{ 1.38 + MOZ_COUNT_DTOR(nsDOMCSSAttributeDeclaration); 1.39 +} 1.40 + 1.41 +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(nsDOMCSSAttributeDeclaration, mElement) 1.42 + 1.43 +// mElement holds a strong ref to us, so if it's going to be 1.44 +// skipped, the attribute declaration can't be part of a garbage 1.45 +// cycle. 1.46 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsDOMCSSAttributeDeclaration) 1.47 + if (tmp->mElement && Element::CanSkip(tmp->mElement, true)) { 1.48 + if (tmp->PreservingWrapper()) { 1.49 + // This marks the wrapper black. 1.50 + tmp->GetWrapper(); 1.51 + } 1.52 + return true; 1.53 + } 1.54 + return tmp->IsBlack(); 1.55 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END 1.56 + 1.57 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsDOMCSSAttributeDeclaration) 1.58 + return tmp->IsBlack() || 1.59 + (tmp->mElement && Element::CanSkipInCC(tmp->mElement)); 1.60 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END 1.61 + 1.62 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsDOMCSSAttributeDeclaration) 1.63 + return tmp->IsBlack() || 1.64 + (tmp->mElement && Element::CanSkipThis(tmp->mElement)); 1.65 +NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END 1.66 + 1.67 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMCSSAttributeDeclaration) 1.68 + NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY 1.69 +NS_IMPL_QUERY_TAIL_INHERITING(nsDOMCSSDeclaration) 1.70 + 1.71 +NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMCSSAttributeDeclaration) 1.72 +NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMCSSAttributeDeclaration) 1.73 + 1.74 +nsresult 1.75 +nsDOMCSSAttributeDeclaration::SetCSSDeclaration(css::Declaration* aDecl) 1.76 +{ 1.77 + NS_ASSERTION(mElement, "Must have Element to set the declaration!"); 1.78 + css::StyleRule* oldRule = 1.79 + mIsSMILOverride ? mElement->GetSMILOverrideStyleRule() : 1.80 + mElement->GetInlineStyleRule(); 1.81 + NS_ASSERTION(oldRule, "Element must have rule"); 1.82 + 1.83 + nsRefPtr<css::StyleRule> newRule = 1.84 + oldRule->DeclarationChanged(aDecl, false); 1.85 + if (!newRule) { 1.86 + return NS_ERROR_OUT_OF_MEMORY; 1.87 + } 1.88 + 1.89 + return 1.90 + mIsSMILOverride ? mElement->SetSMILOverrideStyleRule(newRule, true) : 1.91 + mElement->SetInlineStyleRule(newRule, nullptr, true); 1.92 +} 1.93 + 1.94 +nsIDocument* 1.95 +nsDOMCSSAttributeDeclaration::DocToUpdate() 1.96 +{ 1.97 + // XXXbz this is a bit of a hack, especially doing it before the 1.98 + // BeginUpdate(), but this is a good chokepoint where we know we 1.99 + // plan to modify the CSSDeclaration, so need to notify 1.100 + // AttributeWillChange if this is inline style. 1.101 + if (!mIsSMILOverride) { 1.102 + nsNodeUtils::AttributeWillChange(mElement, kNameSpaceID_None, 1.103 + nsGkAtoms::style, 1.104 + nsIDOMMutationEvent::MODIFICATION); 1.105 + } 1.106 + 1.107 + // We need OwnerDoc() rather than GetCurrentDoc() because it might 1.108 + // be the BeginUpdate call that inserts mElement into the document. 1.109 + return mElement->OwnerDoc(); 1.110 +} 1.111 + 1.112 +css::Declaration* 1.113 +nsDOMCSSAttributeDeclaration::GetCSSDeclaration(bool aAllocate) 1.114 +{ 1.115 + if (!mElement) 1.116 + return nullptr; 1.117 + 1.118 + css::StyleRule* cssRule; 1.119 + if (mIsSMILOverride) 1.120 + cssRule = mElement->GetSMILOverrideStyleRule(); 1.121 + else 1.122 + cssRule = mElement->GetInlineStyleRule(); 1.123 + 1.124 + if (cssRule) { 1.125 + return cssRule->GetDeclaration(); 1.126 + } 1.127 + if (!aAllocate) { 1.128 + return nullptr; 1.129 + } 1.130 + 1.131 + // cannot fail 1.132 + css::Declaration *decl = new css::Declaration(); 1.133 + decl->InitializeEmpty(); 1.134 + nsRefPtr<css::StyleRule> newRule = new css::StyleRule(nullptr, decl); 1.135 + 1.136 + // this *can* fail (inside SetAttrAndNotify, at least). 1.137 + nsresult rv; 1.138 + if (mIsSMILOverride) 1.139 + rv = mElement->SetSMILOverrideStyleRule(newRule, false); 1.140 + else 1.141 + rv = mElement->SetInlineStyleRule(newRule, nullptr, false); 1.142 + 1.143 + if (NS_FAILED(rv)) { 1.144 + return nullptr; // the decl will be destroyed along with the style rule 1.145 + } 1.146 + 1.147 + return decl; 1.148 +} 1.149 + 1.150 +void 1.151 +nsDOMCSSAttributeDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) 1.152 +{ 1.153 + NS_ASSERTION(mElement, "Something is severely broken -- there should be an Element here!"); 1.154 + 1.155 + nsIDocument* doc = mElement->OwnerDoc(); 1.156 + aCSSParseEnv.mSheetURI = doc->GetDocumentURI(); 1.157 + aCSSParseEnv.mBaseURI = mElement->GetBaseURI(); 1.158 + aCSSParseEnv.mPrincipal = mElement->NodePrincipal(); 1.159 + aCSSParseEnv.mCSSLoader = doc->CSSLoader(); 1.160 +} 1.161 + 1.162 +NS_IMETHODIMP 1.163 +nsDOMCSSAttributeDeclaration::GetParentRule(nsIDOMCSSRule **aParent) 1.164 +{ 1.165 + NS_ENSURE_ARG_POINTER(aParent); 1.166 + 1.167 + *aParent = nullptr; 1.168 + return NS_OK; 1.169 +} 1.170 + 1.171 +/* virtual */ nsINode* 1.172 +nsDOMCSSAttributeDeclaration::GetParentObject() 1.173 +{ 1.174 + return mElement; 1.175 +} 1.176 + 1.177 +NS_IMETHODIMP 1.178 +nsDOMCSSAttributeDeclaration::SetPropertyValue(const nsCSSProperty aPropID, 1.179 + const nsAString& aValue) 1.180 +{ 1.181 + // Scripted modifications to style.opacity or style.transform 1.182 + // could immediately force us into the animated state if heuristics suggest 1.183 + // this is scripted animation. 1.184 + if (aPropID == eCSSProperty_opacity || aPropID == eCSSProperty_transform || 1.185 + aPropID == eCSSProperty_left || aPropID == eCSSProperty_top || 1.186 + aPropID == eCSSProperty_right || aPropID == eCSSProperty_bottom || 1.187 + aPropID == eCSSProperty_margin_left || aPropID == eCSSProperty_margin_top || 1.188 + aPropID == eCSSProperty_margin_right || aPropID == eCSSProperty_margin_bottom) { 1.189 + nsIFrame* frame = mElement->GetPrimaryFrame(); 1.190 + if (frame) { 1.191 + ActiveLayerTracker::NotifyInlineStyleRuleModified(frame, aPropID); 1.192 + } 1.193 + } 1.194 + return nsDOMCSSDeclaration::SetPropertyValue(aPropID, aValue); 1.195 +}