1/*
2 * Copyright (C) 2006, 2007 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 "WebKitDLL.h"
28#include "WebMutableURLRequest.h"
29
30#include "WebKit.h"
31#include "MarshallingHelpers.h"
32#include "WebKit.h"
33#include <WebCore/BString.h>
34#include <WebCore/COMPtr.h>
35#include <WebCore/FormData.h>
36#include <WebCore/ResourceHandle.h>
37#include <wtf/text/CString.h>
38#include <wtf/RetainPtr.h>
39
40#if USE(CF)
41#include <WebCore/CertificateCFWin.h>
42#endif
43
44#if USE(CFNETWORK)
45#include <CFNetwork/CFURLRequestPriv.h>
46#endif
47
48using namespace WebCore;
49
50// IWebURLRequest ----------------------------------------------------------------
51
52WebMutableURLRequest::WebMutableURLRequest(bool isMutable)
53    : m_refCount(0)
54    , m_isMutable(isMutable)
55{
56    gClassCount++;
57    gClassNameCount.add("WebMutableURLRequest");
58}
59
60WebMutableURLRequest* WebMutableURLRequest::createInstance()
61{
62    WebMutableURLRequest* instance = new WebMutableURLRequest(true);
63    instance->AddRef();
64    return instance;
65}
66
67WebMutableURLRequest* WebMutableURLRequest::createInstance(IWebMutableURLRequest* req)
68{
69    WebMutableURLRequest* instance = new WebMutableURLRequest(true);
70    instance->AddRef();
71    instance->m_request = static_cast<WebMutableURLRequest*>(req)->m_request;
72    return instance;
73}
74
75WebMutableURLRequest* WebMutableURLRequest::createInstance(const ResourceRequest& request)
76{
77    WebMutableURLRequest* instance = new WebMutableURLRequest(true);
78    instance->AddRef();
79    instance->m_request = request;
80    return instance;
81}
82
83WebMutableURLRequest* WebMutableURLRequest::createImmutableInstance()
84{
85    WebMutableURLRequest* instance = new WebMutableURLRequest(false);
86    instance->AddRef();
87    return instance;
88}
89
90WebMutableURLRequest* WebMutableURLRequest::createImmutableInstance(const ResourceRequest& request)
91{
92    WebMutableURLRequest* instance = new WebMutableURLRequest(false);
93    instance->AddRef();
94    instance->m_request = request;
95    return instance;
96}
97
98WebMutableURLRequest::~WebMutableURLRequest()
99{
100    gClassCount--;
101    gClassNameCount.remove("WebMutableURLRequest");
102}
103
104// IUnknown -------------------------------------------------------------------
105
106HRESULT STDMETHODCALLTYPE WebMutableURLRequest::QueryInterface(REFIID riid, void** ppvObject)
107{
108    *ppvObject = 0;
109    if (IsEqualGUID(riid, CLSID_WebMutableURLRequest))
110        *ppvObject = this;
111    else if (IsEqualGUID(riid, IID_IUnknown))
112        *ppvObject = static_cast<IWebURLRequest*>(this);
113    else if (IsEqualGUID(riid, IID_IWebMutableURLRequest) && m_isMutable)
114        *ppvObject = static_cast<IWebMutableURLRequest*>(this);
115    else if (IsEqualGUID(riid, __uuidof(IWebMutableURLRequestPrivate)) && m_isMutable)
116        *ppvObject = static_cast<IWebMutableURLRequestPrivate*>(this);
117    else if (IsEqualGUID(riid, IID_IWebURLRequest))
118        *ppvObject = static_cast<IWebURLRequest*>(this);
119    else
120        return E_NOINTERFACE;
121
122    AddRef();
123    return S_OK;
124}
125
126ULONG STDMETHODCALLTYPE WebMutableURLRequest::AddRef(void)
127{
128    return ++m_refCount;
129}
130
131ULONG STDMETHODCALLTYPE WebMutableURLRequest::Release(void)
132{
133    ULONG newRef = --m_refCount;
134    if (!newRef)
135        delete(this);
136
137    return newRef;
138}
139
140// IWebURLRequest --------------------------------------------------------------------
141
142HRESULT STDMETHODCALLTYPE WebMutableURLRequest::requestWithURL(
143    /* [in] */ BSTR /*theURL*/,
144    /* [optional][in] */ WebURLRequestCachePolicy /*cachePolicy*/,
145    /* [optional][in] */ double /*timeoutInterval*/)
146{
147    ASSERT_NOT_REACHED();
148    return E_NOTIMPL;
149}
150
151HRESULT STDMETHODCALLTYPE WebMutableURLRequest::allHTTPHeaderFields(
152    /* [retval][out] */ IPropertyBag** /*result*/)
153{
154    ASSERT_NOT_REACHED();
155    return E_NOTIMPL;
156}
157
158HRESULT STDMETHODCALLTYPE WebMutableURLRequest::cachePolicy(
159    /* [retval][out] */ WebURLRequestCachePolicy* result)
160{
161    *result = kit(m_request.cachePolicy());
162    return S_OK;
163}
164
165HRESULT STDMETHODCALLTYPE WebMutableURLRequest::HTTPBody(
166    /* [retval][out] */ IStream** /*result*/)
167{
168    ASSERT_NOT_REACHED();
169    return E_NOTIMPL;
170}
171
172HRESULT STDMETHODCALLTYPE WebMutableURLRequest::HTTPBodyStream(
173    /* [retval][out] */ IStream** /*result*/)
174{
175    ASSERT_NOT_REACHED();
176    return E_NOTIMPL;
177}
178
179HRESULT STDMETHODCALLTYPE WebMutableURLRequest::HTTPMethod(
180    /* [retval][out] */ BSTR* result)
181{
182    BString httpMethod = BString(m_request.httpMethod());
183    *result = httpMethod.release();
184    return S_OK;
185}
186
187HRESULT STDMETHODCALLTYPE WebMutableURLRequest::HTTPShouldHandleCookies(
188    /* [retval][out] */ BOOL* result)
189{
190    bool shouldHandleCookies = m_request.allowCookies();
191
192    *result = shouldHandleCookies ? TRUE : FALSE;
193    return S_OK;
194}
195
196HRESULT STDMETHODCALLTYPE WebMutableURLRequest::initWithURL(
197    /* [in] */ BSTR url,
198    /* [optional][in] */ WebURLRequestCachePolicy cachePolicy,
199    /* [optional][in] */ double timeoutInterval)
200{
201    m_request.setURL(MarshallingHelpers::BSTRToKURL(url));
202    m_request.setCachePolicy(core(cachePolicy));
203    m_request.setTimeoutInterval(timeoutInterval);
204
205    return S_OK;
206}
207
208HRESULT STDMETHODCALLTYPE WebMutableURLRequest::mainDocumentURL(
209    /* [retval][out] */ BSTR* result)
210{
211    *result = MarshallingHelpers::KURLToBSTR(m_request.firstPartyForCookies());
212    return S_OK;
213}
214
215HRESULT STDMETHODCALLTYPE WebMutableURLRequest::timeoutInterval(
216    /* [retval][out] */ double* result)
217{
218    *result = m_request.timeoutInterval();
219    return S_OK;
220}
221
222HRESULT STDMETHODCALLTYPE WebMutableURLRequest::URL(
223    /* [retval][out] */ BSTR* result)
224{
225    *result = MarshallingHelpers::KURLToBSTR(m_request.url());
226    return S_OK;
227}
228
229HRESULT STDMETHODCALLTYPE WebMutableURLRequest::valueForHTTPHeaderField(
230    /* [in] */ BSTR field,
231    /* [retval][out] */ BSTR* result)
232{
233    if (!result) {
234        ASSERT_NOT_REACHED();
235        return E_POINTER;
236    }
237
238    *result = BString(m_request.httpHeaderField(String(field, SysStringLen(field)))).release();
239    return S_OK;
240}
241
242HRESULT STDMETHODCALLTYPE WebMutableURLRequest::isEmpty(
243    /* [retval][out] */ BOOL* result)
244{
245    *result = m_request.isEmpty();
246    return S_OK;
247}
248
249HRESULT STDMETHODCALLTYPE WebMutableURLRequest::isEqual(
250        /* [in] */ IWebURLRequest* other,
251        /* [out, retval] */ BOOL* result)
252{
253    COMPtr<WebMutableURLRequest> requestImpl(Query, other);
254
255    if (!requestImpl) {
256        *result = FALSE;
257        return S_OK;
258    }
259
260    *result = m_request == requestImpl->resourceRequest();
261    return S_OK;
262}
263
264
265// IWebMutableURLRequest --------------------------------------------------------
266
267HRESULT STDMETHODCALLTYPE WebMutableURLRequest::addValue(
268    /* [in] */ BSTR value,
269    /* [in] */ BSTR field)
270{
271    m_request.addHTTPHeaderField(WTF::AtomicString(value, SysStringLen(value)), String(field, SysStringLen(field)));
272    return S_OK;
273}
274
275HRESULT STDMETHODCALLTYPE WebMutableURLRequest::setAllHTTPHeaderFields(
276    /* [in] */ IPropertyBag* /*headerFields*/)
277{
278    ASSERT_NOT_REACHED();
279    return E_NOTIMPL;
280}
281
282HRESULT STDMETHODCALLTYPE WebMutableURLRequest::setCachePolicy(
283    /* [in] */ WebURLRequestCachePolicy policy)
284{
285    m_request.setCachePolicy(core(policy));
286    return S_OK;
287}
288
289HRESULT STDMETHODCALLTYPE WebMutableURLRequest::setHTTPBody(
290    /* [in] */ IStream* /*data*/)
291{
292    ASSERT_NOT_REACHED();
293    return E_NOTIMPL;
294}
295
296HRESULT STDMETHODCALLTYPE WebMutableURLRequest::setHTTPBodyStream(
297    /* [in] */ IStream* /*data*/)
298{
299    ASSERT_NOT_REACHED();
300    return E_NOTIMPL;
301}
302
303HRESULT STDMETHODCALLTYPE WebMutableURLRequest::setHTTPMethod(
304    /* [in] */ BSTR method)
305{
306    m_request.setHTTPMethod(String(method));
307    return S_OK;
308}
309
310HRESULT STDMETHODCALLTYPE WebMutableURLRequest::setHTTPShouldHandleCookies(
311    /* [in] */ BOOL handleCookies)
312{
313    m_request.setAllowCookies(handleCookies);
314    return S_OK;
315}
316
317HRESULT STDMETHODCALLTYPE WebMutableURLRequest::setMainDocumentURL(
318    /* [in] */ BSTR theURL)
319{
320    m_request.setFirstPartyForCookies(MarshallingHelpers::BSTRToKURL(theURL));
321    return S_OK;
322}
323
324HRESULT STDMETHODCALLTYPE WebMutableURLRequest::setTimeoutInterval(
325    /* [in] */ double timeoutInterval)
326{
327    m_request.setTimeoutInterval(timeoutInterval);
328    return S_OK;
329}
330
331HRESULT STDMETHODCALLTYPE WebMutableURLRequest::setURL(
332    /* [in] */ BSTR url)
333{
334    m_request.setURL(MarshallingHelpers::BSTRToKURL(url));
335    return S_OK;
336}
337
338HRESULT STDMETHODCALLTYPE WebMutableURLRequest::setValue(
339    /* [in] */ BSTR value,
340    /* [in] */ BSTR field)
341{
342    String valueString(value, SysStringLen(value));
343    String fieldString(field, SysStringLen(field));
344    m_request.setHTTPHeaderField(fieldString, valueString);
345    return S_OK;
346}
347
348HRESULT STDMETHODCALLTYPE WebMutableURLRequest::setAllowsAnyHTTPSCertificate(void)
349{
350    ResourceHandle::setHostAllowsAnyHTTPSCertificate(m_request.url().host());
351
352    return S_OK;
353}
354
355HRESULT STDMETHODCALLTYPE WebMutableURLRequest::setClientCertificate(
356    /* [in] */ OLE_HANDLE cert)
357{
358    if (!cert)
359        return E_POINTER;
360
361    PCCERT_CONTEXT certContext = reinterpret_cast<PCCERT_CONTEXT>((ULONG64)cert);
362    RetainPtr<CFDataRef> certData = WebCore::copyCertificateToData(certContext);
363    ResourceHandle::setClientCertificate(m_request.url().host(), certData.get());
364    return S_OK;
365}
366
367CFURLRequestRef STDMETHODCALLTYPE WebMutableURLRequest::cfRequest()
368{
369    return m_request.cfURLRequest(UpdateHTTPBody);
370}
371
372HRESULT STDMETHODCALLTYPE WebMutableURLRequest::mutableCopy(
373        /* [out, retval] */ IWebMutableURLRequest** result)
374{
375    if (!result)
376        return E_POINTER;
377
378#if USE(CFNETWORK)
379    RetainPtr<CFMutableURLRequestRef> mutableRequest = adoptCF(CFURLRequestCreateMutableCopy(kCFAllocatorDefault, m_request.cfURLRequest(UpdateHTTPBody)));
380    *result = createInstance(ResourceRequest(mutableRequest.get()));
381    return S_OK;
382#else
383    *result = createInstance(m_request);
384    return S_OK;
385#endif
386}
387
388// IWebMutableURLRequest ----------------------------------------------------
389
390void WebMutableURLRequest::setFormData(const PassRefPtr<FormData> data)
391{
392    m_request.setHTTPBody(data);
393}
394
395const PassRefPtr<FormData> WebMutableURLRequest::formData() const
396{
397    return m_request.httpBody();
398}
399
400void WebMutableURLRequest::addHTTPHeaderFields(const HTTPHeaderMap& headerFields)
401{
402    m_request.addHTTPHeaderFields(headerFields);
403}
404
405const HTTPHeaderMap& WebMutableURLRequest::httpHeaderFields() const
406{
407    return m_request.httpHeaderFields();
408}
409
410const ResourceRequest& WebMutableURLRequest::resourceRequest() const
411{
412    return m_request;
413}
414