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