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