Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / fetch / Resource.cpp
index c0a3235..9596f8d 100644 (file)
@@ -24,7 +24,7 @@
 #include "config.h"
 #include "core/fetch/Resource.h"
 
-#include "FetchInitiatorTypeNames.h"
+#include "core/FetchInitiatorTypeNames.h"
 #include "core/fetch/CachedMetadata.h"
 #include "core/fetch/CrossOriginAccessControl.h"
 #include "core/fetch/MemoryCache.h"
@@ -36,6 +36,7 @@
 #include "core/inspector/InspectorInstrumentation.h"
 #include "platform/Logging.h"
 #include "platform/SharedBuffer.h"
+#include "platform/TraceEvent.h"
 #include "platform/weborigin/KURL.h"
 #include "public/platform/Platform.h"
 #include "wtf/CurrentTime.h"
@@ -47,7 +48,7 @@
 
 using namespace WTF;
 
-namespace WebCore {
+namespace blink {
 
 // These response headers are not copied from a revalidated response to the
 // cached response headers. For compatibility, this list is based on Chromium's
@@ -92,12 +93,12 @@ static inline bool shouldUpdateHeaderAfterRevalidation(const AtomicString& heade
 }
 
 DEFINE_DEBUG_ONLY_GLOBAL(RefCountedLeakCounter, cachedResourceLeakCounter, ("Resource"));
+unsigned Resource::s_instanceCount = 0;
 
 Resource::Resource(const ResourceRequest& request, Type type)
     : m_resourceRequest(request)
     , m_responseTimestamp(currentTime())
     , m_cancelTimer(this, &Resource::cancelTimerFired)
-    , m_lastDecodedAccessTime(0)
     , m_loadFinishTime(0)
     , m_identifier(0)
     , m_encodedSize(0)
@@ -105,8 +106,8 @@ Resource::Resource(const ResourceRequest& request, Type type)
     , m_handleCount(0)
     , m_preloadCount(0)
     , m_protectorCount(0)
+    , m_cacheIdentifier(MemoryCache::defaultCacheIdentifier())
     , m_preloadResult(PreloadNotReferenced)
-    , m_cacheLiveResourcePriority(CacheLiveResourcePriorityLow)
     , m_requestedFromNetworkingLayer(false)
     , m_loading(false)
     , m_switchingClientsToRevalidatedResource(false)
@@ -117,13 +118,15 @@ Resource::Resource(const ResourceRequest& request, Type type)
 #ifdef ENABLE_RESOURCE_IS_DELETED_CHECK
     , m_deleted(false)
 #endif
-    , m_resourceToRevalidate(0)
-    , m_proxyResource(0)
+    , m_resourceToRevalidate(nullptr)
+    , m_proxyResource(nullptr)
 {
     ASSERT(m_type == unsigned(type)); // m_type is a bitfield, so this tests careless updates of the enum.
+    ++s_instanceCount;
 #ifndef NDEBUG
     cachedResourceLeakCounter.increment();
 #endif
+    memoryCache()->registerLiveResource(*this);
 
     if (!m_resourceRequest.url().hasFragmentIdentifier())
         return;
@@ -140,7 +143,6 @@ Resource::~Resource()
     ASSERT(canDelete());
     RELEASE_ASSERT(!memoryCache()->contains(this));
     RELEASE_ASSERT(!ResourceCallback::callbackHandler()->isScheduled(this));
-    ASSERT(url().isNull() || memoryCache()->resourceForURL(KURL(ParsedURLString, url())) != this);
     assertAlive();
 
 #ifdef ENABLE_RESOURCE_IS_DELETED_CHECK
@@ -149,6 +151,18 @@ Resource::~Resource()
 #ifndef NDEBUG
     cachedResourceLeakCounter.decrement();
 #endif
+    --s_instanceCount;
+}
+
+void Resource::dispose()
+{
+}
+
+void Resource::trace(Visitor* visitor)
+{
+    visitor->trace(m_loader);
+    visitor->trace(m_resourceToRevalidate);
+    visitor->trace(m_proxyResource);
 }
 
 void Resource::failBeforeStarting()
@@ -199,9 +213,9 @@ void Resource::checkNotify()
         c->notifyFinished(this);
 }
 
-void Resource::appendData(const char* data, int length)
+void Resource::appendData(const char* data, unsigned length)
 {
-    TRACE_EVENT0("webkit", "Resource::appendData");
+    TRACE_EVENT0("blink", "Resource::appendData");
     ASSERT(!m_resourceToRevalidate);
     ASSERT(!errorOccurred());
     if (m_options.dataBufferingPolicy == DoNotBufferData)
@@ -251,11 +265,10 @@ void Resource::finishOnePart()
     checkNotify();
 }
 
-void Resource::finish(double finishTime)
+void Resource::finish()
 {
     ASSERT(!m_resourceToRevalidate);
     ASSERT(!errorOccurred());
-    m_loadFinishTime = finishTime;
     finishOnePart();
     if (!errorOccurred())
         m_status = Cached;
@@ -269,7 +282,7 @@ bool Resource::passesAccessControlCheck(SecurityOrigin* securityOrigin)
 
 bool Resource::passesAccessControlCheck(SecurityOrigin* securityOrigin, String& errorDescription)
 {
-    return WebCore::passesAccessControlCheck(m_response, resourceRequest().allowStoredCredentials() ? AllowStoredCredentials : DoNotAllowStoredCredentials, securityOrigin, errorDescription);
+    return blink::passesAccessControlCheck(m_response, resourceRequest().allowStoredCredentials() ? AllowStoredCredentials : DoNotAllowStoredCredentials, securityOrigin, errorDescription);
 }
 
 static double currentAge(const ResourceResponse& response, double responseTimestamp)
@@ -284,7 +297,7 @@ static double currentAge(const ResourceResponse& response, double responseTimest
     return correctedReceivedAge + residentTime;
 }
 
-static double freshnessLifetime(const ResourceResponse& response, double responseTimestamp)
+static double freshnessLifetime(ResourceResponse& response, double responseTimestamp)
 {
 #if !OS(ANDROID)
     // On desktop, local files should be reloaded in case they change.
@@ -313,7 +326,7 @@ static double freshnessLifetime(const ResourceResponse& response, double respons
     return 0;
 }
 
-static bool canUseResponse(const ResourceResponse& response, double responseTimestamp)
+static bool canUseResponse(ResourceResponse& response, double responseTimestamp)
 {
     if (response.isNull())
         return false;
@@ -339,16 +352,16 @@ static bool canUseResponse(const ResourceResponse& response, double responseTime
     return currentAge(response, responseTimestamp) <= freshnessLifetime(response, responseTimestamp);
 }
 
-const ResourceRequest& Resource::lastResourceRequest()
+const ResourceRequest& Resource::lastResourceRequest() const
 {
     if (!m_redirectChain.size())
         return m_resourceRequest;
     return m_redirectChain.last().m_request;
 }
 
-void Resource::willSendRequest(ResourceRequest& request, const ResourceResponse& response)
+void Resource::willFollowRedirect(ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
 {
-    m_redirectChain.append(RedirectPair(request, response));
+    m_redirectChain.append(RedirectPair(newRequest, redirectResponse));
     m_requestedFromNetworkingLayer = true;
 }
 
@@ -367,7 +380,12 @@ bool Resource::unlock()
     return true;
 }
 
-void Resource::responseReceived(const ResourceResponse& response)
+bool Resource::hasRightHandleCountApartFromCache(unsigned targetCount) const
+{
+    return m_handleCount == targetCount + (memoryCache()->contains(this) ? 1 : 0);
+}
+
+void Resource::responseReceived(const ResourceResponse& response, PassOwnPtr<WebDataConsumerHandle>)
 {
     setResponse(response);
     m_responseTimestamp = currentTime();
@@ -394,7 +412,7 @@ void Resource::setSerializedCachedMetadata(const char* data, size_t size)
     m_cachedMetadata = CachedMetadata::deserialize(data, size);
 }
 
-void Resource::setCachedMetadata(unsigned dataTypeID, const char* data, size_t size)
+void Resource::setCachedMetadata(unsigned dataTypeID, const char* data, size_t size, MetadataCacheType cacheType)
 {
     // Currently, only one type of cached metadata per resource is supported.
     // If the need arises for multiple types of metadata per resource this could
@@ -402,25 +420,34 @@ void Resource::setCachedMetadata(unsigned dataTypeID, const char* data, size_t s
     ASSERT(!m_cachedMetadata);
 
     m_cachedMetadata = CachedMetadata::create(dataTypeID, data, size);
-    const Vector<char>& serializedData = m_cachedMetadata->serialize();
-    blink::Platform::current()->cacheMetadata(m_response.url(), m_response.responseTime(), serializedData.data(), serializedData.size());
+
+    if (cacheType == SendToPlatform) {
+        const Vector<char>& serializedData = m_cachedMetadata->serialize();
+        blink::Platform::current()->cacheMetadata(m_response.url(), m_response.responseTime(), serializedData.data(), serializedData.size());
+    }
 }
 
-CachedMetadata* Resource::cachedMetadata(unsigned dataTypeID) const
+void Resource::clearCachedMetadata()
 {
-    if (!m_cachedMetadata || m_cachedMetadata->dataTypeID() != dataTypeID)
-        return 0;
-    return m_cachedMetadata.get();
+    m_cachedMetadata.clear();
 }
 
-void Resource::setCacheLiveResourcePriority(CacheLiveResourcePriority priority)
+bool Resource::canDelete() const
 {
-    if (memoryCache()->contains(this) && memoryCache()->isInLiveDecodedResourcesList(this) && cacheLiveResourcePriority() != static_cast<unsigned>(priority)) {
-        memoryCache()->removeFromLiveDecodedResourcesList(this);
-        m_cacheLiveResourcePriority = priority;
-        memoryCache()->insertInLiveDecodedResourcesList(this);
-        memoryCache()->prune();
-    }
+    return !hasClients() && !m_loader && !m_preloadCount && hasRightHandleCountApartFromCache(0)
+        && !m_protectorCount && !m_resourceToRevalidate && !m_proxyResource;
+}
+
+bool Resource::hasOneHandle() const
+{
+    return hasRightHandleCountApartFromCache(1);
+}
+
+CachedMetadata* Resource::cachedMetadata(unsigned dataTypeID) const
+{
+    if (!m_cachedMetadata || m_cachedMetadata->dataTypeID() != dataTypeID)
+        return nullptr;
+    return m_cachedMetadata.get();
 }
 
 void Resource::clearLoader()
@@ -471,8 +498,8 @@ bool Resource::addClientToSet(ResourceClient* client)
         else
             m_preloadResult = PreloadReferenced;
     }
-    if (!hasClients() && memoryCache()->contains(this))
-        memoryCache()->addToLiveResourcesSize(this);
+    if (!hasClients())
+        memoryCache()->makeLive(this);
 
     // If we have existing data to send to the new client and the resource type supprts it, send it asynchronously.
     if (!m_response.isNull() && !m_proxyResource && !shouldSendCachedDataSynchronouslyForType(type()) && !m_needsSynchronousCacheHit) {
@@ -501,10 +528,7 @@ void Resource::removeClient(ResourceClient* client)
 
     bool deleted = deleteIfPossible();
     if (!deleted && !hasClients()) {
-        if (memoryCache()->contains(this)) {
-            memoryCache()->removeFromLiveResourcesSize(this);
-            memoryCache()->removeFromLiveDecodedResourcesList(this);
-        }
+        memoryCache()->makeDead(this);
         if (!m_switchingClientsToRevalidatedResource)
             allClientsRemoved();
 
@@ -512,7 +536,7 @@ void Resource::removeClient(ResourceClient* client)
         // "no-store: ... MUST make a best-effort attempt to remove the information from volatile storage as promptly as possible"
         // "... History buffers MAY store such responses as part of their normal operation."
         // We allow non-secure content to be reused in history, but we do not allow secure content to be reused.
-        if (response().cacheControlContainsNoStore() && url().protocolIs("https")) {
+        if (hasCacheControlNoStoreHeader() && url().protocolIs("https")) {
             memoryCache()->remove(this);
             memoryCache()->prune();
         } else {
@@ -549,7 +573,11 @@ bool Resource::deleteIfPossible()
 {
     if (canDelete() && !memoryCache()->contains(this)) {
         InspectorInstrumentation::willDestroyResource(this);
+        dispose();
+        memoryCache()->unregisterLiveResource(*this);
+#if !ENABLE(OILPAN)
         delete this;
+#endif
         return true;
     }
     return false;
@@ -561,23 +589,8 @@ void Resource::setDecodedSize(size_t decodedSize)
         return;
     size_t oldSize = size();
     m_decodedSize = decodedSize;
-
-    if (memoryCache()->contains(this)) {
-        // Insert into or remove from the live decoded list if necessary.
-        // When inserting into the LiveDecodedResourcesList it is possible
-        // that the m_lastDecodedAccessTime is still zero or smaller than
-        // the m_lastDecodedAccessTime of the current list head. This is a
-        // violation of the invariant that the list is to be kept sorted
-        // by access time. The weakening of the invariant does not pose
-        // a problem. For more details please see: https://bugs.webkit.org/show_bug.cgi?id=30209
-        if (m_decodedSize && !memoryCache()->isInLiveDecodedResourcesList(this) && hasClients())
-            memoryCache()->insertInLiveDecodedResourcesList(this);
-        else if (!m_decodedSize && memoryCache()->isInLiveDecodedResourcesList(this))
-            memoryCache()->removeFromLiveDecodedResourcesList(this);
-
-        // Update the cache's size totals.
-        memoryCache()->update(this, oldSize, size());
-    }
+    memoryCache()->update(this, oldSize, size());
+    memoryCache()->updateDecodedResource(this, UpdateForPropertyChange);
 }
 
 void Resource::setEncodedSize(size_t encodedSize)
@@ -586,20 +599,13 @@ void Resource::setEncodedSize(size_t encodedSize)
         return;
     size_t oldSize = size();
     m_encodedSize = encodedSize;
-    if (memoryCache()->contains(this))
-        memoryCache()->update(this, oldSize, size());
+    memoryCache()->update(this, oldSize, size());
 }
 
-void Resource::didAccessDecodedData(double timeStamp)
+void Resource::didAccessDecodedData()
 {
-    m_lastDecodedAccessTime = timeStamp;
-    if (memoryCache()->contains(this)) {
-        if (memoryCache()->isInLiveDecodedResourcesList(this)) {
-            memoryCache()->removeFromLiveDecodedResourcesList(this);
-            memoryCache()->insertInLiveDecodedResourcesList(this);
-        }
-        memoryCache()->prune();
-    }
+    memoryCache()->updateDecodedResource(this, UpdateForAccess);
+    memoryCache()->prune();
 }
 
 void Resource::finishPendingClients()
@@ -616,9 +622,7 @@ void Resource::finishPendingClients()
     Vector<ResourceClient*> clientsToNotify;
     copyToVector(m_clientsAwaitingCallback, clientsToNotify);
 
-    for (size_t i = 0; i < clientsToNotify.size(); ++i) {
-        ResourceClient* client = clientsToNotify[i];
-
+    for (const auto& client : clientsToNotify) {
         // Handle case (2) to skip removed clients.
         if (!m_clientsAwaitingCallback.remove(client))
             continue;
@@ -669,11 +673,11 @@ void Resource::clearResourceToRevalidate()
 
     // 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.
     if (m_resourceToRevalidate->m_proxyResource == this) {
-        m_resourceToRevalidate->m_proxyResource = 0;
+        m_resourceToRevalidate->m_proxyResource = nullptr;
         m_resourceToRevalidate->deleteIfPossible();
     }
     m_handlesToRevalidate.clear();
-    m_resourceToRevalidate = 0;
+    m_resourceToRevalidate = nullptr;
     deleteIfPossible();
 }
 
@@ -683,14 +687,12 @@ void Resource::switchClientsToRevalidatedResource()
     ASSERT(memoryCache()->contains(m_resourceToRevalidate));
     ASSERT(!memoryCache()->contains(this));
 
-    WTF_LOG(ResourceLoading, "Resource %p switchClientsToRevalidatedResource %p", this, m_resourceToRevalidate);
+    WTF_LOG(ResourceLoading, "Resource %p switchClientsToRevalidatedResource %p", this, m_resourceToRevalidate.get());
 
     m_resourceToRevalidate->m_identifier = m_identifier;
 
     m_switchingClientsToRevalidatedResource = true;
-    HashSet<ResourcePtrBase*>::iterator end = m_handlesToRevalidate.end();
-    for (HashSet<ResourcePtrBase*>::iterator it = m_handlesToRevalidate.begin(); it != end; ++it) {
-        ResourcePtrBase* handle = *it;
+    for (ResourcePtrBase* handle : m_handlesToRevalidate) {
         handle->m_resource = m_resourceToRevalidate;
         m_resourceToRevalidate->registerHandle(handle);
         --m_handleCount;
@@ -699,14 +701,10 @@ void Resource::switchClientsToRevalidatedResource()
     m_handlesToRevalidate.clear();
 
     Vector<ResourceClient*> clientsToMove;
-    HashCountedSet<ResourceClient*>::iterator end2 = m_clients.end();
-    for (HashCountedSet<ResourceClient*>::iterator it = m_clients.begin(); it != end2; ++it) {
-        ResourceClient* client = it->key;
-        unsigned count = it->value;
-        while (count) {
-            clientsToMove.append(client);
-            --count;
-        }
+    for (const auto& clientHashEntry : m_clients) {
+        unsigned count = clientHashEntry.value;
+        while (count--)
+            clientsToMove.append(clientHashEntry.key);
     }
 
     unsigned moveCount = clientsToMove.size();
@@ -734,16 +732,15 @@ void Resource::updateResponseAfterRevalidation(const ResourceResponse& validatin
     // RFC2616 10.3.5
     // Update cached headers from the 304 response
     const HTTPHeaderMap& newHeaders = validatingResponse.httpHeaderFields();
-    HTTPHeaderMap::const_iterator end = newHeaders.end();
-    for (HTTPHeaderMap::const_iterator it = newHeaders.begin(); it != end; ++it) {
+    for (const auto& header : newHeaders) {
         // Entity headers should not be sent by servers when generating a 304
         // response; misconfigured servers send them anyway. We shouldn't allow
         // such headers to update the original request. We'll base this on the
         // list defined by RFC2616 7.1, with a few additions for extension headers
         // we care about.
-        if (!shouldUpdateHeaderAfterRevalidation(it->key))
+        if (!shouldUpdateHeaderAfterRevalidation(header.key))
             continue;
-        m_response.setHTTPHeaderField(it->key, it->value);
+        m_response.setHTTPHeaderField(header.key, header.value);
     }
 }
 
@@ -752,7 +749,6 @@ void Resource::revalidationSucceeded(const ResourceResponse& response)
     ASSERT(m_resourceToRevalidate);
     ASSERT(!memoryCache()->contains(m_resourceToRevalidate));
     ASSERT(m_resourceToRevalidate->isLoaded());
-    ASSERT(memoryCache()->contains(this));
 
     // Calling evict() can potentially delete revalidatingResource, which we use
     // below. This mustn't be the case since revalidation means it is loaded
@@ -799,31 +795,40 @@ void Resource::unregisterHandle(ResourcePtrBase* h)
         unlock();
     } else if (m_handleCount == 1 && memoryCache()->contains(this)) {
         unlock();
+        if (!hasClients())
+            memoryCache()->prune(this);
     }
 }
 
-bool Resource::canReuseRedirectChain() const
+bool Resource::canReuseRedirectChain()
 {
-    for (size_t i = 0; i < m_redirectChain.size(); ++i) {
-        if (!canUseResponse(m_redirectChain[i].m_redirectResponse, m_responseTimestamp))
+    for (auto& redirect : m_redirectChain) {
+        if (!canUseResponse(redirect.m_redirectResponse, m_responseTimestamp))
+            return false;
+        if (redirect.m_request.cacheControlContainsNoCache() || redirect.m_request.cacheControlContainsNoStore())
             return false;
     }
     return true;
 }
 
-bool Resource::mustRevalidateDueToCacheHeaders() const
+bool Resource::hasCacheControlNoStoreHeader()
+{
+    return m_response.cacheControlContainsNoStore() || m_resourceRequest.cacheControlContainsNoStore();
+}
+
+bool Resource::mustRevalidateDueToCacheHeaders()
 {
-    return !canUseResponse(m_response, m_responseTimestamp);
+    return !canUseResponse(m_response, m_responseTimestamp) || m_resourceRequest.cacheControlContainsNoCache() || m_resourceRequest.cacheControlContainsNoStore();
 }
 
-bool Resource::canUseCacheValidator() const
+bool Resource::canUseCacheValidator()
 {
     if (m_loading || errorOccurred())
         return false;
 
-    if (m_response.cacheControlContainsNoStore())
+    if (hasCacheControlNoStoreHeader())
         return false;
-    return m_response.hasCacheValidatorFields();
+    return m_response.hasCacheValidatorFields() || m_resourceRequest.hasCacheValidatorFields();
 }
 
 bool Resource::isPurgeable() const
@@ -898,20 +903,19 @@ bool Resource::ResourceCallback::isScheduled(Resource* resource) const
 
 void Resource::ResourceCallback::timerFired(Timer<ResourceCallback>*)
 {
-    HashSet<Resource*>::iterator end = m_resourcesWithPendingClients.end();
-    Vector<ResourcePtr<Resource> > resources;
-    for (HashSet<Resource*>::iterator it = m_resourcesWithPendingClients.begin(); it != end; ++it)
-        resources.append(*it);
+    Vector<ResourcePtr<Resource>> resources;
+    for (Resource* resource : m_resourcesWithPendingClients)
+        resources.append(resource);
     m_resourcesWithPendingClients.clear();
 
-    for (size_t i = 0; i < resources.size(); i++) {
-        resources[i]->assertAlive();
-        resources[i]->finishPendingClients();
-        resources[i]->assertAlive();
+    for (const auto& resource : resources) {
+        resource->assertAlive();
+        resource->finishPendingClients();
+        resource->assertAlive();
     }
 
-    for (size_t i = 0; i < resources.size(); i++)
-        resources[i]->assertAlive();
+    for (const auto& resource : resources)
+        resource->assertAlive();
 }
 
 static const char* initatorTypeNameToString(const AtomicString& initiatorTypeName)
@@ -963,10 +967,10 @@ const char* Resource::resourceTypeToString(Type type, const FetchInitiatorInfo&
         return "Link subresource";
     case Resource::TextTrack:
         return "Text track";
-    case Resource::Shader:
-        return "Shader";
     case Resource::ImportResource:
         return "Imported resource";
+    case Resource::Media:
+        return "Media";
     }
     ASSERT_NOT_REACHED();
     return initatorTypeNameToString(initiatorInfo.name);
@@ -998,10 +1002,10 @@ const char* ResourceTypeName(Resource::Type type)
         return "LinkSubresource";
     case Resource::TextTrack:
         return "TextTrack";
-    case Resource::Shader:
-        return "Shader";
     case Resource::ImportResource:
         return "ImportResource";
+    case Resource::Media:
+        return "Media";
     }
     ASSERT_NOT_REACHED();
     return "Unknown";