OLD | NEW |
1 /* | 1 /* |
2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) | 2 Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de) |
3 Copyright (C) 2001 Dirk Mueller (mueller@kde.org) | 3 Copyright (C) 2001 Dirk Mueller (mueller@kde.org) |
4 Copyright (C) 2002 Waldo Bastian (bastian@kde.org) | 4 Copyright (C) 2002 Waldo Bastian (bastian@kde.org) |
5 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All | 5 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All |
6 rights reserved. | 6 rights reserved. |
7 Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ | 7 Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/ |
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 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
96 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, TextTrack) \ | 96 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, TextTrack) \ |
97 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, XSLStyleSheet) \ | 97 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, XSLStyleSheet) \ |
98 } | 98 } |
99 | 99 |
100 bool IsCrossOrigin(const KURL& a, const KURL& b) { | 100 bool IsCrossOrigin(const KURL& a, const KURL& b) { |
101 RefPtr<SecurityOrigin> originA = SecurityOrigin::create(a); | 101 RefPtr<SecurityOrigin> originA = SecurityOrigin::create(a); |
102 RefPtr<SecurityOrigin> originB = SecurityOrigin::create(b); | 102 RefPtr<SecurityOrigin> originB = SecurityOrigin::create(b); |
103 return !originB->isSameSchemeHostPort(originA.get()); | 103 return !originB->isSameSchemeHostPort(originA.get()); |
104 } | 104 } |
105 | 105 |
| 106 void addRedirectsToTimingInfo(Resource* resource, ResourceTimingInfo* info) { |
| 107 // Store redirect responses that were packed inside the final response. |
| 108 const auto& responses = resource->response().redirectResponses(); |
| 109 for (size_t i = 0; i < responses.size(); ++i) { |
| 110 const KURL& newURL = i + 1 < responses.size() |
| 111 ? KURL(responses[i + 1].url()) |
| 112 : resource->resourceRequest().url(); |
| 113 bool crossOrigin = IsCrossOrigin(responses[i].url(), newURL); |
| 114 info->addRedirect(responses[i], crossOrigin); |
| 115 } |
| 116 } |
| 117 |
106 } // namespace | 118 } // namespace |
107 | 119 |
108 static void RecordSriResourceIntegrityMismatchEvent( | 120 static void RecordSriResourceIntegrityMismatchEvent( |
109 SriResourceIntegrityMismatchEvent event) { | 121 SriResourceIntegrityMismatchEvent event) { |
110 DEFINE_THREAD_SAFE_STATIC_LOCAL( | 122 DEFINE_THREAD_SAFE_STATIC_LOCAL( |
111 EnumerationHistogram, integrityHistogram, | 123 EnumerationHistogram, integrityHistogram, |
112 new EnumerationHistogram("sri.resource_integrity_mismatch_event", | 124 new EnumerationHistogram("sri.resource_integrity_mismatch_event", |
113 SriResourceIntegrityMismatchEventCount)); | 125 SriResourceIntegrityMismatchEventCount)); |
114 integrityHistogram.count(event); | 126 integrityHistogram.count(event); |
115 } | 127 } |
(...skipping 474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
590 resource = createResourceForLoading(request, request.charset(), factory); | 602 resource = createResourceForLoading(request, request.charset(), factory); |
591 break; | 603 break; |
592 case Revalidate: | 604 case Revalidate: |
593 initializeRevalidation(request.mutableResourceRequest(), resource); | 605 initializeRevalidation(request.mutableResourceRequest(), resource); |
594 break; | 606 break; |
595 case Use: | 607 case Use: |
596 if (resource->isLinkPreload() && !request.isLinkPreload()) | 608 if (resource->isLinkPreload() && !request.isLinkPreload()) |
597 resource->setLinkPreload(false); | 609 resource->setLinkPreload(false); |
598 break; | 610 break; |
599 } | 611 } |
600 | |
601 if (!resource) | 612 if (!resource) |
602 return nullptr; | 613 return nullptr; |
603 if (resource->getType() != factory.type()) { | 614 if (resource->getType() != factory.type()) { |
604 DCHECK(request.forPreload()); | 615 DCHECK(request.forPreload()); |
605 return nullptr; | 616 return nullptr; |
606 } | 617 } |
607 | 618 |
608 if (!resource->isAlive()) | 619 if (!resource->isAlive()) |
609 m_deadStatsRecorder.update(policy); | 620 m_deadStatsRecorder.update(policy); |
610 | 621 |
(...skipping 23 matching lines...) Expand all Loading... |
634 | 645 |
635 // Returns with an existing resource if the resource does not need to start | 646 // Returns with an existing resource if the resource does not need to start |
636 // loading immediately. If revalidation policy was determined as |Revalidate|, | 647 // loading immediately. If revalidation policy was determined as |Revalidate|, |
637 // the resource was already initialized for the revalidation here, but won't | 648 // the resource was already initialized for the revalidation here, but won't |
638 // start loading. | 649 // start loading. |
639 if (!resourceNeedsLoad(resource, request, policy)) | 650 if (!resourceNeedsLoad(resource, request, policy)) |
640 return resource; | 651 return resource; |
641 | 652 |
642 if (!startLoad(resource)) | 653 if (!startLoad(resource)) |
643 return nullptr; | 654 return nullptr; |
644 | |
645 scopedResourceLoadTracker.resourceLoadContinuesBeyondScope(); | 655 scopedResourceLoadTracker.resourceLoadContinuesBeyondScope(); |
646 | 656 |
647 DCHECK(!resource->errorOccurred() || | 657 DCHECK(!resource->errorOccurred() || |
648 request.options().synchronousPolicy == RequestSynchronously); | 658 request.options().synchronousPolicy == RequestSynchronously); |
649 return resource; | 659 return resource; |
650 } | 660 } |
651 | 661 |
652 void ResourceFetcher::resourceTimingReportTimerFired(TimerBase* timer) { | 662 void ResourceFetcher::resourceTimingReportTimerFired(TimerBase* timer) { |
653 DCHECK_EQ(timer, &m_resourceTimingReportTimer); | 663 DCHECK_EQ(timer, &m_resourceTimingReportTimer); |
654 Vector<std::unique_ptr<ResourceTimingInfo>> timingReports; | 664 Vector<std::unique_ptr<ResourceTimingInfo>> timingReports; |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
750 | 760 |
751 // - Don't add main resource to cache to prevent reuse. | 761 // - Don't add main resource to cache to prevent reuse. |
752 // - Don't add the resource if its body will not be stored. | 762 // - Don't add the resource if its body will not be stored. |
753 if (factory.type() != Resource::MainResource && | 763 if (factory.type() != Resource::MainResource && |
754 request.options().dataBufferingPolicy != DoNotBufferData) { | 764 request.options().dataBufferingPolicy != DoNotBufferData) { |
755 memoryCache()->add(resource); | 765 memoryCache()->add(resource); |
756 } | 766 } |
757 return resource; | 767 return resource; |
758 } | 768 } |
759 | 769 |
760 void ResourceFetcher::storeResourceTimingInitiatorInformation( | 770 void ResourceFetcher::storePerformanceTimingInitiatorInformation( |
761 Resource* resource) { | 771 Resource* resource) { |
762 const AtomicString& fetchInitiator = resource->options().initiatorInfo.name; | 772 const AtomicString& fetchInitiator = resource->options().initiatorInfo.name; |
763 if (fetchInitiator == FetchInitiatorTypeNames::internal) | 773 if (fetchInitiator == FetchInitiatorTypeNames::internal) |
764 return; | 774 return; |
765 | 775 |
766 bool isMainResource = resource->getType() == Resource::MainResource; | 776 bool isMainResource = resource->getType() == Resource::MainResource; |
767 | 777 |
768 // The request can already be fetched in a previous navigation. Thus | 778 // The request can already be fetched in a previous navigation. Thus |
769 // startTime must be set accordingly. | 779 // startTime must be set accordingly. |
770 double startTime = resource->resourceRequest().navigationStartTime() | 780 double startTime = resource->resourceRequest().navigationStartTime() |
771 ? resource->resourceRequest().navigationStartTime() | 781 ? resource->resourceRequest().navigationStartTime() |
772 : monotonicallyIncreasingTime(); | 782 : monotonicallyIncreasingTime(); |
773 | 783 |
| 784 // This buffer is created and populated for providing transferSize |
| 785 // and redirect timing opt-in information. |
| 786 if (isMainResource) { |
| 787 DCHECK(!m_navigationTimingInfo); |
| 788 m_navigationTimingInfo = |
| 789 ResourceTimingInfo::create(fetchInitiator, startTime, isMainResource); |
| 790 } |
| 791 |
774 std::unique_ptr<ResourceTimingInfo> info = | 792 std::unique_ptr<ResourceTimingInfo> info = |
775 ResourceTimingInfo::create(fetchInitiator, startTime, isMainResource); | 793 ResourceTimingInfo::create(fetchInitiator, startTime, isMainResource); |
776 | 794 |
777 if (resource->isCacheValidator()) { | 795 if (resource->isCacheValidator()) { |
778 const AtomicString& timingAllowOrigin = | 796 const AtomicString& timingAllowOrigin = |
779 resource->response().httpHeaderField(HTTPNames::Timing_Allow_Origin); | 797 resource->response().httpHeaderField(HTTPNames::Timing_Allow_Origin); |
780 if (!timingAllowOrigin.isEmpty()) | 798 if (!timingAllowOrigin.isEmpty()) |
781 info->setOriginalTimingAllowOrigin(timingAllowOrigin); | 799 info->setOriginalTimingAllowOrigin(timingAllowOrigin); |
782 } | 800 } |
783 | 801 |
784 if (!isMainResource || | 802 if (!isMainResource || |
785 context().updateTimingInfoForIFrameNavigation(info.get())) | 803 context().updateTimingInfoForIFrameNavigation(info.get())) { |
786 m_resourceTimingInfoMap.add(resource, std::move(info)); | 804 m_resourceTimingInfoMap.add(resource, std::move(info)); |
| 805 } |
787 } | 806 } |
788 | 807 |
789 ResourceFetcher::RevalidationPolicy | 808 ResourceFetcher::RevalidationPolicy |
790 ResourceFetcher::determineRevalidationPolicy(Resource::Type type, | 809 ResourceFetcher::determineRevalidationPolicy(Resource::Type type, |
791 const FetchRequest& fetchRequest, | 810 const FetchRequest& fetchRequest, |
792 Resource* existingResource, | 811 Resource* existingResource, |
793 bool isStaticData) const { | 812 bool isStaticData) const { |
794 const ResourceRequest& request = fetchRequest.resourceRequest(); | 813 const ResourceRequest& request = fetchRequest.resourceRequest(); |
795 | 814 |
796 if (!existingResource) | 815 if (!existingResource) |
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1118 } | 1137 } |
1119 | 1138 |
1120 ArchiveResource* ResourceFetcher::createArchive(Resource* resource) { | 1139 ArchiveResource* ResourceFetcher::createArchive(Resource* resource) { |
1121 // Only the top-frame can load MHTML. | 1140 // Only the top-frame can load MHTML. |
1122 if (!context().isMainFrame()) | 1141 if (!context().isMainFrame()) |
1123 return nullptr; | 1142 return nullptr; |
1124 m_archive = MHTMLArchive::create(resource->url(), resource->resourceBuffer()); | 1143 m_archive = MHTMLArchive::create(resource->url(), resource->resourceBuffer()); |
1125 return m_archive ? m_archive->mainResource() : nullptr; | 1144 return m_archive ? m_archive->mainResource() : nullptr; |
1126 } | 1145 } |
1127 | 1146 |
| 1147 ResourceTimingInfo* ResourceFetcher::getNavigationTimingInfo() { |
| 1148 return m_navigationTimingInfo.get(); |
| 1149 } |
| 1150 |
1128 void ResourceFetcher::didFinishLoading(Resource* resource, | 1151 void ResourceFetcher::didFinishLoading(Resource* resource, |
1129 double finishTime, | 1152 double finishTime, |
1130 DidFinishLoadingReason finishReason) { | 1153 DidFinishLoadingReason finishReason) { |
1131 network_instrumentation::endResourceLoad( | 1154 network_instrumentation::endResourceLoad( |
1132 resource->identifier(), network_instrumentation::RequestOutcome::Success); | 1155 resource->identifier(), network_instrumentation::RequestOutcome::Success); |
1133 DCHECK(resource); | 1156 DCHECK(resource); |
1134 const int64_t encodedDataLength = resource->response().encodedDataLength(); | 1157 const int64_t encodedDataLength = resource->response().encodedDataLength(); |
1135 | 1158 |
1136 // When loading a multipart resource, make the loader non-block when finishing | 1159 // When loading a multipart resource, make the loader non-block when finishing |
1137 // loading the first part. | 1160 // loading the first part. |
1138 if (finishReason == DidFinishFirstPartInMultipart) | 1161 if (finishReason == DidFinishFirstPartInMultipart) |
1139 moveResourceLoaderToNonBlocking(resource->loader()); | 1162 moveResourceLoaderToNonBlocking(resource->loader()); |
1140 else | 1163 else |
1141 removeResourceLoader(resource->loader()); | 1164 removeResourceLoader(resource->loader()); |
1142 DCHECK(!m_loaders.contains(resource->loader())); | 1165 DCHECK(!m_loaders.contains(resource->loader())); |
1143 DCHECK(finishReason == DidFinishFirstPartInMultipart || | 1166 DCHECK(finishReason == DidFinishFirstPartInMultipart || |
1144 !m_nonBlockingLoaders.contains(resource->loader())); | 1167 !m_nonBlockingLoaders.contains(resource->loader())); |
1145 | 1168 |
| 1169 if (resource->getType() == Resource::MainResource) { |
| 1170 DCHECK(m_navigationTimingInfo); |
| 1171 // Store redirect responses that were packed inside the final response. |
| 1172 addRedirectsToTimingInfo(resource, m_navigationTimingInfo.get()); |
| 1173 if (resource->response().isHTTP()) { |
| 1174 m_navigationTimingInfo->addFinalTransferSize( |
| 1175 encodedDataLength == -1 ? 0 : encodedDataLength); |
| 1176 } |
| 1177 } |
1146 if (std::unique_ptr<ResourceTimingInfo> info = | 1178 if (std::unique_ptr<ResourceTimingInfo> info = |
1147 m_resourceTimingInfoMap.take(resource)) { | 1179 m_resourceTimingInfoMap.take(resource)) { |
1148 // Store redirect responses that were packed inside the final response. | 1180 // Store redirect responses that were packed inside the final response. |
1149 const Vector<ResourceResponse>& responses = | 1181 addRedirectsToTimingInfo(resource, info.get()); |
1150 resource->response().redirectResponses(); | |
1151 for (size_t i = 0; i < responses.size(); ++i) { | |
1152 const KURL& newURL = i + 1 < responses.size() | |
1153 ? KURL(responses[i + 1].url()) | |
1154 : resource->resourceRequest().url(); | |
1155 bool crossOrigin = IsCrossOrigin(responses[i].url(), newURL); | |
1156 info->addRedirect(responses[i], crossOrigin); | |
1157 } | |
1158 | 1182 |
1159 if (resource->response().isHTTP() && | 1183 if (resource->response().isHTTP() && |
1160 resource->response().httpStatusCode() < 400) { | 1184 resource->response().httpStatusCode() < 400) { |
1161 populateResourceTiming(info.get(), resource); | 1185 populateResourceTiming(info.get(), resource); |
1162 info->setLoadFinishTime(finishTime); | 1186 info->setLoadFinishTime(finishTime); |
1163 // encodedDataLength == -1 means "not available". | 1187 // encodedDataLength == -1 means "not available". |
1164 // TODO(ricea): Find cases where it is not available but the | 1188 // TODO(ricea): Find cases where it is not available but the |
1165 // PerformanceResourceTiming spec requires it to be available and fix | 1189 // PerformanceResourceTiming spec requires it to be available and fix |
1166 // them. | 1190 // them. |
1167 info->addFinalTransferSize(encodedDataLength == -1 ? 0 | 1191 info->addFinalTransferSize(encodedDataLength == -1 ? 0 |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1319 SecurityOrigin* sourceOrigin = context().getSecurityOrigin(); | 1343 SecurityOrigin* sourceOrigin = context().getSecurityOrigin(); |
1320 if (sourceOrigin && sourceOrigin->hasSuborigin()) | 1344 if (sourceOrigin && sourceOrigin->hasSuborigin()) |
1321 request.setSkipServiceWorker(WebURLRequest::SkipServiceWorker::All); | 1345 request.setSkipServiceWorker(WebURLRequest::SkipServiceWorker::All); |
1322 | 1346 |
1323 ResourceLoader* loader = ResourceLoader::create(this, resource); | 1347 ResourceLoader* loader = ResourceLoader::create(this, resource); |
1324 if (resource->shouldBlockLoadEvent()) | 1348 if (resource->shouldBlockLoadEvent()) |
1325 m_loaders.add(loader); | 1349 m_loaders.add(loader); |
1326 else | 1350 else |
1327 m_nonBlockingLoaders.add(loader); | 1351 m_nonBlockingLoaders.add(loader); |
1328 | 1352 |
1329 storeResourceTimingInitiatorInformation(resource); | 1353 storePerformanceTimingInitiatorInformation(resource); |
1330 resource->setFetcherSecurityOrigin(sourceOrigin); | 1354 resource->setFetcherSecurityOrigin(sourceOrigin); |
1331 | 1355 |
1332 loader->activateCacheAwareLoadingIfNeeded(request); | 1356 loader->activateCacheAwareLoadingIfNeeded(request); |
1333 loader->start(request, context().loadingTaskRunner(), | 1357 loader->start(request, context().loadingTaskRunner(), |
1334 context().defersLoading()); | 1358 context().defersLoading()); |
1335 return true; | 1359 return true; |
1336 } | 1360 } |
1337 | 1361 |
1338 void ResourceFetcher::removeResourceLoader(ResourceLoader* loader) { | 1362 void ResourceFetcher::removeResourceLoader(ResourceLoader* loader) { |
1339 DCHECK(loader); | 1363 DCHECK(loader); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1412 shouldDeferImageLoad(newRequest.url())) { | 1436 shouldDeferImageLoad(newRequest.url())) { |
1413 return ResourceRequestBlockedReason::Other; | 1437 return ResourceRequestBlockedReason::Other; |
1414 } | 1438 } |
1415 } | 1439 } |
1416 | 1440 |
1417 ResourceTimingInfoMap::iterator it = m_resourceTimingInfoMap.find(resource); | 1441 ResourceTimingInfoMap::iterator it = m_resourceTimingInfoMap.find(resource); |
1418 if (it != m_resourceTimingInfoMap.end()) { | 1442 if (it != m_resourceTimingInfoMap.end()) { |
1419 bool crossOrigin = IsCrossOrigin(redirectResponse.url(), newRequest.url()); | 1443 bool crossOrigin = IsCrossOrigin(redirectResponse.url(), newRequest.url()); |
1420 it->value->addRedirect(redirectResponse, crossOrigin); | 1444 it->value->addRedirect(redirectResponse, crossOrigin); |
1421 } | 1445 } |
| 1446 |
| 1447 if (resource->getType() == Resource::MainResource) { |
| 1448 DCHECK(m_navigationTimingInfo); |
| 1449 bool crossOrigin = IsCrossOrigin(redirectResponse.url(), newRequest.url()); |
| 1450 m_navigationTimingInfo->addRedirect(redirectResponse, crossOrigin); |
| 1451 } |
| 1452 |
1422 newRequest.setAllowStoredCredentials(resource->options().allowCredentials == | 1453 newRequest.setAllowStoredCredentials(resource->options().allowCredentials == |
1423 AllowStoredCredentials); | 1454 AllowStoredCredentials); |
1424 willSendRequest(resource->identifier(), newRequest, redirectResponse, | 1455 willSendRequest(resource->identifier(), newRequest, redirectResponse, |
1425 resource->options()); | 1456 resource->options()); |
1426 return ResourceRequestBlockedReason::None; | 1457 return ResourceRequestBlockedReason::None; |
1427 } | 1458 } |
1428 | 1459 |
1429 void ResourceFetcher::willSendRequest(unsigned long identifier, | 1460 void ResourceFetcher::willSendRequest(unsigned long identifier, |
1430 ResourceRequest& newRequest, | 1461 ResourceRequest& newRequest, |
1431 const ResourceResponse& redirectResponse, | 1462 const ResourceResponse& redirectResponse, |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1674 visitor->trace(m_context); | 1705 visitor->trace(m_context); |
1675 visitor->trace(m_archive); | 1706 visitor->trace(m_archive); |
1676 visitor->trace(m_loaders); | 1707 visitor->trace(m_loaders); |
1677 visitor->trace(m_nonBlockingLoaders); | 1708 visitor->trace(m_nonBlockingLoaders); |
1678 visitor->trace(m_documentResources); | 1709 visitor->trace(m_documentResources); |
1679 visitor->trace(m_preloads); | 1710 visitor->trace(m_preloads); |
1680 visitor->trace(m_resourceTimingInfoMap); | 1711 visitor->trace(m_resourceTimingInfoMap); |
1681 } | 1712 } |
1682 | 1713 |
1683 } // namespace blink | 1714 } // namespace blink |
OLD | NEW |