Home | History | Annotate | Download | only in network
      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 
     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 
     63 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 
     91 bool ResourceRequest::isEmpty() const
     92 {
     93     return m_url.isEmpty();
     94 }
     95 
     96 bool ResourceRequest::isNull() const
     97 {
     98     return m_url.isNull();
     99 }
    100 
    101 const KURL& ResourceRequest::url() const
    102 {
    103     return m_url;
    104 }
    105 
    106 void ResourceRequest::setURL(const KURL& url)
    107 {
    108     m_url = url;
    109 }
    110 
    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 
    120 ResourceRequestCachePolicy ResourceRequest::cachePolicy() const
    121 {
    122     return m_cachePolicy;
    123 }
    124 
    125 void ResourceRequest::setCachePolicy(ResourceRequestCachePolicy cachePolicy)
    126 {
    127     m_cachePolicy = cachePolicy;
    128 }
    129 
    130 double ResourceRequest::timeoutInterval() const
    131 {
    132     return m_timeoutInterval;
    133 }
    134 
    135 void ResourceRequest::setTimeoutInterval(double timeoutInterval)
    136 {
    137     m_timeoutInterval = timeoutInterval;
    138 }
    139 
    140 const KURL& ResourceRequest::firstPartyForCookies() const
    141 {
    142     return m_firstPartyForCookies;
    143 }
    144 
    145 void ResourceRequest::setFirstPartyForCookies(const KURL& firstPartyForCookies)
    146 {
    147     m_firstPartyForCookies = firstPartyForCookies;
    148 }
    149 
    150 const AtomicString& ResourceRequest::httpMethod() const
    151 {
    152     return m_httpMethod;
    153 }
    154 
    155 void ResourceRequest::setHTTPMethod(const AtomicString& httpMethod)
    156 {
    157     m_httpMethod = httpMethod;
    158 }
    159 
    160 const HTTPHeaderMap& ResourceRequest::httpHeaderFields() const
    161 {
    162     return m_httpHeaderFields;
    163 }
    164 
    165 const AtomicString& ResourceRequest::httpHeaderField(const AtomicString& name) const
    166 {
    167     return m_httpHeaderFields.get(name);
    168 }
    169 
    170 const AtomicString& ResourceRequest::httpHeaderField(const char* name) const
    171 {
    172     return m_httpHeaderFields.get(name);
    173 }
    174 
    175 void ResourceRequest::setHTTPHeaderField(const AtomicString& name, const AtomicString& value)
    176 {
    177     m_httpHeaderFields.set(name, value);
    178 }
    179 
    180 void ResourceRequest::setHTTPHeaderField(const char* name, const AtomicString& value)
    181 {
    182     setHTTPHeaderField(AtomicString(name), value);
    183 }
    184 
    185 void ResourceRequest::clearHTTPAuthorization()
    186 {
    187     m_httpHeaderFields.remove("Authorization");
    188 }
    189 
    190 void ResourceRequest::clearHTTPReferrer()
    191 {
    192     m_httpHeaderFields.remove("Referer");
    193     m_referrerPolicy = ReferrerPolicyDefault;
    194 }
    195 
    196 void ResourceRequest::clearHTTPOrigin()
    197 {
    198     m_httpHeaderFields.remove("Origin");
    199 }
    200 
    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 
    227 void ResourceRequest::clearHTTPUserAgent()
    228 {
    229     m_httpHeaderFields.remove("User-Agent");
    230 }
    231 
    232 FormData* ResourceRequest::httpBody() const
    233 {
    234     return m_httpBody.get();
    235 }
    236 
    237 void ResourceRequest::setHTTPBody(PassRefPtr<FormData> httpBody)
    238 {
    239     m_httpBody = httpBody;
    240 }
    241 
    242 bool ResourceRequest::allowStoredCredentials() const
    243 {
    244     return m_allowStoredCredentials;
    245 }
    246 
    247 void ResourceRequest::setAllowStoredCredentials(bool allowCredentials)
    248 {
    249     m_allowStoredCredentials = allowCredentials;
    250 }
    251 
    252 ResourceLoadPriority ResourceRequest::priority() const
    253 {
    254     return m_priority;
    255 }
    256 
    257 void ResourceRequest::setPriority(ResourceLoadPriority priority, int intraPriorityValue)
    258 {
    259     m_priority = priority;
    260     m_intraPriorityValue = intraPriorityValue;
    261 }
    262 
    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 
    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 
    277 void ResourceRequest::clearHTTPHeaderField(const AtomicString& name)
    278 {
    279     m_httpHeaderFields.remove(name);
    280 }
    281 
    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 
    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 
    333 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 
    343 static const AtomicString& cacheControlHeaderString()
    344 {
    345     DEFINE_STATIC_LOCAL(const AtomicString, cacheControlHeader, ("cache-control", AtomicString::ConstructFromLiteral));
    346     return cacheControlHeader;
    347 }
    348 
    349 static const AtomicString& pragmaHeaderString()
    350 {
    351     DEFINE_STATIC_LOCAL(const AtomicString, pragmaHeader, ("pragma", AtomicString::ConstructFromLiteral));
    352     return pragmaHeader;
    353 }
    354 
    355 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 
    362 bool ResourceRequest::cacheControlContainsNoCache() const
    363 {
    364     return cacheControlHeader().containsNoCache;
    365 }
    366 
    367 bool ResourceRequest::cacheControlContainsNoStore() const
    368 {
    369     return cacheControlHeader().containsNoStore;
    370 }
    371 
    372 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 
    379 double ResourceRequest::defaultTimeoutInterval()
    380 {
    381     return s_defaultTimeoutInterval;
    382 }
    383 
    384 void ResourceRequest::setDefaultTimeoutInterval(double timeoutInterval)
    385 {
    386     s_defaultTimeoutInterval = timeoutInterval;
    387 }
    388 
    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.
    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