blob: 99debdcee42a42265dc1f8d15804cb5a48dfe568 [file] [log] [blame]
/*
* (C) 1999-2003 Lars Knoll (knoll@kde.org)
* Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2012 Apple Inc. All
* rights reserved.
* Copyright (C) 2011 Research In Motion Limited. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "third_party/blink/renderer/core/css/abstract_property_set_css_style_declaration.h"
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
#include "third_party/blink/renderer/core/css/css_property_value_set.h"
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
#include "third_party/blink/renderer/core/css/parser/css_property_parser.h"
#include "third_party/blink/renderer/core/css/style_attribute_mutation_scope.h"
#include "third_party/blink/renderer/core/css/style_engine.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/element.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/execution_context/security_context.h"
#include "third_party/blink/renderer/core/style_property_shorthand.h"
namespace blink {
unsigned AbstractPropertySetCSSStyleDeclaration::length() const {
return PropertySet().PropertyCount();
}
String AbstractPropertySetCSSStyleDeclaration::item(unsigned i) const {
if (i >= PropertySet().PropertyCount()) {
return "";
}
return PropertySet().PropertyAt(i).Name().ToAtomicString();
}
String AbstractPropertySetCSSStyleDeclaration::cssText() const {
return PropertySet().AsText();
}
void AbstractPropertySetCSSStyleDeclaration::setCSSText(
const ExecutionContext* execution_context,
const String& text,
ExceptionState&) {
StyleAttributeMutationScope mutation_scope(this);
WillMutate();
const SecureContextMode mode = execution_context
? execution_context->GetSecureContextMode()
: SecureContextMode::kInsecureContext;
PropertySet().ParseDeclarationList(text, mode, ContextStyleSheet());
DidMutate(kPropertyChanged);
mutation_scope.EnqueueMutationRecord();
}
String AbstractPropertySetCSSStyleDeclaration::getPropertyValue(
const String& property_name) {
CSSPropertyID property_id =
CssPropertyID(GetExecutionContext(), property_name);
if (!IsValidCSSPropertyID(property_id)) {
return String();
}
if (property_id == CSSPropertyID::kVariable) {
return PropertySet().GetPropertyValue(AtomicString(property_name));
}
return PropertySet().GetPropertyValue(property_id);
}
String AbstractPropertySetCSSStyleDeclaration::getPropertyPriority(
const String& property_name) {
CSSPropertyID property_id =
CssPropertyID(GetExecutionContext(), property_name);
if (!IsValidCSSPropertyID(property_id)) {
return String();
}
bool important = false;
if (property_id == CSSPropertyID::kVariable) {
important = PropertySet().PropertyIsImportant(AtomicString(property_name));
} else {
important = PropertySet().PropertyIsImportant(property_id);
}
return important ? "important" : "";
}
String AbstractPropertySetCSSStyleDeclaration::GetPropertyShorthand(
const String& property_name) {
CSSPropertyID property_id =
CssPropertyID(GetExecutionContext(), property_name);
// Custom properties don't have shorthands, so we can ignore them here.
if (!IsValidCSSPropertyID(property_id) ||
!CSSProperty::Get(property_id).IsLonghand()) {
return String();
}
CSSPropertyID shorthand_id = PropertySet().GetPropertyShorthand(property_id);
if (!IsValidCSSPropertyID(shorthand_id)) {
return String();
}
return CSSProperty::Get(shorthand_id).GetPropertyNameString();
}
bool AbstractPropertySetCSSStyleDeclaration::IsPropertyImplicit(
const String& property_name) {
CSSPropertyID property_id =
CssPropertyID(GetExecutionContext(), property_name);
// Custom properties don't have shorthands, so we can ignore them here.
if (property_id < kFirstCSSProperty) {
return false;
}
return PropertySet().IsPropertyImplicit(property_id);
}
void AbstractPropertySetCSSStyleDeclaration::setProperty(
const ExecutionContext* execution_context,
const String& property_name,
const String& value,
const String& priority,
ExceptionState& exception_state) {
CSSPropertyID property_id =
UnresolvedCSSPropertyID(execution_context, property_name);
if (!IsValidCSSPropertyID(property_id) || !IsPropertyValid(property_id)) {
return;
}
bool important = EqualIgnoringASCIICase(priority, "important");
if (!important && !priority.empty()) {
return;
}
const SecureContextMode mode = execution_context
? execution_context->GetSecureContextMode()
: SecureContextMode::kInsecureContext;
SetPropertyInternal(property_id, property_name, value, important, mode,
exception_state);
}
String AbstractPropertySetCSSStyleDeclaration::removeProperty(
const String& property_name,
ExceptionState& exception_state) {
CSSPropertyID property_id =
CssPropertyID(GetExecutionContext(), property_name);
if (!IsValidCSSPropertyID(property_id)) {
return String();
}
StyleAttributeMutationScope mutation_scope(this);
WillMutate();
String result;
bool changed = false;
if (property_id == CSSPropertyID::kVariable) {
changed =
PropertySet().RemoveProperty(AtomicString(property_name), &result);
} else {
changed = PropertySet().RemoveProperty(property_id, &result);
}
DidMutate(changed ? kPropertyChanged : kNoChanges);
if (changed) {
mutation_scope.EnqueueMutationRecord();
}
return result;
}
const CSSValue*
AbstractPropertySetCSSStyleDeclaration::GetPropertyCSSValueInternal(
CSSPropertyID property_id) {
return PropertySet().GetPropertyCSSValue(property_id);
}
const CSSValue*
AbstractPropertySetCSSStyleDeclaration::GetPropertyCSSValueInternal(
const AtomicString& custom_property_name) {
DCHECK_EQ(CSSPropertyID::kVariable,
CssPropertyID(GetExecutionContext(), custom_property_name));
return PropertySet().GetPropertyCSSValue(custom_property_name);
}
String AbstractPropertySetCSSStyleDeclaration::GetPropertyValueInternal(
CSSPropertyID property_id) {
return PropertySet().GetPropertyValue(property_id);
}
String AbstractPropertySetCSSStyleDeclaration::GetPropertyValueWithHint(
const String& property_name,
unsigned index) {
CSSPropertyID property_id =
CssPropertyID(GetExecutionContext(), property_name);
if (!IsValidCSSPropertyID(property_id)) {
return String();
}
if (property_id == CSSPropertyID::kVariable) {
return PropertySet().GetPropertyValueWithHint(AtomicString(property_name),
index);
}
return PropertySet().GetPropertyValue(property_id);
}
String AbstractPropertySetCSSStyleDeclaration::GetPropertyPriorityWithHint(
const String& property_name,
unsigned index) {
CSSPropertyID property_id =
CssPropertyID(GetExecutionContext(), property_name);
if (!IsValidCSSPropertyID(property_id)) {
return String();
}
bool important = false;
if (property_id == CSSPropertyID::kVariable) {
important = PropertySet().PropertyIsImportantWithHint(
AtomicString(property_name), index);
} else {
important = PropertySet().PropertyIsImportant(property_id);
}
return important ? "important" : "";
}
DISABLE_CFI_PERF
void AbstractPropertySetCSSStyleDeclaration::SetPropertyInternal(
CSSPropertyID unresolved_property,
const String& custom_property_name,
StringView value,
bool important,
SecureContextMode secure_context_mode,
ExceptionState&) {
StyleAttributeMutationScope mutation_scope(this);
WillMutate();
MutableCSSPropertyValueSet::SetResult result;
if (unresolved_property == CSSPropertyID::kVariable) {
AtomicString atomic_name(custom_property_name);
bool is_animation_tainted = IsKeyframeStyle();
result = PropertySet().ParseAndSetCustomProperty(
atomic_name, value, important, secure_context_mode, ContextStyleSheet(),
is_animation_tainted);
} else {
result = PropertySet().ParseAndSetProperty(unresolved_property, value,
important, secure_context_mode,
ContextStyleSheet());
}
if (result == MutableCSSPropertyValueSet::kParseError ||
result == MutableCSSPropertyValueSet::kUnchanged) {
DidMutate(kNoChanges);
return;
}
CSSPropertyID property_id = ResolveCSSPropertyID(unresolved_property);
if (result == MutableCSSPropertyValueSet::kModifiedExisting &&
CSSProperty::Get(property_id).SupportsIncrementalStyle()) {
DidMutate(kIndependentPropertyChanged);
} else {
DidMutate(kPropertyChanged);
}
mutation_scope.EnqueueMutationRecord();
}
bool AbstractPropertySetCSSStyleDeclaration::FastPathSetProperty(
CSSPropertyID unresolved_property,
double value) {
if (unresolved_property == CSSPropertyID::kVariable) {
// We don't bother with the fast path for custom properties,
// even though we could.
return false;
}
if (!std::isfinite(value)) {
// Just to be on the safe side.
return false;
}
CSSPropertyID property_id = ResolveCSSPropertyID(unresolved_property);
const CSSProperty& property = CSSProperty::Get(property_id);
if (!property.AcceptsNumericLiteral()) {
// Not all properties are prepared to accept numeric literals;
// e.g. widths could accept doubles but want to convert them
// to lengths, and shorthand properties may want to do their
// own things. We don't support either yet, only specifically
// allowlisted properties.
return false;
}
StyleAttributeMutationScope mutation_scope(this);
WillMutate();
const CSSValue* css_value = CSSNumericLiteralValue::Create(
value, CSSPrimitiveValue::UnitType::kNumber);
MutableCSSPropertyValueSet::SetResult result =
PropertySet().SetLonghandProperty(
CSSPropertyValue(CSSPropertyName(property_id), *css_value,
/*important=*/false));
if (result == MutableCSSPropertyValueSet::kParseError ||
result == MutableCSSPropertyValueSet::kUnchanged) {
DidMutate(kNoChanges);
return true;
}
if (result == MutableCSSPropertyValueSet::kModifiedExisting &&
property.SupportsIncrementalStyle()) {
DidMutate(kIndependentPropertyChanged);
} else {
DidMutate(kPropertyChanged);
}
mutation_scope.EnqueueMutationRecord();
return true;
}
DISABLE_CFI_PERF
StyleSheetContents* AbstractPropertySetCSSStyleDeclaration::ContextStyleSheet()
const {
CSSStyleSheet* css_style_sheet = ParentStyleSheet();
return css_style_sheet ? css_style_sheet->Contents() : nullptr;
}
bool AbstractPropertySetCSSStyleDeclaration::CssPropertyMatches(
CSSPropertyID property_id,
const CSSValue& property_value) const {
return PropertySet().PropertyMatches(property_id, property_value);
}
void AbstractPropertySetCSSStyleDeclaration::Trace(Visitor* visitor) const {
CSSStyleDeclaration::Trace(visitor);
}
} // namespace blink