Remove Cocoa CFURLConnection loading code
[WebKit-https.git] / Source / WebCore / platform / network / cf / ResourceErrorCF.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 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 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 "ResourceError.h"
28
29 #if USE(CFURLCONNECTION)
30
31 #include "URL.h"
32 #include <CoreFoundation/CFError.h>
33 #include <CFNetwork/CFNetworkErrors.h>
34 #include <WebKitSystemInterface/WebKitSystemInterface.h>
35 #include <wtf/RetainPtr.h>
36
37 namespace WebCore {
38
39 ResourceError::ResourceError(CFErrorRef cfError)
40     : ResourceErrorBase(Type::Null)
41     , m_dataIsUpToDate(false)
42     , m_platformError(cfError)
43 {
44     if (cfError)
45         setType((CFErrorGetCode(m_platformError.get()) == kCFURLErrorTimedOut) ? Type::Timeout : Type::General);
46 }
47
48 ResourceError::ResourceError(const String& domain, int errorCode, const URL& failingURL, const String& localizedDescription, CFDataRef certificate)
49     : ResourceErrorBase(domain, errorCode, failingURL, localizedDescription, Type::General)
50     , m_dataIsUpToDate(true)
51     , m_certificate(certificate)
52 {
53 }
54
55 PCCERT_CONTEXT ResourceError::certificate() const
56 {
57     if (!m_certificate)
58         return 0;
59     
60     return reinterpret_cast<PCCERT_CONTEXT>(CFDataGetBytePtr(m_certificate.get()));
61 }
62
63 void ResourceError::setCertificate(CFDataRef certificate)
64 {
65     m_certificate = certificate;
66 }
67
68 const CFStringRef failingURLStringKey = CFSTR("NSErrorFailingURLStringKey");
69 const CFStringRef failingURLKey = CFSTR("NSErrorFailingURLKey");
70
71 void ResourceError::platformLazyInit()
72 {
73     if (m_dataIsUpToDate)
74         return;
75
76     if (!m_platformError)
77         return;
78
79     CFStringRef domain = CFErrorGetDomain(m_platformError.get());
80     if (domain == kCFErrorDomainMach || domain == kCFErrorDomainCocoa)
81         m_domain ="NSCustomErrorDomain";
82     else if (domain == kCFErrorDomainCFNetwork)
83         m_domain = "CFURLErrorDomain";
84     else if (domain == kCFErrorDomainPOSIX)
85         m_domain = "NSPOSIXErrorDomain";
86     else if (domain == kCFErrorDomainOSStatus)
87         m_domain = "NSOSStatusErrorDomain";
88     else if (domain == kCFErrorDomainWinSock)
89         m_domain = "kCFErrorDomainWinSock";
90     else
91         m_domain = domain;
92
93     m_errorCode = CFErrorGetCode(m_platformError.get());
94
95     RetainPtr<CFDictionaryRef> userInfo = adoptCF(CFErrorCopyUserInfo(m_platformError.get()));
96     if (userInfo.get()) {
97         CFStringRef failingURLString = (CFStringRef) CFDictionaryGetValue(userInfo.get(), failingURLStringKey);
98         if (failingURLString)
99             m_failingURL = URL(URL(), failingURLString);
100         else {
101             CFURLRef failingURL = (CFURLRef) CFDictionaryGetValue(userInfo.get(), failingURLKey);
102             if (failingURL) {
103                 if (RetainPtr<CFURLRef> absoluteURLRef = adoptCF(CFURLCopyAbsoluteURL(failingURL)))
104                     m_failingURL = URL(absoluteURLRef.get());
105             }
106         }
107         m_localizedDescription = (CFStringRef) CFDictionaryGetValue(userInfo.get(), kCFErrorLocalizedDescriptionKey);
108         
109         m_certificate = wkGetSSLPeerCertificateData(userInfo.get());
110     }
111
112     m_dataIsUpToDate = true;
113 }
114
115
116 void ResourceError::doPlatformIsolatedCopy(const ResourceError& other)
117 {
118     m_certificate = other.m_certificate;
119 }
120
121 bool ResourceError::platformCompare(const ResourceError& a, const ResourceError& b)
122 {
123     return a.cfError() == b.cfError();
124 }
125
126 CFErrorRef ResourceError::cfError() const
127 {
128     if (isNull()) {
129         ASSERT(!m_platformError);
130         return 0;
131     }
132
133     if (!m_platformError) {
134         RetainPtr<CFMutableDictionaryRef> userInfo = adoptCF(CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
135
136         if (!m_localizedDescription.isEmpty())
137             CFDictionarySetValue(userInfo.get(), kCFErrorLocalizedDescriptionKey, m_localizedDescription.createCFString().get());
138
139         if (!m_failingURL.isEmpty()) {
140             RetainPtr<CFStringRef> failingURLString = m_failingURL.string().createCFString();
141             CFDictionarySetValue(userInfo.get(), failingURLStringKey, failingURLString.get());
142             if (RetainPtr<CFURLRef> url = m_failingURL.createCFURL())
143                 CFDictionarySetValue(userInfo.get(), failingURLKey, url.get());
144         }
145
146         if (m_certificate)
147             wkSetSSLPeerCertificateData(userInfo.get(), m_certificate.get());
148         
149         m_platformError = adoptCF(CFErrorCreate(0, m_domain.createCFString().get(), m_errorCode, userInfo.get()));
150     }
151
152     return m_platformError.get();
153 }
154
155 ResourceError::operator CFErrorRef() const
156 {
157     return cfError();
158 }
159
160 // FIXME: Once <rdar://problem/5050841> is fixed we can remove this constructor.
161 ResourceError::ResourceError(CFStreamError error)
162     : ResourceErrorBase(Type::General)
163     , m_dataIsUpToDate(true)
164 {
165     m_errorCode = error.error;
166
167     switch(error.domain) {
168     case kCFStreamErrorDomainCustom:
169         m_domain ="NSCustomErrorDomain";
170         break;
171     case kCFStreamErrorDomainPOSIX:
172         m_domain = "NSPOSIXErrorDomain";
173         break;
174     case kCFStreamErrorDomainMacOSStatus:
175         m_domain = "NSOSStatusErrorDomain";
176         break;
177     }
178 }
179
180 CFStreamError ResourceError::cfStreamError() const
181 {
182     lazyInit();
183
184     CFStreamError result;
185     result.error = m_errorCode;
186
187     if (m_domain == "NSCustomErrorDomain")
188         result.domain = kCFStreamErrorDomainCustom;
189     else if (m_domain == "NSPOSIXErrorDomain")
190         result.domain = kCFStreamErrorDomainPOSIX;
191     else if (m_domain == "NSOSStatusErrorDomain")
192         result.domain = kCFStreamErrorDomainMacOSStatus;
193     else {
194         result.domain = kCFStreamErrorDomainCustom;
195         ASSERT_NOT_REACHED();
196     }
197
198     return result;
199 }
200
201 ResourceError::operator CFStreamError() const
202 {
203     return cfStreamError();
204 }
205
206 } // namespace WebCore
207
208 #endif // USE(CFURLCONNECTION)