Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2006, 2007, 2010, 2011 Apple Inc. All rights reserved. | 2 * Copyright (C) 2006, 2007, 2010, 2011 Apple Inc. All rights reserved. |
| 3 * (C) 2007 Graham Dennis (graham.dennis@gmail.com) | 3 * (C) 2007 Graham Dennis (graham.dennis@gmail.com) |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
| 7 * are met: | 7 * are met: |
| 8 * | 8 * |
| 9 * 1. Redistributions of source code must retain the above copyright | 9 * 1. Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
| 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 28 */ | 28 */ |
| 29 | 29 |
| 30 #include "core/fetch/ResourceLoader.h" | 30 #include "core/fetch/ResourceLoader.h" |
| 31 | 31 |
| 32 #include "core/fetch/CrossOriginAccessControl.h" | |
| 33 #include "core/fetch/FetchContext.h" | |
| 32 #include "core/fetch/Resource.h" | 34 #include "core/fetch/Resource.h" |
| 33 #include "core/fetch/ResourceFetcher.h" | 35 #include "core/fetch/ResourceFetcher.h" |
| 34 #include "platform/SharedBuffer.h" | 36 #include "platform/SharedBuffer.h" |
| 35 #include "platform/exported/WrappedResourceRequest.h" | 37 #include "platform/exported/WrappedResourceRequest.h" |
| 36 #include "platform/exported/WrappedResourceResponse.h" | 38 #include "platform/exported/WrappedResourceResponse.h" |
| 39 #include "platform/network/NetworkInstrumentation.h" | |
| 37 #include "platform/network/ResourceError.h" | 40 #include "platform/network/ResourceError.h" |
| 38 #include "public/platform/Platform.h" | 41 #include "public/platform/Platform.h" |
| 39 #include "public/platform/WebCachePolicy.h" | 42 #include "public/platform/WebCachePolicy.h" |
| 40 #include "public/platform/WebData.h" | 43 #include "public/platform/WebData.h" |
| 41 #include "public/platform/WebURLError.h" | 44 #include "public/platform/WebURLError.h" |
| 42 #include "public/platform/WebURLRequest.h" | 45 #include "public/platform/WebURLRequest.h" |
| 43 #include "public/platform/WebURLResponse.h" | 46 #include "public/platform/WebURLResponse.h" |
| 44 #include "wtf/Assertions.h" | 47 #include "wtf/Assertions.h" |
| 45 #include "wtf/CurrentTime.h" | 48 #include "wtf/CurrentTime.h" |
| 46 #include "wtf/PtrUtil.h" | 49 #include "wtf/PtrUtil.h" |
| 47 #include <memory> | 50 #include <memory> |
| 48 | 51 |
| 49 namespace blink { | 52 namespace blink { |
| 50 | 53 |
| 51 ResourceLoader* ResourceLoader::create(ResourceFetcher* fetcher, | 54 ResourceLoader* ResourceLoader::create(ResourceFetcher* fetcher, |
| 52 Resource* resource) { | 55 Resource* resource) { |
| 53 return new ResourceLoader(fetcher, resource); | 56 return new ResourceLoader(fetcher, resource); |
| 54 } | 57 } |
| 55 | 58 |
| 56 ResourceLoader::ResourceLoader(ResourceFetcher* fetcher, Resource* resource) | 59 ResourceLoader::ResourceLoader(ResourceFetcher* fetcher, Resource* resource) |
| 57 : m_fetcher(fetcher), | 60 : m_fetcher(fetcher), |
| 58 m_resource(resource), | 61 m_resource(resource), |
| 59 m_isCacheAwareLoadingActivated(false) { | 62 m_isCacheAwareLoadingActivated(false) { |
| 60 DCHECK(m_resource); | 63 DCHECK(m_resource); |
| 61 DCHECK(m_fetcher); | 64 DCHECK(m_fetcher); |
| 65 | |
| 62 m_resource->setLoader(this); | 66 m_resource->setLoader(this); |
| 63 } | 67 } |
| 64 | 68 |
| 65 ResourceLoader::~ResourceLoader() { | 69 ResourceLoader::~ResourceLoader() { |
| 66 DCHECK(!m_loader); | 70 DCHECK(!m_loader); |
| 67 } | 71 } |
| 68 | 72 |
| 69 DEFINE_TRACE(ResourceLoader) { | 73 DEFINE_TRACE(ResourceLoader) { |
| 70 visitor->trace(m_fetcher); | 74 visitor->trace(m_fetcher); |
| 71 visitor->trace(m_resource); | 75 visitor->trace(m_resource); |
| 72 } | 76 } |
| 73 | 77 |
| 74 void ResourceLoader::start(const ResourceRequest& request, | 78 void ResourceLoader::start(const ResourceRequest& request) { |
| 75 WebTaskRunner* loadingTaskRunner, | |
| 76 bool defersLoading) { | |
| 77 DCHECK(!m_loader); | 79 DCHECK(!m_loader); |
| 80 | |
| 78 if (m_resource->options().synchronousPolicy == RequestSynchronously && | 81 if (m_resource->options().synchronousPolicy == RequestSynchronously && |
| 79 defersLoading) { | 82 context().defersLoading()) { |
| 80 cancel(); | 83 cancel(); |
| 81 return; | 84 return; |
| 82 } | 85 } |
| 83 | 86 |
| 84 m_loader = wrapUnique(Platform::current()->createURLLoader()); | 87 m_loader = wrapUnique(Platform::current()->createURLLoader()); |
| 85 DCHECK(m_loader); | 88 DCHECK(m_loader); |
| 86 m_loader->setDefersLoading(defersLoading); | 89 m_loader->setDefersLoading(context().defersLoading()); |
| 87 m_loader->setLoadingTaskRunner(loadingTaskRunner); | 90 m_loader->setLoadingTaskRunner(context().loadingTaskRunner()); |
| 88 | 91 |
| 89 if (m_isCacheAwareLoadingActivated) { | 92 if (m_isCacheAwareLoadingActivated) { |
| 90 // Override cache policy for cache-aware loading. If this request fails, a | 93 // Override cache policy for cache-aware loading. If this request fails, a |
| 91 // reload with original request will be triggered in didFail(). | 94 // reload with original request will be triggered in didFail(). |
| 92 ResourceRequest cacheAwareRequest(request); | 95 ResourceRequest cacheAwareRequest(request); |
| 93 cacheAwareRequest.setCachePolicy(WebCachePolicy::ReturnCacheDataIfValid); | 96 cacheAwareRequest.setCachePolicy(WebCachePolicy::ReturnCacheDataIfValid); |
| 94 m_loader->loadAsynchronously(WrappedResourceRequest(cacheAwareRequest), | 97 m_loader->loadAsynchronously(WrappedResourceRequest(cacheAwareRequest), |
| 95 this); | 98 this); |
| 96 return; | 99 return; |
| 97 } | 100 } |
| 98 | 101 |
| 99 if (m_resource->options().synchronousPolicy == RequestSynchronously) | 102 if (m_resource->options().synchronousPolicy == RequestSynchronously) |
| 100 requestSynchronously(request); | 103 requestSynchronously(request); |
| 101 else | 104 else |
| 102 m_loader->loadAsynchronously(WrappedResourceRequest(request), this); | 105 m_loader->loadAsynchronously(WrappedResourceRequest(request), this); |
| 103 } | 106 } |
| 104 | 107 |
| 105 void ResourceLoader::restart(const ResourceRequest& request, | 108 void ResourceLoader::restart(const ResourceRequest& request) { |
| 106 WebTaskRunner* loadingTaskRunner, | |
| 107 bool defersLoading) { | |
| 108 CHECK_EQ(m_resource->options().synchronousPolicy, RequestAsynchronously); | 109 CHECK_EQ(m_resource->options().synchronousPolicy, RequestAsynchronously); |
| 110 | |
| 109 m_loader.reset(); | 111 m_loader.reset(); |
| 110 start(request, loadingTaskRunner, defersLoading); | 112 start(request); |
| 111 } | 113 } |
| 112 | 114 |
| 113 void ResourceLoader::setDefersLoading(bool defers) { | 115 void ResourceLoader::setDefersLoading(bool defers) { |
| 114 DCHECK(m_loader); | 116 DCHECK(m_loader); |
| 117 | |
| 115 m_loader->setDefersLoading(defers); | 118 m_loader->setDefersLoading(defers); |
| 116 } | 119 } |
| 117 | 120 |
| 118 void ResourceLoader::didDownloadData(int length, int encodedDataLength) { | |
| 119 m_fetcher->didDownloadData(m_resource.get(), length, encodedDataLength); | |
| 120 m_resource->didDownloadData(length); | |
| 121 } | |
| 122 | |
| 123 void ResourceLoader::didChangePriority(ResourceLoadPriority loadPriority, | 121 void ResourceLoader::didChangePriority(ResourceLoadPriority loadPriority, |
| 124 int intraPriorityValue) { | 122 int intraPriorityValue) { |
| 125 if (m_loader) { | 123 if (m_loader) { |
| 126 m_loader->didChangePriority( | 124 m_loader->didChangePriority( |
| 127 static_cast<WebURLRequest::Priority>(loadPriority), intraPriorityValue); | 125 static_cast<WebURLRequest::Priority>(loadPriority), intraPriorityValue); |
| 128 } | 126 } |
| 129 } | 127 } |
| 130 | 128 |
| 131 void ResourceLoader::cancel() { | 129 void ResourceLoader::cancel() { |
| 132 didFail( | 130 handleError( |
| 133 ResourceError::cancelledError(m_resource->lastResourceRequest().url())); | 131 ResourceError::cancelledError(m_resource->lastResourceRequest().url())); |
| 134 } | 132 } |
| 135 | 133 |
| 136 void ResourceLoader::cancelForRedirectAccessCheckError(const KURL& newURL) { | 134 void ResourceLoader::cancelForRedirectAccessCheckError(const KURL& newURL) { |
| 137 m_resource->willNotFollowRedirect(); | 135 m_resource->willNotFollowRedirect(); |
| 138 | 136 |
| 139 if (m_loader) | 137 if (m_loader) |
| 140 didFail(ResourceError::cancelledDueToAccessCheckError(newURL)); | 138 handleError(ResourceError::cancelledDueToAccessCheckError(newURL)); |
| 139 } | |
| 140 | |
| 141 static bool isManualRedirectFetchRequest(const ResourceRequest& request) { | |
| 142 return request.fetchRedirectMode() == | |
| 143 WebURLRequest::FetchRedirectModeManual && | |
| 144 request.requestContext() == WebURLRequest::RequestContextFetch; | |
| 141 } | 145 } |
| 142 | 146 |
| 143 bool ResourceLoader::willFollowRedirect( | 147 bool ResourceLoader::willFollowRedirect( |
| 144 WebURLRequest& passedNewRequest, | 148 WebURLRequest& passedNewRequest, |
| 145 const WebURLResponse& passedRedirectResponse) { | 149 const WebURLResponse& passedRedirectResponse) { |
| 146 DCHECK(!passedNewRequest.isNull()); | 150 DCHECK(!passedNewRequest.isNull()); |
| 147 DCHECK(!passedRedirectResponse.isNull()); | 151 DCHECK(!passedRedirectResponse.isNull()); |
| 148 | 152 |
| 149 if (m_isCacheAwareLoadingActivated) { | 153 if (m_isCacheAwareLoadingActivated) { |
| 150 // Fail as cache miss if cached response is a redirect. | 154 // Fail as cache miss if cached response is a redirect. |
| 151 didFail( | 155 handleError( |
| 152 ResourceError::cacheMissError(m_resource->lastResourceRequest().url())); | 156 ResourceError::cacheMissError(m_resource->lastResourceRequest().url())); |
| 153 return false; | 157 return false; |
| 154 } | 158 } |
| 155 | 159 |
| 156 ResourceRequest& newRequest(passedNewRequest.toMutableResourceRequest()); | 160 ResourceRequest& newRequest(passedNewRequest.toMutableResourceRequest()); |
| 157 const ResourceResponse& redirectResponse( | 161 const ResourceResponse& redirectResponse( |
| 158 passedRedirectResponse.toResourceResponse()); | 162 passedRedirectResponse.toResourceResponse()); |
| 163 | |
| 159 newRequest.setRedirectStatus( | 164 newRequest.setRedirectStatus( |
| 160 ResourceRequest::RedirectStatus::FollowedRedirect); | 165 ResourceRequest::RedirectStatus::FollowedRedirect); |
| 161 | 166 |
| 162 const KURL originalURL = newRequest.url(); | 167 const KURL originalURL = newRequest.url(); |
| 163 | 168 |
| 164 if (!m_fetcher->willFollowRedirect(m_resource.get(), newRequest, | 169 if (!isManualRedirectFetchRequest(m_resource->resourceRequest())) { |
| 165 redirectResponse)) { | 170 if (!context().canRequest( |
| 166 cancelForRedirectAccessCheckError(newRequest.url()); | 171 m_resource->getType(), newRequest, newRequest.url(), |
| 167 return false; | 172 m_resource->options(), m_resource->isUnusedPreload(), |
| 173 FetchRequest::UseDefaultOriginRestrictionForType)) { | |
| 174 cancelForRedirectAccessCheckError(newRequest.url()); | |
| 175 return false; | |
| 176 } | |
| 177 | |
| 178 if (m_resource->options().corsEnabled == IsCORSEnabled) { | |
| 179 RefPtr<SecurityOrigin> sourceOrigin = | |
| 180 m_resource->options().securityOrigin; | |
| 181 if (!sourceOrigin.get()) | |
| 182 sourceOrigin = context().getSecurityOrigin(); | |
| 183 | |
| 184 String errorMessage; | |
| 185 StoredCredentials withCredentials = | |
| 186 m_resource->lastResourceRequest().allowStoredCredentials() | |
| 187 ? AllowStoredCredentials | |
| 188 : DoNotAllowStoredCredentials; | |
| 189 if (!CrossOriginAccessControl::handleRedirect( | |
| 190 sourceOrigin, newRequest, redirectResponse, withCredentials, | |
| 191 m_resource->mutableOptions(), errorMessage)) { | |
| 192 m_resource->setCORSFailed(); | |
| 193 context().addConsoleMessage(errorMessage); | |
| 194 cancelForRedirectAccessCheckError(newRequest.url()); | |
| 195 return false; | |
| 196 } | |
| 197 } | |
| 198 if (m_resource->getType() == Resource::Image && | |
| 199 m_fetcher->shouldDeferImageLoad(newRequest.url())) { | |
| 200 cancelForRedirectAccessCheckError(newRequest.url()); | |
| 201 return false; | |
| 202 } | |
| 168 } | 203 } |
| 169 | 204 |
| 205 bool crossOrigin = | |
| 206 !SecurityOrigin::areSameOrigin(redirectResponse.url(), newRequest.url()); | |
| 207 m_fetcher->recordResourceTimingOnRedirect(m_resource.get(), redirectResponse, | |
| 208 crossOrigin); | |
| 209 | |
| 210 newRequest.setAllowStoredCredentials(m_resource->options().allowCredentials == | |
| 211 AllowStoredCredentials); | |
| 212 | |
| 213 context().dispatchWillSendRequest(m_resource->identifier(), newRequest, | |
| 214 redirectResponse, | |
| 215 m_resource->options().initiatorInfo); | |
| 216 | |
| 170 // ResourceFetcher::willFollowRedirect() may rewrite the URL to | 217 // ResourceFetcher::willFollowRedirect() may rewrite the URL to |
| 171 // something else not for rejecting redirect but for other reasons. | 218 // something else not for rejecting redirect but for other reasons. |
| 172 // E.g. WebFrameTestClient::willSendRequest() and | 219 // E.g. WebFrameTestClient::willSendRequest() and |
| 173 // RenderFrameImpl::willSendRequest(). We should reflect the | 220 // RenderFrameImpl::willSendRequest(). We should reflect the |
| 174 // rewriting but currently we cannot. So, return false to make the | 221 // rewriting but currently we cannot. So, return false to make the |
| 175 // redirect fail. | 222 // redirect fail. |
| 176 if (newRequest.url() != originalURL) { | 223 if (newRequest.url() != originalURL) { |
| 177 cancelForRedirectAccessCheckError(newRequest.url()); | 224 cancelForRedirectAccessCheckError(newRequest.url()); |
| 178 return false; | 225 return false; |
| 179 } | 226 } |
| 180 | 227 |
| 181 if (!m_resource->willFollowRedirect(newRequest, redirectResponse)) { | 228 if (!m_resource->willFollowRedirect(newRequest, redirectResponse)) { |
| 182 cancelForRedirectAccessCheckError(newRequest.url()); | 229 cancelForRedirectAccessCheckError(newRequest.url()); |
| 183 return false; | 230 return false; |
| 184 } | 231 } |
| 185 | 232 |
| 186 return true; | 233 return true; |
| 187 } | 234 } |
| 188 | 235 |
| 189 void ResourceLoader::didReceiveCachedMetadata(const char* data, int length) { | 236 void ResourceLoader::didReceiveCachedMetadata(const char* data, int length) { |
| 190 m_resource->setSerializedCachedMetadata(data, length); | 237 m_resource->setSerializedCachedMetadata(data, length); |
| 191 } | 238 } |
| 192 | 239 |
| 193 void ResourceLoader::didSendData(unsigned long long bytesSent, | 240 void ResourceLoader::didSendData(unsigned long long bytesSent, |
| 194 unsigned long long totalBytesToBeSent) { | 241 unsigned long long totalBytesToBeSent) { |
| 195 m_resource->didSendData(bytesSent, totalBytesToBeSent); | 242 m_resource->didSendData(bytesSent, totalBytesToBeSent); |
| 196 } | 243 } |
| 197 | 244 |
| 245 FetchContext& ResourceLoader::context() const { | |
| 246 return m_fetcher->context(); | |
| 247 } | |
| 248 | |
| 249 bool ResourceLoader::canAccessResponse(Resource* resource, | |
| 250 const ResourceResponse& response) const { | |
| 251 // Redirects can change the response URL different from one of request. | |
| 252 bool forPreload = resource->isUnusedPreload(); | |
| 253 if (!context().canRequest(resource->getType(), resource->resourceRequest(), | |
| 254 response.url(), resource->options(), forPreload, | |
| 255 FetchRequest::UseDefaultOriginRestrictionForType)) | |
| 256 return false; | |
| 257 | |
| 258 SecurityOrigin* sourceOrigin = resource->options().securityOrigin.get(); | |
| 259 if (!sourceOrigin) | |
| 260 sourceOrigin = context().getSecurityOrigin(); | |
| 261 | |
| 262 if (sourceOrigin->canRequestNoSuborigin(response.url())) | |
| 263 return true; | |
| 264 | |
| 265 // Use the original response instead of the 304 response for a successful | |
| 266 // revaldiation. | |
| 267 const ResourceResponse& responseForAccessControl = | |
| 268 (resource->isCacheValidator() && response.httpStatusCode() == 304) | |
| 269 ? resource->response() | |
| 270 : response; | |
| 271 String errorDescription; | |
| 272 if (!passesAccessControlCheck( | |
| 273 responseForAccessControl, resource->options().allowCredentials, | |
| 274 sourceOrigin, errorDescription, | |
| 275 resource->lastResourceRequest().requestContext())) { | |
| 276 resource->setCORSFailed(); | |
| 277 if (!forPreload) { | |
| 278 String resourceType = Resource::resourceTypeToString( | |
| 279 resource->getType(), resource->options().initiatorInfo); | |
| 280 context().addConsoleMessage( | |
| 281 "Access to " + resourceType + " at '" + response.url().getString() + | |
| 282 "' from origin '" + sourceOrigin->toString() + | |
| 283 "' has been blocked by CORS policy: " + errorDescription); | |
| 284 } | |
| 285 return false; | |
| 286 } | |
| 287 return true; | |
| 288 } | |
| 289 | |
| 198 void ResourceLoader::didReceiveResponse( | 290 void ResourceLoader::didReceiveResponse( |
| 199 const WebURLResponse& response, | 291 const WebURLResponse& webURLResponse, |
| 200 std::unique_ptr<WebDataConsumerHandle> handle) { | 292 std::unique_ptr<WebDataConsumerHandle> handle) { |
| 201 DCHECK(!response.isNull()); | 293 DCHECK(!webURLResponse.isNull()); |
| 202 m_fetcher->didReceiveResponse(m_resource.get(), response.toResourceResponse(), | 294 |
| 203 std::move(handle)); | 295 const ResourceResponse& response = webURLResponse.toResourceResponse(); |
| 296 | |
| 297 if (response.wasFetchedViaServiceWorker()) { | |
| 298 if (m_resource->options().corsEnabled == IsCORSEnabled && | |
| 299 response.wasFallbackRequiredByServiceWorker()) { | |
| 300 ResourceRequest request = m_resource->lastResourceRequest(); | |
| 301 DCHECK_EQ(request.skipServiceWorker(), | |
| 302 WebURLRequest::SkipServiceWorker::None); | |
| 303 // This code handles the case when a regular controlling service worker | |
| 304 // doesn't handle a cross origin request. When this happens we still want | |
| 305 // to give foreign fetch a chance to handle the request, so only skip the | |
| 306 // controlling service worker for the fallback request. This is currently | |
| 307 // safe because of http://crbug.com/604084 the | |
| 308 // wasFallbackRequiredByServiceWorker flag is never set when foreign fetch | |
| 309 // handled a request. | |
| 310 if (!context().shouldLoadNewResource(m_resource->getType())) { | |
| 311 // Cancel the request if we should not trigger a reload now. | |
| 312 handleError(ResourceError::cancelledError(response.url())); | |
| 313 return; | |
| 314 } | |
| 315 request.setSkipServiceWorker( | |
| 316 WebURLRequest::SkipServiceWorker::Controlling); | |
| 317 restart(request); | |
| 318 return; | |
| 319 } | |
| 320 | |
| 321 // If the response is fetched via ServiceWorker, the original URL of the | |
| 322 // response could be different from the URL of the request. We check the URL | |
| 323 // not to load the resources which are forbidden by the page CSP. | |
| 324 // https://w3c.github.io/webappsec-csp/#should-block-response | |
| 325 const KURL& originalURL = response.originalURLViaServiceWorker(); | |
| 326 if (!originalURL.isEmpty() && | |
| 327 !context().allowResponse(m_resource->getType(), | |
| 328 m_resource->resourceRequest(), originalURL, | |
| 329 m_resource->options())) { | |
| 330 handleError(ResourceError::cancelledDueToAccessCheckError(originalURL)); | |
| 331 return; | |
| 332 } | |
| 333 } else if (m_resource->options().corsEnabled == IsCORSEnabled && | |
| 334 !canAccessResponse(m_resource, response)) { | |
| 335 handleError(ResourceError::cancelledDueToAccessCheckError(response.url())); | |
| 336 return; | |
| 337 } | |
| 338 | |
| 339 context().dispatchDidReceiveResponse( | |
| 340 m_resource->identifier(), response, | |
| 341 m_resource->resourceRequest().frameType(), | |
| 342 m_resource->resourceRequest().requestContext(), m_resource); | |
| 343 | |
| 344 Resource* resource = m_resource.get(); | |
| 345 resource->responseReceived(response, std::move(handle)); | |
| 346 if (!resource->loader()) | |
|
Nate Chapin
2016/12/07 19:13:00
Rather than stashing a Resource* here, could we ch
tyoshino (SeeGerritForStatus)
2016/12/12 11:10:55
I just noticed that the ResourceLoader is garbage
| |
| 347 return; | |
| 348 | |
| 349 if (response.httpStatusCode() >= 400 && | |
| 350 !m_resource->shouldIgnoreHTTPStatusCodeErrors()) { | |
| 351 handleError(ResourceError::cancelledError(response.url())); | |
| 352 } | |
| 204 } | 353 } |
| 205 | 354 |
| 206 void ResourceLoader::didReceiveResponse(const WebURLResponse& response) { | 355 void ResourceLoader::didReceiveResponse(const WebURLResponse& response) { |
| 207 didReceiveResponse(response, nullptr); | 356 didReceiveResponse(response, nullptr); |
| 208 } | 357 } |
| 209 | 358 |
| 359 void ResourceLoader::didDownloadData(int length, int encodedDataLength) { | |
| 360 context().dispatchDidDownloadData(m_resource->identifier(), length, | |
| 361 encodedDataLength); | |
| 362 m_resource->didDownloadData(length); | |
| 363 } | |
| 364 | |
| 210 void ResourceLoader::didReceiveData(const char* data, | 365 void ResourceLoader::didReceiveData(const char* data, |
| 211 int length, | 366 int length, |
| 212 int encodedDataLength) { | 367 int encodedDataLength) { |
| 213 CHECK_GE(length, 0); | 368 CHECK_GE(length, 0); |
| 214 m_fetcher->didReceiveData(m_resource.get(), data, length, encodedDataLength); | 369 |
| 370 context().dispatchDidReceiveData(m_resource->identifier(), data, length, | |
| 371 encodedDataLength); | |
|
kinuko
2016/12/09 02:03:19
This still bothers me a bit (I would be confused b
tyoshino (SeeGerritForStatus)
2016/12/12 11:10:55
Done
| |
| 215 m_resource->addToDecodedBodyLength(length); | 372 m_resource->addToDecodedBodyLength(length); |
| 216 m_resource->appendData(data, length); | 373 m_resource->appendData(data, length); |
| 217 } | 374 } |
| 218 | 375 |
| 219 void ResourceLoader::didFinishLoadingFirstPartInMultipart() { | 376 void ResourceLoader::didFinishLoadingFirstPartInMultipart() { |
| 220 m_fetcher->didFinishLoading(m_resource.get(), 0, | 377 network_instrumentation::endResourceLoad( |
| 221 ResourceFetcher::DidFinishFirstPartInMultipart); | 378 m_resource->identifier(), |
| 379 network_instrumentation::RequestOutcome::Success); | |
| 380 | |
| 381 m_fetcher->handleLoaderFinish(m_resource.get(), 0, | |
| 382 ResourceFetcher::DidFinishFirstPartInMultipart); | |
| 222 } | 383 } |
| 223 | 384 |
| 224 void ResourceLoader::didFinishLoading(double finishTime, | 385 void ResourceLoader::didFinishLoading(double finishTime, |
| 225 int64_t encodedDataLength, | 386 int64_t encodedDataLength, |
| 226 int64_t encodedBodyLength) { | 387 int64_t encodedBodyLength) { |
| 227 m_resource->setEncodedDataLength(encodedDataLength); | 388 m_resource->setEncodedDataLength(encodedDataLength); |
| 228 m_resource->addToEncodedBodyLength(encodedBodyLength); | 389 m_resource->addToEncodedBodyLength(encodedBodyLength); |
| 390 | |
| 229 m_loader.reset(); | 391 m_loader.reset(); |
| 230 m_fetcher->didFinishLoading(m_resource.get(), finishTime, | 392 |
| 231 ResourceFetcher::DidFinishLoading); | 393 network_instrumentation::endResourceLoad( |
| 394 m_resource->identifier(), | |
| 395 network_instrumentation::RequestOutcome::Success); | |
| 396 | |
| 397 m_fetcher->handleLoaderFinish(m_resource.get(), finishTime, | |
| 398 ResourceFetcher::DidFinishLoading); | |
| 399 // |this| is dead here. | |
|
yhirano
2016/12/12 06:32:04
No, |this| is not dead, in terms of use-after-free
tyoshino (SeeGerritForStatus)
2016/12/12 11:10:55
Removed!
| |
| 232 } | 400 } |
| 233 | 401 |
| 234 void ResourceLoader::didFail(const WebURLError& error, | 402 void ResourceLoader::didFail(const WebURLError& error, |
| 235 int64_t encodedDataLength, | 403 int64_t encodedDataLength, |
| 236 int64_t encodedBodyLength) { | 404 int64_t encodedBodyLength) { |
| 237 m_resource->setEncodedDataLength(encodedDataLength); | 405 m_resource->setEncodedDataLength(encodedDataLength); |
| 238 m_resource->addToEncodedBodyLength(encodedBodyLength); | 406 m_resource->addToEncodedBodyLength(encodedBodyLength); |
| 239 didFail(error); | 407 handleError(error); |
| 240 } | 408 } |
| 241 | 409 |
| 242 void ResourceLoader::didFail(const ResourceError& error) { | 410 void ResourceLoader::handleError(const ResourceError& error) { |
| 243 if (m_isCacheAwareLoadingActivated && error.isCacheMiss() && | 411 if (m_isCacheAwareLoadingActivated && error.isCacheMiss() && |
| 244 m_fetcher->context().shouldLoadNewResource(m_resource->getType())) { | 412 context().shouldLoadNewResource(m_resource->getType())) { |
| 245 m_resource->willReloadAfterDiskCacheMiss(); | 413 m_resource->willReloadAfterDiskCacheMiss(); |
| 246 m_isCacheAwareLoadingActivated = false; | 414 m_isCacheAwareLoadingActivated = false; |
| 247 restart(m_resource->resourceRequest(), | 415 restart(m_resource->resourceRequest()); |
| 248 m_fetcher->context().loadingTaskRunner(), | |
| 249 m_fetcher->context().defersLoading()); | |
| 250 return; | 416 return; |
| 251 } | 417 } |
| 252 | 418 |
| 253 m_loader.reset(); | 419 m_loader.reset(); |
| 254 m_fetcher->didFailLoading(m_resource.get(), error); | 420 |
| 421 network_instrumentation::endResourceLoad( | |
| 422 m_resource->identifier(), network_instrumentation::RequestOutcome::Fail); | |
| 423 | |
| 424 m_fetcher->handleLoaderError(m_resource.get(), error); | |
| 425 // |this| is dead here. | |
|
yhirano
2016/12/12 06:32:04
Ditto
tyoshino (SeeGerritForStatus)
2016/12/12 11:10:55
Removed! Right, it's garbage collected.
| |
| 255 } | 426 } |
| 256 | 427 |
| 257 void ResourceLoader::requestSynchronously(const ResourceRequest& request) { | 428 void ResourceLoader::requestSynchronously(const ResourceRequest& request) { |
| 258 // downloadToFile is not supported for synchronous requests. | 429 // downloadToFile is not supported for synchronous requests. |
| 259 DCHECK(!request.downloadToFile()); | 430 DCHECK(!request.downloadToFile()); |
| 260 DCHECK(m_loader); | 431 DCHECK(m_loader); |
| 261 DCHECK_EQ(request.priority(), ResourceLoadPriorityHighest); | 432 DCHECK_EQ(request.priority(), ResourceLoadPriorityHighest); |
| 262 | 433 |
| 263 WrappedResourceRequest requestIn(request); | 434 WrappedResourceRequest requestIn(request); |
| 264 WebURLResponse responseOut; | 435 WebURLResponse responseOut; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 280 didReceiveResponse(responseOut); | 451 didReceiveResponse(responseOut); |
| 281 if (!m_loader) | 452 if (!m_loader) |
| 282 return; | 453 return; |
| 283 DCHECK_GE(responseOut.toResourceResponse().encodedBodyLength(), 0); | 454 DCHECK_GE(responseOut.toResourceResponse().encodedBodyLength(), 0); |
| 284 | 455 |
| 285 // Follow the async case convention of not calling didReceiveData or | 456 // Follow the async case convention of not calling didReceiveData or |
| 286 // appending data to m_resource if the response body is empty. Copying the | 457 // appending data to m_resource if the response body is empty. Copying the |
| 287 // empty buffer is a noop in most cases, but is destructive in the case of | 458 // empty buffer is a noop in most cases, but is destructive in the case of |
| 288 // a 304, where it will overwrite the cached data we should be reusing. | 459 // a 304, where it will overwrite the cached data we should be reusing. |
| 289 if (dataOut.size()) { | 460 if (dataOut.size()) { |
| 290 m_fetcher->didReceiveData(m_resource.get(), dataOut.data(), dataOut.size(), | 461 context().dispatchDidReceiveData(m_resource->identifier(), dataOut.data(), |
| 291 encodedDataLength); | 462 dataOut.size(), encodedDataLength); |
| 292 m_resource->setResourceBuffer(dataOut); | 463 m_resource->setResourceBuffer(dataOut); |
| 293 } | 464 } |
| 294 didFinishLoading(monotonicallyIncreasingTime(), encodedDataLength, | 465 didFinishLoading(monotonicallyIncreasingTime(), encodedDataLength, |
| 295 encodedBodyLength); | 466 encodedBodyLength); |
| 296 } | 467 } |
| 297 | 468 |
| 298 void ResourceLoader::activateCacheAwareLoadingIfNeeded( | 469 void ResourceLoader::activateCacheAwareLoadingIfNeeded( |
| 299 const ResourceRequest& request) { | 470 const ResourceRequest& request) { |
| 300 DCHECK(!m_isCacheAwareLoadingActivated); | 471 DCHECK(!m_isCacheAwareLoadingActivated); |
| 301 | 472 |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 312 return; | 483 return; |
| 313 | 484 |
| 314 // Don't activate if cache policy is explicitly set. | 485 // Don't activate if cache policy is explicitly set. |
| 315 if (request.getCachePolicy() != WebCachePolicy::UseProtocolCachePolicy) | 486 if (request.getCachePolicy() != WebCachePolicy::UseProtocolCachePolicy) |
| 316 return; | 487 return; |
| 317 | 488 |
| 318 m_isCacheAwareLoadingActivated = true; | 489 m_isCacheAwareLoadingActivated = true; |
| 319 } | 490 } |
| 320 | 491 |
| 321 } // namespace blink | 492 } // namespace blink |
| OLD | NEW |