blob: 46d5bba0855780d86eae40b0ee930f124bd38c6e [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/css/css_test_helpers.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_property_definition.h"
#include "third_party/blink/renderer/core/css/css_custom_ident_value.h"
#include "third_party/blink/renderer/core/css/css_numeric_literal_value.h"
#include "third_party/blink/renderer/core/css/css_rule_list.h"
#include "third_party/blink/renderer/core/css/css_style_sheet.h"
#include "third_party/blink/renderer/core/css/css_syntax_definition.h"
#include "third_party/blink/renderer/core/css/css_syntax_string_parser.h"
#include "third_party/blink/renderer/core/css/css_variable_data.h"
#include "third_party/blink/renderer/core/css/parser/css_parser.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
#include "third_party/blink/renderer/core/css/parser/css_parser_local_context.h"
#include "third_party/blink/renderer/core/css/parser/css_property_parser.h"
#include "third_party/blink/renderer/core/css/parser/css_selector_parser.h"
#include "third_party/blink/renderer/core/css/parser/css_tokenizer.h"
#include "third_party/blink/renderer/core/css/properties/css_property_ref.h"
#include "third_party/blink/renderer/core/css/properties/longhand.h"
#include "third_party/blink/renderer/core/css/property_registration.h"
#include "third_party/blink/renderer/core/css/property_registry.h"
#include "third_party/blink/renderer/core/css/rule_set.h"
#include "third_party/blink/renderer/core/css/style_sheet_contents.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/wtf/text/text_encoding.h"
namespace blink {
namespace css_test_helpers {
TestStyleSheet::~TestStyleSheet() = default;
TestStyleSheet::TestStyleSheet() {
document_ = Document::CreateForTest();
style_sheet_ = CreateStyleSheet(*document_);
}
CSSRuleList* TestStyleSheet::CssRules() {
DummyExceptionStateForTesting exception_state;
CSSRuleList* result = style_sheet_->cssRules(exception_state);
EXPECT_FALSE(exception_state.HadException());
return result;
}
RuleSet& TestStyleSheet::GetRuleSet() {
RuleSet& rule_set = style_sheet_->Contents()->EnsureRuleSet(
MediaQueryEvaluator(document_->GetFrame()), kRuleHasNoSpecialState);
rule_set.CompactRulesIfNeeded();
return rule_set;
}
void TestStyleSheet::AddCSSRules(const String& css_text, bool is_empty_sheet) {
TextPosition position;
unsigned sheet_length = style_sheet_->length();
style_sheet_->Contents()->ParseStringAtPosition(css_text, position);
if (!is_empty_sheet)
ASSERT_GT(style_sheet_->length(), sheet_length);
else
ASSERT_EQ(style_sheet_->length(), sheet_length);
}
CSSStyleSheet* CreateStyleSheet(Document& document) {
TextPosition position;
return CSSStyleSheet::CreateInline(document, NullURL(), position,
UTF8Encoding());
}
PropertyRegistration* CreatePropertyRegistration(const String& name) {
auto syntax_definition = CSSSyntaxStringParser("*").Parse();
DCHECK(syntax_definition);
return MakeGarbageCollected<PropertyRegistration>(
AtomicString(name), *syntax_definition, false /* inherits */,
nullptr /* initial */, nullptr /* initial_variable_data */);
}
PropertyRegistration* CreateLengthRegistration(const String& name, int px) {
auto syntax_definition = CSSSyntaxStringParser("<length>").Parse();
DCHECK(syntax_definition);
const CSSValue* initial =
CSSNumericLiteralValue::Create(px, CSSPrimitiveValue::UnitType::kPixels);
return MakeGarbageCollected<PropertyRegistration>(
AtomicString(name), *syntax_definition, false /* inherits */, initial,
CreateVariableData(initial->CssText()));
}
void RegisterProperty(Document& document,
const String& name,
const String& syntax,
const base::Optional<String>& initial_value,
bool is_inherited) {
DCHECK(!initial_value || !initial_value.value().IsNull());
DummyExceptionStateForTesting exception_state;
PropertyDefinition* property_definition = PropertyDefinition::Create();
property_definition->setName(name);
property_definition->setSyntax(syntax);
property_definition->setInherits(is_inherited);
if (initial_value)
property_definition->setInitialValue(initial_value.value());
PropertyRegistration::registerProperty(document.GetExecutionContext(),
property_definition, exception_state);
ASSERT_FALSE(exception_state.HadException());
}
scoped_refptr<CSSVariableData> CreateVariableData(String s) {
CSSTokenizer tokenizer(s);
auto tokens = tokenizer.TokenizeToEOF();
CSSParserTokenRange range(tokens);
bool is_animation_tainted = false;
bool needs_variable_resolution = false;
return CSSVariableData::Create({range, StringView(s)}, is_animation_tainted,
needs_variable_resolution, KURL(),
WTF::TextEncoding());
}
const CSSValue* CreateCustomIdent(AtomicString s) {
return MakeGarbageCollected<CSSCustomIdentValue>(s);
}
const CSSValue* ParseLonghand(Document& document,
const CSSProperty& property,
const String& value) {
const auto* longhand = DynamicTo<Longhand>(property);
if (!longhand)
return nullptr;
const auto* context = MakeGarbageCollected<CSSParserContext>(document);
CSSParserLocalContext local_context;
auto tokens = CSSTokenizer(value).TokenizeToEOF();
CSSParserTokenRange range(tokens);
return longhand->ParseSingleValue(range, *context, local_context);
}
const CSSPropertyValueSet* ParseDeclarationBlock(const String& block_text,
CSSParserMode mode) {
auto* set = MakeGarbageCollected<MutableCSSPropertyValueSet>(mode);
set->ParseDeclarationList(block_text, SecureContextMode::kSecureContext,
nullptr);
return set;
}
StyleRuleBase* ParseRule(Document& document, String text) {
TextPosition position;
auto* sheet = CSSStyleSheet::CreateInline(document, NullURL(), position,
UTF8Encoding());
const auto* context = MakeGarbageCollected<CSSParserContext>(document);
return CSSParser::ParseRule(context, sheet->Contents(), text);
}
const CSSValue* ParseValue(Document& document, String syntax, String value) {
auto syntax_definition = CSSSyntaxStringParser(syntax).Parse();
if (!syntax_definition.has_value())
return nullptr;
const auto* context = MakeGarbageCollected<CSSParserContext>(document);
CSSTokenizer tokenizer(value);
auto tokens = tokenizer.TokenizeToEOF();
CSSParserTokenRange range(tokens);
return syntax_definition->Parse(range, *context,
/* is_animation_tainted */ false);
}
CSSSelectorList ParseSelectorList(const String& string) {
auto* context = MakeGarbageCollected<CSSParserContext>(
kHTMLStandardMode, SecureContextMode::kInsecureContext);
auto* sheet = MakeGarbageCollected<StyleSheetContents>(context);
CSSTokenizer tokenizer(string);
const auto tokens = tokenizer.TokenizeToEOF();
CSSParserTokenRange range(tokens);
return CSSSelectorParser::ParseSelector(range, context, sheet);
}
} // namespace css_test_helpers
} // namespace blink