Home | History | Annotate | Download | only in html
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 1999 Antti Koivisto (koivisto (at) kde.org)
      4  *           (C) 2001 Dirk Mueller (mueller (at) kde.org)
      5  * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
      6  * Copyright (C) 2009 Rob Buis (rwlbuis (at) gmail.com)
      7  * Copyright (C) 2011 Google Inc. All rights reserved.
      8  *
      9  * This library is free software; you can redistribute it and/or
     10  * modify it under the terms of the GNU Library General Public
     11  * License as published by the Free Software Foundation; either
     12  * version 2 of the License, or (at your option) any later version.
     13  *
     14  * This library is distributed in the hope that it will be useful,
     15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     17  * Library General Public License for more details.
     18  *
     19  * You should have received a copy of the GNU Library General Public License
     20  * along with this library; see the file COPYING.LIB.  If not, write to
     21  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     22  * Boston, MA 02110-1301, USA.
     23  */
     24 
     25 #include "config.h"
     26 #include "core/html/HTMLLinkElement.h"
     27 
     28 #include "bindings/core/v8/ScriptEventListener.h"
     29 #include "bindings/core/v8/V8DOMActivityLogger.h"
     30 #include "core/HTMLNames.h"
     31 #include "core/css/MediaList.h"
     32 #include "core/css/MediaQueryEvaluator.h"
     33 #include "core/css/StyleSheetContents.h"
     34 #include "core/css/resolver/StyleResolver.h"
     35 #include "core/dom/Attribute.h"
     36 #include "core/dom/Document.h"
     37 #include "core/dom/StyleEngine.h"
     38 #include "core/events/Event.h"
     39 #include "core/events/EventSender.h"
     40 #include "core/fetch/CSSStyleSheetResource.h"
     41 #include "core/fetch/FetchRequest.h"
     42 #include "core/fetch/ResourceFetcher.h"
     43 #include "core/frame/FrameView.h"
     44 #include "core/frame/LocalFrame.h"
     45 #include "core/frame/csp/ContentSecurityPolicy.h"
     46 #include "core/html/LinkManifest.h"
     47 #include "core/html/imports/LinkImport.h"
     48 #include "core/loader/FrameLoader.h"
     49 #include "core/loader/FrameLoaderClient.h"
     50 #include "core/rendering/style/StyleInheritedData.h"
     51 #include "platform/RuntimeEnabledFeatures.h"
     52 #include "wtf/StdLibExtras.h"
     53 
     54 namespace blink {
     55 
     56 using namespace HTMLNames;
     57 
     58 template <typename CharacterType>
     59 static void parseSizes(const CharacterType* value, unsigned length, Vector<IntSize>& iconSizes)
     60 {
     61     enum State {
     62         ParseStart,
     63         ParseWidth,
     64         ParseHeight
     65     };
     66     int width = 0;
     67     unsigned start = 0;
     68     unsigned i = 0;
     69     State state = ParseStart;
     70     bool invalid = false;
     71     for (; i < length; ++i) {
     72         if (state == ParseWidth) {
     73             if (value[i] == 'x' || value[i] == 'X') {
     74                 if (i == start) {
     75                     invalid = true;
     76                     break;
     77                 }
     78                 width = charactersToInt(value + start, i - start);
     79                 start = i + 1;
     80                 state = ParseHeight;
     81             } else if (value[i] < '0' || value[i] > '9') {
     82                 invalid = true;
     83                 break;
     84             }
     85         } else if (state == ParseHeight) {
     86             if (value[i] == ' ') {
     87                 if (i == start) {
     88                     invalid = true;
     89                     break;
     90                 }
     91                 int height = charactersToInt(value + start, i - start);
     92                 iconSizes.append(IntSize(width, height));
     93                 start = i + 1;
     94                 state = ParseStart;
     95             } else if (value[i] < '0' || value[i] > '9') {
     96                 invalid = true;
     97                 break;
     98             }
     99         } else if (state == ParseStart) {
    100             if (value[i] >= '0' && value[i] <= '9') {
    101                 start = i;
    102                 state = ParseWidth;
    103             } else if (value[i] != ' ') {
    104                 invalid = true;
    105                 break;
    106             }
    107         }
    108     }
    109     if (invalid || state == ParseWidth || (state == ParseHeight && start == i)) {
    110         iconSizes.clear();
    111         return;
    112     }
    113     if (state == ParseHeight && i > start) {
    114         int height = charactersToInt(value + start, i - start);
    115         iconSizes.append(IntSize(width, height));
    116     }
    117 }
    118 
    119 static LinkEventSender& linkLoadEventSender()
    120 {
    121     DEFINE_STATIC_LOCAL(LinkEventSender, sharedLoadEventSender, (EventTypeNames::load));
    122     return sharedLoadEventSender;
    123 }
    124 
    125 void HTMLLinkElement::parseSizesAttribute(const AtomicString& value, Vector<IntSize>& iconSizes)
    126 {
    127     ASSERT(iconSizes.isEmpty());
    128     if (value.isEmpty())
    129         return;
    130     if (value.is8Bit())
    131         parseSizes(value.characters8(), value.length(), iconSizes);
    132     else
    133         parseSizes(value.characters16(), value.length(), iconSizes);
    134 }
    135 
    136 inline HTMLLinkElement::HTMLLinkElement(Document& document, bool createdByParser)
    137     : HTMLElement(linkTag, document)
    138     , m_linkLoader(this)
    139     , m_sizes(DOMSettableTokenList::create())
    140     , m_createdByParser(createdByParser)
    141     , m_isInShadowTree(false)
    142 {
    143 }
    144 
    145 PassRefPtrWillBeRawPtr<HTMLLinkElement> HTMLLinkElement::create(Document& document, bool createdByParser)
    146 {
    147     return adoptRefWillBeNoop(new HTMLLinkElement(document, createdByParser));
    148 }
    149 
    150 HTMLLinkElement::~HTMLLinkElement()
    151 {
    152 #if !ENABLE(OILPAN)
    153     m_link.clear();
    154 
    155     if (inDocument())
    156         document().styleEngine()->removeStyleSheetCandidateNode(this);
    157 #endif
    158 
    159     linkLoadEventSender().cancelEvent(this);
    160 }
    161 
    162 void HTMLLinkElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
    163 {
    164     if (name == relAttr) {
    165         m_relAttribute = LinkRelAttribute(value);
    166         process();
    167     } else if (name == hrefAttr) {
    168         process();
    169     } else if (name == typeAttr) {
    170         m_type = value;
    171         process();
    172     } else if (name == sizesAttr) {
    173         m_sizes->setValue(value);
    174         parseSizesAttribute(value, m_iconSizes);
    175         process();
    176     } else if (name == mediaAttr) {
    177         m_media = value.lower();
    178         process();
    179     } else if (name == disabledAttr) {
    180         if (LinkStyle* link = linkStyle())
    181             link->setDisabledState(!value.isNull());
    182     } else {
    183         if (name == titleAttr) {
    184             if (LinkStyle* link = linkStyle())
    185                 link->setSheetTitle(value);
    186         }
    187 
    188         HTMLElement::parseAttribute(name, value);
    189     }
    190 }
    191 
    192 bool HTMLLinkElement::shouldLoadLink()
    193 {
    194     return inDocument();
    195 }
    196 
    197 bool HTMLLinkElement::loadLink(const String& type, const KURL& url)
    198 {
    199     return m_linkLoader.loadLink(m_relAttribute, fastGetAttribute(HTMLNames::crossoriginAttr), type, url, document());
    200 }
    201 
    202 LinkResource* HTMLLinkElement::linkResourceToProcess()
    203 {
    204     bool visible = inDocument() && !m_isInShadowTree;
    205     if (!visible) {
    206         ASSERT(!linkStyle() || !linkStyle()->hasSheet());
    207         return 0;
    208     }
    209 
    210     if (!m_link) {
    211         if (m_relAttribute.isImport()) {
    212             m_link = LinkImport::create(this);
    213         } else if (m_relAttribute.isManifest()) {
    214             m_link = LinkManifest::create(this);
    215         } else {
    216             OwnPtrWillBeRawPtr<LinkStyle> link = LinkStyle::create(this);
    217             if (fastHasAttribute(disabledAttr) || m_relAttribute.isTransitionExitingStylesheet())
    218                 link->setDisabledState(true);
    219             m_link = link.release();
    220         }
    221     }
    222 
    223     return m_link.get();
    224 }
    225 
    226 LinkStyle* HTMLLinkElement::linkStyle() const
    227 {
    228     if (!m_link || m_link->type() != LinkResource::Style)
    229         return 0;
    230     return static_cast<LinkStyle*>(m_link.get());
    231 }
    232 
    233 LinkImport* HTMLLinkElement::linkImport() const
    234 {
    235     if (!m_link || m_link->type() != LinkResource::Import)
    236         return 0;
    237     return static_cast<LinkImport*>(m_link.get());
    238 }
    239 
    240 Document* HTMLLinkElement::import() const
    241 {
    242     if (LinkImport* link = linkImport())
    243         return link->importedDocument();
    244     return 0;
    245 }
    246 
    247 void HTMLLinkElement::process()
    248 {
    249     if (LinkResource* link = linkResourceToProcess())
    250         link->process();
    251 }
    252 
    253 void HTMLLinkElement::enableIfExitTransitionStyle()
    254 {
    255     if (m_relAttribute.isTransitionExitingStylesheet()) {
    256         if (LinkStyle* link = linkStyle())
    257             link->setDisabledState(false);
    258     }
    259 }
    260 
    261 Node::InsertionNotificationRequest HTMLLinkElement::insertedInto(ContainerNode* insertionPoint)
    262 {
    263     if (insertionPoint->inDocument()) {
    264         V8DOMActivityLogger* activityLogger = V8DOMActivityLogger::currentActivityLoggerIfIsolatedWorld();
    265         if (activityLogger) {
    266             Vector<String> argv;
    267             argv.append("link");
    268             argv.append(fastGetAttribute(relAttr));
    269             argv.append(fastGetAttribute(hrefAttr));
    270             activityLogger->logEvent("blinkAddElement", argv.size(), argv.data());
    271         }
    272     }
    273     HTMLElement::insertedInto(insertionPoint);
    274     if (!insertionPoint->inDocument())
    275         return InsertionDone;
    276 
    277     m_isInShadowTree = isInShadowTree();
    278     if (m_isInShadowTree)
    279         return InsertionDone;
    280 
    281     document().styleEngine()->addStyleSheetCandidateNode(this, m_createdByParser);
    282 
    283     process();
    284 
    285     if (m_link)
    286         m_link->ownerInserted();
    287 
    288     return InsertionDone;
    289 }
    290 
    291 void HTMLLinkElement::removedFrom(ContainerNode* insertionPoint)
    292 {
    293     HTMLElement::removedFrom(insertionPoint);
    294     if (!insertionPoint->inDocument())
    295         return;
    296 
    297     m_linkLoader.released();
    298 
    299     if (m_isInShadowTree) {
    300         ASSERT(!linkStyle() || !linkStyle()->hasSheet());
    301         return;
    302     }
    303     document().styleEngine()->removeStyleSheetCandidateNode(this);
    304 
    305     RefPtrWillBeRawPtr<StyleSheet> removedSheet = sheet();
    306 
    307     if (m_link)
    308         m_link->ownerRemoved();
    309 
    310     document().removedStyleSheet(removedSheet.get());
    311 }
    312 
    313 void HTMLLinkElement::finishParsingChildren()
    314 {
    315     m_createdByParser = false;
    316     HTMLElement::finishParsingChildren();
    317 }
    318 
    319 bool HTMLLinkElement::styleSheetIsLoading() const
    320 {
    321     return linkStyle() && linkStyle()->styleSheetIsLoading();
    322 }
    323 
    324 void HTMLLinkElement::linkLoaded()
    325 {
    326     dispatchEvent(Event::create(EventTypeNames::load));
    327 }
    328 
    329 void HTMLLinkElement::linkLoadingErrored()
    330 {
    331     dispatchEvent(Event::create(EventTypeNames::error));
    332 }
    333 
    334 void HTMLLinkElement::didStartLinkPrerender()
    335 {
    336     dispatchEvent(Event::create(EventTypeNames::webkitprerenderstart));
    337 }
    338 
    339 void HTMLLinkElement::didStopLinkPrerender()
    340 {
    341     dispatchEvent(Event::create(EventTypeNames::webkitprerenderstop));
    342 }
    343 
    344 void HTMLLinkElement::didSendLoadForLinkPrerender()
    345 {
    346     dispatchEvent(Event::create(EventTypeNames::webkitprerenderload));
    347 }
    348 
    349 void HTMLLinkElement::didSendDOMContentLoadedForLinkPrerender()
    350 {
    351     dispatchEvent(Event::create(EventTypeNames::webkitprerenderdomcontentloaded));
    352 }
    353 
    354 bool HTMLLinkElement::sheetLoaded()
    355 {
    356     ASSERT(linkStyle());
    357     return linkStyle()->sheetLoaded();
    358 }
    359 
    360 void HTMLLinkElement::notifyLoadedSheetAndAllCriticalSubresources(bool errorOccurred)
    361 {
    362     ASSERT(linkStyle());
    363     linkStyle()->notifyLoadedSheetAndAllCriticalSubresources(errorOccurred);
    364 }
    365 
    366 void HTMLLinkElement::dispatchPendingLoadEvents()
    367 {
    368     linkLoadEventSender().dispatchPendingEvents();
    369 }
    370 
    371 void HTMLLinkElement::dispatchPendingEvent(LinkEventSender* eventSender)
    372 {
    373     ASSERT_UNUSED(eventSender, eventSender == &linkLoadEventSender());
    374     ASSERT(m_link);
    375     if (m_link->hasLoaded())
    376         linkLoaded();
    377     else
    378         linkLoadingErrored();
    379 }
    380 
    381 void HTMLLinkElement::scheduleEvent()
    382 {
    383     linkLoadEventSender().dispatchEventSoon(this);
    384 }
    385 
    386 void HTMLLinkElement::startLoadingDynamicSheet()
    387 {
    388     ASSERT(linkStyle());
    389     linkStyle()->startLoadingDynamicSheet();
    390 }
    391 
    392 bool HTMLLinkElement::isURLAttribute(const Attribute& attribute) const
    393 {
    394     return attribute.name().localName() == hrefAttr || HTMLElement::isURLAttribute(attribute);
    395 }
    396 
    397 bool HTMLLinkElement::hasLegalLinkAttribute(const QualifiedName& name) const
    398 {
    399     return name == hrefAttr || HTMLElement::hasLegalLinkAttribute(name);
    400 }
    401 
    402 const QualifiedName& HTMLLinkElement::subResourceAttributeName() const
    403 {
    404     // If the link element is not css, ignore it.
    405     if (equalIgnoringCase(getAttribute(typeAttr), "text/css")) {
    406         // FIXME: Add support for extracting links of sub-resources which
    407         // are inside style-sheet such as @import, @font-face, url(), etc.
    408         return hrefAttr;
    409     }
    410     return HTMLElement::subResourceAttributeName();
    411 }
    412 
    413 KURL HTMLLinkElement::href() const
    414 {
    415     return document().completeURL(getAttribute(hrefAttr));
    416 }
    417 
    418 const AtomicString& HTMLLinkElement::rel() const
    419 {
    420     return getAttribute(relAttr);
    421 }
    422 
    423 const AtomicString& HTMLLinkElement::type() const
    424 {
    425     return getAttribute(typeAttr);
    426 }
    427 
    428 bool HTMLLinkElement::async() const
    429 {
    430     return fastHasAttribute(HTMLNames::asyncAttr);
    431 }
    432 
    433 IconType HTMLLinkElement::iconType() const
    434 {
    435     return m_relAttribute.iconType();
    436 }
    437 
    438 const Vector<IntSize>& HTMLLinkElement::iconSizes() const
    439 {
    440     return m_iconSizes;
    441 }
    442 
    443 DOMSettableTokenList* HTMLLinkElement::sizes() const
    444 {
    445     return m_sizes.get();
    446 }
    447 
    448 void HTMLLinkElement::trace(Visitor* visitor)
    449 {
    450     visitor->trace(m_link);
    451     visitor->trace(m_sizes);
    452     HTMLElement::trace(visitor);
    453 }
    454 
    455 void HTMLLinkElement::attributeWillChange(const QualifiedName& name, const AtomicString& oldValue, const AtomicString& newValue)
    456 {
    457     if (name == hrefAttr && inDocument()) {
    458         V8DOMActivityLogger* activityLogger = V8DOMActivityLogger::currentActivityLoggerIfIsolatedWorld();
    459         if (activityLogger) {
    460             Vector<String> argv;
    461             argv.append("link");
    462             argv.append(hrefAttr.toString());
    463             argv.append(oldValue);
    464             argv.append(newValue);
    465             activityLogger->logEvent("blinkSetAttribute", argv.size(), argv.data());
    466         }
    467     }
    468     HTMLElement::attributeWillChange(name, oldValue, newValue);
    469 }
    470 
    471 PassOwnPtrWillBeRawPtr<LinkStyle> LinkStyle::create(HTMLLinkElement* owner)
    472 {
    473     return adoptPtrWillBeNoop(new LinkStyle(owner));
    474 }
    475 
    476 LinkStyle::LinkStyle(HTMLLinkElement* owner)
    477     : LinkResource(owner)
    478     , m_disabledState(Unset)
    479     , m_pendingSheetType(None)
    480     , m_loading(false)
    481     , m_firedLoad(false)
    482     , m_loadedSheet(false)
    483 {
    484 }
    485 
    486 LinkStyle::~LinkStyle()
    487 {
    488 #if !ENABLE(OILPAN)
    489     if (m_sheet)
    490         m_sheet->clearOwnerNode();
    491 #endif
    492 }
    493 
    494 Document& LinkStyle::document()
    495 {
    496     return m_owner->document();
    497 }
    498 
    499 void LinkStyle::setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CSSStyleSheetResource* cachedStyleSheet)
    500 {
    501     if (!m_owner->inDocument()) {
    502         ASSERT(!m_sheet);
    503         return;
    504 
    505     }
    506     // Completing the sheet load may cause scripts to execute.
    507     RefPtrWillBeRawPtr<Node> protector(m_owner.get());
    508 
    509     CSSParserContext parserContext(m_owner->document(), 0, baseURL, charset);
    510 
    511     if (RefPtrWillBeRawPtr<StyleSheetContents> restoredSheet = const_cast<CSSStyleSheetResource*>(cachedStyleSheet)->restoreParsedStyleSheet(parserContext)) {
    512         ASSERT(restoredSheet->isCacheable());
    513         ASSERT(!restoredSheet->isLoading());
    514 
    515         if (m_sheet)
    516             clearSheet();
    517         m_sheet = CSSStyleSheet::create(restoredSheet, m_owner);
    518         m_sheet->setMediaQueries(MediaQuerySet::create(m_owner->media()));
    519         m_sheet->setTitle(m_owner->title());
    520 
    521         m_loading = false;
    522         restoredSheet->checkLoaded();
    523         return;
    524     }
    525 
    526     RefPtrWillBeRawPtr<StyleSheetContents> styleSheet = StyleSheetContents::create(href, parserContext);
    527 
    528     if (m_sheet)
    529         clearSheet();
    530     m_sheet = CSSStyleSheet::create(styleSheet, m_owner);
    531     m_sheet->setMediaQueries(MediaQuerySet::create(m_owner->media()));
    532     m_sheet->setTitle(m_owner->title());
    533 
    534     styleSheet->parseAuthorStyleSheet(cachedStyleSheet, m_owner->document().securityOrigin());
    535 
    536     m_loading = false;
    537     styleSheet->notifyLoadedSheet(cachedStyleSheet);
    538     styleSheet->checkLoaded();
    539 
    540     if (styleSheet->isCacheable())
    541         const_cast<CSSStyleSheetResource*>(cachedStyleSheet)->saveParsedStyleSheet(styleSheet);
    542 }
    543 
    544 bool LinkStyle::sheetLoaded()
    545 {
    546     if (!styleSheetIsLoading()) {
    547         removePendingSheet();
    548         return true;
    549     }
    550     return false;
    551 }
    552 
    553 void LinkStyle::notifyLoadedSheetAndAllCriticalSubresources(bool errorOccurred)
    554 {
    555     if (m_firedLoad)
    556         return;
    557     m_loadedSheet = !errorOccurred;
    558     if (m_owner)
    559         m_owner->scheduleEvent();
    560     m_firedLoad = true;
    561 }
    562 
    563 void LinkStyle::startLoadingDynamicSheet()
    564 {
    565     ASSERT(m_pendingSheetType < Blocking);
    566     addPendingSheet(Blocking);
    567 }
    568 
    569 void LinkStyle::clearSheet()
    570 {
    571     ASSERT(m_sheet);
    572     ASSERT(m_sheet->ownerNode() == m_owner);
    573     m_sheet->clearOwnerNode();
    574     m_sheet = nullptr;
    575 }
    576 
    577 bool LinkStyle::styleSheetIsLoading() const
    578 {
    579     if (m_loading)
    580         return true;
    581     if (!m_sheet)
    582         return false;
    583     return m_sheet->contents()->isLoading();
    584 }
    585 
    586 void LinkStyle::addPendingSheet(PendingSheetType type)
    587 {
    588     if (type <= m_pendingSheetType)
    589         return;
    590     m_pendingSheetType = type;
    591 
    592     if (m_pendingSheetType == NonBlocking)
    593         return;
    594     m_owner->document().styleEngine()->addPendingSheet();
    595 }
    596 
    597 void LinkStyle::removePendingSheet()
    598 {
    599     PendingSheetType type = m_pendingSheetType;
    600     m_pendingSheetType = None;
    601 
    602     if (type == None)
    603         return;
    604     if (type == NonBlocking) {
    605         // Tell StyleEngine to re-compute styleSheets of this m_owner's treescope.
    606         m_owner->document().styleEngine()->modifiedStyleSheetCandidateNode(m_owner);
    607         // Document::removePendingSheet() triggers the style selector recalc for blocking sheets.
    608         // FIXME: We don't have enough knowledge at this point to know if we're adding or removing a sheet
    609         // so we can't call addedStyleSheet() or removedStyleSheet().
    610         m_owner->document().styleResolverChanged();
    611         return;
    612     }
    613 
    614     m_owner->document().styleEngine()->removePendingSheet(m_owner);
    615 }
    616 
    617 void LinkStyle::setDisabledState(bool disabled)
    618 {
    619     LinkStyle::DisabledState oldDisabledState = m_disabledState;
    620     m_disabledState = disabled ? Disabled : EnabledViaScript;
    621     if (oldDisabledState != m_disabledState) {
    622         // If we change the disabled state while the sheet is still loading, then we have to
    623         // perform three checks:
    624         if (styleSheetIsLoading()) {
    625             // Check #1: The sheet becomes disabled while loading.
    626             if (m_disabledState == Disabled)
    627                 removePendingSheet();
    628 
    629             // Check #2: An alternate sheet becomes enabled while it is still loading.
    630             if (m_owner->relAttribute().isAlternate() && m_disabledState == EnabledViaScript)
    631                 addPendingSheet(Blocking);
    632 
    633             // Check #3: A main sheet becomes enabled while it was still loading and
    634             // after it was disabled via script. It takes really terrible code to make this
    635             // happen (a double toggle for no reason essentially). This happens on
    636             // virtualplastic.net, which manages to do about 12 enable/disables on only 3
    637             // sheets. :)
    638             if (!m_owner->relAttribute().isAlternate() && m_disabledState == EnabledViaScript && oldDisabledState == Disabled)
    639                 addPendingSheet(Blocking);
    640 
    641             // If the sheet is already loading just bail.
    642             return;
    643         }
    644 
    645         if (m_sheet)
    646             m_sheet->setDisabled(disabled);
    647 
    648         // Load the sheet, since it's never been loaded before.
    649         if (!m_sheet && m_disabledState == EnabledViaScript) {
    650             if (m_owner->shouldProcessStyle())
    651                 process();
    652         } else {
    653             // FIXME: We don't have enough knowledge here to know if we should call addedStyleSheet() or removedStyleSheet().
    654             m_owner->document().styleResolverChanged();
    655         }
    656     }
    657 }
    658 
    659 void LinkStyle::process()
    660 {
    661     ASSERT(m_owner->shouldProcessStyle());
    662     String type = m_owner->typeValue().lower();
    663     LinkRequestBuilder builder(m_owner);
    664 
    665     if (m_owner->relAttribute().iconType() != InvalidIcon && builder.url().isValid() && !builder.url().isEmpty()) {
    666         if (!m_owner->shouldLoadLink())
    667             return;
    668         if (!document().securityOrigin()->canDisplay(builder.url()))
    669             return;
    670         if (!document().contentSecurityPolicy()->allowImageFromSource(builder.url()))
    671             return;
    672         if (document().frame() && document().frame()->loader().client())
    673             document().frame()->loader().client()->dispatchDidChangeIcons(m_owner->relAttribute().iconType());
    674     }
    675 
    676     if (!m_owner->loadLink(type, builder.url()))
    677         return;
    678 
    679     if ((m_disabledState != Disabled) && (m_owner->relAttribute().isStyleSheet() || m_owner->relAttribute().isTransitionExitingStylesheet())
    680         && shouldLoadResource() && builder.url().isValid()) {
    681 
    682         if (resource()) {
    683             removePendingSheet();
    684             clearResource();
    685         }
    686 
    687         if (!m_owner->shouldLoadLink())
    688             return;
    689 
    690         m_loading = true;
    691 
    692         bool mediaQueryMatches = true;
    693         LocalFrame* frame = loadingFrame();
    694         if (!m_owner->media().isEmpty() && frame && frame->document()) {
    695             RefPtr<RenderStyle> documentStyle = StyleResolver::styleForDocument(*frame->document());
    696             RefPtrWillBeRawPtr<MediaQuerySet> media = MediaQuerySet::create(m_owner->media());
    697             MediaQueryEvaluator evaluator(frame);
    698             mediaQueryMatches = evaluator.eval(media.get());
    699         }
    700 
    701         // Don't hold up render tree construction and script execution on stylesheets
    702         // that are not needed for the rendering at the moment.
    703         bool blocking = mediaQueryMatches && !m_owner->isAlternate();
    704         addPendingSheet(blocking ? Blocking : NonBlocking);
    705 
    706         // Load stylesheets that are not needed for the rendering immediately with low priority.
    707         FetchRequest request = builder.build(blocking);
    708         AtomicString crossOriginMode = m_owner->fastGetAttribute(HTMLNames::crossoriginAttr);
    709         if (!crossOriginMode.isNull())
    710             request.setCrossOriginAccessControl(document().securityOrigin(), crossOriginMode);
    711         setResource(document().fetcher()->fetchCSSStyleSheet(request));
    712 
    713         if (!resource()) {
    714             // The request may have been denied if (for example) the stylesheet is local and the document is remote.
    715             m_loading = false;
    716             removePendingSheet();
    717         }
    718     } else if (m_sheet) {
    719         // we no longer contain a stylesheet, e.g. perhaps rel or type was changed
    720         RefPtrWillBeRawPtr<StyleSheet> removedSheet = m_sheet.get();
    721         clearSheet();
    722         document().removedStyleSheet(removedSheet.get());
    723     }
    724 }
    725 
    726 void LinkStyle::setSheetTitle(const String& title)
    727 {
    728     if (m_sheet)
    729         m_sheet->setTitle(title);
    730 }
    731 
    732 void LinkStyle::ownerRemoved()
    733 {
    734     if (m_sheet)
    735         clearSheet();
    736 
    737     if (styleSheetIsLoading())
    738         removePendingSheet();
    739 }
    740 
    741 void LinkStyle::trace(Visitor* visitor)
    742 {
    743     visitor->trace(m_sheet);
    744     LinkResource::trace(visitor);
    745 }
    746 
    747 } // namespace blink
    748