Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / fetch / RawResource.cpp
1 /*
2  * Copyright (C) 2011 Google 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 AND ITS CONTRIBUTORS ``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 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 "core/fetch/RawResource.h"
28
29 #include "core/fetch/ResourceClientWalker.h"
30 #include "core/fetch/ResourceFetcher.h"
31 #include "core/fetch/ResourceLoader.h"
32 #include "platform/SharedBuffer.h"
33
34 namespace blink {
35
36 RawResource::RawResource(const ResourceRequest& resourceRequest, Type type)
37     : Resource(resourceRequest, type)
38 {
39 }
40
41 void RawResource::appendData(const char* data, unsigned length)
42 {
43     Resource::appendData(data, length);
44
45     ResourcePtr<RawResource> protect(this);
46     ResourceClientWalker<RawResourceClient> w(m_clients);
47     while (RawResourceClient* c = w.next())
48         c->dataReceived(this, data, length);
49 }
50
51 void RawResource::didAddClient(ResourceClient* c)
52 {
53     if (!hasClient(c))
54         return;
55     // The calls to the client can result in events running, potentially causing
56     // this resource to be evicted from the cache and all clients to be removed,
57     // so a protector is necessary.
58     ResourcePtr<RawResource> protect(this);
59     RawResourceClient* client = static_cast<RawResourceClient*>(c);
60     for (const auto& redirect : redirectChain()) {
61         ResourceRequest request(redirect.m_request);
62         client->redirectReceived(this, request, redirect.m_redirectResponse);
63         if (!hasClient(c))
64             return;
65     }
66
67     if (!m_response.isNull())
68         client->responseReceived(this, m_response, nullptr);
69     if (!hasClient(c))
70         return;
71     if (m_data)
72         client->dataReceived(this, m_data->data(), m_data->size());
73     if (!hasClient(c))
74         return;
75     Resource::didAddClient(client);
76 }
77
78 void RawResource::willFollowRedirect(ResourceRequest& newRequest, const ResourceResponse& redirectResponse)
79 {
80     ResourcePtr<RawResource> protect(this);
81     if (!redirectResponse.isNull()) {
82         ResourceClientWalker<RawResourceClient> w(m_clients);
83         while (RawResourceClient* c = w.next())
84             c->redirectReceived(this, newRequest, redirectResponse);
85     }
86     Resource::willFollowRedirect(newRequest, redirectResponse);
87 }
88
89 void RawResource::updateRequest(const ResourceRequest& request)
90 {
91     ResourcePtr<RawResource> protect(this);
92     ResourceClientWalker<RawResourceClient> w(m_clients);
93     while (RawResourceClient* c = w.next())
94         c->updateRequest(this, request);
95 }
96
97 void RawResource::responseReceived(const ResourceResponse& response, PassOwnPtr<WebDataConsumerHandle> handle)
98 {
99     InternalResourcePtr protect(this);
100     Resource::responseReceived(response, nullptr);
101     ResourceClientWalker<RawResourceClient> w(m_clients);
102     ASSERT(count() <= 1 || !handle);
103     while (RawResourceClient* c = w.next()) {
104         // |handle| is cleared when passed, but it's not a problem because
105         // |handle| is null when there are two or more clients, as asserted.
106         c->responseReceived(this, m_response, handle);
107     }
108 }
109
110 void RawResource::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
111 {
112     ResourceClientWalker<RawResourceClient> w(m_clients);
113     while (RawResourceClient* c = w.next())
114         c->dataSent(this, bytesSent, totalBytesToBeSent);
115 }
116
117 void RawResource::didDownloadData(int dataLength)
118 {
119     ResourceClientWalker<RawResourceClient> w(m_clients);
120     while (RawResourceClient* c = w.next())
121         c->dataDownloaded(this, dataLength);
122 }
123
124 void RawResource::setDefersLoading(bool defers)
125 {
126     if (m_loader)
127         m_loader->setDefersLoading(defers);
128 }
129
130 static bool shouldIgnoreHeaderForCacheReuse(AtomicString headerName)
131 {
132     // FIXME: This list of headers that don't affect cache policy almost certainly isn't complete.
133     DEFINE_STATIC_LOCAL(HashSet<AtomicString>, m_headers, ());
134     if (m_headers.isEmpty()) {
135         m_headers.add("Cache-Control");
136         m_headers.add("If-Modified-Since");
137         m_headers.add("If-None-Match");
138         m_headers.add("Origin");
139         m_headers.add("Pragma");
140         m_headers.add("Purpose");
141         m_headers.add("Referer");
142         m_headers.add("User-Agent");
143     }
144     return m_headers.contains(headerName);
145 }
146
147 static bool isCacheableHTTPMethod(const AtomicString& method)
148 {
149     // Per http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.10,
150     // these methods always invalidate the cache entry.
151     return method != "POST" && method != "PUT" && method != "DELETE";
152 }
153
154 bool RawResource::canReuse(const ResourceRequest& newRequest) const
155 {
156     if (m_options.dataBufferingPolicy == DoNotBufferData)
157         return false;
158
159     if (!isCacheableHTTPMethod(m_resourceRequest.httpMethod()))
160         return false;
161     if (m_resourceRequest.httpMethod() != newRequest.httpMethod())
162         return false;
163
164     if (m_resourceRequest.httpBody() != newRequest.httpBody())
165         return false;
166
167     if (m_resourceRequest.allowStoredCredentials() != newRequest.allowStoredCredentials())
168         return false;
169
170     // Ensure most headers match the existing headers before continuing.
171     // Note that the list of ignored headers includes some headers explicitly related to caching.
172     // A more detailed check of caching policy will be performed later, this is simply a list of
173     // headers that we might permit to be different and still reuse the existing Resource.
174     const HTTPHeaderMap& newHeaders = newRequest.httpHeaderFields();
175     const HTTPHeaderMap& oldHeaders = m_resourceRequest.httpHeaderFields();
176
177     for (const auto& header : newHeaders) {
178         AtomicString headerName = header.key;
179         if (!shouldIgnoreHeaderForCacheReuse(headerName) && header.value != oldHeaders.get(headerName))
180             return false;
181     }
182
183     for (const auto& header : oldHeaders) {
184         AtomicString headerName = header.key;
185         if (!shouldIgnoreHeaderForCacheReuse(headerName) && header.value != newHeaders.get(headerName))
186             return false;
187     }
188
189     return true;
190 }
191
192 } // namespace blink