2 * Copyright (C) 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2011 Google Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of Apple Inc. ("Apple") nor the names of
15 * its contributors may be used to endorse or promote products derived
16 * from this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 #ifndef DocumentLoader_h
31 #define DocumentLoader_h
33 #include "CachedRawResourceClient.h"
34 #include "CachedResourceHandle.h"
35 #include "DocumentLoadTiming.h"
36 #include "DocumentWriter.h"
37 #include "IconDatabaseBase.h"
38 #include "NavigationAction.h"
39 #include "ResourceError.h"
40 #include "ResourceLoaderOptions.h"
41 #include "ResourceRequest.h"
42 #include "ResourceResponse.h"
43 #include "StringWithDirection.h"
44 #include "StyleSheetContents.h"
45 #include "SubstituteData.h"
47 #include <wtf/HashSet.h>
48 #include <wtf/RefPtr.h>
49 #include <wtf/Vector.h>
51 #if HAVE(RUNLOOP_TIMER)
52 #include <wtf/RunLoopTimer.h>
56 #include "QuickLook.h"
61 class ApplicationCacheHost;
63 class ArchiveResource;
64 class ArchiveResourceCollection;
65 class CachedRawResource;
66 class CachedResourceLoader;
73 class SubresourceLoader;
74 class SubstituteResource;
76 #if ENABLE(CONTENT_FILTERING)
80 typedef HashMap<unsigned long, RefPtr<ResourceLoader>> ResourceLoaderMap;
81 typedef Vector<ResourceResponse> ResponseVector;
83 class DocumentLoader : public RefCounted<DocumentLoader>, private CachedRawResourceClient {
84 WTF_MAKE_FAST_ALLOCATED;
86 static Ref<DocumentLoader> create(const ResourceRequest& request, const SubstituteData& data)
88 return adoptRef(*new DocumentLoader(request, data));
90 WEBCORE_EXPORT virtual ~DocumentLoader();
92 void attachToFrame(Frame&);
93 Frame* frame() const { return m_frame; }
95 WEBCORE_EXPORT virtual void detachFromFrame();
97 WEBCORE_EXPORT FrameLoader* frameLoader() const;
98 WEBCORE_EXPORT SubresourceLoader* mainResourceLoader() const;
99 WEBCORE_EXPORT PassRefPtr<SharedBuffer> mainResourceData() const;
101 DocumentWriter& writer() const { return m_writer; }
103 WEBCORE_EXPORT const ResourceRequest& originalRequest() const;
104 WEBCORE_EXPORT const ResourceRequest& originalRequestCopy() const;
106 WEBCORE_EXPORT const ResourceRequest& request() const;
107 WEBCORE_EXPORT ResourceRequest& request();
109 CachedResourceLoader& cachedResourceLoader() { return m_cachedResourceLoader; }
111 const SubstituteData& substituteData() const { return m_substituteData; }
113 WEBCORE_EXPORT const URL& url() const;
114 WEBCORE_EXPORT const URL& unreachableURL() const;
116 const URL& originalURL() const;
117 WEBCORE_EXPORT const URL& responseURL() const;
118 WEBCORE_EXPORT const String& responseMIMEType() const;
120 // FIXME: This method seems to violate the encapsulation of this class.
121 WEBCORE_EXPORT void setResponseMIMEType(const String&);
123 const String& currentContentType() const;
124 void replaceRequestURLForSameDocumentNavigation(const URL&);
125 bool isStopping() const { return m_isStopping; }
127 void setCommitted(bool committed) { m_committed = committed; }
128 bool isCommitted() const { return m_committed; }
129 WEBCORE_EXPORT bool isLoading() const;
131 const ResourceError& mainDocumentError() const { return m_mainDocumentError; }
133 const ResourceResponse& response() const { return m_response; }
135 // FIXME: This method seems to violate the encapsulation of this class.
136 void setResponse(const ResourceResponse& response) { m_response = response; }
139 bool isClientRedirect() const { return m_isClientRedirect; }
140 void setIsClientRedirect(bool isClientRedirect) { m_isClientRedirect = isClientRedirect; }
141 void handledOnloadEvents();
142 bool wasOnloadHandled() { return m_wasOnloadHandled; }
143 WEBCORE_EXPORT bool isLoadingInAPISense() const;
144 WEBCORE_EXPORT void setTitle(const StringWithDirection&);
145 const String& overrideEncoding() const { return m_overrideEncoding; }
148 void schedule(SchedulePair&);
149 void unschedule(SchedulePair&);
152 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
153 void setArchive(PassRefPtr<Archive>);
154 WEBCORE_EXPORT void addAllArchiveResources(Archive*);
155 WEBCORE_EXPORT void addArchiveResource(PassRefPtr<ArchiveResource>);
156 PassRefPtr<Archive> popArchiveForSubframe(const String& frameName, const URL&);
157 WEBCORE_EXPORT SharedBuffer* parsedArchiveData() const;
159 WEBCORE_EXPORT bool scheduleArchiveLoad(ResourceLoader*, const ResourceRequest&);
161 void scheduleSubstituteResourceLoad(ResourceLoader&, SubstituteResource&);
163 // Return the ArchiveResource for the URL only when loading an Archive
164 ArchiveResource* archiveResourceForURL(const URL&) const;
166 WEBCORE_EXPORT PassRefPtr<ArchiveResource> mainResource() const;
168 // Return an ArchiveResource for the URL, either creating from live data or
169 // pulling from the ArchiveResourceCollection
170 WEBCORE_EXPORT PassRefPtr<ArchiveResource> subresource(const URL&) const;
171 WEBCORE_EXPORT Vector<RefPtr<ArchiveResource>> subresources() const;
174 bool isSubstituteLoadPending(ResourceLoader*) const;
176 void cancelPendingSubstituteLoad(ResourceLoader*);
178 void addResponse(const ResourceResponse&);
179 const ResponseVector& responses() const { return m_responses; }
181 const NavigationAction& triggeringAction() const { return m_triggeringAction; }
182 void setTriggeringAction(const NavigationAction&);
183 void setOverrideEncoding(const String& encoding) { m_overrideEncoding = encoding; }
184 void setLastCheckedRequest(const ResourceRequest& request) { m_lastCheckedRequest = request; }
185 const ResourceRequest& lastCheckedRequest() { return m_lastCheckedRequest; }
187 void stopRecordingResponses();
188 const StringWithDirection& title() const { return m_pageTitle; }
190 WEBCORE_EXPORT URL urlForHistory() const;
191 WEBCORE_EXPORT bool urlForHistoryReflectsFailure() const;
193 // These accessors accommodate WebCore's somewhat fickle custom of creating history
194 // items for redirects, but only sometimes. For "source" and "destination",
195 // these accessors return the URL that would have been used if a history
196 // item were created. This allows WebKit to link history items reflecting
197 // redirects into a chain from start to finish.
198 String clientRedirectSourceForHistory() const { return m_clientRedirectSourceForHistory; } // null if no client redirect occurred.
199 String clientRedirectDestinationForHistory() const { return urlForHistory(); }
200 void setClientRedirectSourceForHistory(const String& clientRedirectSourceForHistory) { m_clientRedirectSourceForHistory = clientRedirectSourceForHistory; }
202 String serverRedirectSourceForHistory() const { return (urlForHistory() == url() || url() == blankURL()) ? String() : urlForHistory().string(); } // null if no server redirect occurred.
203 String serverRedirectDestinationForHistory() const { return url(); }
205 bool didCreateGlobalHistoryEntry() const { return m_didCreateGlobalHistoryEntry; }
206 void setDidCreateGlobalHistoryEntry(bool didCreateGlobalHistoryEntry) { m_didCreateGlobalHistoryEntry = didCreateGlobalHistoryEntry; }
208 bool subresourceLoadersArePageCacheAcceptable() const { return m_subresourceLoadersArePageCacheAcceptable; }
210 void setDefersLoading(bool);
211 void setMainResourceDataBufferingPolicy(DataBufferingPolicy);
213 void startLoadingMainResource();
214 WEBCORE_EXPORT void cancelMainResourceLoad(const ResourceError&);
216 // Support iconDatabase in synchronous mode.
217 void iconLoadDecisionAvailable();
219 // Support iconDatabase in asynchronous mode.
220 void continueIconLoadWithDecision(IconLoadDecision);
221 void getIconLoadDecisionForIconURL(const String&);
222 void getIconDataForIconURL(const String&);
224 bool isLoadingMainResource() const { return m_loadingMainResource; }
225 bool isLoadingMultipartContent() const { return m_isLoadingMultipartContent; }
227 void stopLoadingPlugIns();
228 void stopLoadingSubresources();
230 void addSubresourceLoader(ResourceLoader*);
231 void removeSubresourceLoader(ResourceLoader*);
232 void addPlugInStreamLoader(ResourceLoader&);
233 void removePlugInStreamLoader(ResourceLoader&);
235 void subresourceLoaderFinishedLoadingOnePart(ResourceLoader*);
237 void setDeferMainResourceDataLoad(bool defer) { m_deferMainResourceDataLoad = defer; }
239 void didTellClientAboutLoad(const String& url)
242 // Don't include data urls here, as if a lot of data is loaded
243 // that way, we hold on to the (large) url string for too long.
244 if (protocolIs(url, "data"))
248 m_resourcesClientKnowsAbout.add(url);
250 bool haveToldClientAboutLoad(const String& url) { return m_resourcesClientKnowsAbout.contains(url); }
251 void recordMemoryCacheLoadForFutureClientNotification(const ResourceRequest&);
252 void takeMemoryCacheLoadsForClientNotification(Vector<ResourceRequest>& loads);
254 DocumentLoadTiming& timing() { return m_documentLoadTiming; }
255 void resetTiming() { m_documentLoadTiming = DocumentLoadTiming(); }
257 // The WebKit layer calls this function when it's ready for the data to
258 // actually be added to the document.
259 WEBCORE_EXPORT void commitData(const char* bytes, size_t length);
261 ApplicationCacheHost* applicationCacheHost() const { return m_applicationCacheHost.get(); }
263 void checkLoadComplete();
265 // The URL of the document resulting from this DocumentLoader.
266 URL documentURL() const;
269 void setQuickLookHandle(std::unique_ptr<QuickLookHandle> quickLookHandle) { m_quickLookHandle = WTF::move(quickLookHandle); }
270 QuickLookHandle* quickLookHandle() const { return m_quickLookHandle.get(); }
273 #if ENABLE(CONTENT_EXTENSIONS)
274 void addPendingContentExtensionSheet(const String& identifier, StyleSheetContents&);
275 void addPendingContentExtensionDisplayNoneSelector(const String& identifier, const String& selector, uint32_t selectorID);
278 void setShouldOpenExternalURLsPolicy(ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicy) { m_shouldOpenExternalURLsPolicy = shouldOpenExternalURLsPolicy; }
279 ShouldOpenExternalURLsPolicy shouldOpenExternalURLsPolicyToPropagate() const;
282 WEBCORE_EXPORT DocumentLoader(const ResourceRequest&, const SubstituteData&);
284 WEBCORE_EXPORT virtual void attachToFrame();
286 bool m_deferMainResourceDataLoad;
289 Document* document() const;
291 void setRequest(const ResourceRequest&);
293 void commitIfReady();
294 void setMainDocumentError(const ResourceError&);
295 void commitLoad(const char*, int);
296 void clearMainResourceLoader();
298 void setupForReplace();
299 void maybeFinishLoadingMultipartContent();
301 bool maybeCreateArchive();
302 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
303 void clearArchiveResources();
306 void willSendRequest(ResourceRequest&, const ResourceResponse&);
307 void finishedLoading(double finishTime);
308 void mainReceivedError(const ResourceError&);
309 WEBCORE_EXPORT virtual void redirectReceived(CachedResource*, ResourceRequest&, const ResourceResponse&) override;
310 WEBCORE_EXPORT virtual void responseReceived(CachedResource*, const ResourceResponse&) override;
311 WEBCORE_EXPORT virtual void dataReceived(CachedResource*, const char* data, int length) override;
312 WEBCORE_EXPORT virtual void notifyFinished(CachedResource*) override;
314 bool maybeLoadEmpty();
316 bool isMultipartReplacingLoad() const;
317 bool isPostOrRedirectAfterPost(const ResourceRequest&, const ResourceResponse&);
319 void continueAfterNavigationPolicy(const ResourceRequest&, bool shouldContinue);
321 void continueAfterContentPolicy(PolicyAction);
323 void stopLoadingForPolicyChange();
324 ResourceError interruptedForPolicyChangeError() const;
326 #if HAVE(RUNLOOP_TIMER)
327 typedef RunLoopTimer<DocumentLoader> DocumentLoaderTimer;
329 typedef Timer DocumentLoaderTimer;
331 void handleSubstituteDataLoadSoon();
332 void handleSubstituteDataLoadNow();
333 void startDataLoadTimer();
335 void deliverSubstituteResourcesAfterDelay();
336 void substituteResourceDeliveryTimerFired();
338 void clearMainResource();
340 void cancelPolicyCheckIfNeeded();
341 void becomeMainResourceClient();
343 #if ENABLE(CONTENT_FILTERING)
344 friend class ContentFilter;
345 void installContentFilterUnblockHandler(ContentFilter&);
346 void contentFilterDidDecide();
350 Ref<CachedResourceLoader> m_cachedResourceLoader;
352 CachedResourceHandle<CachedRawResource> m_mainResource;
353 ResourceLoaderMap m_subresourceLoaders;
354 ResourceLoaderMap m_multipartSubresourceLoaders;
355 ResourceLoaderMap m_plugInStreamLoaders;
357 mutable DocumentWriter m_writer;
359 // A reference to actual request used to create the data source.
360 // This should only be used by the resourceLoadDelegate's
361 // identifierForInitialRequest:fromDatasource: method. It is
362 // not guaranteed to remain unchanged, as requests are mutable.
363 ResourceRequest m_originalRequest;
365 SubstituteData m_substituteData;
367 // A copy of the original request used to create the data source.
368 // We have to copy the request because requests are mutable.
369 ResourceRequest m_originalRequestCopy;
371 // The 'working' request. It may be mutated
372 // several times from the original request to include additional
373 // headers, cookie information, canonicalization and redirects.
374 ResourceRequest m_request;
376 ResourceResponse m_response;
378 ResourceError m_mainDocumentError;
380 bool m_originalSubstituteDataWasValid;
384 bool m_isClientRedirect;
385 bool m_isLoadingMultipartContent;
387 // FIXME: Document::m_processingLoadEvent and DocumentLoader::m_wasOnloadHandled are roughly the same
388 // and should be merged.
389 bool m_wasOnloadHandled;
391 StringWithDirection m_pageTitle;
393 String m_overrideEncoding;
395 // The action that triggered loading - we keep this around for the
396 // benefit of the various policy handlers.
397 NavigationAction m_triggeringAction;
399 // The last request that we checked click policy for - kept around
400 // so we can avoid asking again needlessly.
401 ResourceRequest m_lastCheckedRequest;
403 // We retain all the received responses so we can play back the
404 // WebResourceLoadDelegate messages if the item is loaded from the
406 ResponseVector m_responses;
407 bool m_stopRecordingResponses;
409 typedef HashMap<RefPtr<ResourceLoader>, RefPtr<SubstituteResource>> SubstituteResourceMap;
410 SubstituteResourceMap m_pendingSubstituteResources;
411 Timer m_substituteResourceDeliveryTimer;
413 std::unique_ptr<ArchiveResourceCollection> m_archiveResourceCollection;
414 #if ENABLE(WEB_ARCHIVE) || ENABLE(MHTML)
415 RefPtr<Archive> m_archive;
416 RefPtr<SharedBuffer> m_parsedArchiveData;
419 HashSet<String> m_resourcesClientKnowsAbout;
420 Vector<ResourceRequest> m_resourcesLoadedFromMemoryCacheForClientNotification;
422 String m_clientRedirectSourceForHistory;
423 bool m_didCreateGlobalHistoryEntry;
425 bool m_loadingMainResource;
426 DocumentLoadTiming m_documentLoadTiming;
428 double m_timeOfLastDataReceived;
429 unsigned long m_identifierForLoadWithoutResourceLoader;
431 DocumentLoaderTimer m_dataLoadTimer;
432 bool m_waitingForContentPolicy;
434 RefPtr<IconLoadDecisionCallback> m_iconLoadDecisionCallback;
435 RefPtr<IconDataCallback> m_iconDataCallback;
437 bool m_subresourceLoadersArePageCacheAcceptable;
438 ShouldOpenExternalURLsPolicy m_shouldOpenExternalURLsPolicy { ShouldOpenExternalURLsPolicy::ShouldNotAllow };
440 std::unique_ptr<ApplicationCacheHost> m_applicationCacheHost;
442 #if ENABLE(CONTENT_FILTERING)
443 std::unique_ptr<ContentFilter> m_contentFilter;
447 std::unique_ptr<QuickLookHandle> m_quickLookHandle;
450 #if ENABLE(CONTENT_EXTENSIONS)
451 HashMap<String, RefPtr<StyleSheetContents>> m_pendingNamedContentExtensionStyleSheets;
452 HashMap<String, Vector<std::pair<String, uint32_t>>> m_pendingContentExtensionDisplayNoneSelectors;
456 bool m_hasEverBeenAttached { false };
460 inline void DocumentLoader::recordMemoryCacheLoadForFutureClientNotification(const ResourceRequest& request)
462 m_resourcesLoadedFromMemoryCacheForClientNotification.append(request);
465 inline void DocumentLoader::takeMemoryCacheLoadsForClientNotification(Vector<ResourceRequest>& loadsSet)
467 loadsSet.swap(m_resourcesLoadedFromMemoryCacheForClientNotification);
468 m_resourcesLoadedFromMemoryCacheForClientNotification.clear();
473 #endif // DocumentLoader_h