Home | History | Annotate | Download | only in appcache
      1 /*
      2  * Copyright (C) 2008, 2009, 2010 Apple Inc. All Rights Reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef ApplicationCacheGroup_h
     27 #define ApplicationCacheGroup_h
     28 
     29 #if ENABLE(OFFLINE_WEB_APPLICATIONS)
     30 
     31 #include "DOMApplicationCache.h"
     32 #include "KURL.h"
     33 #include "PlatformString.h"
     34 #include "ResourceHandle.h"
     35 #include "ResourceHandleClient.h"
     36 #include "SharedBuffer.h"
     37 
     38 #include <wtf/Noncopyable.h>
     39 #include <wtf/HashMap.h>
     40 #include <wtf/HashSet.h>
     41 
     42 namespace WebCore {
     43 
     44 class ApplicationCache;
     45 class ApplicationCacheResource;
     46 class Document;
     47 class DocumentLoader;
     48 class Frame;
     49 class SecurityOrigin;
     50 
     51 enum ApplicationCacheUpdateOption {
     52     ApplicationCacheUpdateWithBrowsingContext,
     53     ApplicationCacheUpdateWithoutBrowsingContext
     54 };
     55 
     56 class ApplicationCacheGroup : ResourceHandleClient {
     57     WTF_MAKE_NONCOPYABLE(ApplicationCacheGroup); WTF_MAKE_FAST_ALLOCATED;
     58 public:
     59     ApplicationCacheGroup(const KURL& manifestURL, bool isCopy = false);
     60     ~ApplicationCacheGroup();
     61 
     62     enum UpdateStatus { Idle, Checking, Downloading };
     63 
     64     static ApplicationCache* cacheForMainRequest(const ResourceRequest&, DocumentLoader*);
     65     static ApplicationCache* fallbackCacheForMainRequest(const ResourceRequest&, DocumentLoader*);
     66 
     67     static void selectCache(Frame*, const KURL& manifestURL);
     68     static void selectCacheWithoutManifestURL(Frame*);
     69 
     70     const KURL& manifestURL() const { return m_manifestURL; }
     71     const SecurityOrigin* origin() const { return m_origin.get(); }
     72     UpdateStatus updateStatus() const { return m_updateStatus; }
     73     void setUpdateStatus(UpdateStatus status);
     74 
     75     void setStorageID(unsigned storageID) { m_storageID = storageID; }
     76     unsigned storageID() const { return m_storageID; }
     77     void clearStorageID();
     78 
     79     void update(Frame*, ApplicationCacheUpdateOption); // FIXME: Frame should not be needed when updating without browsing context.
     80     void cacheDestroyed(ApplicationCache*);
     81 
     82     bool cacheIsBeingUpdated(const ApplicationCache* cache) const { return cache == m_cacheBeingUpdated; }
     83 
     84     void stopLoadingInFrame(Frame*);
     85 
     86     ApplicationCache* newestCache() const { return m_newestCache.get(); }
     87     void setNewestCache(PassRefPtr<ApplicationCache>);
     88 
     89     void makeObsolete();
     90     bool isObsolete() const { return m_isObsolete; }
     91 
     92     void finishedLoadingMainResource(DocumentLoader*);
     93     void failedLoadingMainResource(DocumentLoader*);
     94 
     95     void disassociateDocumentLoader(DocumentLoader*);
     96 
     97     bool isCopy() const { return m_isCopy; }
     98 
     99 private:
    100     static void postListenerTask(ApplicationCacheHost::EventID id, const HashSet<DocumentLoader*>& set) { postListenerTask(id, 0, 0, set); }
    101     static void postListenerTask(ApplicationCacheHost::EventID id, DocumentLoader* loader)  { postListenerTask(id, 0, 0, loader); }
    102     static void postListenerTask(ApplicationCacheHost::EventID, int progressTotal, int progressDone, const HashSet<DocumentLoader*>&);
    103     static void postListenerTask(ApplicationCacheHost::EventID, int progressTotal, int progressDone, DocumentLoader*);
    104 
    105     void scheduleReachedMaxAppCacheSizeCallback();
    106     void scheduleReachedOriginQuotaCallback();
    107 
    108     PassRefPtr<ResourceHandle> createResourceHandle(const KURL&, ApplicationCacheResource* newestCachedResource);
    109 
    110     // For normal resource loading, WebKit client is asked about each resource individually. Since application cache does not belong to any particular document,
    111     // the existing client callback cannot be used, so assume that any client that enables application cache also wants it to use credential storage.
    112     virtual bool shouldUseCredentialStorage(ResourceHandle*) { return true; }
    113 
    114     virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&);
    115     virtual void didReceiveData(ResourceHandle*, const char*, int length, int encodedDataLength);
    116     virtual void didFinishLoading(ResourceHandle*, double finishTime);
    117     virtual void didFail(ResourceHandle*, const ResourceError&);
    118 
    119     void didReceiveManifestResponse(const ResourceResponse&);
    120     void didReceiveManifestData(const char*, int);
    121     void didFinishLoadingManifest();
    122     void didReachMaxAppCacheSize();
    123     void didReachOriginQuota(PassRefPtr<Frame> frame);
    124 
    125     void startLoadingEntry();
    126     void deliverDelayedMainResources();
    127     void checkIfLoadIsComplete();
    128     void cacheUpdateFailed();
    129     void cacheUpdateFailedDueToOriginQuota();
    130     void manifestNotFound();
    131 
    132     void addEntry(const String&, unsigned type);
    133 
    134     void associateDocumentLoaderWithCache(DocumentLoader*, ApplicationCache*);
    135 
    136     void stopLoading();
    137 
    138     KURL m_manifestURL;
    139     RefPtr<SecurityOrigin> m_origin;
    140     UpdateStatus m_updateStatus;
    141 
    142     // This is the newest complete cache in the group.
    143     RefPtr<ApplicationCache> m_newestCache;
    144 
    145     // All complete caches in this cache group.
    146     HashSet<ApplicationCache*> m_caches;
    147 
    148     // The cache being updated (if any). Note that cache updating does not immediately create a new
    149     // ApplicationCache object, so this may be null even when update status is not Idle.
    150     RefPtr<ApplicationCache> m_cacheBeingUpdated;
    151 
    152     // List of pending master entries, used during the update process to ensure that new master entries are cached.
    153     HashSet<DocumentLoader*> m_pendingMasterResourceLoaders;
    154     // How many of the above pending master entries have not yet finished downloading.
    155     int m_downloadingPendingMasterResourceLoadersCount;
    156 
    157     // These are all the document loaders that are associated with a cache in this group.
    158     HashSet<DocumentLoader*> m_associatedDocumentLoaders;
    159 
    160     // The URLs and types of pending cache entries.
    161     typedef HashMap<String, unsigned> EntryMap;
    162     EntryMap m_pendingEntries;
    163 
    164     // The total number of items to be processed to update the cache group and the number that have been done.
    165     int m_progressTotal;
    166     int m_progressDone;
    167 
    168     // Frame used for fetching resources when updating.
    169     // FIXME: An update started by a particular frame should not stop if it is destroyed, but there are other frames associated with the same cache group.
    170     Frame* m_frame;
    171 
    172     // An obsolete cache group is never stored, but the opposite is not true - storing may fail for multiple reasons, such as exceeding disk quota.
    173     unsigned m_storageID;
    174     bool m_isObsolete;
    175 
    176     // During update, this is used to handle asynchronously arriving results.
    177     enum CompletionType {
    178         None,
    179         NoUpdate,
    180         Failure,
    181         Completed
    182     };
    183     CompletionType m_completionType;
    184 
    185     // Whether this cache group is a copy that's only used for transferring the cache to another file.
    186     bool m_isCopy;
    187 
    188     // This flag is set immediately after the ChromeClient::reachedMaxAppCacheSize() callback is invoked as a result of the storage layer failing to save a cache
    189     // due to reaching the maximum size of the application cache database file. This flag is used by ApplicationCacheGroup::checkIfLoadIsComplete() to decide
    190     // the course of action in case of this failure (i.e. call the ChromeClient callback or run the failure steps).
    191     bool m_calledReachedMaxAppCacheSize;
    192 
    193     RefPtr<ResourceHandle> m_currentHandle;
    194     RefPtr<ApplicationCacheResource> m_currentResource;
    195 
    196 #if ENABLE(INSPECTOR)
    197     unsigned long m_currentResourceIdentifier;
    198 #endif
    199 
    200     RefPtr<ApplicationCacheResource> m_manifestResource;
    201     RefPtr<ResourceHandle> m_manifestHandle;
    202 
    203     int64_t m_loadedSize;
    204     int64_t m_availableSpaceInQuota;
    205     bool m_originQuotaReached;
    206 
    207     friend class ChromeClientCallbackTimer;
    208     friend class OriginQuotaReachedCallbackTimer;
    209 };
    210 
    211 } // namespace WebCore
    212 
    213 #endif // ENABLE(OFFLINE_WEB_APPLICATIONS)
    214 
    215 #endif // ApplicationCacheGroup_h
    216