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