• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2004, 2006, 2007, 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 COMPUTER, 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 COMPUTER, 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 #include "config.h"
27 #include "ResourceHandle.h"
28 #include "ResourceHandleInternal.h"
29 
30 #include "BlobRegistry.h"
31 #include "DNS.h"
32 #include "Logging.h"
33 #include "ResourceHandleClient.h"
34 #include "Timer.h"
35 #include <algorithm>
36 #include <wtf/text/CString.h>
37 
38 namespace WebCore {
39 
40 static bool shouldForceContentSniffing;
41 
ResourceHandle(const ResourceRequest & request,ResourceHandleClient * client,bool defersLoading,bool shouldContentSniff)42 ResourceHandle::ResourceHandle(const ResourceRequest& request, ResourceHandleClient* client, bool defersLoading, bool shouldContentSniff)
43     : d(new ResourceHandleInternal(this, request, client, defersLoading, shouldContentSniff && shouldContentSniffURL(request.url())))
44 {
45     if (!request.url().isValid()) {
46         scheduleFailure(InvalidURLFailure);
47         return;
48     }
49 
50     if (!portAllowed(request.url())) {
51         scheduleFailure(BlockedFailure);
52         return;
53     }
54 }
55 
create(NetworkingContext * context,const ResourceRequest & request,ResourceHandleClient * client,bool defersLoading,bool shouldContentSniff)56 PassRefPtr<ResourceHandle> ResourceHandle::create(NetworkingContext* context, const ResourceRequest& request, ResourceHandleClient* client, bool defersLoading, bool shouldContentSniff)
57 {
58 #if ENABLE(BLOB)
59     if (request.url().protocolIs("blob")) {
60         PassRefPtr<ResourceHandle> handle = blobRegistry().createResourceHandle(request, client);
61         if (handle)
62             return handle;
63     }
64 #endif
65 
66     RefPtr<ResourceHandle> newHandle(adoptRef(new ResourceHandle(request, client, defersLoading, shouldContentSniff)));
67 
68     if (newHandle->d->m_scheduledFailureType != NoFailure)
69         return newHandle.release();
70 
71     if (newHandle->start(context))
72         return newHandle.release();
73 
74     return 0;
75 }
76 
scheduleFailure(FailureType type)77 void ResourceHandle::scheduleFailure(FailureType type)
78 {
79     d->m_scheduledFailureType = type;
80     d->m_failureTimer.startOneShot(0);
81 }
82 
fireFailure(Timer<ResourceHandle> *)83 void ResourceHandle::fireFailure(Timer<ResourceHandle>*)
84 {
85     if (!client())
86         return;
87 
88     switch (d->m_scheduledFailureType) {
89         case NoFailure:
90             ASSERT_NOT_REACHED();
91             return;
92         case BlockedFailure:
93             d->m_scheduledFailureType = NoFailure;
94             client()->wasBlocked(this);
95             return;
96         case InvalidURLFailure:
97             d->m_scheduledFailureType = NoFailure;
98             client()->cannotShowURL(this);
99             return;
100     }
101 
102     ASSERT_NOT_REACHED();
103 }
104 
client() const105 ResourceHandleClient* ResourceHandle::client() const
106 {
107     return d->m_client;
108 }
109 
setClient(ResourceHandleClient * client)110 void ResourceHandle::setClient(ResourceHandleClient* client)
111 {
112     d->m_client = client;
113 }
114 
firstRequest()115 ResourceRequest& ResourceHandle::firstRequest()
116 {
117     return d->m_firstRequest;
118 }
119 
lastHTTPMethod() const120 const String& ResourceHandle::lastHTTPMethod() const
121 {
122     return d->m_lastHTTPMethod;
123 }
124 
hasAuthenticationChallenge() const125 bool ResourceHandle::hasAuthenticationChallenge() const
126 {
127     return !d->m_currentWebChallenge.isNull();
128 }
129 
clearAuthentication()130 void ResourceHandle::clearAuthentication()
131 {
132 #if PLATFORM(MAC)
133     d->m_currentMacChallenge = nil;
134 #endif
135     d->m_currentWebChallenge.nullify();
136 }
137 
shouldContentSniff() const138 bool ResourceHandle::shouldContentSniff() const
139 {
140     return d->m_shouldContentSniff;
141 }
142 
shouldContentSniffURL(const KURL & url)143 bool ResourceHandle::shouldContentSniffURL(const KURL& url)
144 {
145 #if PLATFORM(MAC)
146     if (shouldForceContentSniffing)
147         return true;
148 #endif
149     // We shouldn't content sniff file URLs as their MIME type should be established via their extension.
150     return !url.protocolIs("file");
151 }
152 
forceContentSniffing()153 void ResourceHandle::forceContentSniffing()
154 {
155     shouldForceContentSniffing = true;
156 }
157 
setDefersLoading(bool defers)158 void ResourceHandle::setDefersLoading(bool defers)
159 {
160     LOG(Network, "Handle %p setDefersLoading(%s)", this, defers ? "true" : "false");
161 
162     ASSERT(d->m_defersLoading != defers); // Deferring is not counted, so calling setDefersLoading() repeatedly is likely to be in error.
163     d->m_defersLoading = defers;
164 
165     if (defers) {
166         ASSERT(d->m_failureTimer.isActive() == (d->m_scheduledFailureType != NoFailure));
167         if (d->m_failureTimer.isActive())
168             d->m_failureTimer.stop();
169     } else if (d->m_scheduledFailureType != NoFailure) {
170         ASSERT(!d->m_failureTimer.isActive());
171         d->m_failureTimer.startOneShot(0);
172     }
173 
174     platformSetDefersLoading(defers);
175 }
176 
177 #if !USE(SOUP)
prepareForURL(const KURL & url)178 void ResourceHandle::prepareForURL(const KURL& url)
179 {
180     return prefetchDNS(url.host());
181 }
182 #endif
183 
cacheMetadata(const ResourceResponse &,const Vector<char> &)184 void ResourceHandle::cacheMetadata(const ResourceResponse&, const Vector<char>&)
185 {
186     // Optionally implemented by platform.
187 }
188 
189 #if USE(CFURLSTORAGESESSIONS)
190 
privateStorageSession()191 static RetainPtr<CFURLStorageSessionRef>& privateStorageSession()
192 {
193     DEFINE_STATIC_LOCAL(RetainPtr<CFURLStorageSessionRef>, storageSession, ());
194     return storageSession;
195 }
196 
privateBrowsingStorageSessionIdentifierBase()197 static String& privateBrowsingStorageSessionIdentifierBase()
198 {
199     DEFINE_STATIC_LOCAL(String, base, ());
200     return base;
201 }
202 
setPrivateBrowsingEnabled(bool enabled)203 void ResourceHandle::setPrivateBrowsingEnabled(bool enabled)
204 {
205     if (!enabled) {
206         privateStorageSession() = nullptr;
207         return;
208     }
209 
210     if (privateStorageSession())
211         return;
212 
213     String base = privateBrowsingStorageSessionIdentifierBase().isNull() ? privateBrowsingStorageSessionIdentifierDefaultBase() : privateBrowsingStorageSessionIdentifierBase();
214     RetainPtr<CFStringRef> cfIdentifier(AdoptCF, String::format("%s.PrivateBrowsing", base.utf8().data()).createCFString());
215 
216     privateStorageSession() = createPrivateBrowsingStorageSession(cfIdentifier.get());
217 }
218 
privateBrowsingStorageSession()219 CFURLStorageSessionRef ResourceHandle::privateBrowsingStorageSession()
220 {
221     return privateStorageSession().get();
222 }
223 
setPrivateBrowsingStorageSessionIdentifierBase(const String & identifier)224 void ResourceHandle::setPrivateBrowsingStorageSessionIdentifierBase(const String& identifier)
225 {
226     privateBrowsingStorageSessionIdentifierBase() = identifier;
227 }
228 
229 #endif // USE(CFURLSTORAGESESSIONS)
230 
231 } // namespace WebCore
232