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 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
158 , m_requestedFromNetworkingLayer(false) | 158 , m_requestedFromNetworkingLayer(false) |
159 , m_loading(false) | 159 , m_loading(false) |
160 , m_switchingClientsToRevalidatedResource(false) | 160 , m_switchingClientsToRevalidatedResource(false) |
161 , m_type(type) | 161 , m_type(type) |
162 , m_status(Pending) | 162 , m_status(Pending) |
163 , m_wasPurged(false) | 163 , m_wasPurged(false) |
164 , m_needsSynchronousCacheHit(false) | 164 , m_needsSynchronousCacheHit(false) |
165 #ifdef ENABLE_RESOURCE_IS_DELETED_CHECK | 165 #ifdef ENABLE_RESOURCE_IS_DELETED_CHECK |
166 , m_deleted(false) | 166 , m_deleted(false) |
167 #endif | 167 #endif |
168 , m_resourceToRevalidate(nullptr) | |
169 , m_proxyResource(nullptr) | |
170 { | 168 { |
171 ASSERT(m_type == unsigned(type)); // m_type is a bitfield, so this tests car
eless updates of the enum. | 169 ASSERT(m_type == unsigned(type)); // m_type is a bitfield, so this tests car
eless updates of the enum. |
172 InstanceCounters::incrementCounter(InstanceCounters::ResourceCounter); | 170 InstanceCounters::incrementCounter(InstanceCounters::ResourceCounter); |
173 memoryCache()->registerLiveResource(*this); | 171 memoryCache()->registerLiveResource(*this); |
174 | 172 |
175 // Currently we support the metadata caching only for HTTP family. | 173 // Currently we support the metadata caching only for HTTP family. |
176 if (m_resourceRequest.url().protocolIsInHTTPFamily()) | 174 if (m_resourceRequest.url().protocolIsInHTTPFamily()) |
177 m_cacheHandler = CacheHandler::create(this); | 175 m_cacheHandler = CacheHandler::create(this); |
178 | 176 |
179 if (!m_resourceRequest.url().hasFragmentIdentifier()) | 177 if (!m_resourceRequest.url().hasFragmentIdentifier()) |
180 return; | 178 return; |
181 KURL urlForCache = MemoryCache::removeFragmentIdentifierIfNeeded(m_resourceR
equest.url()); | 179 KURL urlForCache = MemoryCache::removeFragmentIdentifierIfNeeded(m_resourceR
equest.url()); |
182 if (urlForCache.hasFragmentIdentifier()) | 180 if (urlForCache.hasFragmentIdentifier()) |
183 return; | 181 return; |
184 m_fragmentIdentifierForRequest = m_resourceRequest.url().fragmentIdentifier(
); | 182 m_fragmentIdentifierForRequest = m_resourceRequest.url().fragmentIdentifier(
); |
185 m_resourceRequest.setURL(urlForCache); | 183 m_resourceRequest.setURL(urlForCache); |
186 } | 184 } |
187 | 185 |
188 Resource::~Resource() | 186 Resource::~Resource() |
189 { | 187 { |
190 ASSERT(!m_resourceToRevalidate); // Should be true because canDelete() check
s this. | |
191 ASSERT(canDelete()); | 188 ASSERT(canDelete()); |
192 RELEASE_ASSERT(!memoryCache()->contains(this)); | 189 RELEASE_ASSERT(!memoryCache()->contains(this)); |
193 RELEASE_ASSERT(!ResourceCallback::callbackHandler()->isScheduled(this)); | 190 RELEASE_ASSERT(!ResourceCallback::callbackHandler()->isScheduled(this)); |
194 assertAlive(); | 191 assertAlive(); |
195 | 192 |
196 #ifdef ENABLE_RESOURCE_IS_DELETED_CHECK | 193 #ifdef ENABLE_RESOURCE_IS_DELETED_CHECK |
197 m_deleted = true; | 194 m_deleted = true; |
198 #endif | 195 #endif |
199 InstanceCounters::decrementCounter(InstanceCounters::ResourceCounter); | 196 InstanceCounters::decrementCounter(InstanceCounters::ResourceCounter); |
200 } | 197 } |
201 | 198 |
202 void Resource::dispose() | 199 void Resource::dispose() |
203 { | 200 { |
204 } | 201 } |
205 | 202 |
206 DEFINE_TRACE(Resource) | 203 DEFINE_TRACE(Resource) |
207 { | 204 { |
208 visitor->trace(m_loader); | 205 visitor->trace(m_loader); |
209 visitor->trace(m_resourceToRevalidate); | |
210 visitor->trace(m_proxyResource); | |
211 #if ENABLE(OILPAN) | 206 #if ENABLE(OILPAN) |
212 visitor->trace(m_cacheHandler); | 207 visitor->trace(m_cacheHandler); |
213 #endif | 208 #endif |
214 } | 209 } |
215 | 210 |
216 void Resource::load(ResourceFetcher* fetcher, const ResourceLoaderOptions& optio
ns) | 211 void Resource::load(ResourceFetcher* fetcher, const ResourceLoaderOptions& optio
ns) |
217 { | 212 { |
218 m_options = options; | 213 m_options = options; |
219 m_loading = true; | 214 m_loading = true; |
220 | 215 |
| 216 ResourceRequest request(m_revalidatingRequest.isNull() ? m_resourceRequest :
m_revalidatingRequest); |
221 if (!accept().isEmpty()) | 217 if (!accept().isEmpty()) |
222 m_resourceRequest.setHTTPAccept(accept()); | 218 request.setHTTPAccept(accept()); |
223 | 219 |
224 // FIXME: It's unfortunate that the cache layer and below get to know anythi
ng about fragment identifiers. | 220 // FIXME: It's unfortunate that the cache layer and below get to know anythi
ng about fragment identifiers. |
225 // We should look into removing the expectation of that knowledge from the p
latform network stacks. | 221 // We should look into removing the expectation of that knowledge from the p
latform network stacks. |
226 ResourceRequest request(m_resourceRequest); | |
227 if (!m_fragmentIdentifierForRequest.isNull()) { | 222 if (!m_fragmentIdentifierForRequest.isNull()) { |
228 KURL url = request.url(); | 223 KURL url = request.url(); |
229 url.setFragmentIdentifier(m_fragmentIdentifierForRequest); | 224 url.setFragmentIdentifier(m_fragmentIdentifierForRequest); |
230 request.setURL(url); | 225 request.setURL(url); |
231 m_fragmentIdentifierForRequest = String(); | 226 m_fragmentIdentifierForRequest = String(); |
232 } | 227 } |
233 m_status = Pending; | 228 m_status = Pending; |
234 if (m_loader) { | 229 if (m_loader) { |
| 230 ASSERT(m_revalidatingRequest.isNull()); |
235 RELEASE_ASSERT(m_options.synchronousPolicy == RequestSynchronously); | 231 RELEASE_ASSERT(m_options.synchronousPolicy == RequestSynchronously); |
236 m_loader->changeToSynchronous(); | 232 m_loader->changeToSynchronous(); |
237 return; | 233 return; |
238 } | 234 } |
239 m_loader = ResourceLoader::create(fetcher, this, request, options); | 235 m_loader = ResourceLoader::create(fetcher, this, request, options); |
240 m_loader->start(); | 236 m_loader->start(); |
241 } | 237 } |
242 | 238 |
243 void Resource::checkNotify() | 239 void Resource::checkNotify() |
244 { | 240 { |
245 if (isLoading()) | 241 if (isLoading()) |
246 return; | 242 return; |
247 | 243 |
248 ResourceClientWalker<ResourceClient> w(m_clients); | 244 ResourceClientWalker<ResourceClient> w(m_clients); |
249 while (ResourceClient* c = w.next()) | 245 while (ResourceClient* c = w.next()) |
250 c->notifyFinished(this); | 246 c->notifyFinished(this); |
251 } | 247 } |
252 | 248 |
253 void Resource::appendData(const char* data, unsigned length) | 249 void Resource::appendData(const char* data, unsigned length) |
254 { | 250 { |
255 TRACE_EVENT0("blink", "Resource::appendData"); | 251 TRACE_EVENT0("blink", "Resource::appendData"); |
256 ASSERT(!m_resourceToRevalidate); | 252 ASSERT(m_revalidatingRequest.isNull()); |
257 ASSERT(!errorOccurred()); | 253 ASSERT(!errorOccurred()); |
258 if (m_options.dataBufferingPolicy == DoNotBufferData) | 254 if (m_options.dataBufferingPolicy == DoNotBufferData) |
259 return; | 255 return; |
260 if (m_data) | 256 if (m_data) |
261 m_data->append(data, length); | 257 m_data->append(data, length); |
262 else | 258 else |
263 m_data = SharedBuffer::createPurgeable(data, length); | 259 m_data = SharedBuffer::createPurgeable(data, length); |
264 setEncodedSize(m_data->size()); | 260 setEncodedSize(m_data->size()); |
265 } | 261 } |
266 | 262 |
267 void Resource::setResourceBuffer(PassRefPtr<SharedBuffer> resourceBuffer) | 263 void Resource::setResourceBuffer(PassRefPtr<SharedBuffer> resourceBuffer) |
268 { | 264 { |
269 ASSERT(!m_resourceToRevalidate); | 265 ASSERT(m_revalidatingRequest.isNull()); |
270 ASSERT(!errorOccurred()); | 266 ASSERT(!errorOccurred()); |
271 ASSERT(m_options.dataBufferingPolicy == BufferData); | 267 ASSERT(m_options.dataBufferingPolicy == BufferData); |
272 m_data = resourceBuffer; | 268 m_data = resourceBuffer; |
273 setEncodedSize(m_data->size()); | 269 setEncodedSize(m_data->size()); |
274 } | 270 } |
275 | 271 |
276 void Resource::setDataBufferingPolicy(DataBufferingPolicy dataBufferingPolicy) | 272 void Resource::setDataBufferingPolicy(DataBufferingPolicy dataBufferingPolicy) |
277 { | 273 { |
278 m_options.dataBufferingPolicy = dataBufferingPolicy; | 274 m_options.dataBufferingPolicy = dataBufferingPolicy; |
279 m_data.clear(); | 275 m_data.clear(); |
280 setEncodedSize(0); | 276 setEncodedSize(0); |
281 } | 277 } |
282 | 278 |
| 279 void Resource::markClientsFinished() |
| 280 { |
| 281 while (!m_clients.isEmpty()) { |
| 282 HashCountedSet<ResourceClient*>::iterator it = m_clients.begin(); |
| 283 for (int i = it->value; i; i--) { |
| 284 m_finishedClients.add(it->key); |
| 285 m_clients.remove(it); |
| 286 } |
| 287 } |
| 288 } |
| 289 |
283 void Resource::error(Resource::Status status) | 290 void Resource::error(Resource::Status status) |
284 { | 291 { |
285 if (m_resourceToRevalidate) | 292 if (!m_revalidatingRequest.isNull()) |
286 revalidationFailed(); | 293 m_revalidatingRequest = ResourceRequest(); |
287 | 294 |
288 if (!m_error.isNull() && (m_error.isCancellation() || !isPreloaded())) | 295 if (!m_error.isNull() && (m_error.isCancellation() || !isPreloaded())) |
289 memoryCache()->remove(this); | 296 memoryCache()->remove(this); |
290 | 297 |
291 setStatus(status); | 298 setStatus(status); |
292 ASSERT(errorOccurred()); | 299 ASSERT(errorOccurred()); |
293 m_data.clear(); | 300 m_data.clear(); |
294 | 301 |
295 setLoading(false); | 302 setLoading(false); |
296 checkNotify(); | 303 checkNotify(); |
| 304 markClientsFinished(); |
297 } | 305 } |
298 | 306 |
299 void Resource::finishOnePart() | 307 void Resource::finishOnePart() |
300 { | 308 { |
301 setLoading(false); | 309 setLoading(false); |
302 checkNotify(); | 310 checkNotify(); |
303 } | 311 } |
304 | 312 |
305 void Resource::finish() | 313 void Resource::finish() |
306 { | 314 { |
307 ASSERT(!m_resourceToRevalidate); | 315 ASSERT(m_revalidatingRequest.isNull()); |
308 ASSERT(!errorOccurred()); | 316 ASSERT(!errorOccurred()); |
309 finishOnePart(); | 317 finishOnePart(); |
| 318 markClientsFinished(); |
310 if (!errorOccurred()) | 319 if (!errorOccurred()) |
311 m_status = Cached; | 320 m_status = Cached; |
312 } | 321 } |
313 | 322 |
314 bool Resource::passesAccessControlCheck(SecurityOrigin* securityOrigin) const | 323 bool Resource::passesAccessControlCheck(SecurityOrigin* securityOrigin) const |
315 { | 324 { |
316 String ignoredErrorDescription; | 325 String ignoredErrorDescription; |
317 return passesAccessControlCheck(securityOrigin, ignoredErrorDescription); | 326 return passesAccessControlCheck(securityOrigin, ignoredErrorDescription); |
318 } | 327 } |
319 | 328 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 } | 433 } |
425 | 434 |
426 bool Resource::unlock() | 435 bool Resource::unlock() |
427 { | 436 { |
428 if (!m_data) | 437 if (!m_data) |
429 return false; | 438 return false; |
430 | 439 |
431 if (!m_data->isLocked()) | 440 if (!m_data->isLocked()) |
432 return true; | 441 return true; |
433 | 442 |
434 if (!memoryCache()->contains(this) || hasClients() || m_handleCount > 1 || m
_proxyResource || m_resourceToRevalidate || !m_loadFinishTime || !isSafeToUnlock
()) | 443 if (!memoryCache()->contains(this) || hasClients() || m_handleCount > 1 || !
m_revalidatingRequest.isNull() || !m_loadFinishTime || !isSafeToUnlock()) |
435 return false; | 444 return false; |
436 | 445 |
437 m_data->unlock(); | 446 m_data->unlock(); |
438 return true; | 447 return true; |
439 } | 448 } |
440 | 449 |
441 bool Resource::hasRightHandleCountApartFromCache(unsigned targetCount) const | 450 bool Resource::hasRightHandleCountApartFromCache(unsigned targetCount) const |
442 { | 451 { |
443 return m_handleCount == targetCount + (memoryCache()->contains(this) ? 1 : 0
); | 452 return m_handleCount == targetCount + (memoryCache()->contains(this) ? 1 : 0
); |
444 } | 453 } |
445 | 454 |
446 void Resource::responseReceived(const ResourceResponse& response, PassOwnPtr<Web
DataConsumerHandle>) | 455 void Resource::responseReceived(const ResourceResponse& response, PassOwnPtr<Web
DataConsumerHandle>) |
447 { | 456 { |
| 457 m_responseTimestamp = currentTime(); |
| 458 |
| 459 if (!m_revalidatingRequest.isNull()) { |
| 460 if (response.httpStatusCode() == 304) { |
| 461 revalidationSucceeded(response); |
| 462 return; |
| 463 } |
| 464 revalidationFailed(); |
| 465 } |
| 466 |
448 setResponse(response); | 467 setResponse(response); |
449 m_responseTimestamp = currentTime(); | |
450 String encoding = response.textEncodingName(); | 468 String encoding = response.textEncodingName(); |
451 if (!encoding.isNull()) | 469 if (!encoding.isNull()) |
452 setEncoding(encoding); | 470 setEncoding(encoding); |
453 | |
454 if (!m_resourceToRevalidate) | |
455 return; | |
456 if (response.httpStatusCode() == 304) | |
457 revalidationSucceeded(response); | |
458 else | |
459 revalidationFailed(); | |
460 } | 471 } |
461 | 472 |
462 void Resource::setSerializedCachedMetadata(const char* data, size_t size) | 473 void Resource::setSerializedCachedMetadata(const char* data, size_t size) |
463 { | 474 { |
464 // We only expect to receive cached metadata from the platform once. | 475 // We only expect to receive cached metadata from the platform once. |
465 // If this triggers, it indicates an efficiency problem which is most | 476 // If this triggers, it indicates an efficiency problem which is most |
466 // likely unexpected in code designed to improve performance. | 477 // likely unexpected in code designed to improve performance. |
467 ASSERT(!m_cachedMetadata); | 478 ASSERT(!m_cachedMetadata); |
468 ASSERT(!m_resourceToRevalidate); | 479 ASSERT(m_revalidatingRequest.isNull()); |
469 | 480 |
470 m_cachedMetadata = CachedMetadata::deserialize(data, size); | 481 m_cachedMetadata = CachedMetadata::deserialize(data, size); |
471 } | 482 } |
472 | 483 |
473 CachedMetadataHandler* Resource::cacheHandler() | 484 CachedMetadataHandler* Resource::cacheHandler() |
474 { | 485 { |
475 return m_cacheHandler.get(); | 486 return m_cacheHandler.get(); |
476 } | 487 } |
477 | 488 |
478 void Resource::setCachedMetadata(unsigned dataTypeID, const char* data, size_t s
ize, CachedMetadataHandler::CacheType cacheType) | 489 void Resource::setCachedMetadata(unsigned dataTypeID, const char* data, size_t s
ize, CachedMetadataHandler::CacheType cacheType) |
(...skipping 20 matching lines...) Expand all Loading... |
499 { | 510 { |
500 m_cachedMetadata.clear(); | 511 m_cachedMetadata.clear(); |
501 | 512 |
502 if (cacheType == CachedMetadataHandler::SendToPlatform) | 513 if (cacheType == CachedMetadataHandler::SendToPlatform) |
503 Platform::current()->cacheMetadata(m_response.url(), m_response.response
Time(), 0, 0); | 514 Platform::current()->cacheMetadata(m_response.url(), m_response.response
Time(), 0, 0); |
504 } | 515 } |
505 | 516 |
506 bool Resource::canDelete() const | 517 bool Resource::canDelete() const |
507 { | 518 { |
508 return !hasClients() && !m_loader && !m_preloadCount && hasRightHandleCountA
partFromCache(0) | 519 return !hasClients() && !m_loader && !m_preloadCount && hasRightHandleCountA
partFromCache(0) |
509 && !m_protectorCount && !m_resourceToRevalidate && !m_proxyResource; | 520 && !m_protectorCount; |
510 } | 521 } |
511 | 522 |
512 bool Resource::hasOneHandle() const | 523 bool Resource::hasOneHandle() const |
513 { | 524 { |
514 return hasRightHandleCountApartFromCache(1); | 525 return hasRightHandleCountApartFromCache(1); |
515 } | 526 } |
516 | 527 |
517 CachedMetadata* Resource::cachedMetadata(unsigned dataTypeID) const | 528 CachedMetadata* Resource::cachedMetadata(unsigned dataTypeID) const |
518 { | 529 { |
519 if (!m_cachedMetadata || m_cachedMetadata->dataTypeID() != dataTypeID) | 530 if (!m_cachedMetadata || m_cachedMetadata->dataTypeID() != dataTypeID) |
520 return nullptr; | 531 return nullptr; |
521 return m_cachedMetadata.get(); | 532 return m_cachedMetadata.get(); |
522 } | 533 } |
523 | 534 |
524 void Resource::clearLoader() | 535 void Resource::clearLoader() |
525 { | 536 { |
526 m_loader = nullptr; | 537 m_loader = nullptr; |
527 } | 538 } |
528 | 539 |
529 void Resource::addClient(ResourceClient* client) | |
530 { | |
531 if (addClientToSet(client)) | |
532 didAddClient(client); | |
533 } | |
534 | |
535 void Resource::didAddClient(ResourceClient* c) | 540 void Resource::didAddClient(ResourceClient* c) |
536 { | 541 { |
537 if (!isLoading() && !stillNeedsLoad()) | 542 if (!isLoading() && !stillNeedsLoad()) { |
538 c->notifyFinished(this); | 543 c->notifyFinished(this); |
| 544 if (m_clients.contains(c)) { |
| 545 m_finishedClients.add(c); |
| 546 m_clients.remove(c); |
| 547 } |
| 548 } |
539 } | 549 } |
540 | 550 |
541 static bool shouldSendCachedDataSynchronouslyForType(Resource::Type type) | 551 static bool shouldSendCachedDataSynchronouslyForType(Resource::Type type) |
542 { | 552 { |
543 // Some resources types default to return data synchronously. | 553 // Some resources types default to return data synchronously. |
544 // For most of these, it's because there are layout tests that | 554 // For most of these, it's because there are layout tests that |
545 // expect data to return synchronously in case of cache hit. In | 555 // expect data to return synchronously in case of cache hit. In |
546 // the case of fonts, there was a performance regression. | 556 // the case of fonts, there was a performance regression. |
547 // FIXME: Get to the point where we don't need to special-case sync/async | 557 // FIXME: Get to the point where we don't need to special-case sync/async |
548 // behavior for different resource types. | 558 // behavior for different resource types. |
549 if (type == Resource::Image) | 559 if (type == Resource::Image) |
550 return true; | 560 return true; |
551 if (type == Resource::CSSStyleSheet) | 561 if (type == Resource::CSSStyleSheet) |
552 return true; | 562 return true; |
553 if (type == Resource::Script) | 563 if (type == Resource::Script) |
554 return true; | 564 return true; |
555 if (type == Resource::Font) | 565 if (type == Resource::Font) |
556 return true; | 566 return true; |
557 return false; | 567 return false; |
558 } | 568 } |
559 | 569 |
560 bool Resource::addClientToSet(ResourceClient* client) | 570 void Resource::addClient(ResourceClient* client) |
561 { | 571 { |
562 ASSERT(!isPurgeable()); | 572 ASSERT(!isPurgeable()); |
563 | 573 |
564 if (m_preloadResult == PreloadNotReferenced) { | 574 if (m_preloadResult == PreloadNotReferenced) { |
565 if (isLoaded()) | 575 if (isLoaded()) |
566 m_preloadResult = PreloadReferencedWhileComplete; | 576 m_preloadResult = PreloadReferencedWhileComplete; |
567 else if (m_requestedFromNetworkingLayer) | 577 else if (m_requestedFromNetworkingLayer) |
568 m_preloadResult = PreloadReferencedWhileLoading; | 578 m_preloadResult = PreloadReferencedWhileLoading; |
569 else | 579 else |
570 m_preloadResult = PreloadReferenced; | 580 m_preloadResult = PreloadReferenced; |
571 } | 581 } |
572 if (!hasClients()) | 582 if (!hasClients()) |
573 memoryCache()->makeLive(this); | 583 memoryCache()->makeLive(this); |
574 | 584 |
| 585 if (!m_revalidatingRequest.isNull()) { |
| 586 m_clients.add(client); |
| 587 return; |
| 588 } |
| 589 |
575 // If we have existing data to send to the new client and the resource type
supprts it, send it asynchronously. | 590 // If we have existing data to send to the new client and the resource type
supprts it, send it asynchronously. |
576 if (!m_response.isNull() && !m_proxyResource && !shouldSendCachedDataSynchro
nouslyForType(type()) && !m_needsSynchronousCacheHit) { | 591 if (!m_response.isNull() && !shouldSendCachedDataSynchronouslyForType(type()
) && !m_needsSynchronousCacheHit) { |
577 m_clientsAwaitingCallback.add(client); | 592 m_clientsAwaitingCallback.add(client); |
578 ResourceCallback::callbackHandler()->schedule(this); | 593 ResourceCallback::callbackHandler()->schedule(this); |
579 return false; | 594 return; |
580 } | 595 } |
581 | 596 |
582 m_clients.add(client); | 597 m_clients.add(client); |
583 return true; | 598 didAddClient(client); |
| 599 return; |
584 } | 600 } |
585 | 601 |
586 void Resource::removeClient(ResourceClient* client) | 602 void Resource::removeClient(ResourceClient* client) |
587 { | 603 { |
588 if (m_clientsAwaitingCallback.contains(client)) { | 604 ASSERT(hasClient(client)); |
589 ASSERT(!m_clients.contains(client)); | 605 if (m_finishedClients.contains(client)) |
| 606 m_finishedClients.remove(client); |
| 607 else if (m_clientsAwaitingCallback.contains(client)) |
590 m_clientsAwaitingCallback.remove(client); | 608 m_clientsAwaitingCallback.remove(client); |
591 } else { | 609 else |
592 ASSERT(m_clients.contains(client)); | |
593 m_clients.remove(client); | 610 m_clients.remove(client); |
594 didRemoveClient(client); | 611 |
595 } | 612 didRemoveClient(client); |
596 | 613 |
597 if (m_clientsAwaitingCallback.isEmpty()) | 614 if (m_clientsAwaitingCallback.isEmpty()) |
598 ResourceCallback::callbackHandler()->cancel(this); | 615 ResourceCallback::callbackHandler()->cancel(this); |
599 | 616 |
600 bool deleted = deleteIfPossible(); | 617 bool deleted = deleteIfPossible(); |
601 if (!deleted && !hasClients()) { | 618 if (!deleted && !hasClients()) { |
602 memoryCache()->makeDead(this); | 619 memoryCache()->makeDead(this); |
603 if (!m_switchingClientsToRevalidatedResource) | 620 if (!m_switchingClientsToRevalidatedResource) |
604 allClientsRemoved(); | 621 allClientsRemoved(); |
605 | 622 |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
710 // Prevent the case when there are clients waiting but no callback scheduled
. | 727 // Prevent the case when there are clients waiting but no callback scheduled
. |
711 ASSERT(m_clientsAwaitingCallback.isEmpty() || scheduled); | 728 ASSERT(m_clientsAwaitingCallback.isEmpty() || scheduled); |
712 } | 729 } |
713 | 730 |
714 void Resource::prune() | 731 void Resource::prune() |
715 { | 732 { |
716 destroyDecodedDataIfPossible(); | 733 destroyDecodedDataIfPossible(); |
717 unlock(); | 734 unlock(); |
718 } | 735 } |
719 | 736 |
720 void Resource::setResourceToRevalidate(Resource* resource) | |
721 { | |
722 ASSERT(resource); | |
723 ASSERT(!m_resourceToRevalidate); | |
724 ASSERT(resource != this); | |
725 ASSERT(m_handlesToRevalidate.isEmpty()); | |
726 ASSERT(resource->type() == type()); | |
727 | 737 |
728 WTF_LOG(ResourceLoading, "Resource %p setResourceToRevalidate %p", this, res
ource); | 738 void Resource::revalidationSucceeded(const ResourceResponse& validatingResponse) |
729 | |
730 // The following assert should be investigated whenever it occurs. Although
it should never fire, it currently does in rare circumstances. | |
731 // https://bugs.webkit.org/show_bug.cgi?id=28604. | |
732 // So the code needs to be robust to this assert failing thus the "if (m_res
ourceToRevalidate->m_proxyResource == this)" in Resource::clearResourceToRevalid
ate. | |
733 ASSERT(!resource->m_proxyResource); | |
734 | |
735 resource->m_proxyResource = this; | |
736 m_resourceToRevalidate = resource; | |
737 } | |
738 | |
739 void Resource::clearResourceToRevalidate() | |
740 { | |
741 ASSERT(m_resourceToRevalidate); | |
742 if (m_switchingClientsToRevalidatedResource) | |
743 return; | |
744 | |
745 // 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. | |
746 if (m_resourceToRevalidate->m_proxyResource == this) { | |
747 m_resourceToRevalidate->m_proxyResource = nullptr; | |
748 m_resourceToRevalidate->deleteIfPossible(); | |
749 } | |
750 m_handlesToRevalidate.clear(); | |
751 m_resourceToRevalidate = nullptr; | |
752 deleteIfPossible(); | |
753 } | |
754 | |
755 void Resource::switchClientsToRevalidatedResource() | |
756 { | |
757 ASSERT(m_resourceToRevalidate); | |
758 ASSERT(memoryCache()->contains(m_resourceToRevalidate)); | |
759 ASSERT(!memoryCache()->contains(this)); | |
760 | |
761 WTF_LOG(ResourceLoading, "Resource %p switchClientsToRevalidatedResource %p"
, this, m_resourceToRevalidate.get()); | |
762 | |
763 m_resourceToRevalidate->m_identifier = m_identifier; | |
764 | |
765 m_switchingClientsToRevalidatedResource = true; | |
766 for (ResourcePtrBase* handle : m_handlesToRevalidate) { | |
767 handle->m_resource = m_resourceToRevalidate; | |
768 m_resourceToRevalidate->registerHandle(handle); | |
769 --m_handleCount; | |
770 } | |
771 ASSERT(!m_handleCount); | |
772 m_handlesToRevalidate.clear(); | |
773 | |
774 Vector<ResourceClient*> clientsToMove; | |
775 for (const auto& clientHashEntry : m_clients) { | |
776 unsigned count = clientHashEntry.value; | |
777 while (count--) | |
778 clientsToMove.append(clientHashEntry.key); | |
779 } | |
780 | |
781 unsigned moveCount = clientsToMove.size(); | |
782 for (unsigned n = 0; n < moveCount; ++n) | |
783 removeClient(clientsToMove[n]); | |
784 ASSERT(m_clients.isEmpty()); | |
785 | |
786 for (unsigned n = 0; n < moveCount; ++n) | |
787 m_resourceToRevalidate->addClientToSet(clientsToMove[n]); | |
788 for (unsigned n = 0; n < moveCount; ++n) { | |
789 // Calling didAddClient may do anything, including trying to cancel reva
lidation. | |
790 // Assert that it didn't succeed. | |
791 ASSERT(m_resourceToRevalidate); | |
792 // Calling didAddClient for a client may end up removing another client.
In that case it won't be in the set anymore. | |
793 if (m_resourceToRevalidate->m_clients.contains(clientsToMove[n])) | |
794 m_resourceToRevalidate->didAddClient(clientsToMove[n]); | |
795 } | |
796 m_switchingClientsToRevalidatedResource = false; | |
797 } | |
798 | |
799 void Resource::updateResponseAfterRevalidation(const ResourceResponse& validatin
gResponse) | |
800 { | 739 { |
801 m_responseTimestamp = currentTime(); | 740 m_responseTimestamp = currentTime(); |
| 741 m_response.setResourceLoadTiming(validatingResponse.resourceLoadTiming()); |
802 | 742 |
803 // RFC2616 10.3.5 | 743 // RFC2616 10.3.5 |
804 // Update cached headers from the 304 response | 744 // Update cached headers from the 304 response |
805 const HTTPHeaderMap& newHeaders = validatingResponse.httpHeaderFields(); | 745 const HTTPHeaderMap& newHeaders = validatingResponse.httpHeaderFields(); |
806 for (const auto& header : newHeaders) { | 746 for (const auto& header : newHeaders) { |
807 // Entity headers should not be sent by servers when generating a 304 | 747 // Entity headers should not be sent by servers when generating a 304 |
808 // response; misconfigured servers send them anyway. We shouldn't allow | 748 // response; misconfigured servers send them anyway. We shouldn't allow |
809 // such headers to update the original request. We'll base this on the | 749 // such headers to update the original request. We'll base this on the |
810 // list defined by RFC2616 7.1, with a few additions for extension heade
rs | 750 // list defined by RFC2616 7.1, with a few additions for extension heade
rs |
811 // we care about. | 751 // we care about. |
812 if (!shouldUpdateHeaderAfterRevalidation(header.key)) | 752 if (!shouldUpdateHeaderAfterRevalidation(header.key)) |
813 continue; | 753 continue; |
814 m_response.setHTTPHeaderField(header.key, header.value); | 754 m_response.setHTTPHeaderField(header.key, header.value); |
815 } | 755 } |
816 } | |
817 | 756 |
818 void Resource::revalidationSucceeded(const ResourceResponse& response) | |
819 { | |
820 ASSERT(m_resourceToRevalidate); | |
821 ASSERT(!memoryCache()->contains(m_resourceToRevalidate)); | |
822 ASSERT(m_resourceToRevalidate->isLoaded()); | |
823 | |
824 // Calling evict() can potentially delete revalidatingResource, which we use | |
825 // below. This mustn't be the case since revalidation means it is loaded | |
826 // and so canDelete() is false. | |
827 ASSERT(!canDelete()); | |
828 | |
829 m_resourceToRevalidate->updateResponseAfterRevalidation(response); | |
830 memoryCache()->replace(m_resourceToRevalidate, this); | |
831 | |
832 switchClientsToRevalidatedResource(); | |
833 assertAlive(); | 757 assertAlive(); |
834 // clearResourceToRevalidate deletes this. | 758 m_resourceRequest = m_revalidatingRequest; |
835 clearResourceToRevalidate(); | 759 m_revalidatingRequest = ResourceRequest(); |
836 } | 760 } |
837 | 761 |
838 void Resource::revalidationFailed() | 762 void Resource::revalidationFailed() |
839 { | 763 { |
840 ASSERT(WTF::isMainThread()); | 764 m_resourceRequest = m_revalidatingRequest; |
841 WTF_LOG(ResourceLoading, "Revalidation failed for %p", this); | 765 m_revalidatingRequest = ResourceRequest(); |
842 ASSERT(resourceToRevalidate()); | 766 m_data.clear(); |
843 clearResourceToRevalidate(); | 767 destroyDecodedDataForFailedRevalidation(); |
844 } | 768 } |
845 | 769 |
846 void Resource::registerHandle(ResourcePtrBase* h) | 770 void Resource::registerHandle(ResourcePtrBase* h) |
847 { | 771 { |
848 assertAlive(); | 772 assertAlive(); |
849 ++m_handleCount; | 773 ++m_handleCount; |
850 if (m_resourceToRevalidate) | |
851 m_handlesToRevalidate.add(h); | |
852 } | 774 } |
853 | 775 |
854 void Resource::unregisterHandle(ResourcePtrBase* h) | 776 void Resource::unregisterHandle(ResourcePtrBase* h) |
855 { | 777 { |
856 assertAlive(); | 778 assertAlive(); |
857 ASSERT(m_handleCount > 0); | 779 ASSERT(m_handleCount > 0); |
858 --m_handleCount; | 780 --m_handleCount; |
859 | 781 |
860 if (m_resourceToRevalidate) | |
861 m_handlesToRevalidate.remove(h); | |
862 | |
863 if (!m_handleCount) { | 782 if (!m_handleCount) { |
864 if (deleteIfPossible()) | 783 if (deleteIfPossible()) |
865 return; | 784 return; |
866 unlock(); | 785 unlock(); |
867 } else if (m_handleCount == 1 && memoryCache()->contains(this)) { | 786 } else if (m_handleCount == 1 && memoryCache()->contains(this)) { |
868 unlock(); | 787 unlock(); |
869 if (!hasClients()) | 788 if (!hasClients()) |
870 memoryCache()->prune(this); | 789 memoryCache()->prune(this); |
871 } | 790 } |
872 } | 791 } |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1108 return "ImportResource"; | 1027 return "ImportResource"; |
1109 case Resource::Media: | 1028 case Resource::Media: |
1110 return "Media"; | 1029 return "Media"; |
1111 } | 1030 } |
1112 ASSERT_NOT_REACHED(); | 1031 ASSERT_NOT_REACHED(); |
1113 return "Unknown"; | 1032 return "Unknown"; |
1114 } | 1033 } |
1115 #endif // !LOG_DISABLED | 1034 #endif // !LOG_DISABLED |
1116 | 1035 |
1117 } // namespace blink | 1036 } // namespace blink |
OLD | NEW |