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