1/* 2 * Copyright (C) 2010 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 "WebCoreArgumentCoders.h" 28 29#import "ArgumentCodersCF.h" 30#import "PlatformCertificateInfo.h" 31#import "WebKitSystemInterface.h" 32#import <WebCore/KeyboardEvent.h> 33#import <WebCore/ResourceError.h> 34#import <WebCore/ResourceRequest.h> 35 36using namespace WebCore; 37using namespace WebKit; 38 39namespace CoreIPC { 40 41void ArgumentCoder<ResourceRequest>::encodePlatformData(ArgumentEncoder& encoder, const ResourceRequest& resourceRequest) 42{ 43 RetainPtr<NSURLRequest> requestToSerialize = resourceRequest.nsURLRequest(DoNotUpdateHTTPBody); 44 45 bool requestIsPresent = requestToSerialize; 46 encoder << requestIsPresent; 47 48 if (!requestIsPresent) 49 return; 50 51 // We don't send HTTP body over IPC for better performance. 52 // Also, it's not always possible to do, as streams can only be created in process that does networking. 53 if ([requestToSerialize.get() HTTPBody] || [requestToSerialize.get() HTTPBodyStream]) { 54 requestToSerialize = adoptNS([requestToSerialize.get() mutableCopy]); 55 [(NSMutableURLRequest *)requestToSerialize.get() setHTTPBody:nil]; 56 [(NSMutableURLRequest *)requestToSerialize.get() setHTTPBodyStream:nil]; 57 } 58 59 RetainPtr<CFDictionaryRef> dictionary = adoptCF(WKNSURLRequestCreateSerializableRepresentation(requestToSerialize.get(), CoreIPC::tokenNullTypeRef())); 60 CoreIPC::encode(encoder, dictionary.get()); 61 62 // The fallback array is part of NSURLRequest, but it is not encoded by WKNSURLRequestCreateSerializableRepresentation. 63 encoder << resourceRequest.responseContentDispositionEncodingFallbackArray(); 64} 65 66bool ArgumentCoder<ResourceRequest>::decodePlatformData(ArgumentDecoder& decoder, ResourceRequest& resourceRequest) 67{ 68 bool requestIsPresent; 69 if (!decoder.decode(requestIsPresent)) 70 return false; 71 72 if (!requestIsPresent) { 73 resourceRequest = ResourceRequest(); 74 return true; 75 } 76 77 RetainPtr<CFDictionaryRef> dictionary; 78 if (!CoreIPC::decode(decoder, dictionary)) 79 return false; 80 81 NSURLRequest *nsURLRequest = WKNSURLRequestFromSerializableRepresentation(dictionary.get(), CoreIPC::tokenNullTypeRef()); 82 if (!nsURLRequest) 83 return false; 84 85 resourceRequest = ResourceRequest(nsURLRequest); 86 87 Vector<String> responseContentDispositionEncodingFallbackArray; 88 if (!decoder.decode(responseContentDispositionEncodingFallbackArray)) 89 return false; 90 91 resourceRequest.setResponseContentDispositionEncodingFallbackArray( 92 responseContentDispositionEncodingFallbackArray.size() > 0 ? responseContentDispositionEncodingFallbackArray[0] : String(), 93 responseContentDispositionEncodingFallbackArray.size() > 1 ? responseContentDispositionEncodingFallbackArray[1] : String(), 94 responseContentDispositionEncodingFallbackArray.size() > 2 ? responseContentDispositionEncodingFallbackArray[2] : String() 95 ); 96 97 return true; 98} 99 100void ArgumentCoder<ResourceResponse>::encodePlatformData(ArgumentEncoder& encoder, const ResourceResponse& resourceResponse) 101{ 102 bool responseIsPresent = resourceResponse.platformResponseIsUpToDate() && resourceResponse.nsURLResponse(); 103 encoder << responseIsPresent; 104 105 if (!responseIsPresent) 106 return; 107 108 RetainPtr<CFDictionaryRef> dictionary = adoptCF(WKNSURLResponseCreateSerializableRepresentation(resourceResponse.nsURLResponse(), CoreIPC::tokenNullTypeRef())); 109 CoreIPC::encode(encoder, dictionary.get()); 110} 111 112bool ArgumentCoder<ResourceResponse>::decodePlatformData(ArgumentDecoder& decoder, ResourceResponse& resourceResponse) 113{ 114 bool responseIsPresent; 115 if (!decoder.decode(responseIsPresent)) 116 return false; 117 118 if (!responseIsPresent) { 119 resourceResponse = ResourceResponse(); 120 return true; 121 } 122 123 RetainPtr<CFDictionaryRef> dictionary; 124 if (!CoreIPC::decode(decoder, dictionary)) 125 return false; 126 127 NSURLResponse* nsURLResponse = WKNSURLResponseFromSerializableRepresentation(dictionary.get(), CoreIPC::tokenNullTypeRef()); 128 if (!nsURLResponse) 129 return false; 130 131 resourceResponse = ResourceResponse(nsURLResponse); 132 return true; 133} 134 135static NSString* nsString(const String& string) 136{ 137 return string.impl() ? [NSString stringWithCharacters:reinterpret_cast<const UniChar*>(string.characters()) length:string.length()] : @""; 138} 139 140void ArgumentCoder<ResourceError>::encodePlatformData(ArgumentEncoder& encoder, const ResourceError& resourceError) 141{ 142 bool errorIsNull = resourceError.isNull(); 143 encoder << errorIsNull; 144 145 if (errorIsNull) 146 return; 147 148 NSError *nsError = resourceError.nsError(); 149 150 String domain = [nsError domain]; 151 encoder << domain; 152 153 int64_t code = [nsError code]; 154 encoder << code; 155 156 HashMap<String, String> stringUserInfoMap; 157 158 NSDictionary* userInfo = [nsError userInfo]; 159 for (NSString *key in userInfo) { 160 id value = [userInfo objectForKey:key]; 161 if (![value isKindOfClass:[NSString class]]) 162 continue; 163 164 stringUserInfoMap.set(key, (NSString *)value); 165 continue; 166 } 167 encoder << stringUserInfoMap; 168 169 id peerCertificateChain = [userInfo objectForKey:@"NSErrorPeerCertificateChainKey"]; 170 ASSERT(!peerCertificateChain || [peerCertificateChain isKindOfClass:[NSArray class]]); 171 encoder << PlatformCertificateInfo((CFArrayRef)peerCertificateChain); 172} 173 174bool ArgumentCoder<ResourceError>::decodePlatformData(ArgumentDecoder& decoder, ResourceError& resourceError) 175{ 176 bool errorIsNull; 177 if (!decoder.decode(errorIsNull)) 178 return false; 179 180 if (errorIsNull) { 181 resourceError = ResourceError(); 182 return true; 183 } 184 185 String domain; 186 if (!decoder.decode(domain)) 187 return false; 188 189 int64_t code; 190 if (!decoder.decode(code)) 191 return false; 192 193 HashMap<String, String> stringUserInfoMap; 194 if (!decoder.decode(stringUserInfoMap)) 195 return false; 196 197 PlatformCertificateInfo certificate; 198 if (!decoder.decode(certificate)) 199 return false; 200 201 NSUInteger userInfoSize = stringUserInfoMap.size(); 202 if (certificate.certificateChain()) 203 userInfoSize++; 204 205 NSMutableDictionary* userInfo = [NSMutableDictionary dictionaryWithCapacity:userInfoSize]; 206 207 HashMap<String, String>::const_iterator it = stringUserInfoMap.begin(); 208 HashMap<String, String>::const_iterator end = stringUserInfoMap.end(); 209 for (; it != end; ++it) 210 [userInfo setObject:nsString(it->value) forKey:nsString(it->key)]; 211 212 if (certificate.certificateChain()) 213 [userInfo setObject:(NSArray *)certificate.certificateChain() forKey:@"NSErrorPeerCertificateChainKey"]; 214 215 RetainPtr<NSError> nsError = adoptNS([[NSError alloc] initWithDomain:nsString(domain) code:code userInfo:userInfo]); 216 217 resourceError = ResourceError(nsError.get()); 218 return true; 219} 220 221void ArgumentCoder<KeypressCommand>::encode(ArgumentEncoder& encoder, const KeypressCommand& keypressCommand) 222{ 223 encoder << keypressCommand.commandName << keypressCommand.text; 224} 225 226bool ArgumentCoder<KeypressCommand>::decode(ArgumentDecoder& decoder, KeypressCommand& keypressCommand) 227{ 228 if (!decoder.decode(keypressCommand.commandName)) 229 return false; 230 231 if (!decoder.decode(keypressCommand.text)) 232 return false; 233 234 return true; 235} 236 237} // namespace CoreIPC 238