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