1/*
2 * Copyright (C) 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 "WebURLAuthenticationChallenge.h"
29
30#include "WebError.h"
31#include "WebKit.h"
32#include "WebURLAuthenticationChallengeSender.h"
33#include "WebURLCredential.h"
34#include "WebURLProtectionSpace.h"
35#include "WebURLResponse.h"
36#include "WebKit.h"
37#include <WebCore/BString.h>
38#include <WebCore/COMPtr.h>
39#include <WebCore/ResourceHandle.h>
40
41using namespace WebCore;
42
43// WebURLAuthenticationChallenge ----------------------------------------------------------------
44
45WebURLAuthenticationChallenge::WebURLAuthenticationChallenge(const AuthenticationChallenge& authenticationChallenge,
46                                                             IWebURLAuthenticationChallengeSender* sender)
47    : m_refCount(0)
48    , m_authenticationChallenge(authenticationChallenge)
49    , m_sender(sender)
50{
51    gClassCount++;
52    gClassNameCount.add("WebURLAuthenticationChallenge");
53}
54
55WebURLAuthenticationChallenge::~WebURLAuthenticationChallenge()
56{
57    gClassCount--;
58    gClassNameCount.remove("WebURLAuthenticationChallenge");
59}
60
61WebURLAuthenticationChallenge* WebURLAuthenticationChallenge::createInstance(const AuthenticationChallenge& authenticationChallenge)
62{
63    WebURLAuthenticationChallenge* instance = new WebURLAuthenticationChallenge(authenticationChallenge, 0);
64    instance->AddRef();
65    return instance;
66}
67
68WebURLAuthenticationChallenge* WebURLAuthenticationChallenge::createInstance(const AuthenticationChallenge& authenticationChallenge,
69                                                                             IWebURLAuthenticationChallengeSender* sender)
70{
71    WebURLAuthenticationChallenge* instance = new WebURLAuthenticationChallenge(authenticationChallenge, sender);
72    instance->AddRef();
73    return instance;
74}
75
76// IUnknown -------------------------------------------------------------------
77
78HRESULT STDMETHODCALLTYPE WebURLAuthenticationChallenge::QueryInterface(REFIID riid, void** ppvObject)
79{
80    *ppvObject = 0;
81    if (IsEqualGUID(riid, IID_IUnknown))
82        *ppvObject = static_cast<IUnknown*>(this);
83    else if (IsEqualGUID(riid, __uuidof(this)))
84        *ppvObject = static_cast<WebURLAuthenticationChallenge*>(this);
85    else if (IsEqualGUID(riid, IID_IWebURLAuthenticationChallenge))
86        *ppvObject = static_cast<IWebURLAuthenticationChallenge*>(this);
87    else
88        return E_NOINTERFACE;
89
90    AddRef();
91    return S_OK;
92}
93
94ULONG STDMETHODCALLTYPE WebURLAuthenticationChallenge::AddRef(void)
95{
96    return ++m_refCount;
97}
98
99ULONG STDMETHODCALLTYPE WebURLAuthenticationChallenge::Release(void)
100{
101    ULONG newRef = --m_refCount;
102    if (!newRef)
103        delete(this);
104
105    return newRef;
106}
107
108// IWebURLAuthenticationChallenge -------------------------------------------------------------------
109
110HRESULT STDMETHODCALLTYPE WebURLAuthenticationChallenge::initWithProtectionSpace(
111    /* [in] */ IWebURLProtectionSpace* space,
112    /* [in] */ IWebURLCredential* proposedCredential,
113    /* [in] */ int previousFailureCount,
114    /* [in] */ IWebURLResponse* failureResponse,
115    /* [in] */ IWebError* error,
116    /* [in] */ IWebURLAuthenticationChallengeSender* sender)
117{
118    LOG_ERROR("Calling the ala carte init for WebURLAuthenticationChallenge - is this really what you want to do?");
119
120    if (!space || !proposedCredential || !failureResponse || !sender)
121        return E_POINTER;
122
123    HRESULT hr = S_OK;
124    COMPtr<WebURLProtectionSpace> webSpace;
125    hr = space->QueryInterface(&webSpace);
126    if (FAILED(hr))
127        return hr;
128
129    COMPtr<WebURLCredential> webCredential(Query, proposedCredential);
130    if (!webCredential)
131        return E_NOINTERFACE;
132
133    COMPtr<WebURLResponse> webResponse;
134    hr = failureResponse->QueryInterface(&webResponse);
135    if (FAILED(hr))
136        return hr;
137
138    COMPtr<WebError> webError;
139    hr = error->QueryInterface(CLSID_WebError, (void**)&webError);
140    if (FAILED(hr))
141        return hr;
142
143    COMPtr<WebURLAuthenticationChallengeSender> webSender(Query, sender);
144    if (!webSender)
145        return E_NOINTERFACE;
146
147    // FIXME: After we change AuthenticationChallenge to use "ResourceHandle" as the abstract "Sender" or "Source of this Auth Challenge", then we'll
148    // construct the AuthenticationChallenge with that as obtained from the webSender
149#if USE(CFNETWORK)
150    m_authenticationChallenge = AuthenticationChallenge(webSpace->protectionSpace(), webCredential->credential(),
151                                    previousFailureCount, webResponse->resourceResponse(), webError->resourceError());
152#endif
153    return S_OK;
154}
155
156HRESULT STDMETHODCALLTYPE WebURLAuthenticationChallenge::initWithAuthenticationChallenge(
157    /* [in] */ IWebURLAuthenticationChallenge* challenge,
158    /* [in] */ IWebURLAuthenticationChallengeSender* sender)
159{
160    if (!challenge || !sender)
161        return E_POINTER;
162
163    COMPtr<WebURLAuthenticationChallenge> webChallenge(Query, challenge);
164    if (!webChallenge)
165        return E_NOINTERFACE;
166
167    COMPtr<WebURLAuthenticationChallengeSender> webSender(Query, sender);
168    if (!webSender)
169        return E_NOINTERFACE;
170
171#if USE(CFNETWORK)
172    m_authenticationChallenge = AuthenticationChallenge(webChallenge->authenticationChallenge().cfURLAuthChallengeRef(), webSender->authenticationClient());
173
174    return S_OK;
175#else
176
177    return E_FAIL;
178#endif
179}
180
181HRESULT STDMETHODCALLTYPE WebURLAuthenticationChallenge::error(
182    /* [out, retval] */ IWebError** result)
183{
184    *result = WebError::createInstance(m_authenticationChallenge.error());
185    return S_OK;
186}
187
188HRESULT STDMETHODCALLTYPE WebURLAuthenticationChallenge::failureResponse(
189    /* [out, retval] */ IWebURLResponse** result)
190{
191    *result = WebURLResponse::createInstance(m_authenticationChallenge.failureResponse());
192    return S_OK;
193}
194
195HRESULT STDMETHODCALLTYPE WebURLAuthenticationChallenge::previousFailureCount(
196    /* [out, retval] */ UINT* result)
197{
198    *result = m_authenticationChallenge.previousFailureCount();
199    return S_OK;
200}
201
202HRESULT STDMETHODCALLTYPE WebURLAuthenticationChallenge::proposedCredential(
203    /* [out, retval] */ IWebURLCredential** result)
204{
205    *result = WebURLCredential::createInstance(m_authenticationChallenge.proposedCredential());
206    return S_OK;
207}
208
209HRESULT STDMETHODCALLTYPE WebURLAuthenticationChallenge::protectionSpace(
210    /* [out, retval] */ IWebURLProtectionSpace** result)
211{
212    *result = WebURLProtectionSpace::createInstance(m_authenticationChallenge.protectionSpace());
213    return S_OK;
214}
215
216HRESULT STDMETHODCALLTYPE WebURLAuthenticationChallenge::sender(
217    /* [out, retval] */ IWebURLAuthenticationChallengeSender** sender)
218{
219    if (!m_sender) {
220        AuthenticationClient* client = m_authenticationChallenge.authenticationClient();
221        m_sender.adoptRef(WebURLAuthenticationChallengeSender::createInstance(client));
222    }
223
224    return m_sender.copyRefTo(sender);
225}
226
227// WebURLAuthenticationChallenge -------------------------------------------------------------------
228const AuthenticationChallenge& WebURLAuthenticationChallenge::authenticationChallenge() const
229{
230    return m_authenticationChallenge;
231}
232