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) 2006 Samuel Weinig (sam.weinig@gmail.com) | 5 Copyright (C) 2006 Samuel Weinig (sam.weinig@gmail.com) |
6 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. | 6 Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved. |
7 | 7 |
8 This library is free software; you can redistribute it and/or | 8 This library is free software; you can redistribute it and/or |
9 modify it under the terms of the GNU Library General Public | 9 modify it under the terms of the GNU Library General Public |
10 License as published by the Free Software Foundation; either | 10 License as published by the Free Software Foundation; either |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
161 , m_requestedFromNetworkingLayer(false) | 161 , m_requestedFromNetworkingLayer(false) |
162 , m_loading(false) | 162 , m_loading(false) |
163 , m_switchingClientsToRevalidatedResource(false) | 163 , m_switchingClientsToRevalidatedResource(false) |
164 , m_type(type) | 164 , m_type(type) |
165 , m_status(Pending) | 165 , m_status(Pending) |
166 , m_wasPurged(false) | 166 , m_wasPurged(false) |
167 , m_needsSynchronousCacheHit(false) | 167 , m_needsSynchronousCacheHit(false) |
168 #ifdef ENABLE_RESOURCE_IS_DELETED_CHECK | 168 #ifdef ENABLE_RESOURCE_IS_DELETED_CHECK |
169 , m_deleted(false) | 169 , m_deleted(false) |
170 #endif | 170 #endif |
171 , m_resourceToRevalidate(nullptr) | |
172 , m_proxyResource(nullptr) | |
173 { | 171 { |
174 ASSERT(m_type == unsigned(type)); // m_type is a bitfield, so this tests car eless updates of the enum. | 172 ASSERT(m_type == unsigned(type)); // m_type is a bitfield, so this tests car eless updates of the enum. |
175 InstanceCounters::incrementCounter(InstanceCounters::ResourceCounter); | 173 InstanceCounters::incrementCounter(InstanceCounters::ResourceCounter); |
176 #ifndef NDEBUG | 174 #ifndef NDEBUG |
177 cachedResourceLeakCounter.increment(); | 175 cachedResourceLeakCounter.increment(); |
178 #endif | 176 #endif |
179 memoryCache()->registerLiveResource(*this); | 177 memoryCache()->registerLiveResource(*this); |
180 | 178 |
181 // Currently we support the metadata caching only for HTTP family. | 179 // Currently we support the metadata caching only for HTTP family. |
182 if (m_resourceRequest.url().protocolIsInHTTPFamily()) | 180 if (m_resourceRequest.url().protocolIsInHTTPFamily()) |
183 m_cacheHandler = CacheHandler::create(this); | 181 m_cacheHandler = CacheHandler::create(this); |
184 | 182 |
185 if (!m_resourceRequest.url().hasFragmentIdentifier()) | 183 if (!m_resourceRequest.url().hasFragmentIdentifier()) |
186 return; | 184 return; |
187 KURL urlForCache = MemoryCache::removeFragmentIdentifierIfNeeded(m_resourceR equest.url()); | 185 KURL urlForCache = MemoryCache::removeFragmentIdentifierIfNeeded(m_resourceR equest.url()); |
188 if (urlForCache.hasFragmentIdentifier()) | 186 if (urlForCache.hasFragmentIdentifier()) |
189 return; | 187 return; |
190 m_fragmentIdentifierForRequest = m_resourceRequest.url().fragmentIdentifier( ); | 188 m_fragmentIdentifierForRequest = m_resourceRequest.url().fragmentIdentifier( ); |
191 m_resourceRequest.setURL(urlForCache); | 189 m_resourceRequest.setURL(urlForCache); |
192 } | 190 } |
193 | 191 |
194 Resource::~Resource() | 192 Resource::~Resource() |
195 { | 193 { |
196 ASSERT(!m_resourceToRevalidate); // Should be true because canDelete() check s this. | |
197 ASSERT(canDelete()); | 194 ASSERT(canDelete()); |
198 RELEASE_ASSERT(!memoryCache()->contains(this)); | 195 RELEASE_ASSERT(!memoryCache()->contains(this)); |
199 RELEASE_ASSERT(!ResourceCallback::callbackHandler()->isScheduled(this)); | 196 RELEASE_ASSERT(!ResourceCallback::callbackHandler()->isScheduled(this)); |
200 assertAlive(); | 197 assertAlive(); |
201 | 198 |
202 #ifdef ENABLE_RESOURCE_IS_DELETED_CHECK | 199 #ifdef ENABLE_RESOURCE_IS_DELETED_CHECK |
203 m_deleted = true; | 200 m_deleted = true; |
204 #endif | 201 #endif |
205 #ifndef NDEBUG | 202 #ifndef NDEBUG |
206 cachedResourceLeakCounter.decrement(); | 203 cachedResourceLeakCounter.decrement(); |
207 #endif | 204 #endif |
208 InstanceCounters::decrementCounter(InstanceCounters::ResourceCounter); | 205 InstanceCounters::decrementCounter(InstanceCounters::ResourceCounter); |
209 } | 206 } |
210 | 207 |
211 void Resource::dispose() | 208 void Resource::dispose() |
212 { | 209 { |
213 } | 210 } |
214 | 211 |
215 DEFINE_TRACE(Resource) | 212 DEFINE_TRACE(Resource) |
216 { | 213 { |
217 visitor->trace(m_loader); | 214 visitor->trace(m_loader); |
218 visitor->trace(m_resourceToRevalidate); | |
219 visitor->trace(m_proxyResource); | |
220 #if ENABLE(OILPAN) | 215 #if ENABLE(OILPAN) |
221 visitor->trace(m_cacheHandler); | 216 visitor->trace(m_cacheHandler); |
222 #endif | 217 #endif |
223 } | 218 } |
224 | 219 |
225 void Resource::load(ResourceFetcher* fetcher, const ResourceLoaderOptions& optio ns) | 220 void Resource::load(ResourceFetcher* fetcher, const ResourceLoaderOptions& optio ns) |
226 { | 221 { |
227 m_options = options; | 222 m_options = options; |
228 m_loading = true; | 223 m_loading = true; |
229 | 224 |
225 ResourceRequest request(m_revalidatingRequest.isNull() ? m_resourceRequest : m_revalidatingRequest); | |
230 if (!accept().isEmpty()) | 226 if (!accept().isEmpty()) |
231 m_resourceRequest.setHTTPAccept(accept()); | 227 request.setHTTPAccept(accept()); |
232 | 228 |
233 // FIXME: It's unfortunate that the cache layer and below get to know anythi ng about fragment identifiers. | 229 // FIXME: It's unfortunate that the cache layer and below get to know anythi ng about fragment identifiers. |
234 // We should look into removing the expectation of that knowledge from the p latform network stacks. | 230 // We should look into removing the expectation of that knowledge from the p latform network stacks. |
235 ResourceRequest request(m_resourceRequest); | |
236 if (!m_fragmentIdentifierForRequest.isNull()) { | 231 if (!m_fragmentIdentifierForRequest.isNull()) { |
237 KURL url = request.url(); | 232 KURL url = request.url(); |
238 url.setFragmentIdentifier(m_fragmentIdentifierForRequest); | 233 url.setFragmentIdentifier(m_fragmentIdentifierForRequest); |
239 request.setURL(url); | 234 request.setURL(url); |
240 m_fragmentIdentifierForRequest = String(); | 235 m_fragmentIdentifierForRequest = String(); |
241 } | 236 } |
242 m_status = Pending; | 237 m_status = Pending; |
243 if (m_loader) { | 238 if (m_loader) { |
239 ASSERT(m_revalidatingRequest.isNull()); | |
244 RELEASE_ASSERT(m_options.synchronousPolicy == RequestSynchronously); | 240 RELEASE_ASSERT(m_options.synchronousPolicy == RequestSynchronously); |
245 m_loader->changeToSynchronous(); | 241 m_loader->changeToSynchronous(); |
246 return; | 242 return; |
247 } | 243 } |
248 m_loader = ResourceLoader::create(fetcher, this, request, options); | 244 m_loader = ResourceLoader::create(fetcher, this, request, options); |
249 m_loader->start(); | 245 m_loader->start(); |
250 } | 246 } |
251 | 247 |
252 void Resource::checkNotify() | 248 void Resource::checkNotify() |
253 { | 249 { |
254 if (isLoading()) | 250 if (isLoading()) |
255 return; | 251 return; |
256 | 252 |
257 ResourceClientWalker<ResourceClient> w(m_clients); | 253 ResourceClientWalker<ResourceClient> w(m_clients); |
258 while (ResourceClient* c = w.next()) | 254 while (ResourceClient* c = w.next()) |
259 c->notifyFinished(this); | 255 c->notifyFinished(this); |
260 } | 256 } |
261 | 257 |
262 void Resource::appendData(const char* data, unsigned length) | 258 void Resource::appendData(const char* data, unsigned length) |
263 { | 259 { |
264 TRACE_EVENT0("blink", "Resource::appendData"); | 260 TRACE_EVENT0("blink", "Resource::appendData"); |
265 ASSERT(!m_resourceToRevalidate); | 261 ASSERT(m_revalidatingRequest.isNull()); |
266 ASSERT(!errorOccurred()); | 262 ASSERT(!errorOccurred()); |
267 if (m_options.dataBufferingPolicy == DoNotBufferData) | 263 if (m_options.dataBufferingPolicy == DoNotBufferData) |
268 return; | 264 return; |
269 if (m_data) | 265 if (m_data) |
270 m_data->append(data, length); | 266 m_data->append(data, length); |
271 else | 267 else |
272 m_data = SharedBuffer::createPurgeable(data, length); | 268 m_data = SharedBuffer::createPurgeable(data, length); |
273 setEncodedSize(m_data->size()); | 269 setEncodedSize(m_data->size()); |
274 } | 270 } |
275 | 271 |
276 void Resource::setResourceBuffer(PassRefPtr<SharedBuffer> resourceBuffer) | 272 void Resource::setResourceBuffer(PassRefPtr<SharedBuffer> resourceBuffer) |
277 { | 273 { |
278 ASSERT(!m_resourceToRevalidate); | 274 ASSERT(m_revalidatingRequest.isNull()); |
279 ASSERT(!errorOccurred()); | 275 ASSERT(!errorOccurred()); |
280 ASSERT(m_options.dataBufferingPolicy == BufferData); | 276 ASSERT(m_options.dataBufferingPolicy == BufferData); |
281 m_data = resourceBuffer; | 277 m_data = resourceBuffer; |
282 setEncodedSize(m_data->size()); | 278 setEncodedSize(m_data->size()); |
283 } | 279 } |
284 | 280 |
285 void Resource::setDataBufferingPolicy(DataBufferingPolicy dataBufferingPolicy) | 281 void Resource::setDataBufferingPolicy(DataBufferingPolicy dataBufferingPolicy) |
286 { | 282 { |
287 m_options.dataBufferingPolicy = dataBufferingPolicy; | 283 m_options.dataBufferingPolicy = dataBufferingPolicy; |
288 m_data.clear(); | 284 m_data.clear(); |
289 setEncodedSize(0); | 285 setEncodedSize(0); |
290 } | 286 } |
291 | 287 |
292 void Resource::error(Resource::Status status) | 288 void Resource::error(Resource::Status status) |
293 { | 289 { |
294 if (m_resourceToRevalidate) | 290 if (!m_revalidatingRequest.isNull()) |
295 revalidationFailed(); | 291 m_revalidatingRequest = ResourceRequest(); |
Nate Chapin
2015/07/16 23:35:27
The only difference between this and the original
Yoav Weiss
2015/07/17 08:57:03
Do we have tests that caught this logic change?
| |
296 | 292 |
297 if (!m_error.isNull() && (m_error.isCancellation() || !isPreloaded())) | 293 if (!m_error.isNull() && (m_error.isCancellation() || !isPreloaded())) |
298 memoryCache()->remove(this); | 294 memoryCache()->remove(this); |
299 | 295 |
300 setStatus(status); | 296 setStatus(status); |
301 ASSERT(errorOccurred()); | 297 ASSERT(errorOccurred()); |
302 m_data.clear(); | 298 m_data.clear(); |
303 | 299 |
304 setLoading(false); | 300 setLoading(false); |
305 checkNotify(); | 301 checkNotify(); |
306 } | 302 } |
307 | 303 |
308 void Resource::finishOnePart() | 304 void Resource::finishOnePart() |
309 { | 305 { |
310 setLoading(false); | 306 setLoading(false); |
311 checkNotify(); | 307 checkNotify(); |
312 } | 308 } |
313 | 309 |
314 void Resource::finish() | 310 void Resource::finish() |
315 { | 311 { |
316 ASSERT(!m_resourceToRevalidate); | 312 ASSERT(m_revalidatingRequest.isNull()); |
317 ASSERT(!errorOccurred()); | 313 ASSERT(!errorOccurred()); |
318 finishOnePart(); | 314 finishOnePart(); |
319 if (!errorOccurred()) | 315 if (!errorOccurred()) |
320 m_status = Cached; | 316 m_status = Cached; |
321 } | 317 } |
322 | 318 |
323 bool Resource::passesAccessControlCheck(SecurityOrigin* securityOrigin) const | 319 bool Resource::passesAccessControlCheck(SecurityOrigin* securityOrigin) const |
324 { | 320 { |
325 String ignoredErrorDescription; | 321 String ignoredErrorDescription; |
326 return passesAccessControlCheck(securityOrigin, ignoredErrorDescription); | 322 return passesAccessControlCheck(securityOrigin, ignoredErrorDescription); |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
433 } | 429 } |
434 | 430 |
435 bool Resource::unlock() | 431 bool Resource::unlock() |
436 { | 432 { |
437 if (!m_data) | 433 if (!m_data) |
438 return false; | 434 return false; |
439 | 435 |
440 if (!m_data->isLocked()) | 436 if (!m_data->isLocked()) |
441 return true; | 437 return true; |
442 | 438 |
443 if (!memoryCache()->contains(this) || hasClients() || m_handleCount > 1 || m _proxyResource || m_resourceToRevalidate || !m_loadFinishTime || !isSafeToUnlock ()) | 439 if (!memoryCache()->contains(this) || hasClients() || m_handleCount > 1 || ! m_revalidatingRequest.isNull() || !m_loadFinishTime || !isSafeToUnlock()) |
444 return false; | 440 return false; |
445 | 441 |
446 m_data->unlock(); | 442 m_data->unlock(); |
447 return true; | 443 return true; |
448 } | 444 } |
449 | 445 |
450 bool Resource::hasRightHandleCountApartFromCache(unsigned targetCount) const | 446 bool Resource::hasRightHandleCountApartFromCache(unsigned targetCount) const |
451 { | 447 { |
452 return m_handleCount == targetCount + (memoryCache()->contains(this) ? 1 : 0 ); | 448 return m_handleCount == targetCount + (memoryCache()->contains(this) ? 1 : 0 ); |
453 } | 449 } |
454 | 450 |
455 void Resource::responseReceived(const ResourceResponse& response, PassOwnPtr<Web DataConsumerHandle>) | 451 void Resource::responseReceived(const ResourceResponse& response, PassOwnPtr<Web DataConsumerHandle>) |
456 { | 452 { |
453 m_responseTimestamp = currentTime(); | |
454 | |
455 if (!m_revalidatingRequest.isNull()) { | |
456 if (response.httpStatusCode() == 304) { | |
457 revalidationSucceeded(response); | |
458 return; | |
459 } | |
460 revalidationFailed(); | |
461 } | |
462 | |
457 setResponse(response); | 463 setResponse(response); |
458 m_responseTimestamp = currentTime(); | |
459 String encoding = response.textEncodingName(); | 464 String encoding = response.textEncodingName(); |
460 if (!encoding.isNull()) | 465 if (!encoding.isNull()) |
461 setEncoding(encoding); | 466 setEncoding(encoding); |
462 | |
463 if (!m_resourceToRevalidate) | |
464 return; | |
465 if (response.httpStatusCode() == 304) | |
466 revalidationSucceeded(response); | |
467 else | |
468 revalidationFailed(); | |
469 } | 467 } |
470 | 468 |
471 void Resource::setSerializedCachedMetadata(const char* data, size_t size) | 469 void Resource::setSerializedCachedMetadata(const char* data, size_t size) |
472 { | 470 { |
473 // We only expect to receive cached metadata from the platform once. | 471 // We only expect to receive cached metadata from the platform once. |
474 // If this triggers, it indicates an efficiency problem which is most | 472 // If this triggers, it indicates an efficiency problem which is most |
475 // likely unexpected in code designed to improve performance. | 473 // likely unexpected in code designed to improve performance. |
476 ASSERT(!m_cachedMetadata); | 474 ASSERT(!m_cachedMetadata); |
477 ASSERT(!m_resourceToRevalidate); | 475 ASSERT(m_revalidatingRequest.isNull()); |
478 | 476 |
479 m_cachedMetadata = CachedMetadata::deserialize(data, size); | 477 m_cachedMetadata = CachedMetadata::deserialize(data, size); |
480 } | 478 } |
481 | 479 |
482 CachedMetadataHandler* Resource::cacheHandler() | 480 CachedMetadataHandler* Resource::cacheHandler() |
483 { | 481 { |
484 return m_cacheHandler.get(); | 482 return m_cacheHandler.get(); |
485 } | 483 } |
486 | 484 |
487 void Resource::setCachedMetadata(unsigned dataTypeID, const char* data, size_t s ize, CachedMetadataHandler::CacheType cacheType) | 485 void Resource::setCachedMetadata(unsigned dataTypeID, const char* data, size_t s ize, CachedMetadataHandler::CacheType cacheType) |
(...skipping 20 matching lines...) Expand all Loading... | |
508 { | 506 { |
509 m_cachedMetadata.clear(); | 507 m_cachedMetadata.clear(); |
510 | 508 |
511 if (cacheType == CachedMetadataHandler::SendToPlatform) | 509 if (cacheType == CachedMetadataHandler::SendToPlatform) |
512 Platform::current()->cacheMetadata(m_response.url(), m_response.response Time(), 0, 0); | 510 Platform::current()->cacheMetadata(m_response.url(), m_response.response Time(), 0, 0); |
513 } | 511 } |
514 | 512 |
515 bool Resource::canDelete() const | 513 bool Resource::canDelete() const |
516 { | 514 { |
517 return !hasClients() && !m_loader && !m_preloadCount && hasRightHandleCountA partFromCache(0) | 515 return !hasClients() && !m_loader && !m_preloadCount && hasRightHandleCountA partFromCache(0) |
518 && !m_protectorCount && !m_resourceToRevalidate && !m_proxyResource; | 516 && !m_protectorCount; |
519 } | 517 } |
520 | 518 |
521 bool Resource::hasOneHandle() const | 519 bool Resource::hasOneHandle() const |
522 { | 520 { |
523 return hasRightHandleCountApartFromCache(1); | 521 return hasRightHandleCountApartFromCache(1); |
524 } | 522 } |
525 | 523 |
526 CachedMetadata* Resource::cachedMetadata(unsigned dataTypeID) const | 524 CachedMetadata* Resource::cachedMetadata(unsigned dataTypeID) const |
527 { | 525 { |
528 if (!m_cachedMetadata || m_cachedMetadata->dataTypeID() != dataTypeID) | 526 if (!m_cachedMetadata || m_cachedMetadata->dataTypeID() != dataTypeID) |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
575 m_preloadResult = PreloadReferencedWhileComplete; | 573 m_preloadResult = PreloadReferencedWhileComplete; |
576 else if (m_requestedFromNetworkingLayer) | 574 else if (m_requestedFromNetworkingLayer) |
577 m_preloadResult = PreloadReferencedWhileLoading; | 575 m_preloadResult = PreloadReferencedWhileLoading; |
578 else | 576 else |
579 m_preloadResult = PreloadReferenced; | 577 m_preloadResult = PreloadReferenced; |
580 } | 578 } |
581 if (!hasClients()) | 579 if (!hasClients()) |
582 memoryCache()->makeLive(this); | 580 memoryCache()->makeLive(this); |
583 | 581 |
584 // If we have existing data to send to the new client and the resource type supprts it, send it asynchronously. | 582 // If we have existing data to send to the new client and the resource type supprts it, send it asynchronously. |
585 if (!m_response.isNull() && !m_proxyResource && !shouldSendCachedDataSynchro nouslyForType(type()) && !m_needsSynchronousCacheHit) { | 583 if (!m_response.isNull() && !shouldSendCachedDataSynchronouslyForType(type() ) && !m_needsSynchronousCacheHit) { |
586 m_clientsAwaitingCallback.add(client); | 584 m_clientsAwaitingCallback.add(client); |
587 ResourceCallback::callbackHandler()->schedule(this); | 585 ResourceCallback::callbackHandler()->schedule(this); |
588 return false; | 586 return false; |
589 } | 587 } |
590 | 588 |
591 m_clients.add(client); | 589 m_clients.add(client); |
592 return true; | 590 return true; |
593 } | 591 } |
594 | 592 |
595 void Resource::removeClient(ResourceClient* client) | 593 void Resource::removeClient(ResourceClient* client) |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
719 // Prevent the case when there are clients waiting but no callback scheduled . | 717 // Prevent the case when there are clients waiting but no callback scheduled . |
720 ASSERT(m_clientsAwaitingCallback.isEmpty() || scheduled); | 718 ASSERT(m_clientsAwaitingCallback.isEmpty() || scheduled); |
721 } | 719 } |
722 | 720 |
723 void Resource::prune() | 721 void Resource::prune() |
724 { | 722 { |
725 destroyDecodedDataIfPossible(); | 723 destroyDecodedDataIfPossible(); |
726 unlock(); | 724 unlock(); |
727 } | 725 } |
728 | 726 |
729 void Resource::setResourceToRevalidate(Resource* resource) | 727 |
728 void Resource::revalidationSucceeded(const ResourceResponse& validatingResponse) | |
730 { | 729 { |
731 ASSERT(resource); | 730 // Calling evict() can potentially delete revalidatingResource, which we use |
732 ASSERT(!m_resourceToRevalidate); | 731 // below. This mustn't be the case since revalidation means it is loaded |
733 ASSERT(resource != this); | 732 // and so canDelete() is false. |
734 ASSERT(m_handlesToRevalidate.isEmpty()); | 733 ASSERT(!canDelete()); |
735 ASSERT(resource->type() == type()); | |
736 | 734 |
737 WTF_LOG(ResourceLoading, "Resource %p setResourceToRevalidate %p", this, res ource); | |
738 | |
739 // The following assert should be investigated whenever it occurs. Although it should never fire, it currently does in rare circumstances. | |
740 // https://bugs.webkit.org/show_bug.cgi?id=28604. | |
741 // So the code needs to be robust to this assert failing thus the "if (m_res ourceToRevalidate->m_proxyResource == this)" in Resource::clearResourceToRevalid ate. | |
742 ASSERT(!resource->m_proxyResource); | |
743 | |
744 resource->m_proxyResource = this; | |
745 m_resourceToRevalidate = resource; | |
746 } | |
747 | |
748 void Resource::clearResourceToRevalidate() | |
749 { | |
750 ASSERT(m_resourceToRevalidate); | |
751 if (m_switchingClientsToRevalidatedResource) | |
752 return; | |
753 | |
754 // A resource may start revalidation before this method has been called, so check that this resource is still the proxy resource before clearing it out. | |
755 if (m_resourceToRevalidate->m_proxyResource == this) { | |
756 m_resourceToRevalidate->m_proxyResource = nullptr; | |
757 m_resourceToRevalidate->deleteIfPossible(); | |
758 } | |
759 m_handlesToRevalidate.clear(); | |
760 m_resourceToRevalidate = nullptr; | |
761 deleteIfPossible(); | |
762 } | |
763 | |
764 void Resource::switchClientsToRevalidatedResource() | |
765 { | |
766 ASSERT(m_resourceToRevalidate); | |
767 ASSERT(memoryCache()->contains(m_resourceToRevalidate)); | |
768 ASSERT(!memoryCache()->contains(this)); | |
769 | |
770 WTF_LOG(ResourceLoading, "Resource %p switchClientsToRevalidatedResource %p" , this, m_resourceToRevalidate.get()); | |
771 | |
772 m_resourceToRevalidate->m_identifier = m_identifier; | |
773 | |
774 m_switchingClientsToRevalidatedResource = true; | |
775 for (ResourcePtrBase* handle : m_handlesToRevalidate) { | |
776 handle->m_resource = m_resourceToRevalidate; | |
777 m_resourceToRevalidate->registerHandle(handle); | |
778 --m_handleCount; | |
779 } | |
780 ASSERT(!m_handleCount); | |
781 m_handlesToRevalidate.clear(); | |
782 | |
783 Vector<ResourceClient*> clientsToMove; | |
784 for (const auto& clientHashEntry : m_clients) { | |
785 unsigned count = clientHashEntry.value; | |
786 while (count--) | |
787 clientsToMove.append(clientHashEntry.key); | |
788 } | |
789 | |
790 unsigned moveCount = clientsToMove.size(); | |
791 for (unsigned n = 0; n < moveCount; ++n) | |
792 removeClient(clientsToMove[n]); | |
793 ASSERT(m_clients.isEmpty()); | |
794 | |
795 for (unsigned n = 0; n < moveCount; ++n) | |
796 m_resourceToRevalidate->addClientToSet(clientsToMove[n]); | |
797 for (unsigned n = 0; n < moveCount; ++n) { | |
798 // Calling didAddClient may do anything, including trying to cancel reva lidation. | |
799 // Assert that it didn't succeed. | |
800 ASSERT(m_resourceToRevalidate); | |
801 // Calling didAddClient for a client may end up removing another client. In that case it won't be in the set anymore. | |
802 if (m_resourceToRevalidate->m_clients.contains(clientsToMove[n])) | |
803 m_resourceToRevalidate->didAddClient(clientsToMove[n]); | |
804 } | |
805 m_switchingClientsToRevalidatedResource = false; | |
806 } | |
807 | |
808 void Resource::updateResponseAfterRevalidation(const ResourceResponse& validatin gResponse) | |
809 { | |
810 m_responseTimestamp = currentTime(); | 735 m_responseTimestamp = currentTime(); |
736 m_response.setResourceLoadTiming(validatingResponse.resourceLoadTiming()); | |
811 | 737 |
812 // RFC2616 10.3.5 | 738 // RFC2616 10.3.5 |
813 // Update cached headers from the 304 response | 739 // Update cached headers from the 304 response |
814 const HTTPHeaderMap& newHeaders = validatingResponse.httpHeaderFields(); | 740 const HTTPHeaderMap& newHeaders = validatingResponse.httpHeaderFields(); |
815 for (const auto& header : newHeaders) { | 741 for (const auto& header : newHeaders) { |
816 // Entity headers should not be sent by servers when generating a 304 | 742 // Entity headers should not be sent by servers when generating a 304 |
817 // response; misconfigured servers send them anyway. We shouldn't allow | 743 // response; misconfigured servers send them anyway. We shouldn't allow |
818 // such headers to update the original request. We'll base this on the | 744 // such headers to update the original request. We'll base this on the |
819 // list defined by RFC2616 7.1, with a few additions for extension heade rs | 745 // list defined by RFC2616 7.1, with a few additions for extension heade rs |
820 // we care about. | 746 // we care about. |
821 if (!shouldUpdateHeaderAfterRevalidation(header.key)) | 747 if (!shouldUpdateHeaderAfterRevalidation(header.key)) |
822 continue; | 748 continue; |
823 m_response.setHTTPHeaderField(header.key, header.value); | 749 m_response.setHTTPHeaderField(header.key, header.value); |
824 } | 750 } |
825 } | |
826 | 751 |
827 void Resource::revalidationSucceeded(const ResourceResponse& response) | |
828 { | |
829 ASSERT(m_resourceToRevalidate); | |
830 ASSERT(!memoryCache()->contains(m_resourceToRevalidate)); | |
831 ASSERT(m_resourceToRevalidate->isLoaded()); | |
832 | |
833 // Calling evict() can potentially delete revalidatingResource, which we use | |
834 // below. This mustn't be the case since revalidation means it is loaded | |
835 // and so canDelete() is false. | |
836 ASSERT(!canDelete()); | |
837 | |
838 m_resourceToRevalidate->updateResponseAfterRevalidation(response); | |
839 memoryCache()->replace(m_resourceToRevalidate, this); | |
840 | |
841 switchClientsToRevalidatedResource(); | |
842 assertAlive(); | 752 assertAlive(); |
843 // clearResourceToRevalidate deletes this. | 753 m_resourceRequest = m_revalidatingRequest; |
844 clearResourceToRevalidate(); | 754 m_revalidatingRequest = ResourceRequest(); |
845 } | 755 } |
846 | 756 |
847 void Resource::revalidationFailed() | 757 void Resource::revalidationFailed() |
848 { | 758 { |
849 ASSERT(WTF::isMainThread()); | 759 m_resourceRequest = m_revalidatingRequest; |
850 WTF_LOG(ResourceLoading, "Revalidation failed for %p", this); | 760 m_revalidatingRequest = ResourceRequest(); |
851 ASSERT(resourceToRevalidate()); | 761 m_data.clear(); |
852 clearResourceToRevalidate(); | 762 destroyDecodedDataForFailedRevalidation(); |
853 } | 763 } |
854 | 764 |
855 void Resource::registerHandle(ResourcePtrBase* h) | 765 void Resource::registerHandle(ResourcePtrBase* h) |
856 { | 766 { |
857 assertAlive(); | 767 assertAlive(); |
858 ++m_handleCount; | 768 ++m_handleCount; |
859 if (m_resourceToRevalidate) | |
860 m_handlesToRevalidate.add(h); | |
861 } | 769 } |
862 | 770 |
863 void Resource::unregisterHandle(ResourcePtrBase* h) | 771 void Resource::unregisterHandle(ResourcePtrBase* h) |
864 { | 772 { |
865 assertAlive(); | 773 assertAlive(); |
866 ASSERT(m_handleCount > 0); | 774 ASSERT(m_handleCount > 0); |
867 --m_handleCount; | 775 --m_handleCount; |
868 | 776 |
869 if (m_resourceToRevalidate) | |
870 m_handlesToRevalidate.remove(h); | |
871 | |
872 if (!m_handleCount) { | 777 if (!m_handleCount) { |
873 if (deleteIfPossible()) | 778 if (deleteIfPossible()) |
874 return; | 779 return; |
875 unlock(); | 780 unlock(); |
876 } else if (m_handleCount == 1 && memoryCache()->contains(this)) { | 781 } else if (m_handleCount == 1 && memoryCache()->contains(this)) { |
877 unlock(); | 782 unlock(); |
878 if (!hasClients()) | 783 if (!hasClients()) |
879 memoryCache()->prune(this); | 784 memoryCache()->prune(this); |
880 } | 785 } |
881 } | 786 } |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1090 return "ImportResource"; | 995 return "ImportResource"; |
1091 case Resource::Media: | 996 case Resource::Media: |
1092 return "Media"; | 997 return "Media"; |
1093 } | 998 } |
1094 ASSERT_NOT_REACHED(); | 999 ASSERT_NOT_REACHED(); |
1095 return "Unknown"; | 1000 return "Unknown"; |
1096 } | 1001 } |
1097 #endif // !LOG_DISABLED | 1002 #endif // !LOG_DISABLED |
1098 | 1003 |
1099 } // namespace blink | 1004 } // namespace blink |
OLD | NEW |