edb6c8b77de095cbb18dd6dd55bde0f8ac6870cb
[WebKit-https.git] / Source / WebKit2 / Shared / mac / WebCoreArgumentCodersMac.mm
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2013 Company 100 Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24  * THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #import "config.h"
28 #import "WebCoreArgumentCoders.h"
29
30 #import "ArgumentCodersCF.h"
31 #import "DataReference.h"
32 #import "WebKitSystemInterface.h"
33 #import <WebCore/CertificateInfo.h>
34 #import <WebCore/KeyboardEvent.h>
35 #import <WebCore/ResourceError.h>
36 #import <WebCore/ResourceRequest.h>
37
38 using namespace WebCore;
39
40 namespace IPC {
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(), IPC::tokenNullTypeRef()));
61     IPC::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 (!IPC::decode(decoder, dictionary))
80         return false;
81
82     RetainPtr<NSURLRequest> nsURLRequest = WKNSURLRequestFromSerializableRepresentation(dictionary.get(), IPC::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(), IPC::tokenNullTypeRef()));
110     IPC::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 (!IPC::decode(decoder, dictionary))
126         return false;
127
128     RetainPtr<NSURLResponse> nsURLResponse = WKNSURLResponseFromSerializableRepresentation(dictionary.get(), IPC::tokenNullTypeRef());
129
130     if (!nsURLResponse)
131         return false;
132
133     resourceResponse = ResourceResponse(nsURLResponse.get());
134     return true;
135 }
136
137 void ArgumentCoder<CertificateInfo>::encode(ArgumentEncoder& encoder, const CertificateInfo& certificateInfo)
138 {
139     CFArrayRef certificateChain = certificateInfo.certificateChain();
140     if (!certificateChain) {
141         encoder << false;
142         return;
143     }
144
145     encoder << true;
146     IPC::encode(encoder, certificateChain);
147 }
148
149 bool ArgumentCoder<CertificateInfo>::decode(ArgumentDecoder& decoder, CertificateInfo& certificateInfo)
150 {
151     bool hasCertificateChain;
152     if (!decoder.decode(hasCertificateChain))
153         return false;
154
155     if (!hasCertificateChain)
156         return true;
157
158     RetainPtr<CFArrayRef> certificateChain;
159     if (!IPC::decode(decoder, certificateChain))
160         return false;
161
162     certificateInfo.setCertificateChain(certificateChain.get());
163
164     return true;
165 }
166
167 void ArgumentCoder<ResourceError>::encodePlatformData(ArgumentEncoder& encoder, const ResourceError& resourceError)
168 {
169     bool errorIsNull = resourceError.isNull();
170     encoder << errorIsNull;
171
172     if (errorIsNull)
173         return;
174
175     NSError *nsError = resourceError.nsError();
176
177     String domain = [nsError domain];
178     encoder << domain;
179
180     int64_t code = [nsError code];
181     encoder << code;
182
183     NSDictionary *userInfo = [nsError userInfo];
184
185     RetainPtr<CFMutableDictionaryRef> filteredUserInfo = adoptCF(CFDictionaryCreateMutable(kCFAllocatorDefault, userInfo.count, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
186
187     [userInfo enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL*) {
188         if ([value isKindOfClass:[NSString class]] || [value isKindOfClass:[NSURL class]])
189             CFDictionarySetValue(filteredUserInfo.get(), key, value);
190     }];
191
192     IPC::encode(encoder, filteredUserInfo.get());
193
194     id peerCertificateChain = [userInfo objectForKey:@"NSErrorPeerCertificateChainKey"];
195     if (!peerCertificateChain) {
196         if (SecTrustRef peerTrust = (SecTrustRef)[userInfo objectForKey:NSURLErrorFailingURLPeerTrustErrorKey]) {
197             CFIndex count = SecTrustGetCertificateCount(peerTrust);
198             peerCertificateChain = [NSMutableArray arrayWithCapacity:count];
199             for (CFIndex i = 0; i < count; ++i)
200                 [peerCertificateChain addObject:(id)SecTrustGetCertificateAtIndex(peerTrust, i)];
201         }
202     }
203     ASSERT(!peerCertificateChain || [peerCertificateChain isKindOfClass:[NSArray class]]);
204     encoder << CertificateInfo((CFArrayRef)peerCertificateChain);
205 }
206
207 bool ArgumentCoder<ResourceError>::decodePlatformData(ArgumentDecoder& decoder, ResourceError& resourceError)
208 {
209     bool errorIsNull;
210     if (!decoder.decode(errorIsNull))
211         return false;
212     
213     if (errorIsNull) {
214         resourceError = ResourceError();
215         return true;
216     }
217
218     String domain;
219     if (!decoder.decode(domain))
220         return false;
221
222     int64_t code;
223     if (!decoder.decode(code))
224         return false;
225
226     RetainPtr<CFDictionaryRef> userInfo;
227     if (!IPC::decode(decoder, userInfo))
228         return false;
229
230     CertificateInfo certificate;
231     if (!decoder.decode(certificate))
232         return false;
233
234     if (certificate.certificateChain()) {
235         userInfo = adoptCF(CFDictionaryCreateMutableCopy(kCFAllocatorDefault, CFDictionaryGetCount(userInfo.get()) + 1, userInfo.get()));
236         CFDictionarySetValue((CFMutableDictionaryRef)userInfo.get(), CFSTR("NSErrorPeerCertificateChainKey"), (CFArrayRef)certificate.certificateChain());
237     }
238
239     RetainPtr<NSError> nsError = adoptNS([[NSError alloc] initWithDomain:domain code:code userInfo:(NSDictionary *)userInfo.get()]);
240
241     resourceError = ResourceError(nsError.get());
242     return true;
243 }
244
245 void ArgumentCoder<KeypressCommand>::encode(ArgumentEncoder& encoder, const KeypressCommand& keypressCommand)
246 {
247     encoder << keypressCommand.commandName << keypressCommand.text;
248 }
249     
250 bool ArgumentCoder<KeypressCommand>::decode(ArgumentDecoder& decoder, KeypressCommand& keypressCommand)
251 {
252     if (!decoder.decode(keypressCommand.commandName))
253         return false;
254
255     if (!decoder.decode(keypressCommand.text))
256         return false;
257
258     return true;
259 }
260
261 } // namespace IPC