| 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 |