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

#include "ApplicationCache.h"
#include "ApplicationCacheHost.h"
#include "ApplicationCacheResource.h"
#include "ApplicationCacheResourceLoader.h"
#include "ApplicationCacheStorage.h"
#include "Chrome.h"
#include "ChromeClient.h"
#include "DOMApplicationCache.h"
#include "DocumentLoader.h"
#include "EventNames.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "FrameLoaderClient.h"
#include "HTTPHeaderNames.h"
#include "InspectorInstrumentation.h"
#include "ManifestParser.h"
#include "NavigationScheduler.h"
#include "NetworkLoadMetrics.h"
#include "Page.h"
#include "ProgressTracker.h"
#include "SecurityOrigin.h"
#include "Settings.h"
#include <wtf/CompletionHandler.h>
#include <wtf/HashMap.h>
#include <wtf/MainThread.h>

namespace WebCore {

ApplicationCacheGroup::ApplicationCacheGroup(Ref<ApplicationCacheStorage>&& storage, const URL& manifestURL)
    : m_storage(WTFMove(storage))
    , m_manifestURL(manifestURL)
    , m_origin(SecurityOrigin::create(manifestURL))
    , m_availableSpaceInQuota(ApplicationCacheStorage::unknownQuota())
{
}

ApplicationCacheGroup::~ApplicationCacheGroup()
{
    ASSERT(!m_newestCache);
    ASSERT(m_caches.isEmpty());

    stopLoading();

    m_storage->cacheGroupDestroyed(*this);
}
    
ApplicationCache* ApplicationCacheGroup::cacheForMainRequest(const ResourceRequest& request, DocumentLoader* documentLoader)
{
    if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request))
        return nullptr;

    URL url(request.url());
    url.removeFragmentIdentifier();

    auto* page = documentLoader->frame() ? documentLoader->frame()->page() : nullptr;
    if (!page || page->usesEphemeralSession())
        return nullptr;

    auto* group = page->applicationCacheStorage().cacheGroupForURL(url);
    if (!group)
        return nullptr;

    ASSERT(group->newestCache());
    ASSERT(!group->isObsolete());

    return group->newestCache();
}
    
ApplicationCache* ApplicationCacheGroup::fallbackCacheForMainRequest(const ResourceRequest& request, DocumentLoader* documentLoader)
{
    if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request))
        return nullptr;

    auto* frame = documentLoader->frame();
    if (!frame)
        return nullptr;

    auto* page = frame->page();
    if (!page)
        return nullptr;

    URL url(request.url());
    url.removeFragmentIdentifier();

    auto* group = page->applicationCacheStorage().fallbackCacheGroupForURL(url);
    if (!group)
        return nullptr;

    ASSERT(group->newestCache());
    ASSERT(!group->isObsolete());

    return group->newestCache();
}

void ApplicationCacheGroup::selectCache(Frame& frame, const URL& passedManifestURL)
{
    ASSERT(frame.document());
    ASSERT(frame.page());
    ASSERT(frame.loader().documentLoader());

    if (!frame.settings().offlineWebApplicationCacheEnabled())
        return;

    auto& documentLoader = *frame.loader().documentLoader();
    ASSERT(!documentLoader.applicationCacheHost().applicationCache());

    if (passedManifestURL.isNull()) {
        selectCacheWithoutManifestURL(frame);
        return;
    }

    // Don't access anything on disk if private browsing is enabled.
    if (frame.page()->usesEphemeralSession() || !frame.document()->securityOrigin().canAccessApplicationCache(frame.tree().top().document()->securityOrigin())) {
        postListenerTask(eventNames().checkingEvent, documentLoader);
        postListenerTask(eventNames().errorEvent, documentLoader);
        return;
    }

    URL manifestURL(passedManifestURL);
    manifestURL.removeFragmentIdentifier();

    auto* mainResourceCache = documentLoader.applicationCacheHost().mainResourceApplicationCache();
    
    if (mainResourceCache) {
        ASSERT(mainResourceCache->group());
        if (manifestURL == mainResourceCache->group()->m_manifestURL) {
            // The cache may have gotten obsoleted after we've loaded from it, but before we parsed the document and saw cache manifest.
            if (mainResourceCache->group()->isObsolete())
                return;
            mainResourceCache->group()->associateDocumentLoaderWithCache(&documentLoader, mainResourceCache);
            mainResourceCache->group()->update(frame, ApplicationCacheUpdateWithBrowsingContext);
        } else {
            // The main resource was loaded from cache, so the cache must have an entry for it. Mark it as foreign.
            URL resourceURL { documentLoader.responseURL() };
            resourceURL.removeFragmentIdentifier();

            ASSERT(mainResourceCache->resourceForURL(resourceURL));
            auto& resource = *mainResourceCache->resourceForURL(resourceURL);

            bool inStorage = resource.storageID();
            resource.addType(ApplicationCacheResource::Foreign);
            if (inStorage)
                frame.page()->applicationCacheStorage().storeUpdatedType(&resource, mainResourceCache);

            // Restart the current navigation from the top of the navigation algorithm, undoing any changes that were made
            // as part of the initial load.
            // The navigation will not result in the same resource being loaded, because "foreign" entries are never picked during navigation.
            frame.navigationScheduler().scheduleLocationChange(*frame.document(), frame.document()->securityOrigin(), documentLoader.url(), frame.loader().referrer());
        }
        return;
    }

    // The resource was loaded from the network, check if it is a HTTP/HTTPS GET.    
    auto& request = frame.loader().activeDocumentLoader()->request();

    if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request))
        return;

    // Check that the resource URL has the same scheme/host/port as the manifest URL.
    if (!protocolHostAndPortAreEqual(manifestURL, request.url()))
        return;

    auto& group = *frame.page()->applicationCacheStorage().findOrCreateCacheGroup(manifestURL);

    documentLoader.applicationCacheHost().setCandidateApplicationCacheGroup(&group);
    group.m_pendingMasterResourceLoaders.add(&documentLoader);
    group.m_downloadingPendingMasterResourceLoadersCount++;

    ASSERT(!group.m_cacheBeingUpdated || group.m_updateStatus != Idle);
    group.update(frame, ApplicationCacheUpdateWithBrowsingContext);
}

void ApplicationCacheGroup::selectCacheWithoutManifestURL(Frame& frame)
{
    if (!frame.settings().offlineWebApplicationCacheEnabled())
        return;

    ASSERT(frame.document());
    ASSERT(frame.page());
    ASSERT(frame.loader().documentLoader());
    auto& documentLoader = *frame.loader().documentLoader();
    ASSERT(!documentLoader.applicationCacheHost().applicationCache());

    // Don't access anything on disk if private browsing is enabled.
    if (frame.page()->usesEphemeralSession() || !frame.document()->securityOrigin().canAccessApplicationCache(frame.tree().top().document()->securityOrigin())) {
        postListenerTask(eventNames().checkingEvent, documentLoader);
        postListenerTask(eventNames().errorEvent, documentLoader);
        return;
    }

    if (auto* mainResourceCache = documentLoader.applicationCacheHost().mainResourceApplicationCache()) {
        ASSERT(mainResourceCache->group());
        auto& group = *mainResourceCache->group();
        group.associateDocumentLoaderWithCache(&documentLoader, mainResourceCache);
        group.update(frame, ApplicationCacheUpdateWithBrowsingContext);
    }
}

void ApplicationCacheGroup::finishedLoadingMainResource(DocumentLoader& loader)
{
    ASSERT(m_pendingMasterResourceLoaders.contains(&loader));
    ASSERT(m_completionType == None || m_pendingEntries.isEmpty());
    URL url = loader.url();
    url.removeFragmentIdentifier();

    switch (m_completionType) {
    case None:
        // The main resource finished loading before the manifest was ready. It will be handled via dispatchMainResources() later.
        return;
    case NoUpdate:
        ASSERT(!m_cacheBeingUpdated);
        associateDocumentLoaderWithCache(&loader, m_newestCache.get());
        if (auto* resource = m_newestCache->resourceForURL(url)) {
            if (!(resource->type() & ApplicationCacheResource::Master)) {
                resource->addType(ApplicationCacheResource::Master);
                ASSERT(!resource->storageID());
            }
        } else
            m_newestCache->addResource(ApplicationCacheResource::create(url, loader.response(), ApplicationCacheResource::Master, loader.mainResourceData()));
        break;
    case Failure:
        // Cache update has been a failure, so there is no reason to keep the document associated with the incomplete cache
        // (its main resource was not cached yet, so it is likely that the application changed significantly server-side).
        ASSERT(!m_cacheBeingUpdated); // Already cleared out by stopLoading().
        loader.applicationCacheHost().setApplicationCache(nullptr); // Will unset candidate, too.
        m_associatedDocumentLoaders.remove(&loader);
        postListenerTask(eventNames().errorEvent, loader);
        break;
    case Completed:
        ASSERT(m_associatedDocumentLoaders.contains(&loader));
        if (auto* resource = m_cacheBeingUpdated->resourceForURL(url)) {
            if (!(resource->type() & ApplicationCacheResource::Master)) {
                resource->addType(ApplicationCacheResource::Master);
                ASSERT(!resource->storageID());
            }
        } else
            m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, loader.response(), ApplicationCacheResource::Master, loader.mainResourceData()));
        // The "cached" event will be posted to all associated documents once update is complete.
        break;
    }

    ASSERT(m_downloadingPendingMasterResourceLoadersCount > 0);
    m_downloadingPendingMasterResourceLoadersCount--;
    checkIfLoadIsComplete();
}

void ApplicationCacheGroup::failedLoadingMainResource(DocumentLoader& loader)
{
    ASSERT(m_pendingMasterResourceLoaders.contains(&loader));
    ASSERT(m_completionType == None || m_pendingEntries.isEmpty());

    switch (m_completionType) {
    case None:
        // The main resource finished loading before the manifest was ready. It will be handled via dispatchMainResources() later.
        return;
    case NoUpdate:
        ASSERT(!m_cacheBeingUpdated);
        // The manifest didn't change, and we have a relevant cache - but the main resource download failed mid-way, so it cannot be stored to the cache,
        // and the loader does not get associated to it. If there are other main resources being downloaded for this cache group, they may still succeed.
        postListenerTask(eventNames().errorEvent, loader);
        break;
    case Failure:
        // Cache update failed, too.
        ASSERT(!m_cacheBeingUpdated); // Already cleared out by stopLoading().
        ASSERT(!loader.applicationCacheHost().applicationCache() || loader.applicationCacheHost().applicationCache()->group() == this);
        loader.applicationCacheHost().setApplicationCache(nullptr); // Will unset candidate, too.
        m_associatedDocumentLoaders.remove(&loader);
        postListenerTask(eventNames().errorEvent, loader);
        break;
    case Completed:
        // The cache manifest didn't list this main resource, and all cache entries were already updated successfully - but the main resource failed to load,
        // so it cannot be stored to the cache. If there are other main resources being downloaded for this cache group, they may still succeed.
        ASSERT(m_associatedDocumentLoaders.contains(&loader));
        ASSERT(loader.applicationCacheHost().applicationCache() == m_cacheBeingUpdated);
        ASSERT(!loader.applicationCacheHost().candidateApplicationCacheGroup());
        m_associatedDocumentLoaders.remove(&loader);
        loader.applicationCacheHost().setApplicationCache(nullptr);
        postListenerTask(eventNames().errorEvent, loader);
        break;
    }

    ASSERT(m_downloadingPendingMasterResourceLoadersCount > 0);
    m_downloadingPendingMasterResourceLoadersCount--;
    checkIfLoadIsComplete();
}

void ApplicationCacheGroup::stopLoading()
{
    if (m_manifestLoader) {
        m_manifestLoader->cancel();
        m_manifestLoader = nullptr;
    }

    if (m_entryLoader) {
        m_entryLoader->cancel();
        m_entryLoader = nullptr;
    }

    // FIXME: Resetting just a tiny part of the state in this function is confusing. Callers have to take care of a lot more.
    m_cacheBeingUpdated = nullptr;
    m_pendingEntries.clear();
}    

void ApplicationCacheGroup::disassociateDocumentLoader(DocumentLoader& loader)
{
    m_associatedDocumentLoaders.remove(&loader);
    m_pendingMasterResourceLoaders.remove(&loader);

    if (auto* host = loader.applicationCacheHostUnlessBeingDestroyed())
        host->setApplicationCache(nullptr); // Will set candidate group to null, too.

    if (!m_associatedDocumentLoaders.isEmpty() || !m_pendingMasterResourceLoaders.isEmpty())
        return;

    if (m_caches.isEmpty()) {
        // There is an initial cache attempt in progress.
        ASSERT(!m_newestCache);
        // Delete ourselves, causing the cache attempt to be stopped.
        delete this;
        return;
    }

    ASSERT(m_caches.contains(m_newestCache.get()));

    // Release our reference to the newest cache. This could cause us to be deleted.
    // Any ongoing updates will be stopped from destructor.
    m_newestCache = nullptr;
}

void ApplicationCacheGroup::cacheDestroyed(ApplicationCache& cache)
{
    if (m_caches.remove(&cache) && m_caches.isEmpty()) {
        ASSERT(m_associatedDocumentLoaders.isEmpty());
        ASSERT(m_pendingMasterResourceLoaders.isEmpty());
        delete this;
    }
}

void ApplicationCacheGroup::stopLoadingInFrame(Frame& frame)
{
    if (&frame != m_frame)
        return;

    cacheUpdateFailed();
}

void ApplicationCacheGroup::setNewestCache(Ref<ApplicationCache>&& newestCache)
{
    m_newestCache = WTFMove(newestCache);

    m_caches.add(m_newestCache.get());
    m_newestCache->setGroup(this);
}

void ApplicationCacheGroup::makeObsolete()
{
    if (isObsolete())
        return;

    m_isObsolete = true;
    m_storage->cacheGroupMadeObsolete(*this);
    ASSERT(!m_storageID);
}

void ApplicationCacheGroup::update(Frame& frame, ApplicationCacheUpdateOption updateOption)
{
    ASSERT(frame.loader().documentLoader());
    auto& documentLoader = *frame.loader().documentLoader();

    if (m_updateStatus == Checking || m_updateStatus == Downloading) {
        if (updateOption == ApplicationCacheUpdateWithBrowsingContext) {
            postListenerTask(eventNames().checkingEvent, documentLoader);
            if (m_updateStatus == Downloading)
                postListenerTask(eventNames().downloadingEvent, documentLoader);
        }
        return;
    }

    // Don't access anything on disk if private browsing is enabled.
    if (frame.page()->usesEphemeralSession() || !frame.document()->securityOrigin().canAccessApplicationCache(frame.tree().top().document()->securityOrigin())) {
        ASSERT(m_pendingMasterResourceLoaders.isEmpty());
        ASSERT(m_pendingEntries.isEmpty());
        ASSERT(!m_cacheBeingUpdated);
        postListenerTask(eventNames().checkingEvent, documentLoader);
        postListenerTask(eventNames().errorEvent, documentLoader);
        return;
    }

    ASSERT(!m_frame);
    m_frame = &frame;

    setUpdateStatus(Checking);

    postListenerTask(eventNames().checkingEvent, m_associatedDocumentLoaders);
    if (!m_newestCache) {
        ASSERT(updateOption == ApplicationCacheUpdateWithBrowsingContext);
        postListenerTask(eventNames().checkingEvent, documentLoader);
    }
    
    ASSERT(!m_manifestLoader);
    ASSERT(!m_entryLoader);
    ASSERT(!m_manifestResource);
    ASSERT(!m_currentResource);
    ASSERT(m_completionType == None);

    // FIXME: Handle defer loading

    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_manifestLoader = ApplicationCacheResourceLoader::create(ApplicationCacheResource::Type::Manifest, documentLoader.cachedResourceLoader(), WTFMove(request), [this] (auto&& resourceOrError) {
        // 'this' is only valid if returned value is not Error::Abort.
        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::AccessControl });
                this->cacheUpdateFailed();
                return;
            }
            this->didFailLoadingManifest(error);
            return;
        }

        m_manifestResource = WTFMove(resourceOrError.value());
        this->didFinishLoadingManifest();
    });
}

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)
        return;
    ASSERT(m_updateStatus == Checking || (m_updateStatus == Downloading && m_cacheBeingUpdated));

    if (m_completionType != None)
        return;

    frame.document()->addConsoleMessage(MessageSource::AppCache, MessageLevel::Debug, ASCIILiteral("Application Cache download process was aborted."));
    cacheUpdateFailed();
}

void ApplicationCacheGroup::didFinishLoadingEntry(const URL& entryURL)
{
    // FIXME: We should have NetworkLoadMetrics for ApplicationCache loads.
    NetworkLoadMetrics emptyMetrics;
    InspectorInstrumentation::didFinishLoading(m_frame, m_frame->loader().documentLoader(), m_currentResourceIdentifier, emptyMetrics, nullptr);

    ASSERT(m_pendingEntries.contains(entryURL));
    
    auto type = m_pendingEntries.take(entryURL);
    
    ASSERT(m_cacheBeingUpdated);

    // Did we received a 304?
    if (!m_currentResource) {
        if (m_newestCache) {
            ApplicationCacheResource* newestCachedResource = m_newestCache->resourceForURL(entryURL);
            if (newestCachedResource) {
                m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(entryURL, newestCachedResource->response(), type, &newestCachedResource->data(), newestCachedResource->path()));
                m_entryLoader = nullptr;
                startLoadingEntry();
                return;
            }
        }
        // The server could return 304 for an unconditional request - in this case, we handle the response as a normal error.
        m_entryLoader = nullptr;
        startLoadingEntry();
        return;
    }

    m_cacheBeingUpdated->addResource(m_currentResource.releaseNonNull());
    m_entryLoader = nullptr;

    // While downloading check to see if we have exceeded the available quota.
    // We can stop immediately if we have already previously failed
    // due to an earlier quota restriction. The client was already notified
    // of the quota being reached and decided not to increase it then.
    // FIXME: Should we break earlier and prevent redownloading on later page loads?
    if (m_originQuotaExceededPreviously && m_availableSpaceInQuota < m_cacheBeingUpdated->estimatedSizeInStorage()) {
        m_currentResource = nullptr;
        m_frame->document()->addConsoleMessage(MessageSource::AppCache, MessageLevel::Error, ASCIILiteral("Application Cache update failed, because size quota was exceeded."));
        cacheUpdateFailed();
        return;
    }
    
    // Load the next resource, if any.
    startLoadingEntry();
}

void ApplicationCacheGroup::didFailLoadingEntry(ApplicationCacheResourceLoader::Error error, const URL& entryURL)
{
    // FIXME: We should get back the error from ApplicationCacheResourceLoader level.
    ResourceError resourceError { error == ApplicationCacheResourceLoader::Error::CannotCreateResource ? ResourceError::Type::AccessControl : ResourceError::Type::General };

    InspectorInstrumentation::didFailLoading(m_frame, m_frame->loader().documentLoader(), m_currentResourceIdentifier, resourceError);

    unsigned type = m_entryLoader->type();
    URL url(entryURL);
    url.removeFragmentIdentifier();

    ASSERT(!m_currentResource || !m_pendingEntries.contains(url));
    m_currentResource = nullptr;
    m_pendingEntries.remove(url);

    if ((type & ApplicationCacheResource::Explicit) || (type & ApplicationCacheResource::Fallback)) {
        m_frame->document()->addConsoleMessage(MessageSource::AppCache, MessageLevel::Error, "Application Cache update failed, because " + url.stringCenterEllipsizedToLength() + (m_entryLoader->hasRedirection() ? " was redirected." : " could not be fetched."));
        // Note that cacheUpdateFailed() can cause the cache group to be deleted.
        cacheUpdateFailed();
        return;
    }

    if (error == ApplicationCacheResourceLoader::Error::NotFound) {
        // Skip this resource. It is dropped from the cache.
        m_pendingEntries.remove(url);
        startLoadingEntry();
        return;
    }

    // Copy the resource and its metadata from the newest application cache in cache group whose completeness flag is complete, and act
    // as if that was the fetched resource, ignoring the resource obtained from the network.
    ASSERT(m_newestCache);
    ApplicationCacheResource* newestCachedResource = m_newestCache->resourceForURL(url);
    ASSERT(newestCachedResource);
    m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, newestCachedResource->response(), type, &newestCachedResource->data(), newestCachedResource->path()));
    // Load the next resource, if any.
    startLoadingEntry();
}

void ApplicationCacheGroup::didFinishLoadingManifest()
{
    bool isUpgradeAttempt = m_newestCache;

    if (!isUpgradeAttempt && !m_manifestResource) {
        // The server returned 304 Not Modified even though we didn't send a conditional request.
        m_frame->document()->addConsoleMessage(MessageSource::AppCache, MessageLevel::Error, ASCIILiteral("Application Cache manifest could not be fetched because of an unexpected 304 Not Modified server response."));
        cacheUpdateFailed();
        return;
    }

    m_manifestLoader = nullptr;

    // Check if the manifest was not modified.
    if (isUpgradeAttempt) {
        ApplicationCacheResource* newestManifest = m_newestCache->manifestResource();
        ASSERT(newestManifest);
    
        if (!m_manifestResource || // The resource will be null if HTTP response was 304 Not Modified.
            (newestManifest->data().size() == m_manifestResource->data().size() && !memcmp(newestManifest->data().data(), m_manifestResource->data().data(), newestManifest->data().size()))) {

            m_completionType = NoUpdate;
            m_manifestResource = nullptr;
            deliverDelayedMainResources();

            return;
        }
    }
    
    Manifest manifest;
    if (!parseManifest(m_manifestURL, m_manifestResource->response().mimeType(), m_manifestResource->data().data(), m_manifestResource->data().size(), manifest)) {
        // At the time of this writing, lack of "CACHE MANIFEST" signature is the only reason for parseManifest to fail.
        m_frame->document()->addConsoleMessage(MessageSource::AppCache, MessageLevel::Error, ASCIILiteral("Application Cache manifest could not be parsed. Does it start with CACHE MANIFEST?"));
        cacheUpdateFailed();
        return;
    }

    ASSERT(!m_cacheBeingUpdated);
    m_cacheBeingUpdated = ApplicationCache::create();
    m_cacheBeingUpdated->setGroup(this);

    for (auto& loader : m_pendingMasterResourceLoaders)
        associateDocumentLoaderWithCache(loader, m_cacheBeingUpdated.get());

    // We have the manifest, now download the resources.
    setUpdateStatus(Downloading);
    
    postListenerTask(eventNames().downloadingEvent, m_associatedDocumentLoaders);

    ASSERT(m_pendingEntries.isEmpty());

    if (isUpgradeAttempt) {
        for (const auto& urlAndResource : m_newestCache->resources()) {
            unsigned type = urlAndResource.value->type();
            if (type & ApplicationCacheResource::Master)
                addEntry(urlAndResource.key, type);
        }
    }
    
    for (const auto& explicitURL : manifest.explicitURLs)
        addEntry(explicitURL, ApplicationCacheResource::Explicit);

    for (auto& fallbackURL : manifest.fallbackURLs)
        addEntry(fallbackURL.second, ApplicationCacheResource::Fallback);
    
    m_cacheBeingUpdated->setOnlineWhitelist(manifest.onlineWhitelistedURLs);
    m_cacheBeingUpdated->setFallbackURLs(manifest.fallbackURLs);
    m_cacheBeingUpdated->setAllowsAllNetworkRequests(manifest.allowAllNetworkRequests);

    m_progressTotal = m_pendingEntries.size();
    m_progressDone = 0;

    recalculateAvailableSpaceInQuota();

    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_manifestLoader->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_manifestLoader->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_manifestLoader->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_manifestLoader->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_manifestLoader->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_manifestLoader->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);
    ASSERT(m_cacheBeingUpdated);
    m_frame->page()->chrome().client().reachedMaxAppCacheSize(m_frame->page()->applicationCacheStorage().spaceNeeded(m_cacheBeingUpdated->estimatedSizeInStorage()));
    m_calledReachedMaxAppCacheSize = true;
    checkIfLoadIsComplete();
}

void ApplicationCacheGroup::didReachOriginQuota(int64_t totalSpaceNeeded)
{
    // Inform the client the origin quota has been reached, they may decide to increase the quota.
    // We expect quota to be increased synchronously while waiting for the call to return.
    m_frame->page()->chrome().client().reachedApplicationCacheOriginQuota(m_origin.get(), totalSpaceNeeded);
}

void ApplicationCacheGroup::cacheUpdateFailed()
{
    stopLoading();
    m_manifestResource = nullptr;

    // Wait for master resource loads to finish.
    m_completionType = Failure;
    deliverDelayedMainResources();
}

void ApplicationCacheGroup::recalculateAvailableSpaceInQuota()
{
    if (!m_frame->page()->applicationCacheStorage().calculateRemainingSizeForOriginExcludingCache(m_origin, m_newestCache.get(), m_availableSpaceInQuota)) {
        // Failed to determine what is left in the quota. Fallback to allowing anything.
        m_availableSpaceInQuota = ApplicationCacheStorage::noQuota();
    }
}
    
void ApplicationCacheGroup::manifestNotFound()
{
    makeObsolete();

    postListenerTask(eventNames().obsoleteEvent, m_associatedDocumentLoaders);
    postListenerTask(eventNames().errorEvent, m_pendingMasterResourceLoaders);

    stopLoading();

    ASSERT(m_pendingEntries.isEmpty());
    m_manifestResource = nullptr;

    while (!m_pendingMasterResourceLoaders.isEmpty()) {
        HashSet<DocumentLoader*>::iterator it = m_pendingMasterResourceLoaders.begin();
        
        ASSERT((*it)->applicationCacheHost().candidateApplicationCacheGroup() == this);
        ASSERT(!(*it)->applicationCacheHost().applicationCache());
        (*it)->applicationCacheHost().setCandidateApplicationCacheGroup(nullptr);
        m_pendingMasterResourceLoaders.remove(it);
    }

    m_downloadingPendingMasterResourceLoadersCount = 0;
    setUpdateStatus(Idle);    
    m_frame = nullptr;

    if (m_caches.isEmpty()) {
        ASSERT(m_associatedDocumentLoaders.isEmpty());
        ASSERT(!m_cacheBeingUpdated);
        delete this;
    }
}

void ApplicationCacheGroup::checkIfLoadIsComplete()
{
    if (m_manifestLoader || m_entryLoader || !m_pendingEntries.isEmpty() || m_downloadingPendingMasterResourceLoadersCount)
        return;

    // We're done, all resources have finished downloading (successfully or not).

    bool isUpgradeAttempt = m_newestCache;

    switch (m_completionType) {
    case None:
        ASSERT_NOT_REACHED();
        return;
    case NoUpdate:
        ASSERT(isUpgradeAttempt);
        ASSERT(!m_cacheBeingUpdated);

        // The storage could have been manually emptied by the user.
        if (!m_storageID)
            m_storage->storeNewestCache(*this);

        postListenerTask(eventNames().noupdateEvent, m_associatedDocumentLoaders);
        break;
    case Failure:
        ASSERT(!m_cacheBeingUpdated);
        postListenerTask(eventNames().errorEvent, m_associatedDocumentLoaders);
        if (m_caches.isEmpty()) {
            ASSERT(m_associatedDocumentLoaders.isEmpty());
            delete this;
            return;
        }
        break;
    case Completed: {
        // FIXME: Fetch the resource from manifest URL again, and check whether it is identical to the one used for update (in case the application was upgraded server-side in the meanwhile). (<rdar://problem/6467625>)

        ASSERT(m_cacheBeingUpdated);
        if (m_manifestResource)
            m_cacheBeingUpdated->setManifestResource(m_manifestResource.releaseNonNull());
        else {
            // We can get here as a result of retrying the Complete step, following
            // a failure of the cache storage to save the newest cache due to hitting
            // the maximum size. In such a case, m_manifestResource may be 0, as
            // the manifest was already set on the newest cache object.
            ASSERT(m_cacheBeingUpdated->manifestResource());
            ASSERT(m_storage->isMaximumSizeReached());
            ASSERT(m_calledReachedMaxAppCacheSize);
        }

        RefPtr<ApplicationCache> oldNewestCache = (m_newestCache == m_cacheBeingUpdated) ? RefPtr<ApplicationCache>() : m_newestCache;

        // If we exceeded the origin quota while downloading we can request a quota
        // increase now, before we attempt to store the cache.
        int64_t totalSpaceNeeded;
        if (!m_storage->checkOriginQuota(this, oldNewestCache.get(), m_cacheBeingUpdated.get(), totalSpaceNeeded))
            didReachOriginQuota(totalSpaceNeeded);

        ApplicationCacheStorage::FailureReason failureReason;
        setNewestCache(m_cacheBeingUpdated.releaseNonNull());
        if (m_storage->storeNewestCache(*this, oldNewestCache.get(), failureReason)) {
            // New cache stored, now remove the old cache.
            if (oldNewestCache)
                m_storage->remove(oldNewestCache.get());

            // Fire the final progress event.
            ASSERT(m_progressDone == m_progressTotal);
            postListenerTask(eventNames().progressEvent, m_progressTotal, m_progressDone, m_associatedDocumentLoaders);

            // Fire the success event.
            postListenerTask(isUpgradeAttempt ? eventNames().updatereadyEvent : eventNames().cachedEvent, m_associatedDocumentLoaders);
            // It is clear that the origin quota was not reached, so clear the flag if it was set.
            m_originQuotaExceededPreviously = false;
        } else {
            if (failureReason == ApplicationCacheStorage::OriginQuotaReached) {
                // We ran out of space for this origin. Fall down to the normal error handling
                // after recording this state.
                m_originQuotaExceededPreviously = true;
                m_frame->document()->addConsoleMessage(MessageSource::AppCache, MessageLevel::Error, ASCIILiteral("Application Cache update failed, because size quota was exceeded."));
            }

            if (failureReason == ApplicationCacheStorage::TotalQuotaReached && !m_calledReachedMaxAppCacheSize) {
                // FIXME: Should this be handled more like Origin Quotas? Does this fail properly?

                // We ran out of space. All the changes in the cache storage have
                // been rolled back. We roll back to the previous state in here,
                // as well, call the chrome client asynchronously and retry to
                // save the new cache.

                // Save a reference to the new cache.
                m_cacheBeingUpdated = WTFMove(m_newestCache);
                if (oldNewestCache)
                    setNewestCache(oldNewestCache.releaseNonNull());
                scheduleReachedMaxAppCacheSizeCallback();
                return;
            }

            // Run the "cache failure steps"
            // Fire the error events to all pending master entries, as well any other cache hosts
            // currently associated with a cache in this group.
            postListenerTask(eventNames().errorEvent, m_associatedDocumentLoaders);
            // Disassociate the pending master entries from the failed new cache. Note that
            // all other loaders in the m_associatedDocumentLoaders are still associated with
            // some other cache in this group. They are not associated with the failed new cache.

            // Need to copy loaders, because the cache group may be destroyed at the end of iteration.
            for (auto& loader : copyToVector(m_pendingMasterResourceLoaders))
                disassociateDocumentLoader(*loader); // This can delete this group.

            // Reinstate the oldNewestCache, if there was one.
            if (oldNewestCache) {
                // This will discard the failed new cache.
                setNewestCache(oldNewestCache.releaseNonNull());
            } else {
                // We must have been deleted by the last call to disassociateDocumentLoader().
                return;
            }
        }
        break;
    }
    }

    // Empty cache group's list of pending master entries.
    m_pendingMasterResourceLoaders.clear();
    m_completionType = None;
    setUpdateStatus(Idle);
    m_frame = nullptr;
    m_availableSpaceInQuota = ApplicationCacheStorage::unknownQuota();
    m_calledReachedMaxAppCacheSize = false;
}

void ApplicationCacheGroup::startLoadingEntry()
{
    ASSERT(m_cacheBeingUpdated);

    if (m_pendingEntries.isEmpty()) {
        m_completionType = Completed;
        deliverDelayedMainResources();
        return;
    }
    
    auto firstPendingEntryURL = m_pendingEntries.begin()->key;

    postListenerTask(eventNames().progressEvent, m_progressTotal, m_progressDone, m_associatedDocumentLoaders);
    m_progressDone++;

    ASSERT(!m_manifestLoader);
    ASSERT(!m_entryLoader);

    auto request = createRequest(URL { ParsedURLString, firstPendingEntryURL }, m_newestCache ? m_newestCache->resourceForURL(firstPendingEntryURL) : nullptr);

    m_currentResourceIdentifier = m_frame->page()->progress().createUniqueIdentifier();
    InspectorInstrumentation::willSendRequest(m_frame, m_currentResourceIdentifier, m_frame->loader().documentLoader(), request, ResourceResponse { });

    auto& documentLoader = *m_frame->loader().documentLoader();
    m_entryLoader = ApplicationCacheResourceLoader::create(m_pendingEntries.begin()->value, documentLoader.cachedResourceLoader(), WTFMove(request), [this] (auto&& resourceOrError) {
        if (!resourceOrError.has_value()) {
            auto error = resourceOrError.error();
            if (error == ApplicationCacheResourceLoader::Error::Abort)
                return;
            this->didFailLoadingEntry(error, m_entryLoader->resource()->url());
            return;
        }

        m_currentResource = WTFMove(resourceOrError.value());
        this->didFinishLoadingEntry(m_entryLoader->resource()->url());
    });
}

void ApplicationCacheGroup::deliverDelayedMainResources()
{
    // Need to copy loaders, because the cache group may be destroyed at the end of iteration.
    auto loaders = copyToVector(m_pendingMasterResourceLoaders);
    for (auto* loader : loaders) {
        if (loader->isLoadingMainResource())
            continue;
        if (loader->mainDocumentError().isNull())
            finishedLoadingMainResource(*loader);
        else
            failedLoadingMainResource(*loader);
    }
    if (loaders.isEmpty())
        checkIfLoadIsComplete();
}

void ApplicationCacheGroup::addEntry(const String& url, unsigned type)
{
    ASSERT(m_cacheBeingUpdated);
    ASSERT(!URL(ParsedURLString, url).hasFragmentIdentifier());

    // Don't add the URL if we already have an master resource in the cache
    // (i.e., the main resource finished loading before the manifest).
    if (auto* resource = m_cacheBeingUpdated->resourceForURL(url)) {
        ASSERT(resource->type() & ApplicationCacheResource::Master);
        ASSERT(!m_frame->loader().documentLoader()->isLoadingMainResource());
        resource->addType(type);
        return;
    }

    // Don't add the URL if it's the same as the manifest URL.
    ASSERT(m_manifestResource);
    if (m_manifestResource->url() == url) {
        m_manifestResource->addType(type);
        return;
    }

    m_pendingEntries.add(url, type).iterator->value |= type;
}

void ApplicationCacheGroup::associateDocumentLoaderWithCache(DocumentLoader* loader, ApplicationCache* cache)
{
    // If teardown started already, revive the group.
    if (!m_newestCache && !m_cacheBeingUpdated)
        m_newestCache = cache;

    ASSERT(!m_isObsolete);

    loader->applicationCacheHost().setApplicationCache(cache);

    ASSERT(!m_associatedDocumentLoaders.contains(loader));
    m_associatedDocumentLoaders.add(loader);
}

class ChromeClientCallbackTimer final : public TimerBase {
public:
    ChromeClientCallbackTimer(ApplicationCacheGroup& group)
        : m_group(group)
    {
    }

private:
    void fired() final
    {
        m_group.didReachMaxAppCacheSize();
        delete this;
    }

    // Note that there is no need to use a Ref here. The ApplicationCacheGroup instance is guaranteed
    // to be alive when the timer fires since invoking the callback is part of its normal
    // update machinery and nothing can yet cause it to get deleted.
    ApplicationCacheGroup& m_group;
};

void ApplicationCacheGroup::scheduleReachedMaxAppCacheSizeCallback()
{
    ASSERT(isMainThread());
    auto* timer = new ChromeClientCallbackTimer(*this);
    timer->startOneShot(0_s);
    // The timer will delete itself once it fires.
}

void ApplicationCacheGroup::postListenerTask(const AtomicString& eventType, int progressTotal, int progressDone, const HashSet<DocumentLoader*>& loaderSet)
{
    for (auto& loader : loaderSet)
        postListenerTask(eventType, progressTotal, progressDone, *loader);
}

void ApplicationCacheGroup::postListenerTask(const AtomicString& eventType, int progressTotal, int progressDone, DocumentLoader& loader)
{
    auto* frame = loader.frame();
    if (!frame)
        return;
    
    ASSERT(frame->loader().documentLoader() == &loader);

    RefPtr<DocumentLoader> protectedLoader(&loader);
    frame->document()->postTask([protectedLoader, &eventType, progressTotal, progressDone] (ScriptExecutionContext& context) {
        ASSERT_UNUSED(context, context.isDocument());
        auto* frame = protectedLoader->frame();
        if (!frame)
            return;

        ASSERT(frame->loader().documentLoader() == protectedLoader);
        protectedLoader->applicationCacheHost().notifyDOMApplicationCache(eventType, progressTotal, progressDone);
    });
}

void ApplicationCacheGroup::setUpdateStatus(UpdateStatus status)
{
    m_updateStatus = status;
}

void ApplicationCacheGroup::clearStorageID()
{
    m_storageID = 0;
    for (auto& cache : m_caches)
        cache->clearStorageID();
}

}
