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 "CustomProtocolManagerProxy.h" 28 29#if ENABLE(CUSTOM_PROTOCOLS) 30 31#import "ChildProcessProxy.h" 32#import "Connection.h" 33#import "CustomProtocolManagerMessages.h" 34#import "CustomProtocolManagerProxyMessages.h" 35#import "DataReference.h" 36#import "WebCoreArgumentCoders.h" 37#import <WebCore/ResourceError.h> 38#import <WebCore/ResourceRequest.h> 39#import <WebCore/ResourceResponse.h> 40 41using namespace IPC; 42using namespace WebCore; 43using namespace WebKit; 44 45@interface WKCustomProtocolLoader : NSObject <NSURLConnectionDelegate> { 46@private 47 CustomProtocolManagerProxy* _customProtocolManagerProxy; 48 uint64_t _customProtocolID; 49 RefPtr<Connection> _connection; 50 NSURLCacheStoragePolicy _storagePolicy; 51 NSURLConnection *_urlConnection; 52} 53- (id)initWithCustomProtocolManagerProxy:(CustomProtocolManagerProxy*)customProtocolManagerProxy customProtocolID:(uint64_t)customProtocolID request:(NSURLRequest *)request connection:(Connection *)connection; 54@end 55 56@implementation WKCustomProtocolLoader 57 58- (id)initWithCustomProtocolManagerProxy:(CustomProtocolManagerProxy*)customProtocolManagerProxy customProtocolID:(uint64_t)customProtocolID request:(NSURLRequest *)request connection:(Connection *)connection 59{ 60 self = [super init]; 61 if (!self) 62 return nil; 63 64 ASSERT(customProtocolManagerProxy); 65 ASSERT(request); 66 ASSERT(connection); 67 _customProtocolManagerProxy = customProtocolManagerProxy; 68 _customProtocolID = customProtocolID; 69 _connection = connection; 70 _storagePolicy = NSURLCacheStorageNotAllowed; 71 _urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES]; 72 73 return self; 74} 75 76- (void)dealloc 77{ 78 _connection.clear(); 79 [_urlConnection cancel]; 80 [_urlConnection release]; 81 [super dealloc]; 82} 83 84- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 85{ 86 ResourceError coreError(error); 87 _connection->send(Messages::CustomProtocolManager::DidFailWithError(_customProtocolID, coreError), 0); 88 _customProtocolManagerProxy->stopLoading(_customProtocolID); 89} 90 91- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse 92{ 93 ASSERT(_storagePolicy == NSURLCacheStorageNotAllowed); 94 _storagePolicy = [cachedResponse storagePolicy]; 95 return cachedResponse; 96} 97 98- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 99{ 100 ResourceResponse coreResponse(response); 101 _connection->send(Messages::CustomProtocolManager::DidReceiveResponse(_customProtocolID, coreResponse, _storagePolicy), 0); 102} 103 104- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 105{ 106 IPC::DataReference coreData(static_cast<const uint8_t*>([data bytes]), [data length]); 107 _connection->send(Messages::CustomProtocolManager::DidLoadData(_customProtocolID, coreData), 0); 108} 109 110- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse 111{ 112 return request; 113} 114 115- (void)connectionDidFinishLoading:(NSURLConnection *)connection 116{ 117 _connection->send(Messages::CustomProtocolManager::DidFinishLoading(_customProtocolID), 0); 118 _customProtocolManagerProxy->stopLoading(_customProtocolID); 119} 120 121@end 122 123namespace WebKit { 124 125CustomProtocolManagerProxy::CustomProtocolManagerProxy(ChildProcessProxy* childProcessProxy, WebContext& webContext) 126 : m_childProcessProxy(childProcessProxy) 127 , m_webContext(webContext) 128{ 129 ASSERT(m_childProcessProxy); 130 m_childProcessProxy->addMessageReceiver(Messages::CustomProtocolManagerProxy::messageReceiverName(), *this); 131} 132 133void CustomProtocolManagerProxy::startLoading(uint64_t customProtocolID, const ResourceRequest& coreRequest) 134{ 135 NSURLRequest *request = coreRequest.nsURLRequest(DoNotUpdateHTTPBody); 136 if (!request) 137 return; 138 139 WKCustomProtocolLoader *loader = [[WKCustomProtocolLoader alloc] initWithCustomProtocolManagerProxy:this customProtocolID:customProtocolID request:request connection:m_childProcessProxy->connection()]; 140 ASSERT(loader); 141 ASSERT(!m_loaderMap.contains(customProtocolID)); 142 m_loaderMap.add(customProtocolID, loader); 143 [loader release]; 144} 145 146void CustomProtocolManagerProxy::stopLoading(uint64_t customProtocolID) 147{ 148 m_loaderMap.remove(customProtocolID); 149} 150 151} // namespace WebKit 152 153#endif // ENABLE(CUSTOM_PROTOCOLS) 154