| Index: third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
|
| diff --git a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
|
| index 7b5cfd145bd2136c74b40fc4c2ef13be5512615f..9b402d3c27a141347a0b993a6164e753549fbd3b 100644
|
| --- a/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
|
| +++ b/third_party/WebKit/Source/core/html/HTMLLinkElement.cpp
|
| @@ -27,50 +27,25 @@
|
|
|
| #include "bindings/core/v8/ScriptEventListener.h"
|
| #include "core/HTMLNames.h"
|
| -#include "core/css/MediaList.h"
|
| -#include "core/css/MediaQueryEvaluator.h"
|
| -#include "core/css/StyleSheetContents.h"
|
| -#include "core/css/resolver/StyleResolver.h"
|
| #include "core/dom/Attribute.h"
|
| #include "core/dom/Document.h"
|
| -#include "core/dom/StyleEngine.h"
|
| #include "core/dom/TaskRunnerHelper.h"
|
| #include "core/events/Event.h"
|
| -#include "core/fetch/CSSStyleSheetResource.h"
|
| -#include "core/fetch/FetchRequest.h"
|
| -#include "core/fetch/ResourceFetcher.h"
|
| -#include "core/frame/FrameView.h"
|
| -#include "core/frame/LocalFrame.h"
|
| -#include "core/frame/SubresourceIntegrity.h"
|
| #include "core/frame/UseCounter.h"
|
| -#include "core/frame/csp/ContentSecurityPolicy.h"
|
| #include "core/html/CrossOriginAttribute.h"
|
| #include "core/html/LinkManifest.h"
|
| #include "core/html/imports/LinkImport.h"
|
| #include "core/inspector/ConsoleMessage.h"
|
| -#include "core/loader/FrameLoader.h"
|
| #include "core/loader/FrameLoaderClient.h"
|
| #include "core/loader/NetworkHintsInterface.h"
|
| #include "core/origin_trials/OriginTrials.h"
|
| -#include "core/style/StyleInheritedData.h"
|
| -#include "platform/ContentType.h"
|
| -#include "platform/Histogram.h"
|
| -#include "platform/MIMETypeRegistry.h"
|
| -#include "platform/RuntimeEnabledFeatures.h"
|
| #include "public/platform/WebIconSizesParser.h"
|
| #include "public/platform/WebSize.h"
|
| -#include "wtf/StdLibExtras.h"
|
|
|
| namespace blink {
|
|
|
| using namespace HTMLNames;
|
|
|
| -static bool styleSheetTypeIsSupported(const String& type) {
|
| - String trimmedType = ContentType(type).type();
|
| - return trimmedType.isEmpty() ||
|
| - MIMETypeRegistry::isSupportedStyleSheetMIMEType(trimmedType);
|
| -}
|
| -
|
| inline HTMLLinkElement::HTMLLinkElement(Document& document,
|
| bool createdByParser)
|
| : HTMLElement(linkTag, document),
|
| @@ -384,391 +359,4 @@ DEFINE_TRACE_WRAPPERS(HTMLLinkElement) {
|
| HTMLElement::traceWrappers(visitor);
|
| }
|
|
|
| -LinkStyle* LinkStyle::create(HTMLLinkElement* owner) {
|
| - return new LinkStyle(owner);
|
| -}
|
| -
|
| -LinkStyle::LinkStyle(HTMLLinkElement* owner)
|
| - : LinkResource(owner),
|
| - m_disabledState(Unset),
|
| - m_pendingSheetType(None),
|
| - m_loading(false),
|
| - m_firedLoad(false),
|
| - m_loadedSheet(false),
|
| - m_fetchFollowingCORS(false) {}
|
| -
|
| -LinkStyle::~LinkStyle() {}
|
| -
|
| -Document& LinkStyle::document() {
|
| - return m_owner->document();
|
| -}
|
| -
|
| -enum StyleSheetCacheStatus {
|
| - StyleSheetNewEntry,
|
| - StyleSheetInDiskCache,
|
| - StyleSheetInMemoryCache,
|
| - StyleSheetCacheStatusCount,
|
| -};
|
| -
|
| -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();
|
| -}
|
| -
|
| -bool LinkStyle::sheetLoaded() {
|
| - if (!styleSheetIsLoading()) {
|
| - removePendingSheet();
|
| - return true;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -void LinkStyle::notifyLoadedSheetAndAllCriticalSubresources(
|
| - Node::LoadedSheetErrorStatus errorStatus) {
|
| - if (m_firedLoad)
|
| - return;
|
| - m_loadedSheet = (errorStatus == Node::NoErrorLoadingSubresource);
|
| - if (m_owner)
|
| - m_owner->scheduleEvent();
|
| - m_firedLoad = true;
|
| -}
|
| -
|
| -void LinkStyle::startLoadingDynamicSheet() {
|
| - DCHECK_LT(m_pendingSheetType, Blocking);
|
| - addPendingSheet(Blocking);
|
| -}
|
| -
|
| -void LinkStyle::clearSheet() {
|
| - DCHECK(m_sheet);
|
| - DCHECK_EQ(m_sheet->ownerNode(), m_owner);
|
| - m_sheet.release()->clearOwnerNode();
|
| -}
|
| -
|
| -bool LinkStyle::styleSheetIsLoading() const {
|
| - if (m_loading)
|
| - return true;
|
| - if (!m_sheet)
|
| - return false;
|
| - return m_sheet->contents()->isLoading();
|
| -}
|
| -
|
| -void LinkStyle::addPendingSheet(PendingSheetType type) {
|
| - if (type <= m_pendingSheetType)
|
| - return;
|
| - m_pendingSheetType = type;
|
| -
|
| - if (m_pendingSheetType == NonBlocking)
|
| - return;
|
| - m_owner->document().styleEngine().addPendingSheet(m_styleEngineContext);
|
| -}
|
| -
|
| -void LinkStyle::removePendingSheet() {
|
| - DCHECK(m_owner);
|
| - PendingSheetType type = m_pendingSheetType;
|
| - m_pendingSheetType = None;
|
| -
|
| - if (type == None)
|
| - return;
|
| - if (type == NonBlocking) {
|
| - // Tell StyleEngine to re-compute styleSheets of this m_owner's treescope.
|
| - m_owner->document().styleEngine().modifiedStyleSheetCandidateNode(*m_owner);
|
| - return;
|
| - }
|
| -
|
| - m_owner->document().styleEngine().removePendingSheet(*m_owner,
|
| - m_styleEngineContext);
|
| -}
|
| -
|
| -void LinkStyle::setDisabledState(bool disabled) {
|
| - LinkStyle::DisabledState oldDisabledState = m_disabledState;
|
| - m_disabledState = disabled ? Disabled : EnabledViaScript;
|
| - if (oldDisabledState != m_disabledState) {
|
| - // If we change the disabled state while the sheet is still loading, then we
|
| - // have to perform three checks:
|
| - if (styleSheetIsLoading()) {
|
| - // Check #1: The sheet becomes disabled while loading.
|
| - if (m_disabledState == Disabled)
|
| - removePendingSheet();
|
| -
|
| - // Check #2: An alternate sheet becomes enabled while it is still loading.
|
| - if (m_owner->relAttribute().isAlternate() &&
|
| - m_disabledState == EnabledViaScript)
|
| - addPendingSheet(Blocking);
|
| -
|
| - // Check #3: A main sheet becomes enabled while it was still loading and
|
| - // after it was disabled via script. It takes really terrible code to make
|
| - // this happen (a double toggle for no reason essentially). This happens
|
| - // on virtualplastic.net, which manages to do about 12 enable/disables on
|
| - // only 3 sheets. :)
|
| - if (!m_owner->relAttribute().isAlternate() &&
|
| - m_disabledState == EnabledViaScript && oldDisabledState == Disabled)
|
| - addPendingSheet(Blocking);
|
| -
|
| - // If the sheet is already loading just bail.
|
| - return;
|
| - }
|
| -
|
| - if (m_sheet) {
|
| - m_sheet->setDisabled(disabled);
|
| - return;
|
| - }
|
| -
|
| - if (m_disabledState == EnabledViaScript && m_owner->shouldProcessStyle())
|
| - process();
|
| - }
|
| -}
|
| -
|
| -void LinkStyle::setCrossOriginStylesheetStatus(CSSStyleSheet* sheet) {
|
| - if (m_fetchFollowingCORS && resource() && !resource()->errorOccurred()) {
|
| - // Record the security origin the CORS access check succeeded at, if cross
|
| - // origin. Only origins that are script accessible to it may access the
|
| - // stylesheet's rules.
|
| - sheet->setAllowRuleAccessFromOrigin(
|
| - m_owner->document().getSecurityOrigin());
|
| - }
|
| - m_fetchFollowingCORS = false;
|
| -}
|
| -
|
| -void LinkStyle::process() {
|
| - DCHECK(m_owner->shouldProcessStyle());
|
| - String type = m_owner->typeValue().lower();
|
| - String as = m_owner->asValue().lower();
|
| - String media = m_owner->media().lower();
|
| - LinkRequestBuilder builder(m_owner);
|
| -
|
| - if (m_owner->relAttribute().getIconType() != InvalidIcon &&
|
| - builder.url().isValid() && !builder.url().isEmpty()) {
|
| - if (!m_owner->shouldLoadLink())
|
| - return;
|
| - if (!document().getSecurityOrigin()->canDisplay(builder.url()))
|
| - return;
|
| - if (!document().contentSecurityPolicy()->allowImageFromSource(
|
| - builder.url()))
|
| - return;
|
| - if (document().frame() && document().frame()->loader().client())
|
| - document().frame()->loader().client()->dispatchDidChangeIcons(
|
| - m_owner->relAttribute().getIconType());
|
| - }
|
| -
|
| - if (!m_owner->loadLink(type, as, media, builder.url()))
|
| - return;
|
| -
|
| - if (m_disabledState != Disabled && m_owner->relAttribute().isStyleSheet() &&
|
| - styleSheetTypeIsSupported(type) && shouldLoadResource() &&
|
| - builder.url().isValid()) {
|
| - if (resource()) {
|
| - removePendingSheet();
|
| - clearResource();
|
| - clearFetchFollowingCORS();
|
| - }
|
| -
|
| - if (!m_owner->shouldLoadLink())
|
| - return;
|
| -
|
| - m_loading = true;
|
| -
|
| - String title = m_owner->title();
|
| - if (!title.isEmpty() && !m_owner->isAlternate() &&
|
| - m_disabledState != EnabledViaScript && m_owner->isInDocumentTree())
|
| - document().styleEngine().setPreferredStylesheetSetNameIfNotSet(
|
| - title, StyleEngine::DontUpdateActiveSheets);
|
| -
|
| - bool mediaQueryMatches = true;
|
| - LocalFrame* frame = loadingFrame();
|
| - if (!m_owner->media().isEmpty() && frame) {
|
| - MediaQuerySet* media = MediaQuerySet::create(m_owner->media());
|
| - MediaQueryEvaluator evaluator(frame);
|
| - mediaQueryMatches = evaluator.eval(media);
|
| - }
|
| -
|
| - // Don't hold up layout tree construction and script execution on
|
| - // stylesheets that are not needed for the layout at the moment.
|
| - bool blocking = mediaQueryMatches && !m_owner->isAlternate() &&
|
| - m_owner->isCreatedByParser();
|
| - addPendingSheet(blocking ? Blocking : NonBlocking);
|
| -
|
| - // Load stylesheets that are not needed for the layout immediately with low
|
| - // priority. When the link element is created by scripts, load the
|
| - // stylesheets asynchronously but in high priority.
|
| - bool lowPriority = !mediaQueryMatches || m_owner->isAlternate();
|
| - FetchRequest request = builder.build(lowPriority);
|
| - CrossOriginAttributeValue crossOrigin = crossOriginAttributeValue(
|
| - m_owner->fastGetAttribute(HTMLNames::crossoriginAttr));
|
| - if (crossOrigin != CrossOriginAttributeNotSet) {
|
| - request.setCrossOriginAccessControl(document().getSecurityOrigin(),
|
| - crossOrigin);
|
| - setFetchFollowingCORS();
|
| - }
|
| -
|
| - String integrityAttr = m_owner->fastGetAttribute(HTMLNames::integrityAttr);
|
| - if (!integrityAttr.isEmpty()) {
|
| - IntegrityMetadataSet metadataSet;
|
| - SubresourceIntegrity::parseIntegrityAttribute(integrityAttr, metadataSet);
|
| - request.setIntegrityMetadata(metadataSet);
|
| - }
|
| - setResource(CSSStyleSheetResource::fetch(request, document().fetcher()));
|
| -
|
| - if (m_loading && !resource()) {
|
| - // The request may have been denied if (for example) the stylesheet is
|
| - // local and the document is remote, or if there was a Content Security
|
| - // Policy Failure. setCSSStyleSheet() can be called synchronuosly in
|
| - // setResource() and thus resource() is null and |m_loading| is false in
|
| - // such cases even if the request succeeds.
|
| - m_loading = false;
|
| - removePendingSheet();
|
| - notifyLoadedSheetAndAllCriticalSubresources(
|
| - Node::ErrorOccurredLoadingSubresource);
|
| - }
|
| - } else if (m_sheet) {
|
| - // we no longer contain a stylesheet, e.g. perhaps rel or type was changed
|
| - StyleSheet* removedSheet = m_sheet.get();
|
| - clearSheet();
|
| - document().styleEngine().setNeedsActiveStyleUpdate(removedSheet,
|
| - FullStyleUpdate);
|
| - }
|
| -}
|
| -
|
| -void LinkStyle::setSheetTitle(
|
| - const String& title,
|
| - StyleEngine::ActiveSheetsUpdate updateActiveSheets) {
|
| - if (!m_owner->isInDocumentTree() || !m_owner->relAttribute().isStyleSheet())
|
| - return;
|
| -
|
| - if (m_sheet)
|
| - m_sheet->setTitle(title);
|
| -
|
| - if (title.isEmpty() || !isUnset() || m_owner->isAlternate())
|
| - return;
|
| -
|
| - KURL href = m_owner->getNonEmptyURLAttribute(hrefAttr);
|
| - if (href.isValid() && !href.isEmpty())
|
| - document().styleEngine().setPreferredStylesheetSetNameIfNotSet(
|
| - title, updateActiveSheets);
|
| -}
|
| -
|
| -void LinkStyle::ownerRemoved() {
|
| - if (m_sheet)
|
| - clearSheet();
|
| -
|
| - if (styleSheetIsLoading())
|
| - removePendingSheet();
|
| -}
|
| -
|
| -DEFINE_TRACE(LinkStyle) {
|
| - visitor->trace(m_sheet);
|
| - LinkResource::trace(visitor);
|
| - ResourceOwner<StyleSheetResource>::trace(visitor);
|
| -}
|
| -
|
| } // namespace blink
|
|
|