| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
| 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
| 4 * (C) 2001 Dirk Mueller (mueller@kde.org) | 4 * (C) 2001 Dirk Mueller (mueller@kde.org) |
| 5 * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights | 5 * Copyright (C) 2003, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights |
| 6 * reserved. | 6 * reserved. |
| 7 * Copyright (C) 2009 Rob Buis (rwlbuis@gmail.com) | 7 * Copyright (C) 2009 Rob Buis (rwlbuis@gmail.com) |
| 8 * Copyright (C) 2011 Google Inc. All rights reserved. | 8 * Copyright (C) 2011 Google Inc. All rights reserved. |
| 9 * | 9 * |
| 10 * This library is free software; you can redistribute it and/or | 10 * This library is free software; you can redistribute it and/or |
| 11 * modify it under the terms of the GNU Library General Public | 11 * modify it under the terms of the GNU Library General Public |
| 12 * License as published by the Free Software Foundation; either | 12 * License as published by the Free Software Foundation; either |
| 13 * version 2 of the License, or (at your option) any later version. | 13 * version 2 of the License, or (at your option) any later version. |
| 14 * | 14 * |
| 15 * This library is distributed in the hope that it will be useful, | 15 * This library is distributed in the hope that it will be useful, |
| 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 18 * Library General Public License for more details. | 18 * Library General Public License for more details. |
| 19 * | 19 * |
| 20 * You should have received a copy of the GNU Library General Public License | 20 * You should have received a copy of the GNU Library General Public License |
| 21 * along with this library; see the file COPYING.LIB. If not, write to | 21 * along with this library; see the file COPYING.LIB. If not, write to |
| 22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 23 * Boston, MA 02110-1301, USA. | 23 * Boston, MA 02110-1301, USA. |
| 24 */ | 24 */ |
| 25 | 25 |
| 26 #include "core/html/HTMLLinkElement.h" | 26 #include "core/html/HTMLLinkElement.h" |
| 27 | 27 |
| 28 #include "bindings/core/v8/ScriptEventListener.h" | 28 #include "bindings/core/v8/ScriptEventListener.h" |
| 29 #include "core/HTMLNames.h" | 29 #include "core/HTMLNames.h" |
| 30 #include "core/css/MediaList.h" | |
| 31 #include "core/css/MediaQueryEvaluator.h" | |
| 32 #include "core/css/StyleSheetContents.h" | |
| 33 #include "core/css/resolver/StyleResolver.h" | |
| 34 #include "core/dom/Attribute.h" | 30 #include "core/dom/Attribute.h" |
| 35 #include "core/dom/Document.h" | 31 #include "core/dom/Document.h" |
| 36 #include "core/dom/StyleEngine.h" | |
| 37 #include "core/dom/TaskRunnerHelper.h" | 32 #include "core/dom/TaskRunnerHelper.h" |
| 38 #include "core/events/Event.h" | 33 #include "core/events/Event.h" |
| 39 #include "core/fetch/CSSStyleSheetResource.h" | |
| 40 #include "core/fetch/FetchRequest.h" | |
| 41 #include "core/fetch/ResourceFetcher.h" | |
| 42 #include "core/frame/FrameView.h" | |
| 43 #include "core/frame/LocalFrame.h" | |
| 44 #include "core/frame/SubresourceIntegrity.h" | |
| 45 #include "core/frame/UseCounter.h" | 34 #include "core/frame/UseCounter.h" |
| 46 #include "core/frame/csp/ContentSecurityPolicy.h" | |
| 47 #include "core/html/CrossOriginAttribute.h" | 35 #include "core/html/CrossOriginAttribute.h" |
| 48 #include "core/html/LinkManifest.h" | 36 #include "core/html/LinkManifest.h" |
| 49 #include "core/html/imports/LinkImport.h" | 37 #include "core/html/imports/LinkImport.h" |
| 50 #include "core/inspector/ConsoleMessage.h" | 38 #include "core/inspector/ConsoleMessage.h" |
| 51 #include "core/loader/FrameLoader.h" | |
| 52 #include "core/loader/FrameLoaderClient.h" | 39 #include "core/loader/FrameLoaderClient.h" |
| 53 #include "core/loader/NetworkHintsInterface.h" | 40 #include "core/loader/NetworkHintsInterface.h" |
| 54 #include "core/origin_trials/OriginTrials.h" | 41 #include "core/origin_trials/OriginTrials.h" |
| 55 #include "core/style/StyleInheritedData.h" | |
| 56 #include "platform/ContentType.h" | |
| 57 #include "platform/Histogram.h" | |
| 58 #include "platform/MIMETypeRegistry.h" | |
| 59 #include "platform/RuntimeEnabledFeatures.h" | |
| 60 #include "public/platform/WebIconSizesParser.h" | 42 #include "public/platform/WebIconSizesParser.h" |
| 61 #include "public/platform/WebSize.h" | 43 #include "public/platform/WebSize.h" |
| 62 #include "wtf/StdLibExtras.h" | |
| 63 | 44 |
| 64 namespace blink { | 45 namespace blink { |
| 65 | 46 |
| 66 using namespace HTMLNames; | 47 using namespace HTMLNames; |
| 67 | 48 |
| 68 static bool styleSheetTypeIsSupported(const String& type) { | |
| 69 String trimmedType = ContentType(type).type(); | |
| 70 return trimmedType.isEmpty() || | |
| 71 MIMETypeRegistry::isSupportedStyleSheetMIMEType(trimmedType); | |
| 72 } | |
| 73 | |
| 74 inline HTMLLinkElement::HTMLLinkElement(Document& document, | 49 inline HTMLLinkElement::HTMLLinkElement(Document& document, |
| 75 bool createdByParser) | 50 bool createdByParser) |
| 76 : HTMLElement(linkTag, document), | 51 : HTMLElement(linkTag, document), |
| 77 m_linkLoader(LinkLoader::create(this)), | 52 m_linkLoader(LinkLoader::create(this)), |
| 78 m_sizes(DOMTokenList::create(this)), | 53 m_sizes(DOMTokenList::create(this)), |
| 79 m_relList(RelList::create(this)), | 54 m_relList(RelList::create(this)), |
| 80 m_createdByParser(createdByParser) {} | 55 m_createdByParser(createdByParser) {} |
| 81 | 56 |
| 82 HTMLLinkElement* HTMLLinkElement::create(Document& document, | 57 HTMLLinkElement* HTMLLinkElement::create(Document& document, |
| 83 bool createdByParser) { | 58 bool createdByParser) { |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 HTMLElement::trace(visitor); | 352 HTMLElement::trace(visitor); |
| 378 LinkLoaderClient::trace(visitor); | 353 LinkLoaderClient::trace(visitor); |
| 379 DOMTokenListObserver::trace(visitor); | 354 DOMTokenListObserver::trace(visitor); |
| 380 } | 355 } |
| 381 | 356 |
| 382 DEFINE_TRACE_WRAPPERS(HTMLLinkElement) { | 357 DEFINE_TRACE_WRAPPERS(HTMLLinkElement) { |
| 383 visitor->traceWrappers(m_relList); | 358 visitor->traceWrappers(m_relList); |
| 384 HTMLElement::traceWrappers(visitor); | 359 HTMLElement::traceWrappers(visitor); |
| 385 } | 360 } |
| 386 | 361 |
| 387 LinkStyle* LinkStyle::create(HTMLLinkElement* owner) { | |
| 388 return new LinkStyle(owner); | |
| 389 } | |
| 390 | |
| 391 LinkStyle::LinkStyle(HTMLLinkElement* owner) | |
| 392 : LinkResource(owner), | |
| 393 m_disabledState(Unset), | |
| 394 m_pendingSheetType(None), | |
| 395 m_loading(false), | |
| 396 m_firedLoad(false), | |
| 397 m_loadedSheet(false), | |
| 398 m_fetchFollowingCORS(false) {} | |
| 399 | |
| 400 LinkStyle::~LinkStyle() {} | |
| 401 | |
| 402 Document& LinkStyle::document() { | |
| 403 return m_owner->document(); | |
| 404 } | |
| 405 | |
| 406 enum StyleSheetCacheStatus { | |
| 407 StyleSheetNewEntry, | |
| 408 StyleSheetInDiskCache, | |
| 409 StyleSheetInMemoryCache, | |
| 410 StyleSheetCacheStatusCount, | |
| 411 }; | |
| 412 | |
| 413 void LinkStyle::setCSSStyleSheet( | |
| 414 const String& href, | |
| 415 const KURL& baseURL, | |
| 416 const String& charset, | |
| 417 const CSSStyleSheetResource* cachedStyleSheet) { | |
| 418 if (!m_owner->isConnected()) { | |
| 419 // While the stylesheet is asynchronously loading, the owner can be | |
| 420 // disconnected from a document. | |
| 421 // In that case, cancel any processing on the loaded content. | |
| 422 m_loading = false; | |
| 423 removePendingSheet(); | |
| 424 if (m_sheet) | |
| 425 clearSheet(); | |
| 426 return; | |
| 427 } | |
| 428 | |
| 429 // See the comment in PendingScript.cpp about why this check is necessary | |
| 430 // here, instead of in the resource fetcher. https://crbug.com/500701. | |
| 431 if (!cachedStyleSheet->errorOccurred() && | |
| 432 !m_owner->fastGetAttribute(HTMLNames::integrityAttr).isEmpty() && | |
| 433 !cachedStyleSheet->integrityMetadata().isEmpty()) { | |
| 434 ResourceIntegrityDisposition disposition = | |
| 435 cachedStyleSheet->integrityDisposition(); | |
| 436 | |
| 437 if (disposition == ResourceIntegrityDisposition::NotChecked && | |
| 438 !cachedStyleSheet->loadFailedOrCanceled()) { | |
| 439 bool checkResult; | |
| 440 | |
| 441 // cachedStyleSheet->resourceBuffer() can be nullptr on load success. | |
| 442 // If response size == 0. | |
| 443 const char* data = nullptr; | |
| 444 size_t size = 0; | |
| 445 if (cachedStyleSheet->resourceBuffer()) { | |
| 446 data = cachedStyleSheet->resourceBuffer()->data(); | |
| 447 size = cachedStyleSheet->resourceBuffer()->size(); | |
| 448 } | |
| 449 checkResult = SubresourceIntegrity::CheckSubresourceIntegrity( | |
| 450 *m_owner, data, size, KURL(baseURL, href), *cachedStyleSheet); | |
| 451 disposition = checkResult ? ResourceIntegrityDisposition::Passed | |
| 452 : ResourceIntegrityDisposition::Failed; | |
| 453 | |
| 454 // TODO(kouhei): Remove this const_cast crbug.com/653502 | |
| 455 const_cast<CSSStyleSheetResource*>(cachedStyleSheet) | |
| 456 ->setIntegrityDisposition(disposition); | |
| 457 } | |
| 458 | |
| 459 if (disposition == ResourceIntegrityDisposition::Failed) { | |
| 460 m_loading = false; | |
| 461 removePendingSheet(); | |
| 462 notifyLoadedSheetAndAllCriticalSubresources( | |
| 463 Node::ErrorOccurredLoadingSubresource); | |
| 464 return; | |
| 465 } | |
| 466 } | |
| 467 | |
| 468 CSSParserContext parserContext(m_owner->document(), nullptr, baseURL, | |
| 469 charset); | |
| 470 | |
| 471 DEFINE_STATIC_LOCAL(EnumerationHistogram, restoredCachedStyleSheetHistogram, | |
| 472 ("Blink.RestoredCachedStyleSheet", 2)); | |
| 473 DEFINE_STATIC_LOCAL( | |
| 474 EnumerationHistogram, restoredCachedStyleSheet2Histogram, | |
| 475 ("Blink.RestoredCachedStyleSheet2", StyleSheetCacheStatusCount)); | |
| 476 | |
| 477 if (StyleSheetContents* restoredSheet = | |
| 478 const_cast<CSSStyleSheetResource*>(cachedStyleSheet) | |
| 479 ->restoreParsedStyleSheet(parserContext)) { | |
| 480 DCHECK(restoredSheet->isCacheableForResource()); | |
| 481 DCHECK(!restoredSheet->isLoading()); | |
| 482 | |
| 483 if (m_sheet) | |
| 484 clearSheet(); | |
| 485 m_sheet = CSSStyleSheet::create(restoredSheet, *m_owner); | |
| 486 m_sheet->setMediaQueries(MediaQuerySet::create(m_owner->media())); | |
| 487 if (m_owner->isInDocumentTree()) | |
| 488 setSheetTitle(m_owner->title()); | |
| 489 setCrossOriginStylesheetStatus(m_sheet.get()); | |
| 490 | |
| 491 m_loading = false; | |
| 492 restoredSheet->checkLoaded(); | |
| 493 | |
| 494 restoredCachedStyleSheetHistogram.count(true); | |
| 495 restoredCachedStyleSheet2Histogram.count(StyleSheetInMemoryCache); | |
| 496 return; | |
| 497 } | |
| 498 restoredCachedStyleSheetHistogram.count(false); | |
| 499 StyleSheetCacheStatus cacheStatus = cachedStyleSheet->response().wasCached() | |
| 500 ? StyleSheetInDiskCache | |
| 501 : StyleSheetNewEntry; | |
| 502 restoredCachedStyleSheet2Histogram.count(cacheStatus); | |
| 503 | |
| 504 StyleSheetContents* styleSheet = | |
| 505 StyleSheetContents::create(href, parserContext); | |
| 506 | |
| 507 if (m_sheet) | |
| 508 clearSheet(); | |
| 509 | |
| 510 m_sheet = CSSStyleSheet::create(styleSheet, *m_owner); | |
| 511 m_sheet->setMediaQueries(MediaQuerySet::create(m_owner->media())); | |
| 512 if (m_owner->isInDocumentTree()) | |
| 513 setSheetTitle(m_owner->title()); | |
| 514 setCrossOriginStylesheetStatus(m_sheet.get()); | |
| 515 | |
| 516 styleSheet->parseAuthorStyleSheet(cachedStyleSheet, | |
| 517 m_owner->document().getSecurityOrigin()); | |
| 518 | |
| 519 m_loading = false; | |
| 520 styleSheet->notifyLoadedSheet(cachedStyleSheet); | |
| 521 styleSheet->checkLoaded(); | |
| 522 | |
| 523 if (styleSheet->isCacheableForResource()) | |
| 524 const_cast<CSSStyleSheetResource*>(cachedStyleSheet) | |
| 525 ->saveParsedStyleSheet(styleSheet); | |
| 526 clearResource(); | |
| 527 } | |
| 528 | |
| 529 bool LinkStyle::sheetLoaded() { | |
| 530 if (!styleSheetIsLoading()) { | |
| 531 removePendingSheet(); | |
| 532 return true; | |
| 533 } | |
| 534 return false; | |
| 535 } | |
| 536 | |
| 537 void LinkStyle::notifyLoadedSheetAndAllCriticalSubresources( | |
| 538 Node::LoadedSheetErrorStatus errorStatus) { | |
| 539 if (m_firedLoad) | |
| 540 return; | |
| 541 m_loadedSheet = (errorStatus == Node::NoErrorLoadingSubresource); | |
| 542 if (m_owner) | |
| 543 m_owner->scheduleEvent(); | |
| 544 m_firedLoad = true; | |
| 545 } | |
| 546 | |
| 547 void LinkStyle::startLoadingDynamicSheet() { | |
| 548 DCHECK_LT(m_pendingSheetType, Blocking); | |
| 549 addPendingSheet(Blocking); | |
| 550 } | |
| 551 | |
| 552 void LinkStyle::clearSheet() { | |
| 553 DCHECK(m_sheet); | |
| 554 DCHECK_EQ(m_sheet->ownerNode(), m_owner); | |
| 555 m_sheet.release()->clearOwnerNode(); | |
| 556 } | |
| 557 | |
| 558 bool LinkStyle::styleSheetIsLoading() const { | |
| 559 if (m_loading) | |
| 560 return true; | |
| 561 if (!m_sheet) | |
| 562 return false; | |
| 563 return m_sheet->contents()->isLoading(); | |
| 564 } | |
| 565 | |
| 566 void LinkStyle::addPendingSheet(PendingSheetType type) { | |
| 567 if (type <= m_pendingSheetType) | |
| 568 return; | |
| 569 m_pendingSheetType = type; | |
| 570 | |
| 571 if (m_pendingSheetType == NonBlocking) | |
| 572 return; | |
| 573 m_owner->document().styleEngine().addPendingSheet(m_styleEngineContext); | |
| 574 } | |
| 575 | |
| 576 void LinkStyle::removePendingSheet() { | |
| 577 DCHECK(m_owner); | |
| 578 PendingSheetType type = m_pendingSheetType; | |
| 579 m_pendingSheetType = None; | |
| 580 | |
| 581 if (type == None) | |
| 582 return; | |
| 583 if (type == NonBlocking) { | |
| 584 // Tell StyleEngine to re-compute styleSheets of this m_owner's treescope. | |
| 585 m_owner->document().styleEngine().modifiedStyleSheetCandidateNode(*m_owner); | |
| 586 return; | |
| 587 } | |
| 588 | |
| 589 m_owner->document().styleEngine().removePendingSheet(*m_owner, | |
| 590 m_styleEngineContext); | |
| 591 } | |
| 592 | |
| 593 void LinkStyle::setDisabledState(bool disabled) { | |
| 594 LinkStyle::DisabledState oldDisabledState = m_disabledState; | |
| 595 m_disabledState = disabled ? Disabled : EnabledViaScript; | |
| 596 if (oldDisabledState != m_disabledState) { | |
| 597 // If we change the disabled state while the sheet is still loading, then we | |
| 598 // have to perform three checks: | |
| 599 if (styleSheetIsLoading()) { | |
| 600 // Check #1: The sheet becomes disabled while loading. | |
| 601 if (m_disabledState == Disabled) | |
| 602 removePendingSheet(); | |
| 603 | |
| 604 // Check #2: An alternate sheet becomes enabled while it is still loading. | |
| 605 if (m_owner->relAttribute().isAlternate() && | |
| 606 m_disabledState == EnabledViaScript) | |
| 607 addPendingSheet(Blocking); | |
| 608 | |
| 609 // Check #3: A main sheet becomes enabled while it was still loading and | |
| 610 // after it was disabled via script. It takes really terrible code to make | |
| 611 // this happen (a double toggle for no reason essentially). This happens | |
| 612 // on virtualplastic.net, which manages to do about 12 enable/disables on | |
| 613 // only 3 sheets. :) | |
| 614 if (!m_owner->relAttribute().isAlternate() && | |
| 615 m_disabledState == EnabledViaScript && oldDisabledState == Disabled) | |
| 616 addPendingSheet(Blocking); | |
| 617 | |
| 618 // If the sheet is already loading just bail. | |
| 619 return; | |
| 620 } | |
| 621 | |
| 622 if (m_sheet) { | |
| 623 m_sheet->setDisabled(disabled); | |
| 624 return; | |
| 625 } | |
| 626 | |
| 627 if (m_disabledState == EnabledViaScript && m_owner->shouldProcessStyle()) | |
| 628 process(); | |
| 629 } | |
| 630 } | |
| 631 | |
| 632 void LinkStyle::setCrossOriginStylesheetStatus(CSSStyleSheet* sheet) { | |
| 633 if (m_fetchFollowingCORS && resource() && !resource()->errorOccurred()) { | |
| 634 // Record the security origin the CORS access check succeeded at, if cross | |
| 635 // origin. Only origins that are script accessible to it may access the | |
| 636 // stylesheet's rules. | |
| 637 sheet->setAllowRuleAccessFromOrigin( | |
| 638 m_owner->document().getSecurityOrigin()); | |
| 639 } | |
| 640 m_fetchFollowingCORS = false; | |
| 641 } | |
| 642 | |
| 643 void LinkStyle::process() { | |
| 644 DCHECK(m_owner->shouldProcessStyle()); | |
| 645 String type = m_owner->typeValue().lower(); | |
| 646 String as = m_owner->asValue().lower(); | |
| 647 String media = m_owner->media().lower(); | |
| 648 LinkRequestBuilder builder(m_owner); | |
| 649 | |
| 650 if (m_owner->relAttribute().getIconType() != InvalidIcon && | |
| 651 builder.url().isValid() && !builder.url().isEmpty()) { | |
| 652 if (!m_owner->shouldLoadLink()) | |
| 653 return; | |
| 654 if (!document().getSecurityOrigin()->canDisplay(builder.url())) | |
| 655 return; | |
| 656 if (!document().contentSecurityPolicy()->allowImageFromSource( | |
| 657 builder.url())) | |
| 658 return; | |
| 659 if (document().frame() && document().frame()->loader().client()) | |
| 660 document().frame()->loader().client()->dispatchDidChangeIcons( | |
| 661 m_owner->relAttribute().getIconType()); | |
| 662 } | |
| 663 | |
| 664 if (!m_owner->loadLink(type, as, media, builder.url())) | |
| 665 return; | |
| 666 | |
| 667 if (m_disabledState != Disabled && m_owner->relAttribute().isStyleSheet() && | |
| 668 styleSheetTypeIsSupported(type) && shouldLoadResource() && | |
| 669 builder.url().isValid()) { | |
| 670 if (resource()) { | |
| 671 removePendingSheet(); | |
| 672 clearResource(); | |
| 673 clearFetchFollowingCORS(); | |
| 674 } | |
| 675 | |
| 676 if (!m_owner->shouldLoadLink()) | |
| 677 return; | |
| 678 | |
| 679 m_loading = true; | |
| 680 | |
| 681 String title = m_owner->title(); | |
| 682 if (!title.isEmpty() && !m_owner->isAlternate() && | |
| 683 m_disabledState != EnabledViaScript && m_owner->isInDocumentTree()) | |
| 684 document().styleEngine().setPreferredStylesheetSetNameIfNotSet( | |
| 685 title, StyleEngine::DontUpdateActiveSheets); | |
| 686 | |
| 687 bool mediaQueryMatches = true; | |
| 688 LocalFrame* frame = loadingFrame(); | |
| 689 if (!m_owner->media().isEmpty() && frame) { | |
| 690 MediaQuerySet* media = MediaQuerySet::create(m_owner->media()); | |
| 691 MediaQueryEvaluator evaluator(frame); | |
| 692 mediaQueryMatches = evaluator.eval(media); | |
| 693 } | |
| 694 | |
| 695 // Don't hold up layout tree construction and script execution on | |
| 696 // stylesheets that are not needed for the layout at the moment. | |
| 697 bool blocking = mediaQueryMatches && !m_owner->isAlternate() && | |
| 698 m_owner->isCreatedByParser(); | |
| 699 addPendingSheet(blocking ? Blocking : NonBlocking); | |
| 700 | |
| 701 // Load stylesheets that are not needed for the layout immediately with low | |
| 702 // priority. When the link element is created by scripts, load the | |
| 703 // stylesheets asynchronously but in high priority. | |
| 704 bool lowPriority = !mediaQueryMatches || m_owner->isAlternate(); | |
| 705 FetchRequest request = builder.build(lowPriority); | |
| 706 CrossOriginAttributeValue crossOrigin = crossOriginAttributeValue( | |
| 707 m_owner->fastGetAttribute(HTMLNames::crossoriginAttr)); | |
| 708 if (crossOrigin != CrossOriginAttributeNotSet) { | |
| 709 request.setCrossOriginAccessControl(document().getSecurityOrigin(), | |
| 710 crossOrigin); | |
| 711 setFetchFollowingCORS(); | |
| 712 } | |
| 713 | |
| 714 String integrityAttr = m_owner->fastGetAttribute(HTMLNames::integrityAttr); | |
| 715 if (!integrityAttr.isEmpty()) { | |
| 716 IntegrityMetadataSet metadataSet; | |
| 717 SubresourceIntegrity::parseIntegrityAttribute(integrityAttr, metadataSet); | |
| 718 request.setIntegrityMetadata(metadataSet); | |
| 719 } | |
| 720 setResource(CSSStyleSheetResource::fetch(request, document().fetcher())); | |
| 721 | |
| 722 if (m_loading && !resource()) { | |
| 723 // The request may have been denied if (for example) the stylesheet is | |
| 724 // local and the document is remote, or if there was a Content Security | |
| 725 // Policy Failure. setCSSStyleSheet() can be called synchronuosly in | |
| 726 // setResource() and thus resource() is null and |m_loading| is false in | |
| 727 // such cases even if the request succeeds. | |
| 728 m_loading = false; | |
| 729 removePendingSheet(); | |
| 730 notifyLoadedSheetAndAllCriticalSubresources( | |
| 731 Node::ErrorOccurredLoadingSubresource); | |
| 732 } | |
| 733 } else if (m_sheet) { | |
| 734 // we no longer contain a stylesheet, e.g. perhaps rel or type was changed | |
| 735 StyleSheet* removedSheet = m_sheet.get(); | |
| 736 clearSheet(); | |
| 737 document().styleEngine().setNeedsActiveStyleUpdate(removedSheet, | |
| 738 FullStyleUpdate); | |
| 739 } | |
| 740 } | |
| 741 | |
| 742 void LinkStyle::setSheetTitle( | |
| 743 const String& title, | |
| 744 StyleEngine::ActiveSheetsUpdate updateActiveSheets) { | |
| 745 if (!m_owner->isInDocumentTree() || !m_owner->relAttribute().isStyleSheet()) | |
| 746 return; | |
| 747 | |
| 748 if (m_sheet) | |
| 749 m_sheet->setTitle(title); | |
| 750 | |
| 751 if (title.isEmpty() || !isUnset() || m_owner->isAlternate()) | |
| 752 return; | |
| 753 | |
| 754 KURL href = m_owner->getNonEmptyURLAttribute(hrefAttr); | |
| 755 if (href.isValid() && !href.isEmpty()) | |
| 756 document().styleEngine().setPreferredStylesheetSetNameIfNotSet( | |
| 757 title, updateActiveSheets); | |
| 758 } | |
| 759 | |
| 760 void LinkStyle::ownerRemoved() { | |
| 761 if (m_sheet) | |
| 762 clearSheet(); | |
| 763 | |
| 764 if (styleSheetIsLoading()) | |
| 765 removePendingSheet(); | |
| 766 } | |
| 767 | |
| 768 DEFINE_TRACE(LinkStyle) { | |
| 769 visitor->trace(m_sheet); | |
| 770 LinkResource::trace(visitor); | |
| 771 ResourceOwner<StyleSheetResource>::trace(visitor); | |
| 772 } | |
| 773 | |
| 774 } // namespace blink | 362 } // namespace blink |
| OLD | NEW |