Source/WebCore: Make DocumentThreadableLoader a CachedResourceClient.
authorjaphet@chromium.org <japhet@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 18 Oct 2011 16:31:32 +0000 (16:31 +0000)
committerjaphet@chromium.org <japhet@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 18 Oct 2011 16:31:32 +0000 (16:31 +0000)
This will allow us to cache ThreadableLoaderClients as
appropriate in a later patch.
https://bugs.webkit.org/show_bug.cgi?id=61225

Reviewed by Antti Koivisto.

No new tests, no functionality change intended.

* WebCore.gypi:
* loader/DocumentThreadableLoader.cpp:
(WebCore::DocumentThreadableLoader::notifyFinished): CachedResourceClients don't send separate callbacks
    for didFail() and didFinishLoading(), so we need to differentiate here.
(WebCore::DocumentThreadableLoader::loadRequest): Call CachedResourceLoader::requestRawResource()
    instead of ResourceLoadScheduler::scheduleSubresourceLoad().
* loader/DocumentThreadableLoader.h:
* loader/cache/CachedRawResource.cpp:
(WebCore::CachedRawResource::data): Handle the complexity of some ThreadableLoaderClients setting
    DoNotBufferData in ResoureLoaderOptions. If the DataBufferingPolicy is BufferData, then the
    'data' input parameter will contain all data received so far, and we need to determine the
    incremental data to forward to the clients. If the policy is DoNotBufferData, 'data' is just
    the incremental data.
* loader/cache/CachedRawResource.h:
* loader/cache/CachedResource.cpp:
* loader/cache/CachedResource.h:
(WebCore::CachedResource::preloadResult):
(WebCore::CachedResource::didSendData):
(WebCore::CachedResource::didDownloadData):
(WebCore::CachedResource::setLoadFinishTime):
(WebCore::CachedResource::loadFinishTime):
* loader/cache/CachedResourceClient.h: Add several new callbacks needed by DocumentThreadableLoader.
* loader/cache/CachedResourceRequest.cpp:
(WebCore::CachedResourceRequest::didReceiveResponse): CachedResource::setResponse() can now cancel
    the request, so protect appropriately.
* loader/cache/CachedResourceRequest.h:
* loader/chromium/CachedRawResourceChromium.cpp: Added (plumb didDownloadData() to DocumentThreadableLoader).
* loader/chromium/CachedResourceRequestChromium.cpp: Added (plumb didDownloadData() to DocumentThreadableLoader).
* loader/chromium/DocumentThreadableLoaderChromium.cpp:
* platform/network/BlobResourceHandle.cpp:
(WebCore::BlobResourceHandle::notifyResponse): Protect before setting response, since it might kill us.

LayoutTests: Test update for https://bugs.webkit.org/show_bug.cgi?id=61225.
Due to changes in the implementation of DocumentThreadableLoader (and
therefore XHR), this test will have empty (rather than null) content
if we go over the length limit.

Reviewed by Antti Koivisto.

* http/tests/inspector/network/network-content-replacement-xhr-expected.txt:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@97765 268f45cc-cd09-0410-ab3c-d52691b4dbfc

18 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/inspector/network/network-content-replacement-xhr-expected.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.gypi
Source/WebCore/loader/DocumentThreadableLoader.cpp
Source/WebCore/loader/DocumentThreadableLoader.h
Source/WebCore/loader/cache/CachedRawResource.cpp
Source/WebCore/loader/cache/CachedRawResource.h
Source/WebCore/loader/cache/CachedResource.cpp
Source/WebCore/loader/cache/CachedResource.h
Source/WebCore/loader/cache/CachedResourceClient.h
Source/WebCore/loader/cache/CachedResourceRequest.cpp
Source/WebCore/loader/cache/CachedResourceRequest.h
Source/WebCore/loader/chromium/CachedRawResourceChromium.cpp [new file with mode: 0644]
Source/WebCore/loader/chromium/CachedResourceRequestChromium.cpp [new file with mode: 0644]
Source/WebCore/loader/chromium/DocumentThreadableLoaderChromium.cpp
Source/WebCore/loader/icon/IconLoader.h
Source/WebCore/platform/network/BlobResourceHandle.cpp

index 6c5821d..3e84cb9 100644 (file)
@@ -1,3 +1,14 @@
+2011-10-18  Nate Chapin  <japhet@chromium.org>
+
+        Test update for https://bugs.webkit.org/show_bug.cgi?id=61225.
+        Due to changes in the implementation of DocumentThreadableLoader (and
+        therefore XHR), this test will have empty (rather than null) content
+        if we go over the length limit.
+
+        Reviewed by Antti Koivisto.
+
+        * http/tests/inspector/network/network-content-replacement-xhr-expected.txt:
+
 2011-10-18  Mihnea Ovidenie  <mihnea@adobe.com>
 
         Unreviewed Qt rebaseline after r97738.
index d1ef73f..242de14 100644 (file)
@@ -2,11 +2,11 @@ CONSOLE MESSAGE: line 39: Done.
 Tests NetworkResourcesData logic for XHR content replacement.
 
 http://127.0.0.1:8000/inspector/network/resources/resource.php?size=200
-resource.content: null
+resource.content: 
 http://127.0.0.1:8000/inspector/network/resources/resource.php?size=100
 resource.content: ****************************************************************************************************
 http://127.0.0.1:8000/inspector/network/resources/resource.php?size=201
-resource.content: null
+resource.content: 
 http://127.0.0.1:8000/inspector/network/resources/resource.php?size=100
 resource.content: ****************************************************************************************************
 
index 7ca969e..a20e489 100644 (file)
@@ -1,3 +1,46 @@
+2011-10-18  Nate Chapin  <japhet@chromium.org>
+
+        Make DocumentThreadableLoader a CachedResourceClient.
+        This will allow us to cache ThreadableLoaderClients as
+        appropriate in a later patch.
+        https://bugs.webkit.org/show_bug.cgi?id=61225
+
+        Reviewed by Antti Koivisto.
+
+        No new tests, no functionality change intended.
+
+        * WebCore.gypi:
+        * loader/DocumentThreadableLoader.cpp:
+        (WebCore::DocumentThreadableLoader::notifyFinished): CachedResourceClients don't send separate callbacks
+            for didFail() and didFinishLoading(), so we need to differentiate here.
+        (WebCore::DocumentThreadableLoader::loadRequest): Call CachedResourceLoader::requestRawResource()
+            instead of ResourceLoadScheduler::scheduleSubresourceLoad().
+        * loader/DocumentThreadableLoader.h:
+        * loader/cache/CachedRawResource.cpp:
+        (WebCore::CachedRawResource::data): Handle the complexity of some ThreadableLoaderClients setting
+            DoNotBufferData in ResoureLoaderOptions. If the DataBufferingPolicy is BufferData, then the
+            'data' input parameter will contain all data received so far, and we need to determine the
+            incremental data to forward to the clients. If the policy is DoNotBufferData, 'data' is just
+            the incremental data.
+        * loader/cache/CachedRawResource.h:
+        * loader/cache/CachedResource.cpp:
+        * loader/cache/CachedResource.h:
+        (WebCore::CachedResource::preloadResult):
+        (WebCore::CachedResource::didSendData):
+        (WebCore::CachedResource::didDownloadData):
+        (WebCore::CachedResource::setLoadFinishTime):
+        (WebCore::CachedResource::loadFinishTime):
+        * loader/cache/CachedResourceClient.h: Add several new callbacks needed by DocumentThreadableLoader.
+        * loader/cache/CachedResourceRequest.cpp:
+        (WebCore::CachedResourceRequest::didReceiveResponse): CachedResource::setResponse() can now cancel
+            the request, so protect appropriately.
+        * loader/cache/CachedResourceRequest.h:
+        * loader/chromium/CachedRawResourceChromium.cpp: Added (plumb didDownloadData() to DocumentThreadableLoader).
+        * loader/chromium/CachedResourceRequestChromium.cpp: Added (plumb didDownloadData() to DocumentThreadableLoader).
+        * loader/chromium/DocumentThreadableLoaderChromium.cpp:
+        * platform/network/BlobResourceHandle.cpp:
+        (WebCore::BlobResourceHandle::notifyResponse): Protect before setting response, since it might kill us.
+
 2011-10-18  Sheriff Bot  <webkit.review.bot@gmail.com>
 
         Unreviewed, rolling out r97752.
index b9e3d12..0e1debe 100644 (file)
             'loader/cache/CachedXSLStyleSheet.h',
             'loader/cache/MemoryCache.cpp',
             'loader/cf/ResourceLoaderCFNet.cpp',
+            'loader/chromium/CachedRawResourceChromium.cpp',
+            'loader/chromium/CachedResourceRequestChromium.cpp',
             'loader/chromium/DocumentThreadableLoaderChromium.cpp',
             'loader/chromium/ResourceLoaderChromium.cpp',
             'loader/chromium/SubresourceLoaderChromium.cpp',
index 80e0ff2..1527697 100644 (file)
 #include "config.h"
 #include "DocumentThreadableLoader.h"
 
-#include "AuthenticationChallenge.h"
+#include "CachedRawResource.h"
+#include "CachedResourceLoader.h"
 #include "CrossOriginAccessControl.h"
 #include "CrossOriginPreflightResultCache.h"
 #include "Document.h"
 #include "DocumentThreadableLoaderClient.h"
 #include "Frame.h"
 #include "FrameLoader.h"
-#include "ResourceHandle.h"
-#include "ResourceLoadScheduler.h"
+#include "ResourceError.h"
 #include "ResourceRequest.h"
 #include "SecurityOrigin.h"
-#include "SubresourceLoader.h"
 #include "ThreadableLoaderClient.h"
+#include <wtf/Assertions.h>
 #include <wtf/UnusedParam.h>
 
 #if ENABLE(INSPECTOR)
@@ -63,7 +63,7 @@ void DocumentThreadableLoader::loadResourceSynchronously(Document* document, con
 PassRefPtr<DocumentThreadableLoader> DocumentThreadableLoader::create(Document* document, ThreadableLoaderClient* client, const ResourceRequest& request, const ThreadableLoaderOptions& options)
 {
     RefPtr<DocumentThreadableLoader> loader = adoptRef(new DocumentThreadableLoader(document, client, LoadAsynchronously, request, options));
-    if (!loader->m_loader)
+    if (!loader->m_resource)
         loader = 0;
     return loader.release();
 }
@@ -133,31 +133,39 @@ void DocumentThreadableLoader::makeCrossOriginAccessRequestWithPreflight(const R
 
 DocumentThreadableLoader::~DocumentThreadableLoader()
 {
-    if (m_loader)
-        m_loader->clearClient();
+    if (m_resource)
+        m_resource->removeClient(this);
 }
 
 void DocumentThreadableLoader::cancel()
 {
-    if (!m_loader)
-        return;
-
-    m_loader->cancel();
-    m_loader->clearClient();
-    m_loader = 0;
+    if (m_client) {
+        ResourceError error(errorDomainWebKitInternal, 0, m_resource->url(), "Load cancelled");
+        error.setIsCancellation(true);
+        didFail(error);
+    }
+    clearResource();
     m_client = 0;
 }
 
 void DocumentThreadableLoader::setDefersLoading(bool value)
 {
-    if (m_loader)
-        m_loader->setDefersLoading(value);
+    if (m_resource)
+        m_resource->setDefersLoading(value);
 }
 
-void DocumentThreadableLoader::willSendRequest(SubresourceLoader* loader, ResourceRequest& request, const ResourceResponse& redirectResponse)
+void DocumentThreadableLoader::clearResource()
+{
+    if (m_resource) {
+        m_resource->removeClient(this);
+        m_resource = 0;
+    }
+}
+
+void DocumentThreadableLoader::redirectReceived(CachedResource* resource, ResourceRequest& request, const ResourceResponse& redirectResponse)
 {
     ASSERT(m_client);
-    ASSERT_UNUSED(loader, loader == m_loader);
+    ASSERT_UNUSED(resource, resource == m_resource);
 
     if (!isAllowedRedirect(request.url())) {
         RefPtr<DocumentThreadableLoader> protect(this);
@@ -169,18 +177,17 @@ void DocumentThreadableLoader::willSendRequest(SubresourceLoader* loader, Resour
     }
 }
 
-void DocumentThreadableLoader::didSendData(SubresourceLoader* loader, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
+void DocumentThreadableLoader::dataSent(CachedResource* resource, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
 {
     ASSERT(m_client);
-    ASSERT_UNUSED(loader, loader == m_loader);
-
+    ASSERT_UNUSED(resource, resource == m_resource);
     m_client->didSendData(bytesSent, totalBytesToBeSent);
 }
 
-void DocumentThreadableLoader::didReceiveResponse(SubresourceLoader* loader, const ResourceResponse& response)
+void DocumentThreadableLoader::responseReceived(CachedResource* resource, const ResourceResponse& response)
 {
-    ASSERT(loader == m_loader);
-    didReceiveResponse(loader->identifier(), response);
+    ASSERT_UNUSED(resource, resource == m_resource);
+    didReceiveResponse(m_resource->identifier(), response);
 }
 
 void DocumentThreadableLoader::didReceiveResponse(unsigned long identifier, const ResourceResponse& response)
@@ -223,10 +230,10 @@ void DocumentThreadableLoader::didReceiveResponse(unsigned long identifier, cons
     }
 }
 
-void DocumentThreadableLoader::didReceiveData(SubresourceLoader* loader, const char* data, int dataLength)
+void DocumentThreadableLoader::dataReceived(CachedResource* resource, const char* data, int dataLength)
 {
     ASSERT(m_client);
-    ASSERT_UNUSED(loader, loader == m_loader);
+    ASSERT_UNUSED(resource, resource == m_resource);
 
 #if ENABLE(INSPECTOR)
     if (m_preflightRequestIdentifier)
@@ -240,23 +247,18 @@ void DocumentThreadableLoader::didReceiveData(SubresourceLoader* loader, const c
     m_client->didReceiveData(data, dataLength);
 }
 
-void DocumentThreadableLoader::didReceiveCachedMetadata(SubresourceLoader* loader, const char* data, int dataLength)
-{
-    ASSERT(m_client);
-    ASSERT_UNUSED(loader, loader == m_loader);
-
-    // Preflight data should be invisible to clients.
-    if (m_actualRequest)
-        return;
-
-    m_client->didReceiveCachedMetadata(data, dataLength);
-}
-
-void DocumentThreadableLoader::didFinishLoading(SubresourceLoader* loader, double finishTime)
+void DocumentThreadableLoader::notifyFinished(CachedResource* resource)
 {
-    ASSERT(loader == m_loader);
     ASSERT(m_client);
-    didFinishLoading(loader->identifier(), finishTime);
+    ASSERT_UNUSED(resource, resource == m_resource);
+        
+    if (m_resource && (m_resource->errorOccurred() || m_resource->wasCanceled())) {
+        ResourceError error("Network Request Failed", 0, m_resource->url(), "Resource failed to load");
+        if (m_resource->wasCanceled())
+            error.setIsCancellation(true);
+        didFail(error);
+    } else
+        didFinishLoading(m_resource->identifier(), m_resource->loadFinishTime());
 }
 
 void DocumentThreadableLoader::didFinishLoading(unsigned long identifier, double finishTime)
@@ -274,12 +276,8 @@ void DocumentThreadableLoader::didFinishLoading(unsigned long identifier, double
         m_client->didFinishLoading(identifier, finishTime);
 }
 
-void DocumentThreadableLoader::didFail(SubresourceLoader* loader, const ResourceError& error)
+void DocumentThreadableLoader::didFail(const ResourceError& error)
 {
-    ASSERT(m_client);
-    // m_loader may be null if we arrive here via SubresourceLoader::create in the ctor
-    ASSERT_UNUSED(loader, loader == m_loader || !m_loader);
-
 #if ENABLE(INSPECTOR)
     if (m_preflightRequestIdentifier)
         InspectorInstrumentation::didFailLoading(m_document->frame(), m_document->frame()->loader()->documentLoader(), m_preflightRequestIdentifier, error);
@@ -295,6 +293,8 @@ void DocumentThreadableLoader::preflightSuccess()
 
     actualRequest->setHTTPOrigin(securityOrigin()->toString());
 
+    clearResource();
+
     // It should be ok to skip the security check since we already asked about the preflight request.
     loadRequest(*actualRequest, SkipSecurityCheck);
 }
@@ -324,19 +324,19 @@ void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, Secur
             options.shouldBufferData = BufferData;
         }
 
+        ResourceRequest newRequest(request);
 #if ENABLE(INSPECTOR)
         if (m_actualRequest) {
-            ResourceRequest newRequest(request);
             // Because willSendRequest only gets called during redirects, we initialize the identifier and the first willSendRequest here.
             m_preflightRequestIdentifier = m_document->frame()->page()->progress()->createUniqueIdentifier();
             ResourceResponse redirectResponse = ResourceResponse();
             InspectorInstrumentation::willSendRequest(m_document->frame(), m_preflightRequestIdentifier, m_document->frame()->loader()->documentLoader(), newRequest, redirectResponse);
         }
 #endif
-
-        // Clear the loader so that any callbacks from SubresourceLoader::create will not have the old loader.
-        m_loader = 0;
-        m_loader = resourceLoadScheduler()->scheduleSubresourceLoad(m_document->frame(), this, request, ResourceLoadPriorityMedium, options);
+        ASSERT(!m_resource);
+        m_resource = m_document->cachedResourceLoader()->requestRawResource(newRequest, options);
+        if (m_resource)
+            m_resource->addClient(this);
         return;
     }
     
@@ -367,7 +367,7 @@ void DocumentThreadableLoader::loadRequest(const ResourceRequest& request, Secur
 
     const char* bytes = static_cast<const char*>(data.data());
     int len = static_cast<int>(data.size());
-    didReceiveData(0, bytes, len);
+    dataReceived(0, bytes, len);
 
     didFinishLoading(identifier, 0.0);
 }
index 31d8dcf..236ae74 100644 (file)
@@ -31,8 +31,9 @@
 #ifndef DocumentThreadableLoader_h
 #define DocumentThreadableLoader_h
 
+#include "CachedRawResource.h"
+#include "CachedResourceHandle.h"
 #include "FrameLoaderTypes.h"
-#include "SubresourceLoaderClient.h"
 #include "ThreadableLoader.h"
 #include <wtf/Forward.h>
 #include <wtf/OwnPtr.h>
@@ -48,7 +49,7 @@ namespace WebCore {
     class SecurityOrigin;
     class ThreadableLoaderClient;
 
-    class DocumentThreadableLoader : public RefCounted<DocumentThreadableLoader>, public ThreadableLoader, private SubresourceLoaderClient  {
+    class DocumentThreadableLoader : public RefCounted<DocumentThreadableLoader>, public ThreadableLoader, private CachedRawResourceClient  {
         WTF_MAKE_FAST_ALLOCATED;
     public:
         static void loadResourceSynchronously(Document*, const ResourceRequest&, ThreadableLoaderClient&, const ThreadableLoaderOptions&);
@@ -73,21 +74,21 @@ namespace WebCore {
 
         DocumentThreadableLoader(Document*, ThreadableLoaderClient*, BlockingBehavior, const ResourceRequest&, const ThreadableLoaderOptions&);
 
-        virtual void willSendRequest(SubresourceLoader*, ResourceRequest&, const ResourceResponse& redirectResponse);
-        virtual void didSendData(SubresourceLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent);
-
-        virtual void didReceiveResponse(SubresourceLoader*, const ResourceResponse&);
-        virtual void didReceiveData(SubresourceLoader*, const char*, int dataLength);
-        virtual void didReceiveCachedMetadata(SubresourceLoader*, const char*, int dataLength);
-        virtual void didFinishLoading(SubresourceLoader*, double);
-        virtual void didFail(SubresourceLoader*, const ResourceError&);
+        void clearResource();
 
+        // CachedRawResourceClient
+        virtual void dataSent(CachedResource*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent);
+        virtual void responseReceived(CachedResource*, const ResourceResponse&);
+        virtual void dataReceived(CachedResource*, const char* data, int dataLength);
+        virtual void redirectReceived(CachedResource*, ResourceRequest&, const ResourceResponse&);
+        virtual void notifyFinished(CachedResource*);
 #if PLATFORM(CHROMIUM)
-        virtual void didDownloadData(SubresourceLoader*, int dataLength);
+        virtual void dataDownloaded(CachedResource*, int);
 #endif
 
         void didReceiveResponse(unsigned long identifier, const ResourceResponse&);
         void didFinishLoading(unsigned long identifier, double finishTime);
+        void didFail(const ResourceError&);
         void makeSimpleCrossOriginAccessRequest(const ResourceRequest& request);
         void makeCrossOriginAccessRequestWithPreflight(const ResourceRequest& request);
         void preflightSuccess();
@@ -98,7 +99,7 @@ namespace WebCore {
 
         SecurityOrigin* securityOrigin() const;
 
-        RefPtr<SubresourceLoader> m_loader;
+        CachedResourceHandle<CachedRawResource> m_resource;
         ThreadableLoaderClient* m_client;
         Document* m_document;
         ThreadableLoaderOptions m_options;
index e45f616..c88678c 100644 (file)
@@ -37,19 +37,84 @@ namespace WebCore {
 
 CachedRawResource::CachedRawResource(ResourceRequest& resourceRequest)
     : CachedResource(resourceRequest, RawResource)
+    , m_dataLength(0)
 {
 }
 
 void CachedRawResource::data(PassRefPtr<SharedBuffer> data, bool allDataReceived)
 {
-    m_data = data;
+    if (data) {
+        // If we are buffering data, then we are saving the buffer in m_data and need to manually
+        // calculate the incremental data. If we are not buffering, then m_data will be null and
+        // the buffer contains only the incremental data.
+        size_t previousDataLength = (m_options.shouldBufferData == BufferData) ? m_dataLength : 0;
+        ASSERT(data->size() >= previousDataLength);
+        const char* incrementalData = data->data() + previousDataLength;
+        size_t incrementalDataLength = data->size() - previousDataLength;
+
+        if (incrementalDataLength) {
+            CachedResourceClientWalker<CachedRawResourceClient> w(m_clients);
+            while (CachedRawResourceClient* c = w.next())
+                c->dataReceived(this, incrementalData, incrementalDataLength);
+        }
+    }
+    
+    if (m_options.shouldBufferData == BufferData) {
+        m_dataLength = data ? data->size() : 0;
+        m_data = data;
+    }
     CachedResource::data(m_data, allDataReceived);
 }
 
+void CachedRawResource::didAddClient(CachedResourceClient* c)
+{
+    if (m_data) {
+        static_cast<CachedRawResourceClient*>(c)->responseReceived(this, m_response);
+        static_cast<CachedRawResourceClient*>(c)->dataReceived(this, m_data->data(), m_data->size());
+    }
+    CachedResource::didAddClient(c);
+}
+
 void CachedRawResource::allClientsRemoved()
 {
     if (m_request)
         m_request->cancel();
 }
 
+void CachedRawResource::willSendRequest(ResourceRequest& request, const ResourceResponse& response)
+{
+    if (!response.isNull()) {
+        CachedResourceClientWalker<CachedRawResourceClient> w(m_clients);
+        while (CachedRawResourceClient* c = w.next())
+            c->redirectReceived(this, request, response);
+    }
+    CachedResource::willSendRequest(request, response);
+}
+
+void CachedRawResource::setResponse(const ResourceResponse& response)
+{
+    CachedResource::setResponse(response);
+    CachedResourceClientWalker<CachedRawResourceClient> w(m_clients);
+    while (CachedRawResourceClient* c = w.next())
+        c->responseReceived(this, m_response);
+}
+
+void CachedRawResource::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
+{
+    CachedResourceClientWalker<CachedRawResourceClient> w(m_clients);
+    while (CachedRawResourceClient* c = w.next())
+        c->dataSent(this, bytesSent, totalBytesToBeSent);
+}
+
+void CachedRawResource::setDefersLoading(bool defers)
+{
+    if (m_request)
+        m_request->setDefersLoading(defers);
+}
+
+unsigned long CachedRawResource::identifier() const
+{
+    return m_request ? m_request->identifier() : 0;
+}
+
 } // namespace WebCore
index 915e637..9b0cab5 100644 (file)
 #define CachedRawResource_h
 
 #include "CachedResource.h"
+#include "CachedResourceClient.h"
 
 namespace WebCore {
 
 class CachedRawResource : public CachedResource {
 public:
     CachedRawResource(ResourceRequest&);
+
+    // FIXME: AssociatedURLLoader shouldn't be a DocumentThreadableLoader and therefore shouldn't
+    // use CachedRawResource. However, it is, and it needs to be able to defer loading.
+    // This can be fixed by splitting CORS preflighting out of DocumentThreacableLoader.
+    virtual void setDefersLoading(bool);
     
+    // FIXME: This is exposed for the InpsectorInstrumentation for preflights in DocumentThreadableLoader. It's also really lame.
+    unsigned long identifier() const;
+
 private:
+    virtual void didAddClient(CachedResourceClient*);
     virtual void data(PassRefPtr<SharedBuffer> data, bool allDataReceived);
 
     virtual bool shouldIgnoreHTTPStatusCodeErrors() const { return true; }
     virtual void allClientsRemoved();
+
+    virtual void willSendRequest(ResourceRequest&, const ResourceResponse&);
+    virtual void setResponse(const ResourceResponse&);
+    virtual void didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent);
+#if PLATFORM(CHROMIUM)
+    virtual void didDownloadData(int);
+#endif
+
+    size_t m_dataLength;
+};
+
+
+class CachedRawResourceClient : public CachedResourceClient {
+public:
+    virtual ~CachedRawResourceClient() { }
+    static CachedResourceClientType expectedType() { return RawResourceType; }
+    virtual CachedResourceClientType resourceClientType() { return expectedType(); }
+
+    virtual void dataSent(CachedResource*, unsigned long long /* bytesSent */, unsigned long long /* totalBytesToBeSent */) { }
+    virtual void responseReceived(CachedResource*, const ResourceResponse&) { }
+    virtual void dataReceived(CachedResource*, const char* /* data */, int /* length */) { }
+    virtual void redirectReceived(CachedResource*, ResourceRequest&, const ResourceResponse&) { }
+#if PLATFORM(CHROMIUM)
+    virtual void dataDownloaded(CachedResource*, int) { }
+#endif
 };
 
 }
index 6767784..6e67419 100644 (file)
@@ -87,6 +87,7 @@ CachedResource::CachedResource(const ResourceRequest& request, Type type)
     , m_loadPriority(defaultPriorityForResourceType(type))
     , m_responseTimestamp(currentTime())
     , m_lastDecodedAccessTime(0)
+    , m_loadFinishTime(0)
     , m_encodedSize(0)
     , m_decodedSize(0)
     , m_accessCount(0)
index d07a507..693c23b 100644 (file)
@@ -118,7 +118,6 @@ public:
         PreloadReferencedWhileComplete
     };
     PreloadResult preloadResult() const { return static_cast<PreloadResult>(m_preloadResult); }
-    void setRequestedFromNetworkingLayer() { m_requestedFromNetworkingLayer = true; }
 
     virtual void didAddClient(CachedResourceClient*);
     virtual void allClientsRemoved() { }
@@ -173,7 +172,8 @@ public:
 
     SharedBuffer* data() const { ASSERT(!m_purgeableData); return m_data.get(); }
 
-    void setResponse(const ResourceResponse&);
+    virtual void willSendRequest(ResourceRequest&, const ResourceResponse&) { m_requestedFromNetworkingLayer = true; }
+    virtual void setResponse(const ResourceResponse&);
     const ResourceResponse& response() const { return m_response; }
 
     // Sets the serialized metadata retrieved from the platform's cache.
@@ -231,6 +231,14 @@ public:
     void switchClientsToRevalidatedResource();
     void clearResourceToRevalidate();
     void updateResponseAfterRevalidation(const ResourceResponse& validatingResponse);
+    
+    virtual void didSendData(unsigned long long /* bytesSent */, unsigned long long /* totalBytesToBeSent */) { }
+#if PLATFORM(CHROMIUM)
+    virtual void didDownloadData(int) { }
+#endif
+
+    void setLoadFinishTime(double finishTime) { m_loadFinishTime = finishTime; }
+    double loadFinishTime() const { return m_loadFinishTime; }
 
 protected:
     void checkNotify();
@@ -266,6 +274,7 @@ private:
     RefPtr<CachedMetadata> m_cachedMetadata;
 
     double m_lastDecodedAccessTime; // Used as a "thrash guard" in the cache
+    double m_loadFinishTime;
 
     unsigned m_encodedSize;
     unsigned m_decodedSize;
index 2a72f61..4aa2dd2 100644 (file)
@@ -38,7 +38,8 @@ public:
         BaseResourceType,
         ImageType,
         FontType,
-        StyleSheetType
+        StyleSheetType,
+        RawResourceType
     };
 
     virtual ~CachedResourceClient() { }
index d34ceb4..4466adc 100644 (file)
@@ -90,6 +90,8 @@ CachedResourceRequest::CachedResourceRequest(CachedResourceLoader* cachedResourc
 
 CachedResourceRequest::~CachedResourceRequest()
 {
+    if (m_loader)
+        m_loader->clearClient();
 }
 
 PassOwnPtr<CachedResourceRequest> CachedResourceRequest::load(CachedResourceLoader* cachedResourceLoader, CachedResource* resource, const ResourceLoaderOptions& options)
@@ -142,13 +144,13 @@ PassOwnPtr<CachedResourceRequest> CachedResourceRequest::load(CachedResourceLoad
     return request.release();
 }
 
-void CachedResourceRequest::willSendRequest(SubresourceLoader* loader, ResourceRequest& req, const ResourceResponse&)
+void CachedResourceRequest::willSendRequest(SubresourceLoader* loader, ResourceRequest& req, const ResourceResponse& response)
 {
     if (!m_cachedResourceLoader->canRequest(m_resource->type(), req.url())) {
         loader->cancel();
         return;
     }
-    m_resource->setRequestedFromNetworkingLayer();
+    m_resource->willSendRequest(req, response);
 }
 
 void CachedResourceRequest::cancel()
@@ -158,7 +160,18 @@ void CachedResourceRequest::cancel()
     m_loader->cancel();
 }
 
-void CachedResourceRequest::didFinishLoading(SubresourceLoader* loader, double)
+unsigned long CachedResourceRequest::identifier() const
+{
+    return m_loader->identifier();
+}
+
+void CachedResourceRequest::setDefersLoading(bool defers)
+{
+    if (m_loader)
+        m_loader->setDefersLoading(defers);
+}
+
+void CachedResourceRequest::didFinishLoading(SubresourceLoader* loader, double finishTime)
 {
     if (m_finishing)
         return;
@@ -178,6 +191,7 @@ void CachedResourceRequest::didFinishLoading(SubresourceLoader* loader, double)
     // error, so we can't send the successful data() and finish() callbacks.
     if (!m_resource->errorOccurred()) {
         m_cachedResourceLoader->loadFinishing();
+        m_resource->setLoadFinishTime(finishTime);
         m_resource->data(loader->resourceData(), true);
         if (!m_resource->errorOccurred())
             m_resource->finish();
@@ -239,7 +253,13 @@ void CachedResourceRequest::didReceiveResponse(SubresourceLoader* loader, const
         memoryCache()->revalidationFailed(m_resource);
     }
 
+    // setResponse() might cancel the request, so we need to keep ourselves alive. Unfortunately,
+    // we can't protect a CachedResourceRequest, but we can protect m_resource, which has the
+    // power to kill the CachedResourceRequest (and will switch isLoading() to false if it does so).
+    CachedResourceHandle<CachedResource> protect(m_resource);
     m_resource->setResponse(response);
+    if (!protect->isLoading())
+        return;
 
     String encoding = response.textEncodingName();
     if (!encoding.isNull())
@@ -271,18 +291,20 @@ void CachedResourceRequest::didReceiveData(SubresourceLoader* loader, const char
     if (m_resource->errorOccurred())
         return;
 
-    if (m_resource->response().httpStatusCode() >= 400) {
-        if (!m_resource->shouldIgnoreHTTPStatusCodeErrors())
-            m_resource->error(CachedResource::LoadError);
+    if (m_resource->response().httpStatusCode() >= 400 && !m_resource->shouldIgnoreHTTPStatusCodeErrors()) {
+        m_resource->error(CachedResource::LoadError);
         return;
     }
 
-    // Set the data.
-    if (m_multipart) {
-        // The loader delivers the data in a multipart section all at once, send eof.
-        // The resource data will change as the next part is loaded, so we need to make a copy.
+    // There are two cases where we might need to create our own SharedBuffer instead of copying the one in ResourceLoader.
+    // (1) Multipart content: The loader delivers the data in a multipart section all at once, then sends eof.
+    //     The resource data will change as the next part is loaded, so we need to make a copy.
+    // (2) Our client requested that the data not be buffered at the ResourceLoader level via ResourceLoaderOptions. In this case,
+    //     ResourceLoader::resourceData() will be null. However, unlike the multipart case, we don't want to tell the CachedResource
+    //     that all data has been received yet.
+    if (m_multipart || !loader->resourceData()) {
         RefPtr<SharedBuffer> copiedData = SharedBuffer::create(data, size);
-        m_resource->data(copiedData.release(), true);
+        m_resource->data(copiedData.release(), m_multipart);
     } else
         m_resource->data(loader->resourceData(), false);
 }
@@ -292,7 +314,12 @@ void CachedResourceRequest::didReceiveCachedMetadata(SubresourceLoader*, const c
     ASSERT(!m_resource->isCacheValidator());
     m_resource->setSerializedCachedMetadata(data, size);
 }
-    
+
+void CachedResourceRequest::didSendData(SubresourceLoader*, unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
+{
+    m_resource->didSendData(bytesSent, totalBytesToBeSent);
+}
+
 void CachedResourceRequest::end()
 {
     m_cachedResourceLoader->loadDone();
index 3207e61..3176608 100644 (file)
@@ -49,6 +49,12 @@ namespace WebCore {
         CachedResourceLoader* cachedResourceLoader() const { return m_cachedResourceLoader; }
         void cancel();
 
+        // FIXME: Like CachedResource::identifier(), this is a lame hack for preflight InspectorInstrumentation in DocumentThreadableLoader.
+        unsigned long identifier() const;
+
+        // FIXME: See CachedRawResource::setDefersLoading() for the relevant rant.
+        void setDefersLoading(bool);
+
     private:
         CachedResourceRequest(CachedResourceLoader*, CachedResource*);
         virtual void willSendRequest(SubresourceLoader*, ResourceRequest&, const ResourceResponse&);
@@ -59,6 +65,11 @@ namespace WebCore {
         virtual void didFail(SubresourceLoader*, const ResourceError&);
         void end();
 
+        virtual void didSendData(SubresourceLoader*, unsigned long long /*bytesSent*/, unsigned long long /*totalBytesToBeSent*/);
+#if PLATFORM(CHROMIUM)
+        virtual void didDownloadData(SubresourceLoader*, int);
+#endif
+
         RefPtr<SubresourceLoader> m_loader;
         CachedResourceLoader* m_cachedResourceLoader;
         CachedResource* m_resource;
diff --git a/Source/WebCore/loader/chromium/CachedRawResourceChromium.cpp b/Source/WebCore/loader/chromium/CachedRawResourceChromium.cpp
new file mode 100644 (file)
index 0000000..eae6890
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011, Google Inc. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CachedRawResource.h"
+
+#include "CachedResourceClient.h"
+#include "CachedResourceClientWalker.h"
+
+namespace WebCore {
+
+void CachedRawResource::didDownloadData(int dataLength)
+{
+    CachedResourceClientWalker<CachedRawResourceClient> w(m_clients);
+    while (CachedRawResourceClient* c = w.next())
+        c->dataDownloaded(this, dataLength);
+}
+
+}
diff --git a/Source/WebCore/loader/chromium/CachedResourceRequestChromium.cpp b/Source/WebCore/loader/chromium/CachedResourceRequestChromium.cpp
new file mode 100644 (file)
index 0000000..daa6b8a
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2011, Google Inc. All rights reserved.
+ * 
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * 
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CachedResourceRequest.h"
+
+#include "CachedResource.h"
+#include "SubresourceLoader.h"
+
+namespace WebCore {
+
+void CachedResourceRequest::didDownloadData(SubresourceLoader* loader, int length)
+{
+    ASSERT_UNUSED(loader, loader == m_loader);
+    m_resource->didDownloadData(length);
+}
+
+}
index 9c5a081..e36b87f 100644 (file)
 #include "config.h"
 #include "DocumentThreadableLoader.h"
 
-#include "SubresourceLoader.h"
+#include "CachedRawResource.h"
 #include "ThreadableLoaderClient.h"
 
 namespace WebCore {
 
-void DocumentThreadableLoader::didDownloadData(SubresourceLoader* loader, int dataLength)
+void DocumentThreadableLoader::dataDownloaded(CachedResource* resource, int dataLength)
 {
     ASSERT(m_client);
-    ASSERT_UNUSED(loader, loader == m_loader);
+    ASSERT_UNUSED(resource, resource == m_resource);
     ASSERT(!m_actualRequest);
 
     m_client->didDownloadData(dataLength);
index 9675ced..65e8bd5 100644 (file)
@@ -26,7 +26,7 @@
 #ifndef IconLoader_h
 #define IconLoader_h
 
-#include "CachedResourceClient.h"
+#include "CachedRawResource.h"
 #include "CachedResourceHandle.h"
 #include <wtf/Forward.h>
 #include <wtf/Noncopyable.h>
@@ -37,11 +37,11 @@ namespace WebCore {
 class CachedRawResource;
 class Frame;
 
-class IconLoader : private CachedResourceClient {
+class IconLoader : private CachedRawResourceClient {
     WTF_MAKE_NONCOPYABLE(IconLoader); WTF_MAKE_FAST_ALLOCATED;
 public:
     static PassOwnPtr<IconLoader> create(Frame*);
-    ~IconLoader();
+    virtual ~IconLoader();
 
     void startLoading();
     void stopLoading();
index e739d9c..2b94bdb 100644 (file)
@@ -538,6 +538,7 @@ void BlobResourceHandle::notifyResponse()
         return;
 
     if (m_errorCode) {
+        RefPtr<BlobResourceHandle> protect(this);
         notifyResponseOnError();
         notifyFinish();
     } else