/*
 * 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 "CustomHeaderFields.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);
}

ApplicationCacheGroup* ApplicationCacheHost::candidateApplicationCacheGroup() const
{
    return m_candidateApplicationCacheGroup.get();
}

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.get();
    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 AtomString& 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 AtomString& 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 AtomString& 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 = makeWeakPtr(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;
    
    auto* group = cache->group();
    if (!group)
        return false;

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

    // If there is no newer cache, raise an InvalidStateError exception.
    auto* newestCache = group->newestCache();
    if (!newestCache || cache == newestCache)
        return false;
    
    ASSERT(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
