• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2003, 2006 Apple Computer, Inc.  All rights reserved.
3  * Copyright (C) 2009, 2012 Google Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include "config.h"
28 #include "platform/network/ResourceRequest.h"
29 #include "platform/weborigin/SecurityOrigin.h"
30 #include "public/platform/WebURLRequest.h"
31 
32 namespace blink {
33 
34 double ResourceRequest::s_defaultTimeoutInterval = INT_MAX;
35 
adopt(PassOwnPtr<CrossThreadResourceRequestData> data)36 PassOwnPtr<ResourceRequest> ResourceRequest::adopt(PassOwnPtr<CrossThreadResourceRequestData> data)
37 {
38     OwnPtr<ResourceRequest> request = adoptPtr(new ResourceRequest());
39     request->setURL(data->m_url);
40     request->setCachePolicy(data->m_cachePolicy);
41     request->setTimeoutInterval(data->m_timeoutInterval);
42     request->setFirstPartyForCookies(data->m_firstPartyForCookies);
43     request->setHTTPMethod(AtomicString(data->m_httpMethod));
44     request->setPriority(data->m_priority, data->m_intraPriorityValue);
45 
46     request->m_httpHeaderFields.adopt(data->m_httpHeaders.release());
47 
48     request->setHTTPBody(data->m_httpBody);
49     request->setAllowStoredCredentials(data->m_allowStoredCredentials);
50     request->setReportUploadProgress(data->m_reportUploadProgress);
51     request->setHasUserGesture(data->m_hasUserGesture);
52     request->setDownloadToFile(data->m_downloadToFile);
53     request->setSkipServiceWorker(data->m_skipServiceWorker);
54     request->setRequestorID(data->m_requestorID);
55     request->setRequestorProcessID(data->m_requestorProcessID);
56     request->setAppCacheHostID(data->m_appCacheHostID);
57     request->setRequestContext(data->m_requestContext);
58     request->setFrameType(data->m_frameType);
59     request->m_referrerPolicy = data->m_referrerPolicy;
60     return request.release();
61 }
62 
copyData() const63 PassOwnPtr<CrossThreadResourceRequestData> ResourceRequest::copyData() const
64 {
65     OwnPtr<CrossThreadResourceRequestData> data = adoptPtr(new CrossThreadResourceRequestData());
66     data->m_url = url().copy();
67     data->m_cachePolicy = cachePolicy();
68     data->m_timeoutInterval = timeoutInterval();
69     data->m_firstPartyForCookies = firstPartyForCookies().copy();
70     data->m_httpMethod = httpMethod().string().isolatedCopy();
71     data->m_httpHeaders = httpHeaderFields().copyData();
72     data->m_priority = priority();
73     data->m_intraPriorityValue = m_intraPriorityValue;
74 
75     if (m_httpBody)
76         data->m_httpBody = m_httpBody->deepCopy();
77     data->m_allowStoredCredentials = m_allowStoredCredentials;
78     data->m_reportUploadProgress = m_reportUploadProgress;
79     data->m_hasUserGesture = m_hasUserGesture;
80     data->m_downloadToFile = m_downloadToFile;
81     data->m_skipServiceWorker = m_skipServiceWorker;
82     data->m_requestorID = m_requestorID;
83     data->m_requestorProcessID = m_requestorProcessID;
84     data->m_appCacheHostID = m_appCacheHostID;
85     data->m_requestContext = m_requestContext;
86     data->m_frameType = m_frameType;
87     data->m_referrerPolicy = m_referrerPolicy;
88     return data.release();
89 }
90 
isEmpty() const91 bool ResourceRequest::isEmpty() const
92 {
93     return m_url.isEmpty();
94 }
95 
isNull() const96 bool ResourceRequest::isNull() const
97 {
98     return m_url.isNull();
99 }
100 
url() const101 const KURL& ResourceRequest::url() const
102 {
103     return m_url;
104 }
105 
setURL(const KURL & url)106 void ResourceRequest::setURL(const KURL& url)
107 {
108     m_url = url;
109 }
110 
removeCredentials()111 void ResourceRequest::removeCredentials()
112 {
113     if (m_url.user().isEmpty() && m_url.pass().isEmpty())
114         return;
115 
116     m_url.setUser(String());
117     m_url.setPass(String());
118 }
119 
cachePolicy() const120 ResourceRequestCachePolicy ResourceRequest::cachePolicy() const
121 {
122     return m_cachePolicy;
123 }
124 
setCachePolicy(ResourceRequestCachePolicy cachePolicy)125 void ResourceRequest::setCachePolicy(ResourceRequestCachePolicy cachePolicy)
126 {
127     m_cachePolicy = cachePolicy;
128 }
129 
timeoutInterval() const130 double ResourceRequest::timeoutInterval() const
131 {
132     return m_timeoutInterval;
133 }
134 
setTimeoutInterval(double timeoutInterval)135 void ResourceRequest::setTimeoutInterval(double timeoutInterval)
136 {
137     m_timeoutInterval = timeoutInterval;
138 }
139 
firstPartyForCookies() const140 const KURL& ResourceRequest::firstPartyForCookies() const
141 {
142     return m_firstPartyForCookies;
143 }
144 
setFirstPartyForCookies(const KURL & firstPartyForCookies)145 void ResourceRequest::setFirstPartyForCookies(const KURL& firstPartyForCookies)
146 {
147     m_firstPartyForCookies = firstPartyForCookies;
148 }
149 
httpMethod() const150 const AtomicString& ResourceRequest::httpMethod() const
151 {
152     return m_httpMethod;
153 }
154 
setHTTPMethod(const AtomicString & httpMethod)155 void ResourceRequest::setHTTPMethod(const AtomicString& httpMethod)
156 {
157     m_httpMethod = httpMethod;
158 }
159 
httpHeaderFields() const160 const HTTPHeaderMap& ResourceRequest::httpHeaderFields() const
161 {
162     return m_httpHeaderFields;
163 }
164 
httpHeaderField(const AtomicString & name) const165 const AtomicString& ResourceRequest::httpHeaderField(const AtomicString& name) const
166 {
167     return m_httpHeaderFields.get(name);
168 }
169 
httpHeaderField(const char * name) const170 const AtomicString& ResourceRequest::httpHeaderField(const char* name) const
171 {
172     return m_httpHeaderFields.get(name);
173 }
174 
setHTTPHeaderField(const AtomicString & name,const AtomicString & value)175 void ResourceRequest::setHTTPHeaderField(const AtomicString& name, const AtomicString& value)
176 {
177     m_httpHeaderFields.set(name, value);
178 }
179 
setHTTPHeaderField(const char * name,const AtomicString & value)180 void ResourceRequest::setHTTPHeaderField(const char* name, const AtomicString& value)
181 {
182     setHTTPHeaderField(AtomicString(name), value);
183 }
184 
clearHTTPAuthorization()185 void ResourceRequest::clearHTTPAuthorization()
186 {
187     m_httpHeaderFields.remove("Authorization");
188 }
189 
clearHTTPReferrer()190 void ResourceRequest::clearHTTPReferrer()
191 {
192     m_httpHeaderFields.remove("Referer");
193     m_referrerPolicy = ReferrerPolicyDefault;
194 }
195 
clearHTTPOrigin()196 void ResourceRequest::clearHTTPOrigin()
197 {
198     m_httpHeaderFields.remove("Origin");
199 }
200 
addHTTPOriginIfNeeded(const AtomicString & origin)201 void ResourceRequest::addHTTPOriginIfNeeded(const AtomicString& origin)
202 {
203     if (!httpOrigin().isEmpty())
204         return; // Request already has an Origin header.
205 
206     // Don't send an Origin header for GET or HEAD to avoid privacy issues.
207     // For example, if an intranet page has a hyperlink to an external web
208     // site, we don't want to include the Origin of the request because it
209     // will leak the internal host name. Similar privacy concerns have lead
210     // to the widespread suppression of the Referer header at the network
211     // layer.
212     if (httpMethod() == "GET" || httpMethod() == "HEAD")
213         return;
214 
215     // For non-GET and non-HEAD methods, always send an Origin header so the
216     // server knows we support this feature.
217 
218     if (origin.isEmpty()) {
219         // If we don't know what origin header to attach, we attach the value
220         // for an empty origin.
221         setHTTPOrigin(SecurityOrigin::createUnique()->toAtomicString());
222         return;
223     }
224     setHTTPOrigin(origin);
225 }
226 
clearHTTPUserAgent()227 void ResourceRequest::clearHTTPUserAgent()
228 {
229     m_httpHeaderFields.remove("User-Agent");
230 }
231 
httpBody() const232 FormData* ResourceRequest::httpBody() const
233 {
234     return m_httpBody.get();
235 }
236 
setHTTPBody(PassRefPtr<FormData> httpBody)237 void ResourceRequest::setHTTPBody(PassRefPtr<FormData> httpBody)
238 {
239     m_httpBody = httpBody;
240 }
241 
allowStoredCredentials() const242 bool ResourceRequest::allowStoredCredentials() const
243 {
244     return m_allowStoredCredentials;
245 }
246 
setAllowStoredCredentials(bool allowCredentials)247 void ResourceRequest::setAllowStoredCredentials(bool allowCredentials)
248 {
249     m_allowStoredCredentials = allowCredentials;
250 }
251 
priority() const252 ResourceLoadPriority ResourceRequest::priority() const
253 {
254     return m_priority;
255 }
256 
setPriority(ResourceLoadPriority priority,int intraPriorityValue)257 void ResourceRequest::setPriority(ResourceLoadPriority priority, int intraPriorityValue)
258 {
259     m_priority = priority;
260     m_intraPriorityValue = intraPriorityValue;
261 }
262 
addHTTPHeaderField(const AtomicString & name,const AtomicString & value)263 void ResourceRequest::addHTTPHeaderField(const AtomicString& name, const AtomicString& value)
264 {
265     HTTPHeaderMap::AddResult result = m_httpHeaderFields.add(name, value);
266     if (!result.isNewEntry)
267         result.storedValue->value = result.storedValue->value + ',' + value;
268 }
269 
addHTTPHeaderFields(const HTTPHeaderMap & headerFields)270 void ResourceRequest::addHTTPHeaderFields(const HTTPHeaderMap& headerFields)
271 {
272     HTTPHeaderMap::const_iterator end = headerFields.end();
273     for (HTTPHeaderMap::const_iterator it = headerFields.begin(); it != end; ++it)
274         addHTTPHeaderField(it->key, it->value);
275 }
276 
clearHTTPHeaderField(const AtomicString & name)277 void ResourceRequest::clearHTTPHeaderField(const AtomicString& name)
278 {
279     m_httpHeaderFields.remove(name);
280 }
281 
equalIgnoringHeaderFields(const ResourceRequest & a,const ResourceRequest & b)282 bool equalIgnoringHeaderFields(const ResourceRequest& a, const ResourceRequest& b)
283 {
284     if (a.url() != b.url())
285         return false;
286 
287     if (a.cachePolicy() != b.cachePolicy())
288         return false;
289 
290     if (a.timeoutInterval() != b.timeoutInterval())
291         return false;
292 
293     if (a.firstPartyForCookies() != b.firstPartyForCookies())
294         return false;
295 
296     if (a.httpMethod() != b.httpMethod())
297         return false;
298 
299     if (a.allowStoredCredentials() != b.allowStoredCredentials())
300         return false;
301 
302     if (a.priority() != b.priority())
303         return false;
304 
305     if (a.referrerPolicy() != b.referrerPolicy())
306         return false;
307 
308     FormData* formDataA = a.httpBody();
309     FormData* formDataB = b.httpBody();
310 
311     if (!formDataA)
312         return !formDataB;
313     if (!formDataB)
314         return !formDataA;
315 
316     if (*formDataA != *formDataB)
317         return false;
318 
319     return true;
320 }
321 
compare(const ResourceRequest & a,const ResourceRequest & b)322 bool ResourceRequest::compare(const ResourceRequest& a, const ResourceRequest& b)
323 {
324     if (!equalIgnoringHeaderFields(a, b))
325         return false;
326 
327     if (a.httpHeaderFields() != b.httpHeaderFields())
328         return false;
329 
330     return true;
331 }
332 
isConditional() const333 bool ResourceRequest::isConditional() const
334 {
335     return (m_httpHeaderFields.contains("If-Match")
336         || m_httpHeaderFields.contains("If-Modified-Since")
337         || m_httpHeaderFields.contains("If-None-Match")
338         || m_httpHeaderFields.contains("If-Range")
339         || m_httpHeaderFields.contains("If-Unmodified-Since"));
340 }
341 
342 
cacheControlHeaderString()343 static const AtomicString& cacheControlHeaderString()
344 {
345     DEFINE_STATIC_LOCAL(const AtomicString, cacheControlHeader, ("cache-control", AtomicString::ConstructFromLiteral));
346     return cacheControlHeader;
347 }
348 
pragmaHeaderString()349 static const AtomicString& pragmaHeaderString()
350 {
351     DEFINE_STATIC_LOCAL(const AtomicString, pragmaHeader, ("pragma", AtomicString::ConstructFromLiteral));
352     return pragmaHeader;
353 }
354 
cacheControlHeader() const355 const CacheControlHeader& ResourceRequest::cacheControlHeader() const
356 {
357     if (!m_cacheControlHeaderCache.parsed)
358         m_cacheControlHeaderCache = parseCacheControlDirectives(m_httpHeaderFields.get(cacheControlHeaderString()), m_httpHeaderFields.get(pragmaHeaderString()));
359     return m_cacheControlHeaderCache;
360 }
361 
cacheControlContainsNoCache() const362 bool ResourceRequest::cacheControlContainsNoCache() const
363 {
364     return cacheControlHeader().containsNoCache;
365 }
366 
cacheControlContainsNoStore() const367 bool ResourceRequest::cacheControlContainsNoStore() const
368 {
369     return cacheControlHeader().containsNoStore;
370 }
371 
hasCacheValidatorFields() const372 bool ResourceRequest::hasCacheValidatorFields() const
373 {
374     DEFINE_STATIC_LOCAL(const AtomicString, lastModifiedHeader, ("last-modified", AtomicString::ConstructFromLiteral));
375     DEFINE_STATIC_LOCAL(const AtomicString, eTagHeader, ("etag", AtomicString::ConstructFromLiteral));
376     return !m_httpHeaderFields.get(lastModifiedHeader).isEmpty() || !m_httpHeaderFields.get(eTagHeader).isEmpty();
377 }
378 
defaultTimeoutInterval()379 double ResourceRequest::defaultTimeoutInterval()
380 {
381     return s_defaultTimeoutInterval;
382 }
383 
setDefaultTimeoutInterval(double timeoutInterval)384 void ResourceRequest::setDefaultTimeoutInterval(double timeoutInterval)
385 {
386     s_defaultTimeoutInterval = timeoutInterval;
387 }
388 
initialize(const KURL & url,ResourceRequestCachePolicy cachePolicy)389 void ResourceRequest::initialize(const KURL& url, ResourceRequestCachePolicy cachePolicy)
390 {
391     m_url = url;
392     m_cachePolicy = cachePolicy;
393     m_timeoutInterval = s_defaultTimeoutInterval;
394     m_httpMethod = "GET";
395     m_allowStoredCredentials = true;
396     m_reportUploadProgress = false;
397     m_reportRawHeaders = false;
398     m_hasUserGesture = false;
399     m_downloadToFile = false;
400     m_skipServiceWorker = false;
401     m_priority = ResourceLoadPriorityLow;
402     m_intraPriorityValue = 0;
403     m_requestorID = 0;
404     m_requestorProcessID = 0;
405     m_appCacheHostID = 0;
406     m_requestContext = blink::WebURLRequest::RequestContextUnspecified;
407     m_frameType = blink::WebURLRequest::FrameTypeNone;
408     m_referrerPolicy = ReferrerPolicyDefault;
409 }
410 
411 // This is used by the loader to control the number of issued parallel load requests.
initializeMaximumHTTPConnectionCountPerHost()412 unsigned initializeMaximumHTTPConnectionCountPerHost()
413 {
414     // The chromium network stack already handles limiting the number of
415     // parallel requests per host, so there's no need to do it here.  Therefore,
416     // this is set to a high value that should never be hit in practice.
417     return 10000;
418 }
419 
420 }
421