Beispiel #1
0
TEST_F(StyleEngineTest, AnalyzedInject) {
  document().body()->setInnerHTML(
      "<style>div { color: red }</style><div id='t1'>Green</div><div></div>");
  document().view()->updateAllLifecyclePhases();

  Element* t1 = document().getElementById("t1");
  ASSERT_TRUE(t1);
  ASSERT_TRUE(t1->computedStyle());
  EXPECT_EQ(makeRGB(255, 0, 0),
            t1->computedStyle()->visitedDependentColor(CSSPropertyColor));

  unsigned beforeCount = styleEngine().styleForElementCount();

  StyleSheetContents* parsedSheet =
      StyleSheetContents::create(CSSParserContext(document(), nullptr));
  parsedSheet->parseString("#t1 { color: green }");
  styleEngine().injectAuthorSheet(parsedSheet);
  document().view()->updateAllLifecyclePhases();

  unsigned afterCount = styleEngine().styleForElementCount();
  EXPECT_EQ(1u, afterCount - beforeCount);

  ASSERT_TRUE(t1->computedStyle());
  EXPECT_EQ(makeRGB(0, 128, 0),
            t1->computedStyle()->visitedDependentColor(CSSPropertyColor));
}
Beispiel #2
0
PassRefPtrWillBeRawPtr<CSSStyleSheet> StyleEngine::createSheet(Element* e, const String& text, TextPosition startPosition, bool createdByParser)
{
    RefPtrWillBeRawPtr<CSSStyleSheet> styleSheet = nullptr;

    e->document().styleEngine()->addPendingSheet();

    if (!e->document().inQuirksMode()) {
        AtomicString textContent(text);

        WillBeHeapHashMap<AtomicString, RawPtrWillBeMember<StyleSheetContents> >::AddResult result = m_textToSheetCache.add(textContent, nullptr);
        if (result.isNewEntry || !result.storedValue->value) {
            styleSheet = StyleEngine::parseSheet(e, text, startPosition, createdByParser);
            if (result.isNewEntry && isCacheableForStyleElement(*styleSheet->contents())) {
                result.storedValue->value = styleSheet->contents();
                m_sheetToTextCache.add(styleSheet->contents(), textContent);
            }
        } else {
            StyleSheetContents* contents = result.storedValue->value;
            ASSERT(contents);
            ASSERT(isCacheableForStyleElement(*contents));
            ASSERT(contents->singleOwnerDocument() == e->document());
            styleSheet = CSSStyleSheet::createInline(contents, e, startPosition);
        }
    } else {
        // FIXME: currently we don't cache StyleSheetContents inQuirksMode.
        styleSheet = StyleEngine::parseSheet(e, text, startPosition, createdByParser);
    }

    ASSERT(styleSheet);
    styleSheet->setTitle(e->title());
    return styleSheet;
}
void ScopedStyleResolver::collectFeaturesTo(RuleFeatureSet& features, HashSet<const StyleSheetContents*>& visitedSharedStyleSheetContents)
{
    for (size_t i = 0; i < m_authorStyleSheets.size(); ++i) {
        StyleSheetContents* contents = m_authorStyleSheets[i]->contents();
        if (contents->hasOneClient() || visitedSharedStyleSheetContents.add(contents).isNewEntry)
            features.add(contents->ruleSet().features());
    }
}
 static CSSStyleSheet* createSheet(const String& cssText = String()) {
   StyleSheetContents* contents =
       StyleSheetContents::create(CSSParserContext(HTMLStandardMode, nullptr));
   contents->parseString(cssText);
   contents->ensureRuleSet(MediaQueryEvaluator(),
                           RuleHasDocumentSecurityOrigin);
   return CSSStyleSheet::create(contents);
 }
Beispiel #5
0
void WebDocument::insertStyleSheet(const WebString& sourceCode) {
  Document* document = unwrap<Document>();
  DCHECK(document);
  StyleSheetContents* parsedSheet =
      StyleSheetContents::create(CSSParserContext(*document, nullptr));
  parsedSheet->parseString(sourceCode);
  document->styleEngine().injectAuthorSheet(parsedSheet);
}
Beispiel #6
0
bool StyleSheetContents::loadCompleted() const {
    StyleSheetContents* parentSheet = parentStyleSheet();
    if (parentSheet)
        return parentSheet->loadCompleted();

    StyleSheetContents* root = rootStyleSheet();
    return root->m_loadingClients.isEmpty();
}
Beispiel #7
0
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();
}
void TreeScopeStyleSheetCollection::clearMediaQueryRuleSetStyleSheets()
{
    for (size_t i = 0; i < m_activeAuthorStyleSheets.size(); ++i) {
        StyleSheetContents* contents = m_activeAuthorStyleSheets[i]->contents();
        if (contents->hasMediaQueries())
            contents->clearRuleSet();
    }
}
static StyleSheetContents* parseUASheet(const String& str)
{
    StyleSheetContents* sheet = StyleSheetContents::create(CSSParserContext(UASheetMode, nullptr));
    sheet->parseString(str);
    // User Agent stylesheets are parsed once for the lifetime of the renderer
    // process and are intentionally leaked.
    LEAK_SANITIZER_IGNORE_OBJECT(sheet);
    return sheet;
}
Beispiel #10
0
TEST_F(StyleEngineTest, DocumentDirtyAfterInject) {
  StyleSheetContents* parsedSheet =
      StyleSheetContents::create(CSSParserContext(document(), nullptr));
  parsedSheet->parseString("div {}");
  styleEngine().injectAuthorSheet(parsedSheet);
  document().view()->updateAllLifecyclePhases();

  EXPECT_TRUE(isDocumentStyleSheetCollectionClean());
}
void ScopedStyleResolver::addRulesFromSheet(CSSStyleSheet* cssSheet, const MediaQueryEvaluator& medium, StyleResolver* resolver)
{
    m_authorStyleSheets.append(cssSheet);
    StyleSheetContents* sheet = cssSheet->contents();

    AddRuleFlags addRuleFlags = resolver->document().securityOrigin()->canRequest(sheet->baseURL()) ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState;
    const RuleSet& ruleSet = sheet->ensureRuleSet(medium, addRuleFlags);
    resolver->addMediaQueryResults(ruleSet.viewportDependentMediaQueryResults());
    resolver->processScopedRules(ruleSet, sheet->baseURL(), &m_scopingNode);
}
Beispiel #12
0
static bool isCacheableForStyleElement(const StyleSheetContents& contents)
{
    // Until import rules are supported in cached sheets it's not possible for loading to fail.
    ASSERT(!contents.didLoadErrorOccur());
    // It is not the original sheet anymore.
    if (contents.isMutable())
        return false;
    if (!contents.hasSyntacticallyValidCSSHeader())
        return false;
    return true;
}
void ScopedStyleResolver::appendCSSStyleSheet(CSSStyleSheet& cssSheet, const MediaQueryEvaluator& medium)
{
    unsigned index = m_authorStyleSheets.size();
    m_authorStyleSheets.append(&cssSheet);
    StyleSheetContents* sheet = cssSheet.contents();
    AddRuleFlags addRuleFlags = treeScope().document().securityOrigin()->canRequest(sheet->baseURL()) ? RuleHasDocumentSecurityOrigin : RuleHasNoSpecialState;
    const RuleSet& ruleSet = sheet->ensureRuleSet(medium, addRuleFlags);

    addKeyframeRules(ruleSet);
    addFontFaceRules(ruleSet);
    addTreeBoundaryCrossingRules(ruleSet, &cssSheet, index);
    treeScope().document().styleResolver()->addMediaQueryResults(ruleSet.viewportDependentMediaQueryResults());
}
void ScopedStyleResolver::collectFeaturesTo(RuleFeatureSet& features, WillBeHeapHashSet<RawPtrWillBeMember<const StyleSheetContents>>& visitedSharedStyleSheetContents) const
{
    for (size_t i = 0; i < m_authorStyleSheets.size(); ++i) {
        ASSERT(m_authorStyleSheets[i]->ownerNode());
        StyleSheetContents* contents = m_authorStyleSheets[i]->contents();
        if (contents->hasOneClient() || visitedSharedStyleSheetContents.add(contents).isNewEntry)
            features.add(contents->ruleSet().features());
    }

    if (!m_treeBoundaryCrossingRuleSet)
        return;

    for (const auto& rules : *m_treeBoundaryCrossingRuleSet)
        features.add(rules->m_ruleSet->features());
}
StyleSheetContents::StyleSheetContents(const StyleSheetContents& o)
    : RefCounted<StyleSheetContents>()
    , m_ownerRule(0)
    , m_originalURL(o.m_originalURL)
    , m_encodingFromCharsetRule(o.m_encodingFromCharsetRule)
    , m_importRules(o.m_importRules.size())
    , m_childRules(o.m_childRules.size())
    , m_namespaces(o.m_namespaces)
    , m_loadCompleted(true)
    , m_isUserStyleSheet(o.m_isUserStyleSheet)
    , m_hasSyntacticallyValidCSSHeader(o.m_hasSyntacticallyValidCSSHeader)
    , m_didLoadErrorOccur(false)
    , m_usesRemUnits(o.m_usesRemUnits)
    , m_isMutable(false)
    , m_isInMemoryCache(false)
    , m_parserContext(o.m_parserContext)
{
    ASSERT(o.isCacheable());

    // FIXME: Copy import rules.
    ASSERT(o.m_importRules.isEmpty());

    for (unsigned i = 0; i < m_childRules.size(); ++i)
        m_childRules[i] = o.m_childRules[i]->copy();
}
StyleSheetContents::StyleSheetContents(const StyleSheetContents& o)
    : m_ownerRule(nullptr)
    , m_originalURL(o.m_originalURL)
    , m_encodingFromCharsetRule(o.m_encodingFromCharsetRule)
    , m_importRules(o.m_importRules.size())
    , m_childRules(o.m_childRules.size())
    , m_namespaces(o.m_namespaces)
    , m_hasSyntacticallyValidCSSHeader(o.m_hasSyntacticallyValidCSSHeader)
    , m_didLoadErrorOccur(false)
    , m_usesRemUnits(o.m_usesRemUnits)
    , m_isMutable(false)
    , m_isInMemoryCache(false)
    , m_hasFontFaceRule(o.m_hasFontFaceRule)
    , m_hasMediaQueries(o.m_hasMediaQueries)
    , m_hasSingleOwnerDocument(true)
    , m_parserContext(o.m_parserContext)
{
    ASSERT(o.isCacheable());

    // FIXME: Copy import rules.
    ASSERT(o.m_importRules.isEmpty());

    for (unsigned i = 0; i < m_childRules.size(); ++i)
        m_childRules[i] = o.m_childRules[i]->copy();
}
Beispiel #17
0
StyleEngineTest::RuleSetInvalidation
StyleEngineTest::scheduleInvalidationsForRules(TreeScope& treeScope,
                                               const String& cssText) {
  StyleSheetContents* sheet =
      StyleSheetContents::create(CSSParserContext(HTMLStandardMode, nullptr));
  sheet->parseString(cssText);
  HeapVector<Member<RuleSet>> ruleSets;
  RuleSet& ruleSet = sheet->ensureRuleSet(MediaQueryEvaluator(),
                                          RuleHasDocumentSecurityOrigin);
  ruleSet.compactRulesIfNeeded();
  if (ruleSet.needsFullRecalcForRuleSetInvalidation())
    return RuleSetInvalidationFullRecalc;
  ruleSets.append(&ruleSet);
  styleEngine().scheduleInvalidationsForRuleSets(treeScope, ruleSets);
  return RuleSetInvalidationsScheduled;
}
Beispiel #18
0
void StyleRuleImport::requestStyleSheet()
{
    if (!m_parentStyleSheet)
        return;
    Document* document = m_parentStyleSheet->singleOwnerDocument();
    if (!document)
        return;

    CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader();
    if (!cachedResourceLoader)
        return;

    URL absURL;
    if (!m_parentStyleSheet->baseURL().isNull())
        // use parent styleheet's URL as the base URL
        absURL = URL(m_parentStyleSheet->baseURL(), m_strHref);
    else
        absURL = document->completeURL(m_strHref);

    // Check for a cycle in our import chain.  If we encounter a stylesheet
    // in our parent chain with the same URL, then just bail.
    StyleSheetContents* rootSheet = m_parentStyleSheet;
    for (StyleSheetContents* sheet = m_parentStyleSheet; sheet; sheet = sheet->parentStyleSheet()) {
        if (equalIgnoringFragmentIdentifier(absURL, sheet->baseURL())
            || equalIgnoringFragmentIdentifier(absURL, document->completeURL(sheet->originalURL())))
            return;
        rootSheet = sheet;
    }

    CachedResourceRequest request(ResourceRequest(absURL), m_parentStyleSheet->charset());
    request.setInitiator(cachedResourceRequestInitiators().css);
    if (m_cachedSheet)
        m_cachedSheet->removeClient(&m_styleSheetClient);
    if (m_parentStyleSheet->isUserStyleSheet())
        m_cachedSheet = cachedResourceLoader->requestUserCSSStyleSheet(request);
    else
        m_cachedSheet = cachedResourceLoader->requestCSSStyleSheet(request);
    if (m_cachedSheet) {
        // if the import rule is issued dynamically, the sheet may be
        // removed from the pending sheet count, so let the doc know
        // the sheet being imported is pending.
        if (m_parentStyleSheet && m_parentStyleSheet->loadCompleted() && rootSheet == m_parentStyleSheet)
            m_parentStyleSheet->startLoadingDynamicSheet();
        m_loading = true;
        m_cachedSheet->addClient(&m_styleSheetClient);
    }
}
Beispiel #19
0
void StyleRuleImport::requestStyleSheet() {
  if (!m_parentStyleSheet)
    return;
  Document* document = m_parentStyleSheet->singleOwnerDocument();
  if (!document)
    return;

  ResourceFetcher* fetcher = document->fetcher();
  if (!fetcher)
    return;

  KURL absURL;
  if (!m_parentStyleSheet->baseURL().isNull()) {
    // use parent styleheet's URL as the base URL
    absURL = KURL(m_parentStyleSheet->baseURL(), m_strHref);
  } else {
    absURL = document->completeURL(m_strHref);
  }

  // Check for a cycle in our import chain.  If we encounter a stylesheet
  // in our parent chain with the same URL, then just bail.
  StyleSheetContents* rootSheet = m_parentStyleSheet;
  for (StyleSheetContents* sheet = m_parentStyleSheet; sheet;
       sheet = sheet->parentStyleSheet()) {
    if (equalIgnoringFragmentIdentifier(absURL, sheet->baseURL()) ||
        equalIgnoringFragmentIdentifier(
            absURL, document->completeURL(sheet->originalURL())))
      return;
    rootSheet = sheet;
  }

  FetchRequest request(ResourceRequest(absURL), FetchInitiatorTypeNames::css,
                       m_parentStyleSheet->charset());
  m_resource = CSSStyleSheetResource::fetch(request, fetcher);
  if (m_resource) {
    // if the import rule is issued dynamically, the sheet may be
    // removed from the pending sheet count, so let the doc know
    // the sheet being imported is pending.
    if (m_parentStyleSheet && m_parentStyleSheet->loadCompleted() &&
        rootSheet == m_parentStyleSheet)
      m_parentStyleSheet->startLoadingDynamicSheet();
    m_loading = true;
    m_resource->addClient(m_styleSheetClient);
  }
}
Beispiel #20
0
void RuleSet::addRulesFromSheet(StyleSheetContents& sheet, const MediaQueryEvaluator& medium, StyleResolver* resolver)
{
    for (auto& rule : sheet.importRules()) {
        if (rule->styleSheet() && (!rule->mediaQueries() || medium.eval(rule->mediaQueries(), resolver)))
            addRulesFromSheet(*rule->styleSheet(), medium, resolver);
    }

    bool hasDocumentSecurityOrigin = resolver && resolver->document().securityOrigin()->canRequest(sheet.baseURL());
    AddRuleFlags addRuleFlags = static_cast<AddRuleFlags>((hasDocumentSecurityOrigin ? RuleHasDocumentSecurityOrigin : 0));

    // FIXME: Skip Content Security Policy check when stylesheet is in a user agent shadow tree.
    // See <https://bugs.webkit.org/show_bug.cgi?id=146663>.
    bool isInitiatingElementInUserAgentShadowTree = false;
    addChildRules(sheet.childRules(), medium, resolver, hasDocumentSecurityOrigin, isInitiatingElementInUserAgentShadowTree, addRuleFlags);

    if (m_autoShrinkToFitEnabled)
        shrinkToFit();
}
void StyleSheetContents::checkLoaded()
{
    if (isLoading())
        return;

    // Avoid |this| being deleted by scripts that run via
    // ScriptableDocumentParser::executeScriptsWaitingForResources().
    // See https://bugs.webkit.org/show_bug.cgi?id=95106
    RefPtrWillBeRawPtr<StyleSheetContents> protect(this);

    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.
    WillBeHeapVector<RefPtrWillBeMember<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 (RefPtrWillBeRawPtr<Node> ownerNode = loadingClients[i]->ownerNode()) {
            if (loadingClients[i]->sheetLoaded())
                ownerNode->notifyLoadedSheetAndAllCriticalSubresources(m_didLoadErrorOccur);
        }
    }
}
void DocumentStyleSheetCollection::maybeAddContentExtensionSheet(const String& identifier, StyleSheetContents& sheet)
{
    ASSERT(sheet.isUserStyleSheet());

    if (m_contentExtensionSheets.contains(identifier))
        return;

    Ref<CSSStyleSheet> cssSheet = CSSStyleSheet::create(sheet, &m_document);
    m_contentExtensionSheets.set(identifier, &cssSheet.get());
    m_userStyleSheets.append(adoptRef(cssSheet.leakRef()));
    m_styleResolverChangedTimer.startOneShot(0);
}
Beispiel #23
0
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 StyleRuleImport::requestStyleSheet(CSSStyleSheet* rootSheet, const CSSParserContext& parserContext)
{
    ASSERT(!rootSheet->parentStyleSheet());
    ASSERT(!m_cachedSheet);

    Node* ownerNode = rootSheet->ownerNode();
    if (!ownerNode)
        return;
    Document* document = ownerNode->document();

    KURL resolvedURL;
    if (!parserContext.baseURL.isNull())
        resolvedURL = KURL(parserContext.baseURL, m_strHref);
    else
        resolvedURL = document->completeURL(m_strHref);

    StyleSheetContents* rootSheetContents = rootSheet->contents();
    if (rootSheetContents->hasImportCycle(this, resolvedURL, document->baseURL()))
        return;

    ResourceRequest request(resolvedURL);
    CachedResourceLoader* cachedResourceLoader = document->cachedResourceLoader();
    if (rootSheetContents->isUserStyleSheet())
        m_cachedSheet = cachedResourceLoader->requestUserCSSStyleSheet(request, parserContext.charset);
    else
        m_cachedSheet = cachedResourceLoader->requestCSSStyleSheet(request, parserContext.charset);

    if (!m_cachedSheet)
        return;
    // if the import rule is issued dynamically, the sheet may be
    // removed from the pending sheet count, so let the doc know
    // the sheet being imported is pending.
    if (rootSheetContents->loadCompleted())
        ownerNode->startLoadingDynamicSheet();

    m_loadContext = adoptPtr(new LoadContext(rootSheet, parserContext));
    m_cachedSheet->addClient(this);
}
Beispiel #25
0
PassRefPtr<CSSStyleSheet> StyleEngine::createSheet(Element* e, const String& text, TextPosition startPosition, bool createdByParser)
{
    RefPtr<CSSStyleSheet> styleSheet = nullptr;

    AtomicString textContent(text);

    HashMap<AtomicString, RawPtr<StyleSheetContents> >::AddResult result = m_textToSheetCache.add(textContent, nullptr);
    if (result.isNewEntry || !result.storedValue->value) {
        styleSheet = StyleEngine::parseSheet(e, text, startPosition, createdByParser);
        if (result.isNewEntry && isCacheableForStyleElement(*styleSheet->contents())) {
            result.storedValue->value = styleSheet->contents();
            m_sheetToTextCache.add(styleSheet->contents(), textContent);
        }
    } else {
        StyleSheetContents* contents = result.storedValue->value;
        ASSERT(contents);
        ASSERT(isCacheableForStyleElement(*contents));
        ASSERT(contents->singleOwnerDocument() == e->document());
        styleSheet = CSSStyleSheet::createInline(contents, e, startPosition);
    }

    ASSERT(styleSheet);
    return styleSheet;
}
static StyleSheetContents* parseUASheet(const String& str)
{
    StyleSheetContents* sheet = StyleSheetContents::create(CSSParserContext(UASheetMode)).leakRef(); // leak the sheet on purpose
    sheet->parseString(str);
    return sheet;
}
Beispiel #27
0
Document* StyleSheetContents::singleOwnerDocument() const {
    StyleSheetContents* root = rootStyleSheet();
    return root->clientSingleOwnerDocument();
}
Beispiel #28
0
void LinkStyle::setCSSStyleSheet(
    const String& href,
    const KURL& baseURL,
    const String& charset,
    const CSSStyleSheetResource* cachedStyleSheet) {
  if (!m_owner->isConnected()) {
    // While the stylesheet is asynchronously loading, the owner can be
    // disconnected from a document.
    // In that case, cancel any processing on the loaded content.
    m_loading = false;
    removePendingSheet();
    if (m_sheet)
      clearSheet();
    return;
  }

  // See the comment in PendingScript.cpp about why this check is necessary
  // here, instead of in the resource fetcher. https://crbug.com/500701.
  if (!cachedStyleSheet->errorOccurred() &&
      !m_owner->fastGetAttribute(HTMLNames::integrityAttr).isEmpty() &&
      !cachedStyleSheet->integrityMetadata().isEmpty()) {
    ResourceIntegrityDisposition disposition =
        cachedStyleSheet->integrityDisposition();

    if (disposition == ResourceIntegrityDisposition::NotChecked &&
        !cachedStyleSheet->loadFailedOrCanceled()) {
      bool checkResult;

      // cachedStyleSheet->resourceBuffer() can be nullptr on load success.
      // If response size == 0.
      const char* data = nullptr;
      size_t size = 0;
      if (cachedStyleSheet->resourceBuffer()) {
        data = cachedStyleSheet->resourceBuffer()->data();
        size = cachedStyleSheet->resourceBuffer()->size();
      }
      checkResult = SubresourceIntegrity::CheckSubresourceIntegrity(
          *m_owner, data, size, KURL(baseURL, href), *cachedStyleSheet);
      disposition = checkResult ? ResourceIntegrityDisposition::Passed
                                : ResourceIntegrityDisposition::Failed;

      // TODO(kouhei): Remove this const_cast crbug.com/653502
      const_cast<CSSStyleSheetResource*>(cachedStyleSheet)
          ->setIntegrityDisposition(disposition);
    }

    if (disposition == ResourceIntegrityDisposition::Failed) {
      m_loading = false;
      removePendingSheet();
      notifyLoadedSheetAndAllCriticalSubresources(
          Node::ErrorOccurredLoadingSubresource);
      return;
    }
  }

  CSSParserContext parserContext(m_owner->document(), nullptr, baseURL,
                                 charset);

  DEFINE_STATIC_LOCAL(EnumerationHistogram, restoredCachedStyleSheetHistogram,
                      ("Blink.RestoredCachedStyleSheet", 2));
  DEFINE_STATIC_LOCAL(
      EnumerationHistogram, restoredCachedStyleSheet2Histogram,
      ("Blink.RestoredCachedStyleSheet2", StyleSheetCacheStatusCount));

  if (StyleSheetContents* restoredSheet =
          const_cast<CSSStyleSheetResource*>(cachedStyleSheet)
              ->restoreParsedStyleSheet(parserContext)) {
    DCHECK(restoredSheet->isCacheableForResource());
    DCHECK(!restoredSheet->isLoading());

    if (m_sheet)
      clearSheet();
    m_sheet = CSSStyleSheet::create(restoredSheet, *m_owner);
    m_sheet->setMediaQueries(MediaQuerySet::create(m_owner->media()));
    if (m_owner->isInDocumentTree())
      setSheetTitle(m_owner->title());
    setCrossOriginStylesheetStatus(m_sheet.get());

    m_loading = false;
    restoredSheet->checkLoaded();

    restoredCachedStyleSheetHistogram.count(true);
    restoredCachedStyleSheet2Histogram.count(StyleSheetInMemoryCache);
    return;
  }
  restoredCachedStyleSheetHistogram.count(false);
  StyleSheetCacheStatus cacheStatus = cachedStyleSheet->response().wasCached()
                                          ? StyleSheetInDiskCache
                                          : StyleSheetNewEntry;
  restoredCachedStyleSheet2Histogram.count(cacheStatus);

  StyleSheetContents* styleSheet =
      StyleSheetContents::create(href, parserContext);

  if (m_sheet)
    clearSheet();

  m_sheet = CSSStyleSheet::create(styleSheet, *m_owner);
  m_sheet->setMediaQueries(MediaQuerySet::create(m_owner->media()));
  if (m_owner->isInDocumentTree())
    setSheetTitle(m_owner->title());
  setCrossOriginStylesheetStatus(m_sheet.get());

  styleSheet->parseAuthorStyleSheet(cachedStyleSheet,
                                    m_owner->document().getSecurityOrigin());

  m_loading = false;
  styleSheet->notifyLoadedSheet(cachedStyleSheet);
  styleSheet->checkLoaded();

  if (styleSheet->isCacheableForResource()) {
    const_cast<CSSStyleSheetResource*>(cachedStyleSheet)
        ->saveParsedStyleSheet(styleSheet);
  }
  clearResource();
}
Beispiel #29
0
CSSDeferredParser::CSSDeferredParser(const CSSParserContext& context, const String& sheetText, StyleSheetContents& styleSheet)
    : m_context(context)
    , m_sheetText(sheetText)
    , m_styleSheet(styleSheet.createWeakPtr())
{
}