Title: [228575] trunk
Revision
228575
Author
[email protected]
Date
2018-02-16 13:31:42 -0800 (Fri, 16 Feb 2018)

Log Message

Use ResourceLoader to load appcache manifest
https://bugs.webkit.org/show_bug.cgi?id=182861

Patch by Youenn Fablet <[email protected]> on 2018-02-16
Reviewed by Alex Christensen.

Source/WebCore:

Covered by updated tests.

Add ApplicationCacheResourceLoader to load an ApplicationCacheResource from a ResourceLoader.
Make use of it to load the app cache manifest.
Future work should load entries using the same loader.

Remove manifest handle.
Ensure that DocumentLoader does not register the manifest resource loader as its lifetime
is handled by its ApplicationCacheGroup.

Add a ResourceLoader option to bypass the application cache.
Use it for manifest loading.

* Sources.txt:
* WebCore.xcodeproj/project.pbxproj:
* loader/DocumentLoader.cpp:
(WebCore::DocumentLoader::addSubresourceLoader):
* loader/ResourceLoaderOptions.h:
* loader/appcache/ApplicationCacheGroup.cpp:
(WebCore::ApplicationCacheGroup::stopLoading):
(WebCore::ApplicationCacheGroup::update):
(WebCore::ApplicationCacheGroup::createRequest):
(WebCore::ApplicationCacheGroup::didReceiveResponseAsync):
(WebCore::ApplicationCacheGroup::didReceiveData):
(WebCore::ApplicationCacheGroup::didFinishLoading):
(WebCore::ApplicationCacheGroup::didFail):
(WebCore::ApplicationCacheGroup::didFinishLoadingManifest):
(WebCore::ApplicationCacheGroup::checkIfLoadIsComplete):
* loader/appcache/ApplicationCacheGroup.h:
* loader/appcache/ApplicationCacheHost.cpp:
(WebCore::ApplicationCacheHost::maybeLoadResource):
(WebCore::ApplicationCacheHost::maybeLoadFallbackForRedirect):
(WebCore::ApplicationCacheHost::maybeLoadFallbackForResponse):
(WebCore::ApplicationCacheHost::maybeLoadFallbackForError):
* loader/appcache/ApplicationCacheResourceLoader.cpp: Added.
* loader/appcache/ApplicationCacheResourceLoader.h: Added.

LayoutTests:

* http/tests/appcache/fail-on-update-2-expected.txt:
* http/tests/appcache/manifest-redirect-2-expected.txt:
* http/tests/appcache/offline-access-expected.txt:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (228574 => 228575)


--- trunk/LayoutTests/ChangeLog	2018-02-16 21:06:34 UTC (rev 228574)
+++ trunk/LayoutTests/ChangeLog	2018-02-16 21:31:42 UTC (rev 228575)
@@ -1,3 +1,14 @@
+2018-02-16  Youenn Fablet  <[email protected]>
+
+        Use ResourceLoader to load appcache manifest
+        https://bugs.webkit.org/show_bug.cgi?id=182861
+
+        Reviewed by Alex Christensen.
+
+        * http/tests/appcache/fail-on-update-2-expected.txt:
+        * http/tests/appcache/manifest-redirect-2-expected.txt:
+        * http/tests/appcache/offline-access-expected.txt:
+
 2018-02-16  Chris Dumez  <[email protected]>
 
         Crash under WebCore::EventTarget::fireEventListeners

Modified: trunk/LayoutTests/http/tests/appcache/fail-on-update-2-expected.txt (228574 => 228575)


--- trunk/LayoutTests/http/tests/appcache/fail-on-update-2-expected.txt	2018-02-16 21:06:34 UTC (rev 228574)
+++ trunk/LayoutTests/http/tests/appcache/fail-on-update-2-expected.txt	2018-02-16 21:31:42 UTC (rev 228575)
@@ -1,7 +1,7 @@
 CONSOLE MESSAGE: line 1: ApplicationCache is deprecated. Please use ServiceWorkers instead.
 CONSOLE MESSAGE: Application Cache manifest could not be fetched, because the manifest had a 404 response.
 CONSOLE MESSAGE: line 1: ApplicationCache is deprecated. Please use ServiceWorkers instead.
-CONSOLE MESSAGE: line 1: ApplicationCache is deprecated. Please use ServiceWorkers instead.
 CONSOLE MESSAGE: Application Cache manifest could not be fetched, because the manifest had a 404 response.
 CONSOLE MESSAGE: line 1: ApplicationCache is deprecated. Please use ServiceWorkers instead.
+CONSOLE MESSAGE: line 1: ApplicationCache is deprecated. Please use ServiceWorkers instead.
 SUCCESS: No crash.

Modified: trunk/LayoutTests/http/tests/appcache/manifest-redirect-2-expected.txt (228574 => 228575)


--- trunk/LayoutTests/http/tests/appcache/manifest-redirect-2-expected.txt	2018-02-16 21:06:34 UTC (rev 228574)
+++ trunk/LayoutTests/http/tests/appcache/manifest-redirect-2-expected.txt	2018-02-16 21:31:42 UTC (rev 228575)
@@ -1,4 +1,5 @@
 CONSOLE MESSAGE: line 1: ApplicationCache is deprecated. Please use ServiceWorkers instead.
+CONSOLE MESSAGE: Application Cache manifest could not be fetched, because a redirection was attempted.
 Test that a redirect makes resource caching fail.
 
 Should say SUCCESS:

Modified: trunk/LayoutTests/http/tests/appcache/offline-access-expected.txt (228574 => 228575)


--- trunk/LayoutTests/http/tests/appcache/offline-access-expected.txt	2018-02-16 21:06:34 UTC (rev 228574)
+++ trunk/LayoutTests/http/tests/appcache/offline-access-expected.txt	2018-02-16 21:31:42 UTC (rev 228575)
@@ -1,5 +1,6 @@
 CONSOLE MESSAGE: line 1: ApplicationCache is deprecated. Please use ServiceWorkers instead.
 CONSOLE MESSAGE: line 1: ApplicationCache is deprecated. Please use ServiceWorkers instead.
+CONSOLE MESSAGE: Application Cache manifest could not be fetched, because a redirection was attempted.
 CONSOLE MESSAGE: line 1: ApplicationCache is deprecated. Please use ServiceWorkers instead.
 Test that offline applications work when there is no network access (simulated).
 

Modified: trunk/Source/WebCore/ChangeLog (228574 => 228575)


--- trunk/Source/WebCore/ChangeLog	2018-02-16 21:06:34 UTC (rev 228574)
+++ trunk/Source/WebCore/ChangeLog	2018-02-16 21:31:42 UTC (rev 228575)
@@ -1,3 +1,47 @@
+2018-02-16  Youenn Fablet  <[email protected]>
+
+        Use ResourceLoader to load appcache manifest
+        https://bugs.webkit.org/show_bug.cgi?id=182861
+
+        Reviewed by Alex Christensen.
+
+        Covered by updated tests.
+
+        Add ApplicationCacheResourceLoader to load an ApplicationCacheResource from a ResourceLoader.
+        Make use of it to load the app cache manifest.
+        Future work should load entries using the same loader.
+
+        Remove manifest handle.
+        Ensure that DocumentLoader does not register the manifest resource loader as its lifetime
+        is handled by its ApplicationCacheGroup.
+
+        Add a ResourceLoader option to bypass the application cache.
+        Use it for manifest loading.
+
+        * Sources.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * loader/DocumentLoader.cpp:
+        (WebCore::DocumentLoader::addSubresourceLoader):
+        * loader/ResourceLoaderOptions.h:
+        * loader/appcache/ApplicationCacheGroup.cpp:
+        (WebCore::ApplicationCacheGroup::stopLoading):
+        (WebCore::ApplicationCacheGroup::update):
+        (WebCore::ApplicationCacheGroup::createRequest):
+        (WebCore::ApplicationCacheGroup::didReceiveResponseAsync):
+        (WebCore::ApplicationCacheGroup::didReceiveData):
+        (WebCore::ApplicationCacheGroup::didFinishLoading):
+        (WebCore::ApplicationCacheGroup::didFail):
+        (WebCore::ApplicationCacheGroup::didFinishLoadingManifest):
+        (WebCore::ApplicationCacheGroup::checkIfLoadIsComplete):
+        * loader/appcache/ApplicationCacheGroup.h:
+        * loader/appcache/ApplicationCacheHost.cpp:
+        (WebCore::ApplicationCacheHost::maybeLoadResource):
+        (WebCore::ApplicationCacheHost::maybeLoadFallbackForRedirect):
+        (WebCore::ApplicationCacheHost::maybeLoadFallbackForResponse):
+        (WebCore::ApplicationCacheHost::maybeLoadFallbackForError):
+        * loader/appcache/ApplicationCacheResourceLoader.cpp: Added.
+        * loader/appcache/ApplicationCacheResourceLoader.h: Added.
+
 2018-02-16  Chris Dumez  <[email protected]>
 
         Crash under WebCore::EventTarget::fireEventListeners

Modified: trunk/Source/WebCore/Sources.txt (228574 => 228575)


--- trunk/Source/WebCore/Sources.txt	2018-02-16 21:06:34 UTC (rev 228574)
+++ trunk/Source/WebCore/Sources.txt	2018-02-16 21:31:42 UTC (rev 228575)
@@ -1253,6 +1253,7 @@
 loader/appcache/ApplicationCacheGroup.cpp
 loader/appcache/ApplicationCacheHost.cpp
 loader/appcache/ApplicationCacheResource.cpp
+loader/appcache/ApplicationCacheResourceLoader.cpp
 loader/appcache/ApplicationCacheStorage.cpp
 loader/appcache/DOMApplicationCache.cpp
 loader/appcache/ManifestParser.cpp

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (228574 => 228575)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2018-02-16 21:06:34 UTC (rev 228574)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2018-02-16 21:31:42 UTC (rev 228575)
@@ -7103,6 +7103,8 @@
 		418C395F1C8F0AAB0051C8A3 /* ReadableStreamDefaultController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReadableStreamDefaultController.h; sourceTree = "<group>"; };
 		418F88020FF957AE0080F045 /* JSAbstractWorker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSAbstractWorker.cpp; sourceTree = "<group>"; };
 		418F88030FF957AE0080F045 /* JSAbstractWorker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSAbstractWorker.h; sourceTree = "<group>"; };
+		41945694203502A5004BA277 /* ApplicationCacheResourceLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ApplicationCacheResourceLoader.cpp; sourceTree = "<group>"; };
+		41945696203502A6004BA277 /* ApplicationCacheResourceLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ApplicationCacheResourceLoader.h; sourceTree = "<group>"; };
 		419ACF8E1F97E7D5009F1A83 /* ServiceWorkerFetch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServiceWorkerFetch.h; sourceTree = "<group>"; };
 		419ACF901F97E7D6009F1A83 /* ServiceWorkerFetch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ServiceWorkerFetch.cpp; sourceTree = "<group>"; };
 		419BC2DC1685329900D64D6D /* VisitedLinkState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VisitedLinkState.cpp; sourceTree = "<group>"; };
@@ -15692,6 +15694,8 @@
 				24F54EAB101FE914000AE741 /* ApplicationCacheHost.h */,
 				1A8F6BB50DB55CDC001DB794 /* ApplicationCacheResource.cpp */,
 				1A8F6BB60DB55CDC001DB794 /* ApplicationCacheResource.h */,
+				41945694203502A5004BA277 /* ApplicationCacheResourceLoader.cpp */,
+				41945696203502A6004BA277 /* ApplicationCacheResourceLoader.h */,
 				1A2AAC560DC2A3B100A20D9A /* ApplicationCacheStorage.cpp */,
 				1A2AAC570DC2A3B100A20D9A /* ApplicationCacheStorage.h */,
 				1A8F6BB70DB55CDC001DB794 /* DOMApplicationCache.cpp */,

Modified: trunk/Source/WebCore/loader/DocumentLoader.cpp (228574 => 228575)


--- trunk/Source/WebCore/loader/DocumentLoader.cpp	2018-02-16 21:06:34 UTC (rev 228574)
+++ trunk/Source/WebCore/loader/DocumentLoader.cpp	2018-02-16 21:31:42 UTC (rev 228575)
@@ -1538,6 +1538,10 @@
     ASSERT(!m_subresourceLoaders.contains(loader->identifier()));
     ASSERT(!mainResourceLoader() || mainResourceLoader() != loader);
 
+    // Application Cache loaders are handled by their ApplicationCacheGroup directly.
+    if (loader->options().applicationCacheMode == ApplicationCacheMode::Bypass)
+        return;
+
     // A page in the PageCache or about to enter PageCache should not be able to start loads.
     ASSERT_WITH_SECURITY_IMPLICATION(!document() || document()->pageCacheState() == Document::NotInPageCache);
 

Modified: trunk/Source/WebCore/loader/ResourceLoaderOptions.h (228574 => 228575)


--- trunk/Source/WebCore/loader/ResourceLoaderOptions.h	2018-02-16 21:06:34 UTC (rev 228574)
+++ trunk/Source/WebCore/loader/ResourceLoaderOptions.h	2018-02-16 21:31:42 UTC (rev 228575)
@@ -101,6 +101,11 @@
     Only // An error will happen if service worker is not handling the fetch. Used to bypass preflight safely.
 };
 
+enum class ApplicationCacheMode {
+    Use,
+    Bypass
+};
+
 enum class ContentEncodingSniffingPolicy {
     Sniff,
     DoNotSniff,
@@ -140,6 +145,7 @@
     SameOriginDataURLFlag sameOriginDataURLFlag { SameOriginDataURLFlag::Unset };
     InitiatorContext initiatorContext { InitiatorContext::Document };
     ServiceWorkersMode serviceWorkersMode { ServiceWorkersMode::All };
+    ApplicationCacheMode applicationCacheMode { ApplicationCacheMode::Use };
 #if ENABLE(SERVICE_WORKER)
     std::optional<ServiceWorkerRegistrationIdentifier> serviceWorkerRegistrationIdentifier;
     // WebKit loading code is adding some HTTP headers between the application and the time service worker intercepts the fetch.

Modified: trunk/Source/WebCore/loader/appcache/ApplicationCacheGroup.cpp (228574 => 228575)


--- trunk/Source/WebCore/loader/appcache/ApplicationCacheGroup.cpp	2018-02-16 21:06:34 UTC (rev 228574)
+++ trunk/Source/WebCore/loader/appcache/ApplicationCacheGroup.cpp	2018-02-16 21:31:42 UTC (rev 228575)
@@ -29,6 +29,7 @@
 #include "ApplicationCache.h"
 #include "ApplicationCacheHost.h"
 #include "ApplicationCacheResource.h"
+#include "ApplicationCacheResourceLoader.h"
 #include "ApplicationCacheStorage.h"
 #include "Chrome.h"
 #include "ChromeClient.h"
@@ -314,18 +315,13 @@
 
 void ApplicationCacheGroup::stopLoading()
 {
-    if (m_manifestHandle) {
-        ASSERT(!m_currentHandle);
+    if (m_loader) {
+        m_loader->cancel();
+        m_loader = nullptr;
+    }
 
-        ASSERT(m_manifestHandle->client() == this);
-        m_manifestHandle->clearClient();
-
-        m_manifestHandle->cancel();
-        m_manifestHandle = nullptr;
-    }
-    
     if (m_currentHandle) {
-        ASSERT(!m_manifestHandle);
+        ASSERT(!m_loader);
         ASSERT(m_cacheBeingUpdated);
 
         ASSERT(m_currentHandle->client() == this);
@@ -436,7 +432,7 @@
         postListenerTask(eventNames().checkingEvent, documentLoader);
     }
     
-    ASSERT(!m_manifestHandle);
+    ASSERT(!m_loader);
     ASSERT(!m_manifestResource);
     ASSERT(!m_currentHandle);
     ASSERT(!m_currentResource);
@@ -443,9 +439,52 @@
     ASSERT(m_completionType == None);
 
     // FIXME: Handle defer loading
-    m_manifestHandle = createResourceHandle(m_manifestURL, m_newestCache ? m_newestCache->manifestResource() : 0);
+
+    auto request = createRequest(URL { m_manifestURL }, m_newestCache ? m_newestCache->manifestResource() : nullptr);
+
+    m_currentResourceIdentifier = m_frame->page()->progress().createUniqueIdentifier();
+    InspectorInstrumentation::willSendRequest(m_frame, m_currentResourceIdentifier, m_frame->loader().documentLoader(), request, ResourceResponse { });
+
+    m_loader = ApplicationCacheResourceLoader::create(documentLoader.cachedResourceLoader(), WTFMove(request), [this] (auto&& resourceOrError) {
+        if (!resourceOrError.has_value()) {
+            auto error = resourceOrError.error();
+            if (error == ApplicationCacheResourceLoader::Error::Abort)
+                return;
+            if (error == ApplicationCacheResourceLoader::Error::CannotCreateResource) {
+                // FIXME: We should get back the error from ApplicationCacheResourceLoader level.
+                InspectorInstrumentation::didFailLoading(m_frame, m_frame->loader().documentLoader(), m_currentResourceIdentifier, ResourceError { ResourceError::Type::General });
+                this->cacheUpdateFailed();
+                return;
+            }
+            this->didFailLoadingManifest(error);
+            ASSERT(!m_loader);
+            return;
+        }
+
+        m_manifestResource = WTFMove(resourceOrError.value());
+        this->didFinishLoadingManifest();
+        ASSERT(!m_loader);
+    });
 }
 
+ResourceRequest ApplicationCacheGroup::createRequest(URL&& url, ApplicationCacheResource* resource)
+{
+    ResourceRequest request { WTFMove(url) };
+    m_frame->loader().applyUserAgentIfNeeded(request);
+    request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "max-age=0");
+
+    if (resource) {
+        const String& lastModified = resource->response().httpHeaderField(HTTPHeaderName::LastModified);
+        if (!lastModified.isEmpty())
+            request.setHTTPHeaderField(HTTPHeaderName::IfModifiedSince, lastModified);
+
+        const String& eTag = resource->response().httpHeaderField(HTTPHeaderName::ETag);
+        if (!eTag.isEmpty())
+            request.setHTTPHeaderField(HTTPHeaderName::IfNoneMatch, eTag);
+    }
+    return request;
+}
+
 void ApplicationCacheGroup::abort(Frame& frame)
 {
     if (m_updateStatus == Idle)
@@ -494,12 +533,6 @@
     ASSERT(m_frame);
     InspectorInstrumentation::didReceiveResourceResponse(*m_frame, m_currentResourceIdentifier, m_frame->loader().documentLoader(), response, nullptr);
 
-    if (handle == m_manifestHandle) {
-        didReceiveManifestResponse(response);
-        completionHandler();
-        return;
-    }
-
     ASSERT(handle == m_currentHandle);
 
     URL url(handle->firstRequest().url());
@@ -578,16 +611,10 @@
 void ApplicationCacheGroup::didReceiveData(ResourceHandle* handle, const char* data, unsigned length, int encodedDataLength)
 {
     UNUSED_PARAM(encodedDataLength);
+    ASSERT_UNUSED(handle, handle == m_currentHandle);
 
     InspectorInstrumentation::didReceiveData(m_frame, m_currentResourceIdentifier, 0, length, 0);
 
-    if (handle == m_manifestHandle) {
-        didReceiveManifestData(data, length);
-        return;
-    }
-    
-    ASSERT(handle == m_currentHandle);
-    
     ASSERT(m_currentResource);
     m_currentResource->data().append(data, length);
 }
@@ -598,11 +625,6 @@
     NetworkLoadMetrics emptyMetrics;
     InspectorInstrumentation::didFinishLoading(m_frame, m_frame->loader().documentLoader(), m_currentResourceIdentifier, emptyMetrics, nullptr);
 
-    if (handle == m_manifestHandle) {
-        didFinishLoadingManifest();
-        return;
-    }
-
     ASSERT(m_currentHandle == handle);
     ASSERT(m_pendingEntries.contains(handle->firstRequest().url()));
     
@@ -633,12 +655,6 @@
 {
     InspectorInstrumentation::didFailLoading(m_frame, m_frame->loader().documentLoader(), m_currentResourceIdentifier, error);
 
-    if (handle == m_manifestHandle) {
-        // A network error is logged elsewhere, no need to log again. Also, it's normal for manifest fetching to fail when working offline.
-        cacheUpdateFailed();
-        return;
-    }
-
     ASSERT(handle == m_currentHandle);
 
     unsigned type = m_currentResource ? m_currentResource->type() : m_pendingEntries.get(handle->firstRequest().url());
@@ -665,44 +681,6 @@
     }
 }
 
-void ApplicationCacheGroup::didReceiveManifestResponse(const ResourceResponse& response)
-{
-    ASSERT(!m_manifestResource);
-    ASSERT(m_manifestHandle);
-
-    if (response.httpStatusCode() == 404 || response.httpStatusCode() == 410) {
-        InspectorInstrumentation::didFailLoading(m_frame, m_frame->loader().documentLoader(), m_currentResourceIdentifier, m_frame->loader().cancelledError(m_manifestHandle->firstRequest()));
-        m_frame->document()->addConsoleMessage(MessageSource::AppCache, MessageLevel::Error, makeString("Application Cache manifest could not be fetched, because the manifest had a ", String::number(response.httpStatusCode()), " response."));
-        manifestNotFound();
-        return;
-    }
-
-    if (response.httpStatusCode() == 304)
-        return;
-
-    if (response.httpStatusCode() / 100 != 2) {
-        InspectorInstrumentation::didFailLoading(m_frame, m_frame->loader().documentLoader(), m_currentResourceIdentifier, m_frame->loader().cancelledError(m_manifestHandle->firstRequest()));
-        m_frame->document()->addConsoleMessage(MessageSource::AppCache, MessageLevel::Error, makeString("Application Cache manifest could not be fetched, because the manifest had a ", String::number(response.httpStatusCode()), " response."));
-        cacheUpdateFailed();
-        return;
-    }
-
-    if (response.url() != m_manifestHandle->firstRequest().url()) {
-        InspectorInstrumentation::didFailLoading(m_frame, m_frame->loader().documentLoader(), m_currentResourceIdentifier, m_frame->loader().cancelledError(m_manifestHandle->firstRequest()));
-        m_frame->document()->addConsoleMessage(MessageSource::AppCache, MessageLevel::Error, ASCIILiteral("Application Cache manifest could not be fetched, because a redirection was attempted."));
-        cacheUpdateFailed();
-        return;
-    }
-
-    m_manifestResource = ApplicationCacheResource::create(m_manifestHandle->firstRequest().url(), response, ApplicationCacheResource::Manifest);
-}
-
-void ApplicationCacheGroup::didReceiveManifestData(const char* data, int length)
-{
-    if (m_manifestResource)
-        m_manifestResource->data().append(data, length);
-}
-
 void ApplicationCacheGroup::didFinishLoadingManifest()
 {
     bool isUpgradeAttempt = m_newestCache;
@@ -714,7 +692,7 @@
         return;
     }
 
-    m_manifestHandle = nullptr;
+    m_loader = nullptr;
 
     // Check if the manifest was not modified.
     if (isUpgradeAttempt) {
@@ -780,6 +758,36 @@
     startLoadingEntry();
 }
 
+void ApplicationCacheGroup::didFailLoadingManifest(ApplicationCacheResourceLoader::Error error)
+{
+    ASSERT(error != ApplicationCacheResourceLoader::Error::Abort && error != ApplicationCacheResourceLoader::Error::CannotCreateResource);
+
+    InspectorInstrumentation::didReceiveResourceResponse(*m_frame, m_currentResourceIdentifier, m_frame->loader().documentLoader(), m_loader->resource()->response(), nullptr);
+    switch (error) {
+    case ApplicationCacheResourceLoader::Error::NetworkError:
+        cacheUpdateFailed();
+        break;
+    case ApplicationCacheResourceLoader::Error::NotFound:
+        InspectorInstrumentation::didFailLoading(m_frame, m_frame->loader().documentLoader(), m_currentResourceIdentifier, m_frame->loader().cancelledError(m_loader->resource()->resourceRequest()));
+        m_frame->document()->addConsoleMessage(MessageSource::AppCache, MessageLevel::Error, makeString("Application Cache manifest could not be fetched, because the manifest had a ", String::number(m_loader->resource()->response().httpStatusCode()), " response."));
+        manifestNotFound();
+        break;
+    case ApplicationCacheResourceLoader::Error::NotOK:
+        InspectorInstrumentation::didFailLoading(m_frame, m_frame->loader().documentLoader(), m_currentResourceIdentifier, m_frame->loader().cancelledError(m_loader->resource()->resourceRequest()));
+        m_frame->document()->addConsoleMessage(MessageSource::AppCache, MessageLevel::Error, makeString("Application Cache manifest could not be fetched, because the manifest had a ", String::number(m_loader->resource()->response().httpStatusCode()), " response."));
+        cacheUpdateFailed();
+        break;
+    case ApplicationCacheResourceLoader::Error::RedirectForbidden:
+        InspectorInstrumentation::didFailLoading(m_frame, m_frame->loader().documentLoader(), m_currentResourceIdentifier, m_frame->loader().cancelledError(m_loader->resource()->resourceRequest()));
+        m_frame->document()->addConsoleMessage(MessageSource::AppCache, MessageLevel::Error, makeString("Application Cache manifest could not be fetched, because a redirection was attempted."));
+        cacheUpdateFailed();
+        break;
+    case ApplicationCacheResourceLoader::Error::CannotCreateResource:
+    case ApplicationCacheResourceLoader::Error::Abort:
+        break;
+    }
+}
+
 void ApplicationCacheGroup::didReachMaxAppCacheSize()
 {
     ASSERT(m_frame);
@@ -848,9 +856,9 @@
 
 void ApplicationCacheGroup::checkIfLoadIsComplete()
 {
-    if (m_manifestHandle || !m_pendingEntries.isEmpty() || m_downloadingPendingMasterResourceLoadersCount)
+    if (m_loader || !m_pendingEntries.isEmpty() || m_downloadingPendingMasterResourceLoadersCount)
         return;
-    
+
     // We're done, all resources have finished downloading (successfully or not).
 
     bool isUpgradeAttempt = m_newestCache;

Modified: trunk/Source/WebCore/loader/appcache/ApplicationCacheGroup.h (228574 => 228575)


--- trunk/Source/WebCore/loader/appcache/ApplicationCacheGroup.h	2018-02-16 21:06:34 UTC (rev 228574)
+++ trunk/Source/WebCore/loader/appcache/ApplicationCacheGroup.h	2018-02-16 21:31:42 UTC (rev 228575)
@@ -25,6 +25,7 @@
 
 #pragma once
 
+#include "ApplicationCacheResourceLoader.h"
 #include "DOMApplicationCache.h"
 #include "URL.h"
 #include "ResourceHandleClient.h"
@@ -118,9 +119,9 @@
     void didFinishLoading(ResourceHandle*) final;
     void didFail(ResourceHandle*, const ResourceError&) final;
 
-    void didReceiveManifestResponse(const ResourceResponse&);
-    void didReceiveManifestData(const char*, int);
     void didFinishLoadingManifest();
+    void didFailLoadingManifest(ApplicationCacheResourceLoader::Error);
+
     void didReachMaxAppCacheSize();
     void didReachOriginQuota(int64_t totalSpaceNeeded);
     
@@ -137,6 +138,8 @@
     
     void stopLoading();
 
+    ResourceRequest createRequest(URL&&, ApplicationCacheResource*);
+
     Ref<ApplicationCacheStorage> m_storage;
 
     URL m_manifestURL;
@@ -195,8 +198,9 @@
     unsigned long m_currentResourceIdentifier;
 
     RefPtr<ApplicationCacheResource> m_manifestResource;
-    RefPtr<ResourceHandle> m_manifestHandle;
 
+    RefPtr<ApplicationCacheResourceLoader> m_loader;
+
     int64_t m_availableSpaceInQuota;
     bool m_originQuotaExceededPreviously { false };
 

Modified: trunk/Source/WebCore/loader/appcache/ApplicationCacheHost.cpp (228574 => 228575)


--- trunk/Source/WebCore/loader/appcache/ApplicationCacheHost.cpp	2018-02-16 21:06:34 UTC (rev 228574)
+++ trunk/Source/WebCore/loader/appcache/ApplicationCacheHost.cpp	2018-02-16 21:31:42 UTC (rev 228575)
@@ -169,6 +169,9 @@
 
 bool ApplicationCacheHost::maybeLoadResource(ResourceLoader& loader, const ResourceRequest& request, const URL& originalURL)
 {
+    if (loader.options().applicationCacheMode != ApplicationCacheMode::Use)
+        return false;
+
     if (!isApplicationCacheEnabled() && !isApplicationCacheBlockedForRequest(request))
         return false;
     
@@ -185,6 +188,9 @@
 
 bool ApplicationCacheHost::maybeLoadFallbackForRedirect(ResourceLoader* resourceLoader, ResourceRequest& request, const ResourceResponse& redirectResponse)
 {
+    if (resourceLoader && resourceLoader->options().applicationCacheMode != ApplicationCacheMode::Use)
+        return false;
+
     if (!redirectResponse.isNull() && !protocolHostAndPortAreEqual(request.url(), redirectResponse.url())) {
         if (scheduleLoadFallbackResourceFromApplicationCache(resourceLoader))
             return true;
@@ -194,6 +200,9 @@
 
 bool ApplicationCacheHost::maybeLoadFallbackForResponse(ResourceLoader* resourceLoader, const ResourceResponse& response)
 {
+    if (resourceLoader && resourceLoader->options().applicationCacheMode != ApplicationCacheMode::Use)
+        return false;
+
     if (response.httpStatusCode() / 100 == 4 || response.httpStatusCode() / 100 == 5) {
         if (scheduleLoadFallbackResourceFromApplicationCache(resourceLoader))
             return true;
@@ -203,6 +212,9 @@
 
 bool ApplicationCacheHost::maybeLoadFallbackForError(ResourceLoader* resourceLoader, const ResourceError& error)
 {
+    if (resourceLoader && resourceLoader->options().applicationCacheMode != ApplicationCacheMode::Use)
+        return false;
+
     if (!error.isCancellation()) {
         if (resourceLoader == m_documentLoader.mainResourceLoader())
             return maybeLoadFallbackForMainError(resourceLoader->request(), error);

Added: trunk/Source/WebCore/loader/appcache/ApplicationCacheResourceLoader.cpp (0 => 228575)


--- trunk/Source/WebCore/loader/appcache/ApplicationCacheResourceLoader.cpp	                        (rev 0)
+++ trunk/Source/WebCore/loader/appcache/ApplicationCacheResourceLoader.cpp	2018-02-16 21:31:42 UTC (rev 228575)
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2018 Apple 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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 "ApplicationCacheResourceLoader.h"
+
+#include "CachedResourceLoader.h"
+
+namespace WebCore {
+
+RefPtr<ApplicationCacheResourceLoader> ApplicationCacheResourceLoader::create(CachedResourceLoader& loader, ResourceRequest&& request, CompletionHandler<void(ResourceOrError&&)>&& callback)
+{
+    ResourceLoaderOptions options;
+    options.storedCredentialsPolicy = StoredCredentialsPolicy::Use;
+    options.credentials = FetchOptions::Credentials::SameOrigin;
+    options.applicationCacheMode = ApplicationCacheMode::Bypass;
+    CachedResourceRequest cachedResourceRequest { WTFMove(request), options };
+    auto resource = loader.requestRawResource(WTFMove(cachedResourceRequest));
+    if (!resource.has_value()) {
+        callback(makeUnexpected(Error::CannotCreateResource));
+        return nullptr;
+    }
+    return adoptRef(*new ApplicationCacheResourceLoader { WTFMove(resource.value()), WTFMove(callback) });
+}
+
+ApplicationCacheResourceLoader::ApplicationCacheResourceLoader(CachedResourceHandle<CachedRawResource>&& resource, CompletionHandler<void(ResourceOrError&&)>&& callback)
+    : m_resource(WTFMove(resource))
+    , m_callback(WTFMove(callback))
+{
+    m_resource->addClient(*this);
+}
+
+ApplicationCacheResourceLoader::~ApplicationCacheResourceLoader()
+{
+    cancel(Error::Abort);
+}
+
+void ApplicationCacheResourceLoader::cancel(Error error)
+{
+    if (auto callback = WTFMove(m_callback))
+        callback(makeUnexpected(error));
+
+    CachedResourceHandle<CachedRawResource> resource;
+    std::swap(resource, m_resource);
+    if (resource)
+        resource->removeClient(*this);
+}
+
+void ApplicationCacheResourceLoader::responseReceived(CachedResource& resource, const ResourceResponse& response)
+{
+    ASSERT_UNUSED(resource, &resource == m_resource);
+
+    receivedManifestResponse(response);
+}
+
+void ApplicationCacheResourceLoader::dataReceived(CachedResource&, const char* data, int length)
+{
+    m_applicationCacheResource->data().append(data, length);
+}
+
+void ApplicationCacheResourceLoader::redirectReceived(CachedResource&, ResourceRequest&&, const ResourceResponse&, CompletionHandler<void(ResourceRequest&&)>&& callback)
+{
+    cancel(Error::RedirectForbidden);
+    callback({ });
+}
+
+void ApplicationCacheResourceLoader::notifyFinished(CachedResource& resource)
+{
+    auto protectedThis = makeRef(*this);
+
+    ASSERT_UNUSED(resource, &resource == m_resource);
+
+    if (m_resource->errorOccurred()) {
+        cancel(Error::NetworkError);
+        return;
+    }
+    if (auto callback = WTFMove(m_callback))
+        callback(WTFMove(m_applicationCacheResource));
+
+    CachedResourceHandle<CachedRawResource> resourceHandle;
+    std::swap(resourceHandle, m_resource);
+    if (resourceHandle)
+        resourceHandle->removeClient(*this);
+}
+
+void ApplicationCacheResourceLoader::receivedManifestResponse(const ResourceResponse& response)
+{
+    if (response.httpStatusCode() == 404 || response.httpStatusCode() == 410) {
+        cancel(Error::NotFound);
+        return;
+    }
+
+    if (response.httpStatusCode() == 304) {
+        notifyFinished(*m_resource);
+        return;
+    }
+
+    if (response.httpStatusCode() / 100 != 2) {
+        cancel(Error::NotOK);
+        return;
+    }
+
+    m_applicationCacheResource = ApplicationCacheResource::create(m_resource->url(), response, ApplicationCacheResource::Manifest);
+}
+
+} // namespace WebCore

Added: trunk/Source/WebCore/loader/appcache/ApplicationCacheResourceLoader.h (0 => 228575)


--- trunk/Source/WebCore/loader/appcache/ApplicationCacheResourceLoader.h	                        (rev 0)
+++ trunk/Source/WebCore/loader/appcache/ApplicationCacheResourceLoader.h	2018-02-16 21:31:42 UTC (rev 228575)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2018 Apple 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:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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.
+ */
+
+#pragma once
+
+#include "CachedRawResource.h"
+#include "CachedRawResourceClient.h"
+#include "CachedResourceHandle.h"
+#include <wtf/CompletionHandler.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class CachedResourceLoader;
+class ResourceRequest;
+
+class ApplicationCacheResourceLoader final : public RefCounted<ApplicationCacheResourceLoader>, private CachedRawResourceClient {
+public:
+    enum class Error { Abort, NetworkError, CannotCreateResource, NotFound, NotOK, RedirectForbidden };
+    using ResourceOrError = Expected<RefPtr<ApplicationCacheResource>, Error>;
+
+    static RefPtr<ApplicationCacheResourceLoader> create(CachedResourceLoader&, ResourceRequest&&, CompletionHandler<void(ResourceOrError&&)>&&);
+    ~ApplicationCacheResourceLoader();
+
+    void cancel(Error = Error::Abort);
+
+    const CachedResource* resource() const { return m_resource.get(); }
+
+private:
+    explicit ApplicationCacheResourceLoader(CachedResourceHandle<CachedRawResource>&&, CompletionHandler<void(ResourceOrError&&)>&&);
+
+    void receivedManifestResponse(const ResourceResponse&);
+
+    // CachedRawResourceClient
+    void responseReceived(CachedResource&, const ResourceResponse&) final;
+    void dataReceived(CachedResource&, const char* data, int dataLength) final;
+    void redirectReceived(CachedResource&, ResourceRequest&&, const ResourceResponse&, CompletionHandler<void(ResourceRequest&&)>&&) final;
+    void notifyFinished(CachedResource&) final;
+
+    CachedResourceHandle<CachedRawResource> m_resource;
+    RefPtr<ApplicationCacheResource> m_applicationCacheResource;
+    CompletionHandler<void(ResourceOrError&&)> m_callback;
+};
+
+} // namespace WebCore
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to