bool ImageSource::getHotSpot(IntPoint& hotSpot) const { RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions())); if (!properties) return false; int x = -1, y = -1; CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties.get(), CFSTR("hotspotX")); if (!num || !CFNumberGetValue(num, kCFNumberIntType, &x)) return false; num = (CFNumberRef)CFDictionaryGetValue(properties.get(), CFSTR("hotspotY")); if (!num || !CFNumberGetValue(num, kCFNumberIntType, &y)) return false; if (x < 0 || y < 0) return false; hotSpot = IntPoint(x, y); return true; }
void ImageSource::setData(SharedBuffer* data, bool allDataReceived) { #if PLATFORM(COCOA) if (!m_decoder) m_decoder = CGImageSourceCreateIncremental(0); // On Mac the NSData inside the SharedBuffer can be secretly appended to without the SharedBuffer's knowledge. We use SharedBuffer's ability // to wrap itself inside CFData to get around this, ensuring that ImageIO is really looking at the SharedBuffer. CGImageSourceUpdateData(m_decoder, data->createCFData().get(), allDataReceived); #else if (!m_decoder) m_decoder = CGImageSourceCreateIncremental(0); // Create a CGDataProvider to wrap the SharedBuffer. data->ref(); // We use the GetBytesAtPosition callback rather than the GetBytePointer one because SharedBuffer // does not provide a way to lock down the byte pointer and guarantee that it won't move, which // is a requirement for using the GetBytePointer callback. CGDataProviderDirectCallbacks providerCallbacks = { 0, 0, 0, sharedBufferGetBytesAtPosition, sharedBufferRelease }; RetainPtr<CGDataProviderRef> dataProvider = adoptCF(CGDataProviderCreateDirect(data, data->size(), &providerCallbacks)); CGImageSourceUpdateDataProvider(m_decoder, dataProvider.get(), allDataReceived); #endif }
IntSize ImageSource::frameSizeAtIndex(size_t index, SubsamplingLevel subsamplingLevel, ImageOrientationDescription description) const { RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions(SkipMetadata, subsamplingLevel))); if (!properties) return IntSize(); int width = 0; int height = 0; CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelWidth); if (num) CFNumberGetValue(num, kCFNumberIntType, &width); num = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelHeight); if (num) CFNumberGetValue(num, kCFNumberIntType, &height); if ((description.respectImageOrientation() == RespectImageOrientation) && orientationFromProperties(properties.get()).usesWidthAsHeight()) return IntSize(height, width); return IntSize(width, height); }
bool ImageSource::allowSubsamplingOfFrameAtIndex(size_t) const { RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions())); if (!properties) return false; CFDictionaryRef jfifProperties = static_cast<CFDictionaryRef>(CFDictionaryGetValue(properties.get(), kCGImagePropertyJFIFDictionary)); if (jfifProperties) { CFBooleanRef isProgCFBool = static_cast<CFBooleanRef>(CFDictionaryGetValue(jfifProperties, kCGImagePropertyJFIFIsProgressive)); if (isProgCFBool) { bool isProgressive = CFBooleanGetValue(isProgCFBool); // Workaround for <rdar://problem/5184655> - Hang rendering very large progressive JPEG. Decoding progressive // images hangs for a very long time right now. Until this is fixed, don't sub-sample progressive images. This // will cause them to fail our large image check and they won't be decoded. // FIXME: Remove once underlying issue is fixed (<rdar://problem/5191418>) return !isProgressive; } } return true; }
static void convertWebResourceDataToString(CFMutableDictionaryRef resource) { CFMutableStringRef mimeType = (CFMutableStringRef)CFDictionaryGetValue(resource, CFSTR("WebResourceMIMEType")); CFStringLowercase(mimeType, CFLocaleGetSystem()); convertMIMEType(mimeType); CFArrayRef supportedMIMETypes = supportedNonImageMIMETypes(); if (CFStringHasPrefix(mimeType, CFSTR("text/")) || CFArrayContainsValue(supportedMIMETypes, CFRangeMake(0, CFArrayGetCount(supportedMIMETypes)), mimeType)) { CFStringRef textEncodingName = static_cast<CFStringRef>(CFDictionaryGetValue(resource, CFSTR("WebResourceTextEncodingName"))); CFStringEncoding stringEncoding; if (textEncodingName && CFStringGetLength(textEncodingName)) stringEncoding = CFStringConvertIANACharSetNameToEncoding(textEncodingName); else stringEncoding = kCFStringEncodingUTF8; CFDataRef data = static_cast<CFDataRef>(CFDictionaryGetValue(resource, CFSTR("WebResourceData"))); RetainPtr<CFStringRef> dataAsString = adoptCF(CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, data, stringEncoding)); if (dataAsString) CFDictionarySetValue(resource, CFSTR("WebResourceData"), dataAsString.get()); } }
static CFCachedURLResponseRef willCacheResponse(CFURLConnectionRef, CFCachedURLResponseRef cachedResponse, const void* clientInfo) { ResourceHandle* handle = static_cast<ResourceHandle*>(const_cast<void*>(clientInfo)); CFURLResponseRef wrappedResponse = CFCachedURLResponseGetWrappedResponse(cachedResponse); // Workaround for <rdar://problem/6300990> Caching does not respect Vary HTTP header. // FIXME: WebCore cache has issues with Vary, too (bug 58797, bug 71509). if (CFHTTPMessageRef httpResponse = CFURLResponseGetHTTPResponse(wrappedResponse)) { ASSERT(CFHTTPMessageIsHeaderComplete(httpResponse)); RetainPtr<CFStringRef> varyValue = adoptCF(CFHTTPMessageCopyHeaderFieldValue(httpResponse, CFSTR("Vary"))); if (varyValue) return 0; } #if PLATFORM(WIN) if (handle->client() && !handle->client()->shouldCacheResponse(handle, cachedResponse)) return 0; #else CFCachedURLResponseRef newResponse = handle->client()->willCacheResponse(handle, cachedResponse); if (newResponse != cachedResponse) return newResponse; #endif CacheStoragePolicy policy = static_cast<CacheStoragePolicy>(CFCachedURLResponseGetStoragePolicy(cachedResponse)); if (handle->client()) handle->client()->willCacheResponse(handle, policy); if (static_cast<CFURLCacheStoragePolicy>(policy) != CFCachedURLResponseGetStoragePolicy(cachedResponse)) { RetainPtr<CFArrayRef> receiverData(AdoptCF, CFCachedURLResponseCopyReceiverDataArray(cachedResponse)); cachedResponse = CFCachedURLResponseCreateWithDataArray(kCFAllocatorDefault, wrappedResponse, receiverData.get(), CFCachedURLResponseGetUserInfo(cachedResponse), static_cast<CFURLCacheStoragePolicy>(policy)); } else CFRetain(cachedResponse); return cachedResponse; }
IntSize ImageSource::originalSize(RespectImageOrientationEnum shouldRespectOrientation) const { frameSizeAtIndex(0, shouldRespectOrientation); RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, 0, imageSourceOptions(SkipMetadata, -1))); if (!properties) return IntSize(); int width = 0; int height = 0; CFNumberRef number = (CFNumberRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelWidth); if (number) CFNumberGetValue(number, kCFNumberIntType, &width); number = static_cast<CFNumberRef>(CFDictionaryGetValue(properties.get(), kCGImagePropertyPixelHeight)); if (number) CFNumberGetValue(number, kCFNumberIntType, &height); if ((shouldRespectOrientation == RespectImageOrientation) && orientationFromProperties(properties.get()).usesWidthAsHeight()) return IntSize(height, width); return IntSize(width, height); }
CFDictionaryRef Font::getCFStringAttributes(bool enableKerning, FontOrientation orientation) const { auto& attributesDictionary = enableKerning ? m_kernedCFStringAttributes : m_nonKernedCFStringAttributes; if (attributesDictionary) return attributesDictionary.get(); attributesDictionary = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 4, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); CFMutableDictionaryRef mutableAttributes = (CFMutableDictionaryRef)attributesDictionary.get(); CFDictionarySetValue(mutableAttributes, kCTFontAttributeName, platformData().ctFont()); if (!enableKerning) { const float zero = 0; static CFNumberRef zeroKerningValue = CFNumberCreate(kCFAllocatorDefault, kCFNumberFloatType, &zero); CFDictionarySetValue(mutableAttributes, kCTKernAttributeName, zeroKerningValue); } if (orientation == Vertical) CFDictionarySetValue(mutableAttributes, kCTVerticalFormsAttributeName, kCFBooleanTrue); return attributesDictionary.get(); }
static RetainPtr<CFArrayRef> filterCookies(CFArrayRef unfilteredCookies) { ASSERT(unfilteredCookies); CFIndex count = CFArrayGetCount(unfilteredCookies); RetainPtr<CFMutableArrayRef> filteredCookies = adoptCF(CFArrayCreateMutable(0, count, &kCFTypeArrayCallBacks)); for (CFIndex i = 0; i < count; ++i) { CFHTTPCookieRef cookie = (CFHTTPCookieRef)CFArrayGetValueAtIndex(unfilteredCookies, i); // <rdar://problem/5632883> CFHTTPCookieStorage would store an empty cookie, // which would be sent as "Cookie: =". We have a workaround in setCookies() to prevent // that, but we also need to avoid sending cookies that were previously stored, and // there's no harm to doing this check because such a cookie is never valid. if (!CFStringGetLength(cookieName(cookie).get())) continue; if (CFHTTPCookieIsHTTPOnly(cookie)) continue; CFArrayAppendValue(filteredCookies.get(), cookie); } return filteredCookies; }
void HIDGamepad::initElements() { RetainPtr<CFArrayRef> elements = adoptCF(IOHIDDeviceCopyMatchingElements(m_hidDevice.get(), NULL, kIOHIDOptionsTypeNone)); initElementsFromArray(elements.get()); // Buttons are specified to appear highest priority first in the array. std::sort(m_buttons.begin(), m_buttons.end(), [](auto& a, auto& b) { return a->priority < b->priority; }); m_axisValues.resize(m_axes.size()); m_buttonValues.resize(m_buttons.size() + (m_dPads.size() * 4)); for (auto& button : m_buttons) getCurrentValueForElement(button.get()); for (auto& dPad : m_dPads) getCurrentValueForElement(dPad.get()); for (auto& axis : m_axes) getCurrentValueForElement(axis.get()); }
// We can't use String::format for two reasons: // 1) It doesn't handle non-ASCII characters in the format string. // 2) It doesn't handle the %2$d syntax. // Note that because |format| is used as the second parameter to va_start, it cannot be a reference // type according to section 18.7/3 of the C++ N1905 standard. static String formatLocalizedString(String format, ...) { #if USE(CF) va_list arguments; va_start(arguments, format); #if COMPILER(CLANG) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wformat-nonliteral" #endif RetainPtr<CFStringRef> result = adoptCF(CFStringCreateWithFormatAndArguments(0, 0, format.createCFString().get(), arguments)); #if COMPILER(CLANG) #pragma clang diagnostic pop #endif va_end(arguments); return result.get(); #else notImplemented(); return format; #endif }
PassRefPtr<BitmapImage> BitmapImage::create(HBITMAP hBitmap) { DIBSECTION dibSection; if (!GetObject(hBitmap, sizeof(DIBSECTION), &dibSection)) return 0; ASSERT(dibSection.dsBm.bmBitsPixel == 32); if (dibSection.dsBm.bmBitsPixel != 32) return 0; ASSERT(dibSection.dsBm.bmBits); if (!dibSection.dsBm.bmBits) return 0; RetainPtr<CGContextRef> bitmapContext = adoptCF(CGBitmapContextCreate(dibSection.dsBm.bmBits, dibSection.dsBm.bmWidth, dibSection.dsBm.bmHeight, 8, dibSection.dsBm.bmWidthBytes, deviceRGBColorSpaceRef(), kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst)); // The BitmapImage takes ownership of this. CGImageRef cgImage = CGBitmapContextCreateImage(bitmapContext.get()); return adoptRef(new BitmapImage(cgImage)); }
void DNSResolveQueue::platformResolve(const String& hostname) { ASSERT(isMainThread()); RetainPtr<CFHostRef> host = adoptCF(CFHostCreateWithName(0, hostname.createCFString().get())); if (!host) { decrementRequestCount(); return; } CFHostClientContext context = { 0, 0, 0, 0, 0 }; CFHostRef leakedHost = host.leakRef(); // The host will be released from clientCallback(). Boolean result = CFHostSetClient(leakedHost, clientCallback, &context); ASSERT_UNUSED(result, result); #if !PLATFORM(WIN) CFHostScheduleWithRunLoop(leakedHost, CFRunLoopGetMain(), kCFRunLoopCommonModes); #else // On Windows, we run a separate thread with CFRunLoop, which is where clientCallback will be called. CFHostScheduleWithRunLoop(leakedHost, loaderRunLoop(), kCFRunLoopDefaultMode); #endif CFHostStartInfoResolution(leakedHost, kCFHostAddresses, 0); }
template<ColorSpace colorSpace> static CGColorRef cachedCGColor(const Color& color) { switch (color.rgb()) { case Color::transparent: { static CGColorRef transparentCGColor = leakCGColor(color, colorSpace); return transparentCGColor; } case Color::black: { static CGColorRef blackCGColor = leakCGColor(color, colorSpace); return blackCGColor; } case Color::white: { static CGColorRef whiteCGColor = leakCGColor(color, colorSpace); return whiteCGColor; } } ASSERT(color.rgb()); const size_t cacheSize = 32; static RGBA32 cachedRGBAValues[cacheSize]; static RetainPtr<CGColorRef>* cachedCGColors = new RetainPtr<CGColorRef>[cacheSize]; for (size_t i = 0; i < cacheSize; ++i) { if (cachedRGBAValues[i] == color.rgb()) return cachedCGColors[i].get(); } CGColorRef newCGColor = leakCGColor(color, colorSpace); static size_t cursor; cachedRGBAValues[cursor] = color.rgb(); cachedCGColors[cursor] = adoptCF(newCGColor); if (++cursor == cacheSize) cursor = 0; return newCGColor; }
int ImageSource::repetitionCount() { if (!initialized()) return cAnimationLoopOnce; RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyProperties(m_decoder, imageSourceOptions().get())); if (!properties) return cAnimationLoopOnce; CFDictionaryRef gifProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyGIFDictionary); if (gifProperties) { CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFLoopCount); // No property means loop once. if (!num) return cAnimationLoopOnce; int loopCount; CFNumberGetValue(num, kCFNumberIntType, &loopCount); // A property with value 0 means loop forever. return loopCount ? loopCount : cAnimationLoopInfinite; } CFDictionaryRef pngProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPNGDictionary); if (pngProperties) { CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(pngProperties, WebCoreCGImagePropertyAPNGLoopCount); if (!num) return cAnimationLoopOnce; int loopCount; CFNumberGetValue(num, kCFNumberIntType, &loopCount); return loopCount ? loopCount : cAnimationLoopInfinite; } // Turns out we're not an animated image after all, so we don't animate. return cAnimationNone; }
static RetainPtr<CFStringRef> utiFromMIMEType(const String& mimeType) { #if PLATFORM(MAC) return adoptCF(UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeType.createCFString().get(), 0)); #else ASSERT(isMainThread()); // It is unclear if CFSTR is threadsafe. // FIXME: Add Windows support for all the supported UTIs when a way to convert from MIMEType to UTI reliably is found. // For now, only support PNG, JPEG, and GIF. See <rdar://problem/6095286>. static const CFStringRef kUTTypePNG = CFSTR("public.png"); static const CFStringRef kUTTypeGIF = CFSTR("com.compuserve.gif"); if (equalIgnoringCase(mimeType, "image/png")) return kUTTypePNG; if (equalIgnoringCase(mimeType, "image/jpeg")) return jpegUTI(); if (equalIgnoringCase(mimeType, "image/gif")) return kUTTypeGIF; ASSERT_NOT_REACHED(); return kUTTypePNG; #endif }
int ImageSource::repetitionCount() { int result = cAnimationLoopOnce; // No property means loop once. if (!initialized()) return result; RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyProperties(m_decoder, imageSourceOptions(SkipMetadata))); if (properties) { CFDictionaryRef gifProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyGIFDictionary); if (gifProperties) { CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFLoopCount); if (num) { // A property with value 0 means loop forever. CFNumberGetValue(num, kCFNumberIntType, &result); if (!result) result = cAnimationLoopInfinite; } } else result = cAnimationNone; // Turns out we're not a GIF after all, so we don't animate. } return result; }
PassRefPtr<LegacyWebArchive> LegacyWebArchive::create(const URL&, SharedBuffer* data) { LOG(Archives, "LegacyWebArchive - Creating from raw data"); RefPtr<LegacyWebArchive> archive = create(); ASSERT(data); if (!data) return 0; RetainPtr<CFDataRef> cfData = data->createCFData(); if (!cfData) return 0; CFStringRef errorString = 0; RetainPtr<CFDictionaryRef> plist = adoptCF(static_cast<CFDictionaryRef>(CFPropertyListCreateFromXMLData(0, cfData.get(), kCFPropertyListImmutable, &errorString))); if (!plist) { #ifndef NDEBUG const char* cError = errorString ? CFStringGetCStringPtr(errorString, kCFStringEncodingUTF8) : "unknown error"; LOG(Archives, "LegacyWebArchive - Error parsing PropertyList from archive data - %s", cError); #endif if (errorString) CFRelease(errorString); return 0; } if (CFGetTypeID(plist.get()) != CFDictionaryGetTypeID()) { LOG(Archives, "LegacyWebArchive - Archive property list is not the expected CFDictionary, aborting invalid WebArchive"); return 0; } if (!archive->extract(plist.get())) return 0; return archive.release(); }
float ImageSource::frameDurationAtIndex(size_t index) { if (!initialized()) return 0; float duration = 0; RetainPtr<CFDictionaryRef> properties = adoptCF(CGImageSourceCopyPropertiesAtIndex(m_decoder, index, imageSourceOptions().get())); if (properties) { CFDictionaryRef gifProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyGIFDictionary); if (gifProperties) { if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFUnclampedDelayTime)) { // Use the unclamped frame delay if it exists. CFNumberGetValue(num, kCFNumberFloatType, &duration); } else if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(gifProperties, kCGImagePropertyGIFDelayTime)) { // Fall back to the clamped frame delay if the unclamped frame delay does not exist. CFNumberGetValue(num, kCFNumberFloatType, &duration); } } CFDictionaryRef pngProperties = (CFDictionaryRef)CFDictionaryGetValue(properties.get(), kCGImagePropertyPNGDictionary); if (pngProperties) { if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(pngProperties, WebCoreCGImagePropertyAPNGUnclampedDelayTime)) CFNumberGetValue(num, kCFNumberFloatType, &duration); else if (CFNumberRef num = (CFNumberRef)CFDictionaryGetValue(pngProperties, WebCoreCGImagePropertyAPNGDelayTime)) CFNumberGetValue(num, kCFNumberFloatType, &duration); } } // Many annoying ads specify a 0 duration to make an image flash as quickly as possible. // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082> // for more information. if (duration < 0.011f) return 0.1f; return duration; }
String imageTitle(const String& filename, const IntSize& size) { #if USE(CF) #if !PLATFORM(MAC) || PLATFORM(IOS) || __MAC_OS_X_VERSION_MIN_REQUIRED >= 1060 RetainPtr<CFLocaleRef> locale = adoptCF(CFLocaleCopyCurrent()); RetainPtr<CFNumberFormatterRef> formatter(AdoptCF, CFNumberFormatterCreate(0, locale.get(), kCFNumberFormatterDecimalStyle)); int widthInt = size.width(); RetainPtr<CFNumberRef> width(AdoptCF, CFNumberCreate(0, kCFNumberIntType, &widthInt)); RetainPtr<CFStringRef> widthString(AdoptCF, CFNumberFormatterCreateStringWithNumber(0, formatter.get(), width.get())); int heightInt = size.height(); RetainPtr<CFNumberRef> height(AdoptCF, CFNumberCreate(0, kCFNumberIntType, &heightInt)); RetainPtr<CFStringRef> heightString(AdoptCF, CFNumberFormatterCreateStringWithNumber(0, formatter.get(), height.get())); return formatLocalizedString(WEB_UI_STRING("%@ %@×%@ pixels", "window title for a standalone image (uses multiplication symbol, not x)"), filename.createCFString().get(), widthString.get(), heightString.get()); #else RetainPtr<CFStringRef> filenameCFString(AdoptCF, filename.createCFString()); return formatLocalizedString(WEB_UI_STRING("%@ %d×%d pixels", "window title for a standalone image (uses multiplication symbol, not x)"), filenameCFString.get(), size.width(), size.height()); #endif #else return formatLocalizedString(WEB_UI_STRING("<filename> %d×%d pixels", "window title for a standalone image (uses multiplication symbol, not x)"), size.width(), size.height()).replace("<filename>", filename); #endif }
void KeyedEncoder::encodeDouble(const String& key, double value) { auto number = adoptCF(CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &value)); CFDictionarySetValue(m_dictionaryStack.last(), key.createCFString().get(), number.get()); }
void KeyedEncoder::encodeBytes(const String& key, const uint8_t* bytes, size_t size) { auto data = adoptCF(CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, bytes, size, kCFAllocatorNull)); CFDictionarySetValue(m_dictionaryStack.last(), key.createCFString().get(), data.get()); }
static RetainPtr<CFMutableDictionaryRef> createDictionary() { return adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); }
void FontPlatformData::platformDataInit(HFONT font, float size, HDC hdc, WCHAR* faceName) { LOGFONT logfont; GetObject(font, sizeof(logfont), &logfont); m_cgFont = adoptCF(CGFontCreateWithPlatformFont(&logfont)); }
ImageDecoder::ImageDecoder(AlphaOption, GammaAndColorProfileOption) { m_nativeDecoder = adoptCF(CGImageSourceCreateIncremental(nullptr)); }
void PDFDocumentImage::createPDFDocument() { RetainPtr<CGDataProviderRef> dataProvider = adoptCF(CGDataProviderCreateWithCFData(data()->createCFData().get())); m_document = adoptCF(CGPDFDocumentCreateWithProvider(dataProvider.get())); }
WKCACFViewLayerTreeHost::WKCACFViewLayerTreeHost() : m_view(adoptCF(WKCACFViewCreate(kWKCACFViewDrawingDestinationWindow))) , m_viewNeedsUpdate(true) { }
void ResourceHandle::createCFURLConnection(bool shouldUseCredentialStorage, bool shouldContentSniff, SchedulingBehavior schedulingBehavior, CFDictionaryRef clientProperties) { if ((!d->m_user.isEmpty() || !d->m_pass.isEmpty()) && !firstRequest().url().protocolIsInHTTPFamily()) { // Credentials for ftp can only be passed in URL, the didReceiveAuthenticationChallenge delegate call won't be made. URL urlWithCredentials(firstRequest().url()); urlWithCredentials.setUser(d->m_user); urlWithCredentials.setPass(d->m_pass); firstRequest().setURL(urlWithCredentials); } // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication, // try and reuse the credential preemptively, as allowed by RFC 2617. if (shouldUseCredentialStorage && firstRequest().url().protocolIsInHTTPFamily()) { if (d->m_user.isEmpty() && d->m_pass.isEmpty()) { // <rdar://problem/7174050> - For URLs that match the paths of those previously challenged for HTTP Basic authentication, // try and reuse the credential preemptively, as allowed by RFC 2617. d->m_initialCredential = CredentialStorage::get(firstRequest().url()); } else { // If there is already a protection space known for the URL, update stored credentials before sending a request. // This makes it possible to implement logout by sending an XMLHttpRequest with known incorrect credentials, and aborting it immediately // (so that an authentication dialog doesn't pop up). CredentialStorage::set(Credential(d->m_user, d->m_pass, CredentialPersistenceNone), firstRequest().url()); } } if (!d->m_initialCredential.isEmpty()) { // FIXME: Support Digest authentication, and Proxy-Authorization. applyBasicAuthorizationHeader(firstRequest(), d->m_initialCredential); } RetainPtr<CFMutableURLRequestRef> request = adoptCF(CFURLRequestCreateMutableCopy(kCFAllocatorDefault, firstRequest().cfURLRequest(UpdateHTTPBody))); wkSetRequestStorageSession(d->m_storageSession.get(), request.get()); if (!shouldContentSniff) wkSetCFURLRequestShouldContentSniff(request.get(), false); RetainPtr<CFMutableDictionaryRef> sslProps; #if PLATFORM(IOS) sslProps = adoptCF(ResourceHandle::createSSLPropertiesFromNSURLRequest(firstRequest())); #else if (allowsAnyHTTPSCertificateHosts().contains(firstRequest().url().host().lower())) { sslProps = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); CFDictionaryAddValue(sslProps.get(), kCFStreamSSLAllowsAnyRoot, kCFBooleanTrue); CFDictionaryAddValue(sslProps.get(), kCFStreamSSLAllowsExpiredRoots, kCFBooleanTrue); CFDictionaryAddValue(sslProps.get(), kCFStreamSSLAllowsExpiredCertificates, kCFBooleanTrue); CFDictionaryAddValue(sslProps.get(), kCFStreamSSLValidatesCertificateChain, kCFBooleanFalse); } HashMap<String, RetainPtr<CFDataRef>>::iterator clientCert = clientCerts().find(firstRequest().url().host().lower()); if (clientCert != clientCerts().end()) { if (!sslProps) sslProps = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); #if PLATFORM(WIN) wkSetClientCertificateInSSLProperties(sslProps.get(), (clientCert->value).get()); #endif } #endif // PLATFORM(IOS) if (sslProps) CFURLRequestSetSSLProperties(request.get(), sslProps.get()); #if PLATFORM(WIN) if (CFHTTPCookieStorageRef cookieStorage = overridenCookieStorage()) { // Overridden cookie storage doesn't come from a session, so the request does not have it yet. CFURLRequestSetHTTPCookieStorage(request.get(), cookieStorage); } #endif CFMutableDictionaryRef streamProperties = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (!shouldUseCredentialStorage) { // Avoid using existing connections, because they may be already authenticated. CFDictionarySetValue(streamProperties, CFSTR("_kCFURLConnectionSessionID"), CFSTR("WebKitPrivateSession")); } if (schedulingBehavior == SchedulingBehavior::Synchronous) { // Synchronous requests should not be subject to regular connection count limit to avoid deadlocks. // If we are using all available connections for async requests, and make a sync request, then prior // requests may get stuck waiting for delegate calls while we are in nested run loop, and the sync // request won't start because there are no available connections. // Connections are grouped by their socket stream properties, with each group having a separate count. CFDictionarySetValue(streamProperties, CFSTR("_WebKitSynchronousRequest"), kCFBooleanTrue); } #if PLATFORM(IOS) || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1090) RetainPtr<CFDataRef> sourceApplicationAuditData = d->m_context->sourceApplicationAuditData(); if (sourceApplicationAuditData) CFDictionarySetValue(streamProperties, CFSTR("kCFStreamPropertySourceApplication"), sourceApplicationAuditData.get()); #endif static const CFStringRef kCFURLConnectionSocketStreamProperties = CFSTR("kCFURLConnectionSocketStreamProperties"); RetainPtr<CFMutableDictionaryRef> propertiesDictionary; if (clientProperties) propertiesDictionary = adoptCF(CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, clientProperties)); else propertiesDictionary = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks)); // FIXME: This code is different from iOS code in ResourceHandleMac.mm in that here we ignore stream properties that were present in client properties. CFDictionaryAddValue(propertiesDictionary.get(), kCFURLConnectionSocketStreamProperties, streamProperties); CFRelease(streamProperties); #if PLATFORM(COCOA) if (client() && client()->usesAsyncCallbacks()) d->m_connectionDelegate = adoptRef(new ResourceHandleCFURLConnectionDelegateWithOperationQueue(this)); else d->m_connectionDelegate = adoptRef(new SynchronousResourceHandleCFURLConnectionDelegate(this)); #else d->m_connectionDelegate = adoptRef(new SynchronousResourceHandleCFURLConnectionDelegate(this)); #endif d->m_connectionDelegate->setupRequest(request.get()); CFURLConnectionClient_V6 client = d->m_connectionDelegate->makeConnectionClient(); d->m_connection = adoptCF(CFURLConnectionCreateWithProperties(0, request.get(), reinterpret_cast<CFURLConnectionClient*>(&client), propertiesDictionary.get())); }
static CFStringRef getPostScriptName(CFStringRef faceName, HDC dc) { const DWORD cMaxNameTableSize = 1024 * 1024; static HashMap<String, RetainPtr<CFStringRef> > nameMap; // Check our hash first. String faceString(faceName); RetainPtr<CFStringRef> result = nameMap.get(faceString); if (result) return result.get(); // We need to obtain the PostScript name from the name table and use it instead,. DWORD bufferSize = GetFontData(dc, 'eman', 0, NULL, 0); // "name" backwards if (bufferSize == 0 || bufferSize == GDI_ERROR || bufferSize > cMaxNameTableSize) return NULL; Vector<BYTE> bufferVector(bufferSize); BYTE* buffer = bufferVector.data(); if (GetFontData(dc, 'eman', 0, buffer, bufferSize) == GDI_ERROR) return NULL; if (bufferSize < 6) return NULL; USHORT numberOfRecords = readBigEndianWord(buffer + 2); UINT stringsOffset = readBigEndianWord(buffer + 4); if (bufferSize < stringsOffset) return NULL; BYTE* strings = buffer + stringsOffset; // Now walk each name record looking for a Mac or Windows PostScript name. UINT offset = 6; for (int i = 0; i < numberOfRecords; i++) { if (bufferSize < offset + 12) return NULL; USHORT platformID = readBigEndianWord(buffer + offset); USHORT encodingID = readBigEndianWord(buffer + offset + 2); USHORT languageID = readBigEndianWord(buffer + offset + 4); USHORT nameID = readBigEndianWord(buffer + offset + 6); USHORT length = readBigEndianWord(buffer + offset + 8); USHORT nameOffset = readBigEndianWord(buffer + offset + 10); if (platformID == 3 && encodingID == 1 && languageID == 0x409 && nameID == 6) { // This is a Windows PostScript name and is therefore UTF-16. // Pass Big Endian as the encoding. if (bufferSize < stringsOffset + nameOffset + length) return NULL; result = adoptCF(CFStringCreateWithBytes(NULL, strings + nameOffset, length, kCFStringEncodingUTF16BE, false)); break; } else if (platformID == 1 && encodingID == 0 && languageID == 0 && nameID == 6) { // This is a Mac PostScript name and is therefore ASCII. // See http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html if (bufferSize < stringsOffset + nameOffset + length) return NULL; result = adoptCF(CFStringCreateWithBytes(NULL, strings + nameOffset, length, kCFStringEncodingASCII, false)); break; } offset += 12; } if (result) nameMap.set(faceString, result); return result.get(); }
void ResourceHandle::didReceiveAuthenticationChallenge(const AuthenticationChallenge& challenge) { LOG(Network, "CFNet - didReceiveAuthenticationChallenge()"); ASSERT(d->m_currentWebChallenge.isNull()); // Since CFURLConnection networking relies on keeping a reference to the original CFURLAuthChallengeRef, // we make sure that is actually present ASSERT(challenge.cfURLAuthChallengeRef()); ASSERT(challenge.authenticationClient() == this); // Should be already set. #if !PLATFORM(WIN) // Proxy authentication is handled by CFNetwork internally. We can get here if the user cancels // CFNetwork authentication dialog, and we shouldn't ask the client to display another one in that case. if (challenge.protectionSpace().isProxy()) { // Cannot use receivedRequestToContinueWithoutCredential(), because current challenge is not yet set. CFURLConnectionUseCredential(d->m_connection.get(), 0, challenge.cfURLAuthChallengeRef()); return; } #endif if (!d->m_user.isNull() && !d->m_pass.isNull()) { RetainPtr<CFURLCredentialRef> credential = adoptCF(CFURLCredentialCreate(kCFAllocatorDefault, d->m_user.createCFString().get(), d->m_pass.createCFString().get(), 0, kCFURLCredentialPersistenceNone)); URL urlToStore; if (challenge.failureResponse().httpStatusCode() == 401) urlToStore = challenge.failureResponse().url(); CredentialStorage::set(core(credential.get()), challenge.protectionSpace(), urlToStore); CFURLConnectionUseCredential(d->m_connection.get(), credential.get(), challenge.cfURLAuthChallengeRef()); d->m_user = String(); d->m_pass = String(); // FIXME: Per the specification, the user shouldn't be asked for credentials if there were incorrect ones provided explicitly. return; } if (!client() || client()->shouldUseCredentialStorage(this)) { if (!d->m_initialCredential.isEmpty() || challenge.previousFailureCount()) { // The stored credential wasn't accepted, stop using it. // There is a race condition here, since a different credential might have already been stored by another ResourceHandle, // but the observable effect should be very minor, if any. CredentialStorage::remove(challenge.protectionSpace()); } if (!challenge.previousFailureCount()) { Credential credential = CredentialStorage::get(challenge.protectionSpace()); if (!credential.isEmpty() && credential != d->m_initialCredential) { ASSERT(credential.persistence() == CredentialPersistenceNone); if (challenge.failureResponse().httpStatusCode() == 401) { // Store the credential back, possibly adding it as a default for this directory. CredentialStorage::set(credential, challenge.protectionSpace(), challenge.failureResponse().url()); } RetainPtr<CFURLCredentialRef> cfCredential = adoptCF(createCF(credential)); CFURLConnectionUseCredential(d->m_connection.get(), cfCredential.get(), challenge.cfURLAuthChallengeRef()); return; } } } d->m_currentWebChallenge = challenge; if (client()) client()->didReceiveAuthenticationChallenge(this, d->m_currentWebChallenge); }