/*
 * Copyright (C) 2012 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:
 * 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 GOOGLE 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 "CachedResourceRequest.h"

#include "CachedResourceLoader.h"
#include "ContentExtensionsBackend.h"
#include "CrossOriginAccessControl.h"
#include "Document.h"
#include "Element.h"
#include "FrameLoader.h"
#include "HTTPHeaderValues.h"
#include "ImageDecoder.h"
#include "MemoryCache.h"
#include "SecurityPolicy.h"
#include "ServiceWorkerRegistrationData.h"
#include <wtf/NeverDestroyed.h>

namespace WebCore {

// Created by binding generator.
String convertEnumerationToString(FetchOptions::Destination);
String convertEnumerationToString(FetchOptions::Mode);

CachedResourceRequest::CachedResourceRequest(ResourceRequest&& resourceRequest, const ResourceLoaderOptions& options, std::optional<ResourceLoadPriority> priority, String&& charset)
    : m_resourceRequest(WTFMove(resourceRequest))
    , m_charset(WTFMove(charset))
    , m_options(options)
    , m_priority(priority)
    , m_fragmentIdentifier(splitFragmentIdentifierFromRequestURL(m_resourceRequest))
{
}

String CachedResourceRequest::splitFragmentIdentifierFromRequestURL(ResourceRequest& request)
{
    if (!MemoryCache::shouldRemoveFragmentIdentifier(request.url()))
        return { };
    URL url = request.url();
    auto fragmentIdentifier = url.fragmentIdentifier().toString();
    url.removeFragmentIdentifier();
    request.setURL(url);
    return fragmentIdentifier;
}

void CachedResourceRequest::setInitiator(Element& element)
{
    ASSERT(!m_initiatorElement);
    ASSERT(m_initiatorName.isEmpty());
    m_initiatorElement = &element;
}

void CachedResourceRequest::setInitiator(const AtomString& name)
{
    ASSERT(!m_initiatorElement);
    ASSERT(m_initiatorName.isEmpty());
    m_initiatorName = name;
}

const AtomString& CachedResourceRequest::initiatorName() const
{
    if (m_initiatorElement)
        return m_initiatorElement->localName();
    if (!m_initiatorName.isEmpty())
        return m_initiatorName;

    static MainThreadNeverDestroyed<const AtomString> defaultName("other"_s);
    return defaultName;
}

void CachedResourceRequest::updateForAccessControl(Document& document)
{
    ASSERT(m_options.mode == FetchOptions::Mode::Cors);

    m_origin = &document.securityOrigin();
    updateRequestForAccessControl(m_resourceRequest, *m_origin, m_options.storedCredentialsPolicy);
}

void upgradeInsecureResourceRequestIfNeeded(ResourceRequest& request, Document& document)
{
    URL url = request.url();

    ASSERT(document.contentSecurityPolicy());
    document.contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(url, ContentSecurityPolicy::InsecureRequestType::Load);

    if (url == request.url())
        return;

    request.setURL(url);
}

void CachedResourceRequest::upgradeInsecureRequestIfNeeded(Document& document)
{
    upgradeInsecureResourceRequestIfNeeded(m_resourceRequest, document);
}

void CachedResourceRequest::setDomainForCachePartition(Document& document)
{
    m_resourceRequest.setDomainForCachePartition(document.domainForCachePartition());
}

void CachedResourceRequest::setDomainForCachePartition(const String& domain)
{
    m_resourceRequest.setDomainForCachePartition(domain);
}

static inline constexpr ASCIILiteral acceptHeaderValueForImageResource(bool supportsVideoImage)
{
#if HAVE(WEBP) || USE(WEBP)
    #define WEBP_HEADER_PART "image/webp,"
#else
    #define WEBP_HEADER_PART ""
#endif
    if (supportsVideoImage)
        return WEBP_HEADER_PART "image/png,image/svg+xml,image/*;q=0.8,video/*;q=0.8,*/*;q=0.5"_s;
    return WEBP_HEADER_PART "image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5"_s;
    #undef WEBP_HEADER_PART
}

String CachedResourceRequest::acceptHeaderValueFromType(CachedResource::Type type)
{
    switch (type) {
    case CachedResource::Type::MainResource:
        return "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"_s;
    case CachedResource::Type::ImageResource:
        return acceptHeaderValueForImageResource(ImageDecoder::supportsMediaType(ImageDecoder::MediaType::Video));
    case CachedResource::Type::CSSStyleSheet:
        return "text/css,*/*;q=0.1"_s;
    case CachedResource::Type::SVGDocumentResource:
        return "image/svg+xml"_s;
#if ENABLE(XSLT)
    case CachedResource::Type::XSLStyleSheet:
        // FIXME: This should accept more general xml formats */*+xml, image/svg+xml for example.
        return "text/xml,application/xml,application/xhtml+xml,text/xsl,application/rss+xml,application/atom+xml"_s;
#endif
    default:
        return "*/*"_s;
    }
}

void CachedResourceRequest::setAcceptHeaderIfNone(CachedResource::Type type)
{
    if (!m_resourceRequest.hasHTTPHeader(HTTPHeaderName::Accept))
        m_resourceRequest.setHTTPHeaderField(HTTPHeaderName::Accept, acceptHeaderValueFromType(type));
}

void CachedResourceRequest::updateAccordingCacheMode()
{
    if (m_options.cache == FetchOptions::Cache::Default
        && (m_resourceRequest.hasHTTPHeaderField(HTTPHeaderName::IfModifiedSince)
            || m_resourceRequest.hasHTTPHeaderField(HTTPHeaderName::IfNoneMatch)
            || m_resourceRequest.hasHTTPHeaderField(HTTPHeaderName::IfUnmodifiedSince)
            || m_resourceRequest.hasHTTPHeaderField(HTTPHeaderName::IfMatch)
            || m_resourceRequest.hasHTTPHeaderField(HTTPHeaderName::IfRange)))
        m_options.cache = FetchOptions::Cache::NoStore;

    switch (m_options.cache) {
    case FetchOptions::Cache::NoCache:
        m_resourceRequest.setCachePolicy(ResourceRequestCachePolicy::RefreshAnyCacheData);
        m_resourceRequest.addHTTPHeaderFieldIfNotPresent(HTTPHeaderName::CacheControl, HTTPHeaderValues::maxAge0());
        break;
    case FetchOptions::Cache::NoStore:
        m_options.cachingPolicy = CachingPolicy::DisallowCaching;
        m_resourceRequest.setCachePolicy(ResourceRequestCachePolicy::DoNotUseAnyCache);
        m_resourceRequest.addHTTPHeaderFieldIfNotPresent(HTTPHeaderName::Pragma, HTTPHeaderValues::noCache());
        m_resourceRequest.addHTTPHeaderFieldIfNotPresent(HTTPHeaderName::CacheControl, HTTPHeaderValues::noCache());
        break;
    case FetchOptions::Cache::Reload:
        m_resourceRequest.setCachePolicy(ResourceRequestCachePolicy::ReloadIgnoringCacheData);
        m_resourceRequest.addHTTPHeaderFieldIfNotPresent(HTTPHeaderName::Pragma, HTTPHeaderValues::noCache());
        m_resourceRequest.addHTTPHeaderFieldIfNotPresent(HTTPHeaderName::CacheControl, HTTPHeaderValues::noCache());
        break;
    case FetchOptions::Cache::Default:
        break;
    case FetchOptions::Cache::ForceCache:
        m_resourceRequest.setCachePolicy(ResourceRequestCachePolicy::ReturnCacheDataElseLoad);
        break;
    case FetchOptions::Cache::OnlyIfCached:
        m_resourceRequest.setCachePolicy(ResourceRequestCachePolicy::ReturnCacheDataDontLoad);
        break;
    }
}

void CachedResourceRequest::updateAcceptEncodingHeader()
{
    if (!m_resourceRequest.hasHTTPHeaderField(HTTPHeaderName::Range))
        return;

    // FIXME: rdar://problem/40879225. Media engines triggering the load should not set this Accept-Encoding header.
    ASSERT(!m_resourceRequest.hasHTTPHeaderField(HTTPHeaderName::AcceptEncoding) || m_options.destination == FetchOptions::Destination::Audio || m_options.destination == FetchOptions::Destination::Video);

    m_resourceRequest.addHTTPHeaderFieldIfNotPresent(HTTPHeaderName::AcceptEncoding, "identity"_s);
}

void CachedResourceRequest::removeFragmentIdentifierIfNeeded()
{
    URL url = MemoryCache::removeFragmentIdentifierIfNeeded(m_resourceRequest.url());
    if (url.string() != m_resourceRequest.url())
        m_resourceRequest.setURL(url);
}

#if ENABLE(CONTENT_EXTENSIONS)

void CachedResourceRequest::applyResults(ContentRuleListResults&& results, Page* page)
{
    ContentExtensions::applyResultsToRequest(WTFMove(results), page, m_resourceRequest);
}

#endif

void CachedResourceRequest::updateReferrerPolicy(ReferrerPolicy defaultPolicy)
{
    if (m_options.referrerPolicy == ReferrerPolicy::EmptyString)
        m_options.referrerPolicy = defaultPolicy;
}

void CachedResourceRequest::updateReferrerAndOriginHeaders(FrameLoader& frameLoader)
{
    // Implementing step 9 to 11 of https://fetch.spec.whatwg.org/#http-network-or-cache-fetch as of 16 March 2018
    String outgoingReferrer = frameLoader.outgoingReferrer();
    if (m_resourceRequest.hasHTTPReferrer())
        outgoingReferrer = m_resourceRequest.httpReferrer();
    updateRequestReferrer(m_resourceRequest, m_options.referrerPolicy, outgoingReferrer);

    if (!m_resourceRequest.httpOrigin().isEmpty())
        return;
    String outgoingOrigin;
    if (m_options.mode == FetchOptions::Mode::Cors)
        outgoingOrigin = SecurityOrigin::createFromString(outgoingReferrer)->toString();
    else
        outgoingOrigin = SecurityPolicy::generateOriginHeader(m_options.referrerPolicy, m_resourceRequest.url(), SecurityOrigin::createFromString(outgoingReferrer));
    FrameLoader::addHTTPOriginIfNeeded(m_resourceRequest, outgoingOrigin);
}

void CachedResourceRequest::updateFetchMetadataHeaders()
{
    // Implementing step 13 of https://fetch.spec.whatwg.org/#http-network-or-cache-fetch as of 22 Feb 2022
    // https://w3c.github.io/webappsec-fetch-metadata/#fetch-integration
    auto requestOrigin = SecurityOrigin::create(m_resourceRequest.url());
    if (!requestOrigin->isPotentiallyTrustworthy())
        return;

    // The Fetch IDL documents this as "" while FetchMetadata expects "empty", otherwise they match.
    String destinationString = m_options.destination == FetchOptions::Destination::EmptyString ? "empty"_s : convertEnumerationToString(m_options.destination);
    m_resourceRequest.setHTTPHeaderField(HTTPHeaderName::SecFetchDest, WTFMove(destinationString));
    m_resourceRequest.setHTTPHeaderField(HTTPHeaderName::SecFetchMode, convertEnumerationToString(m_options.mode));
}

void CachedResourceRequest::updateUserAgentHeader(FrameLoader& frameLoader)
{
    frameLoader.applyUserAgentIfNeeded(m_resourceRequest);
}

bool isRequestCrossOrigin(SecurityOrigin* origin, const URL& requestURL, const ResourceLoaderOptions& options)
{
    if (!origin)
        return false;

    // Using same origin mode guarantees the loader will not do a cross-origin load, so we let it take care of it and just return false.
    if (options.mode == FetchOptions::Mode::SameOrigin)
        return false;

    // FIXME: We should remove options.sameOriginDataURLFlag once https://github.com/whatwg/fetch/issues/393 is fixed.
    if (requestURL.protocolIsData() && options.sameOriginDataURLFlag == SameOriginDataURLFlag::Set)
        return false;

    return !origin->canRequest(requestURL);
}

void CachedResourceRequest::setDestinationIfNotSet(FetchOptions::Destination destination)
{
    if (m_options.destination != FetchOptions::Destination::EmptyString)
        return;
    m_options.destination = destination;
}

#if ENABLE(SERVICE_WORKER)
void CachedResourceRequest::setClientIdentifierIfNeeded(ScriptExecutionContextIdentifier clientIdentifier)
{
    if (!m_options.clientIdentifier)
        m_options.clientIdentifier = clientIdentifier;
}

void CachedResourceRequest::setSelectedServiceWorkerRegistrationIdentifierIfNeeded(ServiceWorkerRegistrationIdentifier identifier)
{
    if (isNonSubresourceRequest(m_options.destination))
        return;
    if (isPotentialNavigationOrSubresourceRequest(m_options.destination))
        return;

    if (m_options.serviceWorkersMode == ServiceWorkersMode::None)
        return;
    if (m_options.serviceWorkerRegistrationIdentifier)
        return;

    m_options.serviceWorkerRegistrationIdentifier = identifier;
}

void CachedResourceRequest::setNavigationServiceWorkerRegistrationData(const std::optional<ServiceWorkerRegistrationData>& data)
{
    if (!data || !data->activeWorker) {
        m_options.serviceWorkersMode = ServiceWorkersMode::None;
        return;
    }
    m_options.serviceWorkerRegistrationIdentifier = data->identifier;
}
#endif

} // namespace WebCore
