1 /* 2 * Copyright (C) 2006, 2007, 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 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14 * its contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #ifndef DocumentLoader_h 30 #define DocumentLoader_h 31 32 #include "NavigationAction.h" 33 #include "ResourceError.h" 34 #include "ResourceRequest.h" 35 #include "ResourceResponse.h" 36 #include "SubstituteData.h" 37 #include "Timer.h" 38 39 namespace WebCore { 40 41 class ApplicationCacheHost; 42 #if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size 43 class Archive; 44 class ArchiveResource; 45 class ArchiveResourceCollection; 46 #endif 47 class CachedPage; 48 class Frame; 49 class FrameLoader; 50 class MainResourceLoader; 51 class ResourceLoader; 52 class SchedulePair; 53 class SharedBuffer; 54 class SubstituteResource; 55 56 typedef HashSet<RefPtr<ResourceLoader> > ResourceLoaderSet; 57 typedef Vector<ResourceResponse> ResponseVector; 58 59 class DocumentLoader : public RefCounted<DocumentLoader> { 60 public: create(const ResourceRequest & request,const SubstituteData & data)61 static PassRefPtr<DocumentLoader> create(const ResourceRequest& request, const SubstituteData& data) 62 { 63 return adoptRef(new DocumentLoader(request, data)); 64 } 65 virtual ~DocumentLoader(); 66 67 void setFrame(Frame*); frame()68 Frame* frame() const { return m_frame; } 69 70 virtual void attachToFrame(); 71 virtual void detachFromFrame(); 72 73 FrameLoader* frameLoader() const; mainResourceLoader()74 MainResourceLoader* mainResourceLoader() const { return m_mainResourceLoader.get(); } 75 PassRefPtr<SharedBuffer> mainResourceData() const; 76 77 const ResourceRequest& originalRequest() const; 78 const ResourceRequest& originalRequestCopy() const; 79 80 const ResourceRequest& request() const; 81 ResourceRequest& request(); 82 void setRequest(const ResourceRequest&); 83 substituteData()84 const SubstituteData& substituteData() const { return m_substituteData; } 85 86 const KURL& url() const; 87 const KURL& unreachableURL() const; 88 89 const KURL& originalURL() const; 90 const KURL& requestURL() const; 91 const KURL& responseURL() const; 92 const String& responseMIMEType() const; 93 94 void replaceRequestURLForAnchorScroll(const KURL&); isStopping()95 bool isStopping() const { return m_isStopping; } 96 void stopLoading(DatabasePolicy = DatabasePolicyStop); setCommitted(bool committed)97 void setCommitted(bool committed) { m_committed = committed; } isCommitted()98 bool isCommitted() const { return m_committed; } isLoading()99 bool isLoading() const { return m_loading; } setLoading(bool loading)100 void setLoading(bool loading) { m_loading = loading; } 101 void updateLoading(); 102 void receivedData(const char*, int); 103 void setupForReplaceByMIMEType(const String& newMIMEType); 104 void finishedLoading(); response()105 const ResourceResponse& response() const { return m_response; } mainDocumentError()106 const ResourceError& mainDocumentError() const { return m_mainDocumentError; } 107 void mainReceivedError(const ResourceError&, bool isComplete); setResponse(const ResourceResponse & response)108 void setResponse(const ResourceResponse& response) { m_response = response; } 109 void prepareForLoadStart(); isClientRedirect()110 bool isClientRedirect() const { return m_isClientRedirect; } setIsClientRedirect(bool isClientRedirect)111 void setIsClientRedirect(bool isClientRedirect) { m_isClientRedirect = isClientRedirect; } 112 bool isLoadingInAPISense() const; 113 void setPrimaryLoadComplete(bool); 114 void setTitle(const String&); overrideEncoding()115 const String& overrideEncoding() const { return m_overrideEncoding; } 116 117 #if PLATFORM(MAC) 118 void schedule(SchedulePair*); 119 void unschedule(SchedulePair*); 120 #endif 121 122 #if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size 123 void addAllArchiveResources(Archive*); 124 void addArchiveResource(PassRefPtr<ArchiveResource>); 125 126 // Return an ArchiveResource for the URL, either creating from live data or 127 // pulling from the ArchiveResourceCollection 128 PassRefPtr<ArchiveResource> subresource(const KURL&) const; 129 // Return the ArchiveResource for the URL only when loading an Archive 130 ArchiveResource* archiveResourceForURL(const KURL&) const; 131 132 PassRefPtr<Archive> popArchiveForSubframe(const String& frameName); 133 void clearArchiveResources(); 134 void setParsedArchiveData(PassRefPtr<SharedBuffer>); 135 SharedBuffer* parsedArchiveData() const; 136 137 PassRefPtr<ArchiveResource> mainResource() const; 138 void getSubresources(Vector<PassRefPtr<ArchiveResource> >&) const; 139 140 bool scheduleArchiveLoad(ResourceLoader*, const ResourceRequest&, const KURL&); 141 #endif 142 #ifndef NDEBUG 143 bool isSubstituteLoadPending(ResourceLoader*) const; 144 #endif 145 void cancelPendingSubstituteLoad(ResourceLoader*); 146 147 void addResponse(const ResourceResponse&); responses()148 const ResponseVector& responses() const { return m_responses; } 149 triggeringAction()150 const NavigationAction& triggeringAction() const { return m_triggeringAction; } setTriggeringAction(const NavigationAction & action)151 void setTriggeringAction(const NavigationAction& action) { m_triggeringAction = action; } setOverrideEncoding(const String & encoding)152 void setOverrideEncoding(const String& encoding) { m_overrideEncoding = encoding; } setLastCheckedRequest(const ResourceRequest & request)153 void setLastCheckedRequest(const ResourceRequest& request) { m_lastCheckedRequest = request; } lastCheckedRequest()154 const ResourceRequest& lastCheckedRequest() { return m_lastCheckedRequest; } 155 156 void stopRecordingResponses(); title()157 const String& title() const { return m_pageTitle; } 158 159 KURL urlForHistory() const; 160 bool urlForHistoryReflectsFailure() const; 161 162 // These accessors accomodate WebCore's somewhat fickle custom of creating history 163 // items for redirects, but only sometimes. For "source" and "destination", 164 // these accessors return the URL that would have been used if a history 165 // item were created. This allows WebKit to link history items reflecting 166 // redirects into a chain from start to finish. clientRedirectSourceForHistory()167 String clientRedirectSourceForHistory() const { return m_clientRedirectSourceForHistory; } // null if no client redirect occurred. clientRedirectDestinationForHistory()168 String clientRedirectDestinationForHistory() const { return urlForHistory(); } setClientRedirectSourceForHistory(const String & clientedirectSourceForHistory)169 void setClientRedirectSourceForHistory(const String& clientedirectSourceForHistory) { m_clientRedirectSourceForHistory = clientedirectSourceForHistory; } 170 serverRedirectSourceForHistory()171 String serverRedirectSourceForHistory() const { return urlForHistory() == url() ? String() : urlForHistory(); } // null if no server redirect occurred. serverRedirectDestinationForHistory()172 String serverRedirectDestinationForHistory() const { return url(); } 173 didCreateGlobalHistoryEntry()174 bool didCreateGlobalHistoryEntry() const { return m_didCreateGlobalHistoryEntry; } setDidCreateGlobalHistoryEntry(bool didCreateGlobalHistoryEntry)175 void setDidCreateGlobalHistoryEntry(bool didCreateGlobalHistoryEntry) { m_didCreateGlobalHistoryEntry = didCreateGlobalHistoryEntry; } 176 177 void loadFromCachedPage(PassRefPtr<CachedPage>); setLoadingFromCachedPage(bool loading)178 void setLoadingFromCachedPage(bool loading) { m_loadingFromCachedPage = loading; } isLoadingFromCachedPage()179 bool isLoadingFromCachedPage() const { return m_loadingFromCachedPage; } 180 181 void setDefersLoading(bool); 182 183 bool startLoadingMainResource(unsigned long identifier); 184 void cancelMainResourceLoad(const ResourceError&); 185 186 void iconLoadDecisionAvailable(); 187 188 bool isLoadingMainResource() const; 189 bool isLoadingSubresources() const; 190 bool isLoadingPlugIns() const; 191 bool isLoadingMultipartContent() const; 192 193 void stopLoadingPlugIns(); 194 void stopLoadingSubresources(); 195 196 void addSubresourceLoader(ResourceLoader*); 197 void removeSubresourceLoader(ResourceLoader*); 198 void addPlugInStreamLoader(ResourceLoader*); 199 void removePlugInStreamLoader(ResourceLoader*); 200 201 void subresourceLoaderFinishedLoadingOnePart(ResourceLoader*); 202 setDeferMainResourceDataLoad(bool defer)203 void setDeferMainResourceDataLoad(bool defer) { m_deferMainResourceDataLoad = defer; } deferMainResourceDataLoad()204 bool deferMainResourceDataLoad() const { return m_deferMainResourceDataLoad; } 205 didTellClientAboutLoad(const String & url)206 void didTellClientAboutLoad(const String& url) { m_resourcesClientKnowsAbout.add(url); } haveToldClientAboutLoad(const String & url)207 bool haveToldClientAboutLoad(const String& url) { return m_resourcesClientKnowsAbout.contains(url); } 208 void recordMemoryCacheLoadForFutureClientNotification(const String& url); 209 void takeMemoryCacheLoadsForClientNotification(Vector<String>& loads); 210 211 #if ENABLE(OFFLINE_WEB_APPLICATIONS) applicationCacheHost()212 ApplicationCacheHost* applicationCacheHost() const { return m_applicationCacheHost.get(); } 213 #endif 214 215 protected: 216 DocumentLoader(const ResourceRequest&, const SubstituteData&); 217 218 bool m_deferMainResourceDataLoad; 219 220 private: 221 void setupForReplace(); 222 void commitIfReady(); 223 void clearErrors(); 224 void setMainDocumentError(const ResourceError&); 225 void commitLoad(const char*, int); 226 bool doesProgressiveLoad(const String& MIMEType) const; 227 228 void deliverSubstituteResourcesAfterDelay(); 229 void substituteResourceDeliveryTimerFired(Timer<DocumentLoader>*); 230 231 Frame* m_frame; 232 233 RefPtr<MainResourceLoader> m_mainResourceLoader; 234 ResourceLoaderSet m_subresourceLoaders; 235 ResourceLoaderSet m_multipartSubresourceLoaders; 236 ResourceLoaderSet m_plugInStreamLoaders; 237 238 RefPtr<SharedBuffer> m_mainResourceData; 239 240 // A reference to actual request used to create the data source. 241 // This should only be used by the resourceLoadDelegate's 242 // identifierForInitialRequest:fromDatasource: method. It is 243 // not guaranteed to remain unchanged, as requests are mutable. 244 ResourceRequest m_originalRequest; 245 246 SubstituteData m_substituteData; 247 248 // A copy of the original request used to create the data source. 249 // We have to copy the request because requests are mutable. 250 ResourceRequest m_originalRequestCopy; 251 252 // The 'working' request. It may be mutated 253 // several times from the original request to include additional 254 // headers, cookie information, canonicalization and redirects. 255 ResourceRequest m_request; 256 257 ResourceResponse m_response; 258 259 ResourceError m_mainDocumentError; 260 261 bool m_committed; 262 bool m_isStopping; 263 bool m_loading; 264 bool m_gotFirstByte; 265 bool m_primaryLoadComplete; 266 bool m_isClientRedirect; 267 bool m_loadingFromCachedPage; 268 269 String m_pageTitle; 270 271 String m_overrideEncoding; 272 273 // The action that triggered loading - we keep this around for the 274 // benefit of the various policy handlers. 275 NavigationAction m_triggeringAction; 276 277 // The last request that we checked click policy for - kept around 278 // so we can avoid asking again needlessly. 279 ResourceRequest m_lastCheckedRequest; 280 281 // We retain all the received responses so we can play back the 282 // WebResourceLoadDelegate messages if the item is loaded from the 283 // page cache. 284 ResponseVector m_responses; 285 bool m_stopRecordingResponses; 286 287 typedef HashMap<RefPtr<ResourceLoader>, RefPtr<SubstituteResource> > SubstituteResourceMap; 288 SubstituteResourceMap m_pendingSubstituteResources; 289 Timer<DocumentLoader> m_substituteResourceDeliveryTimer; 290 291 #if ENABLE(ARCHIVE) // ANDROID extension: disabled to reduce code size 292 OwnPtr<ArchiveResourceCollection> m_archiveResourceCollection; 293 RefPtr<SharedBuffer> m_parsedArchiveData; 294 #endif 295 296 HashSet<String> m_resourcesClientKnowsAbout; 297 Vector<String> m_resourcesLoadedFromMemoryCacheForClientNotification; 298 299 String m_clientRedirectSourceForHistory; 300 bool m_didCreateGlobalHistoryEntry; 301 302 #if ENABLE(OFFLINE_WEB_APPLICATIONS) 303 friend class ApplicationCacheHost; // for substitute resource delivery 304 OwnPtr<ApplicationCacheHost> m_applicationCacheHost; 305 #endif 306 }; 307 recordMemoryCacheLoadForFutureClientNotification(const String & url)308 inline void DocumentLoader::recordMemoryCacheLoadForFutureClientNotification(const String& url) 309 { 310 m_resourcesLoadedFromMemoryCacheForClientNotification.append(url); 311 } 312 takeMemoryCacheLoadsForClientNotification(Vector<String> & loadsSet)313 inline void DocumentLoader::takeMemoryCacheLoadsForClientNotification(Vector<String>& loadsSet) 314 { 315 loadsSet.swap(m_resourcesLoadedFromMemoryCacheForClientNotification); 316 m_resourcesLoadedFromMemoryCacheForClientNotification.clear(); 317 } 318 319 } 320 321 #endif // DocumentLoader_h 322