Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / html / HTMLLinkElement.cpp
1 /*
2  * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3  *           (C) 1999 Antti Koivisto (koivisto@kde.org)
4  *           (C) 2001 Dirk Mueller (mueller@kde.org)
5  * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
6  * Copyright (C) 2009 Rob Buis (rwlbuis@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