1/*
2    Copyright (C) 1998 Lars Knoll (knoll@mpi-hd.mpg.de)
3    Copyright (C) 2001 Dirk Mueller <mueller@kde.org>
4    Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
5    Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/
6
7    This library is free software; you can redistribute it and/or
8    modify it under the terms of the GNU Library General Public
9    License as published by the Free Software Foundation; either
10    version 2 of the License, or (at your option) any later version.
11
12    This library is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15    Library General Public License for more details.
16
17    You should have received a copy of the GNU Library General Public License
18    along with this library; see the file COPYING.LIB.  If not, write to
19    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20    Boston, MA 02110-1301, USA.
21
22    This class provides all functionality needed for loading images, style sheets and html
23    pages from the web. It has a memory cache for these objects.
24*/
25
26#ifndef ResourceFetcher_h
27#define ResourceFetcher_h
28
29#include "core/fetch/CachePolicy.h"
30#include "core/fetch/FetchInitiatorInfo.h"
31#include "core/fetch/FetchRequest.h"
32#include "core/fetch/Resource.h"
33#include "core/fetch/ResourceLoaderHost.h"
34#include "core/fetch/ResourceLoaderOptions.h"
35#include "core/fetch/ResourcePtr.h"
36#include "platform/Timer.h"
37#include "wtf/Deque.h"
38#include "wtf/HashMap.h"
39#include "wtf/HashSet.h"
40#include "wtf/ListHashSet.h"
41#include "wtf/text/StringHash.h"
42
43namespace blink {
44
45class CSSStyleSheetResource;
46class DocumentResource;
47class FetchContext;
48class FontResource;
49class ImageResource;
50class RawResource;
51class ScriptResource;
52class SubstituteData;
53class XSLStyleSheetResource;
54class Document;
55class DocumentLoader;
56class LocalFrame;
57class FrameLoader;
58class ImageLoader;
59class KURL;
60class ResourceTimingInfo;
61class ResourceLoaderSet;
62
63// The ResourceFetcher provides a per-context interface to the MemoryCache
64// and enforces a bunch of security checks and rules for resource revalidation.
65// Its lifetime is roughly per-DocumentLoader, in that it is generally created
66// in the DocumentLoader constructor and loses its ability to generate network
67// requests when the DocumentLoader is destroyed. Documents also hold a
68// RefPtr<ResourceFetcher> for their lifetime (and will create one if they
69// are initialized without a LocalFrame), so a Document can keep a ResourceFetcher
70// alive past detach if scripts still reference the Document.
71class ResourceFetcher FINAL : public RefCountedWillBeGarbageCollectedFinalized<ResourceFetcher>, public ResourceLoaderHost {
72    WTF_MAKE_NONCOPYABLE(ResourceFetcher); WTF_MAKE_FAST_ALLOCATED_WILL_BE_REMOVED;
73    WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(ResourceFetcher);
74friend class ImageLoader;
75friend class ResourceCacheValidationSuppressor;
76
77public:
78    static PassRefPtrWillBeRawPtr<ResourceFetcher> create(DocumentLoader* documentLoader) { return adoptRefWillBeNoop(new ResourceFetcher(documentLoader)); }
79    virtual ~ResourceFetcher();
80    virtual void trace(Visitor*);
81
82#if !ENABLE(OILPAN)
83    using RefCounted<ResourceFetcher>::ref;
84    using RefCounted<ResourceFetcher>::deref;
85#endif
86
87    ResourcePtr<Resource> fetchSynchronously(FetchRequest&);
88    ResourcePtr<ImageResource> fetchImage(FetchRequest&);
89    ResourcePtr<CSSStyleSheetResource> fetchCSSStyleSheet(FetchRequest&);
90    ResourcePtr<ScriptResource> fetchScript(FetchRequest&);
91    ResourcePtr<FontResource> fetchFont(FetchRequest&);
92    ResourcePtr<RawResource> fetchRawResource(FetchRequest&);
93    ResourcePtr<RawResource> fetchMainResource(FetchRequest&, const SubstituteData&);
94    ResourcePtr<DocumentResource> fetchSVGDocument(FetchRequest&);
95    ResourcePtr<XSLStyleSheetResource> fetchXSLStyleSheet(FetchRequest&);
96    ResourcePtr<Resource> fetchLinkResource(Resource::Type, FetchRequest&);
97    ResourcePtr<RawResource> fetchImport(FetchRequest&);
98    ResourcePtr<RawResource> fetchMedia(FetchRequest&);
99    ResourcePtr<RawResource> fetchTextTrack(FetchRequest&);
100
101    // Logs an access denied message to the console for the specified URL.
102    void printAccessDeniedMessage(const KURL&) const;
103
104    Resource* cachedResource(const KURL&) const;
105
106    typedef HashMap<String, ResourcePtr<Resource> > DocumentResourceMap;
107    const DocumentResourceMap& allResources() const { return m_documentResources; }
108
109    bool autoLoadImages() const { return m_autoLoadImages; }
110    void setAutoLoadImages(bool);
111
112    void setImagesEnabled(bool);
113
114    bool shouldDeferImageLoad(const KURL&) const;
115
116    LocalFrame* frame() const; // Can be null
117    FetchContext& context() const;
118    Document* document() const { return m_document; } // Can be null
119    void setDocument(RawPtr<Document> document) { m_document = document; }
120
121    DocumentLoader* documentLoader() const { return m_documentLoader; }
122    void clearDocumentLoader() { m_documentLoader = 0; }
123
124    void garbageCollectDocumentResources();
125
126    int requestCount() const { return m_requestCount; }
127
128    bool isPreloaded(const String& urlString) const;
129    void clearPreloads();
130    void preload(Resource::Type, FetchRequest&, const String& charset);
131    void printPreloadStats();
132
133    void setDefersLoading(bool);
134    void stopFetching();
135    bool isFetching() const;
136
137    // ResourceLoaderHost
138    virtual void incrementRequestCount(const Resource*) OVERRIDE;
139    virtual void decrementRequestCount(const Resource*) OVERRIDE;
140    virtual void didLoadResource(Resource*) OVERRIDE;
141    virtual void redirectReceived(Resource*, const ResourceResponse&) OVERRIDE;
142    virtual void didFinishLoading(const Resource*, double finishTime, int64_t encodedDataLength) OVERRIDE;
143    virtual void didChangeLoadingPriority(const Resource*, ResourceLoadPriority, int intraPriorityValue) OVERRIDE;
144    virtual void didFailLoading(const Resource*, const ResourceError&) OVERRIDE;
145    virtual void willSendRequest(unsigned long identifier, ResourceRequest&, const ResourceResponse& redirectResponse, const FetchInitiatorInfo&) OVERRIDE;
146    virtual void didReceiveResponse(const Resource*, const ResourceResponse&) OVERRIDE;
147    virtual void didReceiveData(const Resource*, const char* data, int dataLength, int encodedDataLength) OVERRIDE;
148    virtual void didDownloadData(const Resource*, int dataLength, int encodedDataLength) OVERRIDE;
149    virtual void subresourceLoaderFinishedLoadingOnePart(ResourceLoader*) OVERRIDE;
150    virtual void didInitializeResourceLoader(ResourceLoader*) OVERRIDE;
151    virtual void willTerminateResourceLoader(ResourceLoader*) OVERRIDE;
152    virtual void willStartLoadingResource(Resource*, ResourceRequest&) OVERRIDE;
153    virtual bool defersLoading() const OVERRIDE;
154    virtual bool isLoadedBy(ResourceLoaderHost*) const OVERRIDE;
155    virtual bool canAccessRedirect(Resource*, ResourceRequest&, const ResourceResponse&, ResourceLoaderOptions&) OVERRIDE;
156    virtual bool canAccessResource(Resource*, SecurityOrigin*, const KURL&) const OVERRIDE;
157
158#if !ENABLE(OILPAN)
159    virtual void refResourceLoaderHost() OVERRIDE;
160    virtual void derefResourceLoaderHost() OVERRIDE;
161#endif
162
163    enum ResourceLoadStartType {
164        ResourceLoadingFromNetwork,
165        ResourceLoadingFromCache
166    };
167    void requestLoadStarted(Resource*, const FetchRequest&, ResourceLoadStartType);
168    static const ResourceLoaderOptions& defaultResourceOptions();
169private:
170
171    explicit ResourceFetcher(DocumentLoader*);
172
173    bool shouldLoadNewResource(Resource::Type) const;
174
175    ResourcePtr<Resource> requestResource(Resource::Type, FetchRequest&);
176    ResourcePtr<Resource> createResourceForRevalidation(const FetchRequest&, Resource*);
177    ResourcePtr<Resource> createResourceForLoading(Resource::Type, FetchRequest&, const String& charset);
178    void preCacheDataURIImage(const FetchRequest&);
179    void preCacheSubstituteDataForMainResource(const FetchRequest&, const SubstituteData&);
180    void storeResourceTimingInitiatorInformation(Resource*);
181    void requestPreload(Resource::Type, FetchRequest&, const String& charset);
182
183    enum RevalidationPolicy { Use, Revalidate, Reload, Load };
184    RevalidationPolicy determineRevalidationPolicy(Resource::Type, const FetchRequest&, Resource* existingResource) const;
185
186    void determineRequestContext(ResourceRequest&, Resource::Type);
187    ResourceRequestCachePolicy resourceRequestCachePolicy(const ResourceRequest&, Resource::Type);
188    void addAdditionalRequestHeaders(ResourceRequest&, Resource::Type);
189
190    bool canRequest(Resource::Type, const ResourceRequest&, const KURL&, const ResourceLoaderOptions&, bool forPreload, FetchRequest::OriginRestriction) const;
191
192    static bool resourceNeedsLoad(Resource*, const FetchRequest&, RevalidationPolicy);
193
194    void notifyLoadedFromMemoryCache(Resource*);
195
196    void garbageCollectDocumentResourcesTimerFired(Timer<ResourceFetcher>*);
197    void scheduleDocumentResourcesGC();
198
199    void resourceTimingReportTimerFired(Timer<ResourceFetcher>*);
200
201    bool clientDefersImage(const KURL&) const;
202    void reloadImagesIfNotDeferred();
203
204    HashSet<String> m_validatedURLs;
205    mutable DocumentResourceMap m_documentResources;
206    // FIXME: Oilpan: Ideally this should just be a traced Member but that will
207    // currently leak because RenderStyle and its data are not on the heap.
208    // See crbug.com/383860 for details.
209    RawPtrWillBeWeakMember<Document> m_document;
210    DocumentLoader* m_documentLoader;
211
212    int m_requestCount;
213
214    OwnPtr<ListHashSet<Resource*> > m_preloads;
215
216    Timer<ResourceFetcher> m_garbageCollectDocumentResourcesTimer;
217    Timer<ResourceFetcher> m_resourceTimingReportTimer;
218
219    typedef HashMap<Resource*, RefPtr<ResourceTimingInfo> > ResourceTimingInfoMap;
220    ResourceTimingInfoMap m_resourceTimingInfoMap;
221
222    HashMap<RefPtr<ResourceTimingInfo>, bool> m_scheduledResourceTimingReports;
223
224    OwnPtrWillBeMember<ResourceLoaderSet> m_loaders;
225    OwnPtrWillBeMember<ResourceLoaderSet> m_multipartLoaders;
226
227    // Used in hit rate histograms.
228    class DeadResourceStatsRecorder {
229    public:
230        DeadResourceStatsRecorder();
231        ~DeadResourceStatsRecorder();
232
233        void update(RevalidationPolicy);
234
235    private:
236        int m_useCount;
237        int m_revalidateCount;
238        int m_loadCount;
239    };
240    DeadResourceStatsRecorder m_deadStatsRecorder;
241
242    // 29 bits left
243    bool m_autoLoadImages : 1;
244    bool m_imagesEnabled : 1;
245    bool m_allowStaleResources : 1;
246};
247
248class ResourceCacheValidationSuppressor {
249    WTF_MAKE_NONCOPYABLE(ResourceCacheValidationSuppressor);
250    WTF_MAKE_FAST_ALLOCATED;
251public:
252    ResourceCacheValidationSuppressor(ResourceFetcher* loader)
253        : m_loader(loader)
254        , m_previousState(false)
255    {
256        if (m_loader) {
257            m_previousState = m_loader->m_allowStaleResources;
258            m_loader->m_allowStaleResources = true;
259        }
260    }
261    ~ResourceCacheValidationSuppressor()
262    {
263        if (m_loader)
264            m_loader->m_allowStaleResources = m_previousState;
265    }
266private:
267    ResourceFetcher* m_loader;
268    bool m_previousState;
269};
270
271} // namespace blink
272
273#endif
274