1/* 2 * Copyright (C) 2012 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. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#import "config.h" 27#import "Download.h" 28 29#if PLATFORM(IOS) 30 31#import "DataReference.h" 32#import <CFNetwork/CFURLDownload.h> 33#import <WebCore/NotImplemented.h> 34#import <WebCore/ResourceError.h> 35#import <WebCore/ResourceHandle.h> 36#import <WebCore/ResourceResponse.h> 37#import <wtf/RetainPtr.h> 38#import <wtf/RunLoop.h> 39 40using namespace WebCore; 41 42namespace WebKit { 43 44// FIXME: If possible, we should consider moving some callbacks off the main thread or at least 45// making them asynchonous calls. 46static void dispatchOnMainThread(void(^block)()) 47{ 48 if (RunLoop::isMain()) { 49 block(); 50 return; 51 } 52 53 dispatch_sync(dispatch_get_main_queue(), block); 54} 55 56static inline Download* toDownload(const void* clientInfo) 57{ 58 return static_cast<Download*>(const_cast<void*>(clientInfo)); 59} 60 61static void setUpDownloadClient(CFURLDownloadClient& client, Download& download) 62{ 63 memset(&client, 0, sizeof(client)); 64 client.clientInfo = &download; 65 66 client.didStart = [](CFURLDownloadRef, const void* clientInfo) { 67 dispatchOnMainThread(^{ 68 toDownload(clientInfo)->didStart(); 69 }); 70 }; 71 72 client.willSendRequest = [](CFURLDownloadRef, CFURLRequestRef request, CFURLResponseRef, const void*) -> CFURLRequestRef { 73 return static_cast<CFURLRequestRef>(CFRetain(request)); 74 }; 75 76 client.didReceiveResponse = [](CFURLDownloadRef, CFURLResponseRef response, const void* clientInfo) { 77 dispatchOnMainThread(^{ 78 toDownload(clientInfo)->didReceiveResponse(response); 79 }); 80 }; 81 82 client.didReceiveData = [](CFURLDownloadRef, CFIndex length, const void* clientInfo) { 83 dispatchOnMainThread(^{ 84 toDownload(clientInfo)->didReceiveData(length); 85 }); 86 }; 87 88 client.shouldDecodeDataOfMIMEType = [](CFURLDownloadRef, CFStringRef encodingType, const void* clientInfo) -> Boolean { 89 __block BOOL returnValue = NO; 90 dispatchOnMainThread(^{ 91 returnValue = toDownload(clientInfo)->shouldDecodeSourceDataOfMIMEType(encodingType); 92 }); 93 return returnValue; 94 }; 95 96 client.decideDestinationWithSuggestedObjectName = [](CFURLDownloadRef downloadRef, CFStringRef objectName, const void* clientInfo) { 97 dispatchOnMainThread(^{ 98 bool allowOverwrite; 99 String destination = toDownload(clientInfo)->decideDestinationWithSuggestedFilename(objectName, allowOverwrite); 100 if (!destination.isNull()) 101 CFURLDownloadSetDestination(downloadRef, reinterpret_cast<CFURLRef>([NSURL fileURLWithPath:destination]), allowOverwrite); 102 }); 103 }; 104 105 client.didCreateDestination = [](CFURLDownloadRef, CFURLRef path, const void* clientInfo) { 106 dispatchOnMainThread(^{ 107 toDownload(clientInfo)->didCreateDestination(CFURLGetString(path)); 108 }); 109 }; 110 111 client.didFinish = [](CFURLDownloadRef, const void* clientInfo) { 112 dispatchOnMainThread(^{ 113 toDownload(clientInfo)->didFinish(); 114 }); 115 }; 116 117 client.didFail = [](CFURLDownloadRef downloadRef, CFErrorRef error, const void* clientInfo) { 118 dispatchOnMainThread(^{ 119 auto resumeData = adoptCF(CFURLDownloadCopyResumeData(downloadRef)); 120 toDownload(clientInfo)->didFail(error, IPC::DataReference(CFDataGetBytePtr(resumeData.get()), CFDataGetLength(resumeData.get()))); 121 }); 122 }; 123} 124 125void Download::start() 126{ 127 notImplemented(); 128} 129 130void Download::startWithHandle(ResourceHandle* handle, const ResourceResponse& response) 131{ 132 CFURLDownloadClient client; 133 setUpDownloadClient(client, *this); 134 m_download = adoptCF(CFURLDownloadCreateAndStartWithLoadingConnection(NULL, handle->releaseConnectionForDownload().get(), m_request.cfURLRequest(UpdateHTTPBody), response.cfURLResponse(), &client)); 135} 136 137void Download::cancel() 138{ 139 notImplemented(); 140} 141 142void Download::platformInvalidate() 143{ 144 notImplemented(); 145} 146 147void Download::didDecideDestination(const String&, bool) 148{ 149 notImplemented(); 150} 151 152void Download::platformDidFinish() 153{ 154 notImplemented(); 155} 156 157void Download::receivedCredential(const AuthenticationChallenge&, const Credential&) 158{ 159 notImplemented(); 160} 161 162void Download::receivedRequestToContinueWithoutCredential(const AuthenticationChallenge&) 163{ 164 notImplemented(); 165} 166 167void Download::receivedCancellation(const AuthenticationChallenge&) 168{ 169 notImplemented(); 170} 171 172void Download::receivedRequestToPerformDefaultHandling(const WebCore::AuthenticationChallenge&) 173{ 174 notImplemented(); 175} 176 177void Download::receivedChallengeRejection(const WebCore::AuthenticationChallenge&) 178{ 179 notImplemented(); 180} 181 182} // namespace WebKit 183 184#endif // PLATFORM(IOS) 185