OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/html/LinkStyle.h" | 5 #include "core/html/LinkStyle.h" |
6 | 6 |
| 7 #include "core/HTMLNames.h" |
7 #include "core/css/StyleSheetContents.h" | 8 #include "core/css/StyleSheetContents.h" |
| 9 #include "core/fetch/FetchRequest.h" |
8 #include "core/frame/LocalFrame.h" | 10 #include "core/frame/LocalFrame.h" |
9 #include "core/frame/SubresourceIntegrity.h" | 11 #include "core/frame/SubresourceIntegrity.h" |
10 #include "core/frame/csp/ContentSecurityPolicy.h" | 12 #include "core/frame/csp/ContentSecurityPolicy.h" |
11 #include "core/html/CrossOriginAttribute.h" | 13 #include "core/html/CrossOriginAttribute.h" |
12 #include "core/html/HTMLLinkElement.h" | 14 #include "core/html/HTMLLinkElement.h" |
| 15 #include "core/html/imports/HTMLImportsController.h" |
13 #include "core/loader/FrameLoaderClient.h" | 16 #include "core/loader/FrameLoaderClient.h" |
14 #include "core/loader/resource/CSSStyleSheetResource.h" | 17 #include "core/loader/resource/CSSStyleSheetResource.h" |
15 #include "platform/ContentType.h" | 18 #include "platform/ContentType.h" |
16 #include "platform/Histogram.h" | 19 #include "platform/Histogram.h" |
17 #include "platform/MIMETypeRegistry.h" | 20 #include "platform/MIMETypeRegistry.h" |
| 21 #include "platform/weborigin/KURL.h" |
| 22 #include "wtf/text/WTFString.h" |
18 | 23 |
19 namespace blink { | 24 namespace blink { |
20 | 25 |
21 using namespace HTMLNames; | 26 using namespace HTMLNames; |
22 | 27 |
23 static bool styleSheetTypeIsSupported(const String& type) { | 28 static bool styleSheetTypeIsSupported(const String& type) { |
24 String trimmedType = ContentType(type).type(); | 29 String trimmedType = ContentType(type).type(); |
25 return trimmedType.isEmpty() || | 30 return trimmedType.isEmpty() || |
26 MIMETypeRegistry::isSupportedStyleSheetMIMEType(trimmedType); | 31 MIMETypeRegistry::isSupportedStyleSheetMIMEType(trimmedType); |
27 } | 32 } |
(...skipping 10 matching lines...) Expand all Loading... |
38 m_firedLoad(false), | 43 m_firedLoad(false), |
39 m_loadedSheet(false), | 44 m_loadedSheet(false), |
40 m_fetchFollowingCORS(false) {} | 45 m_fetchFollowingCORS(false) {} |
41 | 46 |
42 LinkStyle::~LinkStyle() {} | 47 LinkStyle::~LinkStyle() {} |
43 | 48 |
44 Document& LinkStyle::document() { | 49 Document& LinkStyle::document() { |
45 return m_owner->document(); | 50 return m_owner->document(); |
46 } | 51 } |
47 | 52 |
| 53 const Document& LinkStyle::document() const { |
| 54 return m_owner->document(); |
| 55 } |
| 56 |
48 enum StyleSheetCacheStatus { | 57 enum StyleSheetCacheStatus { |
49 StyleSheetNewEntry, | 58 StyleSheetNewEntry, |
50 StyleSheetInDiskCache, | 59 StyleSheetInDiskCache, |
51 StyleSheetInMemoryCache, | 60 StyleSheetInMemoryCache, |
52 StyleSheetCacheStatusCount, | 61 StyleSheetCacheStatusCount, |
53 }; | 62 }; |
54 | 63 |
55 void LinkStyle::setCSSStyleSheet( | 64 void LinkStyle::setCSSStyleSheet( |
56 const String& href, | 65 const String& href, |
57 const KURL& baseURL, | 66 const KURL& baseURL, |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 | 109 |
101 if (disposition == ResourceIntegrityDisposition::Failed) { | 110 if (disposition == ResourceIntegrityDisposition::Failed) { |
102 m_loading = false; | 111 m_loading = false; |
103 removePendingSheet(); | 112 removePendingSheet(); |
104 notifyLoadedSheetAndAllCriticalSubresources( | 113 notifyLoadedSheetAndAllCriticalSubresources( |
105 Node::ErrorOccurredLoadingSubresource); | 114 Node::ErrorOccurredLoadingSubresource); |
106 return; | 115 return; |
107 } | 116 } |
108 } | 117 } |
109 | 118 |
110 CSSParserContext parserContext(m_owner->document(), nullptr, baseURL, | 119 CSSParserContext parserContext(document(), nullptr, baseURL, charset); |
111 charset); | |
112 | 120 |
113 DEFINE_STATIC_LOCAL(EnumerationHistogram, restoredCachedStyleSheetHistogram, | 121 DEFINE_STATIC_LOCAL(EnumerationHistogram, restoredCachedStyleSheetHistogram, |
114 ("Blink.RestoredCachedStyleSheet", 2)); | 122 ("Blink.RestoredCachedStyleSheet", 2)); |
115 DEFINE_STATIC_LOCAL( | 123 DEFINE_STATIC_LOCAL( |
116 EnumerationHistogram, restoredCachedStyleSheet2Histogram, | 124 EnumerationHistogram, restoredCachedStyleSheet2Histogram, |
117 ("Blink.RestoredCachedStyleSheet2", StyleSheetCacheStatusCount)); | 125 ("Blink.RestoredCachedStyleSheet2", StyleSheetCacheStatusCount)); |
118 | 126 |
119 if (StyleSheetContents* restoredSheet = | 127 if (StyleSheetContents* restoredSheet = |
120 const_cast<CSSStyleSheetResource*>(cachedStyleSheet) | 128 const_cast<CSSStyleSheetResource*>(cachedStyleSheet) |
121 ->restoreParsedStyleSheet(parserContext)) { | 129 ->restoreParsedStyleSheet(parserContext)) { |
122 DCHECK(restoredSheet->isCacheableForResource()); | 130 DCHECK(restoredSheet->isCacheableForResource()); |
123 DCHECK(!restoredSheet->isLoading()); | 131 DCHECK(!restoredSheet->isLoading()); |
124 | 132 |
125 if (m_sheet) | 133 if (m_sheet) |
126 clearSheet(); | 134 clearSheet(); |
127 m_sheet = CSSStyleSheet::create(restoredSheet, *m_owner); | 135 m_sheet = CSSStyleSheet::create(restoredSheet, *m_owner); |
128 m_sheet->setMediaQueries(MediaQuerySet::create(m_owner->media())); | 136 m_sheet->setMediaQueries(MediaQuerySet::create(m_owner->media())); |
129 if (m_owner->isInDocumentTree()) | 137 if (m_owner->isInDocumentTree()) |
130 setSheetTitle(m_owner->title()); | 138 setSheetTitle(m_owner->title()); |
131 setCrossOriginStylesheetStatus(m_sheet.get()); | 139 setCrossOriginStylesheetStatus(); |
132 | 140 |
133 m_loading = false; | 141 m_loading = false; |
134 restoredSheet->checkLoaded(); | 142 restoredSheet->checkLoaded(); |
135 | 143 |
136 restoredCachedStyleSheetHistogram.count(true); | 144 restoredCachedStyleSheetHistogram.count(true); |
137 restoredCachedStyleSheet2Histogram.count(StyleSheetInMemoryCache); | 145 restoredCachedStyleSheet2Histogram.count(StyleSheetInMemoryCache); |
138 return; | 146 return; |
139 } | 147 } |
140 restoredCachedStyleSheetHistogram.count(false); | 148 restoredCachedStyleSheetHistogram.count(false); |
141 StyleSheetCacheStatus cacheStatus = cachedStyleSheet->response().wasCached() | 149 StyleSheetCacheStatus cacheStatus = cachedStyleSheet->response().wasCached() |
142 ? StyleSheetInDiskCache | 150 ? StyleSheetInDiskCache |
143 : StyleSheetNewEntry; | 151 : StyleSheetNewEntry; |
144 restoredCachedStyleSheet2Histogram.count(cacheStatus); | 152 restoredCachedStyleSheet2Histogram.count(cacheStatus); |
145 | 153 |
146 StyleSheetContents* styleSheet = | 154 StyleSheetContents* styleSheet = |
147 StyleSheetContents::create(href, parserContext); | 155 StyleSheetContents::create(href, parserContext); |
148 | 156 |
149 if (m_sheet) | 157 if (m_sheet) |
150 clearSheet(); | 158 clearSheet(); |
151 | 159 |
152 m_sheet = CSSStyleSheet::create(styleSheet, *m_owner); | 160 m_sheet = CSSStyleSheet::create(styleSheet, *m_owner); |
153 m_sheet->setMediaQueries(MediaQuerySet::create(m_owner->media())); | 161 m_sheet->setMediaQueries(MediaQuerySet::create(m_owner->media())); |
154 if (m_owner->isInDocumentTree()) | 162 if (m_owner->isInDocumentTree()) |
155 setSheetTitle(m_owner->title()); | 163 setSheetTitle(m_owner->title()); |
156 setCrossOriginStylesheetStatus(m_sheet.get()); | 164 setCrossOriginStylesheetStatus(); |
157 | 165 |
158 styleSheet->parseAuthorStyleSheet(cachedStyleSheet, | 166 styleSheet->parseAuthorStyleSheet(cachedStyleSheet, |
159 m_owner->document().getSecurityOrigin()); | 167 document().getSecurityOrigin()); |
160 | 168 |
161 m_loading = false; | 169 m_loading = false; |
162 styleSheet->notifyLoadedSheet(cachedStyleSheet); | 170 styleSheet->notifyLoadedSheet(cachedStyleSheet); |
163 styleSheet->checkLoaded(); | 171 styleSheet->checkLoaded(); |
164 | 172 |
165 if (styleSheet->isCacheableForResource()) { | 173 if (styleSheet->isCacheableForResource()) { |
166 const_cast<CSSStyleSheetResource*>(cachedStyleSheet) | 174 const_cast<CSSStyleSheetResource*>(cachedStyleSheet) |
167 ->saveParsedStyleSheet(styleSheet); | 175 ->saveParsedStyleSheet(styleSheet); |
168 } | 176 } |
169 clearResource(); | 177 clearResource(); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 return m_sheet->contents()->isLoading(); | 214 return m_sheet->contents()->isLoading(); |
207 } | 215 } |
208 | 216 |
209 void LinkStyle::addPendingSheet(PendingSheetType type) { | 217 void LinkStyle::addPendingSheet(PendingSheetType type) { |
210 if (type <= m_pendingSheetType) | 218 if (type <= m_pendingSheetType) |
211 return; | 219 return; |
212 m_pendingSheetType = type; | 220 m_pendingSheetType = type; |
213 | 221 |
214 if (m_pendingSheetType == NonBlocking) | 222 if (m_pendingSheetType == NonBlocking) |
215 return; | 223 return; |
216 m_owner->document().styleEngine().addPendingSheet(m_styleEngineContext); | 224 document().styleEngine().addPendingSheet(m_styleEngineContext); |
217 } | 225 } |
218 | 226 |
219 void LinkStyle::removePendingSheet() { | 227 void LinkStyle::removePendingSheet() { |
220 DCHECK(m_owner); | 228 DCHECK(m_owner); |
221 PendingSheetType type = m_pendingSheetType; | 229 PendingSheetType type = m_pendingSheetType; |
222 m_pendingSheetType = None; | 230 m_pendingSheetType = None; |
223 | 231 |
224 if (type == None) | 232 if (type == None) |
225 return; | 233 return; |
226 if (type == NonBlocking) { | 234 if (type == NonBlocking) { |
227 // Tell StyleEngine to re-compute styleSheets of this m_owner's treescope. | 235 // Tell StyleEngine to re-compute styleSheets of this m_owner's treescope. |
228 m_owner->document().styleEngine().modifiedStyleSheetCandidateNode(*m_owner); | 236 document().styleEngine().modifiedStyleSheetCandidateNode(*m_owner); |
229 return; | 237 return; |
230 } | 238 } |
231 | 239 |
232 m_owner->document().styleEngine().removePendingSheet(*m_owner, | 240 document().styleEngine().removePendingSheet(*m_owner, m_styleEngineContext); |
233 m_styleEngineContext); | |
234 } | 241 } |
235 | 242 |
236 void LinkStyle::setDisabledState(bool disabled) { | 243 void LinkStyle::setDisabledState(bool disabled) { |
237 LinkStyle::DisabledState oldDisabledState = m_disabledState; | 244 LinkStyle::DisabledState oldDisabledState = m_disabledState; |
238 m_disabledState = disabled ? Disabled : EnabledViaScript; | 245 m_disabledState = disabled ? Disabled : EnabledViaScript; |
239 if (oldDisabledState != m_disabledState) { | 246 if (oldDisabledState == m_disabledState) |
240 // If we change the disabled state while the sheet is still loading, then we | 247 return; |
241 // have to perform three checks: | |
242 if (styleSheetIsLoading()) { | |
243 // Check #1: The sheet becomes disabled while loading. | |
244 if (m_disabledState == Disabled) | |
245 removePendingSheet(); | |
246 | 248 |
247 // Check #2: An alternate sheet becomes enabled while it is still loading. | 249 // If we change the disabled state while the sheet is still loading, then we |
248 if (m_owner->relAttribute().isAlternate() && | 250 // have to perform three checks: |
249 m_disabledState == EnabledViaScript) | 251 if (styleSheetIsLoading()) { |
250 addPendingSheet(Blocking); | 252 // Check #1: The sheet becomes disabled while loading. |
| 253 if (m_disabledState == Disabled) |
| 254 removePendingSheet(); |
251 | 255 |
252 // Check #3: A main sheet becomes enabled while it was still loading and | 256 // Check #2: An alternate sheet becomes enabled while it is still loading. |
253 // after it was disabled via script. It takes really terrible code to make | 257 if (m_owner->relAttribute().isAlternate() && |
254 // this happen (a double toggle for no reason essentially). This happens | 258 m_disabledState == EnabledViaScript) |
255 // on virtualplastic.net, which manages to do about 12 enable/disables on | 259 addPendingSheet(Blocking); |
256 // only 3 sheets. :) | |
257 if (!m_owner->relAttribute().isAlternate() && | |
258 m_disabledState == EnabledViaScript && oldDisabledState == Disabled) | |
259 addPendingSheet(Blocking); | |
260 | 260 |
261 // If the sheet is already loading just bail. | 261 // Check #3: A main sheet becomes enabled while it was still loading and |
262 return; | 262 // after it was disabled via script. It takes really terrible code to make |
263 } | 263 // this happen (a double toggle for no reason essentially). This happens |
| 264 // on virtualplastic.net, which manages to do about 12 enable/disables on |
| 265 // only 3 sheets. :) |
| 266 if (!m_owner->relAttribute().isAlternate() && |
| 267 m_disabledState == EnabledViaScript && oldDisabledState == Disabled) |
| 268 addPendingSheet(Blocking); |
264 | 269 |
265 if (m_sheet) { | 270 // If the sheet is already loading just bail. |
266 m_sheet->setDisabled(disabled); | 271 return; |
267 return; | 272 } |
268 } | |
269 | 273 |
270 if (m_disabledState == EnabledViaScript && m_owner->shouldProcessStyle()) | 274 if (m_sheet) { |
271 process(); | 275 m_sheet->setDisabled(disabled); |
| 276 return; |
272 } | 277 } |
| 278 |
| 279 if (m_disabledState == EnabledViaScript && m_owner->shouldProcessStyle()) |
| 280 process(); |
273 } | 281 } |
274 | 282 |
275 void LinkStyle::setCrossOriginStylesheetStatus(CSSStyleSheet* sheet) { | 283 void LinkStyle::setCrossOriginStylesheetStatus() { |
276 if (m_fetchFollowingCORS && resource() && !resource()->errorOccurred()) { | 284 if (m_fetchFollowingCORS && resource() && !resource()->errorOccurred()) { |
277 // Record the security origin the CORS access check succeeded at, if cross | 285 // Record the security origin the CORS access check succeeded at, if cross |
278 // origin. Only origins that are script accessible to it may access the | 286 // origin. Only origins that are script accessible to it may access the |
279 // stylesheet's rules. | 287 // stylesheet's rules. |
280 sheet->setAllowRuleAccessFromOrigin( | 288 m_sheet->setAllowRuleAccessFromOrigin(document().getSecurityOrigin()); |
281 m_owner->document().getSecurityOrigin()); | |
282 } | 289 } |
283 m_fetchFollowingCORS = false; | 290 m_fetchFollowingCORS = false; |
284 } | 291 } |
285 | 292 |
| 293 bool LinkStyle::shouldLoadResource() const { |
| 294 return document().frame() || document().importsController(); |
| 295 } |
| 296 |
286 // TODO(yoav): move that logic to LinkLoader | 297 // TODO(yoav): move that logic to LinkLoader |
287 LinkStyle::LoadReturnValue LinkStyle::loadStylesheetIfNeeded( | 298 void LinkStyle::loadStylesheetIfNeeded(const String& type) { |
288 const LinkRequestBuilder& builder, | 299 const KURL& href = m_owner->getNonEmptyURLAttribute(hrefAttr); |
289 const String& type) { | 300 |
290 if (m_disabledState == Disabled || !m_owner->relAttribute().isStyleSheet() || | 301 if (m_disabledState == Disabled || !m_owner->relAttribute().isStyleSheet() || |
291 !styleSheetTypeIsSupported(type) || !shouldLoadResource() || | 302 !styleSheetTypeIsSupported(type) || !shouldLoadResource() || |
292 !builder.url().isValid()) | 303 !href.isValid()) { |
293 return NotNeeded; | 304 if (!m_sheet) |
| 305 return; |
| 306 |
| 307 // we no longer contain a stylesheet, e.g. perhaps rel or type was changed |
| 308 StyleSheet* removedSheet = m_sheet.get(); |
| 309 clearSheet(); |
| 310 document().styleEngine().setNeedsActiveStyleUpdate(removedSheet, |
| 311 FullStyleUpdate); |
| 312 return; |
| 313 } |
294 | 314 |
295 if (resource()) { | 315 if (resource()) { |
296 removePendingSheet(); | 316 removePendingSheet(); |
297 clearResource(); | 317 clearResource(); |
298 clearFetchFollowingCORS(); | 318 m_fetchFollowingCORS = false; |
299 } | 319 } |
300 | 320 |
301 if (!m_owner->shouldLoadLink()) | 321 if (m_owner->shouldLoadLink()) |
302 return Bail; | 322 loadStylesheet(); |
| 323 } |
303 | 324 |
| 325 LocalFrame* LinkStyle::loadingFrame() const { |
| 326 HTMLImportsController* importsController = document().importsController(); |
| 327 if (!importsController) |
| 328 return document().frame(); |
| 329 return importsController->master()->frame(); |
| 330 } |
| 331 |
| 332 void LinkStyle::loadStylesheet() { |
304 m_loading = true; | 333 m_loading = true; |
305 | 334 |
306 String title = m_owner->title(); | 335 String title = m_owner->title(); |
307 if (!title.isEmpty() && !m_owner->isAlternate() && | 336 if (!title.isEmpty() && !m_owner->isAlternate() && |
308 m_disabledState != EnabledViaScript && m_owner->isInDocumentTree()) { | 337 m_disabledState != EnabledViaScript && m_owner->isInDocumentTree()) { |
309 document().styleEngine().setPreferredStylesheetSetNameIfNotSet( | 338 document().styleEngine().setPreferredStylesheetSetNameIfNotSet( |
310 title, StyleEngine::DontUpdateActiveSheets); | 339 title, StyleEngine::DontUpdateActiveSheets); |
311 } | 340 } |
312 | 341 |
313 bool mediaQueryMatches = true; | 342 bool mediaQueryMatches = true; |
314 LocalFrame* frame = loadingFrame(); | 343 LocalFrame* frame = loadingFrame(); |
315 if (!m_owner->media().isEmpty() && frame) { | 344 if (!m_owner->media().isEmpty() && frame) { |
316 MediaQuerySet* media = MediaQuerySet::create(m_owner->media()); | 345 MediaQuerySet* media = MediaQuerySet::create(m_owner->media()); |
317 MediaQueryEvaluator evaluator(frame); | 346 MediaQueryEvaluator evaluator(frame); |
318 mediaQueryMatches = evaluator.eval(media); | 347 mediaQueryMatches = evaluator.eval(media); |
319 } | 348 } |
320 | 349 |
321 // Don't hold up layout tree construction and script execution on | 350 // Don't hold up layout tree construction and script execution on |
322 // stylesheets that are not needed for the layout at the moment. | 351 // stylesheets that are not needed for the layout at the moment. |
323 bool blocking = mediaQueryMatches && !m_owner->isAlternate() && | 352 bool blocking = mediaQueryMatches && !m_owner->isAlternate() && |
324 m_owner->isCreatedByParser(); | 353 m_owner->isCreatedByParser(); |
325 addPendingSheet(blocking ? Blocking : NonBlocking); | 354 addPendingSheet(blocking ? Blocking : NonBlocking); |
326 | 355 |
| 356 FetchRequest request = m_owner->createFetchRequest(); |
| 357 |
327 // Load stylesheets that are not needed for the layout immediately with low | 358 // Load stylesheets that are not needed for the layout immediately with low |
328 // priority. When the link element is created by scripts, load the | 359 // priority. When the link element is created by scripts, load the |
329 // stylesheets asynchronously but in high priority. | 360 // stylesheets asynchronously but in high priority. |
330 bool lowPriority = !mediaQueryMatches || m_owner->isAlternate(); | 361 if (!mediaQueryMatches || m_owner->isAlternate()) |
331 FetchRequest request = builder.build(lowPriority); | 362 request.setDefer(FetchRequest::LazyLoad); |
| 363 |
332 CrossOriginAttributeValue crossOrigin = crossOriginAttributeValue( | 364 CrossOriginAttributeValue crossOrigin = crossOriginAttributeValue( |
333 m_owner->fastGetAttribute(HTMLNames::crossoriginAttr)); | 365 m_owner->fastGetAttribute(HTMLNames::crossoriginAttr)); |
334 if (crossOrigin != CrossOriginAttributeNotSet) { | 366 if (crossOrigin != CrossOriginAttributeNotSet) { |
335 request.setCrossOriginAccessControl(document().getSecurityOrigin(), | 367 request.setCrossOriginAccessControl(document().getSecurityOrigin(), |
336 crossOrigin); | 368 crossOrigin); |
337 setFetchFollowingCORS(); | 369 DCHECK(!m_fetchFollowingCORS); |
| 370 m_fetchFollowingCORS = true; |
338 } | 371 } |
339 | 372 |
340 String integrityAttr = m_owner->fastGetAttribute(HTMLNames::integrityAttr); | 373 String integrityAttr = m_owner->fastGetAttribute(HTMLNames::integrityAttr); |
341 if (!integrityAttr.isEmpty()) { | 374 if (!integrityAttr.isEmpty()) { |
342 IntegrityMetadataSet metadataSet; | 375 IntegrityMetadataSet metadataSet; |
343 SubresourceIntegrity::parseIntegrityAttribute(integrityAttr, metadataSet); | 376 SubresourceIntegrity::parseIntegrityAttribute(integrityAttr, metadataSet); |
344 request.setIntegrityMetadata(metadataSet); | 377 request.setIntegrityMetadata(metadataSet); |
345 } | 378 } |
346 setResource(CSSStyleSheetResource::fetch(request, document().fetcher())); | 379 setResource(CSSStyleSheetResource::fetch(request, document().fetcher())); |
347 | 380 |
348 if (m_loading && !resource()) { | 381 if (!m_loading || resource()) |
349 // The request may have been denied if (for example) the stylesheet is | 382 return; |
350 // local and the document is remote, or if there was a Content Security | 383 |
351 // Policy Failure. setCSSStyleSheet() can be called synchronuosly in | 384 // The request may have been denied if (for example) the stylesheet is |
352 // setResource() and thus resource() is null and |m_loading| is false in | 385 // local and the document is remote, or if there was a Content Security |
353 // such cases even if the request succeeds. | 386 // Policy Failure. setCSSStyleSheet() can be called synchronuosly in |
354 m_loading = false; | 387 // setResource() and thus resource() is null and |m_loading| is false in |
355 removePendingSheet(); | 388 // such cases even if the request succeeds. |
356 notifyLoadedSheetAndAllCriticalSubresources( | 389 m_loading = false; |
357 Node::ErrorOccurredLoadingSubresource); | 390 removePendingSheet(); |
358 } | 391 notifyLoadedSheetAndAllCriticalSubresources( |
359 return Loaded; | 392 Node::ErrorOccurredLoadingSubresource); |
360 } | 393 } |
361 | 394 |
362 void LinkStyle::process() { | 395 void LinkStyle::process() { |
363 DCHECK(m_owner->shouldProcessStyle()); | 396 DCHECK(m_owner->shouldProcessStyle()); |
| 397 |
364 String type = m_owner->typeValue().lower(); | 398 String type = m_owner->typeValue().lower(); |
365 String as = m_owner->asValue().lower(); | 399 String as = m_owner->asValue().lower(); |
366 String media = m_owner->media().lower(); | 400 String media = m_owner->media().lower(); |
367 LinkRequestBuilder builder(m_owner); | |
368 | 401 |
369 if (m_owner->relAttribute().getIconType() != InvalidIcon && | 402 const KURL& href = m_owner->getNonEmptyURLAttribute(hrefAttr); |
370 builder.url().isValid() && !builder.url().isEmpty()) { | 403 |
| 404 if (m_owner->relAttribute().getIconType() != InvalidIcon && href.isValid() && |
| 405 !href.isEmpty()) { |
371 if (!m_owner->shouldLoadLink()) | 406 if (!m_owner->shouldLoadLink()) |
372 return; | 407 return; |
373 if (!document().getSecurityOrigin()->canDisplay(builder.url())) | 408 if (!document().getSecurityOrigin()->canDisplay(href)) |
374 return; | 409 return; |
375 if (!document().contentSecurityPolicy()->allowImageFromSource( | 410 if (!document().contentSecurityPolicy()->allowImageFromSource(href)) |
376 builder.url())) | |
377 return; | 411 return; |
378 if (document().frame() && document().frame()->loader().client()) { | 412 if (document().frame() && document().frame()->loader().client()) { |
379 document().frame()->loader().client()->dispatchDidChangeIcons( | 413 document().frame()->loader().client()->dispatchDidChangeIcons( |
380 m_owner->relAttribute().getIconType()); | 414 m_owner->relAttribute().getIconType()); |
381 } | 415 } |
382 } | 416 } |
383 | 417 |
384 if (!m_owner->loadLink(type, as, media, m_owner->referrerPolicy(), | 418 if (m_owner->loadLink(type, as, media, m_owner->referrerPolicy(), href)) |
385 builder.url())) | 419 loadStylesheetIfNeeded(type); |
386 return; | |
387 | |
388 if (loadStylesheetIfNeeded(builder, type) == NotNeeded && m_sheet) { | |
389 // we no longer contain a stylesheet, e.g. perhaps rel or type was changed | |
390 StyleSheet* removedSheet = m_sheet.get(); | |
391 clearSheet(); | |
392 document().styleEngine().setNeedsActiveStyleUpdate(removedSheet, | |
393 FullStyleUpdate); | |
394 } | |
395 } | 420 } |
396 | 421 |
397 void LinkStyle::setSheetTitle( | 422 void LinkStyle::setSheetTitle( |
398 const String& title, | 423 const String& title, |
399 StyleEngine::ActiveSheetsUpdate updateActiveSheets) { | 424 StyleEngine::ActiveSheetsUpdate updateActiveSheets) { |
400 if (!m_owner->isInDocumentTree() || !m_owner->relAttribute().isStyleSheet()) | 425 if (!m_owner->isInDocumentTree() || !m_owner->relAttribute().isStyleSheet()) |
401 return; | 426 return; |
402 | 427 |
403 if (m_sheet) | 428 if (m_sheet) |
404 m_sheet->setTitle(title); | 429 m_sheet->setTitle(title); |
405 | 430 |
406 if (title.isEmpty() || !isUnset() || m_owner->isAlternate()) | 431 if (title.isEmpty() || !isUnset() || m_owner->isAlternate()) |
407 return; | 432 return; |
408 | 433 |
409 KURL href = m_owner->getNonEmptyURLAttribute(hrefAttr); | 434 const KURL& href = m_owner->getNonEmptyURLAttribute(hrefAttr); |
410 if (href.isValid() && !href.isEmpty()) { | 435 if (href.isValid() && !href.isEmpty()) { |
411 document().styleEngine().setPreferredStylesheetSetNameIfNotSet( | 436 document().styleEngine().setPreferredStylesheetSetNameIfNotSet( |
412 title, updateActiveSheets); | 437 title, updateActiveSheets); |
413 } | 438 } |
414 } | 439 } |
415 | 440 |
416 void LinkStyle::ownerRemoved() { | 441 void LinkStyle::ownerRemoved() { |
417 if (m_sheet) | 442 if (m_sheet) |
418 clearSheet(); | 443 clearSheet(); |
419 | 444 |
420 if (styleSheetIsLoading()) | 445 if (styleSheetIsLoading()) |
421 removePendingSheet(); | 446 removePendingSheet(); |
422 } | 447 } |
423 | 448 |
424 DEFINE_TRACE(LinkStyle) { | 449 DEFINE_TRACE(LinkStyle) { |
425 visitor->trace(m_sheet); | 450 visitor->trace(m_sheet); |
426 LinkResource::trace(visitor); | 451 LinkResource::trace(visitor); |
427 ResourceOwner<StyleSheetResource>::trace(visitor); | 452 ResourceOwner<StyleSheetResource>::trace(visitor); |
428 } | 453 } |
429 | 454 |
430 } // namespace blink | 455 } // namespace blink |
OLD | NEW |