• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
manifestURL()70     const KURL& manifestURL() const { return m_manifestURL; }
origin()71     const SecurityOrigin* origin() const { return m_origin.get(); }
updateStatus()72     UpdateStatus updateStatus() const { return m_updateStatus; }
73     void setUpdateStatus(UpdateStatus status);
74 
setStorageID(unsigned storageID)75     void setStorageID(unsigned storageID) { m_storageID = 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 
cacheIsBeingUpdated(const ApplicationCache * cache)82     bool cacheIsBeingUpdated(const ApplicationCache* cache) const { return cache == m_cacheBeingUpdated; }
83 
84     void stopLoadingInFrame(Frame*);
85 
newestCache()86     ApplicationCache* newestCache() const { return m_newestCache.get(); }
87     void setNewestCache(PassRefPtr<ApplicationCache>);
88 
89     void makeObsolete();
isObsolete()90     bool isObsolete() const { return m_isObsolete; }
91 
92     void finishedLoadingMainResource(DocumentLoader*);
93     void failedLoadingMainResource(DocumentLoader*);
94 
95     void disassociateDocumentLoader(DocumentLoader*);
96 
isCopy()97     bool isCopy() const { return m_isCopy; }
98 
99 private:
postListenerTask(ApplicationCacheHost::EventID id,const HashSet<DocumentLoader * > & set)100     static void postListenerTask(ApplicationCacheHost::EventID id, const HashSet<DocumentLoader*>& set) { postListenerTask(id, 0, 0, set); }
postListenerTask(ApplicationCacheHost::EventID id,DocumentLoader * loader)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.
shouldUseCredentialStorage(ResourceHandle *)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