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