1 /* 2 * (C) 1999-2003 Lars Knoll (knoll (at) kde.org) 3 * (C) 2002-2003 Dirk Mueller (mueller (at) kde.org) 4 * Copyright (C) 2002, 2005, 2006, 2008, 2009, 2010, 2012 Apple Inc. All rights reserved. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Library General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Library General Public License for more details. 15 * 16 * You should have received a copy of the GNU Library General Public License 17 * along with this library; see the file COPYING.LIB. If not, write to 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA. 20 */ 21 22 #include "config.h" 23 #include "core/css/StyleRuleImport.h" 24 25 #include "core/FetchInitiatorTypeNames.h" 26 #include "core/css/StyleSheetContents.h" 27 #include "core/dom/Document.h" 28 #include "core/fetch/CSSStyleSheetResource.h" 29 #include "core/fetch/FetchRequest.h" 30 #include "core/fetch/ResourceFetcher.h" 31 32 namespace blink { 33 34 PassRefPtrWillBeRawPtr<StyleRuleImport> StyleRuleImport::create(const String& href, PassRefPtrWillBeRawPtr<MediaQuerySet> media) 35 { 36 return adoptRefWillBeNoop(new StyleRuleImport(href, media)); 37 } 38 39 StyleRuleImport::StyleRuleImport(const String& href, PassRefPtrWillBeRawPtr<MediaQuerySet> media) 40 : StyleRuleBase(Import) 41 , m_parentStyleSheet(nullptr) 42 , m_styleSheetClient(this) 43 , m_strHref(href) 44 , m_mediaQueries(media) 45 , m_resource(0) 46 , m_loading(false) 47 { 48 if (!m_mediaQueries) 49 m_mediaQueries = MediaQuerySet::create(String()); 50 } 51 52 StyleRuleImport::~StyleRuleImport() 53 { 54 #if !ENABLE(OILPAN) 55 if (m_styleSheet) 56 m_styleSheet->clearOwnerRule(); 57 #endif 58 if (m_resource) 59 m_resource->removeClient(&m_styleSheetClient); 60 } 61 62 void StyleRuleImport::traceAfterDispatch(Visitor* visitor) 63 { 64 visitor->trace(m_parentStyleSheet); 65 visitor->trace(m_mediaQueries); 66 visitor->trace(m_styleSheet); 67 StyleRuleBase::traceAfterDispatch(visitor); 68 } 69 70 void StyleRuleImport::setCSSStyleSheet(const String& href, const KURL& baseURL, const String& charset, const CSSStyleSheetResource* cachedStyleSheet) 71 { 72 if (m_styleSheet) 73 m_styleSheet->clearOwnerRule(); 74 75 CSSParserContext context = m_parentStyleSheet ? m_parentStyleSheet->parserContext() : strictCSSParserContext(); 76 context.setCharset(charset); 77 Document* document = m_parentStyleSheet ? m_parentStyleSheet->singleOwnerDocument() : 0; 78 if (!baseURL.isNull()) { 79 context.setBaseURL(baseURL); 80 if (document) 81 context.setReferrer(Referrer(baseURL.strippedForUseAsReferrer(), document->referrerPolicy())); 82 } 83 84 m_styleSheet = StyleSheetContents::create(this, href, context); 85 86 m_styleSheet->parseAuthorStyleSheet(cachedStyleSheet, document ? document->securityOrigin() : 0); 87 88 m_loading = false; 89 90 if (m_parentStyleSheet) { 91 m_parentStyleSheet->notifyLoadedSheet(cachedStyleSheet); 92 m_parentStyleSheet->checkLoaded(); 93 } 94 } 95 96 bool StyleRuleImport::isLoading() const 97 { 98 return m_loading || (m_styleSheet && m_styleSheet->isLoading()); 99 } 100 101 void StyleRuleImport::requestStyleSheet() 102 { 103 if (!m_parentStyleSheet) 104 return; 105 Document* document = m_parentStyleSheet->singleOwnerDocument(); 106 if (!document) 107 return; 108 109 ResourceFetcher* fetcher = document->fetcher(); 110 if (!fetcher) 111 return; 112 113 KURL absURL; 114 if (!m_parentStyleSheet->baseURL().isNull()) 115 // use parent styleheet's URL as the base URL 116 absURL = KURL(m_parentStyleSheet->baseURL(), m_strHref); 117 else 118 absURL = document->completeURL(m_strHref); 119 120 // Check for a cycle in our import chain. If we encounter a stylesheet 121 // in our parent chain with the same URL, then just bail. 122 StyleSheetContents* rootSheet = m_parentStyleSheet; 123 for (StyleSheetContents* sheet = m_parentStyleSheet; sheet; sheet = sheet->parentStyleSheet()) { 124 if (equalIgnoringFragmentIdentifier(absURL, sheet->baseURL()) 125 || equalIgnoringFragmentIdentifier(absURL, document->completeURL(sheet->originalURL()))) 126 return; 127 rootSheet = sheet; 128 } 129 130 FetchRequest request(ResourceRequest(absURL), FetchInitiatorTypeNames::css, m_parentStyleSheet->charset()); 131 m_resource = fetcher->fetchCSSStyleSheet(request); 132 if (m_resource) { 133 // if the import rule is issued dynamically, the sheet may be 134 // removed from the pending sheet count, so let the doc know 135 // the sheet being imported is pending. 136 if (m_parentStyleSheet && m_parentStyleSheet->loadCompleted() && rootSheet == m_parentStyleSheet) 137 m_parentStyleSheet->startLoadingDynamicSheet(); 138 m_loading = true; 139 m_resource->addClient(&m_styleSheetClient); 140 } 141 } 142 143 } // namespace blink 144