Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(99)

Side by Side Diff: third_party/WebKit/Source/core/fetch/ResourceFetcher.cpp

Issue 2533683002: Move the code in ResourceFetcher handling calls from WebURLLoaderImpl to ResourceLoader (Closed)
Patch Set: Fix test Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 10 matching lines...) Expand all
21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 Boston, MA 02110-1301, USA. 22 Boston, MA 02110-1301, USA.
23 23
24 This class provides all functionality needed for loading images, style 24 This class provides all functionality needed for loading images, style
25 sheets and html pages from the web. It has a memory cache for these objects. 25 sheets and html pages from the web. It has a memory cache for these objects.
26 */ 26 */
27 27
28 #include "core/fetch/ResourceFetcher.h" 28 #include "core/fetch/ResourceFetcher.h"
29 29
30 #include "bindings/core/v8/V8DOMActivityLogger.h" 30 #include "bindings/core/v8/V8DOMActivityLogger.h"
31 #include "core/fetch/CrossOriginAccessControl.h"
32 #include "core/fetch/FetchContext.h" 31 #include "core/fetch/FetchContext.h"
33 #include "core/fetch/FetchInitiatorTypeNames.h" 32 #include "core/fetch/FetchInitiatorTypeNames.h"
34 #include "core/fetch/ImageResource.h" 33 #include "core/fetch/ImageResource.h"
35 #include "core/fetch/MemoryCache.h" 34 #include "core/fetch/MemoryCache.h"
36 #include "core/fetch/ResourceLoader.h" 35 #include "core/fetch/ResourceLoader.h"
37 #include "core/fetch/ResourceLoadingLog.h" 36 #include "core/fetch/ResourceLoadingLog.h"
38 #include "core/fetch/UniqueIdentifier.h" 37 #include "core/fetch/UniqueIdentifier.h"
39 #include "platform/Histogram.h" 38 #include "platform/Histogram.h"
40 #include "platform/RuntimeEnabledFeatures.h" 39 #include "platform/RuntimeEnabledFeatures.h"
41 #include "platform/mhtml/ArchiveResource.h" 40 #include "platform/mhtml/ArchiveResource.h"
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
90 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, MainResource) \ 89 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, MainResource) \
91 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Manifest) \ 90 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Manifest) \
92 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Media) \ 91 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Media) \
93 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Raw) \ 92 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Raw) \
94 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Script) \ 93 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, Script) \
95 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, SVGDocument) \ 94 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, SVGDocument) \
96 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, TextTrack) \ 95 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, TextTrack) \
97 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, XSLStyleSheet) \ 96 DEFINE_SINGLE_RESOURCE_HISTOGRAM(prefix, XSLStyleSheet) \
98 } 97 }
99 98
100 bool IsCrossOrigin(const KURL& a, const KURL& b) {
101 RefPtr<SecurityOrigin> originA = SecurityOrigin::create(a);
102 RefPtr<SecurityOrigin> originB = SecurityOrigin::create(b);
103 return !originB->isSameSchemeHostPort(originA.get());
104 }
105
106 void addRedirectsToTimingInfo(Resource* resource, ResourceTimingInfo* info) { 99 void addRedirectsToTimingInfo(Resource* resource, ResourceTimingInfo* info) {
107 // Store redirect responses that were packed inside the final response. 100 // Store redirect responses that were packed inside the final response.
108 const auto& responses = resource->response().redirectResponses(); 101 const auto& responses = resource->response().redirectResponses();
109 for (size_t i = 0; i < responses.size(); ++i) { 102 for (size_t i = 0; i < responses.size(); ++i) {
110 const KURL& newURL = i + 1 < responses.size() 103 const KURL& newURL = i + 1 < responses.size()
111 ? KURL(responses[i + 1].url()) 104 ? KURL(responses[i + 1].url())
112 : resource->resourceRequest().url(); 105 : resource->resourceRequest().url();
113 bool crossOrigin = IsCrossOrigin(responses[i].url(), newURL); 106 bool crossOrigin =
107 !SecurityOrigin::areSameSchemeHostPort(responses[i].url(), newURL);
114 info->addRedirect(responses[i], crossOrigin); 108 info->addRedirect(responses[i], crossOrigin);
115 } 109 }
116 } 110 }
117 111
118 } // namespace 112 void RecordSriResourceIntegrityMismatchEvent(
119
120 static void RecordSriResourceIntegrityMismatchEvent(
121 SriResourceIntegrityMismatchEvent event) { 113 SriResourceIntegrityMismatchEvent event) {
122 DEFINE_THREAD_SAFE_STATIC_LOCAL( 114 DEFINE_THREAD_SAFE_STATIC_LOCAL(
123 EnumerationHistogram, integrityHistogram, 115 EnumerationHistogram, integrityHistogram,
124 new EnumerationHistogram("sri.resource_integrity_mismatch_event", 116 new EnumerationHistogram("sri.resource_integrity_mismatch_event",
125 SriResourceIntegrityMismatchEventCount)); 117 SriResourceIntegrityMismatchEventCount));
126 integrityHistogram.count(event); 118 integrityHistogram.count(event);
127 } 119 }
128 120
129 static ResourceLoadPriority typeToPriority(Resource::Type type) { 121 ResourceLoadPriority typeToPriority(Resource::Type type) {
130 switch (type) { 122 switch (type) {
131 case Resource::MainResource: 123 case Resource::MainResource:
132 case Resource::CSSStyleSheet: 124 case Resource::CSSStyleSheet:
133 case Resource::Font: 125 case Resource::Font:
134 // Also parser-blocking scripts (set explicitly in loadPriority) 126 // Also parser-blocking scripts (set explicitly in loadPriority)
135 return ResourceLoadPriorityVeryHigh; 127 return ResourceLoadPriorityVeryHigh;
136 case Resource::XSLStyleSheet: 128 case Resource::XSLStyleSheet:
137 DCHECK(RuntimeEnabledFeatures::xsltEnabled()); 129 DCHECK(RuntimeEnabledFeatures::xsltEnabled());
138 case Resource::Raw: 130 case Resource::Raw:
139 case Resource::ImportResource: 131 case Resource::ImportResource:
(...skipping 11 matching lines...) Expand all
151 // Also async scripts (set explicitly in loadPriority) 143 // Also async scripts (set explicitly in loadPriority)
152 return ResourceLoadPriorityLow; 144 return ResourceLoadPriorityLow;
153 case Resource::LinkPrefetch: 145 case Resource::LinkPrefetch:
154 return ResourceLoadPriorityVeryLow; 146 return ResourceLoadPriorityVeryLow;
155 } 147 }
156 148
157 NOTREACHED(); 149 NOTREACHED();
158 return ResourceLoadPriorityUnresolved; 150 return ResourceLoadPriorityUnresolved;
159 } 151 }
160 152
153 } // namespace
154
161 ResourceLoadPriority ResourceFetcher::computeLoadPriority( 155 ResourceLoadPriority ResourceFetcher::computeLoadPriority(
162 Resource::Type type, 156 Resource::Type type,
163 const FetchRequest& request, 157 const FetchRequest& request,
164 ResourcePriority::VisibilityStatus visibility) { 158 ResourcePriority::VisibilityStatus visibility) {
165 ResourceLoadPriority priority = typeToPriority(type); 159 ResourceLoadPriority priority = typeToPriority(type);
166 160
167 // Visible resources (images in practice) get a boost to High priority. 161 // Visible resources (images in practice) get a boost to High priority.
168 if (visibility == ResourcePriority::Visible) 162 if (visibility == ResourcePriority::Visible)
169 priority = ResourceLoadPriorityHigh; 163 priority = ResourceLoadPriorityHigh;
170 164
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 } 257 }
264 258
265 ResourceFetcher::~ResourceFetcher() {} 259 ResourceFetcher::~ResourceFetcher() {}
266 260
267 Resource* ResourceFetcher::cachedResource(const KURL& resourceURL) const { 261 Resource* ResourceFetcher::cachedResource(const KURL& resourceURL) const {
268 KURL url = MemoryCache::removeFragmentIdentifierIfNeeded(resourceURL); 262 KURL url = MemoryCache::removeFragmentIdentifierIfNeeded(resourceURL);
269 const WeakMember<Resource>& resource = m_documentResources.get(url); 263 const WeakMember<Resource>& resource = m_documentResources.get(url);
270 return resource.get(); 264 return resource.get();
271 } 265 }
272 266
273 ResourceRequestBlockedReason ResourceFetcher::canAccessResponse(
274 Resource* resource,
275 const ResourceResponse& response) const {
276 // Redirects can change the response URL different from one of request.
277 bool forPreload = resource->isUnusedPreload();
278 ResourceRequestBlockedReason blockedReason =
279 context().canRequest(resource->getType(), resource->resourceRequest(),
280 response.url(), resource->options(), forPreload,
281 FetchRequest::UseDefaultOriginRestrictionForType);
282 if (blockedReason != ResourceRequestBlockedReason::None)
283 return blockedReason;
284
285 SecurityOrigin* sourceOrigin = resource->options().securityOrigin.get();
286 if (!sourceOrigin)
287 sourceOrigin = context().getSecurityOrigin();
288
289 if (sourceOrigin->canRequestNoSuborigin(response.url()))
290 return ResourceRequestBlockedReason::None;
291
292 // Use the original response instead of the 304 response for a successful
293 // revaldiation.
294 const ResourceResponse& responseForAccessControl =
295 (resource->isCacheValidator() && response.httpStatusCode() == 304)
296 ? resource->response()
297 : response;
298 String errorDescription;
299 if (!passesAccessControlCheck(
300 responseForAccessControl, resource->options().allowCredentials,
301 sourceOrigin, errorDescription,
302 resource->lastResourceRequest().requestContext())) {
303 resource->setCORSFailed();
304 if (!forPreload) {
305 String resourceType = Resource::resourceTypeToString(
306 resource->getType(), resource->options().initiatorInfo);
307 context().addConsoleMessage(
308 "Access to " + resourceType + " at '" + response.url().getString() +
309 "' from origin '" + sourceOrigin->toString() +
310 "' has been blocked by CORS policy: " + errorDescription);
311 }
312 return ResourceRequestBlockedReason::Other;
313 }
314 return ResourceRequestBlockedReason::None;
315 }
316
317 bool ResourceFetcher::isControlledByServiceWorker() const { 267 bool ResourceFetcher::isControlledByServiceWorker() const {
318 return context().isControlledByServiceWorker(); 268 return context().isControlledByServiceWorker();
319 } 269 }
320 270
321 bool ResourceFetcher::resourceNeedsLoad(Resource* resource, 271 bool ResourceFetcher::resourceNeedsLoad(Resource* resource,
322 const FetchRequest& request, 272 const FetchRequest& request,
323 RevalidationPolicy policy) { 273 RevalidationPolicy policy) {
324 // Defer a font load until it is actually needed unless this is a preload. 274 // Defer a font load until it is actually needed unless this is a preload.
325 if (resource->getType() == Resource::Font && !request.forPreload()) 275 if (resource->getType() == Resource::Font && !request.forPreload())
326 return false; 276 return false;
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after
798 if (!timingAllowOrigin.isEmpty()) 748 if (!timingAllowOrigin.isEmpty())
799 info->setOriginalTimingAllowOrigin(timingAllowOrigin); 749 info->setOriginalTimingAllowOrigin(timingAllowOrigin);
800 } 750 }
801 751
802 if (!isMainResource || 752 if (!isMainResource ||
803 context().updateTimingInfoForIFrameNavigation(info.get())) { 753 context().updateTimingInfoForIFrameNavigation(info.get())) {
804 m_resourceTimingInfoMap.add(resource, std::move(info)); 754 m_resourceTimingInfoMap.add(resource, std::move(info));
805 } 755 }
806 } 756 }
807 757
758 void ResourceFetcher::recordResourceTimingOnRedirect(
759 Resource* resource,
760 const ResourceResponse& redirectResponse,
761 bool crossOrigin) {
762 ResourceTimingInfoMap::iterator it = m_resourceTimingInfoMap.find(resource);
763 if (it != m_resourceTimingInfoMap.end()) {
764 it->value->addRedirect(redirectResponse, crossOrigin);
765 }
766
767 if (resource->getType() == Resource::MainResource) {
768 DCHECK(m_navigationTimingInfo);
769 m_navigationTimingInfo->addRedirect(redirectResponse, crossOrigin);
770 }
771 }
772
808 ResourceFetcher::RevalidationPolicy 773 ResourceFetcher::RevalidationPolicy
809 ResourceFetcher::determineRevalidationPolicy(Resource::Type type, 774 ResourceFetcher::determineRevalidationPolicy(Resource::Type type,
810 const FetchRequest& fetchRequest, 775 const FetchRequest& fetchRequest,
811 Resource* existingResource, 776 Resource* existingResource,
812 bool isStaticData) const { 777 bool isStaticData) const {
813 const ResourceRequest& request = fetchRequest.resourceRequest(); 778 const ResourceRequest& request = fetchRequest.resourceRequest();
814 779
815 if (!existingResource) 780 if (!existingResource)
816 return Load; 781 return Load;
817 782
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
1141 if (!context().isMainFrame()) 1106 if (!context().isMainFrame())
1142 return nullptr; 1107 return nullptr;
1143 m_archive = MHTMLArchive::create(resource->url(), resource->resourceBuffer()); 1108 m_archive = MHTMLArchive::create(resource->url(), resource->resourceBuffer());
1144 return m_archive ? m_archive->mainResource() : nullptr; 1109 return m_archive ? m_archive->mainResource() : nullptr;
1145 } 1110 }
1146 1111
1147 ResourceTimingInfo* ResourceFetcher::getNavigationTimingInfo() { 1112 ResourceTimingInfo* ResourceFetcher::getNavigationTimingInfo() {
1148 return m_navigationTimingInfo.get(); 1113 return m_navigationTimingInfo.get();
1149 } 1114 }
1150 1115
1151 void ResourceFetcher::didFinishLoading(Resource* resource, 1116 void ResourceFetcher::handleLoadCompletion(Resource* resource) {
1152 double finishTime, 1117 context().didLoadResource(resource);
1153 DidFinishLoadingReason finishReason) { 1118
1154 network_instrumentation::endResourceLoad( 1119 if (resource->isImage() &&
1155 resource->identifier(), network_instrumentation::RequestOutcome::Success); 1120 toImageResource(resource)->shouldReloadBrokenPlaceholder()) {
1121 toImageResource(resource)->reloadIfLoFiOrPlaceholder(this);
1122 }
1123 }
1124
1125 void ResourceFetcher::handleLoaderFinish(Resource* resource,
1126 double finishTime,
1127 LoaderFinishType type) {
1156 DCHECK(resource); 1128 DCHECK(resource);
1129
1130 ResourceLoader* loader = resource->loader();
1131 if (type == DidFinishFirstPartInMultipart) {
1132 // When loading a multipart resource, make the loader non-block when
1133 // finishing loading the first part.
1134 moveResourceLoaderToNonBlocking(loader);
1135 } else {
1136 removeResourceLoader(loader);
1137 DCHECK(!m_nonBlockingLoaders.contains(loader));
1138 }
1139 DCHECK(!m_loaders.contains(loader));
1140
1157 const int64_t encodedDataLength = resource->response().encodedDataLength(); 1141 const int64_t encodedDataLength = resource->response().encodedDataLength();
1158 1142
1159 // When loading a multipart resource, make the loader non-block when finishing
1160 // loading the first part.
1161 if (finishReason == DidFinishFirstPartInMultipart)
1162 moveResourceLoaderToNonBlocking(resource->loader());
1163 else
1164 removeResourceLoader(resource->loader());
1165 DCHECK(!m_loaders.contains(resource->loader()));
1166 DCHECK(finishReason == DidFinishFirstPartInMultipart ||
1167 !m_nonBlockingLoaders.contains(resource->loader()));
1168
1169 if (resource->getType() == Resource::MainResource) { 1143 if (resource->getType() == Resource::MainResource) {
1170 DCHECK(m_navigationTimingInfo); 1144 DCHECK(m_navigationTimingInfo);
1171 // Store redirect responses that were packed inside the final response. 1145 // Store redirect responses that were packed inside the final response.
1172 addRedirectsToTimingInfo(resource, m_navigationTimingInfo.get()); 1146 addRedirectsToTimingInfo(resource, m_navigationTimingInfo.get());
1173 if (resource->response().isHTTP()) { 1147 if (resource->response().isHTTP()) {
1174 m_navigationTimingInfo->addFinalTransferSize( 1148 m_navigationTimingInfo->addFinalTransferSize(
1175 encodedDataLength == -1 ? 0 : encodedDataLength); 1149 encodedDataLength == -1 ? 0 : encodedDataLength);
1176 } 1150 }
1177 } 1151 }
1178 if (std::unique_ptr<ResourceTimingInfo> info = 1152 if (std::unique_ptr<ResourceTimingInfo> info =
1179 m_resourceTimingInfoMap.take(resource)) { 1153 m_resourceTimingInfoMap.take(resource)) {
1180 // Store redirect responses that were packed inside the final response. 1154 // Store redirect responses that were packed inside the final response.
1181 addRedirectsToTimingInfo(resource, info.get()); 1155 addRedirectsToTimingInfo(resource, info.get());
1182 1156
1183 if (resource->response().isHTTP() && 1157 if (resource->response().isHTTP() &&
1184 resource->response().httpStatusCode() < 400) { 1158 resource->response().httpStatusCode() < 400) {
1185 populateResourceTiming(info.get(), resource); 1159 populateResourceTiming(info.get(), resource);
1186 info->setLoadFinishTime(finishTime); 1160 info->setLoadFinishTime(finishTime);
1187 // encodedDataLength == -1 means "not available". 1161 // encodedDataLength == -1 means "not available".
1188 // TODO(ricea): Find cases where it is not available but the 1162 // TODO(ricea): Find cases where it is not available but the
1189 // PerformanceResourceTiming spec requires it to be available and fix 1163 // PerformanceResourceTiming spec requires it to be available and fix
1190 // them. 1164 // them.
1191 info->addFinalTransferSize(encodedDataLength == -1 ? 0 1165 info->addFinalTransferSize(encodedDataLength == -1 ? 0
1192 : encodedDataLength); 1166 : encodedDataLength);
1167
1193 if (resource->options().requestInitiatorContext == DocumentContext) 1168 if (resource->options().requestInitiatorContext == DocumentContext)
1194 context().addResourceTiming(*info); 1169 context().addResourceTiming(*info);
1195 resource->reportResourceTimingToClients(*info); 1170 resource->reportResourceTimingToClients(*info);
1196 } 1171 }
1197 } 1172 }
1173
1198 context().dispatchDidFinishLoading(resource->identifier(), finishTime, 1174 context().dispatchDidFinishLoading(resource->identifier(), finishTime,
1199 encodedDataLength); 1175 encodedDataLength);
1200 if (finishReason == DidFinishLoading) 1176
1177 if (type == DidFinishLoading)
1201 resource->finish(finishTime); 1178 resource->finish(finishTime);
1202 context().didLoadResource(resource);
1203 1179
1204 if (resource->isImage() && 1180 handleLoadCompletion(resource);
1205 toImageResource(resource)->shouldReloadBrokenPlaceholder()) {
1206 toImageResource(resource)->reloadIfLoFiOrPlaceholder(this);
1207 }
1208 } 1181 }
1209 1182
1210 void ResourceFetcher::didFailLoading(Resource* resource, 1183 void ResourceFetcher::handleLoaderError(Resource* resource,
1211 const ResourceError& error) { 1184 const ResourceError& error) {
1212 network_instrumentation::endResourceLoad( 1185 DCHECK(resource);
1213 resource->identifier(), network_instrumentation::RequestOutcome::Fail); 1186
1214 removeResourceLoader(resource->loader()); 1187 removeResourceLoader(resource->loader());
1215 m_resourceTimingInfoMap.take(const_cast<Resource*>(resource)); 1188
1189 m_resourceTimingInfoMap.take(resource);
1190
1216 bool isInternalRequest = resource->options().initiatorInfo.name == 1191 bool isInternalRequest = resource->options().initiatorInfo.name ==
1217 FetchInitiatorTypeNames::internal; 1192 FetchInitiatorTypeNames::internal;
1193
1218 context().dispatchDidFail(resource->identifier(), error, 1194 context().dispatchDidFail(resource->identifier(), error,
1219 resource->response().encodedDataLength(), 1195 resource->response().encodedDataLength(),
1220 isInternalRequest); 1196 isInternalRequest);
1197
1221 resource->error(error); 1198 resource->error(error);
1222 context().didLoadResource(resource);
1223 1199
1224 if (resource->isImage() && 1200 handleLoadCompletion(resource);
1225 toImageResource(resource)->shouldReloadBrokenPlaceholder()) {
1226 toImageResource(resource)->reloadIfLoFiOrPlaceholder(this);
1227 }
1228 }
1229
1230 void ResourceFetcher::didReceiveResponse(
1231 Resource* resource,
1232 const ResourceResponse& response,
1233 std::unique_ptr<WebDataConsumerHandle> handle) {
1234 if (response.wasFetchedViaServiceWorker()) {
1235 if (resource->options().corsEnabled == IsCORSEnabled &&
1236 response.wasFallbackRequiredByServiceWorker()) {
1237 ResourceRequest request = resource->lastResourceRequest();
1238 DCHECK_EQ(request.skipServiceWorker(),
1239 WebURLRequest::SkipServiceWorker::None);
1240 // This code handles the case when a regular controlling service worker
1241 // doesn't handle a cross origin request. When this happens we still want
1242 // to give foreign fetch a chance to handle the request, so only skip the
1243 // controlling service worker for the fallback request. This is currently
1244 // safe because of http://crbug.com/604084 the
1245 // wasFallbackRequiredByServiceWorker flag is never set when foreign fetch
1246 // handled a request.
1247 if (!context().shouldLoadNewResource(resource->getType())) {
1248 // Cancel the request if we should not trigger a reload now.
1249 resource->loader()->didFail(
1250 ResourceError::cancelledError(response.url()));
1251 return;
1252 }
1253 request.setSkipServiceWorker(
1254 WebURLRequest::SkipServiceWorker::Controlling);
1255 resource->loader()->restart(request, context().loadingTaskRunner(),
1256 context().defersLoading());
1257 return;
1258 }
1259
1260 // If the response is fetched via ServiceWorker, the original URL of the
1261 // response could be different from the URL of the request. We check the URL
1262 // not to load the resources which are forbidden by the page CSP.
1263 // https://w3c.github.io/webappsec-csp/#should-block-response
1264 const KURL& originalURL = response.originalURLViaServiceWorker();
1265 if (!originalURL.isEmpty()) {
1266 ResourceRequestBlockedReason blockedReason = context().allowResponse(
1267 resource->getType(), resource->resourceRequest(), originalURL,
1268 resource->options());
1269 if (blockedReason != ResourceRequestBlockedReason::None) {
1270 resource->loader()->didFail(
1271 ResourceError::cancelledDueToAccessCheckError(originalURL,
1272 blockedReason));
1273 return;
1274 }
1275 }
1276 } else if (resource->options().corsEnabled == IsCORSEnabled) {
1277 ResourceRequestBlockedReason blockedReason =
1278 canAccessResponse(resource, response);
1279 if (blockedReason != ResourceRequestBlockedReason::None) {
1280 resource->loader()->didFail(ResourceError::cancelledDueToAccessCheckError(
1281 response.url(), blockedReason));
1282 return;
1283 }
1284 }
1285
1286 context().dispatchDidReceiveResponse(
1287 resource->identifier(), response, resource->resourceRequest().frameType(),
1288 resource->resourceRequest().requestContext(), resource);
1289 resource->responseReceived(response, std::move(handle));
1290 if (resource->loader() && response.httpStatusCode() >= 400 &&
1291 !resource->shouldIgnoreHTTPStatusCodeErrors()) {
1292 resource->loader()->didFail(ResourceError::cancelledError(response.url()));
1293 }
1294 }
1295
1296 void ResourceFetcher::didReceiveData(const Resource* resource,
1297 const char* data,
1298 int dataLength) {
1299 context().dispatchDidReceiveData(resource->identifier(), data, dataLength);
1300 }
1301
1302 void ResourceFetcher::didReceiveTransferSizeUpdate(const Resource* resource,
1303 int transferSizeDiff) {
1304 context().dispatchDidReceiveEncodedData(resource->identifier(),
1305 transferSizeDiff);
1306 }
1307
1308 void ResourceFetcher::didDownloadData(const Resource* resource,
1309 int dataLength,
1310 int encodedDataLength) {
1311 context().dispatchDidDownloadData(resource->identifier(), dataLength,
1312 encodedDataLength);
1313 } 1201 }
1314 1202
1315 void ResourceFetcher::moveResourceLoaderToNonBlocking(ResourceLoader* loader) { 1203 void ResourceFetcher::moveResourceLoaderToNonBlocking(ResourceLoader* loader) {
1316 DCHECK(loader); 1204 DCHECK(loader);
1317 // TODO(yoav): Convert CHECK to DCHECK if no crash reports come in. 1205 // TODO(yoav): Convert CHECK to DCHECK if no crash reports come in.
1318 CHECK(m_loaders.contains(loader)); 1206 CHECK(m_loaders.contains(loader));
1319 m_nonBlockingLoaders.add(loader); 1207 m_nonBlockingLoaders.add(loader);
1320 m_loaders.remove(loader); 1208 m_loaders.remove(loader);
1321 } 1209 }
1322 1210
1323 bool ResourceFetcher::startLoad(Resource* resource) { 1211 bool ResourceFetcher::startLoad(Resource* resource) {
1324 DCHECK(resource); 1212 DCHECK(resource);
1325 DCHECK(resource->stillNeedsLoad()); 1213 DCHECK(resource->stillNeedsLoad());
1326 if (!context().shouldLoadNewResource(resource->getType())) { 1214 if (!context().shouldLoadNewResource(resource->getType())) {
1327 memoryCache()->remove(resource); 1215 memoryCache()->remove(resource);
1328 return false; 1216 return false;
1329 } 1217 }
1330 1218
1331 ResourceRequest request(resource->resourceRequest()); 1219 ResourceRequest request(resource->resourceRequest());
1332 willSendRequest(resource->identifier(), request, ResourceResponse(), 1220 context().dispatchWillSendRequest(resource->identifier(), request,
1333 resource->options()); 1221 ResourceResponse(),
1222 resource->options().initiatorInfo);
1334 1223
1335 // TODO(shaochuan): Saving modified ResourceRequest back to |resource|, remove 1224 // TODO(shaochuan): Saving modified ResourceRequest back to |resource|, remove
1336 // once willSendRequest() takes const ResourceRequest. crbug.com/632580 1225 // once dispatchWillSendRequest() takes const ResourceRequest.
1226 // crbug.com/632580
1337 resource->setResourceRequest(request); 1227 resource->setResourceRequest(request);
1338 1228
1339 // Resource requests from suborigins should not be intercepted by the service 1229 // Resource requests from suborigins should not be intercepted by the service
1340 // worker of the physical origin. This has the effect that, for now, 1230 // worker of the physical origin. This has the effect that, for now,
1341 // suborigins do not work with service workers. See 1231 // suborigins do not work with service workers. See
1342 // https://w3c.github.io/webappsec-suborigins/. 1232 // https://w3c.github.io/webappsec-suborigins/.
1343 SecurityOrigin* sourceOrigin = context().getSecurityOrigin(); 1233 SecurityOrigin* sourceOrigin = context().getSecurityOrigin();
1344 if (sourceOrigin && sourceOrigin->hasSuborigin()) 1234 if (sourceOrigin && sourceOrigin->hasSuborigin())
1345 request.setSkipServiceWorker(WebURLRequest::SkipServiceWorker::All); 1235 request.setSkipServiceWorker(WebURLRequest::SkipServiceWorker::All);
1346 1236
1347 ResourceLoader* loader = ResourceLoader::create(this, resource); 1237 ResourceLoader* loader = ResourceLoader::create(this, resource);
1348 if (resource->shouldBlockLoadEvent()) 1238 if (resource->shouldBlockLoadEvent())
1349 m_loaders.add(loader); 1239 m_loaders.add(loader);
1350 else 1240 else
1351 m_nonBlockingLoaders.add(loader); 1241 m_nonBlockingLoaders.add(loader);
1352 1242
1353 storePerformanceTimingInitiatorInformation(resource); 1243 storePerformanceTimingInitiatorInformation(resource);
1354 resource->setFetcherSecurityOrigin(sourceOrigin); 1244 resource->setFetcherSecurityOrigin(sourceOrigin);
1355 1245
1356 loader->activateCacheAwareLoadingIfNeeded(request); 1246 loader->activateCacheAwareLoadingIfNeeded(request);
1357 loader->start(request, context().loadingTaskRunner(), 1247 loader->start(request);
1358 context().defersLoading());
1359 return true; 1248 return true;
1360 } 1249 }
1361 1250
1362 void ResourceFetcher::removeResourceLoader(ResourceLoader* loader) { 1251 void ResourceFetcher::removeResourceLoader(ResourceLoader* loader) {
1363 DCHECK(loader); 1252 DCHECK(loader);
1364 if (m_loaders.contains(loader)) 1253 if (m_loaders.contains(loader))
1365 m_loaders.remove(loader); 1254 m_loaders.remove(loader);
1366 else if (m_nonBlockingLoaders.contains(loader)) 1255 else if (m_nonBlockingLoaders.contains(loader))
1367 m_nonBlockingLoaders.remove(loader); 1256 m_nonBlockingLoaders.remove(loader);
1368 else 1257 else
(...skipping 17 matching lines...) Expand all
1386 return !m_loaders.isEmpty(); 1275 return !m_loaders.isEmpty();
1387 } 1276 }
1388 1277
1389 void ResourceFetcher::setDefersLoading(bool defers) { 1278 void ResourceFetcher::setDefersLoading(bool defers) {
1390 for (const auto& loader : m_nonBlockingLoaders) 1279 for (const auto& loader : m_nonBlockingLoaders)
1391 loader->setDefersLoading(defers); 1280 loader->setDefersLoading(defers);
1392 for (const auto& loader : m_loaders) 1281 for (const auto& loader : m_loaders)
1393 loader->setDefersLoading(defers); 1282 loader->setDefersLoading(defers);
1394 } 1283 }
1395 1284
1396 bool ResourceFetcher::defersLoading() const {
1397 return context().defersLoading();
1398 }
1399
1400 static bool isManualRedirectFetchRequest(const ResourceRequest& request) {
1401 return request.fetchRedirectMode() ==
1402 WebURLRequest::FetchRedirectModeManual &&
1403 request.requestContext() == WebURLRequest::RequestContextFetch;
1404 }
1405
1406 ResourceRequestBlockedReason ResourceFetcher::willFollowRedirect(
1407 Resource* resource,
1408 ResourceRequest& newRequest,
1409 const ResourceResponse& redirectResponse) {
1410 if (!isManualRedirectFetchRequest(resource->resourceRequest())) {
1411 ResourceRequestBlockedReason blockedReason =
1412 context().canRequest(resource->getType(), newRequest, newRequest.url(),
1413 resource->options(), resource->isUnusedPreload(),
1414 FetchRequest::UseDefaultOriginRestrictionForType);
1415 if (blockedReason != ResourceRequestBlockedReason::None)
1416 return blockedReason;
1417 if (resource->options().corsEnabled == IsCORSEnabled) {
1418 RefPtr<SecurityOrigin> sourceOrigin = resource->options().securityOrigin;
1419 if (!sourceOrigin.get())
1420 sourceOrigin = context().getSecurityOrigin();
1421
1422 String errorMessage;
1423 StoredCredentials withCredentials =
1424 resource->lastResourceRequest().allowStoredCredentials()
1425 ? AllowStoredCredentials
1426 : DoNotAllowStoredCredentials;
1427 if (!CrossOriginAccessControl::handleRedirect(
1428 sourceOrigin, newRequest, redirectResponse, withCredentials,
1429 resource->mutableOptions(), errorMessage)) {
1430 resource->setCORSFailed();
1431 context().addConsoleMessage(errorMessage);
1432 return ResourceRequestBlockedReason::Other;
1433 }
1434 }
1435 if (resource->getType() == Resource::Image &&
1436 shouldDeferImageLoad(newRequest.url())) {
1437 return ResourceRequestBlockedReason::Other;
1438 }
1439 }
1440
1441 ResourceTimingInfoMap::iterator it = m_resourceTimingInfoMap.find(resource);
1442 if (it != m_resourceTimingInfoMap.end()) {
1443 bool crossOrigin = IsCrossOrigin(redirectResponse.url(), newRequest.url());
1444 it->value->addRedirect(redirectResponse, crossOrigin);
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
1453 newRequest.setAllowStoredCredentials(resource->options().allowCredentials ==
1454 AllowStoredCredentials);
1455 willSendRequest(resource->identifier(), newRequest, redirectResponse,
1456 resource->options());
1457 return ResourceRequestBlockedReason::None;
1458 }
1459
1460 void ResourceFetcher::willSendRequest(unsigned long identifier,
1461 ResourceRequest& newRequest,
1462 const ResourceResponse& redirectResponse,
1463 const ResourceLoaderOptions& options) {
1464 context().dispatchWillSendRequest(identifier, newRequest, redirectResponse,
1465 options.initiatorInfo);
1466 }
1467
1468 void ResourceFetcher::updateAllImageResourcePriorities() { 1285 void ResourceFetcher::updateAllImageResourcePriorities() {
1469 TRACE_EVENT0( 1286 TRACE_EVENT0(
1470 "blink", 1287 "blink",
1471 "ResourceLoadPriorityOptimizer::updateAllImageResourcePriorities"); 1288 "ResourceLoadPriorityOptimizer::updateAllImageResourcePriorities");
1472 for (const auto& documentResource : m_documentResources) { 1289 for (const auto& documentResource : m_documentResources) {
1473 Resource* resource = documentResource.value.get(); 1290 Resource* resource = documentResource.value.get();
1474 if (!resource || !resource->isImage() || !resource->isLoading()) 1291 if (!resource || !resource->isImage() || !resource->isLoading())
1475 continue; 1292 continue;
1476 1293
1477 ResourcePriority resourcePriority = resource->priorityFromObservers(); 1294 ResourcePriority resourcePriority = resource->priorityFromObservers();
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
1705 visitor->trace(m_context); 1522 visitor->trace(m_context);
1706 visitor->trace(m_archive); 1523 visitor->trace(m_archive);
1707 visitor->trace(m_loaders); 1524 visitor->trace(m_loaders);
1708 visitor->trace(m_nonBlockingLoaders); 1525 visitor->trace(m_nonBlockingLoaders);
1709 visitor->trace(m_documentResources); 1526 visitor->trace(m_documentResources);
1710 visitor->trace(m_preloads); 1527 visitor->trace(m_preloads);
1711 visitor->trace(m_resourceTimingInfoMap); 1528 visitor->trace(m_resourceTimingInfoMap);
1712 } 1529 }
1713 1530
1714 } // namespace blink 1531 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/core/fetch/ResourceFetcher.h ('k') | third_party/WebKit/Source/core/fetch/ResourceFetcherTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698