Shrink various loading-related enums to shrink CachedResource
[WebKit-https.git] / Source / WebCore / Modules / fetch / FetchLoader.cpp
index 6e79e54..c0dbf5f 100644 (file)
 #include "config.h"
 #include "FetchLoader.h"
 
-#if ENABLE(FETCH_API)
-
 #include "BlobURL.h"
+#include "CachedResourceRequestInitiators.h"
+#include "ContentSecurityPolicy.h"
 #include "FetchBody.h"
 #include "FetchLoaderClient.h"
 #include "FetchRequest.h"
+#include "ResourceError.h"
 #include "ResourceRequest.h"
 #include "ScriptExecutionContext.h"
 #include "SecurityOrigin.h"
 #include "SharedBuffer.h"
 #include "TextResourceDecoder.h"
 #include "ThreadableBlobRegistry.h"
-#include "ThreadableLoader.h"
 
 namespace WebCore {
 
-void FetchLoader::start(ScriptExecutionContext& context, Blob& blob)
+FetchLoader::~FetchLoader()
+{
+    if (!m_urlForReading.isEmpty())
+        ThreadableBlobRegistry::unregisterBlobURL(m_urlForReading);
+}
+
+void FetchLoader::start(ScriptExecutionContext& context, const Blob& blob)
+{
+    return startLoadingBlobURL(context, blob.url());
+}
+
+void FetchLoader::startLoadingBlobURL(ScriptExecutionContext& context, const URL& blobURL)
 {
-    auto urlForReading = BlobURL::createPublicURL(context.securityOrigin());
-    if (urlForReading.isEmpty()) {
-        m_client.didFail();
+    m_urlForReading = BlobURL::createPublicURL(context.securityOrigin());
+    if (m_urlForReading.isEmpty()) {
+        m_client.didFail({ errorDomainWebKitInternal, 0, URL(), "Could not create URL for Blob"_s });
         return;
     }
 
-    ThreadableBlobRegistry::registerBlobURL(context.securityOrigin(), urlForReading, blob.url());
+    ThreadableBlobRegistry::registerBlobURL(context.securityOrigin(), m_urlForReading, blobURL);
 
-    ResourceRequest request(urlForReading);
+    ResourceRequest request(m_urlForReading);
+    request.setInitiatorIdentifier(context.resourceRequestIdentifier());
     request.setHTTPMethod("GET");
 
     ThreadableLoaderOptions options;
-    options.setSendLoadCallbacks(SendCallbacks);
-    options.setSniffContent(DoNotSniffContent);
-    options.setDataBufferingPolicy(DoNotBufferData);
-    options.preflightPolicy = ConsiderPreflight;
-    options.setAllowCredentials(AllowStoredCredentials);
-    options.crossOriginRequestPolicy = DenyCrossOriginRequests;
+    options.sendLoadCallbacks = SendCallbackPolicy::SendCallbacks;
+    options.dataBufferingPolicy = DataBufferingPolicy::DoNotBufferData;
+    options.preflightPolicy = PreflightPolicy::Consider;
+    options.credentials = FetchOptions::Credentials::Include;
+    options.mode = FetchOptions::Mode::SameOrigin;
     options.contentSecurityPolicyEnforcement = ContentSecurityPolicyEnforcement::DoNotEnforce;
 
-    m_loader = ThreadableLoader::create(&context, this, request, options);
+    m_loader = ThreadableLoader::create(context, *this, WTFMove(request), options);
     m_isStarted = m_loader;
 }
 
 void FetchLoader::start(ScriptExecutionContext& context, const FetchRequest& request)
 {
-    ThreadableLoaderOptions options;
-    options.setSendLoadCallbacks(SendCallbacks);
-    options.setSniffContent(DoNotSniffContent);
-    options.setDataBufferingPolicy(DoNotBufferData);
-    options.preflightPolicy = ConsiderPreflight;
-    options.setAllowCredentials(AllowStoredCredentials);
-    options.crossOriginRequestPolicy = DenyCrossOriginRequests;
-    options.contentSecurityPolicyEnforcement = ContentSecurityPolicyEnforcement::DoNotEnforce;
+    ResourceLoaderOptions resourceLoaderOptions = request.fetchOptions();
+    resourceLoaderOptions.preflightPolicy = PreflightPolicy::Consider;
+    ThreadableLoaderOptions options(resourceLoaderOptions,
+        context.shouldBypassMainWorldContentSecurityPolicy() ? ContentSecurityPolicyEnforcement::DoNotEnforce : ContentSecurityPolicyEnforcement::EnforceConnectSrcDirective,
+        String(cachedResourceRequestInitiators().fetch),
+        ResponseFilteringPolicy::Disable);
+    options.sendLoadCallbacks = SendCallbackPolicy::SendCallbacks;
+    options.dataBufferingPolicy = DataBufferingPolicy::DoNotBufferData;
+    options.sameOriginDataURLFlag = SameOriginDataURLFlag::Set;
+
+    ResourceRequest fetchRequest = request.resourceRequest();
 
-    // FIXME: Pass directly all fetch options to loader options.
-    options.redirect = request.fetchOptions().redirect;
+    ASSERT(context.contentSecurityPolicy());
+    auto& contentSecurityPolicy = *context.contentSecurityPolicy();
 
-    m_loader = ThreadableLoader::create(&context, this, request.internalRequest(), options);
+    contentSecurityPolicy.upgradeInsecureRequestIfNeeded(fetchRequest, ContentSecurityPolicy::InsecureRequestType::Load);
+
+    if (!context.shouldBypassMainWorldContentSecurityPolicy() && !contentSecurityPolicy.allowConnectToSource(fetchRequest.url())) {
+        m_client.didFail({ errorDomainWebKitInternal, 0, fetchRequest.url(), "Not allowed by ContentSecurityPolicy"_s, ResourceError::Type::AccessControl });
+        return;
+    }
+
+    String referrer = request.internalRequestReferrer();
+    if (referrer == "no-referrer") {
+        options.referrerPolicy = ReferrerPolicy::NoReferrer;
+        referrer = String();
+    } else
+        referrer = (referrer == "client") ? context.url().strippedForUseAsReferrer() : URL(context.url(), referrer).strippedForUseAsReferrer();
+
+    m_loader = ThreadableLoader::create(context, *this, WTFMove(fetchRequest), options, WTFMove(referrer));
     m_isStarted = m_loader;
 }
 
-FetchLoader::FetchLoader(Type type, FetchLoaderClient& client)
-    : m_type(type)
-    , m_client(client)
+FetchLoader::FetchLoader(FetchLoaderClient& client, FetchBodyConsumer* consumer)
+    : m_client(client)
+    , m_consumer(consumer)
 {
 }
 
 void FetchLoader::stop()
 {
-    m_data = nullptr;
+    if (m_consumer)
+        m_consumer->clean();
     if (m_loader)
         m_loader->cancel();
 }
 
 RefPtr<SharedBuffer> FetchLoader::startStreaming()
 {
-    ASSERT(m_type == Type::ArrayBuffer);
-    m_type = Type::Stream;
-    return WTFMove(m_data);
+    ASSERT(m_consumer);
+    auto firstChunk = m_consumer->takeData();
+    m_consumer = nullptr;
+    return firstChunk;
 }
 
 void FetchLoader::didReceiveResponse(unsigned long, const ResourceResponse& response)
@@ -114,37 +144,23 @@ void FetchLoader::didReceiveResponse(unsigned long, const ResourceResponse& resp
     m_client.didReceiveResponse(response);
 }
 
-// FIXME: We should make text and blob creation more efficient.
-// We might also want to merge this class with FileReaderLoader.
 void FetchLoader::didReceiveData(const char* value, int size)
 {
-    if (m_type == Type::Stream) {
+    if (!m_consumer) {
         m_client.didReceiveData(value, size);
         return;
     }
-    if (!m_data) {
-        m_data = SharedBuffer::create(value, size);
-        return;
-    }
-    m_data->append(value, size);
+    m_consumer->append(value, size);
 }
 
-void FetchLoader::didFinishLoading(unsigned long, double)
+void FetchLoader::didFinishLoading(unsigned long)
 {
-    if (m_type == Type::ArrayBuffer)
-        m_client.didFinishLoadingAsArrayBuffer(m_data ? m_data->createArrayBuffer() : ArrayBuffer::tryCreate(nullptr, 0));
-    else if (m_type == Type::Text)
-        m_client.didFinishLoadingAsText(m_data ? TextResourceDecoder::create(ASCIILiteral("text/plain"), "UTF-8")->decodeAndFlush(m_data->data(), m_data->size()): String());
-    m_data = nullptr;
-
     m_client.didSucceed();
 }
 
-void FetchLoader::didFail(const ResourceError&)
+void FetchLoader::didFail(const ResourceError& error)
 {
-    m_client.didFail();
+    m_client.didFail(error);
 }
 
 } // namespace WebCore
-
-#endif // ENABLE(FETCH_API)