Ejemplo n.º 1
0
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);
        }
    }
}
Ejemplo n.º 2
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);
        }
    }
}
Ejemplo n.º 3
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();
}