Async XMLHttpRequest should get access to AppCache resources stored as flat files
authoryouenn.fablet@crf.canon.fr <youenn.fablet@crf.canon.fr@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 31 May 2015 11:38:06 +0000 (11:38 +0000)
committeryouenn.fablet@crf.canon.fr <youenn.fablet@crf.canon.fr@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 31 May 2015 11:38:06 +0000 (11:38 +0000)
https://bugs.webkit.org/show_bug.cgi?id=138506

Reviewed by Darin Adler.

Source/WebCore:

This patch reads flat file data when DocumentLoader substituteResource delivery timer is fired.
Refactoring to remove ApplicationCacheHost/DocumentLoader friend link.
Added ResourceLoader::deliverResponseAndData helper function, taking a SharedBuffer as input to remove an unneeded copy for flat files (no change for other files).

Test: http/tests/appcache/simple-video-async.html

* loader/DocumentLoader.cpp:
(WebCore::DocumentLoader::substituteResourceDeliveryTimerFired):
(WebCore::DocumentLoader::scheduleArchiveLoad):
(WebCore::DocumentLoader::scheduleSubstituteResourceLoad): Helper function to remove ApplicationCacheHost friend link.
* loader/DocumentLoader.h:
* loader/ResourceLoader.cpp:
(WebCore::ResourceLoader::deliverResponseAndData): Helper function, code mostly moved from DocumentLoader::substituteResourceDeliveryTimerFired.
* loader/ResourceLoader.h:
* loader/SubstituteResource.h:
(WebCore::SubstituteResource::deliver): Introduced to be overriden by ApplicationCacheResource to take care of flat file case.
* loader/appcache/ApplicationCacheHost.cpp:
(WebCore::ApplicationCacheHost::maybeLoadResource):
(WebCore::ApplicationCacheHost::scheduleLoadFallbackResourceFromApplicationCache):
* loader/appcache/ApplicationCacheResource.cpp:
(WebCore::ApplicationCacheResource::deliver): Use SharedBuffer::createWithContentsOfFile to load data stored in flat file.
* loader/appcache/ApplicationCacheResource.h:

LayoutTests:

* http/tests/appcache/resources/simple-video-async.manifest: Added.
* http/tests/appcache/simple-video-async-expected.txt: Added.
* http/tests/appcache/simple-video-async.html: Added.

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

13 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/appcache/resources/simple-video-async.manifest [new file with mode: 0644]
LayoutTests/http/tests/appcache/simple-video-async-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/appcache/simple-video-async.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/loader/DocumentLoader.cpp
Source/WebCore/loader/DocumentLoader.h
Source/WebCore/loader/ResourceLoader.cpp
Source/WebCore/loader/ResourceLoader.h
Source/WebCore/loader/SubstituteResource.h
Source/WebCore/loader/appcache/ApplicationCacheHost.cpp
Source/WebCore/loader/appcache/ApplicationCacheResource.cpp
Source/WebCore/loader/appcache/ApplicationCacheResource.h

index 70410b6..0a669f8 100644 (file)
@@ -1,3 +1,14 @@
+2015-05-31  Youenn Fablet  <youenn.fablet@crf.canon.fr>
+
+        Async XMLHttpRequest should get access to AppCache resources stored as flat files
+        https://bugs.webkit.org/show_bug.cgi?id=138506
+
+        Reviewed by Darin Adler.
+
+        * http/tests/appcache/resources/simple-video-async.manifest: Added.
+        * http/tests/appcache/simple-video-async-expected.txt: Added.
+        * http/tests/appcache/simple-video-async.html: Added.
+
 2015-05-31  Xabier Rodriguez Calvar  <calvaris@igalia.com> and Youenn Fablet <youenn.fablet@crf.canon.fr>
 
         [Streams API] Implement ReadableStreamController constructor
diff --git a/LayoutTests/http/tests/appcache/resources/simple-video-async.manifest b/LayoutTests/http/tests/appcache/resources/simple-video-async.manifest
new file mode 100644 (file)
index 0000000..872ccd6
--- /dev/null
@@ -0,0 +1,2 @@
+CACHE MANIFEST
+fake-video.mp4
diff --git a/LayoutTests/http/tests/appcache/simple-video-async-expected.txt b/LayoutTests/http/tests/appcache/simple-video-async-expected.txt
new file mode 100644 (file)
index 0000000..26b9192
--- /dev/null
@@ -0,0 +1,2 @@
+This tests that the application cache works for video retrieved by async XMLHttpRequest
+SUCCESS
diff --git a/LayoutTests/http/tests/appcache/simple-video-async.html b/LayoutTests/http/tests/appcache/simple-video-async.html
new file mode 100644 (file)
index 0000000..8f6661b
--- /dev/null
@@ -0,0 +1,38 @@
+<html manifest="resources/simple-video-async.manifest">
+<script>
+if (window.testRunner) {
+    testRunner.dumpAsText()
+    testRunner.waitUntilDone();
+}
+
+function finishTest(message) {
+    document.getElementById('result').innerHTML = message;
+    testRunner.notifyDone();
+}
+
+function cached()
+{
+    try {
+        var req = new XMLHttpRequest();
+        req.open("GET", "resources/fake-video.mp4");
+        req.send();
+        req.onloadend = function() {
+            if (req.getResponseHeader("Content-Type") != "video/mp4")
+                finishTest("FAILURE: Did not get correct content type from cached resource");
+            if (req.responseText.trim() != "This is a fake video")
+               finishTest("FAILURE: Did not get correct data from cached resource");
+            finishTest("SUCCESS");
+        }            
+    } catch (e) {
+        finishTest("FAILURE: Could not load video data from cache");
+    }     
+}
+
+applicationCache.addEventListener('cached', cached, false);
+applicationCache.addEventListener('noupdate', cached, false);
+
+</script>
+<div>This tests that the application cache works for video retrieved by async XMLHttpRequest</div>
+
+<div id="result">FAILURE</div>
+</html>
index d992e85..8eb8047 100644 (file)
@@ -1,3 +1,33 @@
+2015-05-31  Youenn Fablet  <youenn.fablet@crf.canon.fr>
+
+        Async XMLHttpRequest should get access to AppCache resources stored as flat files
+        https://bugs.webkit.org/show_bug.cgi?id=138506
+
+        Reviewed by Darin Adler.
+
+        This patch reads flat file data when DocumentLoader substituteResource delivery timer is fired.
+        Refactoring to remove ApplicationCacheHost/DocumentLoader friend link.
+        Added ResourceLoader::deliverResponseAndData helper function, taking a SharedBuffer as input to remove an unneeded copy for flat files (no change for other files). 
+
+        Test: http/tests/appcache/simple-video-async.html
+
+        * loader/DocumentLoader.cpp:
+        (WebCore::DocumentLoader::substituteResourceDeliveryTimerFired):
+        (WebCore::DocumentLoader::scheduleArchiveLoad):
+        (WebCore::DocumentLoader::scheduleSubstituteResourceLoad): Helper function to remove ApplicationCacheHost friend link.
+        * loader/DocumentLoader.h:
+        * loader/ResourceLoader.cpp:
+        (WebCore::ResourceLoader::deliverResponseAndData): Helper function, code mostly moved from DocumentLoader::substituteResourceDeliveryTimerFired.
+        * loader/ResourceLoader.h:
+        * loader/SubstituteResource.h:
+        (WebCore::SubstituteResource::deliver): Introduced to be overriden by ApplicationCacheResource to take care of flat file case.
+        * loader/appcache/ApplicationCacheHost.cpp:
+        (WebCore::ApplicationCacheHost::maybeLoadResource):
+        (WebCore::ApplicationCacheHost::scheduleLoadFallbackResourceFromApplicationCache):
+        * loader/appcache/ApplicationCacheResource.cpp:
+        (WebCore::ApplicationCacheResource::deliver): Use SharedBuffer::createWithContentsOfFile to load data stored in flat file.
+        * loader/appcache/ApplicationCacheResource.h:
+
 2015-05-31  Xabier Rodriguez Calvar  <calvaris@igalia.com> and Youenn Fablet <youenn.fablet@crf.canon.fr>
 
         [Streams API] Implement ReadableStreamController constructor
index fdcebe8..cb198cb 100644 (file)
@@ -1119,25 +1119,9 @@ void DocumentLoader::substituteResourceDeliveryTimerFired()
         RefPtr<ResourceLoader> loader = it->key;
         SubstituteResource* resource = it->value.get();
         
-        if (resource) {
-            SharedBuffer* data = resource->data();
-        
-            loader->didReceiveResponse(resource->response());
-
-            // Calling ResourceLoader::didReceiveResponse can end up cancelling the load,
-            // so we need to check if the loader has reached its terminal state.
-            if (loader->reachedTerminalState())
-                return;
-
-            loader->didReceiveData(data->data(), data->size(), data->size(), DataPayloadWholeResource);
-
-            // Calling ResourceLoader::didReceiveData can end up cancelling the load,
-            // so we need to check if the loader has reached its terminal state.
-            if (loader->reachedTerminalState())
-                return;
-
-            loader->didFinishLoading(0);
-        } else {
+        if (resource)
+            resource->deliver(*loader);
+        else {
             // A null resource means that we should fail the load.
             // FIXME: Maybe we should use another error here - something like "not in cache".
             loader->didFail(loader->cannotShowURLError());
@@ -1165,8 +1149,7 @@ void DocumentLoader::cancelPendingSubstituteLoad(ResourceLoader* loader)
 bool DocumentLoader::scheduleArchiveLoad(ResourceLoader* loader, const ResourceRequest& request)
 {
     if (ArchiveResource* resource = archiveResourceForURL(request.url())) {
-        m_pendingSubstituteResources.set(loader, resource);
-        deliverSubstituteResourcesAfterDelay();
+        scheduleSubstituteResourceLoad(*loader, *resource);
         return true;
     }
 
@@ -1189,6 +1172,12 @@ bool DocumentLoader::scheduleArchiveLoad(ResourceLoader* loader, const ResourceR
 }
 #endif // ENABLE(WEB_ARCHIVE)
 
+void DocumentLoader::scheduleSubstituteResourceLoad(ResourceLoader& loader, SubstituteResource& resource)
+{
+    m_pendingSubstituteResources.set(&loader, &resource);
+    deliverSubstituteResourcesAfterDelay();
+}
+
 void DocumentLoader::addResponse(const ResourceResponse& r)
 {
     if (!m_stopRecordingResponses)
index 19802b4..64bf35a 100644 (file)
@@ -158,6 +158,7 @@ namespace WebCore {
 
         WEBCORE_EXPORT bool scheduleArchiveLoad(ResourceLoader*, const ResourceRequest&);
 #endif
+        void scheduleSubstituteResourceLoad(ResourceLoader&, SubstituteResource&);
 
         // Return the ArchiveResource for the URL only when loading an Archive
         ArchiveResource* archiveResourceForURL(const URL&) const;
@@ -431,7 +432,6 @@ namespace WebCore {
         bool m_subresourceLoadersArePageCacheAcceptable;
         ShouldOpenExternalURLsPolicy m_shouldOpenExternalURLsPolicy { ShouldOpenExternalURLsPolicy::ShouldNotAllow };
 
-        friend class ApplicationCacheHost;  // for substitute resource delivery
         std::unique_ptr<ApplicationCacheHost> m_applicationCacheHost;
 
 #if ENABLE(CONTENT_FILTERING)
index f5daf99..2758cc1 100644 (file)
@@ -164,6 +164,24 @@ bool ResourceLoader::init(const ResourceRequest& r)
     return true;
 }
 
+void ResourceLoader::deliverResponseAndData(const ResourceResponse& response, RefPtr<SharedBuffer>&& buffer)
+{
+    Ref<ResourceLoader> protect(*this);
+
+    didReceiveResponse(response);
+    if (reachedTerminalState())
+        return;
+
+    if (buffer) {
+        unsigned size = buffer->size();
+        didReceiveBuffer(buffer.release(), size, DataPayloadWholeResource);
+        if (reachedTerminalState())
+            return;
+    }
+
+    didFinishLoading(0);
+}
+
 void ResourceLoader::start()
 {
     ASSERT(!m_handle);
index 00ed6fe..fde15d3 100644 (file)
@@ -64,6 +64,8 @@ public:
 
     virtual bool init(const ResourceRequest&);
 
+    void deliverResponseAndData(const ResourceResponse&, RefPtr<SharedBuffer>&&);
+
 #if PLATFORM(IOS)
     virtual bool startLoading()
     {
index 98c87a2..3e2b01d 100644 (file)
 #ifndef SubstituteResource_h
 #define SubstituteResource_h
 
-#include <wtf/RefCounted.h>
-
-#include "URL.h"
+#include "ResourceLoader.h"
 #include "ResourceResponse.h"
 #include "SharedBuffer.h"
 
-#include <wtf/RefPtr.h>
-
 namespace WebCore {
 
 class SubstituteResource : public RefCounted<SubstituteResource> {
@@ -44,6 +40,8 @@ public:
     const ResourceResponse& response() const { return m_response; }
     SharedBuffer* data() const { return m_data.get(); }
 
+    virtual void deliver(ResourceLoader& loader) { loader.deliverResponseAndData(m_response, m_data->copy()); }
+
 protected:
     SubstituteResource(const URL& url, const ResourceResponse& response, PassRefPtr<SharedBuffer> data)
         : m_url(url)
@@ -52,13 +50,13 @@ protected:
     {
         ASSERT(m_data);
     }
-    
+
 private:
     URL m_url;
     ResourceResponse m_response;
     RefPtr<SharedBuffer> m_data;
 };
-    
+
 }
 
 #endif // SubstituteResource_h
index 62b768f..b710a25 100644 (file)
@@ -178,9 +178,7 @@ bool ApplicationCacheHost::maybeLoadResource(ResourceLoader* loader, const Resou
     if (!shouldLoadResourceFromApplicationCache(request, resource))
         return false;
 
-    m_documentLoader.m_pendingSubstituteResources.set(loader, resource);
-    m_documentLoader.deliverSubstituteResourcesAfterDelay();
-
+    m_documentLoader.scheduleSubstituteResourceLoad(*loader, *resource);
     return true;
 }
 
@@ -436,8 +434,7 @@ bool ApplicationCacheHost::scheduleLoadFallbackResourceFromApplicationCache(Reso
 
     loader->willSwitchToSubstituteResource();
 
-    m_documentLoader.m_pendingSubstituteResources.set(loader, resource);
-    m_documentLoader.deliverSubstituteResourcesAfterDelay();
+    m_documentLoader.scheduleSubstituteResourceLoad(*loader, *resource);
 
     return true;
 }
index 2d9a8f1..8ec56df 100644 (file)
@@ -38,6 +38,16 @@ ApplicationCacheResource::ApplicationCacheResource(const URL& url, const Resourc
 {
 }
 
+void ApplicationCacheResource::deliver(ResourceLoader& loader)
+{
+    RefPtr<SharedBuffer> buffer;
+    if (m_path.isEmpty())
+        buffer = data()->copy();
+    else
+        buffer = SharedBuffer::createWithContentsOfFile(m_path);
+    loader.deliverResponseAndData(response(), WTF::move(buffer));
+}
+
 void ApplicationCacheResource::addType(unsigned type) 
 {
     // Caller should take care of storing the new type in database.
index c063a0a..cf2288d 100644 (file)
@@ -64,6 +64,8 @@ public:
 private:
     ApplicationCacheResource(const URL&, const ResourceResponse&, unsigned type, PassRefPtr<SharedBuffer>, const String& path);
 
+    virtual void deliver(ResourceLoader&) override;
+
     unsigned m_type;
     unsigned m_storageID;
     int64_t m_estimatedSizeInStorage;