/*
 * (C) 1999-2003 Lars Knoll (knoll@kde.org)
 * Copyright (C) 2004, 2006, 2007, 2012 Apple Inc. 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 "core/css/StyleSheetContents.h"

#include "core/css/CSSStyleSheet.h"
#include "core/css/CSSTiming.h"
#include "core/css/StylePropertySet.h"
#include "core/css/StyleRule.h"
#include "core/css/StyleRuleImport.h"
#include "core/css/StyleRuleNamespace.h"
#include "core/css/parser/CSSParser.h"
#include "core/dom/Document.h"
#include "core/dom/Node.h"
#include "core/dom/StyleEngine.h"
#include "core/frame/UseCounter.h"
#include "core/inspector/InspectorTraceEvents.h"
#include "core/loader/resource/CSSStyleSheetResource.h"
#include "platform/Histogram.h"
#include "platform/instrumentation/tracing/TraceEvent.h"
#include "platform/weborigin/SecurityOrigin.h"

namespace blink {

// static
const Document* StyleSheetContents::singleOwnerDocument(
    const StyleSheetContents* styleSheetContents) {
  // TODO(https://crbug.com/242125): We may want to handle stylesheets that have
  // multiple owners when this is used for UseCounter.
  if (styleSheetContents && styleSheetContents->hasSingleOwnerNode())
    return styleSheetContents->singleOwnerDocument();
  return nullptr;
}

// Rough size estimate for the memory cache.
unsigned StyleSheetContents::estimatedSizeInBytes() const {
  // Note that this does not take into account size of the strings hanging from
  // various objects. The assumption is that nearly all of of them are atomic
  // and would exist anyway.
  unsigned size = sizeof(*this);

  // FIXME: This ignores the children of media rules.
  // Most rules are StyleRules.
  size += ruleCount() * StyleRule::averageSizeInBytes();

  for (unsigned i = 0; i < m_importRules.size(); ++i) {
    if (StyleSheetContents* sheet = m_importRules[i]->styleSheet())
      size += sheet->estimatedSizeInBytes();
  }
  return size;
}

StyleSheetContents::StyleSheetContents(StyleRuleImport* ownerRule,
                                       const String& originalURL,
                                       const CSSParserContext* context)
    : m_ownerRule(ownerRule),
      m_originalURL(originalURL),
      m_defaultNamespace(starAtom),
      m_hasSyntacticallyValidCSSHeader(true),
      m_didLoadErrorOccur(false),
      m_isMutable(false),
      m_hasFontFaceRule(false),
      m_hasViewportRule(false),
      m_hasMediaQueries(false),
      m_hasSingleOwnerDocument(true),
      m_isUsedFromTextCache(false),
      m_parserContext(context) {}

StyleSheetContents::StyleSheetContents(const StyleSheetContents& o)
    : m_ownerRule(nullptr),
      m_originalURL(o.m_originalURL),
      m_importRules(o.m_importRules.size()),
      m_namespaceRules(o.m_namespaceRules.size()),
      m_childRules(o.m_childRules.size()),
      m_namespaces(o.m_namespaces),
      m_defaultNamespace(o.m_defaultNamespace),
      m_hasSyntacticallyValidCSSHeader(o.m_hasSyntacticallyValidCSSHeader),
      m_didLoadErrorOccur(false),
      m_isMutable(false),
      m_hasFontFaceRule(o.m_hasFontFaceRule),
      m_hasViewportRule(o.m_hasViewportRule),
      m_hasMediaQueries(o.m_hasMediaQueries),
      m_hasSingleOwnerDocument(true),
      m_isUsedFromTextCache(false),
      m_parserContext(o.m_parserContext) {
  // FIXME: Copy import rules.
  ASSERT(o.m_importRules.isEmpty());

  for (unsigned i = 0; i < m_namespaceRules.size(); ++i) {
    m_namespaceRules[i] =
        static_cast<StyleRuleNamespace*>(o.m_namespaceRules[i]->copy());
  }

  // LazyParseCSS: Copying child rules is a strict point for lazy parsing, so
  // there is no need to copy lazy parsing state here.
  for (unsigned i = 0; i < m_childRules.size(); ++i)
    m_childRules[i] = o.m_childRules[i]->copy();
}

StyleSheetContents::~StyleSheetContents() {}

void StyleSheetContents::setHasSyntacticallyValidCSSHeader(bool isValidCss) {
  m_hasSyntacticallyValidCSSHeader = isValidCss;
}

bool StyleSheetContents::isCacheableForResource() const {
  // This would require dealing with multiple clients for load callbacks.
  if (!loadCompleted())
    return false;
  // FIXME: StyleSheets with media queries can't be cached because their RuleSet
  // is processed differently based off the media queries, which might resolve
  // differently depending on the context of the parent CSSStyleSheet (e.g.
  // if they are in differently sized iframes). Once RuleSets are media query
  // agnostic, we can restore sharing of StyleSheetContents with medea queries.
  if (m_hasMediaQueries)
    return false;
  // FIXME: Support copying import rules.
  if (!m_importRules.isEmpty())
    return false;
  // FIXME: Support cached stylesheets in import rules.
  if (m_ownerRule)
    return false;
  if (m_didLoadErrorOccur)
    return false;
  // It is not the original sheet anymore.
  if (m_isMutable)
    return false;
  // If the header is valid we are not going to need to check the
  // SecurityOrigin.
  // FIXME: Valid mime type avoids the check too.
  if (!m_hasSyntacticallyValidCSSHeader)
    return false;
  return true;
}

bool StyleSheetContents::isCacheableForStyleElement() const {
  // FIXME: Support copying import rules.
  if (!importRules().isEmpty())
    return false;
  // Until import rules are supported in cached sheets it's not possible for
  // loading to fail.
  DCHECK(!didLoadErrorOccur());
  // It is not the original sheet anymore.
  if (isMutable())
    return false;
  if (!hasSyntacticallyValidCSSHeader())
    return false;
  return true;
}

void StyleSheetContents::parserAppendRule(StyleRuleBase* rule) {
  if (rule->isImportRule()) {
    // Parser enforces that @import rules come before anything else
    ASSERT(m_childRules.isEmpty());
    StyleRuleImport* importRule = toStyleRuleImport(rule);
    if (importRule->mediaQueries())
      setHasMediaQueries();
    m_importRules.push_back(importRule);
    m_importRules.back()->setParentStyleSheet(this);
    m_importRules.back()->requestStyleSheet();
    return;
  }

  if (rule->isNamespaceRule()) {
    // Parser enforces that @namespace rules come before all rules other than
    // import/charset rules
    ASSERT(m_childRules.isEmpty());
    StyleRuleNamespace& namespaceRule = toStyleRuleNamespace(*rule);
    parserAddNamespace(namespaceRule.prefix(), namespaceRule.uri());
    m_namespaceRules.push_back(&namespaceRule);
    return;
  }

  m_childRules.push_back(rule);
}

void StyleSheetContents::setHasMediaQueries() {
  m_hasMediaQueries = true;
  if (parentStyleSheet())
    parentStyleSheet()->setHasMediaQueries();
}

StyleRuleBase* StyleSheetContents::ruleAt(unsigned index) const {
  SECURITY_DCHECK(index < ruleCount());

  if (index < m_importRules.size())
    return m_importRules[index].get();

  index -= m_importRules.size();

  if (index < m_namespaceRules.size())
    return m_namespaceRules[index].get();

  index -= m_namespaceRules.size();

  return m_childRules[index].get();
}

unsigned StyleSheetContents::ruleCount() const {
  return m_importRules.size() + m_namespaceRules.size() + m_childRules.size();
}

void StyleSheetContents::clearRules() {
  for (unsigned i = 0; i < m_importRules.size(); ++i) {
    ASSERT(m_importRules.at(i)->parentStyleSheet() == this);
    m_importRules[i]->clearParentStyleSheet();
  }
  m_importRules.clear();
  m_namespaceRules.clear();
  m_childRules.clear();
}

bool StyleSheetContents::wrapperInsertRule(StyleRuleBase* rule,
                                           unsigned index) {
  ASSERT(m_isMutable);
  SECURITY_DCHECK(index <= ruleCount());

  if (index < m_importRules.size() ||
      (index == m_importRules.size() && rule->isImportRule())) {
    // Inserting non-import rule before @import is not allowed.
    if (!rule->isImportRule())
      return false;

    StyleRuleImport* importRule = toStyleRuleImport(rule);
    if (importRule->mediaQueries())
      setHasMediaQueries();

    m_importRules.insert(index, importRule);
    m_importRules[index]->setParentStyleSheet(this);
    m_importRules[index]->requestStyleSheet();
    // FIXME: Stylesheet doesn't actually change meaningfully before the
    // imported sheets are loaded.
    return true;
  }
  // Inserting @import rule after a non-import rule is not allowed.
  if (rule->isImportRule())
    return false;

  index -= m_importRules.size();

  if (index < m_namespaceRules.size() ||
      (index == m_namespaceRules.size() && rule->isNamespaceRule())) {
    // Inserting non-namespace rules other than import rule before @namespace is
    // not allowed.
    if (!rule->isNamespaceRule())
      return false;
    // Inserting @namespace rule when rules other than import/namespace/charset
    // are present is not allowed.
    if (!m_childRules.isEmpty())
      return false;

    StyleRuleNamespace* namespaceRule = toStyleRuleNamespace(rule);
    m_namespaceRules.insert(index, namespaceRule);
    // For now to be compatible with IE and Firefox if namespace rule with same
    // prefix is added irrespective of adding the rule at any index, last added
    // rule's value is considered.
    // TODO (ramya.v@samsung.com): As per spec last valid rule should be
    // considered, which means if namespace rule is added in the middle of
    // existing namespace rules, rule which comes later in rule list with same
    // prefix needs to be considered.
    parserAddNamespace(namespaceRule->prefix(), namespaceRule->uri());
    return true;
  }

  if (rule->isNamespaceRule())
    return false;

  index -= m_namespaceRules.size();

  m_childRules.insert(index, rule);
  return true;
}

bool StyleSheetContents::wrapperDeleteRule(unsigned index) {
  ASSERT(m_isMutable);
  SECURITY_DCHECK(index < ruleCount());

  if (index < m_importRules.size()) {
    m_importRules[index]->clearParentStyleSheet();
    if (m_importRules[index]->isFontFaceRule())
      notifyRemoveFontFaceRule(toStyleRuleFontFace(m_importRules[index].get()));
    m_importRules.remove(index);
    return true;
  }
  index -= m_importRules.size();

  if (index < m_namespaceRules.size()) {
    if (!m_childRules.isEmpty())
      return false;
    m_namespaceRules.remove(index);
    return true;
  }
  index -= m_namespaceRules.size();

  if (m_childRules[index]->isFontFaceRule())
    notifyRemoveFontFaceRule(toStyleRuleFontFace(m_childRules[index].get()));
  m_childRules.remove(index);
  return true;
}

void StyleSheetContents::parserAddNamespace(const AtomicString& prefix,
                                            const AtomicString& uri) {
  ASSERT(!uri.isNull());
  if (prefix.isNull()) {
    m_defaultNamespace = uri;
    return;
  }
  PrefixNamespaceURIMap::AddResult result = m_namespaces.insert(prefix, uri);
  if (result.isNewEntry)
    return;
  result.storedValue->value = uri;
}

const AtomicString& StyleSheetContents::namespaceURIFromPrefix(
    const AtomicString& prefix) {
  return m_namespaces.at(prefix);
}

void StyleSheetContents::parseAuthorStyleSheet(
    const CSSStyleSheetResource* cachedStyleSheet,
    const SecurityOrigin* securityOrigin) {
  TRACE_EVENT1("blink,devtools.timeline", "ParseAuthorStyleSheet", "data",
               InspectorParseAuthorStyleSheetEvent::data(cachedStyleSheet));
  double startTime = monotonicallyIncreasingTime();

  bool isSameOriginRequest =
      securityOrigin && securityOrigin->canRequest(baseURL());

  // When the response was fetched via the Service Worker, the original URL may
  // not be same as the base URL.
  // TODO(horo): When we will use the original URL as the base URL, we can
  // remove this check. crbug.com/553535
  if (isSameOriginRequest &&
      cachedStyleSheet->response().wasFetchedViaServiceWorker()) {
    const KURL originalURL(
        cachedStyleSheet->response().originalURLViaServiceWorker());
    // |originalURL| is empty when the response is created in the SW.
    if (!originalURL.isEmpty() && !securityOrigin->canRequest(originalURL))
      isSameOriginRequest = false;
  }

  CSSStyleSheetResource::MIMETypeCheck mimeTypeCheck =
      isQuirksModeBehavior(m_parserContext->mode()) && isSameOriginRequest
          ? CSSStyleSheetResource::MIMETypeCheck::Lax
          : CSSStyleSheetResource::MIMETypeCheck::Strict;
  String sheetText = cachedStyleSheet->sheetText(mimeTypeCheck);

  const ResourceResponse& response = cachedStyleSheet->response();
  m_sourceMapURL = response.httpHeaderField(HTTPNames::SourceMap);
  if (m_sourceMapURL.isEmpty()) {
    // Try to get deprecated header.
    m_sourceMapURL = response.httpHeaderField(HTTPNames::X_SourceMap);
  }

  const CSSParserContext* context =
      CSSParserContext::createWithStyleSheetContents(parserContext(), this);
  CSSParser::parseSheet(context, this, sheetText,
                        RuntimeEnabledFeatures::lazyParseCSSEnabled());

  DEFINE_STATIC_LOCAL(CustomCountHistogram, parseHistogram,
                      ("Style.AuthorStyleSheet.ParseTime", 0, 10000000, 50));
  double parseDurationSeconds = (monotonicallyIncreasingTime() - startTime);
  parseHistogram.count(parseDurationSeconds * 1000 * 1000);
  if (Document* document = singleOwnerDocument()) {
    CSSTiming::from(*document).recordAuthorStyleSheetParseTime(
        parseDurationSeconds);
  }
}

void StyleSheetContents::parseString(const String& sheetText) {
  parseStringAtPosition(sheetText, TextPosition::minimumPosition());
}

void StyleSheetContents::parseStringAtPosition(
    const String& sheetText,
    const TextPosition& startPosition) {
  const CSSParserContext* context =
      CSSParserContext::createWithStyleSheetContents(parserContext(), this);
  CSSParser::parseSheet(context, this, sheetText);
}

bool StyleSheetContents::isLoading() const {
  for (unsigned i = 0; i < m_importRules.size(); ++i) {
    if (m_importRules[i]->isLoading())
      return true;
  }
  return false;
}

bool StyleSheetContents::loadCompleted() const {
  StyleSheetContents* parentSheet = parentStyleSheet();
  if (parentSheet)
    return parentSheet->loadCompleted();

  StyleSheetContents* root = rootStyleSheet();
  return root->m_loadingClients.isEmpty();
}

void StyleSheetContents::checkLoaded() {
  if (isLoading())
    return;

  StyleSheetContents* parentSheet = parentStyleSheet();
  if (parentSheet) {
    parentSheet->checkLoaded();
    return;
  }

  ASSERT(this == rootStyleSheet());
  if (m_loadingClients.isEmpty())
    return;

  // Avoid |CSSSStyleSheet| and |ownerNode| being deleted by scripts that run
  // via ScriptableDocumentParser::executeScriptsWaitingForResources(). Also
  // protect the |CSSStyleSheet| from being deleted during iteration via the
  // |sheetLoaded| method.
  //
  // When a sheet is loaded it is moved from the set of loading clients
  // to the set of completed clients. We therefore need the copy in order to
  // not modify the set while iterating it.
  HeapVector<Member<CSSStyleSheet>> loadingClients;
  copyToVector(m_loadingClients, loadingClients);

  for (unsigned i = 0; i < loadingClients.size(); ++i) {
    if (loadingClients[i]->loadCompleted())
      continue;

    // sheetLoaded might be invoked after its owner node is removed from
    // document.
    if (Node* ownerNode = loadingClients[i]->ownerNode()) {
      if (loadingClients[i]->sheetLoaded())
        ownerNode->notifyLoadedSheetAndAllCriticalSubresources(
            m_didLoadErrorOccur ? Node::ErrorOccurredLoadingSubresource
                                : Node::NoErrorLoadingSubresource);
    }
  }
}

void StyleSheetContents::notifyLoadedSheet(const CSSStyleSheetResource* sheet) {
  ASSERT(sheet);
  m_didLoadErrorOccur |= sheet->errorOccurred();
  // updateLayoutIgnorePendingStyleSheets can cause us to create the RuleSet on
  // this sheet before its imports have loaded. So clear the RuleSet when the
  // imports load since the import's subrules are flattened into its parent
  // sheet's RuleSet.
  clearRuleSet();
}

void StyleSheetContents::startLoadingDynamicSheet() {
  StyleSheetContents* root = rootStyleSheet();
  for (const auto& client : root->m_loadingClients)
    client->startLoadingDynamicSheet();
  // Copy the completed clients to a vector for iteration.
  // startLoadingDynamicSheet will move the style sheet from the completed state
  // to the loading state which modifies the set of completed clients. We
  // therefore need the copy in order to not modify the set of completed clients
  // while iterating it.
  HeapVector<Member<CSSStyleSheet>> completedClients;
  copyToVector(root->m_completedClients, completedClients);
  for (unsigned i = 0; i < completedClients.size(); ++i)
    completedClients[i]->startLoadingDynamicSheet();
}

StyleSheetContents* StyleSheetContents::rootStyleSheet() const {
  const StyleSheetContents* root = this;
  while (root->parentStyleSheet())
    root = root->parentStyleSheet();
  return const_cast<StyleSheetContents*>(root);
}

bool StyleSheetContents::hasSingleOwnerNode() const {
  return rootStyleSheet()->hasOneClient();
}

Node* StyleSheetContents::singleOwnerNode() const {
  StyleSheetContents* root = rootStyleSheet();
  if (!root->hasOneClient())
    return nullptr;
  if (root->m_loadingClients.size())
    return (*root->m_loadingClients.begin())->ownerNode();
  return (*root->m_completedClients.begin())->ownerNode();
}

Document* StyleSheetContents::singleOwnerDocument() const {
  StyleSheetContents* root = rootStyleSheet();
  return root->clientSingleOwnerDocument();
}

Document* StyleSheetContents::anyOwnerDocument() const {
  return rootStyleSheet()->clientAnyOwnerDocument();
}

static bool childRulesHaveFailedOrCanceledSubresources(
    const HeapVector<Member<StyleRuleBase>>& rules) {
  for (unsigned i = 0; i < rules.size(); ++i) {
    const StyleRuleBase* rule = rules[i].get();
    switch (rule->type()) {
      case StyleRuleBase::Style:
        if (toStyleRule(rule)->propertiesHaveFailedOrCanceledSubresources())
          return true;
        break;
      case StyleRuleBase::FontFace:
        if (toStyleRuleFontFace(rule)
                ->properties()
                .hasFailedOrCanceledSubresources())
          return true;
        break;
      case StyleRuleBase::Media:
        if (childRulesHaveFailedOrCanceledSubresources(
                toStyleRuleMedia(rule)->childRules()))
          return true;
        break;
      case StyleRuleBase::Charset:
      case StyleRuleBase::Import:
      case StyleRuleBase::Namespace:
        ASSERT_NOT_REACHED();
      case StyleRuleBase::Page:
      case StyleRuleBase::Keyframes:
      case StyleRuleBase::Keyframe:
      case StyleRuleBase::Supports:
      case StyleRuleBase::Viewport:
        break;
    }
  }
  return false;
}

bool StyleSheetContents::hasFailedOrCanceledSubresources() const {
  ASSERT(isCacheableForResource());
  return childRulesHaveFailedOrCanceledSubresources(m_childRules);
}

Document* StyleSheetContents::clientAnyOwnerDocument() const {
  if (clientSize() <= 0)
    return nullptr;
  if (m_loadingClients.size())
    return (*m_loadingClients.begin())->ownerDocument();
  return (*m_completedClients.begin())->ownerDocument();
}

Document* StyleSheetContents::clientSingleOwnerDocument() const {
  return m_hasSingleOwnerDocument ? clientAnyOwnerDocument() : nullptr;
}

StyleSheetContents* StyleSheetContents::parentStyleSheet() const {
  return m_ownerRule ? m_ownerRule->parentStyleSheet() : nullptr;
}

void StyleSheetContents::registerClient(CSSStyleSheet* sheet) {
  ASSERT(!m_loadingClients.contains(sheet) &&
         !m_completedClients.contains(sheet));

  // InspectorCSSAgent::buildObjectForRule creates CSSStyleSheet without any
  // owner node.
  if (!sheet->ownerDocument())
    return;

  if (Document* document = clientSingleOwnerDocument()) {
    if (sheet->ownerDocument() != document)
      m_hasSingleOwnerDocument = false;
  }
  m_loadingClients.insert(sheet);
}

void StyleSheetContents::unregisterClient(CSSStyleSheet* sheet) {
  m_loadingClients.erase(sheet);
  m_completedClients.erase(sheet);

  if (!sheet->ownerDocument() || !m_loadingClients.isEmpty() ||
      !m_completedClients.isEmpty())
    return;

  m_hasSingleOwnerDocument = true;
}

void StyleSheetContents::clientLoadCompleted(CSSStyleSheet* sheet) {
  ASSERT(m_loadingClients.contains(sheet) || !sheet->ownerDocument());
  m_loadingClients.erase(sheet);
  // In m_ownerNode->sheetLoaded, the CSSStyleSheet might be detached.
  // (i.e. clearOwnerNode was invoked.)
  // In this case, we don't need to add the stylesheet to completed clients.
  if (!sheet->ownerDocument())
    return;
  m_completedClients.insert(sheet);
}

void StyleSheetContents::clientLoadStarted(CSSStyleSheet* sheet) {
  ASSERT(m_completedClients.contains(sheet));
  m_completedClients.erase(sheet);
  m_loadingClients.insert(sheet);
}

void StyleSheetContents::setReferencedFromResource(
    CSSStyleSheetResource* resource) {
  DCHECK(resource);
  DCHECK(!isReferencedFromResource());
  DCHECK(isCacheableForResource());
  m_referencedFromResource = resource;
}

void StyleSheetContents::clearReferencedFromResource() {
  DCHECK(isReferencedFromResource());
  DCHECK(isCacheableForResource());
  m_referencedFromResource = nullptr;
}

RuleSet& StyleSheetContents::ensureRuleSet(const MediaQueryEvaluator& medium,
                                           AddRuleFlags addRuleFlags) {
  if (!m_ruleSet) {
    m_ruleSet = RuleSet::create();
    m_ruleSet->addRulesFromSheet(this, medium, addRuleFlags);
  }
  return *m_ruleSet.get();
}

static void setNeedsActiveStyleUpdateForClients(
    HeapHashSet<WeakMember<CSSStyleSheet>>& clients) {
  for (const auto& sheet : clients) {
    Document* document = sheet->ownerDocument();
    Node* node = sheet->ownerNode();
    if (!document || !node || !node->isConnected())
      continue;
    document->styleEngine().setNeedsActiveStyleUpdate(node->treeScope());
  }
}

void StyleSheetContents::clearRuleSet() {
  if (StyleSheetContents* parentSheet = parentStyleSheet())
    parentSheet->clearRuleSet();

  if (!m_ruleSet)
    return;

  m_ruleSet.clear();
  setNeedsActiveStyleUpdateForClients(m_loadingClients);
  setNeedsActiveStyleUpdateForClients(m_completedClients);
}

static void removeFontFaceRules(HeapHashSet<WeakMember<CSSStyleSheet>>& clients,
                                const StyleRuleFontFace* fontFaceRule) {
  for (const auto& sheet : clients) {
    if (Node* ownerNode = sheet->ownerNode())
      ownerNode->document().styleEngine().removeFontFaceRules(
          HeapVector<Member<const StyleRuleFontFace>>(1, fontFaceRule));
  }
}

void StyleSheetContents::notifyRemoveFontFaceRule(
    const StyleRuleFontFace* fontFaceRule) {
  StyleSheetContents* root = rootStyleSheet();
  removeFontFaceRules(root->m_loadingClients, fontFaceRule);
  removeFontFaceRules(root->m_completedClients, fontFaceRule);
}

static void findFontFaceRulesFromRules(
    const HeapVector<Member<StyleRuleBase>>& rules,
    HeapVector<Member<const StyleRuleFontFace>>& fontFaceRules) {
  for (unsigned i = 0; i < rules.size(); ++i) {
    StyleRuleBase* rule = rules[i].get();

    if (rule->isFontFaceRule()) {
      fontFaceRules.push_back(toStyleRuleFontFace(rule));
    } else if (rule->isMediaRule()) {
      StyleRuleMedia* mediaRule = toStyleRuleMedia(rule);
      // We cannot know whether the media rule matches or not, but
      // for safety, remove @font-face in the media rule (if exists).
      findFontFaceRulesFromRules(mediaRule->childRules(), fontFaceRules);
    }
  }
}

void StyleSheetContents::findFontFaceRules(
    HeapVector<Member<const StyleRuleFontFace>>& fontFaceRules) {
  for (unsigned i = 0; i < m_importRules.size(); ++i) {
    if (!m_importRules[i]->styleSheet())
      continue;
    m_importRules[i]->styleSheet()->findFontFaceRules(fontFaceRules);
  }

  findFontFaceRulesFromRules(childRules(), fontFaceRules);
}

DEFINE_TRACE(StyleSheetContents) {
  visitor->trace(m_ownerRule);
  visitor->trace(m_importRules);
  visitor->trace(m_namespaceRules);
  visitor->trace(m_childRules);
  visitor->trace(m_loadingClients);
  visitor->trace(m_completedClients);
  visitor->trace(m_ruleSet);
  visitor->trace(m_referencedFromResource);
  visitor->trace(m_parserContext);
}

}  // namespace blink
