1/*
2 * Copyright (C) 2009 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 are
6 * met:
7 *
8 *     * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 *     * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 *     * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#include "config.h"
32#include "WebURLResponse.h"
33
34#include "ResourceResponse.h"
35#include "ResourceLoadTiming.h"
36
37#include "WebHTTPHeaderVisitor.h"
38#include "WebHTTPLoadInfo.h"
39#include "WebString.h"
40#include "WebURL.h"
41#include "WebURLLoadTiming.h"
42#include "WebURLResponsePrivate.h"
43
44#include <wtf/RefPtr.h>
45
46using namespace WebCore;
47
48namespace WebKit {
49
50// The standard implementation of WebURLResponsePrivate, which maintains
51// ownership of a ResourceResponse instance.
52class WebURLResponsePrivateImpl : public WebURLResponsePrivate {
53public:
54    WebURLResponsePrivateImpl()
55    {
56        m_resourceResponse = &m_resourceResponseAllocation;
57    }
58
59    WebURLResponsePrivateImpl(const WebURLResponsePrivate* p)
60        : m_resourceResponseAllocation(*p->m_resourceResponse)
61    {
62        m_resourceResponse = &m_resourceResponseAllocation;
63    }
64
65    virtual void dispose() { delete this; }
66
67    ResourceResponse m_resourceResponseAllocation;
68};
69
70void WebURLResponse::initialize()
71{
72    assign(new WebURLResponsePrivateImpl());
73}
74
75void WebURLResponse::reset()
76{
77    assign(0);
78}
79
80void WebURLResponse::assign(const WebURLResponse& r)
81{
82    if (&r != this)
83        assign(r.m_private ? new WebURLResponsePrivateImpl(r.m_private) : 0);
84}
85
86bool WebURLResponse::isNull() const
87{
88    return !m_private || m_private->m_resourceResponse->isNull();
89}
90
91WebURL WebURLResponse::url() const
92{
93    return m_private->m_resourceResponse->url();
94}
95
96void WebURLResponse::setURL(const WebURL& url)
97{
98    m_private->m_resourceResponse->setURL(url);
99}
100
101unsigned WebURLResponse::connectionID() const
102{
103    return m_private->m_resourceResponse->connectionID();
104}
105
106void WebURLResponse::setConnectionID(unsigned connectionID)
107{
108    m_private->m_resourceResponse->setConnectionID(connectionID);
109}
110
111bool WebURLResponse::connectionReused() const
112{
113    return m_private->m_resourceResponse->connectionReused();
114}
115
116void WebURLResponse::setConnectionReused(bool connectionReused)
117{
118    m_private->m_resourceResponse->setConnectionReused(connectionReused);
119}
120
121WebURLLoadTiming WebURLResponse::loadTiming()
122{
123    return WebURLLoadTiming(m_private->m_resourceResponse->resourceLoadTiming());
124}
125
126void WebURLResponse::setLoadTiming(const WebURLLoadTiming& timing)
127{
128    RefPtr<ResourceLoadTiming> loadTiming = PassRefPtr<ResourceLoadTiming>(timing);
129    m_private->m_resourceResponse->setResourceLoadTiming(loadTiming.release());
130}
131
132WebHTTPLoadInfo WebURLResponse::httpLoadInfo()
133{
134    return WebHTTPLoadInfo(m_private->m_resourceResponse->resourceLoadInfo());
135}
136
137void WebURLResponse::setHTTPLoadInfo(const WebHTTPLoadInfo& value)
138{
139    m_private->m_resourceResponse->setResourceLoadInfo(value);
140}
141
142double WebURLResponse::responseTime() const
143{
144    return m_private->m_resourceResponse->responseTime();
145}
146
147void WebURLResponse::setResponseTime(double responseTime)
148{
149    m_private->m_resourceResponse->setResponseTime(responseTime);
150}
151
152WebString WebURLResponse::mimeType() const
153{
154    return m_private->m_resourceResponse->mimeType();
155}
156
157void WebURLResponse::setMIMEType(const WebString& mimeType)
158{
159    m_private->m_resourceResponse->setMimeType(mimeType);
160}
161
162long long WebURLResponse::expectedContentLength() const
163{
164    return m_private->m_resourceResponse->expectedContentLength();
165}
166
167void WebURLResponse::setExpectedContentLength(long long expectedContentLength)
168{
169    m_private->m_resourceResponse->setExpectedContentLength(expectedContentLength);
170}
171
172WebString WebURLResponse::textEncodingName() const
173{
174    return m_private->m_resourceResponse->textEncodingName();
175}
176
177void WebURLResponse::setTextEncodingName(const WebString& textEncodingName)
178{
179    m_private->m_resourceResponse->setTextEncodingName(textEncodingName);
180}
181
182WebString WebURLResponse::suggestedFileName() const
183{
184    return m_private->m_resourceResponse->suggestedFilename();
185}
186
187void WebURLResponse::setSuggestedFileName(const WebString& suggestedFileName)
188{
189    m_private->m_resourceResponse->setSuggestedFilename(suggestedFileName);
190}
191
192int WebURLResponse::httpStatusCode() const
193{
194    return m_private->m_resourceResponse->httpStatusCode();
195}
196
197void WebURLResponse::setHTTPStatusCode(int httpStatusCode)
198{
199    m_private->m_resourceResponse->setHTTPStatusCode(httpStatusCode);
200}
201
202WebString WebURLResponse::httpStatusText() const
203{
204    return m_private->m_resourceResponse->httpStatusText();
205}
206
207void WebURLResponse::setHTTPStatusText(const WebString& httpStatusText)
208{
209    m_private->m_resourceResponse->setHTTPStatusText(httpStatusText);
210}
211
212WebString WebURLResponse::httpHeaderField(const WebString& name) const
213{
214    return m_private->m_resourceResponse->httpHeaderField(name);
215}
216
217void WebURLResponse::setHTTPHeaderField(const WebString& name, const WebString& value)
218{
219    m_private->m_resourceResponse->setHTTPHeaderField(name, value);
220}
221
222void WebURLResponse::addHTTPHeaderField(const WebString& name, const WebString& value)
223{
224    if (name.isNull() || value.isNull())
225        return;
226    // FIXME: Add an addHTTPHeaderField method to ResourceResponse.
227    const HTTPHeaderMap& map = m_private->m_resourceResponse->httpHeaderFields();
228    String valueStr(value);
229    pair<HTTPHeaderMap::iterator, bool> result =
230        const_cast<HTTPHeaderMap*>(&map)->add(name, valueStr);
231    if (!result.second)
232        result.first->second += ", " + valueStr;
233}
234
235void WebURLResponse::clearHTTPHeaderField(const WebString& name)
236{
237    // FIXME: Add a clearHTTPHeaderField method to ResourceResponse.
238    const HTTPHeaderMap& map = m_private->m_resourceResponse->httpHeaderFields();
239    const_cast<HTTPHeaderMap*>(&map)->remove(name);
240}
241
242void WebURLResponse::visitHTTPHeaderFields(WebHTTPHeaderVisitor* visitor) const
243{
244    const HTTPHeaderMap& map = m_private->m_resourceResponse->httpHeaderFields();
245    for (HTTPHeaderMap::const_iterator it = map.begin(); it != map.end(); ++it)
246        visitor->visitHeader(it->first, it->second);
247}
248
249double WebURLResponse::lastModifiedDate() const
250{
251    return static_cast<double>(m_private->m_resourceResponse->lastModifiedDate());
252}
253
254void WebURLResponse::setLastModifiedDate(double lastModifiedDate)
255{
256    m_private->m_resourceResponse->setLastModifiedDate(static_cast<time_t>(lastModifiedDate));
257}
258
259long long WebURLResponse::appCacheID() const
260{
261    return m_private->m_resourceResponse->appCacheID();
262}
263
264void WebURLResponse::setAppCacheID(long long appCacheID)
265{
266    m_private->m_resourceResponse->setAppCacheID(appCacheID);
267}
268
269WebURL WebURLResponse::appCacheManifestURL() const
270{
271    return m_private->m_resourceResponse->appCacheManifestURL();
272}
273
274void WebURLResponse::setAppCacheManifestURL(const WebURL& url)
275{
276    m_private->m_resourceResponse->setAppCacheManifestURL(url);
277}
278
279WebCString WebURLResponse::securityInfo() const
280{
281    // FIXME: getSecurityInfo is misnamed.
282    return m_private->m_resourceResponse->getSecurityInfo();
283}
284
285void WebURLResponse::setSecurityInfo(const WebCString& securityInfo)
286{
287    m_private->m_resourceResponse->setSecurityInfo(securityInfo);
288}
289
290ResourceResponse& WebURLResponse::toMutableResourceResponse()
291{
292    ASSERT(m_private);
293    ASSERT(m_private->m_resourceResponse);
294
295    return *m_private->m_resourceResponse;
296}
297
298const ResourceResponse& WebURLResponse::toResourceResponse() const
299{
300    ASSERT(m_private);
301    ASSERT(m_private->m_resourceResponse);
302
303    return *m_private->m_resourceResponse;
304}
305
306bool WebURLResponse::wasCached() const
307{
308    return m_private->m_resourceResponse->wasCached();
309}
310
311void WebURLResponse::setWasCached(bool value)
312{
313    m_private->m_resourceResponse->setWasCached(value);
314}
315
316bool WebURLResponse::wasFetchedViaSPDY() const
317{
318    return m_private->m_resourceResponse->wasFetchedViaSPDY();
319}
320
321void WebURLResponse::setWasFetchedViaSPDY(bool value)
322{
323    m_private->m_resourceResponse->setWasFetchedViaSPDY(value);
324}
325
326bool WebURLResponse::wasNpnNegotiated() const
327{
328    return m_private->m_resourceResponse->wasNpnNegotiated();
329}
330
331void WebURLResponse::setWasNpnNegotiated(bool value)
332{
333    m_private->m_resourceResponse->setWasNpnNegotiated(value);
334}
335
336bool WebURLResponse::wasAlternateProtocolAvailable() const
337{
338    return m_private->m_resourceResponse->wasAlternateProtocolAvailable();
339}
340
341void WebURLResponse::setWasAlternateProtocolAvailable(bool value)
342{
343    m_private->m_resourceResponse->setWasAlternateProtocolAvailable(value);
344}
345
346bool WebURLResponse::wasFetchedViaProxy() const
347{
348    return m_private->m_resourceResponse->wasFetchedViaProxy();
349}
350
351void WebURLResponse::setWasFetchedViaProxy(bool value)
352{
353    m_private->m_resourceResponse->setWasFetchedViaProxy(value);
354}
355
356bool WebURLResponse::isMultipartPayload() const
357{
358    return m_private->m_resourceResponse->isMultipartPayload();
359}
360
361void WebURLResponse::setIsMultipartPayload(bool value)
362{
363    m_private->m_resourceResponse->setIsMultipartPayload(value);
364}
365
366WebString WebURLResponse::downloadFilePath() const
367{
368    return m_private->m_resourceResponse->downloadFilePath();
369}
370
371void WebURLResponse::setDownloadFilePath(const WebString& downloadFilePath)
372{
373    m_private->m_resourceResponse->setDownloadFilePath(downloadFilePath.utf8().data());
374}
375
376WebString WebURLResponse::remoteIPAddress() const
377{
378    return m_private->m_resourceResponse->remoteIPAddress();
379}
380
381void WebURLResponse::setRemoteIPAddress(const WebString& remoteIPAddress)
382{
383    m_private->m_resourceResponse->setRemoteIPAddress(remoteIPAddress);
384}
385
386unsigned short WebURLResponse::remotePort() const
387{
388    return m_private->m_resourceResponse->remotePort();
389}
390
391void WebURLResponse::setRemotePort(unsigned short remotePort)
392{
393    m_private->m_resourceResponse->setRemotePort(remotePort);
394}
395
396void WebURLResponse::assign(WebURLResponsePrivate* p)
397{
398    // Subclasses may call this directly so a self-assignment check is needed
399    // here as well as in the public assign method.
400    if (m_private == p)
401        return;
402    if (m_private)
403        m_private->dispose();
404    m_private = p;
405}
406
407} // namespace WebKit
408