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