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