Home | History | Annotate | Download | only in appcache
      1 /*
      2  * Copyright (C) 2008, 2009 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 <wtf/Noncopyable.h>
     32 #include <wtf/HashMap.h>
     33 #include <wtf/HashSet.h>
     34 
     35 #include "DOMApplicationCache.h"
     36 #include "KURL.h"
     37 #include "PlatformString.h"
     38 #include "ResourceHandle.h"
     39 #include "ResourceHandleClient.h"
     40 #include "SharedBuffer.h"
     41 
     42 namespace WebCore {
     43 
     44 class ApplicationCache;
     45 class ApplicationCacheResource;
     46 class Document;
     47 class DocumentLoader;
     48 class Frame;
     49 
     50 enum ApplicationCacheUpdateOption {
     51     ApplicationCacheUpdateWithBrowsingContext,
     52     ApplicationCacheUpdateWithoutBrowsingContext
     53 };
     54 
     55 class ApplicationCacheGroup : public Noncopyable, ResourceHandleClient {
     56 public:
     57     ApplicationCacheGroup(const KURL& manifestURL, bool isCopy = false);
     58     ~ApplicationCacheGroup();
     59 
     60     enum UpdateStatus { Idle, Checking, Downloading };
     61 
     62     static ApplicationCache* cacheForMainRequest(const ResourceRequest&, DocumentLoader*);
     63     static ApplicationCache* fallbackCacheForMainRequest(const ResourceRequest&, DocumentLoader*);
     64 
     65     static void selectCache(Frame*, const KURL& manifestURL);
     66     static void selectCacheWithoutManifestURL(Frame*);
     67 
     68     const KURL& manifestURL() const { return m_manifestURL; }
     69     UpdateStatus updateStatus() const { return m_updateStatus; }
     70 
     71     void setStorageID(unsigned storageID) { m_storageID = storageID; }
     72     unsigned storageID() const { return m_storageID; }
     73     void clearStorageID();
     74 
     75     void update(Frame*, ApplicationCacheUpdateOption); // FIXME: Frame should not bee needed when updating witout browsing context.
     76     void cacheDestroyed(ApplicationCache*);
     77 
     78     bool cacheIsBeingUpdated(const ApplicationCache* cache) const { return cache == m_cacheBeingUpdated; }
     79 
     80     ApplicationCache* newestCache() const { return m_newestCache.get(); }
     81     void setNewestCache(PassRefPtr<ApplicationCache>);
     82 
     83     void makeObsolete();
     84     bool isObsolete() const { return m_isObsolete; }
     85 
     86     void finishedLoadingMainResource(DocumentLoader*);
     87     void failedLoadingMainResource(DocumentLoader*);
     88 
     89     void disassociateDocumentLoader(DocumentLoader*);
     90 
     91     bool isCopy() const { return m_isCopy; }
     92 
     93 private:
     94     static void postListenerTask(ApplicationCacheHost::EventID, const HashSet<DocumentLoader*>&);
     95     static void postListenerTask(ApplicationCacheHost::EventID, DocumentLoader*);
     96     void scheduleReachedMaxAppCacheSizeCallback();
     97 
     98     PassRefPtr<ResourceHandle> createResourceHandle(const KURL&, ApplicationCacheResource* newestCachedResource);
     99 
    100     // For normal resource loading, WebKit client is asked about each resource individually. Since application cache does not belong to any particular document,
    101     // the existing client callback cannot be used, so assume that any client that enables application cache also wants it to use credential storage.
    102     virtual bool shouldUseCredentialStorage(ResourceHandle*) { return true; }
    103 
    104     virtual void didReceiveResponse(ResourceHandle*, const ResourceResponse&);
    105     virtual void didReceiveData(ResourceHandle*, const char*, int, int lengthReceived);
    106     virtual void didFinishLoading(ResourceHandle*);
    107     virtual void didFail(ResourceHandle*, const ResourceError&);
    108 
    109     void didReceiveManifestResponse(const ResourceResponse&);
    110     void didReceiveManifestData(const char*, int);
    111     void didFinishLoadingManifest();
    112     void didReachMaxAppCacheSize();
    113 
    114     void startLoadingEntry();
    115     void deliverDelayedMainResources();
    116     void checkIfLoadIsComplete();
    117     void cacheUpdateFailed();
    118     void manifestNotFound();
    119 
    120     void addEntry(const String&, unsigned type);
    121 
    122     void associateDocumentLoaderWithCache(DocumentLoader*, ApplicationCache*);
    123 
    124     void stopLoading();
    125 
    126     KURL m_manifestURL;
    127     UpdateStatus m_updateStatus;
    128 
    129     // This is the newest complete cache in the group.
    130     RefPtr<ApplicationCache> m_newestCache;
    131 
    132     // All complete caches in this cache group.
    133     HashSet<ApplicationCache*> m_caches;
    134 
    135     // The cache being updated (if any). Note that cache updating does not immediately create a new
    136     // ApplicationCache object, so this may be null even when update status is not Idle.
    137     RefPtr<ApplicationCache> m_cacheBeingUpdated;
    138 
    139     // List of pending master entries, used during the update process to ensure that new master entries are cached.
    140     HashSet<DocumentLoader*> m_pendingMasterResourceLoaders;
    141     // How many of the above pending master entries have not yet finished downloading.
    142     int m_downloadingPendingMasterResourceLoadersCount;
    143 
    144     // These are all the document loaders that are associated with a cache in this group.
    145     HashSet<DocumentLoader*> m_associatedDocumentLoaders;
    146 
    147     // The URLs and types of pending cache entries.
    148     typedef HashMap<String, unsigned> EntryMap;
    149     EntryMap m_pendingEntries;
    150 
    151     // Frame used for fetching resources when updating.
    152     // 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.
    153     Frame* m_frame;
    154 
    155     // An obsolete cache group is never stored, but the opposite is not true - storing may fail for multiple reasons, such as exceeding disk quota.
    156     unsigned m_storageID;
    157     bool m_isObsolete;
    158 
    159     // During update, this is used to handle asynchronously arriving results.
    160     enum CompletionType {
    161         None,
    162         NoUpdate,
    163         Failure,
    164         Completed
    165     };
    166     CompletionType m_completionType;
    167 
    168     // Whether this cache group is a copy that's only used for transferring the cache to another file.
    169     bool m_isCopy;
    170 
    171     // This flag is set immediately after the ChromeClient::reachedMaxAppCacheSize() callback is invoked as a result of the storage layer failing to save a cache
    172     // due to reaching the maximum size of the application cache database file. This flag is used by ApplicationCacheGroup::checkIfLoadIsComplete() to decide
    173     // the course of action in case of this failure (i.e. call the ChromeClient callback or run the failure steps).
    174     bool m_calledReachedMaxAppCacheSize;
    175 
    176     RefPtr<ResourceHandle> m_currentHandle;
    177     RefPtr<ApplicationCacheResource> m_currentResource;
    178 
    179     RefPtr<ApplicationCacheResource> m_manifestResource;
    180     RefPtr<ResourceHandle> m_manifestHandle;
    181 
    182     friend class ChromeClientCallbackTimer;
    183 };
    184 
    185 } // namespace WebCore
    186 
    187 #endif // ENABLE(OFFLINE_WEB_APPLICATIONS)
    188 
    189 #endif // ApplicationCacheGroup_h
    190