<rdar://problem/5074612> Added SPI to retrieve certificate info from a WebError.
[WebKit-https.git] / WebKit / win / WebError.cpp
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 "WebError.h"
29 #include "WebKit.h"
30
31 #include <WebKitSystemInterface/WebKitSystemInterface.h>
32 #pragma warning(push, 0)
33 #include <WebCore/BString.h>
34 #pragma warning(pop)
35
36 using namespace WebCore;
37
38 // WebError ---------------------------------------------------------------------
39
40 WebError::WebError(const ResourceError& error, IPropertyBag* userInfo)
41     : m_refCount(0)
42     , m_error(error)
43     , m_userInfo(userInfo)
44 {
45     gClassCount++;
46 }
47
48 WebError::~WebError()
49 {
50     gClassCount--;
51 }
52
53 WebError* WebError::createInstance(const ResourceError& error, IPropertyBag* userInfo)
54 {
55     WebError* instance = new WebError(error, userInfo);
56     instance->AddRef();
57     return instance;
58 }
59
60 // IUnknown -------------------------------------------------------------------
61
62 HRESULT STDMETHODCALLTYPE WebError::QueryInterface(REFIID riid, void** ppvObject)
63 {
64     *ppvObject = 0;
65     if (IsEqualGUID(riid, IID_IUnknown))
66         *ppvObject = static_cast<IWebError*>(this);
67     else if (IsEqualGUID(riid, CLSID_WebError))
68         *ppvObject = static_cast<WebError*>(this);
69     else if (IsEqualGUID(riid, IID_IWebError))
70         *ppvObject = static_cast<IWebError*>(this);
71     else if (IsEqualGUID(riid, IID_IWebErrorPrivate))
72         *ppvObject = static_cast<IWebErrorPrivate*>(this);
73     else
74         return E_NOINTERFACE;
75
76     AddRef();
77     return S_OK;
78 }
79
80 ULONG STDMETHODCALLTYPE WebError::AddRef(void)
81 {
82     return ++m_refCount;
83 }
84
85 ULONG STDMETHODCALLTYPE WebError::Release(void)
86 {
87     ULONG newRef = --m_refCount;
88     if (!newRef)
89         delete(this);
90
91     return newRef;
92 }
93
94 // IWebError ------------------------------------------------------------------
95
96 HRESULT STDMETHODCALLTYPE WebError::init( 
97     /* [in] */ BSTR domain,
98     /* [in] */ int code,
99     /* [in] */ BSTR url)
100 {
101     m_error = ResourceError(String(domain, SysStringLen(domain)), code, String(url, SysStringLen(url)), String());
102     return S_OK;
103 }
104   
105 HRESULT STDMETHODCALLTYPE WebError::code( 
106     /* [retval][out] */ int* result)
107 {
108     *result = m_error.errorCode();
109     return S_OK;
110 }
111         
112 HRESULT STDMETHODCALLTYPE WebError::domain( 
113     /* [retval][out] */ BSTR* result)
114 {
115     if (!result)
116         return E_POINTER;
117
118     *result = BString(m_error.domain()).release();
119     return S_OK;
120 }
121                
122 HRESULT STDMETHODCALLTYPE WebError::localizedDescription( 
123     /* [retval][out] */ BSTR* result)
124 {
125     if (!result)
126         return E_POINTER;
127
128     *result = BString(m_error.localizedDescription()).release();
129     return S_OK;
130 }
131
132         
133 HRESULT STDMETHODCALLTYPE WebError::localizedFailureReason( 
134     /* [retval][out] */ BSTR* /*result*/)
135 {
136     ASSERT_NOT_REACHED();
137     return E_NOTIMPL;
138 }
139         
140 HRESULT STDMETHODCALLTYPE WebError::localizedRecoveryOptions( 
141     /* [retval][out] */ IEnumVARIANT** /*result*/)
142 {
143     ASSERT_NOT_REACHED();
144     return E_NOTIMPL;
145 }
146         
147 HRESULT STDMETHODCALLTYPE WebError::localizedRecoverySuggestion( 
148     /* [retval][out] */ BSTR* /*result*/)
149 {
150     ASSERT_NOT_REACHED();
151     return E_NOTIMPL;
152 }
153        
154 HRESULT STDMETHODCALLTYPE WebError::recoverAttempter( 
155     /* [retval][out] */ IUnknown** /*result*/)
156 {
157     ASSERT_NOT_REACHED();
158     return E_NOTIMPL;
159 }
160         
161 HRESULT STDMETHODCALLTYPE WebError::userInfo( 
162     /* [retval][out] */ IPropertyBag** result)
163 {
164     if (!result)
165         return E_POINTER;
166     *result = 0;
167
168     if (!m_userInfo)
169         return E_FAIL;
170
171     return m_userInfo.copyRefTo(result);
172 }
173
174 HRESULT STDMETHODCALLTYPE WebError::failingURL( 
175     /* [retval][out] */ BSTR* result)
176 {
177     if (!result)
178         return E_POINTER;
179
180     *result = BString(m_error.failingURL()).release();
181     return S_OK;
182 }
183
184 HRESULT STDMETHODCALLTYPE WebError::isPolicyChangeError( 
185     /* [retval][out] */ BOOL *result)
186 {
187     if (!result)
188         return E_POINTER;
189
190     *result = m_error.domain() == String(WebKitErrorDomain)
191         && m_error.errorCode() == WebKitErrorFrameLoadInterruptedByPolicyChange;
192     return S_OK;
193 }
194
195 HRESULT STDMETHODCALLTYPE WebError::sslPeerCertificate( 
196     /* [retval][out] */ OLE_HANDLE* result)
197 {
198     if (!result)
199         return E_POINTER;
200     *result = 0;
201
202     if (!m_cfErrorUserInfoDict) {
203         // copy userinfo from CFErrorRef
204         CFErrorRef cfError = m_error;
205         m_cfErrorUserInfoDict.adoptCF(CFErrorCopyUserInfo(cfError));
206     }
207
208     if (!m_cfErrorUserInfoDict)
209         return E_FAIL;
210
211     void* data = wkGetSSLPeerCertificateData(m_cfErrorUserInfoDict.get());
212     if (!data)
213         return E_FAIL;
214     *result = (OLE_HANDLE)(ULONG64)data;
215     return *result ? S_OK : E_FAIL;
216 }
217
218 const ResourceError& WebError::resourceError() const
219 {
220     return m_error;
221 }