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

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

Issue 1926193002: Clean up ResourceLoader finish more, remove ConnectionState enum (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@finish_smaller
Patch Set: Created 4 years, 7 months 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) 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 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 47
48 namespace blink { 48 namespace blink {
49 49
50 ResourceLoader* ResourceLoader::create(ResourceFetcher* fetcher, Resource* resou rce) 50 ResourceLoader* ResourceLoader::create(ResourceFetcher* fetcher, Resource* resou rce)
51 { 51 {
52 return new ResourceLoader(fetcher, resource); 52 return new ResourceLoader(fetcher, resource);
53 } 53 }
54 54
55 ResourceLoader::ResourceLoader(ResourceFetcher* fetcher, Resource* resource) 55 ResourceLoader::ResourceLoader(ResourceFetcher* fetcher, Resource* resource)
56 : m_fetcher(fetcher) 56 : m_fetcher(fetcher)
57 , m_notifiedLoadComplete(false)
Nate Chapin 2016/05/12 20:51:12 Like didFailLoading(), didFinishLoading() should n
58 , m_resource(resource) 57 , m_resource(resource)
59 , m_state(ConnectionStateNew)
60 { 58 {
61 ASSERT(m_resource); 59 ASSERT(m_resource);
62 ASSERT(m_fetcher); 60 ASSERT(m_fetcher);
63 } 61 }
64 62
65 ResourceLoader::~ResourceLoader() 63 ResourceLoader::~ResourceLoader()
66 { 64 {
67 ASSERT(m_state == ConnectionStateReleased); 65 ASSERT(!m_loader);
68 } 66 }
69 67
70 DEFINE_TRACE(ResourceLoader) 68 DEFINE_TRACE(ResourceLoader)
71 { 69 {
72 visitor->trace(m_fetcher); 70 visitor->trace(m_fetcher);
73 visitor->trace(m_resource); 71 visitor->trace(m_resource);
74 } 72 }
75 73
76 void ResourceLoader::releaseResources()
Nate Chapin 2016/05/12 20:51:12 didLoadResource() moved to ResourceFetcher's didFi
77 {
78 ASSERT(m_state != ConnectionStateReleased);
79 ASSERT(m_notifiedLoadComplete);
80 m_fetcher->didLoadResource(m_resource.get());
81 ASSERT(m_state != ConnectionStateReleased);
82 m_resource = nullptr;
83 m_state = ConnectionStateReleased;
84 if (m_loader) {
85 m_loader->cancel();
86 m_loader.clear();
87 }
88 m_fetcher.clear();
89 }
90
91 void ResourceLoader::start(ResourceRequest& request) 74 void ResourceLoader::start(ResourceRequest& request)
92 { 75 {
93 ASSERT(!m_loader); 76 ASSERT(!m_loader);
94 77
95 m_fetcher->willStartLoadingResource(m_resource.get(), this, request); 78 m_fetcher->willStartLoadingResource(m_resource.get(), this, request);
96 RELEASE_ASSERT(m_state == ConnectionStateNew);
97 m_state = ConnectionStateStarted;
98
99 m_loader = adoptPtr(Platform::current()->createURLLoader()); 79 m_loader = adoptPtr(Platform::current()->createURLLoader());
100 m_loader->setDefersLoading(m_fetcher->defersLoading()); 80 m_loader->setDefersLoading(m_fetcher->defersLoading());
101 ASSERT(m_loader); 81 ASSERT(m_loader);
102 m_loader->setLoadingTaskRunner(m_fetcher->loadingTaskRunner()); 82 m_loader->setLoadingTaskRunner(m_fetcher->loadingTaskRunner());
103 83
104 if (m_resource->options().synchronousPolicy == RequestSynchronously) 84 if (m_resource->options().synchronousPolicy == RequestSynchronously)
105 requestSynchronously(request); 85 requestSynchronously(request);
106 else 86 else
107 m_loader->loadAsynchronously(WrappedResourceRequest(request), this); 87 m_loader->loadAsynchronously(WrappedResourceRequest(request), this);
108 } 88 }
109 89
110 void ResourceLoader::setDefersLoading(bool defers) 90 void ResourceLoader::setDefersLoading(bool defers)
111 { 91 {
112 ASSERT(m_loader); 92 ASSERT(m_loader);
113 m_loader->setDefersLoading(defers); 93 m_loader->setDefersLoading(defers);
114 } 94 }
115 95
116 void ResourceLoader::didDownloadData(WebURLLoader*, int length, int encodedDataL ength) 96 void ResourceLoader::didDownloadData(WebURLLoader*, int length, int encodedDataL ength)
117 { 97 {
118 RELEASE_ASSERT(m_state == ConnectionStateReceivedResponse);
Nate Chapin 2016/05/12 20:51:12 If you're not ok with dropping all these ASSERTs,
119 m_fetcher->didDownloadData(m_resource.get(), length, encodedDataLength); 98 m_fetcher->didDownloadData(m_resource.get(), length, encodedDataLength);
120 if (m_state == ConnectionStateReleased)
121 return;
122 m_resource->didDownloadData(length); 99 m_resource->didDownloadData(length);
123 } 100 }
124 101
125 void ResourceLoader::didFinishLoadingOnePart(double finishTime, int64_t encodedD ataLength)
126 {
127 ASSERT(m_state != ConnectionStateReleased);
128 if (m_state == ConnectionStateFinishedLoading) {
Nate Chapin 2016/05/12 20:51:12 This block is in ResourceFetcher::didFinishLoading
129 m_fetcher->removeResourceLoader(this);
130 } else {
131 // When loading a multipart resource, make the loader non-block when
132 // finishing loading the first part.
133 m_fetcher->moveResourceLoaderToNonBlocking(this);
134
135 m_fetcher->didLoadResource(m_resource.get());
136 if (m_state == ConnectionStateReleased)
137 return;
138 }
139
140 if (m_notifiedLoadComplete)
141 return;
142 m_notifiedLoadComplete = true;
143 m_fetcher->didFinishLoading(m_resource.get(), finishTime, encodedDataLength) ;
144 }
145
146 void ResourceLoader::didChangePriority(ResourceLoadPriority loadPriority, int in traPriorityValue) 102 void ResourceLoader::didChangePriority(ResourceLoadPriority loadPriority, int in traPriorityValue)
147 { 103 {
148 ASSERT(m_state != ConnectionStateReleased);
149 if (m_loader) 104 if (m_loader)
150 m_loader->didChangePriority(static_cast<WebURLRequest::Priority>(loadPri ority), intraPriorityValue); 105 m_loader->didChangePriority(static_cast<WebURLRequest::Priority>(loadPri ority), intraPriorityValue);
151 } 106 }
152 107
153 void ResourceLoader::cancel() 108 void ResourceLoader::cancel()
154 { 109 {
155 cancel(ResourceError()); 110 didFail(nullptr, ResourceError::cancelledError(m_resource->lastResourceReque st().url()));
156 }
157
158 void ResourceLoader::cancel(const ResourceError& error)
159 {
160 ASSERT(m_state != ConnectionStateFinishedLoading);
161 ASSERT(m_state != ConnectionStateReleased);
162
163 // If we don't immediately clear m_loader when cancelling, we might get
164 // unexpected reentrancy. m_resource->error() can trigger JS events, which
165 // could start a modal dialog. Normally, a modal dialog would defer loading
166 // and prevent receiving messages for a cancelled ResourceLoader, but
167 // m_fetcher->didFailLoading() severs the connection by which all of a
168 // page's loads are deferred. A response can then arrive, see m_state
169 // is ConnectionStateFinishedLoading, and ASSERT or break in other ways.
170 if (m_loader) {
Nate Chapin 2016/05/12 20:51:12 Because didFail() now starts by clearing m_loader,
171 m_loader->cancel();
172 m_loader.clear();
173 }
174 didFail(nullptr, error.isNull() ? ResourceError::cancelledError(m_resource-> lastResourceRequest().url()) : error);
175 } 111 }
176 112
177 void ResourceLoader::willFollowRedirect(WebURLLoader*, WebURLRequest& passedNewR equest, const WebURLResponse& passedRedirectResponse) 113 void ResourceLoader::willFollowRedirect(WebURLLoader*, WebURLRequest& passedNewR equest, const WebURLResponse& passedRedirectResponse)
178 { 114 {
179 ASSERT(m_state != ConnectionStateReleased);
180 ASSERT(!passedNewRequest.isNull()); 115 ASSERT(!passedNewRequest.isNull());
181 ASSERT(!passedRedirectResponse.isNull()); 116 ASSERT(!passedRedirectResponse.isNull());
182 117
183 ResourceRequest& newRequest(passedNewRequest.toMutableResourceRequest()); 118 ResourceRequest& newRequest(passedNewRequest.toMutableResourceRequest());
184 const ResourceResponse& redirectResponse(passedRedirectResponse.toResourceRe sponse()); 119 const ResourceResponse& redirectResponse(passedRedirectResponse.toResourceRe sponse());
185 newRequest.setFollowedRedirect(true); 120 newRequest.setFollowedRedirect(true);
186 121
187 if (m_fetcher->willFollowRedirect(m_resource.get(), newRequest, redirectResp onse)) { 122 if (m_fetcher->willFollowRedirect(m_resource.get(), newRequest, redirectResp onse)) {
188 m_resource->willFollowRedirect(newRequest, redirectResponse); 123 m_resource->willFollowRedirect(newRequest, redirectResponse);
189 } else { 124 } else {
190 m_resource->willNotFollowRedirect(); 125 m_resource->willNotFollowRedirect();
191 if (m_state != ConnectionStateReleased) 126 if (m_loader)
192 cancel(ResourceError::cancelledDueToAccessCheckError(newRequest.url( ))); 127 didFail(nullptr, ResourceError::cancelledDueToAccessCheckError(newRe quest.url()));
193 } 128 }
194 } 129 }
195 130
196 void ResourceLoader::didReceiveCachedMetadata(WebURLLoader*, const char* data, i nt length) 131 void ResourceLoader::didReceiveCachedMetadata(WebURLLoader*, const char* data, i nt length)
197 { 132 {
198 RELEASE_ASSERT(m_state == ConnectionStateReceivedResponse || m_state == Conn ectionStateReceivingData);
199 m_resource->setSerializedCachedMetadata(data, length); 133 m_resource->setSerializedCachedMetadata(data, length);
200 } 134 }
201 135
202 void ResourceLoader::didSendData(WebURLLoader*, unsigned long long bytesSent, un signed long long totalBytesToBeSent) 136 void ResourceLoader::didSendData(WebURLLoader*, unsigned long long bytesSent, un signed long long totalBytesToBeSent)
203 { 137 {
204 m_resource->didSendData(bytesSent, totalBytesToBeSent); 138 m_resource->didSendData(bytesSent, totalBytesToBeSent);
205 } 139 }
206 140
207 bool ResourceLoader::responseNeedsAccessControlCheck() const 141 bool ResourceLoader::responseNeedsAccessControlCheck() const
208 { 142 {
209 // If the fetch was (potentially) CORS enabled, an access control check of t he response is required. 143 // If the fetch was (potentially) CORS enabled, an access control check of t he response is required.
210 return m_resource->options().corsEnabled == IsCORSEnabled; 144 return m_resource->options().corsEnabled == IsCORSEnabled;
211 } 145 }
212 146
213 void ResourceLoader::didReceiveResponse(WebURLLoader*, const WebURLResponse& res ponse, WebDataConsumerHandle* rawHandle) 147 void ResourceLoader::didReceiveResponse(WebURLLoader*, const WebURLResponse& res ponse, WebDataConsumerHandle* rawHandle)
214 { 148 {
215 ASSERT(!response.isNull()); 149 ASSERT(!response.isNull());
216 // |rawHandle|'s ownership is transferred to the callee. 150 // |rawHandle|'s ownership is transferred to the callee.
217 OwnPtr<WebDataConsumerHandle> handle = adoptPtr(rawHandle); 151 OwnPtr<WebDataConsumerHandle> handle = adoptPtr(rawHandle);
218
219 bool isValidStateTransition = (m_state == ConnectionStateStarted || m_state == ConnectionStateReceivedResponse);
220 RELEASE_ASSERT(isValidStateTransition);
221 m_state = ConnectionStateReceivedResponse;
222
223 const ResourceResponse& resourceResponse = response.toResourceResponse(); 152 const ResourceResponse& resourceResponse = response.toResourceResponse();
224 153
225 if (responseNeedsAccessControlCheck()) { 154 if (responseNeedsAccessControlCheck()) {
226 if (response.wasFetchedViaServiceWorker()) { 155 if (response.wasFetchedViaServiceWorker()) {
227 if (response.wasFallbackRequiredByServiceWorker()) { 156 if (response.wasFallbackRequiredByServiceWorker()) {
228 m_loader->cancel();
229 m_loader.clear(); 157 m_loader.clear();
230 m_state = ConnectionStateStarted;
231 m_loader = adoptPtr(Platform::current()->createURLLoader()); 158 m_loader = adoptPtr(Platform::current()->createURLLoader());
232 ASSERT(m_loader); 159 ASSERT(m_loader);
233 ResourceRequest request = m_resource->lastResourceRequest(); 160 ResourceRequest request = m_resource->lastResourceRequest();
234 ASSERT(!request.skipServiceWorker()); 161 ASSERT(!request.skipServiceWorker());
235 request.setSkipServiceWorker(true); 162 request.setSkipServiceWorker(true);
236 m_loader->loadAsynchronously(WrappedResourceRequest(request), th is); 163 m_loader->loadAsynchronously(WrappedResourceRequest(request), th is);
237 return; 164 return;
238 } 165 }
239 } else { 166 } else {
240 if (!m_resource->isCacheValidator() || resourceResponse.httpStatusCo de() != 304) 167 if (!m_resource->isCacheValidator() || resourceResponse.httpStatusCo de() != 304)
241 m_resource->setResponse(resourceResponse); 168 m_resource->setResponse(resourceResponse);
242 if (!m_fetcher->canAccessResource(m_resource.get(), m_resource->opti ons().securityOrigin.get(), response.url(), ResourceFetcher::ShouldLogAccessCont rolErrors)) { 169 if (!m_fetcher->canAccessResource(m_resource.get(), m_resource->opti ons().securityOrigin.get(), response.url(), ResourceFetcher::ShouldLogAccessCont rolErrors)) {
243 m_fetcher->didReceiveResponse(m_resource.get(), resourceResponse ); 170 m_fetcher->didReceiveResponse(m_resource.get(), resourceResponse );
244 cancel(ResourceError::cancelledDueToAccessCheckError(KURL(respon se.url()))); 171 didFail(nullptr, ResourceError::cancelledDueToAccessCheckError(K URL(response.url())));
245 return; 172 return;
246 } 173 }
247 } 174 }
248 } 175 }
249 176
250 m_resource->responseReceived(resourceResponse, handle.release()); 177 m_resource->responseReceived(resourceResponse, handle.release());
251 if (m_state == ConnectionStateReleased) 178 if (!m_loader)
252 return; 179 return;
253 180
254 m_fetcher->didReceiveResponse(m_resource.get(), resourceResponse); 181 m_fetcher->didReceiveResponse(m_resource.get(), resourceResponse);
255 if (m_state == ConnectionStateReleased) 182 if (!m_loader)
256 return; 183 return;
257 184
258 if (m_resource->response().httpStatusCode() < 400 || m_resource->shouldIgnor eHTTPStatusCodeErrors()) 185 if (m_resource->response().httpStatusCode() < 400 || m_resource->shouldIgnor eHTTPStatusCodeErrors())
259 return; 186 return;
260 cancel(ResourceError::cancelledError(resourceResponse.url())); 187 didFail(nullptr, ResourceError::cancelledError(resourceResponse.url()));
261 } 188 }
262 189
263 void ResourceLoader::didReceiveResponse(WebURLLoader* loader, const WebURLRespon se& response) 190 void ResourceLoader::didReceiveResponse(WebURLLoader* loader, const WebURLRespon se& response)
264 { 191 {
265 didReceiveResponse(loader, response, nullptr); 192 didReceiveResponse(loader, response, nullptr);
266 } 193 }
267 194
268 void ResourceLoader::didReceiveData(WebURLLoader*, const char* data, int length, int encodedDataLength) 195 void ResourceLoader::didReceiveData(WebURLLoader*, const char* data, int length, int encodedDataLength)
269 { 196 {
270 RELEASE_ASSERT(m_state == ConnectionStateReceivedResponse || m_state == Conn ectionStateReceivingData); 197 RELEASE_ASSERT(length >= 0);
271 m_state = ConnectionStateReceivingData; 198 m_fetcher->didReceiveData(m_resource.get(), data, length, encodedDataLength) ;
199 m_resource->appendData(data, length);
200 }
272 201
273 // It is possible to receive data on uninitialized resources if it had an er ror status code, and we are running a nested message 202 void ResourceLoader::didFinishLoadingFirstPartInMultipart()
274 // loop. When this occurs, ignoring the data is the correct action. 203 {
275 if (m_resource->response().httpStatusCode() >= 400 && !m_resource->shouldIgn oreHTTPStatusCodeErrors()) 204 m_fetcher->didFinishLoading(m_resource.get(), 0, WebURLLoaderClient::kUnknow nEncodedDataLength, true);
Nate Chapin 2016/05/12 20:51:12 This exists to defend against nested loops causing
276 return;
277
278 // FIXME: If we get a resource with more than 2B bytes, this code won't do t he right thing.
279 // However, with today's computers and networking speeds, this won't happen in practice.
280 // Could be an issue with a giant local file.
281 m_fetcher->didReceiveData(m_resource.get(), data, length, encodedDataLength) ;
282 if (m_state == ConnectionStateReleased)
283 return;
284 RELEASE_ASSERT(length >= 0);
285 m_resource->appendData(data, length);
286 } 205 }
287 206
288 void ResourceLoader::didFinishLoading(WebURLLoader*, double finishTime, int64_t encodedDataLength) 207 void ResourceLoader::didFinishLoading(WebURLLoader*, double finishTime, int64_t encodedDataLength)
289 { 208 {
290 RELEASE_ASSERT(m_state == ConnectionStateReceivedResponse || m_state == Conn ectionStateReceivingData); 209 m_loader.clear();
291 m_state = ConnectionStateFinishedLoading; 210 m_fetcher->didFinishLoading(m_resource.get(), finishTime, encodedDataLength, false);
292 didFinishLoadingOnePart(finishTime, encodedDataLength);
293 ASSERT(m_state != ConnectionStateReleased);
294 m_resource->finish(finishTime);
Nate Chapin 2016/05/12 20:51:12 Call finish/error from ResourceFetcher, so that it
295 releaseResources();
296 } 211 }
297 212
298 void ResourceLoader::didFail(WebURLLoader*, const WebURLError& error) 213 void ResourceLoader::didFail(WebURLLoader*, const WebURLError& error)
299 { 214 {
300 ASSERT(m_state != ConnectionStateFinishedLoading); 215 m_loader.clear();
301 ASSERT(m_state != ConnectionStateReleased);
302 m_state = ConnectionStateFinishedLoading;
303 m_notifiedLoadComplete = true;
304 m_fetcher->didFailLoading(m_resource.get(), error); 216 m_fetcher->didFailLoading(m_resource.get(), error);
305 ASSERT(m_state != ConnectionStateReleased);
306 m_resource->error(error);
307 releaseResources();
308 } 217 }
309 218
310 void ResourceLoader::requestSynchronously(ResourceRequest& request) 219 void ResourceLoader::requestSynchronously(ResourceRequest& request)
311 { 220 {
312 // downloadToFile is not supported for synchronous requests. 221 // downloadToFile is not supported for synchronous requests.
313 ASSERT(!request.downloadToFile()); 222 ASSERT(!request.downloadToFile());
314 ASSERT(m_loader); 223 ASSERT(m_loader);
315 224
316 // Synchronous requests should always be max priority, lest they hang the re nderer. 225 // Synchronous requests should always be max priority, lest they hang the re nderer.
317 request.setPriority(ResourceLoadPriorityHighest); 226 request.setPriority(ResourceLoadPriorityHighest);
318 227
319 if (m_fetcher->defersLoading()) { 228 if (m_fetcher->defersLoading()) {
320 cancel(); 229 cancel();
321 return; 230 return;
322 } 231 }
323 232
324 WrappedResourceRequest requestIn(request); 233 WrappedResourceRequest requestIn(request);
325 WebURLResponse responseOut; 234 WebURLResponse responseOut;
326 responseOut.initialize(); 235 responseOut.initialize();
327 WebURLError errorOut; 236 WebURLError errorOut;
328 WebData dataOut; 237 WebData dataOut;
329 m_loader->loadSynchronously(requestIn, responseOut, errorOut, dataOut); 238 m_loader->loadSynchronously(requestIn, responseOut, errorOut, dataOut);
239
240 // A message dispatched while synchronously fetching the resource
241 // can bring about the cancellation of this load.
242 if (!m_loader)
243 return;
330 if (errorOut.reason) { 244 if (errorOut.reason) {
331 if (m_state == ConnectionStateReleased) {
332 // A message dispatched while synchronously fetching the resource
333 // can bring about the cancellation of this load.
334 ASSERT(!m_resource);
335 return;
336 }
337 didFail(0, errorOut); 245 didFail(0, errorOut);
338 return; 246 return;
339 } 247 }
340 didReceiveResponse(0, responseOut); 248 didReceiveResponse(0, responseOut);
341 if (m_state == ConnectionStateReleased) 249 if (!m_loader)
342 return; 250 return;
343 RefPtr<ResourceLoadInfo> resourceLoadInfo = responseOut.toResourceResponse() .resourceLoadInfo(); 251 RefPtr<ResourceLoadInfo> resourceLoadInfo = responseOut.toResourceResponse() .resourceLoadInfo();
344 int64_t encodedDataLength = resourceLoadInfo ? resourceLoadInfo->encodedData Length : WebURLLoaderClient::kUnknownEncodedDataLength; 252 int64_t encodedDataLength = resourceLoadInfo ? resourceLoadInfo->encodedData Length : WebURLLoaderClient::kUnknownEncodedDataLength;
345 253
346 // Follow the async case convention of not calling didReceiveData or 254 // Follow the async case convention of not calling didReceiveData or
347 // appending data to m_resource if the response body is empty. Copying the 255 // appending data to m_resource if the response body is empty. Copying the
348 // empty buffer is a noop in most cases, but is destructive in the case of 256 // empty buffer is a noop in most cases, but is destructive in the case of
349 // a 304, where it will overwrite the cached data we should be reusing. 257 // a 304, where it will overwrite the cached data we should be reusing.
350 if (dataOut.size()) { 258 if (dataOut.size()) {
351 m_fetcher->didReceiveData(m_resource.get(), dataOut.data(), dataOut.size (), encodedDataLength); 259 m_fetcher->didReceiveData(m_resource.get(), dataOut.data(), dataOut.size (), encodedDataLength);
352 m_resource->setResourceBuffer(dataOut); 260 m_resource->setResourceBuffer(dataOut);
353 } 261 }
354 didFinishLoading(0, monotonicallyIncreasingTime(), encodedDataLength); 262 didFinishLoading(0, monotonicallyIncreasingTime(), encodedDataLength);
355 } 263 }
356 264
357 } // namespace blink 265 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698