1 | /*
|
---|
2 | * (C) 1999-2003 Lars Knoll ([email protected])
|
---|
3 | * (C) 2002-2003 Dirk Mueller ([email protected])
|
---|
4 | * Copyright (C) 2002-2017 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 "StyleRuleImport.h"
|
---|
24 |
|
---|
25 | #include "CSSStyleSheet.h"
|
---|
26 | #include "CachedCSSStyleSheet.h"
|
---|
27 | #include "CachedResourceLoader.h"
|
---|
28 | #include "CachedResourceRequest.h"
|
---|
29 | #include "CachedResourceRequestInitiators.h"
|
---|
30 | #include "Document.h"
|
---|
31 | #include "MediaList.h"
|
---|
32 | #include "MediaQueryParser.h"
|
---|
33 | #include "SecurityOrigin.h"
|
---|
34 | #include "StyleSheetContents.h"
|
---|
35 | #include <wtf/StdLibExtras.h>
|
---|
36 |
|
---|
37 | namespace WebCore {
|
---|
38 |
|
---|
39 | Ref<StyleRuleImport> StyleRuleImport::create(const String& href, Ref<MediaQuerySet>&& media, std::optional<CascadeLayerName>&& cascadeLayerName)
|
---|
40 | {
|
---|
41 | return adoptRef(*new StyleRuleImport(href, WTFMove(media), WTFMove(cascadeLayerName)));
|
---|
42 | }
|
---|
43 |
|
---|
44 | StyleRuleImport::StyleRuleImport(const String& href, Ref<MediaQuerySet>&& media, std::optional<CascadeLayerName>&& cascadeLayerName)
|
---|
45 | : StyleRuleBase(StyleRuleType::Import)
|
---|
46 | , m_styleSheetClient(this)
|
---|
47 | , m_strHref(href)
|
---|
48 | , m_mediaQueries(WTFMove(media))
|
---|
49 | , m_cascadeLayerName(WTFMove(cascadeLayerName))
|
---|
50 | {
|
---|
51 | if (!m_mediaQueries)
|
---|
52 | m_mediaQueries = MediaQuerySet::create(String(), MediaQueryParserContext());
|
---|
53 | }
|
---|
54 |
|
---|
55 | void StyleRuleImport::cancelLoad()
|
---|
56 | {
|
---|
57 | if (!isLoading())
|
---|
58 | return;
|
---|
59 |
|
---|
60 | m_loading = false;
|
---|
61 | if (m_parentStyleSheet)
|
---|
62 | m_parentStyleSheet->checkLoaded();
|
---|
63 | }
|
---|
64 |
|
---|
65 | StyleRuleImport::~StyleRuleImport()
|
---|
66 | {
|
---|
67 | if (m_styleSheet)
|
---|
68 | m_styleSheet->clearOwnerRule();
|
---|
69 | if (m_cachedSheet)
|
---|
70 | m_cachedSheet->removeClient(m_styleSheetClient);
|
---|
71 | }
|
---|
72 |
|
---|
73 | void StyleRuleImport::setCSSStyleSheet(const String& href, const URL& baseURL, const String& charset, const CachedCSSStyleSheet* cachedStyleSheet)
|
---|
74 | {
|
---|
75 | if (m_styleSheet)
|
---|
76 | m_styleSheet->clearOwnerRule();
|
---|
77 |
|
---|
78 | CSSParserContext context = m_parentStyleSheet ? m_parentStyleSheet->parserContext() : HTMLStandardMode;
|
---|
79 | context.charset = charset;
|
---|
80 | if (!baseURL.isNull())
|
---|
81 | context.baseURL = baseURL;
|
---|
82 |
|
---|
83 | Document* document = m_parentStyleSheet ? m_parentStyleSheet->singleOwnerDocument() : nullptr;
|
---|
84 | m_styleSheet = StyleSheetContents::create(this, href, context);
|
---|
85 | if ((m_parentStyleSheet && m_parentStyleSheet->isContentOpaque()) || !cachedStyleSheet->isCORSSameOrigin())
|
---|
86 | m_styleSheet->setAsOpaque();
|
---|
87 |
|
---|
88 | bool parseSucceeded = m_styleSheet->parseAuthorStyleSheet(cachedStyleSheet, document ? &document->securityOrigin() : nullptr);
|
---|
89 |
|
---|
90 | m_loading = false;
|
---|
91 |
|
---|
92 | if (m_parentStyleSheet) {
|
---|
93 | if (parseSucceeded)
|
---|
94 | m_parentStyleSheet->notifyLoadedSheet(cachedStyleSheet);
|
---|
95 | else
|
---|
96 | m_parentStyleSheet->setLoadErrorOccured();
|
---|
97 | m_parentStyleSheet->checkLoaded();
|
---|
98 | }
|
---|
99 | }
|
---|
100 |
|
---|
101 | bool StyleRuleImport::isLoading() const
|
---|
102 | {
|
---|
103 | return m_loading || (m_styleSheet && m_styleSheet->isLoading());
|
---|
104 | }
|
---|
105 |
|
---|
106 | void StyleRuleImport::requestStyleSheet()
|
---|
107 | {
|
---|
108 | if (!m_parentStyleSheet)
|
---|
109 | return;
|
---|
110 | auto* document = m_parentStyleSheet->singleOwnerDocument();
|
---|
111 | if (!document)
|
---|
112 | return;
|
---|
113 | auto* page = document->page();
|
---|
114 | if (!page)
|
---|
115 | return;
|
---|
116 |
|
---|
117 | URL absURL;
|
---|
118 | if (!m_parentStyleSheet->baseURL().isNull())
|
---|
119 | // use parent styleheet's URL as the base URL
|
---|
120 | absURL = URL(m_parentStyleSheet->baseURL(), m_strHref);
|
---|
121 | else
|
---|
122 | absURL = document->completeURL(m_strHref);
|
---|
123 |
|
---|
124 | // Check for a cycle in our import chain. If we encounter a stylesheet
|
---|
125 | // in our parent chain with the same URL, then just bail.
|
---|
126 | StyleSheetContents* rootSheet = m_parentStyleSheet;
|
---|
127 | for (StyleSheetContents* sheet = m_parentStyleSheet; sheet; sheet = sheet->parentStyleSheet()) {
|
---|
128 | if (equalIgnoringFragmentIdentifier(absURL, sheet->baseURL())
|
---|
129 | || equalIgnoringFragmentIdentifier(absURL, document->completeURL(sheet->originalURL())))
|
---|
130 | return;
|
---|
131 | rootSheet = sheet;
|
---|
132 | }
|
---|
133 |
|
---|
134 | // FIXME: Skip Content Security Policy check when stylesheet is in a user agent shadow tree.
|
---|
135 | // See <https://bugs.webkit.org/show_bug.cgi?id=146663>.
|
---|
136 | CachedResourceRequest request(absURL, CachedResourceLoader::defaultCachedResourceOptions(), std::nullopt, String(m_parentStyleSheet->charset()));
|
---|
137 | request.setInitiator(cachedResourceRequestInitiators().css);
|
---|
138 | if (m_cachedSheet)
|
---|
139 | m_cachedSheet->removeClient(m_styleSheetClient);
|
---|
140 | if (m_parentStyleSheet->isUserStyleSheet()) {
|
---|
141 | ResourceLoaderOptions options {
|
---|
142 | SendCallbackPolicy::DoNotSendCallbacks,
|
---|
143 | ContentSniffingPolicy::SniffContent,
|
---|
144 | DataBufferingPolicy::BufferData,
|
---|
145 | StoredCredentialsPolicy::Use,
|
---|
146 | ClientCredentialPolicy::MayAskClientForCredentials,
|
---|
147 | FetchOptions::Credentials::Include,
|
---|
148 | SecurityCheckPolicy::SkipSecurityCheck,
|
---|
149 | FetchOptions::Mode::NoCors,
|
---|
150 | CertificateInfoPolicy::DoNotIncludeCertificateInfo,
|
---|
151 | ContentSecurityPolicyImposition::SkipPolicyCheck,
|
---|
152 | DefersLoadingPolicy::AllowDefersLoading,
|
---|
153 | CachingPolicy::AllowCaching
|
---|
154 | };
|
---|
155 | options.loadedFromOpaqueSource = m_parentStyleSheet->isContentOpaque() ? LoadedFromOpaqueSource::Yes : LoadedFromOpaqueSource::No;
|
---|
156 |
|
---|
157 | request.setOptions(WTFMove(options));
|
---|
158 |
|
---|
159 | m_cachedSheet = document->cachedResourceLoader().requestUserCSSStyleSheet(*page, WTFMove(request));
|
---|
160 | } else {
|
---|
161 | auto options = request.options();
|
---|
162 | options.loadedFromOpaqueSource = m_parentStyleSheet->isContentOpaque() ? LoadedFromOpaqueSource::Yes : LoadedFromOpaqueSource::No;
|
---|
163 | request.setOptions(WTFMove(options));
|
---|
164 | m_cachedSheet = document->cachedResourceLoader().requestCSSStyleSheet(WTFMove(request)).value_or(nullptr);
|
---|
165 | }
|
---|
166 | if (m_cachedSheet) {
|
---|
167 | // if the import rule is issued dynamically, the sheet may be
|
---|
168 | // removed from the pending sheet count, so let the doc know
|
---|
169 | // the sheet being imported is pending.
|
---|
170 | if (m_parentStyleSheet && m_parentStyleSheet->loadCompleted() && rootSheet == m_parentStyleSheet)
|
---|
171 | m_parentStyleSheet->startLoadingDynamicSheet();
|
---|
172 | m_loading = true;
|
---|
173 | m_cachedSheet->addClient(m_styleSheetClient);
|
---|
174 | } else if (m_parentStyleSheet) {
|
---|
175 | m_parentStyleSheet->setLoadErrorOccured();
|
---|
176 | m_parentStyleSheet->checkLoaded();
|
---|
177 | }
|
---|
178 | }
|
---|
179 |
|
---|
180 | } // namespace WebCore
|
---|