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 10 matching lines...) Expand all Loading... |
21 Boston, MA 02110-1301, USA. | 21 Boston, MA 02110-1301, USA. |
22 */ | 22 */ |
23 | 23 |
24 #include "core/fetch/Resource.h" | 24 #include "core/fetch/Resource.h" |
25 | 25 |
26 #include "core/fetch/CachedMetadata.h" | 26 #include "core/fetch/CachedMetadata.h" |
27 #include "core/fetch/CrossOriginAccessControl.h" | 27 #include "core/fetch/CrossOriginAccessControl.h" |
28 #include "core/fetch/FetchInitiatorTypeNames.h" | 28 #include "core/fetch/FetchInitiatorTypeNames.h" |
29 #include "core/fetch/MemoryCache.h" | 29 #include "core/fetch/MemoryCache.h" |
30 #include "core/fetch/ResourceClient.h" | 30 #include "core/fetch/ResourceClient.h" |
31 #include "core/fetch/ResourceClientOrObserverWalker.h" | 31 #include "core/fetch/ResourceClientWalker.h" |
32 #include "core/fetch/ResourceLoader.h" | 32 #include "core/fetch/ResourceLoader.h" |
33 #include "core/inspector/InstanceCounters.h" | 33 #include "core/inspector/InstanceCounters.h" |
34 #include "platform/Histogram.h" | 34 #include "platform/Histogram.h" |
35 #include "platform/RuntimeEnabledFeatures.h" | 35 #include "platform/RuntimeEnabledFeatures.h" |
36 #include "platform/SharedBuffer.h" | 36 #include "platform/SharedBuffer.h" |
37 #include "platform/TraceEvent.h" | 37 #include "platform/TraceEvent.h" |
38 #include "platform/network/HTTPParsers.h" | 38 #include "platform/network/HTTPParsers.h" |
39 #include "platform/weborigin/KURL.h" | 39 #include "platform/weborigin/KURL.h" |
40 #include "public/platform/Platform.h" | 40 #include "public/platform/Platform.h" |
41 #include "public/platform/WebCachePolicy.h" | 41 #include "public/platform/WebCachePolicy.h" |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
301 , m_overheadSize(calculateOverheadSize()) | 301 , m_overheadSize(calculateOverheadSize()) |
302 , m_preloadCount(0) | 302 , m_preloadCount(0) |
303 , m_preloadDiscoveryTime(0.0) | 303 , m_preloadDiscoveryTime(0.0) |
304 , m_cacheIdentifier(MemoryCache::defaultCacheIdentifier()) | 304 , m_cacheIdentifier(MemoryCache::defaultCacheIdentifier()) |
305 , m_preloadResult(PreloadNotReferenced) | 305 , m_preloadResult(PreloadNotReferenced) |
306 , m_type(type) | 306 , m_type(type) |
307 , m_status(NotStarted) | 307 , m_status(NotStarted) |
308 , m_needsSynchronousCacheHit(false) | 308 , m_needsSynchronousCacheHit(false) |
309 , m_linkPreload(false) | 309 , m_linkPreload(false) |
310 , m_isRevalidating(false) | 310 , m_isRevalidating(false) |
| 311 , m_isAlive(false) |
311 , m_options(options) | 312 , m_options(options) |
312 , m_responseTimestamp(currentTime()) | 313 , m_responseTimestamp(currentTime()) |
313 , m_cancelTimer(this, &Resource::cancelTimerFired) | 314 , m_cancelTimer(this, &Resource::cancelTimerFired) |
314 , m_resourceRequest(request) | 315 , m_resourceRequest(request) |
315 { | 316 { |
316 ASSERT(m_type == unsigned(type)); // m_type is a bitfield, so this tests car
eless updates of the enum. | 317 ASSERT(m_type == unsigned(type)); // m_type is a bitfield, so this tests car
eless updates of the enum. |
317 InstanceCounters::incrementCounter(InstanceCounters::ResourceCounter); | 318 InstanceCounters::incrementCounter(InstanceCounters::ResourceCounter); |
318 | 319 |
319 // Currently we support the metadata caching only for HTTP family. | 320 // Currently we support the metadata caching only for HTTP family. |
320 if (m_resourceRequest.url().protocolIsInHTTPFamily()) | 321 if (m_resourceRequest.url().protocolIsInHTTPFamily()) |
321 m_cacheHandler = CachedMetadataHandlerImpl::create(this); | 322 m_cacheHandler = CachedMetadataHandlerImpl::create(this); |
322 MemoryCoordinator::instance().registerClient(this); | 323 MemoryCoordinator::instance().registerClient(this); |
323 } | 324 } |
324 | 325 |
325 Resource::~Resource() | 326 Resource::~Resource() |
326 { | 327 { |
327 InstanceCounters::decrementCounter(InstanceCounters::ResourceCounter); | 328 InstanceCounters::decrementCounter(InstanceCounters::ResourceCounter); |
328 } | 329 } |
329 | 330 |
330 DEFINE_TRACE(Resource) | 331 DEFINE_TRACE(Resource) |
331 { | 332 { |
332 visitor->trace(m_loader); | 333 visitor->trace(m_loader); |
333 visitor->trace(m_cacheHandler); | 334 visitor->trace(m_cacheHandler); |
| 335 visitor->trace(m_clients); |
| 336 visitor->trace(m_clientsAwaitingCallback); |
| 337 visitor->trace(m_finishedClients); |
334 MemoryCoordinatorClient::trace(visitor); | 338 MemoryCoordinatorClient::trace(visitor); |
335 } | 339 } |
336 | 340 |
337 void Resource::setLoader(ResourceLoader* loader) | 341 void Resource::setLoader(ResourceLoader* loader) |
338 { | 342 { |
339 RELEASE_ASSERT(!m_loader); | 343 RELEASE_ASSERT(!m_loader); |
340 ASSERT(stillNeedsLoad()); | 344 ASSERT(stillNeedsLoad()); |
341 m_loader = loader; | 345 m_loader = loader; |
342 m_status = Pending; | 346 m_status = Pending; |
343 } | 347 } |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
670 m_preloadResult = PreloadReferencedWhileLoading; | 674 m_preloadResult = PreloadReferencedWhileLoading; |
671 else | 675 else |
672 m_preloadResult = PreloadReferenced; | 676 m_preloadResult = PreloadReferenced; |
673 | 677 |
674 if (m_preloadDiscoveryTime) { | 678 if (m_preloadDiscoveryTime) { |
675 int timeSinceDiscovery = static_cast<int>(1000 * (monotonicallyIncre
asingTime() - m_preloadDiscoveryTime)); | 679 int timeSinceDiscovery = static_cast<int>(1000 * (monotonicallyIncre
asingTime() - m_preloadDiscoveryTime)); |
676 DEFINE_STATIC_LOCAL(CustomCountHistogram, preloadDiscoveryHistogram,
("PreloadScanner.ReferenceTime", 0, 10000, 50)); | 680 DEFINE_STATIC_LOCAL(CustomCountHistogram, preloadDiscoveryHistogram,
("PreloadScanner.ReferenceTime", 0, 10000, 50)); |
677 preloadDiscoveryHistogram.count(timeSinceDiscovery); | 681 preloadDiscoveryHistogram.count(timeSinceDiscovery); |
678 } | 682 } |
679 } | 683 } |
680 if (!hasClientsOrObservers()) | 684 if (!hasClientsOrObservers()) { |
| 685 m_isAlive = true; |
681 memoryCache()->makeLive(this); | 686 memoryCache()->makeLive(this); |
| 687 } |
682 } | 688 } |
683 | 689 |
684 void Resource::addClient(ResourceClient* client, PreloadReferencePolicy policy) | 690 void Resource::addClient(ResourceClient* client, PreloadReferencePolicy policy) |
685 { | 691 { |
686 willAddClientOrObserver(policy); | 692 willAddClientOrObserver(policy); |
687 | 693 |
688 if (m_isRevalidating) { | 694 if (m_isRevalidating) { |
689 m_clients.add(client); | 695 m_clients.add(client); |
690 return; | 696 return; |
691 } | 697 } |
692 | 698 |
693 // If we have existing data to send to the new client and the resource type
supprts it, send it asynchronously. | 699 // If we have existing data to send to the new client and the resource type
supprts it, send it asynchronously. |
694 if (!m_response.isNull() && !shouldSendCachedDataSynchronouslyForType(getTyp
e()) && !m_needsSynchronousCacheHit) { | 700 if (!m_response.isNull() && !shouldSendCachedDataSynchronouslyForType(getTyp
e()) && !m_needsSynchronousCacheHit) { |
695 m_clientsAwaitingCallback.add(client); | 701 m_clientsAwaitingCallback.add(client); |
696 ResourceCallback::callbackHandler().schedule(this); | 702 ResourceCallback::callbackHandler().schedule(this); |
697 return; | 703 return; |
698 } | 704 } |
699 | 705 |
700 m_clients.add(client); | 706 m_clients.add(client); |
701 didAddClient(client); | 707 didAddClient(client); |
702 return; | 708 return; |
703 } | 709 } |
704 | 710 |
705 void Resource::removeClient(ResourceClient* client) | 711 void Resource::removeClient(ResourceClient* client) |
706 { | 712 { |
707 ASSERT(hasClient(client)); | 713 // This code may be called in a pre-finalizer, where weak members in the |
| 714 // HashCountedSet are already swept out. |
| 715 |
708 if (m_finishedClients.contains(client)) | 716 if (m_finishedClients.contains(client)) |
709 m_finishedClients.remove(client); | 717 m_finishedClients.remove(client); |
710 else if (m_clientsAwaitingCallback.contains(client)) | 718 else if (m_clientsAwaitingCallback.contains(client)) |
711 m_clientsAwaitingCallback.remove(client); | 719 m_clientsAwaitingCallback.remove(client); |
712 else | 720 else |
713 m_clients.remove(client); | 721 m_clients.remove(client); |
714 | 722 |
715 if (m_clientsAwaitingCallback.isEmpty()) | 723 if (m_clientsAwaitingCallback.isEmpty()) |
716 ResourceCallback::callbackHandler().cancel(this); | 724 ResourceCallback::callbackHandler().cancel(this); |
717 | 725 |
718 didRemoveClientOrObserver(); | 726 didRemoveClientOrObserver(); |
719 // This object may be dead here. | |
720 } | 727 } |
721 | 728 |
722 void Resource::didRemoveClientOrObserver() | 729 void Resource::didRemoveClientOrObserver() |
723 { | 730 { |
724 if (!hasClientsOrObservers()) { | 731 if (!hasClientsOrObservers() && m_isAlive) { |
| 732 m_isAlive = false; |
725 memoryCache()->makeDead(this); | 733 memoryCache()->makeDead(this); |
726 allClientsAndObserversRemoved(); | 734 allClientsAndObserversRemoved(); |
727 | 735 |
728 // RFC2616 14.9.2: | 736 // RFC2616 14.9.2: |
729 // "no-store: ... MUST make a best-effort attempt to remove the informat
ion from volatile storage as promptly as possible" | 737 // "no-store: ... MUST make a best-effort attempt to remove the informat
ion from volatile storage as promptly as possible" |
730 // "... History buffers MAY store such responses as part of their normal
operation." | 738 // "... History buffers MAY store such responses as part of their normal
operation." |
731 // We allow non-secure content to be reused in history, but we do not al
low secure content to be reused. | 739 // We allow non-secure content to be reused in history, but we do not al
low secure content to be reused. |
732 if (hasCacheControlNoStoreHeader() && url().protocolIs("https")) { | 740 if (hasCacheControlNoStoreHeader() && url().protocolIs("https")) { |
733 memoryCache()->remove(this); | 741 memoryCache()->remove(this); |
734 memoryCache()->prune(); | 742 memoryCache()->prune(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
785 { | 793 { |
786 // We're going to notify clients one by one. It is simple if the client does
nothing. | 794 // We're going to notify clients one by one. It is simple if the client does
nothing. |
787 // However there are a couple other things that can happen. | 795 // However there are a couple other things that can happen. |
788 // | 796 // |
789 // 1. Clients can be added during the loop. Make sure they are not processed
. | 797 // 1. Clients can be added during the loop. Make sure they are not processed
. |
790 // 2. Clients can be removed during the loop. Make sure they are always avai
lable to be | 798 // 2. Clients can be removed during the loop. Make sure they are always avai
lable to be |
791 // removed. Also don't call removed clients or add them back. | 799 // removed. Also don't call removed clients or add them back. |
792 | 800 |
793 // Handle case (1) by saving a list of clients to notify. A separate list al
so ensure | 801 // Handle case (1) by saving a list of clients to notify. A separate list al
so ensure |
794 // a client is either in m_clients or m_clientsAwaitingCallback. | 802 // a client is either in m_clients or m_clientsAwaitingCallback. |
795 Vector<ResourceClient*> clientsToNotify; | 803 HeapVector<Member<ResourceClient>> clientsToNotify; |
796 copyToVector(m_clientsAwaitingCallback, clientsToNotify); | 804 copyToVector(m_clientsAwaitingCallback, clientsToNotify); |
797 | 805 |
798 for (const auto& client : clientsToNotify) { | 806 for (const auto& client : clientsToNotify) { |
799 // Handle case (2) to skip removed clients. | 807 // Handle case (2) to skip removed clients. |
800 if (!m_clientsAwaitingCallback.remove(client)) | 808 if (!m_clientsAwaitingCallback.remove(client)) |
801 continue; | 809 continue; |
802 m_clients.add(client); | 810 m_clients.add(client); |
803 didAddClient(client); | 811 didAddClient(client); |
804 } | 812 } |
805 | 813 |
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1065 case Resource::TextTrack: | 1073 case Resource::TextTrack: |
1066 case Resource::Media: | 1074 case Resource::Media: |
1067 case Resource::Manifest: | 1075 case Resource::Manifest: |
1068 return false; | 1076 return false; |
1069 } | 1077 } |
1070 ASSERT_NOT_REACHED(); | 1078 ASSERT_NOT_REACHED(); |
1071 return false; | 1079 return false; |
1072 } | 1080 } |
1073 | 1081 |
1074 } // namespace blink | 1082 } // namespace blink |
OLD | NEW |