/*
 * Copyright (C) 2008-2016 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 "ApplicationCacheHost.h"

#include "ApplicationCache.h"
#include "ApplicationCacheGroup.h"
#include "ApplicationCacheResource.h"
#include "ContentSecurityPolicy.h"
#include "DocumentLoader.h"
#include "DOMApplicationCache.h"
#include "EventNames.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "FrameLoaderClient.h"
#include "InspectorInstrumentation.h"
#include "Page.h"
#include "ProgressEvent.h"
#include "ResourceHandle.h"
#include "ResourceRequest.h"
#include "Settings.h"
#include "SubresourceLoader.h"
#include <wtf/FileSystem.h>
#include <wtf/UUID.h>

namespace WebCore {

ApplicationCacheHost::ApplicationCacheHost(DocumentLoader& documentLoader)
    : m_documentLoader(documentLoader)
{
}

ApplicationCacheHost::~ApplicationCacheHost()
{
    ASSERT(!m_applicationCache || !m_candidateApplicationCacheGroup || m_applicationCache->group() == m_candidateApplicationCacheGroup);
    if (m_applicationCache)
        m_applicationCache->group()->disassociateDocumentLoader(m_documentLoader);
    else if (m_candidateApplicationCacheGroup)
        m_candidateApplicationCacheGroup->disassociateDocumentLoader(m_documentLoader);
}

void ApplicationCacheHost::selectCacheWithoutManifest()
{
    ASSERT(m_documentLoader.frame());
    ApplicationCacheGroup::selectCacheWithoutManifestURL(*m_documentLoader.frame());
}

void ApplicationCacheHost::selectCacheWithManifest(const URL& manifestURL)
{
    ASSERT(m_documentLoader.frame());
    ApplicationCacheGroup::selectCache(*m_documentLoader.frame(), manifestURL);
}

void ApplicationCacheHost::maybeLoadMainResource(const ResourceRequest& request, SubstituteData& substituteData)
{
    // Check if this request should be loaded from the application cache
    if (!substituteData.isValid() && isApplicationCacheEnabled() && !isApplicationCacheBlockedForRequest(request)) {
        ASSERT(!m_mainResourceApplicationCache);

        m_mainResourceApplicationCache = ApplicationCacheGroup::cacheForMainRequest(request, &m_documentLoader);

        if (m_mainResourceApplicationCache) {
            // Get the resource from the application cache. By definition, cacheForMainRequest() returns a cache that contains the resource.
            ApplicationCacheResource* resource = m_mainResourceApplicationCache->resourceForRequest(request);

            // ApplicationCache resources have fragment identifiers stripped off of their URLs,
            // but we'll need to restore that for the SubstituteData.
            ResourceResponse responseToUse = resource->response();
            if (request.url().hasFragmentIdentifier()) {
                URL url = responseToUse.url();
                url.setFragmentIdentifier(request.url().fragmentIdentifier());
                responseToUse.setURL(url);
            }

            substituteData = SubstituteData(&resource->data(),
                                            URL(),
                                            responseToUse,
                                            SubstituteData::SessionHistoryVisibility::Visible);
        }
    }
}

void ApplicationCacheHost::maybeLoadMainResourceForRedirect(const ResourceRequest& request, SubstituteData& substituteData)
{
    ASSERT(status() == UNCACHED);
    maybeLoadMainResource(request, substituteData);
}

bool ApplicationCacheHost::maybeLoadFallbackForMainResponse(const ResourceRequest& request, const ResourceResponse& r)
{
    if (r.httpStatusCode() / 100 == 4 || r.httpStatusCode() / 100 == 5) {
        ASSERT(!m_mainResourceApplicationCache);
        if (isApplicationCacheEnabled() && !isApplicationCacheBlockedForRequest(request)) {
            m_mainResourceApplicationCache = ApplicationCacheGroup::fallbackCacheForMainRequest(request, &m_documentLoader);

            if (scheduleLoadFallbackResourceFromApplicationCache(m_documentLoader.mainResourceLoader(), m_mainResourceApplicationCache.get()))
                return true;
        }
    }
    return false;
}

bool ApplicationCacheHost::maybeLoadFallbackForMainError(const ResourceRequest& request, const ResourceError& error)
{
    if (!error.isCancellation()) {
        ASSERT(!m_mainResourceApplicationCache);
        if (isApplicationCacheEnabled() && !isApplicationCacheBlockedForRequest(request)) {
            m_mainResourceApplicationCache = ApplicationCacheGroup::fallbackCacheForMainRequest(request, &m_documentLoader);

            if (scheduleLoadFallbackResourceFromApplicationCache(m_documentLoader.mainResourceLoader(), m_mainResourceApplicationCache.get()))
                return true;
        }
    }
    return false;
}

void ApplicationCacheHost::mainResourceDataReceived(const char*, int, long long, bool)
{
}

void ApplicationCacheHost::failedLoadingMainResource()
{
    auto* group = m_candidateApplicationCacheGroup;
    if (!group && m_applicationCache) {
        if (mainResourceApplicationCache()) {
            // Even when the main resource is being loaded from an application cache, loading can fail if aborted.
            return;
        }
        group = m_applicationCache->group();
    }
    
    if (group)
        group->failedLoadingMainResource(m_documentLoader);
}

void ApplicationCacheHost::finishedLoadingMainResource()
{
    auto* group = candidateApplicationCacheGroup();
    if (!group && applicationCache() && !mainResourceApplicationCache())
        group = applicationCache()->group();
    
    if (group)
        group->finishedLoadingMainResource(m_documentLoader);
}

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;
    
    if (request.url() != originalURL)
        return false;

#if ENABLE(SERVICE_WORKER)
    if (loader.options().serviceWorkerRegistrationIdentifier)
        return false;
#endif

    ApplicationCacheResource* resource;
    if (!shouldLoadResourceFromApplicationCache(request, resource))
        return false;

    if (resource)
        m_documentLoader.scheduleSubstituteResourceLoad(loader, *resource);
    else
        m_documentLoader.scheduleCannotShowURLError(loader);
    return true;
}

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;
    }
    return false;
}

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;
    }
    return false;
}

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);
        if (scheduleLoadFallbackResourceFromApplicationCache(resourceLoader))
            return true;
    }
    return false;
}

URL ApplicationCacheHost::createFileURL(const String& path)
{
    // FIXME: Can we just use fileURLWithFileSystemPath instead?
#if USE(CF) && PLATFORM(WIN)
    URL url(adoptCF(CFURLCreateWithFileSystemPath(0, path.createCFString().get(), kCFURLWindowsPathStyle, false)).get());
#else
    URL url;
    url.setProtocol("file"_s);
    url.setPath(path);
#endif
    return url;
}

static inline RefPtr<SharedBuffer> bufferFromResource(ApplicationCacheResource& resource)
{
    // FIXME: Clients probably do not need a copy of the SharedBuffer.
    // Remove the call to copy() once we ensure SharedBuffer will not be modified.
    if (resource.path().isEmpty())
        return resource.data().copy();
    return SharedBuffer::createWithContentsOfFile(resource.path());
}

bool ApplicationCacheHost::maybeLoadSynchronously(ResourceRequest& request, ResourceError& error, ResourceResponse& response, RefPtr<SharedBuffer>& data)
{
    ApplicationCacheResource* resource;
    if (!shouldLoadResourceFromApplicationCache(request, resource))
        return false;

    auto responseData = resource ? bufferFromResource(*resource) : nullptr;
    if (!responseData) {
        error = m_documentLoader.frameLoader()->client().cannotShowURLError(request);
        return true;
    }

    response = resource->response();
    data = WTFMove(responseData);
    return true;
}

void ApplicationCacheHost::maybeLoadFallbackSynchronously(const ResourceRequest& request, ResourceError& error, ResourceResponse& response, RefPtr<SharedBuffer>& data)
{
    // If normal loading results in a redirect to a resource with another origin (indicative of a captive portal), or a 4xx or 5xx status code or equivalent,
    // or if there were network errors (but not if the user canceled the download), then instead get, from the cache, the resource of the fallback entry
    // corresponding to the matched namespace.
    if ((!error.isNull() && !error.isCancellation())
         || response.httpStatusCode() / 100 == 4 || response.httpStatusCode() / 100 == 5
         || !protocolHostAndPortAreEqual(request.url(), response.url())) {
        ApplicationCacheResource* resource;
        if (getApplicationCacheFallbackResource(request, resource)) {
            response = resource->response();
            // FIXME: Clients proably do not need a copy of the SharedBuffer.
            // Remove the call to copy() once we ensure SharedBuffer will not be modified.
            data = resource->data().copy();
        }
    }
}

bool ApplicationCacheHost::canCacheInPageCache()
{
    return !applicationCache() && !candidateApplicationCacheGroup();
}

void ApplicationCacheHost::setDOMApplicationCache(DOMApplicationCache* domApplicationCache)
{
    ASSERT(!m_domApplicationCache || !domApplicationCache);
    m_domApplicationCache = makeWeakPtr(domApplicationCache);
}

void ApplicationCacheHost::notifyDOMApplicationCache(const AtomicString& eventType, int total, int done)
{
    if (eventType != eventNames().progressEvent)
        InspectorInstrumentation::updateApplicationCacheStatus(m_documentLoader.frame());

    if (m_defersEvents) {
        // Event dispatching is deferred until document.onload has fired.
        m_deferredEvents.append({ eventType, total, done });
        return;
    }

    dispatchDOMEvent(eventType, total, done);
}

void ApplicationCacheHost::stopLoadingInFrame(Frame& frame)
{
    ASSERT(!m_applicationCache || !m_candidateApplicationCacheGroup || m_applicationCache->group() == m_candidateApplicationCacheGroup);

    if (m_candidateApplicationCacheGroup)
        m_candidateApplicationCacheGroup->stopLoadingInFrame(frame);
    else if (m_applicationCache)
        m_applicationCache->group()->stopLoadingInFrame(frame);
}

void ApplicationCacheHost::stopDeferringEvents()
{
    Ref<DocumentLoader> protect(m_documentLoader);

    // Note, do not cache the size in a local variable.
    // This code needs to properly handle the case where more events are added to
    // m_deferredEvents while iterating it. This is why we don't use a modern for loop.
    for (size_t i = 0; i < m_deferredEvents.size(); ++i) {
        auto& event = m_deferredEvents[i];
        dispatchDOMEvent(event.eventType, event.progressTotal, event.progressDone);
    }

    m_deferredEvents.clear();
    m_defersEvents = false;
}

Vector<ApplicationCacheHost::ResourceInfo> ApplicationCacheHost::resourceList()
{
    auto* cache = applicationCache();
    if (!cache || !cache->isComplete())
        return { };

    return WTF::map(cache->resources(), [] (auto& urlAndResource) -> ApplicationCacheHost::ResourceInfo {
        ASSERT(urlAndResource.value);
        auto& resource = *urlAndResource.value;

        unsigned type = resource.type();
        bool isMaster = type & ApplicationCacheResource::Master;
        bool isManifest = type & ApplicationCacheResource::Manifest;
        bool isExplicit = type & ApplicationCacheResource::Explicit;
        bool isForeign = type & ApplicationCacheResource::Foreign;
        bool isFallback = type & ApplicationCacheResource::Fallback;

        return { resource.url(), isMaster, isManifest, isFallback, isForeign, isExplicit, resource.estimatedSizeInStorage() };
    });
}

ApplicationCacheHost::CacheInfo ApplicationCacheHost::applicationCacheInfo()
{
    auto* cache = applicationCache();
    if (!cache || !cache->isComplete())
        return { { }, 0, 0, 0 };

    // FIXME: Add "Creation Time" and "Update Time" to Application Caches.
    return { cache->manifestResource()->url(), 0, 0, cache->estimatedSizeInStorage() };
}

static Ref<Event> createApplicationCacheEvent(const AtomicString& eventType, int total, int done)
{
    if (eventType == eventNames().progressEvent)
        return ProgressEvent::create(eventType, true, done, total);
    return Event::create(eventType, Event::CanBubble::No, Event::IsCancelable::No);
}

void ApplicationCacheHost::dispatchDOMEvent(const AtomicString& eventType, int total, int done)
{
    if (!m_domApplicationCache || !m_domApplicationCache->frame())
        return;

    m_domApplicationCache->dispatchEvent(createApplicationCacheEvent(eventType, total, done));
}

void ApplicationCacheHost::setCandidateApplicationCacheGroup(ApplicationCacheGroup* group)
{
    ASSERT(!m_applicationCache);
    m_candidateApplicationCacheGroup = group;
}
    
void ApplicationCacheHost::setApplicationCache(RefPtr<ApplicationCache>&& applicationCache)
{
    if (m_candidateApplicationCacheGroup) {
        ASSERT(!m_applicationCache);
        m_candidateApplicationCacheGroup = nullptr;
    }
    m_applicationCache = WTFMove(applicationCache);
}

bool ApplicationCacheHost::shouldLoadResourceFromApplicationCache(const ResourceRequest& originalRequest, ApplicationCacheResource*& resource)
{
    auto* cache = applicationCache();
    if (!cache || !cache->isComplete())
        return false;

    ResourceRequest request(originalRequest);
    if (auto* loaderFrame = m_documentLoader.frame()) {
        if (auto* document = loaderFrame->document())
            document->contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(request, ContentSecurityPolicy::InsecureRequestType::Load);
    }
    
    // If the resource is not to be fetched using the HTTP GET mechanism or equivalent, or if its URL has a different
    // <scheme> component than the application cache's manifest, then fetch the resource normally.
    if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request) || !equalIgnoringASCIICase(request.url().protocol(), cache->manifestResource()->url().protocol()))
        return false;

    // If the resource's URL is an master entry, the manifest, an explicit entry, or a fallback entry
    // in the application cache, then get the resource from the cache (instead of fetching it).
    resource = cache->resourceForURL(request.url());

    // Resources that match fallback namespaces or online whitelist entries are fetched from the network,
    // unless they are also cached.
    if (!resource && (cache->allowsAllNetworkRequests() || cache->urlMatchesFallbackNamespace(request.url()) || cache->isURLInOnlineWhitelist(request.url())))
        return false;

    // Resources that are not present in the manifest will always fail to load (at least, after the
    // cache has been primed the first time), making the testing of offline applications simpler.
    return true;
}

bool ApplicationCacheHost::getApplicationCacheFallbackResource(const ResourceRequest& request, ApplicationCacheResource*& resource, ApplicationCache* cache)
{
    if (!cache) {
        cache = applicationCache();
        if (!cache)
            return false;
    }
    if (!cache->isComplete())
        return false;
    
    // If the resource is not a HTTP/HTTPS GET, then abort
    if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request))
        return false;

    URL fallbackURL;
    if (cache->isURLInOnlineWhitelist(request.url()))
        return false;
    if (!cache->urlMatchesFallbackNamespace(request.url(), &fallbackURL))
        return false;

    resource = cache->resourceForURL(fallbackURL);
    ASSERT(resource);
    return true;
}

bool ApplicationCacheHost::scheduleLoadFallbackResourceFromApplicationCache(ResourceLoader* loader, ApplicationCache* cache)
{
    if (!loader)
        return false;

    if (!isApplicationCacheEnabled() && !isApplicationCacheBlockedForRequest(loader->request()))
        return false;

#if ENABLE(SERVICE_WORKER)
    if (loader->options().serviceWorkerRegistrationIdentifier)
        return false;
#endif

    ApplicationCacheResource* resource;
    if (!getApplicationCacheFallbackResource(loader->request(), resource, cache))
        return false;

    loader->willSwitchToSubstituteResource();
    m_documentLoader.scheduleSubstituteResourceLoad(*loader, *resource);
    return true;
}

ApplicationCacheHost::Status ApplicationCacheHost::status() const
{
    auto* cache = applicationCache();
    if (!cache)
        return UNCACHED;

    switch (cache->group()->updateStatus()) {
    case ApplicationCacheGroup::Checking:
        return CHECKING;
    case ApplicationCacheGroup::Downloading:
        return DOWNLOADING;
    case ApplicationCacheGroup::Idle:
        if (cache->group()->isObsolete())
            return OBSOLETE;
        if (cache != cache->group()->newestCache())
            return UPDATEREADY;
        return IDLE;
    }

    ASSERT_NOT_REACHED();
    return UNCACHED;
}

bool ApplicationCacheHost::update()
{
    auto* cache = applicationCache();
    if (!cache)
        return false;
    auto* frame = m_documentLoader.frame();
    if (!frame)
        return false;
    cache->group()->update(*frame, ApplicationCacheUpdateWithoutBrowsingContext);
    return true;
}

bool ApplicationCacheHost::swapCache()
{
    auto* cache = applicationCache();
    if (!cache)
        return false;

    // If the group of application caches to which cache belongs has the lifecycle status obsolete, unassociate document from cache.
    if (cache->group()->isObsolete()) {
        cache->group()->disassociateDocumentLoader(m_documentLoader);
        return true;
    }

    // If there is no newer cache, raise an InvalidStateError exception.
    auto* newestCache = cache->group()->newestCache();
    if (cache == newestCache)
        return false;
    
    ASSERT(cache->group() == newestCache->group());
    setApplicationCache(newestCache);
    InspectorInstrumentation::updateApplicationCacheStatus(m_documentLoader.frame());
    return true;
}

void ApplicationCacheHost::abort()
{
    auto* frame = m_documentLoader.frame();
    if (!frame)
        return;
    if (auto* cacheGroup = candidateApplicationCacheGroup())
        cacheGroup->abort(*frame);
    else if (auto* cache = applicationCache())
        cache->group()->abort(*frame);
}

bool ApplicationCacheHost::isApplicationCacheEnabled()
{
    return m_documentLoader.frame() && m_documentLoader.frame()->settings().offlineWebApplicationCacheEnabled() && !m_documentLoader.frame()->page()->usesEphemeralSession();
}

bool ApplicationCacheHost::isApplicationCacheBlockedForRequest(const ResourceRequest& request)
{
    auto* frame = m_documentLoader.frame();
    if (!frame)
        return false;
    if (frame->isMainFrame())
        return false;
    return !SecurityOrigin::create(request.url())->canAccessApplicationCache(frame->document()->topOrigin());
}

}  // namespace WebCore
