| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2011 Google Inc. All rights reserved. | 2 * Copyright (C) 2011 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 * | 29 * |
| 30 */ | 30 */ |
| 31 | 31 |
| 32 #include "core/loader/LinkLoader.h" | 32 #include "core/loader/LinkLoader.h" |
| 33 | 33 |
| 34 #include "core/css/MediaList.h" | 34 #include "core/css/MediaList.h" |
| 35 #include "core/css/MediaQueryEvaluator.h" | 35 #include "core/css/MediaQueryEvaluator.h" |
| 36 #include "core/dom/Document.h" | 36 #include "core/dom/Document.h" |
| 37 #include "core/frame/FrameConsole.h" |
| 38 #include "core/frame/LocalFrame.h" |
| 37 #include "core/frame/Settings.h" | 39 #include "core/frame/Settings.h" |
| 38 #include "core/frame/UseCounter.h" | 40 #include "core/frame/UseCounter.h" |
| 39 #include "core/html/CrossOriginAttribute.h" | 41 #include "core/html/CrossOriginAttribute.h" |
| 40 #include "core/html/LinkRelAttribute.h" | 42 #include "core/html/LinkRelAttribute.h" |
| 41 #include "core/html/parser/HTMLPreloadScanner.h" | 43 #include "core/html/parser/HTMLPreloadScanner.h" |
| 42 #include "core/inspector/ConsoleMessage.h" | 44 #include "core/inspector/ConsoleMessage.h" |
| 43 #include "core/loader/DocumentLoader.h" | 45 #include "core/loader/DocumentLoader.h" |
| 44 #include "core/loader/NetworkHintsInterface.h" | 46 #include "core/loader/NetworkHintsInterface.h" |
| 45 #include "core/loader/private/PrerenderHandle.h" | 47 #include "core/loader/private/PrerenderHandle.h" |
| 46 #include "core/loader/resource/LinkFetchResource.h" | 48 #include "core/loader/resource/LinkFetchResource.h" |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 | 123 |
| 122 void LinkLoader::DidSendDOMContentLoadedForPrerender() { | 124 void LinkLoader::DidSendDOMContentLoadedForPrerender() { |
| 123 client_->DidSendDOMContentLoadedForLinkPrerender(); | 125 client_->DidSendDOMContentLoadedForLinkPrerender(); |
| 124 } | 126 } |
| 125 | 127 |
| 126 enum LinkCaller { | 128 enum LinkCaller { |
| 127 kLinkCalledFromHeader, | 129 kLinkCalledFromHeader, |
| 128 kLinkCalledFromMarkup, | 130 kLinkCalledFromMarkup, |
| 129 }; | 131 }; |
| 130 | 132 |
| 133 static void SendMessageToConsoleForPossiblyNullDocument( |
| 134 ConsoleMessage* console_message, |
| 135 Document* document, |
| 136 LocalFrame* frame) { |
| 137 DCHECK(document || frame); |
| 138 DCHECK(!document || document->GetFrame() == frame); |
| 139 // Route the console message through Document if possible, so that script line |
| 140 // numbers can be included. Otherwise, route directly to the FrameConsole, to |
| 141 // ensure we never drop a message. |
| 142 if (document) |
| 143 document->AddConsoleMessage(console_message); |
| 144 else |
| 145 frame->Console().AddMessage(console_message); |
| 146 } |
| 147 |
| 131 static void DnsPrefetchIfNeeded( | 148 static void DnsPrefetchIfNeeded( |
| 132 const LinkRelAttribute& rel_attribute, | 149 const LinkRelAttribute& rel_attribute, |
| 133 const KURL& href, | 150 const KURL& href, |
| 134 Document& document, | 151 Document* document, |
| 152 LocalFrame* frame, |
| 135 const NetworkHintsInterface& network_hints_interface, | 153 const NetworkHintsInterface& network_hints_interface, |
| 136 LinkCaller caller) { | 154 LinkCaller caller) { |
| 137 if (rel_attribute.IsDNSPrefetch()) { | 155 if (rel_attribute.IsDNSPrefetch()) { |
| 138 UseCounter::Count(document, UseCounter::kLinkRelDnsPrefetch); | 156 UseCounter::Count(frame, UseCounter::kLinkRelDnsPrefetch); |
| 139 if (caller == kLinkCalledFromHeader) | 157 if (caller == kLinkCalledFromHeader) |
| 140 UseCounter::Count(document, UseCounter::kLinkHeaderDnsPrefetch); | 158 UseCounter::Count(frame, UseCounter::kLinkHeaderDnsPrefetch); |
| 141 Settings* settings = document.GetSettings(); | 159 Settings* settings = frame ? frame->GetSettings() : nullptr; |
| 142 // FIXME: The href attribute of the link element can be in "//hostname" | 160 // FIXME: The href attribute of the link element can be in "//hostname" |
| 143 // form, and we shouldn't attempt to complete that as URL | 161 // form, and we shouldn't attempt to complete that as URL |
| 144 // <https://bugs.webkit.org/show_bug.cgi?id=48857>. | 162 // <https://bugs.webkit.org/show_bug.cgi?id=48857>. |
| 145 if (settings && settings->GetDNSPrefetchingEnabled() && href.IsValid() && | 163 if (settings && settings->GetDNSPrefetchingEnabled() && href.IsValid() && |
| 146 !href.IsEmpty()) { | 164 !href.IsEmpty()) { |
| 147 if (settings->GetLogDnsPrefetchAndPreconnect()) { | 165 if (settings->GetLogDnsPrefetchAndPreconnect()) { |
| 148 document.AddConsoleMessage(ConsoleMessage::Create( | 166 SendMessageToConsoleForPossiblyNullDocument( |
| 149 kOtherMessageSource, kVerboseMessageLevel, | 167 ConsoleMessage::Create( |
| 150 String("DNS prefetch triggered for " + href.Host()))); | 168 kOtherMessageSource, kVerboseMessageLevel, |
| 169 String("DNS prefetch triggered for " + href.Host())), |
| 170 document, frame); |
| 151 } | 171 } |
| 152 network_hints_interface.DnsPrefetchHost(href.Host()); | 172 network_hints_interface.DnsPrefetchHost(href.Host()); |
| 153 } | 173 } |
| 154 } | 174 } |
| 155 } | 175 } |
| 156 | 176 |
| 157 static void PreconnectIfNeeded( | 177 static void PreconnectIfNeeded( |
| 158 const LinkRelAttribute& rel_attribute, | 178 const LinkRelAttribute& rel_attribute, |
| 159 const KURL& href, | 179 const KURL& href, |
| 160 Document& document, | 180 Document* document, |
| 181 LocalFrame* frame, |
| 161 const CrossOriginAttributeValue cross_origin, | 182 const CrossOriginAttributeValue cross_origin, |
| 162 const NetworkHintsInterface& network_hints_interface, | 183 const NetworkHintsInterface& network_hints_interface, |
| 163 LinkCaller caller) { | 184 LinkCaller caller) { |
| 164 if (rel_attribute.IsPreconnect() && href.IsValid() && | 185 if (rel_attribute.IsPreconnect() && href.IsValid() && |
| 165 href.ProtocolIsInHTTPFamily()) { | 186 href.ProtocolIsInHTTPFamily()) { |
| 166 UseCounter::Count(document, UseCounter::kLinkRelPreconnect); | 187 UseCounter::Count(frame, UseCounter::kLinkRelPreconnect); |
| 167 if (caller == kLinkCalledFromHeader) | 188 if (caller == kLinkCalledFromHeader) |
| 168 UseCounter::Count(document, UseCounter::kLinkHeaderPreconnect); | 189 UseCounter::Count(frame, UseCounter::kLinkHeaderPreconnect); |
| 169 Settings* settings = document.GetSettings(); | 190 Settings* settings = frame ? frame->GetSettings() : nullptr; |
| 170 if (settings && settings->GetLogDnsPrefetchAndPreconnect()) { | 191 if (settings && settings->GetLogDnsPrefetchAndPreconnect()) { |
| 171 document.AddConsoleMessage(ConsoleMessage::Create( | 192 SendMessageToConsoleForPossiblyNullDocument( |
| 172 kOtherMessageSource, kVerboseMessageLevel, | 193 ConsoleMessage::Create( |
| 173 String("Preconnect triggered for ") + href.GetString())); | 194 kOtherMessageSource, kVerboseMessageLevel, |
| 195 String("Preconnect triggered for ") + href.GetString()), |
| 196 document, frame); |
| 174 if (cross_origin != kCrossOriginAttributeNotSet) { | 197 if (cross_origin != kCrossOriginAttributeNotSet) { |
| 175 document.AddConsoleMessage(ConsoleMessage::Create( | 198 SendMessageToConsoleForPossiblyNullDocument( |
| 176 kOtherMessageSource, kVerboseMessageLevel, | 199 ConsoleMessage::Create( |
| 177 String("Preconnect CORS setting is ") + | 200 kOtherMessageSource, kVerboseMessageLevel, |
| 178 String((cross_origin == kCrossOriginAttributeAnonymous) | 201 String("Preconnect CORS setting is ") + |
| 179 ? "anonymous" | 202 String((cross_origin == kCrossOriginAttributeAnonymous) |
| 180 : "use-credentials"))); | 203 ? "anonymous" |
| 204 : "use-credentials")), |
| 205 document, frame); |
| 181 } | 206 } |
| 182 } | 207 } |
| 183 network_hints_interface.PreconnectHost(href, cross_origin); | 208 network_hints_interface.PreconnectHost(href, cross_origin); |
| 184 } | 209 } |
| 185 } | 210 } |
| 186 | 211 |
| 187 WTF::Optional<Resource::Type> LinkLoader::GetResourceTypeFromAsAttribute( | 212 WTF::Optional<Resource::Type> LinkLoader::GetResourceTypeFromAsAttribute( |
| 188 const String& as) { | 213 const String& as) { |
| 189 DCHECK_EQ(as.DeprecatedLower(), as); | 214 DCHECK_EQ(as.DeprecatedLower(), as); |
| 190 if (as == "image") { | 215 if (as == "image") { |
| (...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 373 } | 398 } |
| 374 return LinkFetchResource::Fetch(Resource::kLinkPrefetch, link_fetch_params, | 399 return LinkFetchResource::Fetch(Resource::kLinkPrefetch, link_fetch_params, |
| 375 document.Fetcher()); | 400 document.Fetcher()); |
| 376 } | 401 } |
| 377 return nullptr; | 402 return nullptr; |
| 378 } | 403 } |
| 379 | 404 |
| 380 void LinkLoader::LoadLinksFromHeader( | 405 void LinkLoader::LoadLinksFromHeader( |
| 381 const String& header_value, | 406 const String& header_value, |
| 382 const KURL& base_url, | 407 const KURL& base_url, |
| 408 LocalFrame& frame, |
| 383 Document* document, | 409 Document* document, |
| 384 const NetworkHintsInterface& network_hints_interface, | 410 const NetworkHintsInterface& network_hints_interface, |
| 385 CanLoadResources can_load_resources, | 411 CanLoadResources can_load_resources, |
| 386 MediaPreloadPolicy media_policy, | 412 MediaPreloadPolicy media_policy, |
| 387 ViewportDescriptionWrapper* viewport_description_wrapper) { | 413 ViewportDescriptionWrapper* viewport_description_wrapper) { |
| 388 if (!document || header_value.IsEmpty()) | 414 if (header_value.IsEmpty()) |
| 389 return; | 415 return; |
| 390 LinkHeaderSet header_set(header_value); | 416 LinkHeaderSet header_set(header_value); |
| 391 for (auto& header : header_set) { | 417 for (auto& header : header_set) { |
| 392 if (!header.Valid() || header.Url().IsEmpty() || header.Rel().IsEmpty()) | 418 if (!header.Valid() || header.Url().IsEmpty() || header.Rel().IsEmpty()) |
| 393 continue; | 419 continue; |
| 394 | 420 |
| 395 if (media_policy == kOnlyLoadMedia && header.Media().IsEmpty()) | 421 if (media_policy == kOnlyLoadMedia && header.Media().IsEmpty()) |
| 396 continue; | 422 continue; |
| 397 if (media_policy == kOnlyLoadNonMedia && !header.Media().IsEmpty()) | 423 if (media_policy == kOnlyLoadNonMedia && !header.Media().IsEmpty()) |
| 398 continue; | 424 continue; |
| 399 | 425 |
| 400 LinkRelAttribute rel_attribute(header.Rel()); | 426 LinkRelAttribute rel_attribute(header.Rel()); |
| 401 KURL url(base_url, header.Url()); | 427 KURL url(base_url, header.Url()); |
| 402 // Sanity check to avoid re-entrancy here. | 428 // Sanity check to avoid re-entrancy here. |
| 403 if (url == base_url) | 429 if (url == base_url) |
| 404 continue; | 430 continue; |
| 405 if (can_load_resources != kOnlyLoadResources) { | 431 if (can_load_resources != kOnlyLoadResources) { |
| 406 DnsPrefetchIfNeeded(rel_attribute, url, *document, | 432 DnsPrefetchIfNeeded(rel_attribute, url, document, &frame, |
| 407 network_hints_interface, kLinkCalledFromHeader); | 433 network_hints_interface, kLinkCalledFromHeader); |
| 408 | 434 |
| 409 PreconnectIfNeeded(rel_attribute, url, *document, | 435 PreconnectIfNeeded(rel_attribute, url, document, &frame, |
| 410 GetCrossOriginAttributeValue(header.CrossOrigin()), | 436 GetCrossOriginAttributeValue(header.CrossOrigin()), |
| 411 network_hints_interface, kLinkCalledFromHeader); | 437 network_hints_interface, kLinkCalledFromHeader); |
| 412 } | 438 } |
| 413 if (can_load_resources != kDoNotLoadResources) { | 439 if (can_load_resources != kDoNotLoadResources) { |
| 440 DCHECK(document); |
| 414 bool error_occurred = false; | 441 bool error_occurred = false; |
| 415 ViewportDescription* viewport_description = | 442 ViewportDescription* viewport_description = |
| 416 (viewport_description_wrapper && viewport_description_wrapper->set) | 443 (viewport_description_wrapper && viewport_description_wrapper->set) |
| 417 ? &(viewport_description_wrapper->description) | 444 ? &(viewport_description_wrapper->description) |
| 418 : nullptr; | 445 : nullptr; |
| 419 | 446 |
| 420 CrossOriginAttributeValue cross_origin = | 447 CrossOriginAttributeValue cross_origin = |
| 421 GetCrossOriginAttributeValue(header.CrossOrigin()); | 448 GetCrossOriginAttributeValue(header.CrossOrigin()); |
| 422 PreloadIfNeeded(rel_attribute, url, *document, header.As(), | 449 PreloadIfNeeded(rel_attribute, url, *document, header.As(), |
| 423 header.MimeType(), header.Media(), cross_origin, | 450 header.MimeType(), header.Media(), cross_origin, |
| 424 kLinkCalledFromHeader, error_occurred, | 451 kLinkCalledFromHeader, error_occurred, |
| 425 viewport_description, kReferrerPolicyDefault); | 452 viewport_description, kReferrerPolicyDefault); |
| 426 PrefetchIfNeeded(*document, url, rel_attribute, cross_origin, | 453 PrefetchIfNeeded(*document, url, rel_attribute, cross_origin, |
| 427 kReferrerPolicyDefault); | 454 kReferrerPolicyDefault); |
| 428 } | 455 } |
| 429 if (rel_attribute.IsServiceWorker()) { | 456 if (rel_attribute.IsServiceWorker()) { |
| 430 UseCounter::Count(*document, UseCounter::kLinkHeaderServiceWorker); | 457 UseCounter::Count(&frame, UseCounter::kLinkHeaderServiceWorker); |
| 431 } | 458 } |
| 432 // TODO(yoav): Add more supported headers as needed. | 459 // TODO(yoav): Add more supported headers as needed. |
| 433 } | 460 } |
| 434 } | 461 } |
| 435 | 462 |
| 436 bool LinkLoader::LoadLink( | 463 bool LinkLoader::LoadLink( |
| 437 const LinkRelAttribute& rel_attribute, | 464 const LinkRelAttribute& rel_attribute, |
| 438 CrossOriginAttributeValue cross_origin, | 465 CrossOriginAttributeValue cross_origin, |
| 439 const String& type, | 466 const String& type, |
| 440 const String& as, | 467 const String& as, |
| 441 const String& media, | 468 const String& media, |
| 442 ReferrerPolicy referrer_policy, | 469 ReferrerPolicy referrer_policy, |
| 443 const KURL& href, | 470 const KURL& href, |
| 444 Document& document, | 471 Document& document, |
| 445 const NetworkHintsInterface& network_hints_interface) { | 472 const NetworkHintsInterface& network_hints_interface) { |
| 446 if (!client_->ShouldLoadLink()) | 473 if (!client_->ShouldLoadLink()) |
| 447 return false; | 474 return false; |
| 448 | 475 |
| 449 DnsPrefetchIfNeeded(rel_attribute, href, document, network_hints_interface, | 476 DnsPrefetchIfNeeded(rel_attribute, href, &document, document.GetFrame(), |
| 450 kLinkCalledFromMarkup); | 477 network_hints_interface, kLinkCalledFromMarkup); |
| 451 | 478 |
| 452 PreconnectIfNeeded(rel_attribute, href, document, cross_origin, | 479 PreconnectIfNeeded(rel_attribute, href, &document, document.GetFrame(), |
| 453 network_hints_interface, kLinkCalledFromMarkup); | 480 cross_origin, network_hints_interface, |
| 481 kLinkCalledFromMarkup); |
| 454 | 482 |
| 455 bool error_occurred = false; | 483 bool error_occurred = false; |
| 456 CreateLinkPreloadResourceClient(PreloadIfNeeded( | 484 CreateLinkPreloadResourceClient(PreloadIfNeeded( |
| 457 rel_attribute, href, document, as, type, media, cross_origin, | 485 rel_attribute, href, document, as, type, media, cross_origin, |
| 458 kLinkCalledFromMarkup, error_occurred, nullptr, referrer_policy)); | 486 kLinkCalledFromMarkup, error_occurred, nullptr, referrer_policy)); |
| 459 if (error_occurred) | 487 if (error_occurred) |
| 460 link_loading_error_timer_.StartOneShot(0, BLINK_FROM_HERE); | 488 link_loading_error_timer_.StartOneShot(0, BLINK_FROM_HERE); |
| 461 | 489 |
| 462 if (href.IsEmpty() || !href.IsValid()) | 490 if (href.IsEmpty() || !href.IsValid()) |
| 463 Released(); | 491 Released(); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 498 | 526 |
| 499 DEFINE_TRACE(LinkLoader) { | 527 DEFINE_TRACE(LinkLoader) { |
| 500 visitor->Trace(client_); | 528 visitor->Trace(client_); |
| 501 visitor->Trace(prerender_); | 529 visitor->Trace(prerender_); |
| 502 visitor->Trace(link_preload_resource_client_); | 530 visitor->Trace(link_preload_resource_client_); |
| 503 ResourceOwner<Resource, ResourceClient>::Trace(visitor); | 531 ResourceOwner<Resource, ResourceClient>::Trace(visitor); |
| 504 PrerenderClient::Trace(visitor); | 532 PrerenderClient::Trace(visitor); |
| 505 } | 533 } |
| 506 | 534 |
| 507 } // namespace blink | 535 } // namespace blink |
| OLD | NEW |