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 "KURL.h" 28 #include "ResourceError.h" 29 30 #if USE(CFNETWORK) 31 32 // FIXME: Once <rdar://problem/5050881> is fixed in open source we 33 // can remove this extern "C" 34 extern "C" { 35 #include <CFNetwork/CFNetworkErrors.h> 36 } 37 38 #include <CoreFoundation/CFError.h> 39 #include <WTF/RetainPtr.h> 40 41 namespace WebCore { 42 43 const CFStringRef failingURLStringKey = CFSTR("NSErrorFailingURLStringKey"); 44 const CFStringRef failingURLKey = CFSTR("NSErrorFailingURLKey"); 45 46 // FIXME: Once <rdar://problem/5050841> is fixed we can remove this constructor. 47 ResourceError::ResourceError(CFStreamError error) 48 : m_dataIsUpToDate(true) 49 { 50 m_isNull = false; 51 m_errorCode = error.error; 52 53 switch(error.domain) { 54 case kCFStreamErrorDomainCustom: 55 m_domain ="NSCustomErrorDomain"; 56 break; 57 case kCFStreamErrorDomainPOSIX: 58 m_domain = "NSPOSIXErrorDomain"; 59 break; 60 case kCFStreamErrorDomainMacOSStatus: 61 m_domain = "NSOSStatusErrorDomain"; 62 break; 63 } 64 } 65 66 void ResourceError::platformLazyInit() 67 { 68 if (m_dataIsUpToDate) 69 return; 70 71 if (!m_platformError) 72 return; 73 74 CFStringRef domain = CFErrorGetDomain(m_platformError.get()); 75 if (domain == kCFErrorDomainMach || domain == kCFErrorDomainCocoa) 76 m_domain ="NSCustomErrorDomain"; 77 else if (domain == kCFErrorDomainCFNetwork) 78 m_domain = "CFURLErrorDomain"; 79 else if (domain == kCFErrorDomainPOSIX) 80 m_domain = "NSPOSIXErrorDomain"; 81 else if (domain == kCFErrorDomainOSStatus) 82 m_domain = "NSOSStatusErrorDomain"; 83 else if (domain == kCFErrorDomainWinSock) 84 m_domain = "kCFErrorDomainWinSock"; 85 86 m_errorCode = CFErrorGetCode(m_platformError.get()); 87 88 RetainPtr<CFDictionaryRef> userInfo(AdoptCF, CFErrorCopyUserInfo(m_platformError.get())); 89 if (userInfo.get()) { 90 CFStringRef failingURLString = (CFStringRef) CFDictionaryGetValue(userInfo.get(), failingURLStringKey); 91 if (failingURLString) 92 m_failingURL = String(failingURLString); 93 else { 94 CFURLRef failingURL = (CFURLRef) CFDictionaryGetValue(userInfo.get(), failingURLKey); 95 if (failingURL) { 96 RetainPtr<CFURLRef> absoluteURLRef(AdoptCF, CFURLCopyAbsoluteURL(failingURL)); 97 if (absoluteURLRef.get()) { 98 failingURLString = CFURLGetString(absoluteURLRef.get()); 99 m_failingURL = String(failingURLString); 100 } 101 } 102 } 103 m_localizedDescription = (CFStringRef) CFDictionaryGetValue(userInfo.get(), kCFErrorLocalizedDescriptionKey); 104 } 105 106 m_dataIsUpToDate = true; 107 } 108 109 bool ResourceError::platformCompare(const ResourceError& a, const ResourceError& b) 110 { 111 return (CFErrorRef)a == (CFErrorRef)b; 112 } 113 114 ResourceError::operator CFErrorRef() const 115 { 116 if (m_isNull) { 117 ASSERT(!m_platformError); 118 return nil; 119 } 120 121 if (!m_platformError) { 122 RetainPtr<CFMutableDictionaryRef> userInfo(AdoptCF, CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); 123 124 if (!m_localizedDescription.isEmpty()) { 125 RetainPtr<CFStringRef> localizedDescriptionString(AdoptCF, m_localizedDescription.createCFString()); 126 CFDictionarySetValue(userInfo.get(), kCFErrorLocalizedDescriptionKey, localizedDescriptionString.get()); 127 } 128 129 if (!m_failingURL.isEmpty()) { 130 RetainPtr<CFStringRef> failingURLString(AdoptCF, m_failingURL.createCFString()); 131 CFDictionarySetValue(userInfo.get(), failingURLStringKey, failingURLString.get()); 132 RetainPtr<CFURLRef> url(AdoptCF, KURL(ParsedURLString, m_failingURL).createCFURL()); 133 CFDictionarySetValue(userInfo.get(), failingURLKey, url.get()); 134 } 135 136 RetainPtr<CFStringRef> domainString(AdoptCF, m_domain.createCFString()); 137 m_platformError.adoptCF(CFErrorCreate(0, domainString.get(), m_errorCode, userInfo.get())); 138 } 139 140 return m_platformError.get(); 141 } 142 143 ResourceError::operator CFStreamError() const 144 { 145 lazyInit(); 146 147 CFStreamError result; 148 result.error = m_errorCode; 149 150 if (m_domain == "NSCustomErrorDomain") 151 result.domain = kCFStreamErrorDomainCustom; 152 else if (m_domain == "NSPOSIXErrorDomain") 153 result.domain = kCFStreamErrorDomainPOSIX; 154 else if (m_domain == "NSOSStatusErrorDomain") 155 result.domain = kCFStreamErrorDomainMacOSStatus; 156 else 157 ASSERT_NOT_REACHED(); 158 159 return result; 160 } 161 162 } // namespace WebCore 163 164 #endif // USE(CFNETWORK) 165