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