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 "DocumentLoadTiming.h"
33#include "DocumentWriter.h"
34#include "IconDatabaseBase.h"
35#include "NavigationAction.h"
36#include "ResourceError.h"
37#include "ResourceRequest.h"
38#include "ResourceResponse.h"
39#include "StringWithDirection.h"
40#include "SubstituteData.h"
41#include "Timer.h"
42#include <wtf/HashSet.h>
43#include <wtf/RefPtr.h>
44#include <wtf/Vector.h>
45
46namespace WebCore {
47
48    class ApplicationCacheHost;
49#if ENABLE(WEB_ARCHIVE)
50    class Archive;
51#endif
52    class ArchiveResource;
53    class ArchiveResourceCollection;
54    class Frame;
55    class FrameLoader;
56    class MainResourceLoader;
57    class Page;
58    class ResourceLoader;
59    class SchedulePair;
60    class SharedBuffer;
61    class SubstituteResource;
62
63    typedef HashSet<RefPtr<ResourceLoader> > ResourceLoaderSet;
64    typedef Vector<ResourceResponse> ResponseVector;
65
66    class DocumentLoader : public RefCounted<DocumentLoader> {
67    public:
68        static PassRefPtr<DocumentLoader> create(const ResourceRequest& request, const SubstituteData& data)
69        {
70            return adoptRef(new DocumentLoader(request, data));
71        }
72        virtual ~DocumentLoader();
73
74        void setFrame(Frame*);
75        Frame* frame() const { return m_frame; }
76
77        virtual void attachToFrame();
78        virtual void detachFromFrame();
79
80        FrameLoader* frameLoader() const;
81        MainResourceLoader* mainResourceLoader() const { return m_mainResourceLoader.get(); }
82        PassRefPtr<SharedBuffer> mainResourceData() const;
83
84        DocumentWriter* writer() const { return &m_writer; }
85
86        const ResourceRequest& originalRequest() const;
87        const ResourceRequest& originalRequestCopy() const;
88
89        const ResourceRequest& request() const;
90        ResourceRequest& request();
91        void setRequest(const ResourceRequest&);
92
93        const SubstituteData& substituteData() const { return m_substituteData; }
94
95        const KURL& url() const;
96        const KURL& unreachableURL() const;
97
98        const KURL& originalURL() const;
99        const KURL& requestURL() const;
100        const KURL& responseURL() const;
101        const String& responseMIMEType() const;
102
103        void replaceRequestURLForSameDocumentNavigation(const KURL&);
104        bool isStopping() const { return m_isStopping; }
105        void stopLoading();
106        void setCommitted(bool committed) { m_committed = committed; }
107        bool isCommitted() const { return m_committed; }
108        bool isLoading() const { return m_loading; }
109        void setLoading(bool loading) { m_loading = loading; }
110        void updateLoading();
111        void receivedData(const char*, int);
112        void setupForReplaceByMIMEType(const String& newMIMEType);
113        void finishedLoading();
114        const ResourceResponse& response() const { return m_response; }
115        const ResourceError& mainDocumentError() const { return m_mainDocumentError; }
116        void mainReceivedError(const ResourceError&, bool isComplete);
117        void setResponse(const ResourceResponse& response) { m_response = response; }
118        void prepareForLoadStart();
119        bool isClientRedirect() const { return m_isClientRedirect; }
120        void setIsClientRedirect(bool isClientRedirect) { m_isClientRedirect = isClientRedirect; }
121        void handledOnloadEvents() { m_wasOnloadHandled = true; }
122        bool wasOnloadHandled() { return m_wasOnloadHandled; }
123        bool isLoadingInAPISense() const;
124        void setPrimaryLoadComplete(bool);
125        void setTitle(const StringWithDirection&);
126        void setIconURL(const String&);
127        const String& overrideEncoding() const { return m_overrideEncoding; }
128
129#if PLATFORM(MAC)
130        void schedule(SchedulePair*);
131        void unschedule(SchedulePair*);
132#endif
133
134#if ENABLE(WEB_ARCHIVE)
135        void addAllArchiveResources(Archive*);
136        void addArchiveResource(PassRefPtr<ArchiveResource>);
137
138        PassRefPtr<Archive> popArchiveForSubframe(const String& frameName);
139        void clearArchiveResources();
140        void setParsedArchiveData(PassRefPtr<SharedBuffer>);
141        SharedBuffer* parsedArchiveData() const;
142
143        bool scheduleArchiveLoad(ResourceLoader*, const ResourceRequest&, const KURL&);
144#endif // ENABLE(WEB_ARCHIVE)
145
146        // Return the ArchiveResource for the URL only when loading an Archive
147        ArchiveResource* archiveResourceForURL(const KURL&) const;
148
149        PassRefPtr<ArchiveResource> mainResource() const;
150
151        // Return an ArchiveResource for the URL, either creating from live data or
152        // pulling from the ArchiveResourceCollection
153        PassRefPtr<ArchiveResource> subresource(const KURL&) const;
154        void getSubresources(Vector<PassRefPtr<ArchiveResource> >&) const;
155
156
157#ifndef NDEBUG
158        bool isSubstituteLoadPending(ResourceLoader*) const;
159#endif
160        void cancelPendingSubstituteLoad(ResourceLoader*);
161
162        void addResponse(const ResourceResponse&);
163        const ResponseVector& responses() const { return m_responses; }
164
165        const NavigationAction& triggeringAction() const { return m_triggeringAction; }
166        void setTriggeringAction(const NavigationAction& action) { m_triggeringAction = action; }
167        void setOverrideEncoding(const String& encoding) { m_overrideEncoding = encoding; }
168        void setLastCheckedRequest(const ResourceRequest& request) { m_lastCheckedRequest = request; }
169        const ResourceRequest& lastCheckedRequest()  { return m_lastCheckedRequest; }
170
171        void stopRecordingResponses();
172        const StringWithDirection& title() const { return m_pageTitle; }
173        const String& iconURL() const { return m_pageIconURL; }
174
175        KURL urlForHistory() const;
176        bool urlForHistoryReflectsFailure() const;
177
178        // These accessors accommodate WebCore's somewhat fickle custom of creating history
179        // items for redirects, but only sometimes. For "source" and "destination",
180        // these accessors return the URL that would have been used if a history
181        // item were created. This allows WebKit to link history items reflecting
182        // redirects into a chain from start to finish.
183        String clientRedirectSourceForHistory() const { return m_clientRedirectSourceForHistory; } // null if no client redirect occurred.
184        String clientRedirectDestinationForHistory() const { return urlForHistory(); }
185        void setClientRedirectSourceForHistory(const String& clientedirectSourceForHistory) { m_clientRedirectSourceForHistory = clientedirectSourceForHistory; }
186
187        String serverRedirectSourceForHistory() const { return urlForHistory() == url() ? String() : urlForHistory().string(); } // null if no server redirect occurred.
188        String serverRedirectDestinationForHistory() const { return url(); }
189
190        bool didCreateGlobalHistoryEntry() const { return m_didCreateGlobalHistoryEntry; }
191        void setDidCreateGlobalHistoryEntry(bool didCreateGlobalHistoryEntry) { m_didCreateGlobalHistoryEntry = didCreateGlobalHistoryEntry; }
192
193        void setDefersLoading(bool);
194
195        bool startLoadingMainResource(unsigned long identifier);
196        void cancelMainResourceLoad(const ResourceError&);
197
198        // Support iconDatabase in synchronous mode.
199        void iconLoadDecisionAvailable();
200
201        // Support iconDatabase in asynchronous mode.
202        void continueIconLoadWithDecision(IconLoadDecision);
203        void getIconLoadDecisionForIconURL(const String&);
204        void getIconDataForIconURL(const String&);
205
206        bool isLoadingMainResource() const;
207        bool isLoadingSubresources() const;
208        bool isLoadingPlugIns() const;
209        bool isLoadingMultipartContent() const;
210
211        void stopLoadingPlugIns();
212        void stopLoadingSubresources();
213
214        void addSubresourceLoader(ResourceLoader*);
215        void removeSubresourceLoader(ResourceLoader*);
216        void addPlugInStreamLoader(ResourceLoader*);
217        void removePlugInStreamLoader(ResourceLoader*);
218
219        void subresourceLoaderFinishedLoadingOnePart(ResourceLoader*);
220
221        void transferLoadingResourcesFromPage(Page*);
222
223        void setDeferMainResourceDataLoad(bool defer) { m_deferMainResourceDataLoad = defer; }
224        bool deferMainResourceDataLoad() const { return m_deferMainResourceDataLoad; }
225
226        void didTellClientAboutLoad(const String& url)
227        {
228            if (!url.isEmpty())
229                m_resourcesClientKnowsAbout.add(url);
230        }
231        bool haveToldClientAboutLoad(const String& url) { return m_resourcesClientKnowsAbout.contains(url); }
232        void recordMemoryCacheLoadForFutureClientNotification(const String& url);
233        void takeMemoryCacheLoadsForClientNotification(Vector<String>& loads);
234
235        DocumentLoadTiming* timing() { return &m_documentLoadTiming; }
236        void resetTiming() { m_documentLoadTiming = DocumentLoadTiming(); }
237
238        // The WebKit layer calls this function when it's ready for the data to
239        // actually be added to the document.
240        void commitData(const char* bytes, int length);
241
242#if ENABLE(OFFLINE_WEB_APPLICATIONS)
243        ApplicationCacheHost* applicationCacheHost() const { return m_applicationCacheHost.get(); }
244#endif
245
246    protected:
247        DocumentLoader(const ResourceRequest&, const SubstituteData&);
248
249        bool m_deferMainResourceDataLoad;
250
251    private:
252        void setupForReplace();
253        void commitIfReady();
254        void clearErrors();
255        void setMainDocumentError(const ResourceError&);
256        void commitLoad(const char*, int);
257        bool doesProgressiveLoad(const String& MIMEType) const;
258
259        void deliverSubstituteResourcesAfterDelay();
260        void substituteResourceDeliveryTimerFired(Timer<DocumentLoader>*);
261
262        Frame* m_frame;
263
264        RefPtr<MainResourceLoader> m_mainResourceLoader;
265        ResourceLoaderSet m_subresourceLoaders;
266        ResourceLoaderSet m_multipartSubresourceLoaders;
267        ResourceLoaderSet m_plugInStreamLoaders;
268
269        RefPtr<SharedBuffer> m_mainResourceData;
270
271        mutable DocumentWriter m_writer;
272
273        // A reference to actual request used to create the data source.
274        // This should only be used by the resourceLoadDelegate's
275        // identifierForInitialRequest:fromDatasource: method. It is
276        // not guaranteed to remain unchanged, as requests are mutable.
277        ResourceRequest m_originalRequest;
278
279        SubstituteData m_substituteData;
280
281        // A copy of the original request used to create the data source.
282        // We have to copy the request because requests are mutable.
283        ResourceRequest m_originalRequestCopy;
284
285        // The 'working' request. It may be mutated
286        // several times from the original request to include additional
287        // headers, cookie information, canonicalization and redirects.
288        ResourceRequest m_request;
289
290        ResourceResponse m_response;
291
292        ResourceError m_mainDocumentError;
293
294        bool m_committed;
295        bool m_isStopping;
296        bool m_loading;
297        bool m_gotFirstByte;
298        bool m_primaryLoadComplete;
299        bool m_isClientRedirect;
300        bool m_wasOnloadHandled;
301
302        StringWithDirection m_pageTitle;
303        String m_pageIconURL;
304
305        String m_overrideEncoding;
306
307        // The action that triggered loading - we keep this around for the
308        // benefit of the various policy handlers.
309        NavigationAction m_triggeringAction;
310
311        // The last request that we checked click policy for - kept around
312        // so we can avoid asking again needlessly.
313        ResourceRequest m_lastCheckedRequest;
314
315        // We retain all the received responses so we can play back the
316        // WebResourceLoadDelegate messages if the item is loaded from the
317        // page cache.
318        ResponseVector m_responses;
319        bool m_stopRecordingResponses;
320
321        typedef HashMap<RefPtr<ResourceLoader>, RefPtr<SubstituteResource> > SubstituteResourceMap;
322        SubstituteResourceMap m_pendingSubstituteResources;
323        Timer<DocumentLoader> m_substituteResourceDeliveryTimer;
324
325        OwnPtr<ArchiveResourceCollection> m_archiveResourceCollection;
326#if ENABLE(WEB_ARCHIVE)
327        RefPtr<SharedBuffer> m_parsedArchiveData;
328#endif
329
330        HashSet<String> m_resourcesClientKnowsAbout;
331        Vector<String> m_resourcesLoadedFromMemoryCacheForClientNotification;
332
333        String m_clientRedirectSourceForHistory;
334        bool m_didCreateGlobalHistoryEntry;
335
336        DocumentLoadTiming m_documentLoadTiming;
337
338        RefPtr<IconLoadDecisionCallback> m_iconLoadDecisionCallback;
339        RefPtr<IconDataCallback> m_iconDataCallback;
340
341#if ENABLE(OFFLINE_WEB_APPLICATIONS)
342        friend class ApplicationCacheHost;  // for substitute resource delivery
343        OwnPtr<ApplicationCacheHost> m_applicationCacheHost;
344#endif
345    };
346
347    inline void DocumentLoader::recordMemoryCacheLoadForFutureClientNotification(const String& url)
348    {
349        m_resourcesLoadedFromMemoryCacheForClientNotification.append(url);
350    }
351
352    inline void DocumentLoader::takeMemoryCacheLoadsForClientNotification(Vector<String>& loadsSet)
353    {
354        loadsSet.swap(m_resourcesLoadedFromMemoryCacheForClientNotification);
355        m_resourcesLoadedFromMemoryCacheForClientNotification.clear();
356    }
357
358}
359
360#endif // DocumentLoader_h
361