18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
2e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke * Copyright (C) 2008, 2009, 2010 Apple Inc. All Rights Reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ApplicationCacheGroup.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if ENABLE(OFFLINE_WEB_APPLICATIONS)
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ApplicationCache.h"
320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#include "ApplicationCacheHost.h"
338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ApplicationCacheResource.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ApplicationCacheStorage.h"
35d0825bca7fe65beaee391d30da42e937db621564Steve Block#include "Chrome.h"
36c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu#include "ChromeClient.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "DocumentLoader.h"
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "DOMApplicationCache.h"
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "DOMWindow.h"
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Frame.h"
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FrameLoader.h"
4268513a70bcd92384395513322f1b801e7bf9c729Steve Block#include "FrameLoaderClient.h"
4365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#include "InspectorInstrumentation.h"
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "MainResourceLoader.h"
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ManifestParser.h"
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Page.h"
47db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block#include "SecurityOrigin.h"
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Settings.h"
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/HashMap.h>
50782c335ccf53a3ffc83c9bf7d30c9f5ead1899a8Steve Block#include <wtf/UnusedParam.h>
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
52e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#if ENABLE(INSPECTOR)
53e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#include "ProgressTracker.h"
54e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#endif
55e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectApplicationCacheGroup::ApplicationCacheGroup(const KURL& manifestURL, bool isCopy)
598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    : m_manifestURL(manifestURL)
60db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    , m_origin(SecurityOrigin::create(manifestURL))
61635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    , m_updateStatus(Idle)
625f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    , m_downloadingPendingMasterResourceLoadersCount(0)
63e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    , m_progressTotal(0)
64e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    , m_progressDone(0)
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_frame(0)
668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_storageID(0)
67635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    , m_isObsolete(false)
68635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    , m_completionType(None)
698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_isCopy(isCopy)
70c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    , m_calledReachedMaxAppCacheSize(false)
71db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    , m_loadedSize(0)
72db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    , m_availableSpaceInQuota(ApplicationCacheStorage::unknownQuota())
73db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    , m_originQuotaReached(false)
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectApplicationCacheGroup::~ApplicationCacheGroup()
788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_isCopy) {
808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(m_newestCache);
818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(m_caches.size() == 1);
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(m_caches.contains(m_newestCache.get()));
838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(!m_cacheBeingUpdated);
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(m_associatedDocumentLoaders.isEmpty());
85635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(m_pendingMasterResourceLoaders.isEmpty());
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(m_newestCache->group() == this);
878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!m_newestCache);
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(m_caches.isEmpty());
938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    stopLoading();
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    cacheStorage().cacheGroupDestroyed(this);
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
99635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectApplicationCache* ApplicationCacheGroup::cacheForMainRequest(const ResourceRequest& request, DocumentLoader*)
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request))
1028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    KURL url(request.url());
1050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (url.hasFragmentIdentifier())
1060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        url.removeFragmentIdentifier();
1070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (ApplicationCacheGroup* group = cacheStorage().cacheGroupForURL(url)) {
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(group->newestCache());
110635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(!group->isObsolete());
1118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return group->newestCache();
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
1168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
118635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source ProjectApplicationCache* ApplicationCacheGroup::fallbackCacheForMainRequest(const ResourceRequest& request, DocumentLoader*)
119635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
120635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request))
121635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return 0;
122635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    KURL url(request.url());
1240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (url.hasFragmentIdentifier())
1250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        url.removeFragmentIdentifier();
1260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (ApplicationCacheGroup* group = cacheStorage().fallbackCacheGroupForURL(url)) {
128635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(group->newestCache());
129635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(!group->isObsolete());
130635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
131635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return group->newestCache();
132635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
133635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
134635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    return 0;
135635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
136635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1370bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid ApplicationCacheGroup::selectCache(Frame* frame, const KURL& passedManifestURL)
1388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(frame && frame->page());
1408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!frame->settings()->offlineWebApplicationCacheEnabled())
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    DocumentLoader* documentLoader = frame->loader()->documentLoader();
1450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(!documentLoader->applicationCacheHost()->applicationCache());
1468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (passedManifestURL.isNull()) {
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        selectCacheWithoutManifestURL(frame);
1498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1520bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    KURL manifestURL(passedManifestURL);
1530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (manifestURL.hasFragmentIdentifier())
1540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        manifestURL.removeFragmentIdentifier();
1550bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ApplicationCache* mainResourceCache = documentLoader->applicationCacheHost()->mainResourceApplicationCache();
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (mainResourceCache) {
1598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (manifestURL == mainResourceCache->group()->m_manifestURL) {
160a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            // The cache may have gotten obsoleted after we've loaded from it, but before we parsed the document and saw cache manifest.
161a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (mainResourceCache->group()->isObsolete())
162a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                return;
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            mainResourceCache->group()->associateDocumentLoaderWithCache(documentLoader, mainResourceCache);
164635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            mainResourceCache->group()->update(frame, ApplicationCacheUpdateWithBrowsingContext);
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else {
166635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            // The main resource was loaded from cache, so the cache must have an entry for it. Mark it as foreign.
167a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            KURL resourceURL(documentLoader->responseURL());
168a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (resourceURL.hasFragmentIdentifier())
169a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                resourceURL.removeFragmentIdentifier();
170a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            ApplicationCacheResource* resource = mainResourceCache->resourceForURL(resourceURL);
171635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            bool inStorage = resource->storageID();
172635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            resource->addType(ApplicationCacheResource::Foreign);
173635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            if (inStorage)
174635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                cacheStorage().storeUpdatedType(resource, mainResourceCache);
175635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
176635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            // Restart the current navigation from the top of the navigation algorithm, undoing any changes that were made
177635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            // as part of the initial load.
178635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            // The navigation will not result in the same resource being loaded, because "foreign" entries are never picked during navigation.
179f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            frame->navigationScheduler()->scheduleLocationChange(frame->document()->securityOrigin(), documentLoader->url(), frame->loader()->referrer(), true);
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // The resource was loaded from the network, check if it is a HTTP/HTTPS GET.
1868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const ResourceRequest& request = frame->loader()->activeDocumentLoader()->request();
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
188635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!ApplicationCache::requestIsHTTPOrHTTPSGet(request))
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Check that the resource URL has the same scheme/host/port as the manifest URL.
192635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!protocolHostAndPortAreEqual(manifestURL, request.url()))
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
1948f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
1958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Don't change anything on disk if private browsing is enabled.
1968f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!frame->settings() || frame->settings()->privateBrowsingEnabled()) {
1970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        postListenerTask(ApplicationCacheHost::CHECKING_EVENT, documentLoader);
1980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        postListenerTask(ApplicationCacheHost::ERROR_EVENT, documentLoader);
1998f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return;
2008f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
2018f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
2028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ApplicationCacheGroup* group = cacheStorage().findOrCreateCacheGroup(manifestURL);
203635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
2040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    documentLoader->applicationCacheHost()->setCandidateApplicationCacheGroup(group);
205635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    group->m_pendingMasterResourceLoaders.add(documentLoader);
2065f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    group->m_downloadingPendingMasterResourceLoadersCount++;
207635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
208635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(!group->m_cacheBeingUpdated || group->m_updateStatus != Idle);
209635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    group->update(frame, ApplicationCacheUpdateWithBrowsingContext);
2108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ApplicationCacheGroup::selectCacheWithoutManifestURL(Frame* frame)
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!frame->settings()->offlineWebApplicationCacheEnabled())
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    DocumentLoader* documentLoader = frame->loader()->documentLoader();
2180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(!documentLoader->applicationCacheHost()->applicationCache());
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ApplicationCache* mainResourceCache = documentLoader->applicationCacheHost()->mainResourceApplicationCache();
2218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
222635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (mainResourceCache) {
2238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        mainResourceCache->group()->associateDocumentLoaderWithCache(documentLoader, mainResourceCache);
224635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        mainResourceCache->group()->update(frame, ApplicationCacheUpdateWithBrowsingContext);
2258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ApplicationCacheGroup::finishedLoadingMainResource(DocumentLoader* loader)
2298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
230635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(m_pendingMasterResourceLoaders.contains(loader));
231635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(m_completionType == None || m_pendingEntries.isEmpty());
2320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    KURL url = loader->url();
2330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (url.hasFragmentIdentifier())
2340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        url.removeFragmentIdentifier();
2358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
236635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    switch (m_completionType) {
237635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    case None:
238635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // The main resource finished loading before the manifest was ready. It will be handled via dispatchMainResources() later.
239635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return;
240635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    case NoUpdate:
241635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(!m_cacheBeingUpdated);
242635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        associateDocumentLoaderWithCache(loader, m_newestCache.get());
243635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
244635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (ApplicationCacheResource* resource = m_newestCache->resourceForURL(url)) {
2458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            if (!(resource->type() & ApplicationCacheResource::Master)) {
2468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                resource->addType(ApplicationCacheResource::Master);
247635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                ASSERT(!resource->storageID());
248635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            }
249635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        } else
2508f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            m_newestCache->addResource(ApplicationCacheResource::create(url, loader->response(), ApplicationCacheResource::Master, loader->mainResourceData()));
251635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
252635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        break;
253635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    case Failure:
254635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Cache update has been a failure, so there is no reason to keep the document associated with the incomplete cache
255635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // (its main resource was not cached yet, so it is likely that the application changed significantly server-side).
256635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(!m_cacheBeingUpdated); // Already cleared out by stopLoading().
2570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        loader->applicationCacheHost()->setApplicationCache(0); // Will unset candidate, too.
258635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        m_associatedDocumentLoaders.remove(loader);
2590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        postListenerTask(ApplicationCacheHost::ERROR_EVENT, loader);
260635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        break;
261635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    case Completed:
262635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(m_associatedDocumentLoaders.contains(loader));
263635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
264635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (ApplicationCacheResource* resource = m_cacheBeingUpdated->resourceForURL(url)) {
2658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            if (!(resource->type() & ApplicationCacheResource::Master)) {
2668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                resource->addType(ApplicationCacheResource::Master);
267635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project                ASSERT(!resource->storageID());
268635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            }
269635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        } else
2708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, loader->response(), ApplicationCacheResource::Master, loader->mainResourceData()));
271635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // The "cached" event will be posted to all associated documents once update is complete.
272635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        break;
273635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
2748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2755f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    m_downloadingPendingMasterResourceLoadersCount--;
2768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    checkIfLoadIsComplete();
2778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ApplicationCacheGroup::failedLoadingMainResource(DocumentLoader* loader)
2808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
281635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(m_pendingMasterResourceLoaders.contains(loader));
282635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(m_completionType == None || m_pendingEntries.isEmpty());
2838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
284635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    switch (m_completionType) {
285635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    case None:
286635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // The main resource finished loading before the manifest was ready. It will be handled via dispatchMainResources() later.
287635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return;
288635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    case NoUpdate:
289635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(!m_cacheBeingUpdated);
290635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
291635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // 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,
292635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // 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.
2930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        postListenerTask(ApplicationCacheHost::ERROR_EVENT, loader);
294635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
295635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        break;
296635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    case Failure:
297635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Cache update failed, too.
298635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(!m_cacheBeingUpdated); // Already cleared out by stopLoading().
2990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        ASSERT(!loader->applicationCacheHost()->applicationCache() || loader->applicationCacheHost()->applicationCache() == m_cacheBeingUpdated);
300635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
3010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        loader->applicationCacheHost()->setApplicationCache(0); // Will unset candidate, too.
302635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        m_associatedDocumentLoaders.remove(loader);
3030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        postListenerTask(ApplicationCacheHost::ERROR_EVENT, loader);
304635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        break;
305635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    case Completed:
306635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // The cache manifest didn't list this main resource, and all cache entries were already updated successfully - but the main resource failed to load,
307635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // so it cannot be stored to the cache. If there are other main resources being downloaded for this cache group, they may still succeed.
308635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(m_associatedDocumentLoaders.contains(loader));
3090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        ASSERT(loader->applicationCacheHost()->applicationCache() == m_cacheBeingUpdated);
3100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        ASSERT(!loader->applicationCacheHost()->candidateApplicationCacheGroup());
311635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        m_associatedDocumentLoaders.remove(loader);
3120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        loader->applicationCacheHost()->setApplicationCache(0);
313635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
3140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        postListenerTask(ApplicationCacheHost::ERROR_EVENT, loader);
315635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
316635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        break;
317635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
318635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
3195f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    m_downloadingPendingMasterResourceLoadersCount--;
320635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    checkIfLoadIsComplete();
3218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ApplicationCacheGroup::stopLoading()
324635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
3258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_manifestHandle) {
3268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(!m_currentHandle);
3278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_manifestHandle->setClient(0);
3298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_manifestHandle->cancel();
3308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_manifestHandle = 0;
3318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_currentHandle) {
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(!m_manifestHandle);
3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(m_cacheBeingUpdated);
3368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_currentHandle->setClient(0);
3388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_currentHandle->cancel();
3398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_currentHandle = 0;
3408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_cacheBeingUpdated = 0;
343635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_pendingEntries.clear();
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
346635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid ApplicationCacheGroup::disassociateDocumentLoader(DocumentLoader* loader)
3478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    HashSet<DocumentLoader*>::iterator it = m_associatedDocumentLoaders.find(loader);
349635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (it != m_associatedDocumentLoaders.end())
3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_associatedDocumentLoaders.remove(it);
351635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
352635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_pendingMasterResourceLoaders.remove(loader);
353635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
3540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    loader->applicationCacheHost()->setApplicationCache(0); // Will set candidate to 0, too.
355635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
356635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!m_associatedDocumentLoaders.isEmpty() || !m_pendingMasterResourceLoaders.isEmpty())
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
358635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
359635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (m_caches.isEmpty()) {
360635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // There is an initial cache attempt in progress.
361635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(!m_newestCache);
362635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Delete ourselves, causing the cache attempt to be stopped.
363635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        delete this;
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
366635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
367635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(m_caches.contains(m_newestCache.get()));
368635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
369635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Release our reference to the newest cache. This could cause us to be deleted.
370635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Any ongoing updates will be stopped from destructor.
371635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_newestCache.release();
372635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
3738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ApplicationCacheGroup::cacheDestroyed(ApplicationCache* cache)
3758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
376635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!m_caches.contains(cache))
377635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return;
3788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_caches.remove(cache);
3808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
381635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (m_caches.isEmpty()) {
382635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(m_associatedDocumentLoaders.isEmpty());
383635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(m_pendingMasterResourceLoaders.isEmpty());
3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        delete this;
385635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
3868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
388a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid ApplicationCacheGroup::stopLoadingInFrame(Frame* frame)
389a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
390a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (frame != m_frame)
391a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
392a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
393a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    stopLoading();
394a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
395a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ApplicationCacheGroup::setNewestCache(PassRefPtr<ApplicationCache> newestCache)
397635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
398635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_newestCache = newestCache;
399635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_caches.add(m_newestCache.get());
4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_newestCache->setGroup(this);
40265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    InspectorInstrumentation::updateApplicationCacheStatus(m_frame);
4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
405635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid ApplicationCacheGroup::makeObsolete()
4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
407635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (isObsolete())
408635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return;
409635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
410635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_isObsolete = true;
411635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    cacheStorage().cacheGroupMadeObsolete(this);
412635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(!m_storageID);
41365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    InspectorInstrumentation::updateApplicationCacheStatus(m_frame);
414635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
415635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
416635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid ApplicationCacheGroup::update(Frame* frame, ApplicationCacheUpdateOption updateOption)
417635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
418635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (m_updateStatus == Checking || m_updateStatus == Downloading) {
419635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (updateOption == ApplicationCacheUpdateWithBrowsingContext) {
4200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            postListenerTask(ApplicationCacheHost::CHECKING_EVENT, frame->loader()->documentLoader());
421635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            if (m_updateStatus == Downloading)
4220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                postListenerTask(ApplicationCacheHost::DOWNLOADING_EVENT, frame->loader()->documentLoader());
423635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
425635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
4268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4278f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Don't change anything on disk if private browsing is enabled.
4288f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!frame->settings() || frame->settings()->privateBrowsingEnabled()) {
4298f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        ASSERT(m_pendingMasterResourceLoaders.isEmpty());
4308f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        ASSERT(m_pendingEntries.isEmpty());
4318f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        ASSERT(!m_cacheBeingUpdated);
4320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        postListenerTask(ApplicationCacheHost::CHECKING_EVENT, frame->loader()->documentLoader());
4330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        postListenerTask(ApplicationCacheHost::NOUPDATE_EVENT, frame->loader()->documentLoader());
4348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return;
4358f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
4368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!m_frame);
4388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_frame = frame;
4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
440e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    setUpdateStatus(Checking);
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    postListenerTask(ApplicationCacheHost::CHECKING_EVENT, m_associatedDocumentLoaders);
443635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!m_newestCache) {
444635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(updateOption == ApplicationCacheUpdateWithBrowsingContext);
4450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        postListenerTask(ApplicationCacheHost::CHECKING_EVENT, frame->loader()->documentLoader());
446635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!m_manifestHandle);
4498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!m_manifestResource);
450635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(m_completionType == None);
451635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
4528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // FIXME: Handle defer loading
4538f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_manifestHandle = createResourceHandle(m_manifestURL, m_newestCache ? m_newestCache->manifestResource() : 0);
4548f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian}
4558f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4568f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng QianPassRefPtr<ResourceHandle> ApplicationCacheGroup::createResourceHandle(const KURL& url, ApplicationCacheResource* newestCachedResource)
4578f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian{
4588f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ResourceRequest request(url);
4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_frame->loader()->applyUserAgent(request);
4608f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    request.setHTTPHeaderField("Cache-Control", "max-age=0");
4618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
4628f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (newestCachedResource) {
4638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        const String& lastModified = newestCachedResource->response().httpHeaderField("Last-Modified");
4648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        const String& eTag = newestCachedResource->response().httpHeaderField("ETag");
4658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (!lastModified.isEmpty() || !eTag.isEmpty()) {
4668f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            if (!lastModified.isEmpty())
4678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                request.setHTTPHeaderField("If-Modified-Since", lastModified);
4688f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            if (!eTag.isEmpty())
4698f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                request.setHTTPHeaderField("If-None-Match", eTag);
4708f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        }
4718f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
472e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
47368513a70bcd92384395513322f1b801e7bf9c729Steve Block    RefPtr<ResourceHandle> handle = ResourceHandle::create(m_frame->loader()->networkingContext(), request, this, false, true);
474e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#if ENABLE(INSPECTOR)
475e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    // Because willSendRequest only gets called during redirects, we initialize
476e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    // the identifier and the first willSendRequest here.
477e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    m_currentResourceIdentifier = m_frame->page()->progress()->createUniqueIdentifier();
47865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    ResourceResponse redirectResponse = ResourceResponse();
4792bde8e466a4451c7319e3a072d118917957d6554Steve Block    InspectorInstrumentation::willSendRequest(m_frame, m_currentResourceIdentifier, m_frame->loader()->documentLoader(), request, redirectResponse);
480e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#endif
481e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    return handle;
482e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke}
483e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
4848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ApplicationCacheGroup::didReceiveResponse(ResourceHandle* handle, const ResourceResponse& response)
4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
486e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#if ENABLE(INSPECTOR)
48765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    DocumentLoader* loader = (handle == m_manifestHandle) ? 0 : m_frame->loader()->documentLoader();
48865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    InspectorInstrumentationCookie cookie = InspectorInstrumentation::willReceiveResourceResponse(m_frame, m_currentResourceIdentifier, response);
48965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    InspectorInstrumentation::didReceiveResourceResponse(cookie, m_currentResourceIdentifier, loader, response);
490e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#endif
491e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (handle == m_manifestHandle) {
4938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        didReceiveManifestResponse(response);
4948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(handle == m_currentHandle);
498635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
499967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    KURL url(handle->firstRequest().url());
5000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (url.hasFragmentIdentifier())
5010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        url.removeFragmentIdentifier();
5028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!m_currentResource);
5048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(m_pendingEntries.contains(url));
5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    unsigned type = m_pendingEntries.get(url);
5078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5088f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // If this is an initial cache attempt, we should not get master resources delivered here.
5098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_newestCache)
5108f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        ASSERT(!(type & ApplicationCacheResource::Master));
5118f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
5128f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (m_newestCache && response.httpStatusCode() == 304) { // Not modified.
5130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        ApplicationCacheResource* newestCachedResource = m_newestCache->resourceForURL(url);
5148f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (newestCachedResource) {
5152bde8e466a4451c7319e3a072d118917957d6554Steve Block            m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, newestCachedResource->response(), type, newestCachedResource->data(), newestCachedResource->path()));
516967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch            m_pendingEntries.remove(m_currentHandle->firstRequest().url());
5178f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            m_currentHandle->cancel();
5188f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            m_currentHandle = 0;
5198f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            // Load the next resource, if any.
5208f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            startLoadingEntry();
5218f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            return;
5228f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        }
5238f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // The server could return 304 for an unconditional request - in this case, we handle the response as a normal error.
5248f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    }
525635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
526967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    if (response.httpStatusCode() / 100 != 2 || response.url() != m_currentHandle->firstRequest().url()) {
527635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if ((type & ApplicationCacheResource::Explicit) || (type & ApplicationCacheResource::Fallback)) {
528635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            // Note that cacheUpdateFailed() can cause the cache group to be deleted.
529635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            cacheUpdateFailed();
530635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        } else if (response.httpStatusCode() == 404 || response.httpStatusCode() == 410) {
531635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            // Skip this resource. It is dropped from the cache.
532635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            m_currentHandle->cancel();
533635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            m_currentHandle = 0;
5340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            m_pendingEntries.remove(url);
535635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            // Load the next resource, if any.
536635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            startLoadingEntry();
537635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        } else {
538635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            // Copy the resource and its metadata from the newest application cache in cache group whose completeness flag is complete, and act
539635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            // as if that was the fetched resource, ignoring the resource obtained from the network.
540635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            ASSERT(m_newestCache);
541967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch            ApplicationCacheResource* newestCachedResource = m_newestCache->resourceForURL(handle->firstRequest().url());
5428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            ASSERT(newestCachedResource);
5432bde8e466a4451c7319e3a072d118917957d6554Steve Block            m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, newestCachedResource->response(), type, newestCachedResource->data(), newestCachedResource->path()));
544967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch            m_pendingEntries.remove(m_currentHandle->firstRequest().url());
545635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            m_currentHandle->cancel();
546635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            m_currentHandle = 0;
5478f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            // Load the next resource, if any.
548635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            startLoadingEntry();
549635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        }
550635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return;
551635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
5528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_currentResource = ApplicationCacheResource::create(url, response, type);
5548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5562daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid ApplicationCacheGroup::didReceiveData(ResourceHandle* handle, const char* data, int length, int encodedDataLength)
5578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5582daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    UNUSED_PARAM(encodedDataLength);
5592bde8e466a4451c7319e3a072d118917957d6554Steve Block
560e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#if ENABLE(INSPECTOR)
5612bde8e466a4451c7319e3a072d118917957d6554Steve Block    InspectorInstrumentation::didReceiveContentLength(m_frame, m_currentResourceIdentifier, length, 0);
562e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#endif
563e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
5648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (handle == m_manifestHandle) {
5658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        didReceiveManifestData(data, length);
5668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
5678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(handle == m_currentHandle);
5708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(m_currentResource);
5728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_currentResource->data()->append(data, length);
573db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
574db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    m_loadedSize += length;
5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
57768513a70bcd92384395513322f1b801e7bf9c729Steve Blockvoid ApplicationCacheGroup::didFinishLoading(ResourceHandle* handle, double finishTime)
5788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
579e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#if ENABLE(INSPECTOR)
58065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    InspectorInstrumentation::didFinishLoading(m_frame, m_currentResourceIdentifier, finishTime);
581e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#endif
582e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (handle == m_manifestHandle) {
5848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        didFinishLoadingManifest();
5858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
5868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
587db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
588db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    // After finishing the loading of any resource, we check if it will
589db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    // fit in our last known quota limit.
590db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    if (m_availableSpaceInQuota == ApplicationCacheStorage::unknownQuota()) {
591db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        // Failed to determine what is left in the quota. Fallback to allowing anything.
592db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        if (!cacheStorage().remainingSizeForOriginExcludingCache(m_origin.get(), m_newestCache.get(), m_availableSpaceInQuota))
593db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            m_availableSpaceInQuota = ApplicationCacheStorage::noQuota();
594db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    }
595db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
596db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    // Check each resource, as it loads, to see if it would fit in our
597db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    // idea of the available quota space.
598db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    if (m_availableSpaceInQuota < m_loadedSize) {
599db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        m_currentResource = 0;
600db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        cacheUpdateFailedDueToOriginQuota();
601db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        return;
602db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    }
603db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
6048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(m_currentHandle == handle);
605967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    ASSERT(m_pendingEntries.contains(handle->firstRequest().url()));
6068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
607967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    m_pendingEntries.remove(handle->firstRequest().url());
6088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(m_cacheBeingUpdated);
6108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_cacheBeingUpdated->addResource(m_currentResource.release());
6128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_currentHandle = 0;
6138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
614635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Load the next resource, if any.
615635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    startLoadingEntry();
6168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
618e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkevoid ApplicationCacheGroup::didFail(ResourceHandle* handle, const ResourceError& error)
6198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
620e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#if ENABLE(INSPECTOR)
62165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    InspectorInstrumentation::didFailLoading(m_frame, m_currentResourceIdentifier, error);
622e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke#endif
623e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
6248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (handle == m_manifestHandle) {
625635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        cacheUpdateFailed();
6268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
6278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
628635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
629967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    unsigned type = m_currentResource ? m_currentResource->type() : m_pendingEntries.get(handle->firstRequest().url());
630967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    KURL url(handle->firstRequest().url());
6310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (url.hasFragmentIdentifier())
6320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        url.removeFragmentIdentifier();
633635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
6348f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    ASSERT(!m_currentResource || !m_pendingEntries.contains(url));
635635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_currentResource = 0;
6368f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    m_pendingEntries.remove(url);
637635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
638635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if ((type & ApplicationCacheResource::Explicit) || (type & ApplicationCacheResource::Fallback)) {
639635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Note that cacheUpdateFailed() can cause the cache group to be deleted.
640635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        cacheUpdateFailed();
641635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    } else {
642635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Copy the resource and its metadata from the newest application cache in cache group whose completeness flag is complete, and act
643635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // as if that was the fetched resource, ignoring the resource obtained from the network.
644635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(m_newestCache);
6458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        ApplicationCacheResource* newestCachedResource = m_newestCache->resourceForURL(url);
6468f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        ASSERT(newestCachedResource);
6472bde8e466a4451c7319e3a072d118917957d6554Steve Block        m_cacheBeingUpdated->addResource(ApplicationCacheResource::create(url, newestCachedResource->response(), type, newestCachedResource->data(), newestCachedResource->path()));
648635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // Load the next resource, if any.
649635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        startLoadingEntry();
650635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
6518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ApplicationCacheGroup::didReceiveManifestResponse(const ResourceResponse& response)
6548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
655635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(!m_manifestResource);
656635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(m_manifestHandle);
6578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
658635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (response.httpStatusCode() == 404 || response.httpStatusCode() == 410) {
659635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        manifestNotFound();
6608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
6618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
662635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
6638f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (response.httpStatusCode() == 304)
6648f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        return;
6658f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
666967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    if (response.httpStatusCode() / 100 != 2 || response.url() != m_manifestHandle->firstRequest().url() || !equalIgnoringCase(response.mimeType(), "text/cache-manifest")) {
667635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        cacheUpdateFailed();
668635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return;
669635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
670635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
671967717af5423377c967781471ee106e2bb4e11c8Ben Murdoch    m_manifestResource = ApplicationCacheResource::create(m_manifestHandle->firstRequest().url(), response, ApplicationCacheResource::Manifest);
6728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ApplicationCacheGroup::didReceiveManifestData(const char* data, int length)
6758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6768f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (m_manifestResource)
6778f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        m_manifestResource->data()->append(data, length);
6788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ApplicationCacheGroup::didFinishLoadingManifest()
6818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6828f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    bool isUpgradeAttempt = m_newestCache;
6838f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
6848f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    if (!isUpgradeAttempt && !m_manifestResource) {
6858f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // The server returned 304 Not Modified even though we didn't send a conditional request.
686635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        cacheUpdateFailed();
6878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
6888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
6898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_manifestHandle = 0;
6918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6928f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Check if the manifest was not modified.
6938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isUpgradeAttempt) {
6948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ApplicationCacheResource* newestManifest = m_newestCache->manifestResource();
6958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(newestManifest);
6968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6978f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (!m_manifestResource || // The resource will be null if HTTP response was 304 Not Modified.
698643ca7872b450ea4efacab6188849e5aac2ba161Steve Block            (newestManifest->data()->size() == m_manifestResource->data()->size() && !memcmp(newestManifest->data()->data(), m_manifestResource->data()->data(), newestManifest->data()->size()))) {
699635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
700635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            m_completionType = NoUpdate;
7018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_manifestResource = 0;
702635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            deliverDelayedMainResources();
703635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
7048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return;
7058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
7068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
7078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Manifest manifest;
7098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!parseManifest(m_manifestURL, m_manifestResource->data()->data(), m_manifestResource->data()->size(), manifest)) {
710635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        cacheUpdateFailed();
7118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
7128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
713635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
714635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(!m_cacheBeingUpdated);
715635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_cacheBeingUpdated = ApplicationCache::create();
716635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_cacheBeingUpdated->setGroup(this);
717635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
718635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    HashSet<DocumentLoader*>::const_iterator masterEnd = m_pendingMasterResourceLoaders.end();
719635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    for (HashSet<DocumentLoader*>::const_iterator iter = m_pendingMasterResourceLoaders.begin(); iter != masterEnd; ++iter)
720635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        associateDocumentLoaderWithCache(*iter, m_cacheBeingUpdated.get());
721635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
7228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // We have the manifest, now download the resources.
723e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    setUpdateStatus(Downloading);
7248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    postListenerTask(ApplicationCacheHost::DOWNLOADING_EVENT, m_associatedDocumentLoaders);
726635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
727635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(m_pendingEntries.isEmpty());
7288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isUpgradeAttempt) {
7308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ApplicationCache::ResourceMap::const_iterator end = m_newestCache->end();
7318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        for (ApplicationCache::ResourceMap::const_iterator it = m_newestCache->begin(); it != end; ++it) {
7328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            unsigned type = it->second->type();
7330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            if (type & ApplicationCacheResource::Master)
7348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                addEntry(it->first, type);
7358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
7368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
7378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    HashSet<String>::const_iterator end = manifest.explicitURLs.end();
7398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (HashSet<String>::const_iterator it = manifest.explicitURLs.begin(); it != end; ++it)
7408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        addEntry(*it, ApplicationCacheResource::Explicit);
741635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
742635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    size_t fallbackCount = manifest.fallbackURLs.size();
743635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    for (size_t i = 0; i  < fallbackCount; ++i)
744635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        addEntry(manifest.fallbackURLs[i].second, ApplicationCacheResource::Fallback);
7458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_cacheBeingUpdated->setOnlineWhitelist(manifest.onlineWhitelistedURLs);
747635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_cacheBeingUpdated->setFallbackURLs(manifest.fallbackURLs);
748231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    m_cacheBeingUpdated->setAllowsAllNetworkRequests(manifest.allowAllNetworkRequests);
749e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
750e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    m_progressTotal = m_pendingEntries.size();
751e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    m_progressDone = 0;
752e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
7538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    startLoadingEntry();
7548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
7558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
756c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescuvoid ApplicationCacheGroup::didReachMaxAppCacheSize()
757c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu{
758c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    ASSERT(m_frame);
759c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    ASSERT(m_cacheBeingUpdated);
760c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    m_frame->page()->chrome()->client()->reachedMaxAppCacheSize(cacheStorage().spaceNeeded(m_cacheBeingUpdated->estimatedSizeInStorage()));
761c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    m_calledReachedMaxAppCacheSize = true;
762c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    checkIfLoadIsComplete();
763c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu}
764c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu
765db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockvoid ApplicationCacheGroup::didReachOriginQuota(PassRefPtr<Frame> frame)
766db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block{
767db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    // Inform the client the origin quota has been reached,
768db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    // they may decide to increase the quota.
769db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    frame->page()->chrome()->client()->reachedApplicationCacheOriginQuota(m_origin.get());
770db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block}
771db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
7728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ApplicationCacheGroup::cacheUpdateFailed()
7738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    stopLoading();
775635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_manifestResource = 0;
7768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
777635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Wait for master resource loads to finish.
778635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_completionType = Failure;
779635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    deliverDelayedMainResources();
780635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
781db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
782db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockvoid ApplicationCacheGroup::cacheUpdateFailedDueToOriginQuota()
783db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block{
784db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    if (!m_originQuotaReached) {
785db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        m_originQuotaReached = true;
786db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        scheduleReachedOriginQuotaCallback();
787db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    }
788db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
789db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    cacheUpdateFailed();
790db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block}
791635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
792635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid ApplicationCacheGroup::manifestNotFound()
793635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
794635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    makeObsolete();
795635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
7960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    postListenerTask(ApplicationCacheHost::OBSOLETE_EVENT, m_associatedDocumentLoaders);
7970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    postListenerTask(ApplicationCacheHost::ERROR_EVENT, m_pendingMasterResourceLoaders);
798635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
799635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    stopLoading();
800635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
801635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(m_pendingEntries.isEmpty());
8028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_manifestResource = 0;
8038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
804635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    while (!m_pendingMasterResourceLoaders.isEmpty()) {
805635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        HashSet<DocumentLoader*>::iterator it = m_pendingMasterResourceLoaders.begin();
8068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        ASSERT((*it)->applicationCacheHost()->candidateApplicationCacheGroup() == this);
8080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        ASSERT(!(*it)->applicationCacheHost()->applicationCache());
8090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        (*it)->applicationCacheHost()->setCandidateApplicationCacheGroup(0);
810635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        m_pendingMasterResourceLoaders.remove(it);
8118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
812635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
8135f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    m_downloadingPendingMasterResourceLoadersCount = 0;
814e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    setUpdateStatus(Idle);
8158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_frame = 0;
8168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
817635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (m_caches.isEmpty()) {
818635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(m_associatedDocumentLoaders.isEmpty());
819635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(!m_cacheBeingUpdated);
8208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        delete this;
821635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
8228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
8248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ApplicationCacheGroup::checkIfLoadIsComplete()
8258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (m_manifestHandle || !m_pendingEntries.isEmpty() || m_downloadingPendingMasterResourceLoadersCount)
8278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
8288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
829635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // We're done, all resources have finished downloading (successfully or not).
830635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
8318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool isUpgradeAttempt = m_newestCache;
8328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
833635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    switch (m_completionType) {
834635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    case None:
835635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT_NOT_REACHED();
836635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return;
837635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    case NoUpdate:
838635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(isUpgradeAttempt);
839635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(!m_cacheBeingUpdated);
8408f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
8418f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        // The storage could have been manually emptied by the user.
8428f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        if (!m_storageID)
8438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian            cacheStorage().storeNewestCache(this);
8448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian
8450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        postListenerTask(ApplicationCacheHost::NOUPDATE_EVENT, m_associatedDocumentLoaders);
846635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        break;
847635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    case Failure:
848635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(!m_cacheBeingUpdated);
8490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        postListenerTask(ApplicationCacheHost::ERROR_EVENT, m_associatedDocumentLoaders);
850635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (m_caches.isEmpty()) {
851635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            ASSERT(m_associatedDocumentLoaders.isEmpty());
852635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            delete this;
853635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            return;
8548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
855635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        break;
856635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    case Completed: {
857635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // 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>)
858635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
859635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(m_cacheBeingUpdated);
860c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu        if (m_manifestResource)
861c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu            m_cacheBeingUpdated->setManifestResource(m_manifestResource.release());
862c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu        else {
863c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu            // We can get here as a result of retrying the Complete step, following
864c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu            // a failure of the cache storage to save the newest cache due to hitting
865c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu            // the maximum size. In such a case, m_manifestResource may be 0, as
866c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu            // the manifest was already set on the newest cache object.
867c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu            ASSERT(cacheStorage().isMaximumSizeReached() && m_calledReachedMaxAppCacheSize);
868c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu        }
869635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
870db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        ApplicationCacheStorage::FailureReason failureReason;
8712bde8e466a4451c7319e3a072d118917957d6554Steve Block        RefPtr<ApplicationCache> oldNewestCache = (m_newestCache == m_cacheBeingUpdated) ? RefPtr<ApplicationCache>() : m_newestCache;
872635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        setNewestCache(m_cacheBeingUpdated.release());
873db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block        if (cacheStorage().storeNewestCache(this, oldNewestCache.get(), failureReason)) {
8740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            // New cache stored, now remove the old cache.
8750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            if (oldNewestCache)
8760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                cacheStorage().remove(oldNewestCache.get());
877e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
878e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke            // Fire the final progress event.
879e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke            ASSERT(m_progressDone == m_progressTotal);
880e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke            postListenerTask(ApplicationCacheHost::PROGRESS_EVENT, m_progressTotal, m_progressDone, m_associatedDocumentLoaders);
881e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
882e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke            // Fire the success event.
8830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            postListenerTask(isUpgradeAttempt ? ApplicationCacheHost::UPDATEREADY_EVENT : ApplicationCacheHost::CACHED_EVENT, m_associatedDocumentLoaders);
884db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            // It is clear that the origin quota was not reached, so clear the flag if it was set.
885db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            m_originQuotaReached = false;
8860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        } else {
887db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            if (failureReason == ApplicationCacheStorage::OriginQuotaReached) {
888db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block                // We ran out of space for this origin. Roll back to previous state.
889db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block                if (oldNewestCache)
890db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block                    setNewestCache(oldNewestCache.release());
891db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block                cacheUpdateFailedDueToOriginQuota();
892db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block                return;
893db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            }
894db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
895db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            if (failureReason == ApplicationCacheStorage::TotalQuotaReached && !m_calledReachedMaxAppCacheSize) {
8960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                // We ran out of space. All the changes in the cache storage have
8970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                // been rolled back. We roll back to the previous state in here,
8980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                // as well, call the chrome client asynchronously and retry to
8990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                // save the new cache.
9000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
9010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                // Save a reference to the new cache.
9020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                m_cacheBeingUpdated = m_newestCache.release();
9030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                if (oldNewestCache) {
9040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                    // Reinstate the oldNewestCache.
9050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                    setNewestCache(oldNewestCache.release());
9060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                }
9070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                scheduleReachedMaxAppCacheSizeCallback();
9080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch                return;
909db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            }
910db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
911db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            // Run the "cache failure steps"
912db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            // Fire the error events to all pending master entries, as well any other cache hosts
913db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            // currently associated with a cache in this group.
914db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            postListenerTask(ApplicationCacheHost::ERROR_EVENT, m_associatedDocumentLoaders);
915db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            // Disassociate the pending master entries from the failed new cache. Note that
916db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            // all other loaders in the m_associatedDocumentLoaders are still associated with
917db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            // some other cache in this group. They are not associated with the failed new cache.
918db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
919db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            // Need to copy loaders, because the cache group may be destroyed at the end of iteration.
920db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            Vector<DocumentLoader*> loaders;
921db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            copyToVector(m_pendingMasterResourceLoaders, loaders);
922db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            size_t count = loaders.size();
923db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            for (size_t i = 0; i != count; ++i)
924db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block                disassociateDocumentLoader(loaders[i]); // This can delete this group.
925db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
926db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            // Reinstate the oldNewestCache, if there was one.
927db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block            if (oldNewestCache) {
928db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block                // This will discard the failed new cache.
929db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block                setNewestCache(oldNewestCache.release());
9300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            } else {
931db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block                // We must have been deleted by the last call to disassociateDocumentLoader().
932db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block                return;
9330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            }
9340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
935635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        break;
9368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
937635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
938635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
9395f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // Empty cache group's list of pending master entries.
9405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    m_pendingMasterResourceLoaders.clear();
941635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_completionType = None;
942e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    setUpdateStatus(Idle);
943635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    m_frame = 0;
944db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    m_loadedSize = 0;
945db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block    m_availableSpaceInQuota = ApplicationCacheStorage::unknownQuota();
946c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    m_calledReachedMaxAppCacheSize = false;
9478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ApplicationCacheGroup::startLoadingEntry()
9508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(m_cacheBeingUpdated);
9528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_pendingEntries.isEmpty()) {
954635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        m_completionType = Completed;
955635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        deliverDelayedMainResources();
9568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
9578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
9588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    EntryMap::const_iterator it = m_pendingEntries.begin();
9608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
961e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    postListenerTask(ApplicationCacheHost::PROGRESS_EVENT, m_progressTotal, m_progressDone, m_associatedDocumentLoaders);
962e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    m_progressDone++;
9638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!m_currentHandle);
9658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
966231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    m_currentHandle = createResourceHandle(KURL(ParsedURLString, it->first), m_newestCache ? m_newestCache->resourceForURL(it->first) : 0);
9678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
9688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
969635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectvoid ApplicationCacheGroup::deliverDelayedMainResources()
970635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
971635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // Need to copy loaders, because the cache group may be destroyed at the end of iteration.
972635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    Vector<DocumentLoader*> loaders;
973635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    copyToVector(m_pendingMasterResourceLoaders, loaders);
974635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    size_t count = loaders.size();
975635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    for (size_t i = 0; i != count; ++i) {
976635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        DocumentLoader* loader = loaders[i];
977635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (loader->isLoadingMainResource())
978635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            continue;
979635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
980635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        const ResourceError& error = loader->mainDocumentError();
981635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        if (error.isNull())
982635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            finishedLoadingMainResource(loader);
983635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        else
984635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project            failedLoadingMainResource(loader);
985635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
986635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!count)
987635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        checkIfLoadIsComplete();
988635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project}
989635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
9908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ApplicationCacheGroup::addEntry(const String& url, unsigned type)
9918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
9928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(m_cacheBeingUpdated);
993231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ASSERT(!KURL(ParsedURLString, url).hasFragmentIdentifier());
9948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
9958f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    // Don't add the URL if we already have an master resource in the cache
996635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // (i.e., the main resource finished loading before the manifest).
9978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (ApplicationCacheResource* resource = m_cacheBeingUpdated->resourceForURL(url)) {
9988f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        ASSERT(resource->type() & ApplicationCacheResource::Master);
999635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(!m_frame->loader()->documentLoader()->isLoadingMainResource());
10008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        resource->addType(type);
10028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
10038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
10048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Don't add the URL if it's the same as the manifest URL.
1006635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(m_manifestResource);
1007635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (m_manifestResource->url() == url) {
10088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_manifestResource->addType(type);
10098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
10108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
10118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    pair<EntryMap::iterator, bool> result = m_pendingEntries.add(url, type);
10138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!result.second)
10158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        result.first->second |= type;
10168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
10178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
10188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ApplicationCacheGroup::associateDocumentLoaderWithCache(DocumentLoader* loader, ApplicationCache* cache)
10198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1020635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    // If teardown started already, revive the group.
1021635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!m_newestCache && !m_cacheBeingUpdated)
1022635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        m_newestCache = cache;
1023635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1024635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(!m_isObsolete);
1025635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
10260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    loader->applicationCacheHost()->setApplicationCache(cache);
1027635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
10288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!m_associatedDocumentLoaders.contains(loader));
10298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_associatedDocumentLoaders.add(loader);
10308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1031c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu
1032c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescuclass ChromeClientCallbackTimer: public TimerBase {
1033c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescupublic:
1034c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    ChromeClientCallbackTimer(ApplicationCacheGroup* cacheGroup)
1035c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu        : m_cacheGroup(cacheGroup)
1036c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    {
1037c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    }
1038c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu
1039c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescuprivate:
1040c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    virtual void fired()
1041c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    {
1042c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu        m_cacheGroup->didReachMaxAppCacheSize();
1043c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu        delete this;
1044c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    }
1045c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    // Note that there is no need to use a RefPtr here. The ApplicationCacheGroup instance is guaranteed
1046c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    // to be alive when the timer fires since invoking the ChromeClient callback is part of its normal
1047c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    // update machinery and nothing can yet cause it to get deleted.
1048c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    ApplicationCacheGroup* m_cacheGroup;
1049c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu};
1050c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu
1051c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescuvoid ApplicationCacheGroup::scheduleReachedMaxAppCacheSizeCallback()
1052c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu{
1053c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    ASSERT(isMainThread());
1054c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    ChromeClientCallbackTimer* timer = new ChromeClientCallbackTimer(this);
1055c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    timer->startOneShot(0);
1056c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu    // The timer will delete itself once it fires.
1057c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu}
1058c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu
1059db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Blockvoid ApplicationCacheGroup::scheduleReachedOriginQuotaCallback()
1060db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block{
1061dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    // FIXME: it might be nice to run this asynchronously, because there is no return value to wait for.
1062dd8bb3de4f353a81954234999f1fea748aee2ea9Ben Murdoch    didReachOriginQuota(m_frame);
1063db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block}
1064db14019a23d96bc8a444b6576a5da8bd1cfbc8b0Steve Block
1065635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectclass CallCacheListenerTask : public ScriptExecutionContext::Task {
1066635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectpublic:
1067e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    static PassOwnPtr<CallCacheListenerTask> create(PassRefPtr<DocumentLoader> loader, ApplicationCacheHost::EventID eventID, int progressTotal, int progressDone)
1068635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    {
1069e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        return adoptPtr(new CallCacheListenerTask(loader, eventID, progressTotal, progressDone));
1070635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
10718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1072635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    virtual void performTask(ScriptExecutionContext* context)
1073635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    {
10740bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
10750bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        ASSERT_UNUSED(context, context->isDocument());
10760bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        Frame* frame = m_documentLoader->frame();
10770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (!frame)
10780bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            return;
10790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
10800bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        ASSERT(frame->loader()->documentLoader() == m_documentLoader.get());
10810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1082e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        m_documentLoader->applicationCacheHost()->notifyDOMApplicationCache(m_eventID, m_progressTotal, m_progressDone);
1083635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
1084635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1085635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectprivate:
1086e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    CallCacheListenerTask(PassRefPtr<DocumentLoader> loader, ApplicationCacheHost::EventID eventID, int progressTotal, int progressDone)
10870bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        : m_documentLoader(loader)
10880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        , m_eventID(eventID)
1089e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        , m_progressTotal(progressTotal)
1090e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        , m_progressDone(progressDone)
1091635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    {
1092635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    }
1093635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
10940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    RefPtr<DocumentLoader> m_documentLoader;
10950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ApplicationCacheHost::EventID m_eventID;
1096e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    int m_progressTotal;
1097e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    int m_progressDone;
1098635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project};
1099635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1100e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkevoid ApplicationCacheGroup::postListenerTask(ApplicationCacheHost::EventID eventID, int progressTotal, int progressDone, const HashSet<DocumentLoader*>& loaderSet)
1101635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project{
1102635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    HashSet<DocumentLoader*>::const_iterator loaderSetEnd = loaderSet.end();
1103635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    for (HashSet<DocumentLoader*>::const_iterator iter = loaderSet.begin(); iter != loaderSetEnd; ++iter)
1104e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke        postListenerTask(eventID, progressTotal, progressDone, *iter);
11058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1106635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1107e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkevoid ApplicationCacheGroup::postListenerTask(ApplicationCacheHost::EventID eventID, int progressTotal, int progressDone, DocumentLoader* loader)
11088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1109635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    Frame* frame = loader->frame();
1110635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!frame)
1111635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        return;
1112635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1113635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    ASSERT(frame->loader()->documentLoader() == loader);
1114635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
1115e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    frame->document()->postTask(CallCacheListenerTask::create(loader, eventID, progressTotal, progressDone));
1116e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke}
1117e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke
1118e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarkevoid ApplicationCacheGroup::setUpdateStatus(UpdateStatus status)
1119e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke{
1120e458d70a0d18538346f41b503114c9ebe6b2ce12Leon Clarke    m_updateStatus = status;
112165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    InspectorInstrumentation::updateApplicationCacheStatus(m_frame);
11228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
11238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid ApplicationCacheGroup::clearStorageID()
11258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
11268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_storageID = 0;
11278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    HashSet<ApplicationCache*>::const_iterator end = m_caches.end();
11298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    for (HashSet<ApplicationCache*>::const_iterator it = m_caches.begin(); it != end; ++it)
11308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        (*it)->clearStorageID();
11318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1132c60802dd50f86c37e0596d41c3ef6fc2c8804da4Andrei Popescu
11338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
11358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif // ENABLE(OFFLINE_WEB_APPLICATIONS)
1137