void HTMLLinkElement::setDisabledState(bool disabled) { 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_relAttribute.m_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_relAttribute.m_isAlternate && m_disabledState == EnabledViaScript && oldDisabledState == Disabled) addPendingSheet(Blocking); // If the sheet is already loading just bail. return; } // Load the sheet, since it's never been loaded before. if (!m_sheet && m_disabledState == EnabledViaScript) process(); else document()->styleSelectorChanged(DeferRecalcStyle); // Update the style selector. } }
HTMLLinkElement::~HTMLLinkElement() { if (m_sheet) m_sheet->clearOwnerNode(); if (m_cachedSheet) { m_cachedSheet->removeClient(this); removePendingSheet(); } if (inDocument()) document()->removeStyleSheetCandidateNode(this); linkLoadEventSender().cancelEvent(this); }
void HTMLLinkElement::removedFromDocument() { HTMLElement::removedFromDocument(); if (m_isInShadowTree) { ASSERT(!m_sheet); return; } document()->removeStyleSheetCandidateNode(this); if (m_sheet) clearSheet(); if (styleSheetIsLoading()) removePendingSheet(); if (document()->renderer()) document()->styleSelectorChanged(DeferRecalcStyle); }
void HTMLLinkElement::process() { if (!inDocument() || m_isInShadowTree) { ASSERT(!m_sheet); return; } String type = m_type.lower(); if (!m_linkLoader.loadLink(m_relAttribute, type, m_sizes->toString(), m_url, document())) return; bool acceptIfTypeContainsTextCSS = document()->page() && document()->page()->settings() && document()->page()->settings()->treatsAnyTextCSSLinkAsStylesheet(); if (m_disabledState != Disabled && (m_relAttribute.m_isStyleSheet || (acceptIfTypeContainsTextCSS && type.contains("text/css"))) && document()->frame() && m_url.isValid()) { String charset = getAttribute(charsetAttr); if (charset.isEmpty() && document()->frame()) charset = document()->charset(); if (m_cachedSheet) { removePendingSheet(); m_cachedSheet->removeClient(this); m_cachedSheet = 0; } if (!shouldLoadLink()) return; m_loading = true; bool mediaQueryMatches = true; if (!m_media.isEmpty()) { RefPtr<RenderStyle> documentStyle = CSSStyleSelector::styleForDocument(document()); RefPtr<MediaList> media = MediaList::createAllowingDescriptionSyntax(m_media); MediaQueryEvaluator evaluator(document()->frame()->view()->mediaType(), document()->frame(), documentStyle.get()); mediaQueryMatches = evaluator.eval(media.get()); } // Don't hold up render tree construction and script execution on stylesheets // that are not needed for the rendering at the moment. bool blocking = mediaQueryMatches && !isAlternate(); addPendingSheet(blocking ? Blocking : NonBlocking); // Load stylesheets that are not needed for the rendering immediately with low priority. ResourceLoadPriority priority = blocking ? ResourceLoadPriorityUnresolved : ResourceLoadPriorityVeryLow; ResourceRequest request(document()->completeURL(m_url)); m_cachedSheet = document()->cachedResourceLoader()->requestCSSStyleSheet(request, charset, priority); if (m_cachedSheet) m_cachedSheet->addClient(this); else { // The request may have been denied if (for example) the stylesheet is local and the document is remote. m_loading = false; removePendingSheet(); } } else if (m_sheet) { // we no longer contain a stylesheet, e.g. perhaps rel or type was changed m_sheet = 0; document()->styleSelectorChanged(DeferRecalcStyle); } }
void HTMLLinkElement::process() { if (!inDocument() || m_isInShadowTree) { ASSERT(!m_sheet); return; } String type = m_type.lower(); // IE extension: location of small icon for locationbar / bookmarks // We'll record this URL per document, even if we later only use it in top level frames if (m_relAttribute.m_isIcon && m_url.isValid() && !m_url.isEmpty()) { if (!checkBeforeLoadEvent()) return; document()->setIconURL(m_url.string(), type); } #ifdef ANDROID_APPLE_TOUCH_ICON if ((m_relAttribute.m_isTouchIcon || m_relAttribute.m_isPrecomposedTouchIcon) && m_url.isValid() && !m_url.isEmpty() && document()->frame()) document()->frame()->loader()->client() ->dispatchDidReceiveTouchIconURL(m_url.string(), m_relAttribute.m_isPrecomposedTouchIcon); #endif if (m_relAttribute.m_isDNSPrefetch) { Settings* settings = document()->settings(); // FIXME: The href attribute of the link element can be in "//hostname" form, and we shouldn't attempt // to complete that as URL <https://bugs.webkit.org/show_bug.cgi?id=48857>. if (settings && settings->dnsPrefetchingEnabled() && m_url.isValid() && !m_url.isEmpty()) ResourceHandle::prepareForURL(m_url); } #if ENABLE(LINK_PREFETCH) if ((m_relAttribute.m_isLinkPrefetch || m_relAttribute.m_isLinkPrerender || m_relAttribute.m_isLinkSubresource) && m_url.isValid() && document()->frame()) { if (!checkBeforeLoadEvent()) return; ResourceLoadPriority priority = ResourceLoadPriorityUnresolved; CachedResource::Type type = CachedResource::LinkPrefetch; // We only make one request to the cachedresourcelodaer if multiple rel types are // specified. if (m_relAttribute.m_isLinkSubresource) { priority = ResourceLoadPriorityLow; type = CachedResource::LinkSubresource; } else if (m_relAttribute.m_isLinkPrerender) type = CachedResource::LinkPrerender; ResourceRequest linkRequest(document()->completeURL(m_url)); m_cachedLinkResource = document()->cachedResourceLoader()->requestLinkResource(type, linkRequest, priority); if (m_cachedLinkResource) m_cachedLinkResource->addClient(this); } #endif bool acceptIfTypeContainsTextCSS = document()->page() && document()->page()->settings() && document()->page()->settings()->treatsAnyTextCSSLinkAsStylesheet(); if (m_disabledState != Disabled && (m_relAttribute.m_isStyleSheet || (acceptIfTypeContainsTextCSS && type.contains("text/css"))) && document()->frame() && m_url.isValid()) { String charset = getAttribute(charsetAttr); if (charset.isEmpty() && document()->frame()) charset = document()->charset(); if (m_cachedSheet) { removePendingSheet(); m_cachedSheet->removeClient(this); m_cachedSheet = 0; } if (!checkBeforeLoadEvent()) return; m_loading = true; bool mediaQueryMatches = true; if (!m_media.isEmpty()) { RefPtr<RenderStyle> documentStyle = CSSStyleSelector::styleForDocument(document()); RefPtr<MediaList> media = MediaList::createAllowingDescriptionSyntax(m_media); MediaQueryEvaluator evaluator(document()->frame()->view()->mediaType(), document()->frame(), documentStyle.get()); mediaQueryMatches = evaluator.eval(media.get()); } // Don't hold up render tree construction and script execution on stylesheets // that are not needed for the rendering at the moment. bool blocking = mediaQueryMatches && !isAlternate(); addPendingSheet(blocking ? Blocking : NonBlocking); // Load stylesheets that are not needed for the rendering immediately with low priority. ResourceLoadPriority priority = blocking ? ResourceLoadPriorityUnresolved : ResourceLoadPriorityVeryLow; ResourceRequest request(document()->completeURL(m_url)); m_cachedSheet = document()->cachedResourceLoader()->requestCSSStyleSheet(request, charset, priority); if (m_cachedSheet) m_cachedSheet->addClient(this); else { // The request may have been denied if (for example) the stylesheet is local and the document is remote. m_loading = false; removePendingSheet(); } } else if (m_sheet) { // we no longer contain a stylesheet, e.g. perhaps rel or type was changed m_sheet = 0; document()->styleSelectorChanged(DeferRecalcStyle); } }