From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- dom/base/nsStyledElement.cpp | 197 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 dom/base/nsStyledElement.cpp (limited to 'dom/base/nsStyledElement.cpp') diff --git a/dom/base/nsStyledElement.cpp b/dom/base/nsStyledElement.cpp new file mode 100644 index 000000000..03d1187ab --- /dev/null +++ b/dom/base/nsStyledElement.cpp @@ -0,0 +1,197 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* 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 "nsStyledElement.h" +#include "nsGkAtoms.h" +#include "nsAttrValue.h" +#include "nsAttrValueInlines.h" +#include "mozilla/dom/ElementInlines.h" +#include "mozilla/InternalMutationEvent.h" +#include "nsDOMCSSDeclaration.h" +#include "nsDOMCSSAttrDeclaration.h" +#include "nsServiceManagerUtils.h" +#include "nsIDocument.h" +#include "mozilla/DeclarationBlockInlines.h" +#include "nsCSSParser.h" +#include "mozilla/css/Loader.h" +#include "nsIDOMMutationEvent.h" +#include "nsXULElement.h" +#include "nsContentUtils.h" +#include "nsStyleUtil.h" + +using namespace mozilla; +using namespace mozilla::dom; + +NS_IMPL_QUERY_INTERFACE_INHERITED(nsStyledElement, + nsStyledElementBase, + nsStyledElement) + +//---------------------------------------------------------------------- +// nsIContent methods + +bool +nsStyledElement::ParseAttribute(int32_t aNamespaceID, + nsIAtom* aAttribute, + const nsAString& aValue, + nsAttrValue& aResult) +{ + if (aAttribute == nsGkAtoms::style && aNamespaceID == kNameSpaceID_None) { + SetMayHaveStyle(); + ParseStyleAttribute(aValue, aResult, false); + return true; + } + + return nsStyledElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue, + aResult); +} + +nsresult +nsStyledElement::SetInlineStyleDeclaration(DeclarationBlock* aDeclaration, + const nsAString* aSerialized, + bool aNotify) +{ + SetMayHaveStyle(); + bool modification = false; + nsAttrValue oldValue; + + bool hasListeners = aNotify && + nsContentUtils::HasMutationListeners(this, + NS_EVENT_BITS_MUTATION_ATTRMODIFIED, + this); + + // There's no point in comparing the stylerule pointers since we're always + // getting a new stylerule here. And we can't compare the stringvalues of + // the old and the new rules since both will point to the same declaration + // and thus will be the same. + if (hasListeners) { + // save the old attribute so we can set up the mutation event properly + // XXXbz if the old rule points to the same declaration as the new one, + // this is getting the new attr value, not the old one.... + nsAutoString oldValueStr; + modification = GetAttr(kNameSpaceID_None, nsGkAtoms::style, + oldValueStr); + if (modification) { + oldValue.SetTo(oldValueStr); + } + } + else if (aNotify && IsInUncomposedDoc()) { + modification = !!mAttrsAndChildren.GetAttr(nsGkAtoms::style); + } + + nsAttrValue attrValue(do_AddRef(aDeclaration), aSerialized); + + // XXXbz do we ever end up with ADDITION here? I doubt it. + uint8_t modType = modification ? + static_cast(nsIDOMMutationEvent::MODIFICATION) : + static_cast(nsIDOMMutationEvent::ADDITION); + + return SetAttrAndNotify(kNameSpaceID_None, nsGkAtoms::style, nullptr, + oldValue, attrValue, modType, hasListeners, + aNotify, kDontCallAfterSetAttr); +} + +DeclarationBlock* +nsStyledElement::GetInlineStyleDeclaration() +{ + if (!MayHaveStyle()) { + return nullptr; + } + const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(nsGkAtoms::style); + + if (attrVal && attrVal->Type() == nsAttrValue::eCSSDeclaration) { + return attrVal->GetCSSDeclarationValue(); + } + + return nullptr; +} + +// --------------------------------------------------------------- +// Others and helpers + +nsICSSDeclaration* +nsStyledElement::Style() +{ + Element::nsDOMSlots *slots = DOMSlots(); + + if (!slots->mStyle) { + // Just in case... + ReparseStyleAttribute(true); + + slots->mStyle = new nsDOMCSSAttributeDeclaration(this, false); + SetMayHaveStyle(); + } + + return slots->mStyle; +} + +nsresult +nsStyledElement::ReparseStyleAttribute(bool aForceInDataDoc) +{ + if (!MayHaveStyle()) { + return NS_OK; + } + const nsAttrValue* oldVal = mAttrsAndChildren.GetAttr(nsGkAtoms::style); + if (oldVal && oldVal->Type() != nsAttrValue::eCSSDeclaration) { + nsAttrValue attrValue; + nsAutoString stringValue; + oldVal->ToString(stringValue); + ParseStyleAttribute(stringValue, attrValue, aForceInDataDoc); + // Don't bother going through SetInlineStyleDeclaration; we don't + // want to fire off mutation events or document notifications anyway + nsresult rv = mAttrsAndChildren.SetAndSwapAttr(nsGkAtoms::style, attrValue); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; +} + +nsICSSDeclaration* +nsStyledElement::GetExistingStyle() +{ + Element::nsDOMSlots* slots = GetExistingDOMSlots(); + if (!slots) { + return nullptr; + } + + return slots->mStyle; +} + +void +nsStyledElement::ParseStyleAttribute(const nsAString& aValue, + nsAttrValue& aResult, + bool aForceInDataDoc) +{ + nsIDocument* doc = OwnerDoc(); + bool isNativeAnon = IsInNativeAnonymousSubtree(); + + if (!isNativeAnon && + !nsStyleUtil::CSPAllowsInlineStyle(nullptr, NodePrincipal(), + doc->GetDocumentURI(), 0, aValue, + nullptr)) + return; + + if (aForceInDataDoc || + !doc->IsLoadedAsData() || + GetExistingStyle() || + doc->IsStaticDocument()) { + bool isCSS = true; // assume CSS until proven otherwise + + if (!isNativeAnon) { // native anonymous content always assumes CSS + nsAutoString styleType; + doc->GetHeaderData(nsGkAtoms::headerContentStyleType, styleType); + if (!styleType.IsEmpty()) { + static const char textCssStr[] = "text/css"; + isCSS = (styleType.EqualsIgnoreCase(textCssStr, sizeof(textCssStr) - 1)); + } + } + + if (isCSS && aResult.ParseStyleAttribute(aValue, this)) { + return; + } + } + + aResult.SetTo(aValue); +} -- cgit v1.2.3