// Copyright 2014 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 "core/css/parser/CSSParserImpl.h"

#include <bitset>
#include <memory>
#include "core/css/CSSCustomIdentValue.h"
#include "core/css/CSSCustomPropertyDeclaration.h"
#include "core/css/CSSKeyframesRule.h"
#include "core/css/CSSStyleSheet.h"
#include "core/css/PropertyRegistry.h"
#include "core/css/StyleRuleImport.h"
#include "core/css/StyleRuleKeyframe.h"
#include "core/css/StyleRuleNamespace.h"
#include "core/css/StyleSheetContents.h"
#include "core/css/parser/CSSAtRuleID.h"
#include "core/css/parser/CSSLazyParsingState.h"
#include "core/css/parser/CSSLazyPropertyParserImpl.h"
#include "core/css/parser/CSSParserObserver.h"
#include "core/css/parser/CSSParserObserverWrapper.h"
#include "core/css/parser/CSSParserSelector.h"
#include "core/css/parser/CSSPropertyParser.h"
#include "core/css/parser/CSSSelectorParser.h"
#include "core/css/parser/CSSSupportsParser.h"
#include "core/css/parser/CSSTokenizer.h"
#include "core/css/parser/CSSVariableParser.h"
#include "core/css/parser/MediaQueryParser.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/frame/Deprecation.h"
#include "core/frame/UseCounter.h"
#include "platform/instrumentation/tracing/TraceEvent.h"
#include "platform/wtf/PtrUtil.h"

namespace blink {

CSSParserImpl::CSSParserImpl(const CSSParserContext* context,
                             StyleSheetContents* style_sheet)
    : context_(context),
      style_sheet_(style_sheet),
      observer_wrapper_(nullptr) {}

MutableStylePropertySet::SetResult CSSParserImpl::ParseValue(
    MutableStylePropertySet* declaration,
    CSSPropertyID unresolved_property,
    const String& string,
    bool important,
    const CSSParserContext* context) {
  CSSParserImpl parser(context);
  StyleRule::RuleType rule_type = StyleRule::kStyle;
  if (declaration->CssParserMode() == kCSSViewportRuleMode)
    rule_type = StyleRule::kViewport;
  else if (declaration->CssParserMode() == kCSSFontFaceRuleMode)
    rule_type = StyleRule::kFontFace;
  CSSTokenizer tokenizer(string);
  parser.ConsumeDeclarationValue(tokenizer.TokenRange(), unresolved_property,
                                 important, rule_type);
  bool did_parse = false;
  bool did_change = false;
  if (!parser.parsed_properties_.IsEmpty()) {
    did_parse = true;
    did_change = declaration->AddParsedProperties(parser.parsed_properties_);
  }
  return MutableStylePropertySet::SetResult{did_parse, did_change};
}

MutableStylePropertySet::SetResult CSSParserImpl::ParseVariableValue(
    MutableStylePropertySet* declaration,
    const AtomicString& property_name,
    const PropertyRegistry* registry,
    const String& value,
    bool important,
    const CSSParserContext* context,
    bool is_animation_tainted) {
  CSSParserImpl parser(context);
  CSSTokenizer tokenizer(value);
  parser.ConsumeVariableValue(tokenizer.TokenRange(), property_name, important,
                              is_animation_tainted);
  bool did_parse = false;
  bool did_change = false;
  if (!parser.parsed_properties_.IsEmpty()) {
    const CSSCustomPropertyDeclaration* parsed_declaration =
        ToCSSCustomPropertyDeclaration(parser.parsed_properties_[0].Value());
    if (parsed_declaration->Value() && registry) {
      const PropertyRegistration* registration =
          registry->Registration(property_name);
      // TODO(timloh): This is a bit wasteful, we parse the registered property
      // to validate but throw away the result.
      if (registration &&
          !registration->Syntax().Parse(tokenizer.TokenRange(), context,
                                        is_animation_tainted)) {
        return MutableStylePropertySet::SetResult{did_parse, did_change};
      }
    }
    did_parse = true;
    did_change = declaration->AddParsedProperties(parser.parsed_properties_);
  }
  return MutableStylePropertySet::SetResult{did_parse, did_change};
}

static inline void FilterProperties(
    bool important,
    const HeapVector<CSSProperty, 256>& input,
    HeapVector<CSSProperty, 256>& output,
    size_t& unused_entries,
    std::bitset<numCSSProperties>& seen_properties,
    HashSet<AtomicString>& seen_custom_properties) {
  // Add properties in reverse order so that highest priority definitions are
  // reached first. Duplicate definitions can then be ignored when found.
  for (size_t i = input.size(); i--;) {
    const CSSProperty& property = input[i];
    if (property.IsImportant() != important)
      continue;
    const unsigned property_id_index = property.Id() - firstCSSProperty;

    if (property.Id() == CSSPropertyVariable) {
      const AtomicString& name =
          ToCSSCustomPropertyDeclaration(property.Value())->GetName();
      if (seen_custom_properties.Contains(name))
        continue;
      seen_custom_properties.insert(name);
    } else if (property.Id() == CSSPropertyApplyAtRule) {
      // TODO(timloh): Do we need to do anything here?
    } else {
      if (seen_properties.test(property_id_index))
        continue;
      seen_properties.set(property_id_index);
    }
    output[--unused_entries] = property;
  }
}

static ImmutableStylePropertySet* CreateStylePropertySet(
    HeapVector<CSSProperty, 256>& parsed_properties,
    CSSParserMode mode) {
  std::bitset<numCSSProperties> seen_properties;
  size_t unused_entries = parsed_properties.size();
  HeapVector<CSSProperty, 256> results(unused_entries);
  HashSet<AtomicString> seen_custom_properties;

  FilterProperties(true, parsed_properties, results, unused_entries,
                   seen_properties, seen_custom_properties);
  FilterProperties(false, parsed_properties, results, unused_entries,
                   seen_properties, seen_custom_properties);

  ImmutableStylePropertySet* result = ImmutableStylePropertySet::Create(
      results.data() + unused_entries, results.size() - unused_entries, mode);
  parsed_properties.clear();
  return result;
}

ImmutableStylePropertySet* CSSParserImpl::ParseInlineStyleDeclaration(
    const String& string,
    Element* element) {
  Document& document = element->GetDocument();
  CSSParserContext* context = CSSParserContext::Create(
      document.ElementSheet().Contents()->ParserContext(), &document);
  CSSParserMode mode = element->IsHTMLElement() && !document.InQuirksMode()
                           ? kHTMLStandardMode
                           : kHTMLQuirksMode;
  context->SetMode(mode);
  CSSParserImpl parser(context, document.ElementSheet().Contents());
  CSSTokenizer tokenizer(string);
  parser.ConsumeDeclarationList(tokenizer.TokenRange(), StyleRule::kStyle);
  return CreateStylePropertySet(parser.parsed_properties_, mode);
}

bool CSSParserImpl::ParseDeclarationList(MutableStylePropertySet* declaration,
                                         const String& string,
                                         const CSSParserContext* context) {
  CSSParserImpl parser(context);
  StyleRule::RuleType rule_type = StyleRule::kStyle;
  if (declaration->CssParserMode() == kCSSViewportRuleMode)
    rule_type = StyleRule::kViewport;
  CSSTokenizer tokenizer(string);
  parser.ConsumeDeclarationList(tokenizer.TokenRange(), rule_type);
  if (parser.parsed_properties_.IsEmpty())
    return false;

  std::bitset<numCSSProperties> seen_properties;
  size_t unused_entries = parser.parsed_properties_.size();
  HeapVector<CSSProperty, 256> results(unused_entries);
  HashSet<AtomicString> seen_custom_properties;
  FilterProperties(true, parser.parsed_properties_, results, unused_entries,
                   seen_properties, seen_custom_properties);
  FilterProperties(false, parser.parsed_properties_, results, unused_entries,
                   seen_properties, seen_custom_properties);
  if (unused_entries)
    results.erase(0, unused_entries);
  return declaration->AddParsedProperties(results);
}

StyleRuleBase* CSSParserImpl::ParseRule(const String& string,
                                        const CSSParserContext* context,
                                        StyleSheetContents* style_sheet,
                                        AllowedRulesType allowed_rules) {
  CSSParserImpl parser(context, style_sheet);
  CSSTokenizer tokenizer(string);
  CSSParserTokenRange range = tokenizer.TokenRange();
  range.ConsumeWhitespace();
  if (range.AtEnd())
    return nullptr;  // Parse error, empty rule
  StyleRuleBase* rule;
  if (range.Peek().GetType() == kAtKeywordToken)
    rule = parser.ConsumeAtRule(range, allowed_rules);
  else
    rule = parser.ConsumeQualifiedRule(range, allowed_rules);
  if (!rule)
    return nullptr;  // Parse error, failed to consume rule
  range.ConsumeWhitespace();
  if (!rule || !range.AtEnd())
    return nullptr;  // Parse error, trailing garbage
  return rule;
}

void CSSParserImpl::ParseStyleSheet(const String& string,
                                    const CSSParserContext* context,
                                    StyleSheetContents* style_sheet,
                                    bool defer_property_parsing) {
  TRACE_EVENT_BEGIN2("blink,blink_style", "CSSParserImpl::parseStyleSheet",
                     "baseUrl", context->BaseURL().GetString().Utf8(), "mode",
                     context->Mode());

  TRACE_EVENT_BEGIN0("blink,blink_style",
                     "CSSParserImpl::parseStyleSheet.tokenize");
  CSSTokenizer tokenizer(string);
  TRACE_EVENT_END0("blink,blink_style",
                   "CSSParserImpl::parseStyleSheet.tokenize");

  TRACE_EVENT_BEGIN0("blink,blink_style",
                     "CSSParserImpl::parseStyleSheet.parse");
  CSSParserImpl parser(context, style_sheet);
  if (defer_property_parsing) {
    parser.lazy_state_ = new CSSLazyParsingState(
        context, tokenizer.TakeEscapedStrings(), string, parser.style_sheet_);
  }
  bool first_rule_valid =
      parser.ConsumeRuleList(tokenizer.TokenRange(), kTopLevelRuleList,
                             [&style_sheet](StyleRuleBase* rule) {
                               if (rule->IsCharsetRule())
                                 return;
                               style_sheet->ParserAppendRule(rule);
                             });
  style_sheet->SetHasSyntacticallyValidCSSHeader(first_rule_valid);
  if (parser.lazy_state_)
    parser.lazy_state_->FinishInitialParsing();
  TRACE_EVENT_END0("blink,blink_style", "CSSParserImpl::parseStyleSheet.parse");

  TRACE_EVENT_END2("blink,blink_style", "CSSParserImpl::parseStyleSheet",
                   "tokenCount", tokenizer.TokenCount(), "length",
                   string.length());
}

CSSSelectorList CSSParserImpl::ParsePageSelector(
    CSSParserTokenRange range,
    StyleSheetContents* style_sheet) {
  // We only support a small subset of the css-page spec.
  range.ConsumeWhitespace();
  AtomicString type_selector;
  if (range.Peek().GetType() == kIdentToken)
    type_selector = range.Consume().Value().ToAtomicString();

  AtomicString pseudo;
  if (range.Peek().GetType() == kColonToken) {
    range.Consume();
    if (range.Peek().GetType() != kIdentToken)
      return CSSSelectorList();
    pseudo = range.Consume().Value().ToAtomicString();
  }

  range.ConsumeWhitespace();
  if (!range.AtEnd())
    return CSSSelectorList();  // Parse error; extra tokens in @page selector

  std::unique_ptr<CSSParserSelector> selector;
  if (!type_selector.IsNull() && pseudo.IsNull()) {
    selector = CSSParserSelector::Create(QualifiedName(
        g_null_atom, type_selector, style_sheet->DefaultNamespace()));
  } else {
    selector = CSSParserSelector::Create();
    if (!pseudo.IsNull()) {
      selector->SetMatch(CSSSelector::kPagePseudoClass);
      selector->UpdatePseudoPage(pseudo.LowerASCII());
      if (selector->GetPseudoType() == CSSSelector::kPseudoUnknown)
        return CSSSelectorList();
    }
    if (!type_selector.IsNull()) {
      selector->PrependTagSelector(QualifiedName(
          g_null_atom, type_selector, style_sheet->DefaultNamespace()));
    }
  }

  selector->SetForPage();
  Vector<std::unique_ptr<CSSParserSelector>> selector_vector;
  selector_vector.push_back(std::move(selector));
  CSSSelectorList selector_list =
      CSSSelectorList::AdoptSelectorVector(selector_vector);
  return selector_list;
}

ImmutableStylePropertySet* CSSParserImpl::ParseCustomPropertySet(
    CSSParserTokenRange range) {
  range.ConsumeWhitespace();
  if (range.Peek().GetType() != kLeftBraceToken)
    return nullptr;
  CSSParserTokenRange block = range.ConsumeBlock();
  range.ConsumeWhitespace();
  if (!range.AtEnd())
    return nullptr;
  CSSParserImpl parser(StrictCSSParserContext());
  parser.ConsumeDeclarationList(block, StyleRule::kStyle);

  // Drop nested @apply rules. Seems nicer to do this here instead of making
  // a different StyleRule type
  for (size_t i = parser.parsed_properties_.size(); i--;) {
    if (parser.parsed_properties_[i].Id() == CSSPropertyApplyAtRule)
      parser.parsed_properties_.erase(i);
  }

  return CreateStylePropertySet(parser.parsed_properties_, kHTMLStandardMode);
}

std::unique_ptr<Vector<double>> CSSParserImpl::ParseKeyframeKeyList(
    const String& key_list) {
  return ConsumeKeyframeKeyList(CSSTokenizer(key_list).TokenRange());
}

bool CSSParserImpl::SupportsDeclaration(CSSParserTokenRange& range) {
  DCHECK(parsed_properties_.IsEmpty());
  ConsumeDeclaration(range, StyleRule::kStyle);
  bool result = !parsed_properties_.IsEmpty();
  parsed_properties_.clear();
  return result;
}

void CSSParserImpl::ParseDeclarationListForInspector(
    const String& declaration,
    const CSSParserContext* context,
    CSSParserObserver& observer) {
  CSSParserImpl parser(context);
  CSSParserObserverWrapper wrapper(observer);
  parser.observer_wrapper_ = &wrapper;
  CSSTokenizer tokenizer(declaration, wrapper);
  observer.StartRuleHeader(StyleRule::kStyle, 0);
  observer.EndRuleHeader(1);
  parser.ConsumeDeclarationList(tokenizer.TokenRange(), StyleRule::kStyle);
}

void CSSParserImpl::ParseStyleSheetForInspector(const String& string,
                                                const CSSParserContext* context,
                                                StyleSheetContents* style_sheet,
                                                CSSParserObserver& observer) {
  CSSParserImpl parser(context, style_sheet);
  CSSParserObserverWrapper wrapper(observer);
  parser.observer_wrapper_ = &wrapper;
  CSSTokenizer tokenizer(string, wrapper);
  bool first_rule_valid =
      parser.ConsumeRuleList(tokenizer.TokenRange(), kTopLevelRuleList,
                             [&style_sheet](StyleRuleBase* rule) {
                               if (rule->IsCharsetRule())
                                 return;
                               style_sheet->ParserAppendRule(rule);
                             });
  style_sheet->SetHasSyntacticallyValidCSSHeader(first_rule_valid);
}

StylePropertySet* CSSParserImpl::ParseDeclarationListForLazyStyle(
    CSSParserTokenRange block,
    const CSSParserContext* context) {
  CSSParserImpl parser(context);
  parser.ConsumeDeclarationList(std::move(block), StyleRule::kStyle);
  return CreateStylePropertySet(parser.parsed_properties_, context->Mode());
}

static CSSParserImpl::AllowedRulesType ComputeNewAllowedRules(
    CSSParserImpl::AllowedRulesType allowed_rules,
    StyleRuleBase* rule) {
  if (!rule || allowed_rules == CSSParserImpl::kKeyframeRules ||
      allowed_rules == CSSParserImpl::kNoRules)
    return allowed_rules;
  DCHECK_LE(allowed_rules, CSSParserImpl::kRegularRules);
  if (rule->IsCharsetRule() || rule->IsImportRule())
    return CSSParserImpl::kAllowImportRules;
  if (rule->IsNamespaceRule())
    return CSSParserImpl::kAllowNamespaceRules;
  return CSSParserImpl::kRegularRules;
}

template <typename T>
bool CSSParserImpl::ConsumeRuleList(CSSParserTokenRange range,
                                    RuleListType rule_list_type,
                                    const T callback) {
  AllowedRulesType allowed_rules = kRegularRules;
  switch (rule_list_type) {
    case kTopLevelRuleList:
      allowed_rules = kAllowCharsetRules;
      break;
    case kRegularRuleList:
      allowed_rules = kRegularRules;
      break;
    case kKeyframesRuleList:
      allowed_rules = kKeyframeRules;
      break;
    default:
      NOTREACHED();
  }

  bool seen_rule = false;
  bool first_rule_valid = false;
  while (!range.AtEnd()) {
    StyleRuleBase* rule;
    switch (range.Peek().GetType()) {
      case kWhitespaceToken:
        range.ConsumeWhitespace();
        continue;
      case kAtKeywordToken:
        rule = ConsumeAtRule(range, allowed_rules);
        break;
      case kCDOToken:
      case kCDCToken:
        if (rule_list_type == kTopLevelRuleList) {
          range.Consume();
          continue;
        }
      // fallthrough
      default:
        rule = ConsumeQualifiedRule(range, allowed_rules);
        break;
    }
    if (!seen_rule) {
      seen_rule = true;
      first_rule_valid = rule;
    }
    if (rule) {
      allowed_rules = ComputeNewAllowedRules(allowed_rules, rule);
      callback(rule);
    }
  }

  return first_rule_valid;
}

StyleRuleBase* CSSParserImpl::ConsumeAtRule(CSSParserTokenRange& range,
                                            AllowedRulesType allowed_rules) {
  DCHECK_EQ(range.Peek().GetType(), kAtKeywordToken);
  const StringView name = range.ConsumeIncludingWhitespace().Value();
  const CSSParserToken* prelude_start = &range.Peek();
  while (!range.AtEnd() && range.Peek().GetType() != kLeftBraceToken &&
         range.Peek().GetType() != kSemicolonToken)
    range.ConsumeComponentValue();

  CSSParserTokenRange prelude =
      range.MakeSubRange(prelude_start, &range.Peek());
  CSSAtRuleID id = CssAtRuleID(name);
  if (id != kCSSAtRuleInvalid && context_->IsUseCounterRecordingEnabled())
    CountAtRule(context_, id);

  if (range.AtEnd() || range.Peek().GetType() == kSemicolonToken) {
    range.Consume();
    if (allowed_rules == kAllowCharsetRules && id == kCSSAtRuleCharset)
      return ConsumeCharsetRule(prelude);
    if (allowed_rules <= kAllowImportRules && id == kCSSAtRuleImport)
      return ConsumeImportRule(prelude);
    if (allowed_rules <= kAllowNamespaceRules && id == kCSSAtRuleNamespace)
      return ConsumeNamespaceRule(prelude);
    if (allowed_rules == kApplyRules && id == kCSSAtRuleApply) {
      ConsumeApplyRule(prelude);
      return nullptr;  // ConsumeApplyRule just updates parsed_properties_
    }
    return nullptr;  // Parse error, unrecognised at-rule without block
  }

  CSSParserTokenRange block = range.ConsumeBlock();
  if (allowed_rules == kKeyframeRules)
    return nullptr;  // Parse error, no at-rules supported inside @keyframes
  if (allowed_rules == kNoRules || allowed_rules == kApplyRules)
    return nullptr;  // Parse error, no at-rules with blocks supported inside
                     // declaration lists

  DCHECK_LE(allowed_rules, kRegularRules);

  switch (id) {
    case kCSSAtRuleMedia:
      return ConsumeMediaRule(prelude, block);
    case kCSSAtRuleSupports:
      return ConsumeSupportsRule(prelude, block);
    case kCSSAtRuleViewport:
      return ConsumeViewportRule(prelude, block);
    case kCSSAtRuleFontFace:
      return ConsumeFontFaceRule(prelude, block);
    case kCSSAtRuleWebkitKeyframes:
      return ConsumeKeyframesRule(true, prelude, block);
    case kCSSAtRuleKeyframes:
      return ConsumeKeyframesRule(false, prelude, block);
    case kCSSAtRulePage:
      return ConsumePageRule(prelude, block);
    default:
      return nullptr;  // Parse error, unrecognised at-rule with block
  }
}

StyleRuleBase* CSSParserImpl::ConsumeQualifiedRule(
    CSSParserTokenRange& range,
    AllowedRulesType allowed_rules) {
  const CSSParserToken* prelude_start = &range.Peek();
  while (!range.AtEnd() && range.Peek().GetType() != kLeftBraceToken)
    range.ConsumeComponentValue();

  if (range.AtEnd())
    return nullptr;  // Parse error, EOF instead of qualified rule block

  CSSParserTokenRange prelude =
      range.MakeSubRange(prelude_start, &range.Peek());
  CSSParserTokenRange block = range.ConsumeBlock();

  if (allowed_rules <= kRegularRules)
    return ConsumeStyleRule(prelude, block);
  if (allowed_rules == kKeyframeRules)
    return ConsumeKeyframeStyleRule(prelude, block);

  NOTREACHED();
  return nullptr;
}

// This may still consume tokens if it fails
static AtomicString ConsumeStringOrURI(CSSParserTokenRange& range) {
  const CSSParserToken& token = range.Peek();

  if (token.GetType() == kStringToken || token.GetType() == kUrlToken)
    return range.ConsumeIncludingWhitespace().Value().ToAtomicString();

  if (token.GetType() != kFunctionToken ||
      !EqualIgnoringASCIICase(token.Value(), "url"))
    return AtomicString();

  CSSParserTokenRange contents = range.ConsumeBlock();
  const CSSParserToken& uri = contents.ConsumeIncludingWhitespace();
  if (uri.GetType() == kBadStringToken || !contents.AtEnd())
    return AtomicString();
  DCHECK_EQ(uri.GetType(), kStringToken);
  return uri.Value().ToAtomicString();
}

StyleRuleCharset* CSSParserImpl::ConsumeCharsetRule(
    CSSParserTokenRange prelude) {
  const CSSParserToken& string = prelude.ConsumeIncludingWhitespace();
  if (string.GetType() != kStringToken || !prelude.AtEnd())
    return nullptr;  // Parse error, expected a single string
  return StyleRuleCharset::Create();
}

StyleRuleImport* CSSParserImpl::ConsumeImportRule(CSSParserTokenRange prelude) {
  AtomicString uri(ConsumeStringOrURI(prelude));
  if (uri.IsNull())
    return nullptr;  // Parse error, expected string or URI

  if (observer_wrapper_) {
    unsigned end_offset = observer_wrapper_->EndOffset(prelude);
    observer_wrapper_->Observer().StartRuleHeader(
        StyleRule::kImport, observer_wrapper_->StartOffset(prelude));
    observer_wrapper_->Observer().EndRuleHeader(end_offset);
    observer_wrapper_->Observer().StartRuleBody(end_offset);
    observer_wrapper_->Observer().EndRuleBody(end_offset);
  }

  return StyleRuleImport::Create(uri,
                                 MediaQueryParser::ParseMediaQuerySet(prelude));
}

StyleRuleNamespace* CSSParserImpl::ConsumeNamespaceRule(
    CSSParserTokenRange prelude) {
  AtomicString namespace_prefix;
  if (prelude.Peek().GetType() == kIdentToken)
    namespace_prefix =
        prelude.ConsumeIncludingWhitespace().Value().ToAtomicString();

  AtomicString uri(ConsumeStringOrURI(prelude));
  if (uri.IsNull() || !prelude.AtEnd())
    return nullptr;  // Parse error, expected string or URI

  return StyleRuleNamespace::Create(namespace_prefix, uri);
}

StyleRuleMedia* CSSParserImpl::ConsumeMediaRule(CSSParserTokenRange prelude,
                                                CSSParserTokenRange block) {
  HeapVector<Member<StyleRuleBase>> rules;

  if (observer_wrapper_) {
    observer_wrapper_->Observer().StartRuleHeader(
        StyleRule::kMedia, observer_wrapper_->StartOffset(prelude));
    observer_wrapper_->Observer().EndRuleHeader(
        observer_wrapper_->EndOffset(prelude));
    observer_wrapper_->Observer().StartRuleBody(
        observer_wrapper_->PreviousTokenStartOffset(block));
  }

  if (style_sheet_)
    style_sheet_->SetHasMediaQueries();

  ConsumeRuleList(block, kRegularRuleList,
                  [&rules](StyleRuleBase* rule) { rules.push_back(rule); });

  if (observer_wrapper_)
    observer_wrapper_->Observer().EndRuleBody(
        observer_wrapper_->EndOffset(block));

  return StyleRuleMedia::Create(MediaQueryParser::ParseMediaQuerySet(prelude),
                                rules);
}

StyleRuleSupports* CSSParserImpl::ConsumeSupportsRule(
    CSSParserTokenRange prelude,
    CSSParserTokenRange block) {
  CSSSupportsParser::SupportsResult supported =
      CSSSupportsParser::SupportsCondition(prelude, *this,
                                           CSSSupportsParser::kForAtRule);
  if (supported == CSSSupportsParser::kInvalid)
    return nullptr;  // Parse error, invalid @supports condition

  if (observer_wrapper_) {
    observer_wrapper_->Observer().StartRuleHeader(
        StyleRule::kSupports, observer_wrapper_->StartOffset(prelude));
    observer_wrapper_->Observer().EndRuleHeader(
        observer_wrapper_->EndOffset(prelude));
    observer_wrapper_->Observer().StartRuleBody(
        observer_wrapper_->PreviousTokenStartOffset(block));
  }

  HeapVector<Member<StyleRuleBase>> rules;
  ConsumeRuleList(block, kRegularRuleList,
                  [&rules](StyleRuleBase* rule) { rules.push_back(rule); });

  if (observer_wrapper_)
    observer_wrapper_->Observer().EndRuleBody(
        observer_wrapper_->EndOffset(block));

  return StyleRuleSupports::Create(prelude.Serialize().StripWhiteSpace(),
                                   supported, rules);
}

StyleRuleViewport* CSSParserImpl::ConsumeViewportRule(
    CSSParserTokenRange prelude,
    CSSParserTokenRange block) {
  // Allow @viewport rules from UA stylesheets even if the feature is disabled.
  if (!RuntimeEnabledFeatures::CSSViewportEnabled() &&
      !IsUASheetBehavior(context_->Mode()))
    return nullptr;

  if (!prelude.AtEnd())
    return nullptr;  // Parser error; @viewport prelude should be empty

  if (observer_wrapper_) {
    unsigned end_offset = observer_wrapper_->EndOffset(prelude);
    observer_wrapper_->Observer().StartRuleHeader(
        StyleRule::kViewport, observer_wrapper_->StartOffset(prelude));
    observer_wrapper_->Observer().EndRuleHeader(end_offset);
    observer_wrapper_->Observer().StartRuleBody(end_offset);
    observer_wrapper_->Observer().EndRuleBody(end_offset);
  }

  if (style_sheet_)
    style_sheet_->SetHasViewportRule();

  ConsumeDeclarationList(block, StyleRule::kViewport);
  return StyleRuleViewport::Create(
      CreateStylePropertySet(parsed_properties_, kCSSViewportRuleMode));
}

StyleRuleFontFace* CSSParserImpl::ConsumeFontFaceRule(
    CSSParserTokenRange prelude,
    CSSParserTokenRange block) {
  if (!prelude.AtEnd())
    return nullptr;  // Parse error; @font-face prelude should be empty

  if (observer_wrapper_) {
    unsigned end_offset = observer_wrapper_->EndOffset(prelude);
    observer_wrapper_->Observer().StartRuleHeader(
        StyleRule::kFontFace, observer_wrapper_->StartOffset(prelude));
    observer_wrapper_->Observer().EndRuleHeader(end_offset);
    observer_wrapper_->Observer().StartRuleBody(end_offset);
    observer_wrapper_->Observer().EndRuleBody(end_offset);
  }

  if (style_sheet_)
    style_sheet_->SetHasFontFaceRule();

  ConsumeDeclarationList(block, StyleRule::kFontFace);
  return StyleRuleFontFace::Create(
      CreateStylePropertySet(parsed_properties_, kCSSFontFaceRuleMode));
}

StyleRuleKeyframes* CSSParserImpl::ConsumeKeyframesRule(
    bool webkit_prefixed,
    CSSParserTokenRange prelude,
    CSSParserTokenRange block) {
  CSSParserTokenRange range_copy = prelude;  // For inspector callbacks
  const CSSParserToken& name_token = prelude.ConsumeIncludingWhitespace();
  if (!prelude.AtEnd())
    return nullptr;  // Parse error; expected single non-whitespace token in
                     // @keyframes header

  String name;
  if (name_token.GetType() == kIdentToken) {
    name = name_token.Value().ToString();
  } else if (name_token.GetType() == kStringToken && webkit_prefixed) {
    context_->Count(WebFeature::kQuotedKeyframesRule);
    name = name_token.Value().ToString();
  } else {
    return nullptr;  // Parse error; expected ident token in @keyframes header
  }

  if (observer_wrapper_) {
    observer_wrapper_->Observer().StartRuleHeader(
        StyleRule::kKeyframes, observer_wrapper_->StartOffset(range_copy));
    observer_wrapper_->Observer().EndRuleHeader(
        observer_wrapper_->EndOffset(prelude));
    observer_wrapper_->Observer().StartRuleBody(
        observer_wrapper_->PreviousTokenStartOffset(block));
    observer_wrapper_->Observer().EndRuleBody(
        observer_wrapper_->EndOffset(block));
  }

  StyleRuleKeyframes* keyframe_rule = StyleRuleKeyframes::Create();
  ConsumeRuleList(
      block, kKeyframesRuleList, [keyframe_rule](StyleRuleBase* keyframe) {
        keyframe_rule->ParserAppendKeyframe(ToStyleRuleKeyframe(keyframe));
      });
  keyframe_rule->SetName(name);
  keyframe_rule->SetVendorPrefixed(webkit_prefixed);
  return keyframe_rule;
}

StyleRulePage* CSSParserImpl::ConsumePageRule(CSSParserTokenRange prelude,
                                              CSSParserTokenRange block) {
  CSSSelectorList selector_list = ParsePageSelector(prelude, style_sheet_);
  if (!selector_list.IsValid())
    return nullptr;  // Parse error, invalid @page selector

  if (observer_wrapper_) {
    unsigned end_offset = observer_wrapper_->EndOffset(prelude);
    observer_wrapper_->Observer().StartRuleHeader(
        StyleRule::kPage, observer_wrapper_->StartOffset(prelude));
    observer_wrapper_->Observer().EndRuleHeader(end_offset);
  }

  ConsumeDeclarationList(block, StyleRule::kStyle);

  return StyleRulePage::Create(
      std::move(selector_list),
      CreateStylePropertySet(parsed_properties_, context_->Mode()));
}

void CSSParserImpl::ConsumeApplyRule(CSSParserTokenRange prelude) {
  DCHECK(RuntimeEnabledFeatures::CSSApplyAtRulesEnabled());

  const CSSParserToken& ident = prelude.ConsumeIncludingWhitespace();
  if (!prelude.AtEnd() || !CSSVariableParser::IsValidVariableName(ident))
    return;  // Parse error, expected a single custom property name
  parsed_properties_.push_back(CSSProperty(
      CSSPropertyApplyAtRule,
      *CSSCustomIdentValue::Create(ident.Value().ToAtomicString())));
}

StyleRuleKeyframe* CSSParserImpl::ConsumeKeyframeStyleRule(
    CSSParserTokenRange prelude,
    CSSParserTokenRange block) {
  std::unique_ptr<Vector<double>> key_list = ConsumeKeyframeKeyList(prelude);
  if (!key_list)
    return nullptr;

  if (observer_wrapper_) {
    observer_wrapper_->Observer().StartRuleHeader(
        StyleRule::kKeyframe, observer_wrapper_->StartOffset(prelude));
    observer_wrapper_->Observer().EndRuleHeader(
        observer_wrapper_->EndOffset(prelude));
  }

  ConsumeDeclarationList(block, StyleRule::kKeyframe);
  return StyleRuleKeyframe::Create(
      std::move(key_list),
      CreateStylePropertySet(parsed_properties_, context_->Mode()));
}

static void ObserveSelectors(CSSParserObserverWrapper& wrapper,
                             CSSParserTokenRange selectors) {
  // This is easier than hooking into the CSSSelectorParser
  selectors.ConsumeWhitespace();
  CSSParserTokenRange original_range = selectors;
  wrapper.Observer().StartRuleHeader(StyleRule::kStyle,
                                     wrapper.StartOffset(original_range));

  while (!selectors.AtEnd()) {
    const CSSParserToken* selector_start = &selectors.Peek();
    while (!selectors.AtEnd() && selectors.Peek().GetType() != kCommaToken)
      selectors.ConsumeComponentValue();
    CSSParserTokenRange selector =
        selectors.MakeSubRange(selector_start, &selectors.Peek());
    selectors.ConsumeIncludingWhitespace();

    wrapper.Observer().ObserveSelector(wrapper.StartOffset(selector),
                                       wrapper.EndOffset(selector));
  }

  wrapper.Observer().EndRuleHeader(wrapper.EndOffset(original_range));
}

StyleRule* CSSParserImpl::ConsumeStyleRule(CSSParserTokenRange prelude,
                                           CSSParserTokenRange block) {
  CSSSelectorList selector_list =
      CSSSelectorParser::ParseSelector(prelude, context_, style_sheet_);
  if (!selector_list.IsValid())
    return nullptr;  // Parse error, invalid selector list

  // TODO(csharrison): How should we lazily parse css that needs the observer?
  if (observer_wrapper_) {
    ObserveSelectors(*observer_wrapper_, prelude);
  } else if (lazy_state_ &&
             lazy_state_->ShouldLazilyParseProperties(selector_list, block)) {
    DCHECK(style_sheet_);
    return StyleRule::CreateLazy(std::move(selector_list),
                                 lazy_state_->CreateLazyParser(block));
  }
  ConsumeDeclarationList(block, StyleRule::kStyle);

  return StyleRule::Create(
      std::move(selector_list),
      CreateStylePropertySet(parsed_properties_, context_->Mode()));
}

void CSSParserImpl::ConsumeDeclarationList(CSSParserTokenRange range,
                                           StyleRule::RuleType rule_type) {
  DCHECK(parsed_properties_.IsEmpty());

  bool use_observer = observer_wrapper_ && (rule_type == StyleRule::kStyle ||
                                            rule_type == StyleRule::kKeyframe);
  if (use_observer) {
    observer_wrapper_->Observer().StartRuleBody(
        observer_wrapper_->PreviousTokenStartOffset(range));
    observer_wrapper_->SkipCommentsBefore(range, true);
  }

  while (!range.AtEnd()) {
    switch (range.Peek().GetType()) {
      case kWhitespaceToken:
      case kSemicolonToken:
        range.Consume();
        break;
      case kIdentToken: {
        const CSSParserToken* declaration_start = &range.Peek();

        if (use_observer)
          observer_wrapper_->YieldCommentsBefore(range);

        while (!range.AtEnd() && range.Peek().GetType() != kSemicolonToken)
          range.ConsumeComponentValue();

        ConsumeDeclaration(range.MakeSubRange(declaration_start, &range.Peek()),
                           rule_type);

        if (use_observer)
          observer_wrapper_->SkipCommentsBefore(range, false);
        break;
      }
      case kAtKeywordToken: {
        AllowedRulesType allowed_rules =
            rule_type == StyleRule::kStyle &&
                    RuntimeEnabledFeatures::CSSApplyAtRulesEnabled()
                ? kApplyRules
                : kNoRules;
        StyleRuleBase* rule = ConsumeAtRule(range, allowed_rules);
        DCHECK(!rule);
        break;
      }
      default:  // Parse error, unexpected token in declaration list
        while (!range.AtEnd() && range.Peek().GetType() != kSemicolonToken)
          range.ConsumeComponentValue();
        break;
    }
  }

  // Yield remaining comments
  if (use_observer) {
    observer_wrapper_->YieldCommentsBefore(range);
    observer_wrapper_->Observer().EndRuleBody(
        observer_wrapper_->EndOffset(range));
  }
}

void CSSParserImpl::ConsumeDeclaration(CSSParserTokenRange range,
                                       StyleRule::RuleType rule_type) {
  CSSParserTokenRange range_copy = range;  // For inspector callbacks

  DCHECK_EQ(range.Peek().GetType(), kIdentToken);
  const CSSParserToken& token = range.ConsumeIncludingWhitespace();
  CSSPropertyID unresolved_property = token.ParseAsUnresolvedCSSPropertyID();
  if (range.Consume().GetType() != kColonToken)
    return;  // Parse error

  bool important = false;
  const CSSParserToken* declaration_value_end = range.end();
  const CSSParserToken* last = range.end() - 1;
  while (last->GetType() == kWhitespaceToken)
    --last;
  if (last->GetType() == kIdentToken &&
      EqualIgnoringASCIICase(last->Value(), "important")) {
    --last;
    while (last->GetType() == kWhitespaceToken)
      --last;
    if (last->GetType() == kDelimiterToken && last->Delimiter() == '!') {
      important = true;
      declaration_value_end = last;
    }
  }

  if (important &&
      (rule_type == StyleRule::kFontFace || rule_type == StyleRule::kKeyframe))
    return;

  size_t properties_count = parsed_properties_.size();

  if (unresolved_property == CSSPropertyVariable) {
    if (rule_type != StyleRule::kStyle && rule_type != StyleRule::kKeyframe)
      return;
    AtomicString variable_name = token.Value().ToAtomicString();
    bool is_animation_tainted = rule_type == StyleRule::kKeyframe;
    ConsumeVariableValue(
        range.MakeSubRange(&range.Peek(), declaration_value_end), variable_name,
        important, is_animation_tainted);
  } else if (unresolved_property != CSSPropertyInvalid) {
    if (style_sheet_ && style_sheet_->SingleOwnerDocument())
      Deprecation::WarnOnDeprecatedProperties(
          style_sheet_->SingleOwnerDocument()->GetFrame(), unresolved_property);
    ConsumeDeclarationValue(
        range.MakeSubRange(&range.Peek(), declaration_value_end),
        unresolved_property, important, rule_type);
  }

  if (observer_wrapper_ &&
      (rule_type == StyleRule::kStyle || rule_type == StyleRule::kKeyframe)) {
    observer_wrapper_->Observer().ObserveProperty(
        observer_wrapper_->StartOffset(range_copy),
        observer_wrapper_->EndOffset(range_copy), important,
        parsed_properties_.size() != properties_count);
  }
}

void CSSParserImpl::ConsumeVariableValue(CSSParserTokenRange range,
                                         const AtomicString& variable_name,
                                         bool important,
                                         bool is_animation_tainted) {
  if (CSSCustomPropertyDeclaration* value =
          CSSVariableParser::ParseDeclarationValue(variable_name, range,
                                                   is_animation_tainted)) {
    parsed_properties_.push_back(
        CSSProperty(CSSPropertyVariable, *value, important));
    context_->Count(context_->Mode(), CSSPropertyVariable);
  }
}

void CSSParserImpl::ConsumeDeclarationValue(CSSParserTokenRange range,
                                            CSSPropertyID unresolved_property,
                                            bool important,
                                            StyleRule::RuleType rule_type) {
  CSSPropertyParser::ParseValue(unresolved_property, important, range, context_,
                                parsed_properties_, rule_type);
}

std::unique_ptr<Vector<double>> CSSParserImpl::ConsumeKeyframeKeyList(
    CSSParserTokenRange range) {
  std::unique_ptr<Vector<double>> result = WTF::WrapUnique(new Vector<double>);
  while (true) {
    range.ConsumeWhitespace();
    const CSSParserToken& token = range.ConsumeIncludingWhitespace();
    if (token.GetType() == kPercentageToken && token.NumericValue() >= 0 &&
        token.NumericValue() <= 100)
      result->push_back(token.NumericValue() / 100);
    else if (token.GetType() == kIdentToken &&
             EqualIgnoringASCIICase(token.Value(), "from"))
      result->push_back(0);
    else if (token.GetType() == kIdentToken &&
             EqualIgnoringASCIICase(token.Value(), "to"))
      result->push_back(1);
    else
      return nullptr;  // Parser error, invalid value in keyframe selector
    if (range.AtEnd())
      return result;
    if (range.Consume().GetType() != kCommaToken)
      return nullptr;  // Parser error
  }
}

}  // namespace blink
